--- # tplink_switch_harden — defaults # # ───────────────────────────────────────────────────────────────────────────── # SAFETY: switch_apply defaults to FALSE. # A normal run only logs in and captures `show system-info` (proves access, # changes nothing). Config is applied ONLY with -e switch_apply=true. # ───────────────────────────────────────────────────────────────────────────── switch_apply: false switch_expect_timeout: 30 # Network re-addressing (static IP + gateway) is DISRUPTIVE: applying it drops # the session because the management IP changes. Kept behind its own toggle and # OFF by default, because in steady state (already at the static IP) it is a # no-op, and the one-time DHCP->static cutover is handled deliberately, not on # every run. Enable with -e switch_apply_network=true during the cutover. switch_apply_network: false # ───────────────────────────────────────────────────────────────────────────── # VERIFIED against SG2428LP firmware via on-device `?` help (2026-06-09). # All entries are idempotent — most are already at these values by factory # default, so re-applying is a harmless no-op. Each runs inside `configure`. # ───────────────────────────────────────────────────────────────────────────── switch_harden_commands: - { cmd: "no ip http server", desc: "disable plaintext HTTP management (port 80)" } - { cmd: "ip http secure-server", desc: "ensure HTTPS management is enabled" } - { cmd: "telnet disable", desc: "disable Telnet (port 23)" } - { cmd: "ip ssh server", desc: "ensure SSH server is enabled" } - { cmd: "ip ssh version v2", desc: "enable SSH protocol v2" } - { cmd: "no snmp-server", desc: "ensure SNMP agent is disabled" } - { cmd: "spanning-tree", desc: "enable spanning tree globally" } - { cmd: "spanning-tree mode rstp", desc: "use RSTP" } - { cmd: "loopback-detection", desc: "enable global loopback detection" } # Device identity — safe, non-disruptive (applied with the hardening set). # VERIFY token: JetStream may use `hostname` or `system name`. switch_identity_commands: - { cmd: "hostname {{ switch_hostname }}", desc: "set system hostname" } # Static management addressing — DISRUPTIVE (drops session on the IP change). # Applied only when switch_apply_network=true. VERIFY exact syntax on-device: # the mgmt interface, the dhcp-client disable, and gateway form all vary. switch_network_commands: - { cmd: "interface vlan {{ switch_mgmt_vlan }}", desc: "enter mgmt VLAN interface" } - { cmd: "ip address {{ switch_mgmt_ip_static }} {{ switch_mgmt_netmask }}", desc: "set static mgmt IP (overrides DHCP alloc)" } - { cmd: "exit", desc: "leave interface context" } - { cmd: "ip route 0.0.0.0 0.0.0.0 {{ switch_mgmt_gateway }}", desc: "default route via gateway" } # ───────────────────────────────────────────────────────────────────────────── # OPT-IN, HIGHER-RISK hardening — left OUT of the default set on purpose. # Management access-control can lock you out if the control node is not inside # the permitted range; only enable after confirming syntax AND your admin # subnet. Provided here as a reference to fold into switch_harden_commands once # verified. Do the ACL LAST and from a host inside the permitted range. # ───────────────────────────────────────────────────────────────────────────── # switch_harden_commands_optional: # - { cmd: "user idle-timeout 10", desc: "10-min CLI idle timeout" } # - { cmd: "user access-control ip-based enable", desc: "enable mgmt IP allowlist" } # - { cmd: "user access-control ip-based 10.0.0.0 255.255.255.0", desc: "permit admin subnet" }