feat: support age plugins

Extends how we parse the contents of `SOPS_AGE_KEY` / `SOPS_AGE_KEY_FILE` / `keys.txt`, allowing a user to prepend a comment before any `AGE-PLUGIN-` secret key entry to indicate its corresponding public key.

For example:

```
AGE-PLUGIN-FIDO2-HMAC-xxxxxxxxxxxxx
```

The comment can use any prefix (e.g. `# public key: age1xxxx`, `# recipient: age1xxx`) as we are looking directly for `age1xxxx` within the line.

This change is necessary to support `age` plugins as there is no unified mechanism to recover the public key from a plugin's secret key.

If a plugin secret key does not have a preceding public key comment, an error will be thrown when attempting to set a secret.
This commit is contained in:
Brian McGee
2025-04-09 16:06:46 +01:00
committed by Michael Hoang
parent 852fdc2846
commit 1694a977f1
9 changed files with 400 additions and 281 deletions

View File

@@ -1,18 +1,19 @@
Clan enables encryption of secrets (such as passwords & keys) ensuring security and ease-of-use among users.
By default Clan utilizes the [sops](https://github.com/getsops/sops) format and integrates with [sops-nix](https://github.com/Mic92/sops-nix) on NixOS machines.
By default, Clan uses the [sops](https://github.com/getsops/sops) format
and integrates with [sops-nix](https://github.com/Mic92/sops-nix) on NixOS machines.
Clan can also be configured to be used with other secret store [backends](https://docs.clan.lol/reference/clan-core/vars/#clan.core.vars.settings.secretStore).
This guide will walk you through:
- **Creating a Keypair for Your User**: Learn how to generate a keypair for $USER to securely control all secrets.
- **Creating a Keypair for Your User**: Learn how to generate a keypair for `$USER` to securely control all secrets.
- **Creating Your First Secret**: Step-by-step instructions on creating your initial secret.
- **Assigning Machine Access to the Secret**: Understand how to grant a machine access to the newly created secret.
## Create Your Admin Keypair
To get started, you'll need to create **Your admin keypair**.
To get started, you'll need to create **your admin keypair**.
!!! info
Don't worry — if you've already made one before, this step won't change or overwrite it.
@@ -34,9 +35,42 @@ Also add your age public key to the repository with 'clan secrets users add YOUR
Make sure to keep a safe backup of the private key you've just created.
If it's lost, you won't be able to get to your secrets anymore because they all need the admin key to be unlocked.
If you already have an [age] secret key and want to use that instead, you can simply edit `~/.config/sops/age/keys.txt`:
```title="~/.config/sops/age/keys.txt"
AGE-SECRET-KEY-13GWMK0KNNKXPTJ8KQ9LPSQZU7G3KU8LZDW474NX3D956GGVFAZRQTAE3F4
```
Alternatively, you can provide your [age] secret key as an environment variable `SOPS_AGE_KEY`, or in a different file
using `SOPS_AGE_KEY_FILE`.
For more information see the [SOPS] guide on [encrypting with age].
!!! note
It's safe to add any secrets created by the clan CLI and placed in your repository to version control systems like `git`.
### Using Age Plugins
If you wish to use a key generated using an [age plugin] as your admin key, extra care is needed.
You must **precede your secret key with a comment that contains its corresponding recipient**.
This is usually output as part of the generation process
and is only required because there is no unified mechanism for recovering a recipient from a plugin secret key.
Here is an example:
```title="~/.config/sops/age/keys.txt"
# public key: age1zdy49ek6z60q9r34vf5mmzkx6u43pr9haqdh5lqdg7fh5tpwlfwqea356l
AGE-PLUGIN-FIDO2-HMAC-1QQPQZRFR7ZZ2WCV...
```
!!! note
The comment that precedes the plugin secret key need only contain the recipient.
Any other text is ignored.
In the example above, you can specify `# recipient: age1zdy...`, `# public: age1zdy....` or even
just `# age1zdy....`
### Add Your Public Key(s)
```console
@@ -70,7 +104,7 @@ If you followed the quickstart tutorial all necessary secrets are initialized at
You can list keys for your user with `clan secrets users get $USER`:
```console
bin/clan secrets users get alice
clan secrets users get alice
[
{
@@ -83,17 +117,22 @@ You can list keys for your user with `clan secrets users get $USER`:
"type": "age",
"username": "alice"
}
]
]
```
To add a new key to your user:
To add a new key to your user:
```console
```console
clan secrets users add-key $USER --age-key <your_public_key>
```
To remove a key from your user:
To remove a key from your user:
```console
```console
clan secrets users remove-key $USER --age-key <your_public_key>
```
```
[age]: https://github.com/FiloSottile/age
[age plugin]: https://github.com/FiloSottile/awesome-age?tab=readme-ov-file#plugins
[sops]: https://github.com/getsops/sops
[encrypting with age]: https://github.com/getsops/sops?tab=readme-ov-file#encrypting-using-age