mirror of
https://github.com/ryantm/agenix.git
synced 2024-09-11 14:25:49 +03:00
Merge 0c9ed950df
into f6291c5935
This commit is contained in:
commit
4ae34c2c23
21
README.md
21
README.md
@ -2,8 +2,8 @@
|
||||
|
||||
`agenix` is a small and convenient Nix library for securely managing and deploying secrets using common public-private SSH key pairs:
|
||||
You can encrypt a secret (password, access-token, etc.) on a source machine using a number of public SSH keys,
|
||||
and deploy that encrypted secret to any another target machine that has the corresponding private SSH key of one of those public keys.
|
||||
This project contains two parts:
|
||||
and deploy that encrypted secret to any another target machine that has the corresponding private SSH key of one of those public keys.
|
||||
This project contains two parts:
|
||||
1. An `agenix` commandline app (CLI) to encrypt secrets into secured `.age` files that can be copied into the Nix store.
|
||||
2. An `agenix` NixOS module to conveniently
|
||||
* add those encrypted secrets (`.age` files) into the Nix store so that they can be deployed like any other Nix package using `nixos-rebuild` or similar tools.
|
||||
@ -250,7 +250,7 @@ e.g. inside your `flake.nix` file:
|
||||
$ cd secrets
|
||||
$ touch secrets.nix
|
||||
```
|
||||
This `secrets.nix` file is **not** imported into your NixOS configuration.
|
||||
This `secrets.nix` file is **not** imported into your NixOS configuration.
|
||||
It's only used for the `agenix` CLI tool (example below) to know which public keys to use for encryption.
|
||||
3. Add public keys to your `secrets.nix` file:
|
||||
```nix
|
||||
@ -266,10 +266,15 @@ e.g. inside your `flake.nix` file:
|
||||
{
|
||||
"secret1.age".publicKeys = [ user1 system1 ];
|
||||
"secret2.age".publicKeys = users ++ systems;
|
||||
"armored-secret.age" = {
|
||||
publicKeys = [ user1 ];
|
||||
armor = true;
|
||||
};
|
||||
}
|
||||
```
|
||||
These are the users and systems that will be able to decrypt the `.age` files later with their corresponding private keys.
|
||||
You can obtain the public keys from
|
||||
The armor option may also be supplied here to ensure files are output in Base64 PEM text which is useful for more readable diffs.
|
||||
You can obtain the public keys from
|
||||
* your local computer usually in `~/.ssh`, e.g. `~/.ssh/id_ed25519.pub`.
|
||||
* from a running target machine with `ssh-keyscan`:
|
||||
```ShellSession
|
||||
@ -290,7 +295,7 @@ e.g. inside your `flake.nix` file:
|
||||
age.secrets.secret1.file = ../secrets/secret1.age;
|
||||
}
|
||||
```
|
||||
When the `age.secrets` attribute set contains a secret, the `agenix` NixOS module will later automatically decrypt and mount that secret under the default path `/run/agenix/secret1`.
|
||||
When the `age.secrets` attribute set contains a secret, the `agenix` NixOS module will later automatically decrypt and mount that secret under the default path `/run/agenix/secret1`.
|
||||
Here the `secret1.age` file becomes part of your NixOS deployment, i.e. moves into the Nix store.
|
||||
|
||||
6. Reference the secrets' mount path in your config:
|
||||
@ -306,14 +311,14 @@ e.g. inside your `flake.nix` file:
|
||||
So `config.age.secrets.secret1.path` will contain the path `/run/agenix/secret1` by default.
|
||||
7. Use `nixos-rebuild` or [another deployment tool](https://nixos.wiki/wiki/Applications#Deployment") of choice as usual.
|
||||
|
||||
The `secret1.age` file will be copied over to the target machine like any other Nix package.
|
||||
The `secret1.age` file will be copied over to the target machine like any other Nix package.
|
||||
Then it will be decrypted and mounted as described before.
|
||||
8. Edit secret files:
|
||||
```ShellSession
|
||||
$ agenix -e secret1.age
|
||||
```
|
||||
It assumes your SSH private key is in `~/.ssh/`.
|
||||
In order to decrypt and open a `.age` file for editing you need the private key of one of the public keys
|
||||
It assumes your SSH private key is in `~/.ssh/`.
|
||||
In order to decrypt and open a `.age` file for editing you need the private key of one of the public keys
|
||||
it was encrypted with. You can pass the private key you want to use explicitly with `-i`, e.g.
|
||||
```ShellSession
|
||||
$ agenix -e secret1.age -i ~/.ssh/id_ed25519
|
||||
|
@ -25,6 +25,10 @@
|
||||
{
|
||||
"secret1.age".publicKeys = [ user1 system1 ];
|
||||
"secret2.age".publicKeys = users ++ systems;
|
||||
"armored-secret.age" = {
|
||||
publicKeys = [ user1 ];
|
||||
armor = true;
|
||||
};
|
||||
}
|
||||
```
|
||||
4. Edit secret files (these instructions assume your SSH private key is in ~/.ssh/):
|
||||
|
7
example/armored-secret.age
Normal file
7
example/armored-secret.age
Normal file
@ -0,0 +1,7 @@
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IFYzWG1FQSBpZkZW
|
||||
aFpLNnJxc0VUMHRmZ2dZS0pjMGVENnR3OHd5K0RiT1RjRUhibFZBCnN5UG5vUjA3
|
||||
SXpsNGtiVUw4T0tIVFo5Wkk5QS9NQlBndzVvektiQ0ozc0kKLS0tIGxyY1Q4dEZ1
|
||||
VGZEanJyTFNta2JNRmpZb2FnK2JyS1hSVml1UGdMNWZKQXMKYla+wTXcRedyZoEb
|
||||
LVWaSx49WoUTU0KBPJg9RArxaeC23GoCDzR/aM/1DvYU
|
||||
-----END AGE ENCRYPTED FILE-----
|
@ -5,4 +5,8 @@ in {
|
||||
"secret1.age".publicKeys = [user1 system1];
|
||||
"secret2.age".publicKeys = [user1];
|
||||
"passwordfile-user1.age".publicKeys = [user1 system1];
|
||||
"armored-secret.age" = {
|
||||
publicKeys = [user1];
|
||||
armor = true;
|
||||
};
|
||||
}
|
||||
|
@ -118,6 +118,10 @@ function keys {
|
||||
(@nixInstantiate@ --json --eval --strict -E "(let rules = import $RULES; in rules.\"$1\".publicKeys)" | @jqBin@ -r .[]) || exit 1
|
||||
}
|
||||
|
||||
function armor {
|
||||
(@nixInstantiate@ --json --eval --strict -E "(let rules = import $RULES; in (builtins.hasAttr \"armor\" rules.\"$1\" && rules.\"$1\".armor))") || exit 1
|
||||
}
|
||||
|
||||
function decrypt {
|
||||
FILE=$1
|
||||
KEYS=$2
|
||||
@ -148,6 +152,7 @@ function decrypt {
|
||||
function edit {
|
||||
FILE=$1
|
||||
KEYS=$(keys "$FILE") || exit 1
|
||||
ARMOR=$(armor "$FILE") || exit 1
|
||||
|
||||
CLEARTEXT_DIR=$(@mktempBin@ -d)
|
||||
CLEARTEXT_FILE="$CLEARTEXT_DIR/$(basename "$FILE")"
|
||||
@ -169,6 +174,9 @@ function edit {
|
||||
[ -f "$FILE" ] && [ "$EDITOR" != ":" ] && @diffBin@ -q "$CLEARTEXT_FILE.before" "$CLEARTEXT_FILE" && warn "$FILE wasn't changed, skipping re-encryption." && return
|
||||
|
||||
ENCRYPT=()
|
||||
if [[ "$ARMOR" == "true" ]]; then
|
||||
ENCRYPT+=(--armor)
|
||||
fi
|
||||
while IFS= read -r key
|
||||
do
|
||||
if [ -n "$key" ]; then
|
||||
|
@ -63,6 +63,9 @@ pkgs.nixosTest {
|
||||
file = ../example/secret2.age;
|
||||
path = "/home/user1/secret2";
|
||||
};
|
||||
secrets.armored-secret = {
|
||||
file = ../example/armored-secret.age;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
@ -71,6 +74,7 @@ pkgs.nixosTest {
|
||||
user = "user1";
|
||||
password = "password1234";
|
||||
secret2 = "world!";
|
||||
armored-secret = "Hello World!";
|
||||
in ''
|
||||
system1.wait_for_unit("multi-user.target")
|
||||
system1.wait_until_succeeds("pgrep -f 'agetty.*tty1'")
|
||||
@ -91,6 +95,9 @@ pkgs.nixosTest {
|
||||
system1.send_chars("cat /run/user/$(id -u)/agenix/secret2 > /tmp/2\n")
|
||||
system1.wait_for_file("/tmp/2")
|
||||
assert "${secret2}" in system1.succeed("cat /tmp/2")
|
||||
system1.send_chars("cat /run/user/$(id -u)/agenix/armored-secret > /tmp/3\n")
|
||||
system1.wait_for_file("/tmp/3")
|
||||
assert "${armored-secret}" in system1.succeed("cat /tmp/3")
|
||||
|
||||
userDo = lambda input : f"sudo -u user1 -- bash -c 'set -eou pipefail; cd /tmp/secrets; {input}'"
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user