Aller au contenu principal

Mozilla SOPS

logo devops

Dans cette documentation, je vais vous guider à travers l'utilisation de sops, un outil puissant pour la gestion sécurisée des secrets DevOps. Les secrets, tels que les clés d'API, les mots de passe et les certificats, sont essentiels pour de nombreuses applications, mais les stocker et les gérer de manière sécurisée peut être un défi. Sops simplifie ce processus en permettant le chiffrement de vos secrets tout en les intégrant facilement dans vos flux de travail DevOps.

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 :

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
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

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 .

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

Intégration avec les outils DevOps

L'intégration de sops dans vos flux de travail DevOps est essentielle pour garantir la sécurité et la gestion efficace de vos secrets.

Intégration avec Git

Git est un outil central dans le développement logiciel, mais il est essentiel de gérer les secrets de manière sécurisée lors de l'utilisation de Git. Voici comment intégrer sops avec Git :

  1. Assurez-vous que votre projet Git est configuré pour utiliser sops pour le chiffrement des secrets.
  2. Ajoutez un fichier .sops.yaml à la racine de votre projet Git pour spécifier les options de chiffrement et de stockage.
  3. Lorsque vous ajoutez ou modifiez des fichiers secrets dans votre dépôt Git, assurez-vous de les chiffrer avec sops avant de les ajouter et de les pousser vers le dépôt.
  4. Les membres de l'équipe qui travaillent sur le projet Git auront besoin de la clé de chiffrement PGP pour décrypter les secrets au besoin.

Intégration avec CI/CD

Dans un pipeline CI/CD (Continuous Integration/Continuous Deployment), il est crucial de gérer les secrets de manière automatisée et sécurisée. Voici comment intégrer sops avec votre pipeline CI/CD :

  1. Assurez-vous que votre environnement CI/CD dispose de sops installé et configuré avec la clé de chiffrement nécessaire.
  2. Dans votre pipeline, utilisez sops pour décrypter les secrets au moment de leur utilisation. Vous pouvez intégrer cette étape dans vos scripts de déploiement ou de construction.
  3. Assurez-vous que la clé de chiffrement PGP nécessaire est accessible dans votre environnement CI/CD de manière sécurisée, par exemple, en utilisant des variables d'environnement protégées.

SOPS et Ansible

L'intégration de sops avec Ansible, un outil puissant pour l'automatisation de la gestion de configuration et du déploiement, permet une gestion sécurisée des secrets dans vos playbooks. 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"
}

Intégration avec Kubernetes

Kubernetes est largement utilisé pour l'orchestration de conteneurs, et la gestion des secrets dans Kubernetes est cruciale. Il existe un opérateur qui se charge de déchiffrer les secrets (source)

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.