Le Blog Amazon Web Services

Bonnes pratiques pour le stockage des secrets en utilisant AWS Systems Manager Parameter Store

La façon dont les entreprises gèrent les secrets d’application est essentielle. Aujourd’hui encore, même les entreprises disposant des infrastructures les plus sécurisées peuvent subir de multiples fuites de données dues à des mauvaises pratiques de gestion des secrets. Disposer d’informations d’authentification accessible depuis Internet est comme laisser la clé de votre maison sous un paillasson sur lequel des millions de personnes marchent chaque jour. Même si les secrets sont difficiles à trouver, c’est un jeu de cache-cache que vous finirez par perdre.

Chez Segment, nous gérons de manière centralisée et sécurisée nos secrets avec AWS Systems Manager Parameter Store, une pincée de code Terraform ainsi q’un projet de développement de gestion des secrets appelé Chamber qui s’appuie sur le service AWS Systems Manager Parameter Store. Ce dernier est un outil qui nous convient parfaitement pour la gestion des secrets. Si vous faites fonctionner des charges de travail sur AWS, alors l’utilisation de Parameter Store en tant que magasins de stockage des secrets mérite considération. Cet article dispose de toutes les informations dont vous auriez besoin pour faire fonctionner Parameter Store en environnement de production.

Identité de service

Chez Segment, nous exécutons des centaines de services qui communiquent les uns avec les autres, APIs AWS et APIs tierces. Les services que nous gérons ont des besoins différents et ne devraient avoir accès qu’à des systèmes dont l’interaction est strictement nécessaire. C’est ce qu’on appelle le « principe du moindre privilège ».

Par exemple, notre serveur Web ne devrait jamais avoir accès aux journaux d’audit de sécurité de notre infrastructure. Sans donner une identité aux conteneurs et aux services, il n’est alors pas possible de protéger et de restreindre l’accès aux secrets avec des politiques de contrôle d’accès. Nos services s’identifient à l’aide de rôles IAM créé via le service AWS Identity and Access Management (IAM). À partir des documents AWS : « Un rôle IAM… est une identité avec des stratégies d’autorisation qui déterminent ce que l’identité peut et ne peut pas faire dans AWS ».

Par exemple, nos rôles IAM pour les instances ont un accès en écriture seule à un compartiment Amazon S3 pour ajouter des journaux d’audit, mais empêchent la suppression et la lecture de ces journaux.

Comment les conteneurs peuvent-ils obtenir leur rôle en toute sécurité ?

Une exigence pour utiliser Amazon Elastic Container Service (ECS) est que tous les conteneurs doivent exécuter l’agent de conteneur Amazon ECS (ecs-agent). L’agent s’exécute en tant que conteneur qui orchestre et fournit une API avec laquelle d’autres conteneurs peuvent communiquer. L’agent est le système nerveux central de la façon dont les conteneurs récupèrent les informations d’identification de rôle IAM.

Récupération des informations d'identification avec ecs-agent.

Récupération des informations d’identification avec ecs-agent.

Un élément important pour l’agent est qu’il exécute une API HTTP qui DOIT être accessible aux autres conteneurs qui s’exécutent dans le cluster. Pour rendre cette API disponible, une règle iptables est définie sur l’instance hôte. Cette règle iptables transfère le trafic destiné à une adresse IP spécifique du conteneur ecs-agent.

iptables -t nat \
-A OUTPUT \
-d 169.254.170.2 \
-p tcp \
-m tcp \
--dport 80 \
-j REDIRECT \
--to-ports 51679

Avant que l’agent démarre un conteneur, il récupère d’abord les identifiants pour le rôle de la tâche du conteneur à partir du service d’identification AWS. L’agent définit ensuite l’ID de clé d’identification – il s’agit d’un UUID- en tant que variable d’environnement AWS_CONTENER_CTIFIERALS_RELATIVE_URI à l’intérieur du conteneur lorsqu’il est démarré.

$ env
...
AWS_CONTAINER_CREDENTIALS_RELATIVE_URI=/v2/credentials/53875b56-621a-4b07-8ab6-02ea315b5693
...

