mirror of
https://github.com/dredx/prole.git
synced 2026-09-23 11:03:59 +00:00
Secure and configure the SG2428LP managed switch (10.0.0.10) as repeatable Ansible, driven from the control node over SSH by an expect engine. - tplink_switch_harden role (verified JetStream CLI syntax): HTTP off/ HTTPS-only, Telnet off, SSH v2, SNMP off, RSTP + loopback-detection, then copy running-config startup-config (persist). - playbooks/harden_switch.yml + [switches] inventory group; dry by default, -e switch_apply=true to apply, -e switch_apply_network=true for addressing. - Static mgmt IP 10.0.0.10/24 (off DHCP, below the .20-.199 pool), gw 10.0.0.1, hostname sg2428lp. - op -> ansible-vault bridge (etc/set-switch-1password.sh); admin password in group_vars/switches/vault.yml. - DNS: A/PTR sg2428lp.prole.org -> 10.0.0.10 (records added to dns.yml/ptr_records). - Fix: tag the samba_reverse_dns zone-list set_fact so tag-limited runs define samba_reverse_zones. Engine notes (hard-won): forces password-only SSH auth (the switch drops publickey-first logins); always saves config (unsaved changes revert on reboot). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
63 lines
2.6 KiB
Bash
Executable File
63 lines
2.6 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# set-switch-1password.sh
|
|
# 1Password -> Ansible Vault bridge for the managed switch admin credential.
|
|
#
|
|
# Reads the switch admin password from 1Password (op) and writes it, encrypted
|
|
# with the repo .vault_pass, into the switches group_vars vault file. This keeps
|
|
# 1Password the human source of truth while ansible-vault is what the playbook
|
|
# consumes at run time.
|
|
#
|
|
# op://knoey/TP-Link SG2428LP/password --(op read)--> ENV --(ansible-vault)-->
|
|
# infrastructure/inventory/group_vars/switches/vault.yml
|
|
#
|
|
# Usage:
|
|
# etc/set-switch-1password.sh # default item/account below
|
|
# OP_ACCOUNT=... OP_REFERENCE=... etc/set-switch-1password.sh
|
|
#
|
|
# Requires: op (1Password CLI, unlocked), ansible-vault, repo .vault_pass.
|
|
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
REPO_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
|
|
cd "${REPO_ROOT}"
|
|
|
|
OP_ACCOUNT="${OP_ACCOUNT:-VM7LPYA4XFF4TE2DEI7ZHMZWEA}"
|
|
OP_REFERENCE="${OP_REFERENCE:-op://knoey/TP-Link SG2428LP/password}"
|
|
VAR_NAME="${VAR_NAME:-vault_sg2428lp_admin_password}"
|
|
VAULT_FILE="${VAULT_FILE:-infrastructure/inventory/group_vars/switches/vault.yml}"
|
|
|
|
command -v op >/dev/null 2>&1 || { echo "ERROR: 1Password CLI (op) not found. brew install 1password-cli" >&2; exit 1; }
|
|
command -v ansible-vault >/dev/null 2>&1 || { echo "ERROR: ansible-vault not found." >&2; exit 1; }
|
|
[[ -f .vault_pass ]] || { echo "ERROR: .vault_pass not found at repo root." >&2; exit 1; }
|
|
|
|
# op desktop integration sometimes needs an explicit unlock.
|
|
if ! op read --account "$OP_ACCOUNT" "$OP_REFERENCE" >/dev/null 2>&1; then
|
|
echo "Unlocking 1Password (op signin)..." >&2
|
|
op signin --account "$OP_ACCOUNT" >/dev/null || true
|
|
fi
|
|
|
|
SECRET="$(op read --account "$OP_ACCOUNT" "$OP_REFERENCE" 2>/dev/null || true)"
|
|
if [[ -z "$SECRET" ]]; then
|
|
echo "ERROR: could not read secret from $OP_REFERENCE (is 1Password unlocked?)" >&2
|
|
exit 1
|
|
fi
|
|
echo "Read secret from 1Password (${#SECRET} chars)." >&2
|
|
|
|
# Encrypt as an inline !vault var. Rely on ansible.cfg's vault_password_file so
|
|
# we don't create a duplicate 'default' vault-id (which ansible-vault rejects).
|
|
ENC="$(printf '%s' "$SECRET" | ansible-vault encrypt_string --stdin-name "$VAR_NAME")"
|
|
unset SECRET
|
|
|
|
{
|
|
echo "---"
|
|
echo "# Managed-switch admin password — DO NOT EDIT BY HAND."
|
|
echo "# Source of truth: ${OP_REFERENCE}"
|
|
echo "# Regenerate with: etc/set-switch-1password.sh"
|
|
echo "${ENC}"
|
|
} > "${VAULT_FILE}"
|
|
|
|
echo "Wrote encrypted ${VAR_NAME} -> ${VAULT_FILE}"
|
|
echo "Verify (length only):"
|
|
echo " ansible localhost -m debug -a \"msg={{ ${VAR_NAME} | length }}\" -e @${VAULT_FILE}"
|