# Verwaltung durch Personen statt durch ein Gerät („Weg 1“, 19.10.): SSH-Schlüssel der Admins auf ops (Bastion). # Quelle: sites//proxmox.yaml, access.ops_ssh_keys und access.ops_ssh_keys_revoked. Läuft auf ops: # ansible-playbook playbooks/admins.yml # Fügt nur hinzu bzw. entfernt die ausdrücklich entzogenen Schlüssel; fremde Einträge (z. B. Notfallschlüssel) bleiben. # Proxmox-Weboberfläche: access.admin_users + playbooks/cluster.yml + scripts/pve-admin-user.sh, Gerät in # firewall.management (BETRIEB §8, §10, §15). - name: ops – SSH-Schlüssel der Admins hosts: localhost connection: local gather_facts: false vars: site_file: "{{ playbook_dir }}/../../../../sites/{{ knaster_site | default('knaster') }}/proxmox.yaml" access: "{{ (lookup('file', site_file) | from_yaml).access }}" admin_keys: "{{ access.ops_ssh_keys | default([]) }}" revoked_keys: "{{ access.ops_ssh_keys_revoked | default([]) }}" tasks: - name: Liste prüfen (mindestens ein Schlüssel, Namen eindeutig, kein Schlüssel zugleich entzogen) ansible.builtin.assert: that: - admin_keys | length > 0 - admin_keys | map(attribute='name') | unique | length == admin_keys | length - admin_keys | map(attribute='key') | select('match', '^ssh-(ed25519|rsa) ') | list | length == admin_keys | length - (admin_keys | map(attribute='key') | map('split', ' ') | map(attribute=1) | list) | intersect(revoked_keys | map(attribute='key') | map('split', ' ') | map(attribute=1) | list) | length == 0 fail_msg: "access.ops_ssh_keys in {{ site_file }} prüfen" - name: Schlüssel eintragen ansible.posix.authorized_key: user: root key: "{{ item.key }}" state: present loop: "{{ admin_keys }}" loop_control: label: "{{ item.name }}" - name: Entzogene Schlüssel entfernen ansible.posix.authorized_key: user: root key: "{{ item.key }}" state: absent loop: "{{ revoked_keys }}" loop_control: label: "{{ item.name }}" - name: Schlüssel auf ops (Fingerabdrücke) ansible.builtin.command: ssh-keygen -lf /root/.ssh/authorized_keys register: fingerprints changed_when: false - name: Ergebnis ansible.builtin.debug: msg: "{{ fingerprints.stdout_lines }}"