roots / trellis

WordPress LEMP stack with PHP 8.2, Composer, WP-CLI and more
https://roots.io/trellis/
MIT License
2.5k stars 608 forks source link

Removing keys from authorized_keys when re-provisioning #1087

Open jan-muller opened 5 years ago

jan-muller commented 5 years ago

Feature request

When re-provisioning a server with a users tag trellis provision --tags users env it does not remove the keys from authorized_keys. It would be nice if it could remove keys.

Working with a team of developers, we've put all the keys of all the team members in the /group_vars/all/users.yml. Removing a key in users.yml and re-provision the server does not remove any keys.

This is something to be aware of, might want to modify the docs with a warning.

Related discourse topic: https://discourse.roots.io/t/re-provisioning-with-tag-users-does-not-removing-ssh-keys-from-authorized-keys/15857

swalkinshaw commented 2 years ago

I looked into this and unfortunately it would be very complex to implement. Ansible's authorized_key module helpfully provides a exclusive option which will remove old keys automatically, but the way Trellis adds keys makes this very hard (if not impossible) to use.

To use the exclusive option, all keys need to be provided as a single string blob. But we have two different tasks: https://github.com/roots/trellis/blob/048e5682ddeaf00c0f24b7d82a927d5b00a50b5b/roles/users/tasks/main.yml#L52-L64

Trying to get them all together would also mean not being able to support the https://github.com/username.keys URL feature.

If someone wants to try and implement this please feel free. It would be a great addition but I don't see a way to do it.

dalepgrant commented 11 months ago

Spitballing an idea, we could do something like this:

trellis/roles/users/tasks/main.yml

+ - name: Overwrite user SSH keys with primary user
+  authorized_key:
+    user: "{{ item.name }}"
+    key: "{{ item['keys'] | first }}"  # get first SSH key listed in group_vars/all/users.yml
+    exclusive: true                    # remove all other keys
+  loop: "{{ users | default([]) }}"
+ loop_control:
+    label: "{{ item.name }}"

+ - name: Add other user SSH keys
- - name: Add user SSH keys 
   authorized_key: 
     user: "{{ item.0.name }}" 
     key: "{{ item.1 }}" 
   with_subelements: 
     - "{{ users | default([]) }}" 
     - keys 

There would be a moment where only the first key from each group in group_vars/all/users.yml is present on the server before the other keys are added.

Tested the above on a throwaway server, does the job. Could be improved before it makes it out into being used on production servers by first checking the key exists/isn't blank (if it's a Github key) and moving onto the next key if not. Could also be made to run only if a certain flag is given, it probably doesn't need to be run on every single provision.