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>
61 lines
2.1 KiB
YAML
61 lines
2.1 KiB
YAML
---
|
|
# tplink_switch_harden — drive the JetStream CLI via a rendered expect engine.
|
|
# Runs on the control node (play uses connection: local); the engine SSHes to
|
|
# the switch. The admin password is passed only through the SWITCH_PW env var.
|
|
|
|
- name: Assert admin password is available from vault
|
|
ansible.builtin.assert:
|
|
that:
|
|
- switch_admin_password is defined
|
|
- switch_admin_password | length > 0
|
|
fail_msg: >-
|
|
vault_sg2428lp_admin_password is empty/undefined. Populate it with
|
|
etc/set-switch-1password.sh (op -> ansible-vault bridge).
|
|
|
|
- name: Create temp dir for the rendered engine
|
|
ansible.builtin.tempfile:
|
|
state: directory
|
|
suffix: switch-harden
|
|
register: _sw_tmp
|
|
changed_when: false
|
|
|
|
- name: Render hardening expect engine
|
|
ansible.builtin.template:
|
|
src: harden.exp.j2
|
|
dest: "{{ _sw_tmp.path }}/harden.exp"
|
|
mode: "0700"
|
|
changed_when: false
|
|
|
|
- name: Run switch hardening engine ({{ 'APPLY' if switch_apply | bool else 'DRY/show-only' }})
|
|
ansible.builtin.command:
|
|
cmd: "expect -f {{ _sw_tmp.path }}/harden.exp"
|
|
environment:
|
|
SWITCH_PW: "{{ switch_admin_password }}"
|
|
register: _sw_run
|
|
no_log: true # protects SWITCH_PW in the environment
|
|
changed_when: "'>>>===APPLY-END===<<<' in _sw_run.stdout"
|
|
failed_when: false # evaluate explicitly below so output prints
|
|
|
|
- name: Show switch engine output
|
|
ansible.builtin.debug:
|
|
var: _sw_run.stdout_lines
|
|
|
|
- name: Remove temp dir
|
|
ansible.builtin.file:
|
|
path: "{{ _sw_tmp.path }}"
|
|
state: absent
|
|
changed_when: false
|
|
|
|
- name: Assert hardening engine succeeded
|
|
ansible.builtin.assert:
|
|
that:
|
|
- _sw_run.rc == 0
|
|
- "'AUTH-FAILED' not in _sw_run.stdout"
|
|
- "'FORCED-PASSWORD-CHANGE' not in _sw_run.stdout"
|
|
- "'LOGIN-TIMEOUT' not in _sw_run.stdout"
|
|
fail_msg: "Switch engine failed — review the output above (rc={{ _sw_run.rc }})."
|
|
success_msg: >-
|
|
{{ 'Hardening applied and saved to startup-config.'
|
|
if switch_apply | bool else
|
|
'Access verified (dry run). Re-run with -e switch_apply=true to apply.' }}
|