feat: first-contact bootstrap play (named admin + SSH key import)
Implements Task 4 (the play was run on-site but never committed). Creates the named admin user, imports the operator pubkey over SCP (net_put), enables SSH. Improvements over the plan: the key import is :if [find] guarded so re-runs don't create duplicate keys, and the vaulted password is loaded via vars_files (it is not auto-loaded because group_vars/mikrotik.vault.yml doesn't match the group-name convention). Verified idempotent (changed=0) against crs310-maker; no duplicate key. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
5a5a194437
commit
5931542473
1 changed files with 52 additions and 0 deletions
52
play_bootstrap.yml
Normal file
52
play_bootstrap.yml
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
---
|
||||
# FIRST-CONTACT bootstrap (run once, password auth):
|
||||
# ansible-playbook play_bootstrap.yml -e ansible_user=admin --ask-pass
|
||||
# Creates the named admin user, imports the operator SSH public key over SCP, and
|
||||
# enables SSH so day-2 runs (play_switch.yml) can use key auth as that user.
|
||||
# Keep a WinBox MAC / serial recovery channel open while running this.
|
||||
#
|
||||
# vault_switch_admin_password is decrypted automatically from
|
||||
# group_vars/mikrotik.vault.yml via the `makerfloss` vault id in ansible.cfg.
|
||||
# All device-touching tasks are :if [find] guarded, so the play is safe to re-run.
|
||||
- name: Bootstrap MikroTik switch (first contact, password auth)
|
||||
hosts: mikrotik
|
||||
gather_facts: false
|
||||
# The vaulted admin password is NOT auto-loaded: group_vars/mikrotik.vault.yml
|
||||
# doesn't match the group-name convention (only mikrotik.yml or group_vars/mikrotik/
|
||||
# auto-load), so load it explicitly here. Day-2 (play_switch.yml) is key auth and
|
||||
# needs no secret. Decrypted automatically via the makerfloss vault id in ansible.cfg.
|
||||
vars_files:
|
||||
- group_vars/mikrotik.vault.yml
|
||||
vars:
|
||||
pubkey_local: "{{ switch_admin_ssh_pubkey_file | default('~/.ssh/id_ed25519.pub') }}"
|
||||
pubkey_remote: "id_ansible.pub"
|
||||
tasks:
|
||||
- name: Create named admin user (idempotent)
|
||||
community.routeros.command:
|
||||
commands:
|
||||
- >-
|
||||
:if ([:len [/user find name="{{ switch_admin_user }}"]] = 0)
|
||||
do={ /user add name="{{ switch_admin_user }}"
|
||||
group="{{ switch_admin_group | default('full') }}"
|
||||
password="{{ vault_switch_admin_password }}" }
|
||||
changed_when: false
|
||||
|
||||
- name: Copy operator public key to the switch
|
||||
ansible.netcommon.net_put:
|
||||
src: "{{ pubkey_local }}"
|
||||
dest: "{{ pubkey_remote }}"
|
||||
|
||||
- name: Import the SSH public key for the admin user (only if none yet)
|
||||
community.routeros.command:
|
||||
commands:
|
||||
- >-
|
||||
:if ([:len [/user/ssh-keys/find user="{{ switch_admin_user }}"]] = 0)
|
||||
do={ /user/ssh-keys/import public-key-file="{{ pubkey_remote }}"
|
||||
user="{{ switch_admin_user }}" }
|
||||
changed_when: false
|
||||
|
||||
- name: Ensure SSH service is enabled
|
||||
community.routeros.command:
|
||||
commands:
|
||||
- /ip/service/set ssh disabled=no port={{ switch_ssh_port | default(22) }}
|
||||
changed_when: false
|
||||
Loading…
Add table
Reference in a new issue