Удалите author_keys с помощью Ansible для нескольких ключей и нескольких пользователей

Я новичок в Ansible, и мне поставили задачу. У меня есть файл YAML, в котором у меня есть следующие ключи для нескольких пользователей.

client:
 - key: ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAklOUpkDHrfHY17SbrmTIpNLTGK9Tjom/BWDSU
GPl+nafzlHDTYW7hdI4yZ5ew18JH4JW9jbhUFrviQzM7xlELEVf4h9lFX5QVkbPppSwg0cda3
Pbv7kOdJ/MTyBlWXFCR+HAo3FXRitBqxiX1nKhXpHAZsMciLq8V6RjsNAQwdsdMFvSlVK/7XA
t3FaoJoAsncM1Q9x5+3V0Ww68/eIFmb1zuUFljQJKprrX88XypNDvjYNby6vw/Pb0rwert/En
mZ+AW4OZPnTPI89ZPmVMLuayrD2cE86Z/il8b+gw3r3+1nKatmIkjn2so1d01QraTlMqVSsbx
NrRFi9wrf+M7Q==
  name: user1
 - key: ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAklOUpkDHrfHY17SbrmTIpNLTGK9Tjom/BWDSU
GPl+nafzlHDTYW7hdI4yZ5ew18JH4JW9jbhUFrviQzM7xlELEVf4h9lFX5QVkbPppSwg0cda3
Pbv7kOdJ/MTyBlWXFCR+HAo3FXRitBqxiX1nKhXpHAZsMciLq8V6RjsNAQwdsdMFvSlVK/7XA
t3FaoJoAsncM1Q9x5+3V0Ww68/eIFmb1zuUFljQJKprrX88XypNDvjYNby6vw/Pb0rwert/En
mZ+AW4OZPnTPI89ZPmVMLuayrD2cE86Z/il8b+gw3r3+1nKatmIkjn2so1d01QraTlMqVSsbx
NrRFiefwwefew4w223e3e==
  name: user1
 - key: ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAklOUpkDHrfHY17SbrmTIpNLTGK9Tjom/BWDSU
GPl+nafzlHDTYW7hdI4yZ5ew18JH4JW9jbhUFrviQzM7xlELEVf4h9lFX5QVkbPppSwg0cda3
Pbv7kOdJ/MTyBlWXFCR+HAo3FXRitBqxiX1nKhXpHAZsMciLq8V6RjsNAQwdsdMFvSlVK/7XA
t3FaoJoAsncM1Q9x5+3V0Ww68/eIFmb1zuUFljQJKprrX88XypNDvjYNby6vw/Pb0rwert/En
mZ+AW4OZPnTPI89ZPmVMLuayrD2cE86Z/il8b+gw3r3+1nKatmIku3hrbfwejw4ur4hfjewf4wkjr3434==  
  name: user2
 - key: ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAklOUpkDHrfHY17SbrmTIpNLTGK9Tjom/BWDSU
GPl+nafzlHDTYW7hdI4yZ5ew18JH4JW9jbhUFrviQzM7xlELEVf4h9lFX5QVkbPppSwg0cda3
Pbv7kOdJ/MTyBlWXFCR+HAo3FXRitBqxiX1nKhXpHAZsMciLq8V6RjsNAQwdsdMFvSlVK/7XA
t3FaoJoAsncM1Q9x5+3V0Ww68/eIFmb1zuUFljQJKprrX88XypNDvjYNby6vw/Pb0rwert/En
mZ+AW4OZPnTPI89ZPmVMLuayrD2cE86Z/il8b+gw3r3+1nKatmIkjn2so1d01Qrao3rj32hirbk2jewf239r232e3==
  name: user2

Моя цель — удалить ключи с сервера для пользователей всякий раз, когда ключ удаляется из файла YAML. Я пробовал эксклюзивно, но он не работает, так как не поддерживает цикл. Вот фрагмент моего кода:

   - name: Set authorized key for user ubuntu copying it from current user
     become: yes
     authorized_key:
       user: "{{ item.name }}"
       state: present
       key: "{{ item.key }}"
       exclusive: True
     with_items:
       - "{{ clients }}"

