content_atlanticaweb.fr/posts/Nixos/agenix.md

199 lines
7.6 KiB
Markdown

---
date: 2022-07-06
author: Alexandre LUCAZEAU
title: Gérer ses secrets quand on utilise git et qu'on partage son code (et Nixos)
tags:
- nixos
- agenix
- secret.nix
categories :
- nixos
draft: false
description : "Gestion des secrets dans un environnement déclaratif et public"
---
Quand on met sa configuration système en ligne, encore plus quand on utilise
git/gitea/gitlab/github, la gestion des secrets est importante.
Comment stocker un mot de passe sans le refiler à toute la terre ?
Il existe un projet libre, nommé [age ](https://github.com/FiloSottile/age) qui permet
de chiffrer un fichier à partir de sa clé GPG ou SSH
Je n'utilise pas GPG pour plein de raisons. Par contre j'utilise SSH :)
Sous nixos, on dispose d'un outil qui utilise **age**, il s'agit de
**[agenix](https://github.com/ryantm/agenix)**
**agenix** va déchiffrer le fichier **age** que nous aurons généré (celui qui est stocké
dans git) en un fichier que nous aurons choisi. Le contenu sera alors en clair sur le
système, lisible en fonction des droits qu'on aura défini.
Sur la page github, il y a un tutorial, mais lors de la mise en oeuvre, il m'a manqué
quelques informations. Le but de se billet, est donc de voir la mise en place de la
solution.
# Installation
La documentation officielle est limpide à ce sujet. Moi j'ai opté pour
l'installation **nix-channel** qui est plus proche de mes setups. Je utilise ni
**niv** ni **flakes**
Pour paraphraser la documentation, il suffit d'ajouter le dépot et de mettre à jour le
référentiel :
sudo nix-channel --add https://github.com/ryantm/agenix/archive/main.tar.gz agenix
sudo nix-channel --update
Pour chiffrer le fichier, nous avons besoins de l'utilitaire **agenix** et pour que le
système déchiffre le fichier, il a besoin du module. Il n'est pas nécessaire d'avoir les
2 sur le même poste. Seul le module est, bien sur, obligatoire.
Pour installer le module, il faut ajouter au fichier **configuration.nix** dans la zone
d'import : **<agenix/modules/age.nix>**
Pour installer le programme il faut ajouter la ligne suivante n'import ou :
environment.systemPackages = [ (pkgs.callPackage <agenix/pkgs/agenix.nix> {}) ];
Ou vous pouvez centraliser comme moi, la gestion de vos secrets dans un fichier
**agenix.nix** qui sera lui-même importé dans le **configuration.nix**
`
{ pkgs, ... }: {
imports = [
<agenix/modules/age.nix>
];
environment.systemPackages = [ (pkgs.callPackage <agenix/pkgs/agenix.nix> {}) ]
age.secrets.secret_restic = {
file = ./secrets/secret_restic.age;
path = "/run/restic_pass";
owner = "restic";
group = "restic";
};
}
`
Comme on peut le voir, j'ai définit une variable **age.secrets.secret_restic** qui
contient le chemin relatif vers le fichier chiffré, le path du fichier non chiffré, son
owner et son groupe d'appartenance.
**path**, **owner** et **group** sont facultatifs.
Par défaut, agenix déchiffre dans **/run/agenix.d/xx/secret_restic** ou **xx**
correspond à un nombre et représente la génération. Ce nombre varie à chaque appel de
**nixos-rebuild switch** on comprend assez facilement l'interet de définir une copie
fixe qui sera dans **path**
**owner** et **group** permettent de donner le droit à accéder au secret à des comptes
précis.
Il nous reste à voir la génération du fichier **age** et la configuration de ma
sauvegarde.
# Comment s'articule secrets.nix, GPG, SSH et agenix ?
Nous avons 1 fichier age par mot de passe, et un fichier sercret.nix qui permet de
définir quel clé SSH ou GPG peux déchiffrer le fichier **age** le tout dans un dossier
**secrets**
Comme je souhaite utiliser une clé ssh, je dois déterminer quel clé est disponible :
ssh-keyscan 192.168.10.114
Attention, la commande **nixos-rebuild** ne va pas connaitre votre clé dans $HOME/.ssh
mais va travailler à partir de **/etc/ssh**
# Le fichier secrets.nix
## Exemple d'un fichier secrets.nix
`
let
restic = "ssh-ed25519
AAAAC3NzaC1lZDI1NTE5AAAAIGgO3EpoG14fn0VYC69sSS0iI5ZEB4qx9adFS+L5U5ZB";
users_backup = [ restic];
in
{
"secret_restic.age".publicKeys = users_restic;
}
`
## Exemple avec une autre clé public
`
let
nextcloud-db = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKUA1RW6JwZasspAp8qmFRFnlV5WXjhLfStAAkM+KYLv";
restic = "ssh-ed25519
AAAAC3NzaC1lZDI1NTE5AAAAIGgO3EpoG14fn0VYC69sSS0iI5ZEB4qx9adFS+L5U5ZB";
users_backup = [ restic];
users_nextcloud = [ restic nextcloud-db ];
in
{
"secret_restic.age".publicKeys = users_restic;
"secret_nextclouddb.age".publicKeys = users_nextcloud;
}
`
Subtilité ici, car le groupe users_nexcloud est constitué de restic et nextcloudb
* on défini autant de variable que nous avons clés publics, ici il s'agit de
**nextcloud-db** et **restic**
* on affecte le ou les comptes à des groupes. Ici le compte **restic** appartient au
groupe users_backup et les comptes **restic** et **nextcloud-db** appartiennent au
groupe **users_nextcloud**
* on définit quel groupe peux éditer/modifier quel fichier **age**. Donc ici le groupe
**users_restic** peux déchiffrer/modifier/créer le fichier **secret_restic.age** et
le groupe users_nextcloud (donc les détenteurs des clés publics attachés à
nextcloud-db ainsi que restic) peut éditer/modifier/créer le fichier
**secret_nextclouddb.age**
Petite précision, on parle de user, mais nextcloud-db et restic ne sont pas des comptes
utilisateur au sens unix, mais bien des variables qui permettent de nommée le détenteur
de la clés public
Lorsque le fichier **secrets.nix** est créé, on peux générer nos fichiers **age**
# Génération du fichier **age**
La génération du fichier **age** se fait donc après la création du fichier **secrets.nix**
**Agenix** s'appuis sur ce fichier pour chiffrer et permettre aux différent comptes
défini de modifier ou lire le fichier généré. Parfait pour le travail d'équipe.
Ainsi pour chiffrer ou modifier mon mot de passe :
agenix -e secret_restic.age -i /etc/ssh/ssh_host_ed25519_key.pub
Comme on l'a vu un peu plus haut, le fichier secrets, permet de déclarer des clés, de
les associer à des comptes, ou variables. Ces comptes vont être intégrés à un groupe
d'utilisateur et c'est au groupe que l'on donne l'autorisation de déchiffrer le fichier.
En d'autres termes, on va autoriser 1 ou plusieurs utilisateurs, à partir de leur clé
SSH ou GPG, d'accèder au fichier age déchiffré.
# Utilisation dans le fichier backup.nix
Dans le fichier ci-dessous, on peut voir que l'utilisation dans une configuration est
transparente, et pour cause, le fichier age est déchiffré dans **/run/restic_pass**
`
{config, pkgs, ...}:
{
services.restic.backups = {
localbackup = {
initialize = true;
passwordFile = "/run/restic_pass";
paths = [ "/var/lib/nextcloud/data/" ];
repository = "rest:https://back.atlanticaweb.fr/Nextcloud";
timerConfig = {
OnCalendar = "00:05";
RandomizedDelaySec = "5h";
};
};
};
}
`
# Pour finir
A partir de là, vous pouvez générer votre système avec **nixos-rebuild --switch**
Vos services vons pouvoir fonctionner avec des mots de passes aux accès réduits, et ces
fichiers seront versionnés dans git, sans risque de compromission.
[Vous pouvez retrouver le code complet ici](https://git.atlanticaweb.fr/alexandre/nixos-config/src/branch/main/hosts/next)