I am fairly new to Ansible and has been assigned a task. I have a YAML file in which I have the following keys for multiple users.
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
My goal is to remove the keys from the server for the users whenever the key is removed from the YAML file. I tried exclusive but it is not working as it is not loop aware. Here is the snippet of my code:
- 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 }}"
I tried the following approach but it is only working for single user and not for multiple user because it is just concatenating both keys and adding and removing it for both user. I want that it should add and remove the keys uniquely for both the user.
- 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 }}"
Any help would be greatly appreciated. Thanks
1) Manage users in the list only
Group the keys by names. Declare the variable
client_groups: "{{ client|groupby('name') }}"
Iterate the list
- 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) Manage all users
Get the database
- getent:
database: passwd
Select the users you want to manage. For example by the login shell. Declare the variables
shells: [/bin/csh, /bin/sh, /bin/bash]
users: "{{ getent_passwd|dict2items|
selectattr('value.5', 'in', shells)|
map(attribute='key')|list }}"
Create a dictionary of the keys. Declare the variables
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)) }}"
Iterate the list of the users
- 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 }}"