Devops - Gérer finement vos secrets avec Mozilla SOPS
Publié le : 26 décembre 2022 | Mis à jour le : 2 mai 2023Table des matières
Pour rappel, un secret est une information qui est utilisée pour accéder à certaines ressources, comme des bases de données, des apis, etc et qui ne doit pas être rendue publique pour des raisons évidentes de sécurité. Donc si vous développez du code d’Infrastructure (IaC) vous devez absolument éviter de les divulguer en les posant dans les dépôts de source de code ! Mais alors comment les stocker ?
kms
qui trace tous les accès à vos secrets !Comment stocker vos secrets ?
La première solution est d’utiliser un utilitaire qui va se charger de chiffrer
et de déchiffrer ces données sensibles. Pour le code Ansible, nous avons à notre
disposition ansible-vault. Mais ses fonctionnalités sont très
limitées. Ansible-vault
n’utilise qu’une seule clé pour chiffrer un fichier
Alors comment gérer finement les droits d’accès ?
La seconde solution est de recourir à une application tierce spécialisée pour gérer vos secrets, comme HashiCorp Vault. Mais cela demande pas mal de ressources pour sa mise en place et sa maintenance. Et parfois, nous aimerions tout de même conserver nos fichiers de configuration dans le code source. Mais alors comment les protéger ?
C’est pour répondre à ces problématiques que les ingénieurs de Mozilla ont conçues SOPS.
Qu’est-ce que SOPS
SOPS pour Secrets OPerationS, est une CLI qui permet de chiffrer des fichiers textes ou binaires. Il permet d’éditer directement les fichiers de configuration aux formats : YAML, JSON, ENV et INI. SOPS automatise en fait le déchiffrage à l’ouverture et le chiffrage à la sauvegarde de ces fichiers. Autre particularité, pour ces fichiers textes SOPS ne chiffre que les valeurs et non les clés, ce qui permet d’en garder la structure, bien utile pour les manipuler sans les déchiffrer. Pour chiffrer les données, SOPS peut utiliser des clés PGP, AGE, HashiCorp Vault, AWS KMS, GCP KMS, et Azure Key Vault.
Installations de Mozilla SOPS
SOPS fonctionne sur les principaux systèmes d’exploitation que sont Linux, Windows et MacOS. Toutes les exécutables sont disponibles dans les releases du dépot officiel.
Installation de SOPS sur MacOS
Rien de plus simple :
brew install sops
Installation de SOPS sur un poste Windows
Télécharger le binaire sops-vx.x.x.exe
. Renommer le fichier en sops.exe et
déplacer le dans un répertoire défini dans la variable PATH
ou plus
simplement dans le répertoire C:\Windows\System32
.
Installation de SOPS sur une distribution Linux
Vous avez deux solutions pour installer SOPS sur Linux :
- En récupérant le package dans les releases Github du projet. Par exemple pour les distributions basées sur une Debian :
wget https://github.com/mozilla/sops/releases/download/v3.7.3/sops_3.7.3_amd64.deb
sudo dpkg -i sops_3.7.3_amd64.deb
- En utilisant asdf
asdf plugin add asdf
asdf install sops latest
asdf global sops latest
sops -- version
sops 3.7.3 (latest)
Utilisation de SOPS
Maintenant que SOPS est installé voyons comment l’utiliser pour sécuriser vos secrets dans vos dépôts de code source.
Chiffrer des fichiers avec SOPS
Chiffrer des fichiers avec une clé AGE
Si vous n’utilisez pas de cloud Public, vous pouvez utiliser des clés PGP ou Age pour chiffrer vos secrets. Si vous voulez partager vos secrets à plusieurs personnes, la solution la plus simple est de les stocker dans un gestionnaire de mots de passe comme bitwarden, LastPass, …
Attention le support de PGP pourrait disparaitre dans les prochaines versions de SOPS (cf issue)
Nous ne verrons donc que l’utilisation d'AGE pour chiffrer vos secrets. Commençons par l’installer sur notre poste de travail Ubuntu, pour les autres systèmes d’exploitation, c’est par là.
sudo apt install age
Ensuite créons notre première clé PGP :
mkdir -p ~/keys
age-keygen -o ~/keys/ma-premiere-cle-age.txt
Public key: age1upjug3ygl55vswr4wjewuunnr4z74ptfygkgfj44sm0u454egqsqdkdxqq
Pour notre exemple, nous allons utiliser le fichier test.yaml avec ce contenu
username: test
password: toto
A présent chiffrons notre fichier avec la CLI sops
.
sops -e --age=age1upjug3ygl55vswr4wjewuunnr4z74ptfygkgfj44sm0u454egqsqdkdxqq test.yaml > test-enc.yml
Voici le contenu du fichier généré :
username: ENC[AES256_GCM,data:cEM0zQ==,iv:BzqgugnPJrlDfkjvnplyPglMSxFAQpnJBYTf2BWnBoE=,tag:33X7yZ+J8uB6X60EJx8RzQ==,type:str]
password: ENC[AES256_GCM,data:I5fssg==,iv:IQjy76Wwj7/t8K1EtqPPgrpd9KIZbEhErnAGoMLMsdg=,tag:EinjQGuhrDLafM2Mf9mitg==,type:str]
sops:
kms: []
gcp_kms: []
azure_kv: []
hc_vault: []
age:
- recipient: age1upjug3ygl55vswr4wjewuunnr4z74ptfygkgfj44sm0u454egqsqdkdxqq
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBmKzE4MlpMNTZUR0JUT2pH
VE9TM3p2ekhoYUJwM2hNZzJHaTNWVE10aVJFCkFXYUF2Zyt6WEtsN29seTRCTk5i
NVIwWWxZaGxudjlXRmxDMWh1a1pmMzgKLS0tIEtpNi9xRHZ5bGgybVVUQnBmNFNR
aWd2bFp2Mk1zb3c2WXB2SGZZN0xFNXcKN0mpn+vbo8R7VpTjuKLmmSh0letc4zzd
TvNiI1G0PtCZ94ZvtXvOx9m36gqDkbCmIXsADRU5Ay7LoJP49CoIOQ==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2022-12-26T10:08:45Z"
mac: ENC[AES256_GCM,data:Y7IZLnSdst04Xa2Hga+JhWyK9fnBW+16TpT9II/ehQOCEuHqfZ65xMjQZLm9dnUWohPZV8XKEnh6crIvfHk/RQbiFm5QY/6acEgxsk8Gp7eqbcExmazipcc9iGJB2jAgDS0bRMz6H/xbsITQYeueuL200IfJkjjtbRtpNU5PXWo=,iv:e45jTNmuDdakgP7UTR/8FJxPSmk2iNdAdc7VCEaU61w=,tag:RMrrQtYWoDhZqVSjsv1c6Q==,type:str]
pgp: []
unencrypted_suffix: _unencrypted
version: 3.7.3
Nous voyons que la structure du fichier est bien conservée et que seules les valeurs sont chiffrées.
Chiffrer des fichiers avec AWS KMS
La CLI AWS doit être installé en premier. Ensuite, il suffit de créer la clé KMS :
export AWS_PROFILE=perso
export AWS_DEFAULT_REGION=eu-west-3
aws kms create-key --tags TagKey=Purpose,TagValue=Test --description "Ma première clé KMS"
{
"KeyMetadata": {
"AWSAccountId": "276757567417",
"KeyId": "1ff319fe-cb40-4738-9335-a85c28a2f159",
"Arn": "arn:aws:kms:eu-west-3:276757567417:key/1ff319fe-cb40-4738-9335-a85c28a2f159",
"CreationDate": "2022-12-26T11:32:56.466000+01:00",
"Enabled": true,
"Description": "Ma première clé KMS",
"KeyUsage": "ENCRYPT_DECRYPT",
"KeyState": "Enabled",
"Origin": "AWS_KMS",
"KeyManager": "CUSTOMER",
"CustomerMasterKeySpec": "SYMMETRIC_DEFAULT",
"KeySpec": "SYMMETRIC_DEFAULT",
"EncryptionAlgorithms": [
"SYMMETRIC_DEFAULT"
],
"MultiRegion": false
}
}
Ensuite, nous pouvons chiffrer le fichier :
sops -e --kms arn:aws:kms:eu-west-3:276757567417:key/1ff319fe-cb40-4738-9335-a85c28a2f159 test.yaml > test-enc.yml
Utiliser plusieurs clés dans SOPS
Dans certains cas, vous aimeriez définir une clé par utilisateur pour définir plus finement les accès aux secrets. Commençons par créer une seconde clé :
age-keygen -o ~/keys/ma-second-cle-age.txt
Public key: age1afht98nlh0cmw4recumvw5g4ny72edwz8sp360qzxqsrputfny5smcy2rd
Pour chiffrer le fichier ainsi, il suffit de lancer la même commande que précédemment en séparant les clés par une virgule.
sops -e --age=age1upjug3ygl55vswr4wjewuunnr4z74ptfygkgfj44sm0u454egqsqdkdxqq,age1afht98nlh0cmw4recumvw5g4ny72edwz8sp360qzxqsrputfny5smcy2rd test.yaml > test-enc.yaml
Le contenu du fichier :
username: ENC[AES256_GCM,data:cXaMaw==,iv:1PH3oXYheej1Wyowa5eaxYmZvtYLXGCrMn8cQyEvew0=,tag:Yae59rLccwKssBAZJvbuXw==,type:str]
password: ENC[AES256_GCM,data:iYVYuQ==,iv:UlMyvevl82dnRmhbiAYbi6/DWiWbdj1T+o5sk3+LK94=,tag:lNqCNLnY1QUKdLgY9EyEMQ==,type:str]
sops:
kms: []
gcp_kms: []
azure_kv: []
hc_vault: []
age:
- recipient: age1upjug3ygl55vswr4wjewuunnr4z74ptfygkgfj44sm0u454egqsqdkdxqq
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBXaUZyRndEcG8rSmhQd3FH
QVZhdGlYaFNCOXF3NEV4cExrVXkwYWg3UG5nCjhyWHM2L0lxRjJvaGgwRFdWN1pS
aEhPaVNzUFdFWWNlMzc5SWhGYlg1NU0KLS0tIHNkTERRYXh1R1Y4VDZtTTRGRm50
R1h4ZGNCbjJ2aUFDT2sydFhYQ0ZCN2cK4rmbrwK6tAMq6YvgJeBvn7fnF/8+la0A
a852VWFWusKnTx01E+UwXRuz2dxAyPWkuMLgCvz9LSFc9kWykdkNcw==
-----END AGE ENCRYPTED FILE-----
- recipient: age1afht98nlh0cmw4recumvw5g4ny72edwz8sp360qzxqsrputfny5smcy2rd
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBJRzlOVGlONE5LaHpKMElH
SHdSODltNHFNdW9nMFY0L1U0S2NremZCZEFRCktBdUg5Q1ZWTEhlRWY4MUJEa3RF
NWpzVElOVDdNWjZsUXpqbVh6S3VGaGcKLS0tIE12RmJCUks0LzUwUU9Yckpzb1hL
ZGg5VEdHL3cva0I4eVpwTHhhdEh3RzgKkhIkjujnGHpSezJEWcFkxm0dt15tndZJ
x1C9XMaxrHqNcDMSGxpSVPSByTMVyy+Drh3j9PvgsBOsQLrrGXtHUw==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2022-12-26T10:15:48Z"
mac: ENC[AES256_GCM,data:fqtzM3ezbTI7gv7EvKZsSLy1GwcXrVFw5BRiCkzEfwOatvZeZL2jma5Yg3UGgL0u9Dm5A0LVq+5ZpAvcUvfHDGcOK0gPJ1klvXHRnuMmFgUd7WCzlfS4iLHxx5j8KiL2otcyn0KEkjhIfiEjyW/ajm2A2QIR/z4JRvjSbzleVG0=,iv:lqJRx+v0KKHkodqagqnNRjrhvpY3OZ3rk+3zrmj1ooU=,tag:VxFVvuvyLmYdBA25aWtTpQ==,type:str]
pgp: []
unencrypted_suffix: _unencrypted
version: 3.7.3
On retrouve bien les deux clés.
Vous pouvez aussi utiliser deux systèmes de chiffrement :
sops -e --kms arn:aws:kms:eu-west-3:276757567417:key/1ff319fe-cb40-4738-9335-a85c28a2f159 --age=age1upjug3ygl55vswr4wjewuunnr4z74ptfygkgfj44sm0u454egqsqdkdxqq test.yaml > test-enc.yaml
Déchiffrer des fichiers avec SOPS
Il suffit d’utiliser la commande --decrypt
ou -d
:
sops -d test-enc.yaml
Failed to get the data key required to decrypt the SOPS file.
Group 0: FAILED
age1upjug3ygl55vswr4wjewuunnr4z74ptfygkgfj44sm0u454egqsqdkdxqq: FAILED
- | failed to open file: open
| /home/vagrant/.config/sops/age/keys.txt: no such file or
| directory
age1afht98nlh0cmw4recumvw5g4ny72edwz8sp360qzxqsrputfny5smcy2rd: FAILED
- | failed to open file: open
| /home/vagrant/.config/sops/age/keys.txt: no such file or
| directory
Recovery failed because no master key was able to decrypt the file. In
order for SOPS to recover the file, at least one key has to be successful,
but none were.
Si on lance la commande directement sans indiquer le chemin des clés privées, nous obtenons bien un échec. Pour indiquer le chemin avec la variable suivante :
export SOPS_AGE_KEY_FILE=~/keys/ma-second-cle-age.txt
sops -d test-enc.yaml
username: test
password: toto
Configuration de SOPS
Plutôt que de lancer les commandes avec toutes les options, il est possible de
définir la configuration SOPS, dans un fichier. Le nom du fichier par défaut
est : .sops.yaml
.
creation_rules:
- path_regex: test.*\.yaml
key_groups:
# First key group
- age:
- age1upjug3ygl55vswr4wjewuunnr4z74ptfygkgfj44sm0u454egqsqdkdxqq
kms:
- arn: arn:aws:kms:eu-west-3:276757567417:key/1ff319fe-cb40-4738-9335-a85c28a2f159
SOPS et Ansible
Pour déchiffrer les fichiers produits avec SOPS dans les playbooks Ansible, il suffit d’installer la collection suivante :
ansible-galaxy collection install community.sops
Et de faire appel à son lookup :
---
- name: Decrpyt SOPS
hosts: all
gather_facts: false
tasks:
- name: Read file
ansible.builtin.debug:
msg: "{{ lookup('community.sops.sops', 'test-enc.yaml') }}"
On lance le playbook :
ansible-playbook -i localhost, -c local test-playbook.yml
localhost | SUCCESS => {
"msg": "username: test\npassword: toto"
}
Conclusion
Comme vous avez pu le voir SOPS est un outil qui peut parfaitement d’intégrer dans un pipeline CI/CD. Couplé avec un gestionnaire de mots de passe ou de clés, il offre un bon moyen de stocker dans un dépôt git des données sensibles, et cela, en toute sécurité. Donc fini les multiples secrets stockés dans les configurations de Github et GitLab.