En utilisant ces URI et UUID relatifs, les conteneurs récupèrent les informations d’identification AWS de l’agent via HTTP. Un conteneur ne peut pas accéder aux identifiants d’authentification pour imiter l’identité d’un autre conteneur car l’UUID est suffisamment difficile à deviner.

$ curl 169.254.170.2$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI | jq .
{
"RoleArn": "arn:aws:iam::111111111111:role/test-service",
  "AccessKeyId": "ASIAIYLSOW5USUQCZAAQ",
  "SecretAccessKey": "REDACTRED",
  "Token": "REDACTED",
  "Expiration": "2017-08-10T02:01:43Z"
}

Détails supplémentaires sur la sécurité

En tant qu’utilisateurs intensifs d’Amazon ECS, nous avons trouvé des pièges de sécurité associés aux rôles associés aux tâches ECS. Il est important de se rendre compte que tout conteneur qui accède au service de métadonnées Amazon Elastic Compute Cloud (EC2) en tant qu’hôte, peut endosser n’importe quel autre rôle de tâche ECS sur le système. Cela permettrait dès lors aux conteneurs de contourner les politiques de contrôle d’accès, et l’accès à des systèmes non autorisés, comme expliqué dans la documentation à la section  ECS_ENABLE_TASK_IAM_ROLE_NETWORK_HOST. De plus amples informations sont disponibles à cette page. Prenez donc bien soin de restreindre cet accès, car il n’est pas positionné par défaut.

L'accès des conteneurs non privilégiés au service de métadonnées Amazon EC2 est bloqué

L’accès des conteneurs non privilégiés au service de métadonnées Amazon EC2 est bloqué.

Les deux façons dont un conteneur peut accéder au service de métadonnées sont l’utilisation du réseau hôte, et du pont docker. Lorsqu’un conteneur est exécuté avec -network='host', il est toujours en mesure de se connecter au service de métadonnées EC2 à l’aide du réseau de son hôte. La définition de la variable ECS_ENABLE_TASK_IAM_ROLE_NETWORK_HOST sur false dans le fichier de configuration ecs-agent empêche les conteneurs de s’exécuter avec cette permission.

En complément, il est important de bloquer l’accès à l’adresse IP du service de métadonnées via le pont Docker à l’aide d’iptables. La documentation du Rôles IAM pour les tâches recommande d’empêcher l’accès au service de métadonnées EC2 avec cette règle spécifique.

$ iptables --insert FORWARD 1 --in-interface docker+ --destination 169.254.169.254/32 --jump DROP

Il faut toujours garder le principe du moindre privilège à l’esprit lors de la construction d’un système de sécurité. Définir ECS_DISABLE_PRIVILEGED sur true dans le fichier de configuration ecs-agent de l’hôte peut empêcher l’exécution de conteneurs Docker privilégiés et causer d’autres enjeux de sécurité, comme indiqué dans la documentation. Veillez donc à bien positionner ce paramètre comme tel.

Parameter Store

L’AWS System Manager Parameter Store est un service AWS qui stocke des chaînes de caractères. Il peut stocker tous types de données (secrètes ou pas). Les secrets stockés dans le Parameter Store deviennent des chaînes de caractères chiffrés à l’aide d’une clé gérée par AWS Key Management Service (KMS) spécifique au client.

Dans les coulisses, pour qu’un service demande un accès à des chaînes sécurisées à partir du Parameter Store, il se passe beaucoup de choses :

  1. L’agent du conteneur ECS demande les informations d’identification temporaires de l’instance hôte.
  2. L’agent génère en permanence des informations d’identification temporaires pour chaque rôle de tâche ECS exécuté sur ECS, à l’aide d’un service appelé ACS.
  3. Lorsque l’agent démarre chaque tâche, il définit un UUID secret dans l’environnement du conteneur.
  4. Lorsque la tâche a besoin de ses informations d’identification de rôle de tâche, elle les demande à l’API ecs-agent et s’authentifie avec l’UUID secret.
  5. La tâche ECS demande ses secrets à Parameter Store à l’aide des informations d’identification du rôle de tâche.
  6. Le Parameter Store déchiffre ces chaînes sécurisées de manière transparente avant de les renvoyer à la tâche ECS.
