ryantm / agenix

age-encrypted secrets for NixOS and Home manager
https://matrix.to/#/#agenix:nixos.org
Creative Commons Zero v1.0 Universal
1.55k stars 119 forks source link

Confusing behaviour with age encryption/decryption #64

Closed Padraic-O-Mhuiris closed 3 years ago

Padraic-O-Mhuiris commented 3 years ago

I've managed to set up agenix from unstable to a point where it appears to be working during the nixos-rebuild process. I've been using ssh host keys (located under /etc/ssh/) as outlined in:

https://github.com/ryantm/agenix/blob/53aa91b4170da35a96fab1577c9a34bc0da44e27/modules/age.nix#L99


This is my secrets.nix file I have:

let
  key =
    "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPWMxDpxfrlXhAyln0+MKZs7q3i1VimlHhGgUxVVaeYY Oxygen";
in {
  "ngrokConfig.age" = {
    publicKeys = [ key ];
  };
}


The issue I have arises when I use the agenix tool by command agenix -e ngrokConfig.age. When I first initialise the file it works, opening a blank file and jumping into the neovim process I have set as my editor. However the second time I try to do it, it gives back an error: No identity found to decrypt ngrokConfig.age. Try adding an SSH key at /home/padraic/.ssh/id_rsa or /home/padraic/.ssh/id_ed25519 or using the --identity flag to specify a file.

Using the -v option:

hosts/Oxygen/secrets on  main [⇡]
❯ agenix -e ngrokConfig.age -v
+ test 0 -gt 0
+ RULES=./secrets.nix
+ trap cleanup 0 2 3 15
+ '[' 0 -eq 1 ']'
+ edit ngrokConfig.age
+ FILE=ngrokConfig.age
++ /nix/store/iyw8r3bfd2jgvdp0hwsn97h7a6ps1zxx-nix-2.3.11/bin/nix-instantiate --eval -E '(let rules = import ./secrets.nix; in builtins.concatStringsSep "\n" rules."ngrokConfig.age".publicKeys)'
++ /nix/store/g34ldykl1cal5b9ir3xinnq70m52fcnq-gnused-4.8/bin/sed 's/\\n/\n/g'
++ /nix/store/g34ldykl1cal5b9ir3xinnq70m52fcnq-gnused-4.8/bin/sed 's/"//g'
warning: unknown setting 'experimental-features'
+ KEYS='ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPWMxDpxfrlXhAyln0+MKZs7q3i1VimlHhGgUxVVaeYY Oxygen'
+ '[' -z 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPWMxDpxfrlXhAyln0+MKZs7q3i1VimlHhGgUxVVaeYY Oxygen' ']'
++ /nix/store/761kp8ybw3yq5hiws56h0vxnjmyx9as0-mktemp-1.7/bin/mktemp -d
+ CLEARTEXT_DIR=/tmp/tmp.6J8hPwoNbz
++ basename ngrokConfig.age
+ CLEARTEXT_FILE=/tmp/tmp.6J8hPwoNbz/ngrokConfig.age
+ '[' -f ngrokConfig.age ']'
+ DECRYPT=("${DEFAULT_DECRYPT[@]}")
+ '[' -f /home/padraic/.ssh/id_rsa ']'
+ '[' -f /home/padraic/.ssh/id_ed25519 ']'
+ [[ --decrypt != *\-\-\i\d\e\n\t\i\t\y* ]]
+ echo 'No identity found to decrypt ngrokConfig.age. Try adding an SSH key at /home/padraic/.ssh/id_rsa or /home/padraic/.ssh/id_ed25519 or using the --identity flag to specify a file.'
No identity found to decrypt ngrokConfig.age. Try adding an SSH key at /home/padraic/.ssh/id_rsa or /home/padraic/.ssh/id_ed25519 or using the --identity flag to specify a file.
+ exit 1
+ cleanup
+ '[' '!' -z x ']'
+ rm -rf /tmp/tmp.6J8hPwoNbz
+ '[' '!' -z ']'

<br/>

If I try doing so directly with the host key using the `--identity` flag I get:

