Merge pull request 'init c4 uml & refactor secrets with some diagrams' (#1255) from hsjobeki-main into main
This commit is contained in:
@@ -10,19 +10,19 @@ validation:
|
|||||||
unrecognized_links: warn
|
unrecognized_links: warn
|
||||||
|
|
||||||
markdown_extensions:
|
markdown_extensions:
|
||||||
|
- admonition
|
||||||
- attr_list
|
- attr_list
|
||||||
|
- footnotes
|
||||||
|
- meta
|
||||||
|
- plantuml_markdown
|
||||||
- pymdownx.emoji:
|
- pymdownx.emoji:
|
||||||
emoji_index: !!python/name:material.extensions.emoji.twemoji
|
emoji_index: !!python/name:material.extensions.emoji.twemoji
|
||||||
emoji_generator: !!python/name:material.extensions.emoji.to_svg
|
emoji_generator: !!python/name:material.extensions.emoji.to_svg
|
||||||
|
|
||||||
- pymdownx.tasklist:
|
- pymdownx.tasklist:
|
||||||
custom_checkbox: true
|
custom_checkbox: true
|
||||||
- pymdownx.superfences
|
- pymdownx.superfences
|
||||||
- pymdownx.tabbed:
|
- pymdownx.tabbed:
|
||||||
alternate_style: true
|
alternate_style: true
|
||||||
- footnotes
|
|
||||||
- meta
|
|
||||||
- admonition
|
|
||||||
- pymdownx.details
|
- pymdownx.details
|
||||||
- pymdownx.highlight:
|
- pymdownx.highlight:
|
||||||
use_pygments: true
|
use_pygments: true
|
||||||
|
|||||||
@@ -1,11 +1,17 @@
|
|||||||
{ pkgs, module-docs, ... }:
|
{ pkgs, module-docs, ... }:
|
||||||
|
let
|
||||||
|
uml-c4 = pkgs.python3Packages.plantuml-markdown.override { plantuml = pkgs.plantuml-c4; };
|
||||||
|
in
|
||||||
pkgs.stdenv.mkDerivation {
|
pkgs.stdenv.mkDerivation {
|
||||||
name = "clan-documentation";
|
name = "clan-documentation";
|
||||||
|
|
||||||
src = ../.;
|
src = ../.;
|
||||||
|
|
||||||
nativeBuildInputs =
|
nativeBuildInputs =
|
||||||
[ pkgs.python3 ]
|
[
|
||||||
|
pkgs.python3
|
||||||
|
uml-c4
|
||||||
|
]
|
||||||
++ (with pkgs.python3Packages; [
|
++ (with pkgs.python3Packages; [
|
||||||
mkdocs
|
mkdocs
|
||||||
mkdocs-material
|
mkdocs-material
|
||||||
|
|||||||
324
docs/site/drafts/secret-cli.md
Normal file
324
docs/site/drafts/secret-cli.md
Normal file
@@ -0,0 +1,324 @@
|
|||||||
|
## Secrets (CLI Reference)
|
||||||
|
|
||||||
|
#### Adding Secrets (set)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
clan secrets set mysecret
|
||||||
|
> Paste your secret:
|
||||||
|
```
|
||||||
|
|
||||||
|
!!! note
|
||||||
|
As you type your secret won't be displayed. Press Enter to save the secret.
|
||||||
|
|
||||||
|
#### List all Secrets (list)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
clan secrets list
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Assigning Access (set)
|
||||||
|
|
||||||
|
By default, secrets are encrypted for your key. To specify which users and machines can access a secret:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
clan secrets set --machine <machine1> --machine <machine2> --user <user1> --user <user2> <secret_name>
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Displaying Secrets (get)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
clan secrets get mysecret
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Rename
|
||||||
|
|
||||||
|
TODO
|
||||||
|
|
||||||
|
#### Remove
|
||||||
|
|
||||||
|
TODO
|
||||||
|
|
||||||
|
#### import-sops
|
||||||
|
|
||||||
|
TODO
|
||||||
|
|
||||||
|
### Users (Reference)
|
||||||
|
|
||||||
|
Learn how to manage users and allowing access to existing secrets.
|
||||||
|
|
||||||
|
#### list user
|
||||||
|
|
||||||
|
Lists all added users
|
||||||
|
|
||||||
|
```bash
|
||||||
|
clan secrets user list
|
||||||
|
```
|
||||||
|
|
||||||
|
``` {.console, title="Example output", .no-copy}
|
||||||
|
jon
|
||||||
|
sara
|
||||||
|
```
|
||||||
|
|
||||||
|
!!! Question "Who can execute this command?"
|
||||||
|
Everyone - completely public.
|
||||||
|
|
||||||
|
#### add user
|
||||||
|
|
||||||
|
add a user
|
||||||
|
|
||||||
|
```bash
|
||||||
|
clan secrets users add {username} {public-key}
|
||||||
|
```
|
||||||
|
|
||||||
|
!!! Note
|
||||||
|
Changes can be trusted by maintainer review in version control.
|
||||||
|
|
||||||
|
#### get user
|
||||||
|
|
||||||
|
get a user public key
|
||||||
|
|
||||||
|
```bash
|
||||||
|
clan secrets users get {username}
|
||||||
|
```
|
||||||
|
|
||||||
|
``` {.console, title="Example output", .no-copy}
|
||||||
|
age1zk8uzrte55wkg9lkqxu5x6twsj2ja4lehegks0cw4mkg6jv37d9qsjpt44
|
||||||
|
```
|
||||||
|
|
||||||
|
#### remove user
|
||||||
|
|
||||||
|
remove a user
|
||||||
|
|
||||||
|
```bash
|
||||||
|
clan secrets users remove {username}
|
||||||
|
```
|
||||||
|
|
||||||
|
!!! Note
|
||||||
|
Changes can be trusted by maintainer review in version control.
|
||||||
|
|
||||||
|
#### add-secret user
|
||||||
|
|
||||||
|
Grants the user (`username`) access to the secret (`secret_name`)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
clan secrets users add-secret {username} {secret_name}
|
||||||
|
```
|
||||||
|
|
||||||
|
!!! Note
|
||||||
|
Requires the executor of the command to have access to the secret (`secret_name`).
|
||||||
|
|
||||||
|
#### remove-secret user
|
||||||
|
|
||||||
|
remove the user (`username`) from accessing the secret (`secret_name`)
|
||||||
|
|
||||||
|
!!! Danger "Make sure at least one person has access."
|
||||||
|
It might still be possible for the machine to access the secret. (See [machines](#machines))
|
||||||
|
|
||||||
|
We highly recommend to use version control such as `git` which allows you to rollback secrets in case anything gets messed up.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
clan secrets users remove-secret {username} {secret_name}
|
||||||
|
```
|
||||||
|
|
||||||
|
!!! Question "Who can execute this command?"
|
||||||
|
Requires the executor of the command to have access to the secret (`secret_name`).
|
||||||
|
|
||||||
|
### Machines (Reference)
|
||||||
|
|
||||||
|
- [list](): list machines
|
||||||
|
- [add](): add a machine
|
||||||
|
- [get](): get a machine public key
|
||||||
|
- [remove](): remove a machine
|
||||||
|
- [add-secret](): allow a machine to access a secret
|
||||||
|
- [remove-secret](): remove a machine's access to a secret
|
||||||
|
|
||||||
|
#### List machine
|
||||||
|
|
||||||
|
New machines in Clan come with age keys stored in `./sops/machines/<machine_name>`. To list these machines:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
clan secrets machines list
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Add machine
|
||||||
|
|
||||||
|
For clan machines the machine key is generated automatically on demand if none exists.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
clan secrets machines add <machine_name> <age_key>
|
||||||
|
```
|
||||||
|
|
||||||
|
If you already have a device key and want to add it manually, see: [How to obtain a remote key](#obtain-remote-keys-manually)
|
||||||
|
|
||||||
|
#### get machine
|
||||||
|
|
||||||
|
TODO
|
||||||
|
|
||||||
|
#### remove machine
|
||||||
|
|
||||||
|
TODO
|
||||||
|
|
||||||
|
#### add-secret machine
|
||||||
|
|
||||||
|
TODO
|
||||||
|
|
||||||
|
#### remove-secret machine
|
||||||
|
|
||||||
|
TODO
|
||||||
|
|
||||||
|
### Groups (Reference)
|
||||||
|
|
||||||
|
The Clan-CLI makes it easy to manage access by allowing you to create groups.
|
||||||
|
|
||||||
|
- [list](): list groups
|
||||||
|
- [add-user](): add a user to group
|
||||||
|
- [remove-user](): remove a user from group
|
||||||
|
- [add-machine](): add a machine to group
|
||||||
|
- [remove-machine](): remove a machine from group
|
||||||
|
- [add-secret](): allow a user to access a secret
|
||||||
|
- [remove-secret](): remove a group's access to a secret
|
||||||
|
|
||||||
|
#### List Groups
|
||||||
|
|
||||||
|
```bash
|
||||||
|
clan secrets groups list
|
||||||
|
```
|
||||||
|
|
||||||
|
#### add-user
|
||||||
|
|
||||||
|
Assign users to a new group, e.g., `admins`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
clan secrets groups add-user admins <username>
|
||||||
|
```
|
||||||
|
|
||||||
|
!!! info
|
||||||
|
The group is created if no such group existed before.
|
||||||
|
|
||||||
|
The user must exist in beforehand (See: [users](#users-reference))
|
||||||
|
|
||||||
|
```{.console, .no-copy}
|
||||||
|
.
|
||||||
|
├── flake.nix
|
||||||
|
. ...
|
||||||
|
└── sops
|
||||||
|
├── groups
|
||||||
|
│ └── admins
|
||||||
|
│ └── users
|
||||||
|
│ └── <username> -> ../../../users/<username>
|
||||||
|
```
|
||||||
|
|
||||||
|
#### remove-user
|
||||||
|
|
||||||
|
TODO
|
||||||
|
|
||||||
|
#### add-machine
|
||||||
|
|
||||||
|
TODO
|
||||||
|
|
||||||
|
#### remove-machine
|
||||||
|
|
||||||
|
TODO
|
||||||
|
|
||||||
|
#### add-secret
|
||||||
|
|
||||||
|
```bash
|
||||||
|
clan secrets groups add-secret <group_name> <secret_name>
|
||||||
|
```
|
||||||
|
|
||||||
|
#### remove-secret
|
||||||
|
|
||||||
|
TODO
|
||||||
|
|
||||||
|
### Key (Reference)
|
||||||
|
|
||||||
|
- [generate]() generate age key
|
||||||
|
- [show]() show age public key
|
||||||
|
- [update]() re-encrypt all secrets with current keys (useful when changing keys)
|
||||||
|
|
||||||
|
#### generate
|
||||||
|
|
||||||
|
TODO
|
||||||
|
|
||||||
|
#### show
|
||||||
|
|
||||||
|
TODO
|
||||||
|
|
||||||
|
#### update
|
||||||
|
|
||||||
|
TODO
|
||||||
|
|
||||||
|
## Further
|
||||||
|
|
||||||
|
Secrets in the repository follow this structure:
|
||||||
|
|
||||||
|
```{.console, .no-copy}
|
||||||
|
sops/
|
||||||
|
├── secrets/
|
||||||
|
│ └── <secret_name>/
|
||||||
|
│ ├── secret
|
||||||
|
│ └── users/
|
||||||
|
│ └── <your_username>/
|
||||||
|
```
|
||||||
|
|
||||||
|
The content of the secret is stored encrypted inside the `secret` file under `mysecret`.
|
||||||
|
|
||||||
|
By default, secrets are encrypted with your key to ensure readability.
|
||||||
|
|
||||||
|
### Obtain remote keys manually
|
||||||
|
|
||||||
|
To fetch a **SSH host key** from a preinstalled system:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ssh-keyscan <domain_name> | nix shell nixpkgs#ssh-to-age -c ssh-to-age
|
||||||
|
```
|
||||||
|
|
||||||
|
!!! Success
|
||||||
|
This command converts the SSH key into an age key on the fly. Since this is the format used by the clan secrets backend.
|
||||||
|
|
||||||
|
Once added the **SSH host key** enables seamless integration of existing machines with clan.
|
||||||
|
|
||||||
|
Then add the key by executing:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
clan secrets machines add <machine_name> <age_key>
|
||||||
|
```
|
||||||
|
|
||||||
|
See also: [Machine reference](#machines-reference)
|
||||||
|
|
||||||
|
### NixOS integration
|
||||||
|
|
||||||
|
A NixOS machine will automatically import all secrets that are encrypted for the
|
||||||
|
current machine. At runtime it will use the host key to decrypt all secrets into
|
||||||
|
an in-memory, non-persistent filesystem using [sops-nix](https://github.com/Mic92/sops-nix).
|
||||||
|
In your nixos configuration you can get a path to secrets like this `config.sops.secrets.<name>.path`. For example:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
{ config, ...}: {
|
||||||
|
sops.secrets.my-password.neededForUsers = true;
|
||||||
|
|
||||||
|
users.users.mic92 = {
|
||||||
|
isNormalUser = true;
|
||||||
|
passwordFile = config.sops.secrets.my-password.path;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
See the [readme](https://github.com/Mic92/sops-nix) of sops-nix for more
|
||||||
|
examples.
|
||||||
|
|
||||||
|
### Migration: Importing existing sops-based keys / sops-nix
|
||||||
|
|
||||||
|
`clan secrets` stores each secret in a single file, whereas [sops](https://github.com/Mic92/sops-nix) commonly allows to put all secrets in a yaml or json document.
|
||||||
|
|
||||||
|
If you already happened to use sops-nix, you can migrate by using the `clan secrets import-sops` command by importing these files:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
% clan secrets import-sops --prefix matchbox- --group admins --machine matchbox nixos/matchbox/secrets/secrets.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
This will create secrets for each secret found in `nixos/matchbox/secrets/secrets.yaml` in a `./sops` folder of your repository.
|
||||||
|
Each member of the group `admins` in this case will be able to decrypt the secrets with their respective key.
|
||||||
|
|
||||||
|
Since our clan secret module will auto-import secrets that are encrypted for a particular nixos machine,
|
||||||
|
you can now remove `sops.secrets.<secrets> = { };` unless you need to specify more options for the secret like owner/group of the secret file.
|
||||||
@@ -6,7 +6,7 @@ Clan utilizes the [sops](https://github.com/getsops/sops) format and integrates
|
|||||||
|
|
||||||
This documentation will guide you through managing secrets with the Clan CLI
|
This documentation will guide you through managing secrets with the Clan CLI
|
||||||
|
|
||||||
## 1. Initializing Secrets
|
## Initializing Secrets (Quickstart)
|
||||||
|
|
||||||
### Create Your Master Keypair
|
### Create Your Master Keypair
|
||||||
|
|
||||||
@@ -28,11 +28,11 @@ Generated age private key at '/home/joerg/.config/sops/age/keys.txt' for your us
|
|||||||
Also add your age public key to the repository with 'clan secrets users add YOUR_USER age1wkth7uhpkl555g40t8hjsysr20drq286netu8zptw50lmqz7j95sw2t3l7' (replace YOUR_USER with your actual username)
|
Also add your age public key to the repository with 'clan secrets users add YOUR_USER age1wkth7uhpkl555g40t8hjsysr20drq286netu8zptw50lmqz7j95sw2t3l7' (replace YOUR_USER with your actual username)
|
||||||
```
|
```
|
||||||
|
|
||||||
!!! warning
|
!!! warning
|
||||||
Make sure to keep a safe backup of the private key you've just created.
|
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 master key to be unlocked.
|
If it's lost, you won't be able to get to your secrets anymore because they all need the master key to be unlocked.
|
||||||
|
|
||||||
!!! note
|
!!! note
|
||||||
It's safe to add any secrets created by the clan CLI and placed in your repository to version control systems like `git`.
|
It's safe to add any secrets created by the clan CLI and placed in your repository to version control systems like `git`.
|
||||||
|
|
||||||
### Add Your Public Key
|
### Add Your Public Key
|
||||||
@@ -41,7 +41,7 @@ Also add your age public key to the repository with 'clan secrets users add YOUR
|
|||||||
clan secrets users add <your_username> <your_public_key>
|
clan secrets users add <your_username> <your_public_key>
|
||||||
```
|
```
|
||||||
|
|
||||||
!!! note
|
!!! note
|
||||||
Choose the same username as on your Setup/Source Machine that you use to control the deployment with.
|
Choose the same username as on your Setup/Source Machine that you use to control the deployment with.
|
||||||
|
|
||||||
Once run this will create the following files:
|
Once run this will create the following files:
|
||||||
@@ -53,6 +53,137 @@ sops/
|
|||||||
└── key.json
|
└── key.json
|
||||||
```
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
> If you followed the quickstart tutorial all necessary secrets are initialized at this point.
|
||||||
|
|
||||||
|
- Continue with [deploying machines](./machines.md)
|
||||||
|
- Learn about the [basics concept](#concept) of clan secrets
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Concept
|
||||||
|
|
||||||
|
The secrets system conceptually knows two different entities:
|
||||||
|
|
||||||
|
- **Machine**: consumes secrets
|
||||||
|
- **User**: manages access to secrets
|
||||||
|
|
||||||
|
**A Users** Can add or revoke machines' access to secrets.
|
||||||
|
|
||||||
|
**A machine** Can decrypt secrets that where encrypted specifically for that machine.
|
||||||
|
|
||||||
|
!!! Danger
|
||||||
|
**Always make sure at least one _User_ has access to a secret**. Otherwise you could lock yourself out from accessing the secret.
|
||||||
|
|
||||||
|
### Inherited implications
|
||||||
|
|
||||||
|
By default clan uses [sops](https://github.com/getsops/sops) through [sops-nix](https://github.com/Mic92/sops-nix) for managing its secrets which inherits some implications that are important to understand:
|
||||||
|
|
||||||
|
- **Public/Private keys**: Entities are identified via their public keys. Each Entity can use their respective private key to decrypt a secret.
|
||||||
|
- **Public keys are stored**: All Public keys are stored inside the repository
|
||||||
|
- **Secrets are stored Encrypted**: secrets are stored inside the repository encrypted with the respective public keys
|
||||||
|
- **Secrets are deployed encrypted**: Fully encrypted secrets are deployed to machines at deployment time.
|
||||||
|
- **Secrets are decrypted by sops on-demand**: Each machine decrypts its secrets at runtime and stores them at an ephemeral location.
|
||||||
|
- **Machine key-pairs are auto-generated**: When a machine is created **no user-interaction is required** to setup public/private key-pairs.
|
||||||
|
- **secrets are re-encrypted**: In case machines, users or groups are modified secrets get re-encrypted on demand.
|
||||||
|
|
||||||
|
!!! Important
|
||||||
|
After revoking access to a secret you should also change the underlying secret. i.e. change the API key, or the password.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Machine and user keys
|
||||||
|
|
||||||
|
The following diagrams illustrates how a user can provide a secret (i.e. a Password).
|
||||||
|
|
||||||
|
- By using the **Clan CLI** a user encrypts the password with both the **User public-key** and the **machine's public-key**
|
||||||
|
|
||||||
|
- The *Machine* can decrypt the password with its private-key on demand.
|
||||||
|
|
||||||
|
- The *User* is able to decrypt the password to make changes to it.
|
||||||
|
|
||||||
|
```plantuml
|
||||||
|
@startuml
|
||||||
|
!include C4_Container.puml
|
||||||
|
|
||||||
|
Person(user, "User", "Someone who manages secrets")
|
||||||
|
ContainerDb(secret, "Secret")
|
||||||
|
Container(machine, "Machine", "A Machine. i.e. Needs the Secret for a given Service." )
|
||||||
|
|
||||||
|
Rel_R(user, secret, "Encrypt", "", "Pubkeys: User, Machine")
|
||||||
|
Rel_L(secret, user, "Decrypt", "", "user privkey")
|
||||||
|
Rel_R(secret, machine, "Decrypt", "", "machine privkey" )
|
||||||
|
|
||||||
|
@enduml
|
||||||
|
```
|
||||||
|
|
||||||
|
### Groups
|
||||||
|
|
||||||
|
It is possible to create semantic groups to make access control more convenient.
|
||||||
|
|
||||||
|
#### User groups
|
||||||
|
|
||||||
|
Here we illustrate how machine groups work.
|
||||||
|
|
||||||
|
Common use cases:
|
||||||
|
|
||||||
|
- **Shared Management**: Access among multiple users. I.e. a subset of secrets/machines that have two admins
|
||||||
|
|
||||||
|
```plantuml
|
||||||
|
@startuml
|
||||||
|
!include C4_Container.puml
|
||||||
|
|
||||||
|
System_Boundary(c1, "Group") {
|
||||||
|
Person(user1, "User A", "has access")
|
||||||
|
Person(user2, "User B", "has access")
|
||||||
|
}
|
||||||
|
|
||||||
|
ContainerDb(secret, "Secret")
|
||||||
|
Container(machine, "Machine", "A Machine. i.e. Needs the Secret for a given Service." )
|
||||||
|
|
||||||
|
Rel_R(c1, secret, "Encrypt", "", "Pubkeys: User A, User B, Machine")
|
||||||
|
Rel_R(secret, machine, "Decrypt", "", "machine privkey" )
|
||||||
|
|
||||||
|
|
||||||
|
@enduml
|
||||||
|
```
|
||||||
|
|
||||||
|
<!-- TODO: See also [Groups Reference](#groups-reference) -->
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### Machine groups
|
||||||
|
|
||||||
|
Here we illustrate how machine groups work.
|
||||||
|
|
||||||
|
Common use cases:
|
||||||
|
|
||||||
|
- **Shared secrets**: Among multiple machines such as Wifi passwords
|
||||||
|
|
||||||
|
```plantuml
|
||||||
|
@startuml
|
||||||
|
!include C4_Container.puml
|
||||||
|
!include C4_Deployment.puml
|
||||||
|
|
||||||
|
Person(user, "User", "Someone who manages secrets")
|
||||||
|
ContainerDb(secret, "Secret")
|
||||||
|
System_Boundary(c1, "Group") {
|
||||||
|
Container(machine1, "Machine A", "Both machines need the same secret" )
|
||||||
|
Container(machine2, "Machine B", "Both machines need the same secret" )
|
||||||
|
}
|
||||||
|
|
||||||
|
Rel_R(user, secret, "Encrypt", "", "Pubkeys: machine A, machine B, User")
|
||||||
|
Rel(secret, c1, "Decrypt", "", "Both machine A or B can decrypt using their private key" )
|
||||||
|
|
||||||
|
|
||||||
|
@enduml
|
||||||
|
```
|
||||||
|
|
||||||
|
<!-- TODO: See also [Groups Reference](#groups-reference) -->
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## 2. Adding Machine Keys
|
## 2. Adding Machine Keys
|
||||||
|
|
||||||
New machines in Clan come with age keys stored in `./sops/machines/<machine_name>`. To list these machines:
|
New machines in Clan come with age keys stored in `./sops/machines/<machine_name>`. To list these machines:
|
||||||
|
|||||||
Reference in New Issue
Block a user