--- # Provision OpenBao AppRole credentials to a host # # Usage: ansible-playbook ansible/playbooks/provision-approle.yml -l # Requires: BAO_ADDR and BAO_TOKEN environment variables set # # IMPORTANT: This playbook must target exactly one host to prevent # accidentally regenerating credentials for multiple hosts. - name: Validate single host target hosts: all gather_facts: false tasks: - name: Fail if targeting multiple hosts ansible.builtin.fail: msg: | This playbook must target exactly one host. Use: ansible-playbook provision-approle.yml -l Targeting multiple hosts would regenerate credentials for all of them, potentially breaking existing services. when: ansible_play_hosts | length != 1 run_once: true - name: Fetch AppRole credentials from OpenBao hosts: localhost connection: local gather_facts: false vars: target_host: "{{ groups['all'] | first }}" target_hostname: "{{ hostvars[target_host]['short_hostname'] | default(target_host.split('.')[0]) }}" tasks: - name: Display target host ansible.builtin.debug: msg: "Provisioning AppRole credentials for: {{ target_hostname }}" - name: Get role-id for host ansible.builtin.command: cmd: "bao read -field=role_id auth/approle/role/{{ target_hostname }}/role-id" environment: BAO_ADDR: "{{ vault_addr }}" BAO_SKIP_VERIFY: "1" register: role_id_result changed_when: false - name: Generate secret-id for host ansible.builtin.command: cmd: "bao write -field=secret_id -f auth/approle/role/{{ target_hostname }}/secret-id" environment: BAO_ADDR: "{{ vault_addr }}" BAO_SKIP_VERIFY: "1" register: secret_id_result changed_when: true - name: Store credentials for next play ansible.builtin.set_fact: vault_role_id: "{{ role_id_result.stdout }}" vault_secret_id: "{{ secret_id_result.stdout }}" - name: Deploy AppRole credentials to host hosts: all gather_facts: false vars: vault_role_id: "{{ hostvars['localhost']['vault_role_id'] }}" vault_secret_id: "{{ hostvars['localhost']['vault_secret_id'] }}" tasks: - name: Create AppRole directory ansible.builtin.file: path: /var/lib/vault/approle state: directory mode: "0700" owner: root group: root - name: Write role-id ansible.builtin.copy: content: "{{ vault_role_id }}" dest: /var/lib/vault/approle/role-id mode: "0600" owner: root group: root - name: Write secret-id ansible.builtin.copy: content: "{{ vault_secret_id }}" dest: /var/lib/vault/approle/secret-id mode: "0600" owner: root group: root - name: Display success ansible.builtin.debug: msg: "AppRole credentials provisioned to {{ inventory_hostname }}"