From 4b8b5fa90bc1d3c45bb4f9ceba80c36fb1390018 Mon Sep 17 00:00:00 2001 From: "Dustin C. Hatch" Date: Sun, 28 Jan 2024 11:13:16 -0600 Subject: [PATCH] pyrocufflink: Enable pam_ssh_agent_auth for sudo By default, `sudo` requires users to authenticate with their passwords before granting them elevated privileges. It can be configured to allow (some) users access to (some) privileged commands without prompting for a password (i.e. `NOPASSWD`), however this has a real security implication. Disabling the password requirement would effectively grant *any* program root privileges. Prompting for a password prevents malicious software from running privileged commands without the user knowing. Unfortunately, handling `sudo` authentication for Ansible is quite cumbersome. For interactive use, the `--ask-become-pass`/`-K` argument is useful, though entering the password for each invocation of `ansible-playbook` while iterating on configuration policy development is a bit tedious. For non-interactive use, though, the password of course needs to be stored somewhere. Encrypting it with Ansible Vault is one way to protect it, but it still ends up stored on disk somewhere and needs to be handled carefully. *pam_ssh_agent_auth* provides an acceptable solution to both issues. It is better than disabling `sudo` authentication entirely, but a lot more convenient than dealing with passwords. It uses the calling user's SSH agent to assert that the user has access to a private key corresponding to one of the authorized public keys. Using SSH agent forwarding, that private key can even exist on a remote machine. If the user does not have a corresponding private key, `sudo` will fall back to normal password-based authentication. The security of this solution is highly dependent on the client to store keys appropriately. FIDO2 keys are supported, though when used with Ansible, it is quite annoying to have to touch the token for _every task_ on _every machine_. Thus, I have created new FIDO2 keys for both my laptop and my desktop that have the `no-touch-required` option enabled. This means that in order to use `sudo` remotely, I still need to have my token plugged in to my computer, but I do not have to tap it every time it's used. For Jenkins, a hardware token is obviously impossible, but using a dedicated key stored as a Jenkins credential is probably sufficient. --- group_vars/pyrocufflink/main.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/group_vars/pyrocufflink/main.yml b/group_vars/pyrocufflink/main.yml index 4017b2c..5587f6a 100644 --- a/group_vars/pyrocufflink/main.yml +++ b/group_vars/pyrocufflink/main.yml @@ -13,3 +13,12 @@ root_authorized_keys: | ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJsL5fSylmiJmBtW0DH/viAAmtU2E/2M17GPvysiyRs+ dustin@rosalina ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBw1T18jnBfR5reKAACOs/LMcs+jbclj6Eh8z56kJE7+ dustin@luma {% endif %} + +sudo_use_pam_ssh_agent: true +sudo_authorized_ssh_keys: | + sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIF4yQAS0bAQ9Ymxgxv828MsX0z4ff/Fs//0PQOtPexRJAAAABHNzaDo= dustin@rosalina.pyrocufflink.blue + sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAINal4+Gn/KuyP6YTsQuW4cphfDcjrS428osVIqnqMfagAAAABHNzaDo= dustin@luma.pyrocufflink.blue + ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDD3Ebb7dyEyCylgEjmhFxvGqbPkT+0KSpI+xEGXLFnn jenkins +# Default flags include -n, which makes Ansible complain about a "missing +# become password," even though it would never actually prompt for one. +ansible_become_flags: -H