Я попробовал следующий подход, но он работает только для одного пользователя, а не для нескольких пользователей, потому что он просто объединяет оба ключа и добавляет и удаляет их для обоих пользователей. Я хочу, чтобы он добавлял и удалял ключи однозначно для обоих пользователей.

  - name: lookup ssh pubkeys from keyfiles and create ssh_pubkeys_list
    set_fact:
      ssh_keys: "{{ item.key }}"
    register: ssh_pubkeys_results_list
    with_items:
      - "{{ clients }}"
  
  - name: iterate over ssh_pubkeys_list and join into a string
    set_fact:
      ssh_pubkeys_string: "{{ ssh_pubkeys_results_list.results | map(attribute='ansible_facts.ssh_keys') | join('\n')}}"

  - name: lookup ssh pubkeys from name and create ssh_pubkeys_list
    set_fact:
      ssh_keys: "{{ item.name }}"
    register: ssh_pubkeys_results
    with_items:
      - "{{ clients }}"

  - name: Set authorized key for user ubuntu copying it from current user
    become: yes
    authorized_key:
      user: "{{ item.name }}"
      state: present
      key: "{{ ssh_pubkeys_string }}"
      exclusive: True
    with_items:
      - "{{ clients }}"

Любая помощь будет принята с благодарностью. Спасибо

Можете ли вы изменить формат этого ключевого файла?

Jack 13.11.2022 19:44

@Jack Это похоже только на YAML, откуда он берет ключи. Я добавил настоящие ключи, если это то, что вы искали.

WhizzY 13.11.2022 19:51

Является ли список ключей clients эксклюзивным, т.е. никакие другие ключи не допускаются? Только для пользователей из списка или для всех пользователей?

Vladimir Botka 13.11.2022 21:44

@VladimirBotka Да, это эксклюзивно для всех пользователей.

WhizzY 14.11.2022 03:07

Большое спасибо @VladimirBotka Первое решение работает для меня как шарм. Второй не пробовала, но попробую и этот.

WhizzY 14.11.2022 06:57

@WhizzY Я искал массив ключей для каждого пользователя. Будет намного работоспособнее.

Jack 14.11.2022 17:10
Введение в Ansible Roles
Введение в Ansible Roles
Ansible - это отличный инструмент управления конфигурацией, который можно использовать для автоматизации настройки или развертывания на большом...
1
6
148
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

1) Управление пользователями только из списка

Сгруппируйте ключи по именам. Объявите переменную

client_groups: "{{ client|groupby('name') }}"

Повторить список

    - authorized_key:
        user: "{{ item.0 }}"
        key: "{{ item.1|map(attribute='key')|join('\n') }}"
        exclusive: true
      loop: "{{ client_groups }}"

Example of a complete playbook for testing

Given the authorized keys

shell> ssh admin@test_11 sudo cat /home/alice/.ssh/authorized_keys
ssh-rsa key1 
ssh-rsa key2 
ssh-rsa key3 
shell> ssh admin@test_11 sudo cat /home/bob/.ssh/authorized_keys
ssh-rsa key4 
ssh-rsa key5 
ssh-rsa key6

The playbook

shell> cat pb.yml
- hosts: test_11

  vars:

    client:
      - {name: alice, key: ssh-rsa key1}
      - {name: alice, key: ssh-rsa key2}
      - {name: bob, key: ssh-rsa key4}
      - {name: bob, key: ssh-rsa key5}
    client_groups: "{{ client|groupby('name') }}"

  tasks:

    - block:
        - debug:
            var: client_groups
        - debug:
            msg: |
              user: "{{ item.0 }}"
              key: "{{ item.1|map(attribute='key')|join('\n') }}"
          loop: "{{ client_groups }}"
      when: debug|d(false)|bool

    - authorized_key:
        user: "{{ item.0 }}"
        key: "{{ item.1|map(attribute='key')|join('\n') }}"
        exclusive: true
      loop: "{{ client_groups }}"

gives

shell> ansible-playbook pb.yml -e debug=true -CD

PLAY [test_11] *******************************************************************************