```bashhosts/Oxygen/secrets on  main [⇡]
❯ agenix -e ngrokConfig.age -i /etc/ssh/ssh_host_ed25519_key
Error: Permission denied (os error 13)

[ Did rage not do what you expected? Could an error be more useful? ]
[ Tell us: https://str4d.xyz/rage/report                            ]


And using running the same command as root user through sudo:

❯ EDITOR=nvim sudo agenix -e ngrokConfig.age -i /etc/ssh/ssh_host_ed25519_key -v
+ test 0 -gt 0
+ RULES=./secrets.nix
+ trap cleanup 0 2 3 15
+ '[' 0 -eq 1 ']'
+ edit ngrokConfig.age
+ FILE=ngrokConfig.age
++ /nix/store/iyw8r3bfd2jgvdp0hwsn97h7a6ps1zxx-nix-2.3.11/bin/nix-instantiate --eval -E '(let rules = import ./secrets.nix; in builtins.concatStringsSep "\n" rules."ngrokConfig.age".publicKeys)'
++ /nix/store/g34ldykl1cal5b9ir3xinnq70m52fcnq-gnused-4.8/bin/sed 's/"//g'
++ /nix/store/g34ldykl1cal5b9ir3xinnq70m52fcnq-gnused-4.8/bin/sed 's/\\n/\n/g'
warning: unknown setting 'experimental-features'
+ KEYS='ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPWMxDpxfrlXhAyln0+MKZs7q3i1VimlHhGgUxVVaeYY Oxygen'
+ '[' -z 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPWMxDpxfrlXhAyln0+MKZs7q3i1VimlHhGgUxVVaeYY Oxygen' ']'
++ /nix/store/761kp8ybw3yq5hiws56h0vxnjmyx9as0-mktemp-1.7/bin/mktemp -d
+ CLEARTEXT_DIR=/tmp/tmp.yL3LXJNTNO
++ basename ngrokConfig.age
+ CLEARTEXT_FILE=/tmp/tmp.yL3LXJNTNO/ngrokConfig.age
+ '[' -f ngrokConfig.age ']'
+ DECRYPT=("${DEFAULT_DECRYPT[@]}")
+ '[' -f /root/.ssh/id_rsa ']'
+ '[' -f /root/.ssh/id_ed25519 ']'
+ [[ --decrypt --identity /etc/ssh/ssh_host_ed25519_key != *\-\-\i\d\e\n\t\i\t\y* ]]
+ DECRYPT+=(-o "$CLEARTEXT_FILE" "$FILE")
+ /nix/store/rc7g2395vw74cd625drh32rsvglallhi-rage-0.6.0/bin/rage --decrypt --identity /etc/ssh/ssh_host_ed25519_key -o /tmp/tmp.yL3LXJNTNO/ngrokConfig.age ngrokConfig.age
+ cp /tmp/tmp.yL3LXJNTNO/ngrokConfig.age /tmp/tmp.yL3LXJNTNO/ngrokConfig.age.before
/run/current-system/sw/bin/agenix: line 123: EDITOR: unbound variable
++ cleanup
++ '[' '!' -z x ']'
++ rm -rf /tmp/tmp.yL3LXJNTNO
++ '[' '!' -z ']'

~I'm inclined to think that I may be going about the encryption process incorrectly and it was only intended to be a one-time edit of the file. I can get by well enough by just deleting the file and recreating it again, however it is a bit tedious and would be preferred if I can make incremental changes to secret configs and the such. ~

All above aside, great tool btw

Update:

On further reading of the agenix.nix file, I believe I understand the issue better. I have on my machine two ssh keys, one under /etc/ssh, the "host" key and then a personal ssh key under ~/.ssh. The script will automatically add the ~/.ssh key as a recipient if it exists but does not appear to search under /etc/hosts/ for the decryption, only ~/ssh. I think it would be a good default to lookup host ssh keys in the event of running as root (as they could only be accessed by root).

ryantm commented 3 years ago

Usually you need to have at least two keys per secret in the secrets.nix file: the system's public ssh host key, and your public ssh key. It looks like in your case you've excluded your public ssh key from the secret, so when you encrypt it, it can only be decrypted by your server and not you.

ryantm commented 3 years ago

The script will automatically add the ~/.ssh key as a recipient if it exists

This is not correct. The script automatically adds it as an identity (used for decrypting), but it does not add it as a recipient when encrypting. Recipients are controlled solely by the contents of your secrets.nix file.

Padraic-O-Mhuiris commented 3 years ago

So to clarify, the correct model is a two key approach, the first being a per system "host" key under /etc/ssh which is only used to decrypt secrets. The personal user ssh key under ~/.ssh is used both for encrypting and decrypting as a means to edit the secret1.age file?

Padraic-O-Mhuiris commented 3 years ago

aah I see, this way you can edit any key on any system?

ryantm commented 3 years ago

Yes, that's right.

The idea is you have some set of users (usually identified by ~/.ssh ssh keys) and some set of systems (usually identified by /etc/ssh host keys). The secrets should only be decryptable by the systems they need to be deployed onto and the users that need to edit the secrets.

You can only edit the secrets on computers where your private ssh key is available.

Padraic-O-Mhuiris commented 3 years ago

:+1: Thanks for clearing this up. I'll close the issue

cbr9 commented 1 year ago

I think this should be added to the docs. It was also confusing to me.

n8henrie commented 1 year ago

Interesting, I hadn't set things up this way either -- I have just been editing the secrets as root on the respective systems, but that would make sense to have a second key enabled on each (in order to be able to edit them from my main day-to-day machine).