2-03 Comment gérer les secrets avec Terraform
Objectifs
- Comprendre les enjeux de sécurité des données sensibles dans Terraform
- Savoir passer et protéger des informations sensibles dans Terraform
Sécurité et données en clear text
Est-il utile de rappeler combien de fois des identifiants AWS en clair ont été trouvés dans des repos sur Github?
Il s'agit de cas assez extrême, mais dont les conséquences sont révélatrices du danger à laisser apparaître des données sensible en clair dans le code.
Une fois dépassés ces cas simples, on va voir qu'il n'est pour autant pas forcément simple de sécuriser ces informations.
Il existe une règle importante et simple
NE JAMAIS STOCKER DE DONNÉES SENSIBLES EN CLAIR.
Note: C'est valable pour les données stockées dans git, mais pas seulement.
D'autres informations cruciales à retenir
Les fichiers d'état et les fichiers de planificationde Terraform contiennent forcément des données sensibles en clair.
C'est pourquoi il faut être vigilant sur la façon dont ils sont stockés (cf. backends)
C'est aussi pourquoi on doit absolument éviter de les ajouter dans Git.
Le stockage des secrets doit être un équilibre entre solution pour développeurs et solution pour automatisation.
À terme l'objectif du DevOps est d'automatiser au maximum.
Si on choisit une solution qui ne marche que sur les postes individuels, ça devient un blocage.
On ne peut vraiment faire confiance à personne.
Le disque dur des membres de l'équipe est-il chiffré en cas de vol ? (cf. Attaque LastPass sur un poste admin)
Que se passe-t-il si un membre de l'équipe devient "hostile" ?
Est-ce que les stagiaires doivent avoir accès aux secret de la production en agissant sur l'environnement de dev ?
La sécurité est un processus qui doit tenir compte de nombreux facteurs.
Quel est votre modèle de menace ? Tout le monde n'est pas une banque ou la CNAM.
Quels sont les moyens financiers et techniques de votre structure ?
Quelle est la taille de l'équipe et la fréquence de modifications des mots de passe ?
La sécurité est un processus qui résulte d'une entente DevOps.
La bonne solution sera probablement toujours dépendante d'une certaine manière de fonctionner dans l'application.
Par exemple en utilisant des variables d'environnement (cf. 12-Factor App) pour récupérer des secrets déployés au dernier moment dans les instances.
Différentes solutions pour passer des secrets dans Terraform
Les deux méthodes les plus courantes pour stocker des secrets sont
- Stockage dans un fichier chiffré
- Stockage dans un service centralisé
Stockage dans un fichier chiffré
Les stockages de secrets basés sur des fichiers stockent les secrets dans des fichiers chiffrés, qui sont généralement ajoutés dans git.
Pour chiffrer les fichiers, vous avez besoin d'une clé de chiffrement. Cette clé est elle-même un secret !
Cela crée une petit souci : comment stocker cette clé en toute sécurité ?
L'anti pattern dans cette situation devient d'avoir le même mot de passe pour toutes les clefs de chiffrement.
Assez rapidement tout le monde dans l'équipe connaît le même mot de passe (devops101 par exemple?), qui n'est plus sécure et modifiable.
La solution la plus courante à cette énigme consiste à stocker la clé dans un kKey Management Service (KMS) fourni par votre fournisseur de cloud, tel qu'AWS KMS, GCP KMS ou Azure Key Vault.
Une autre solution consiste à utiliser des clés PGP, et de chiffrer le fichier avec.
Mais les clefs PGP ont un mode de fonctionnement un peu complexe, et il faut que les utilisateurs stockent le mot de passe de leur clef PGP ailleurs... on ne fait que repousser le problème.
Il faut que l'utilisateur ait un système de gestion de mots de passe personnel (ex: Keepass) fiable, redondé, etc..
Stockage dans un service centralisé
Les stockages de secrets centralisés sont généralement des services Web auxquels vous parlez sur le réseau qui chiffrent vos secrets et les stockent dans une base de données.
Pour chiffrer ces secrets, ces magasins de secrets centralisés ont besoin d'une clé de chiffrement. Généralement, la clé de chiffrement est gérée par le service lui-même, ou le service s'appuie sur le KMS d'un fournisseur de cloud.
Les services centralisés
À terme la bonne solution est d'utiliser un service centralisé pensé pour les secrets d'infrastructure.
Voici une liste des solutions, on voit que les fournisseurs de cloud proposent directement cette solution.
HashiCorp Vault
AWS Secrets Manager
Google Secrets Manager
Azure Key Vault
Confidant
Le choix d'un service centralisé dépend de facteurs contextuels, comme évoqué plus haut.
Utiliser le service d'un fournisseur de cloud est rapide et simple, mais il implique une dépendance lourde à ce fournisseur.
Utiliser une solution tierce est plus complexe et demande du support, mais elle offre une certaine liberté.
Vault + AWS dans un lab
Pour illustrer le stockage de secrets dans un service centralisé, on va opter pour Vault dans cet exemple.
Il se trouve que c'est la même société Hashicorp qui produit Terraform et Vault, et que son intégration dans AWS est assez simple.
Lancement de Vault via Docker
$ docker run --rm -d --name vault -p 8200:8200 hashicorp/vault
$ docker logs vault
Lancement des opérations
On peut suivre la doc officielle de Terraform ici :
https://developer.hashicorp.com/terraform/tutorials/secrets/secrets-vault
En utilisant le code fourni dans le projet Git de la formation : TP2.03
Un cas simple... voir simpliste
On voit que cet exemple est un peu limité, car il utilise des méthodes pas très sécures.
fait appel à
terraform_remote_state
qui permet d'aller chercher des informations dans un fichier d'état tiers.utilise un compte d'administration pour générer des secrets
Cependant, il est intéressant dans la mesure où dans le fond il est souhaitable d'éviter d'utililser des tokens de durée longue pour piloter les infrastructures.
Sans cette logique, on peut stocker des authentifiants AWS dans Vault avec
provider "vault" {
address = var.vault_address
}
data "vault_aws_access_credentials" "creds" {
backend = "aws"
role = "prod-role"
}
provider "aws" {
access_key = data.vault_aws_access_credentials.creds.access_key
secret_key = data.vault_aws_access_credentials.creds.secret_key
region = "us-west-2"
}
Et ensuite ?
Voici comment on peut utiliser plus raisonnablement Vault comme source de secrets.
On part du principe qu'on a mis en place :
- une méthode d'authentification sécure ;
- un utilisateur avec un groupe et des droits définiis ;
- un espace de secrets auquel il a accès avec une
Documentation :
- Vault https://developer.hashicorp.com/vault/docs/auth
- Vault provider for Terraform https://registry.terraform.io/providers/hashicorp/vault/latest/docs#
## Set by CI/CD or on Dev machine via ENV VAR
variable vault_url {}
variable vault_token {}
variable vault_aws_role {}
provider "vault" {
address = var.vault_url
# Token conf
token = var.vault_token
# OR Aws conf
auth_login_aws = true
role = var.vault_aws_role
}
data "vault_generic_secret" "app_secrets" {
path = "tf/my_app/${environment}/"
}
provider "aws" {
# [CONFIG ...]
}
## Use the secret in configuration
resource "aws_instance" "my_server" {
ami = "ami-059af0b76ba105e7e"
instance_type = "t2.nano"
provisioner "file" {
content = "PASSWD = ${PASSWD}"
destination = "/etc/environ"
}
}
Informations sur les provisioners :
https://developer.hashicorp.com/terraform/language/resources/provisioners/file
Et ensuite c'est aux personnes en charge du développement d'utiliser la variable d'environnement comme source d'information.
Un mot sur Kubernetes
La gestion native des secrets est une des raisons pour lesquelles Kubernetes a un succès grandissant.
Dans Terraform, quoi qu'on fasse il restera toujours des traces de données sensibles en clair.
Rappel des objectifs
- Comprendre les enjeux de sécurité des données sensibles dans Terraform
- Savoir passer et protéger des informations sensibles dans Terraform