TASK [debug] *********************************************************************************
ok: [test_11] => 
  client_groups:
  - - alice
    - - key: ssh-rsa key1
        name: alice
      - key: ssh-rsa key2
        name: alice
  - - bob
    - - key: ssh-rsa key4
        name: bob
      - key: ssh-rsa key5
        name: bob

TASK [debug] *********************************************************************************
ok: [test_11] => (item=['alice', [{'name': 'alice', 'key': 'ssh-rsa key1'}, {'name': 'alice', 'key': 'ssh-rsa key2'}]]) => 
  msg: |-
    user: "alice"
    key: "ssh-rsa key1\nssh-rsa key2"
ok: [test_11] => (item=['bob', [{'name': 'bob', 'key': 'ssh-rsa key4'}, {'name': 'bob', 'key': 'ssh-rsa key5'}]]) => 
  msg: |-
    user: "bob"
    key: "ssh-rsa key4\nssh-rsa key5"

TASK [authorized_key] ************************************************************************
--- before: /home/alice/.ssh/authorized_keys
+++ after: /home/alice/.ssh/authorized_keys
@@ -1,3 +1,2 @@
 ssh-rsa key1 
 ssh-rsa key2 
-ssh-rsa key3 

changed: [test_11] => (item=['alice', [{'name': 'alice', 'key': 'ssh-rsa key1'}, {'name': 'alice', 'key': 'ssh-rsa key2'}]])
--- before: /home/bob/.ssh/authorized_keys
+++ after: /home/bob/.ssh/authorized_keys
@@ -1,3 +1,2 @@
 ssh-rsa key4 
 ssh-rsa key5 
-ssh-rsa key6 

changed: [test_11] => (item=['bob', [{'name': 'bob', 'key': 'ssh-rsa key4'}, {'name': 'bob', 'key': 'ssh-rsa key5'}]])

PLAY RECAP ***********************************************************************************
test_11: ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

2) Управление всеми пользователями

Получить базу данных

    - getent:
        database: passwd

Выберите пользователей, которыми вы хотите управлять. Например, с помощью оболочки входа. Объявите переменные

shells: [/bin/csh, /bin/sh, /bin/bash]
users: "{{ getent_passwd|dict2items|
                         selectattr('value.5', 'in', shells)|
                         map(attribute='key')|list }}"

Создайте словарь ключей. Объявите переменные

client_groups: "{{ client|groupby('name') }}"
client_nmes: "{{ client_groups|map('first')|list }}"
client_keys: "{{ client_groups|map('last')|
                               map('map', attribute='key')|list }}"
client_dict: "{{ dict(client_nmes|zip(client_keys)) }}"

Итерация списка пользователей

    - authorized_key:
        user: "{{ item }}"
        key: "{{ client_dict[item]|d([])|join('\n') }}"
        exclusive: true
      loop: "{{ users }}"

Example of a complete playbook for testing

- hosts: test_11

  vars:

    client:
      - {name: alice, key: ssh-rsa key1}
      - {name: alice, key: ssh-rsa key2}
      - {name: bob, key: ssh-rsa key4}
      - {name: bob, key: ssh-rsa key5}

    client_groups: "{{ client|groupby('name') }}"
    client_nmes: "{{ client_groups|map('first')|list }}"
    client_keys: "{{ client_groups|map('last')|
                                   map('map', attribute='key')|list }}"
    client_dict: "{{ dict(client_nmes|zip(client_keys)) }}"

    shells: [/bin/csh, /bin/sh, /bin/bash]
    users: "{{ getent_passwd|dict2items|
                             selectattr('value.5', 'in', shells)|
                             map(attribute='key')|list }}"

  tasks:

    - getent:
        database: passwd

    - block:
        - debug:
            var: client_dict
        - debug:
            var: users
        - debug:
            msg: |
              user: "{{ item }}"
              key: "{{ client_dict[item]|d([])|join('\n') }}"
          loop: "{{ users }}"
      when: debug|d(false)|bool

    - authorized_key:
        user: "{{ item }}"
        key: "{{ client_dict[item]|d([])|join('\n') }}"
        exclusive: true
      loop: "{{ users }}"

Другие вопросы по теме