Demande d'accès aux chaînes sécurisées du Parameter Store

Demande d’accès aux chaînes sécurisées du Parameter Store.

L’utilisation de rôles avec le Parameter Store est particulièrement utile car il ne nécessite pas de maintenir des jetons d’authentification (access key/ secret access key) supplémentaires. Cela créerait des tracas et secrets supplémentaires à gérer !

Stratégies IAM de Parameter Store

Chaque rôle qui accède à Parameter Store nécessite l’autorisation ssm:GetParameters. « SSM » signifie « Simple System Manager », l’ancien nom de Systems Manager, et explique comment AWS désigne les opérations de Parameter Store.

L’autorisation ssm:GetParameters est la stratégie utilisée pour appliquer le contrôle d’accès et protéger les secrets d’un service contre un autre. Segment donne à tous les services un rôle IAM qui accorde l’accès aux secrets correspondant au format {{service_name}}/*. Le Parameter Store prend en charge les hiérarchies nativement, de sorte que cette autorisation fournit à chaque service son propre répertoire de secrets.

{
 "Sid": "",
 "Effect": "Allow",
 "Action": "ssm:GetParameters",
 "Resource": [    
   "arn:aws:ssm:*:*:parameter/{{service_name}}/*",
 ]
},

Outre les stratégies de contrôle d’accès, Segment utilise une clé KMS AWS dédiée pour chiffrer les chaînes de caractères sécurisés dans le Parameter Store. Chaque rôle IAM se voit accorder un ensemble d’autorisations KMS afin de déchiffrer les secrets qu’ils stockent dans le Parameter Store.

{
 "Sid": "",
 "Effect": "Allow",
 "Action": [
     "kms:ListKeys",
     "kms:ListAliases",
     "kms:Describe*",
     "kms:Decrypt"
  ],
  "Resource": "parameter_store_key"
}

Automatisation des services d’identification et des stratégies

Segment dispose d’un petit module Terraform qui facilite la création d’un rôle IAM unique, d’équilibreurs de charge, d’enregistrements DNS, d’Auto Scaling` et d’alarmes CloudWatch. Ci-dessous, j’indique comment un équilibreur de charge nginx est défini en utilisant un module.

module "nginx" {
  source            = "../modules/service"
  name              = "nginx"
  image             = "segment/nginx"
  product_area      = "foudation-security"
  health_check_path = "/healthcheck"
  environment       = "${var.environment}"
}

A l’intérieur, le rôle de tâche donné à chaque service dispose de toutes les stratégies IAM que nous avons précédemment répertoriées, ce qui limite l’accès à Parameter Store par la valeur indiquée dans le champ « name ». Aucune configuration n’est requise.

En sus, les développeurs ont la possibilité de remplacer les secrets auxquels leur service a accès en utilisant le paramètre « secret_label » (ou étiquette secrète, en français). Cette étiquette remplace les noms de service dans la stratégie IAM. Si NGINX devait avoir besoin des mêmes secrets qu’une instance HAProxy, les deux services peuvent partager les identifiants en utilisant la même étiquette secrète.

module "nginx" {
  source            = "../modules/service"
  name              = "nginx"
  image             = "segment/nginx"
  product_area      = "foudation-security"
  health_check_path = "/healthcheck"
  environment       = "${var.environment}"
  # Share secrets with loadbalancers
  secret_label = "loadbalancers"
}

 Parameter Store en production

Tous les employés de Segment s’authentifient auprès d’AWS à l’aide d’aws-vault, celui-ci peut stocker en toute sécurité les informations d’identification AWS dans le trousseau macOS ou dans un fichier chiffré pour les utilisateurs Linux. Segment dispose de plusieurs comptes AWS. Les ingénieurs peuvent interagir avec chaque compte à l’aide d’aws-vault et exécuter des commandes localement avec leurs informations d’identification AWS renseignées dans leur environnement.

$ aws-vault exec development -- aws s3 ls s3://segmentio-bucket

Utilisation de Chamber avec Parameter Store

Chamber est un outil CLI que Segment a construit pour permettre aux développeurs et et à leur code de communiquer avec Parameter Store de façon appropriée. En permettant aux développeurs d’utiliser les mêmes outils que ceux qui s’exécutent en production, nous réduisons le nombre de différences entre le code exécuté en développement de celui en Pré-production et Production.

Chamber fonctionne avec aws-vault, et n’a que quelques sous-commandes clés :

  • exec – Une commande après avoir chargé des secrets dans l’environnement.
  • history – des modifications apportées à un secret dans le Parameter Store.
  • list – Les noms de tous les secrets dans un chemin d’accès de services.
  • write – Un secret dans Parameter Store.

Chamber utilise les mécanismes de recherche et d’historique intégrés de Parameter Store pour implémenter les sous-commandes « list » et « history ». Toutes les chaînes stockées dans le Parameter Store sont automatiquement versionnées. La sous-commande utilisée pour récupérer les secrets du Parameter Store est exec. Lorsque les développeurs l’utilisent, ils le font avec aws-vault.

$ aws-vault exec development -- chamber exec loadbalancers -- nginx

Dans la commande précédente, Chamber était exécuté avec les identifiants et les permissions de l’employé sur le compte de développement, et il récupère les secrets associés aux équilibreurs de charge à partir du Parameter Store. Une fois que Chamber a alimenté l’environnement avec les secrets, il exécute le serveur NGINX. 

Execution de Chamber en production

Chamber est embarqué à l’intérieur de nos conteneurs Docker en tant que binaire et est le point d’entrée du conteneur. Chamber transmet des signaux au programme qu’il exécute afin de leur permettre de les gérer convenablement.

Voici une comparaison de ce qu’il y avait besoin pour préparer notre site Web principal avant, et après :

-ENTRYPOINT ["node", "server/boot.js"]
+ENTRYPOINT ["chamber", "exec", "app", "", "node", "server/boot.js"]

Les conteneurs non-Docker peuvent aussi utiliser Chamber pour alimenter leur environnement avec des secrets avant de créer des fichiers de configuration à partir de modèles, d’exécuter des démons, etc.

Audit

Tous les accès à Parameter Store sont enregistrés sous forme de logs avec AWS CloudTrail. Cela rend simple et peu onéreux la mise en place de piste d’audit. La création d’alertes personnalisées et de journalisation d’audit est directe. CloudTrail permet de déterminer exactement quels secrets ont été utilisés et peut rendre possible la découverte de secrets inutilisés ou la possibilité d’accéder aux secrets non autorisés.

AWS enregistre gratuitement tous les accès à Parameter Store sous forme d’événement de gestion CloudTrail. La plupart des solutions SIEM du marché peuvent être configurées pour visualiser et lire les données depuis le service Amazon Simple Storage Service (S3).

Résumé

En utilisant AWS Systems Manager Parameter Store et AWS IAM, Segment a pu créer un outil qui fournit toutes les propriétés les plus importantes dans un système de gestion des secrets.

  • Protéger les secrets au repos avec un chiffrement fort.
  • Appliquer des politiques de contrôle d’accès strictes.
  • Créer des journaux d’audit d’identification, avec prise en charge de l’historique des accès.
  • Une expérience unique en tant que développeur.

Une bonne gestion des secrets peut être très compliquée à mettre en place. De nombreux produits ont été conçus pour gérer des secrets, mais aucun ne correspond mieux aux cas d’utilisation requis par Segment que Parameter Store.

 

Article original rédigé en anglais par Evan Johnson, membre de l’équipe sécurité chez Segment, et traduit par Sébastien Butreau, Partner Solutions Architect dans l’équipe AWS France, LinkedIn.

AWS n’est pas responsable du contenu ou de l’exactitude de cet article. Le contenu et les opinions exprimés dans l’article proviennent uniquement de leur auteur tiers.