Intégrer HashiCorp Vault aux services AWS

le 26/04/2017 par Salim Boulkour
Tags: Software Engineering

Après avoir jeté la PKI Vault sur le grill, nous regardons ici comment Vault peut s'intégrer dans l'environnement AWS.

Notre cas d'usage d'origine était basé sur Puppet et sur le déploiement des certificats par ses agents. J'ai choisi ici de refaire la démo de zéro en utilisant Terraform et Ansible pour des raisons pratiques. À cette différence près, il s'agit de la suite directe du premier article et je vous invite à le lire pour suivre celui-ci.

L'intégration de Vault aux services d'AWS peut se faire à trois endroits :

  • par le backend de stockage, sur S3 et/ou DynamoDB
  • par le backend d'authentification, en ségrégant l'accès aux API Vault qu'à certaines instances EC2.
  • par le secret backend, permettant à Vault de générer des credentials AWS à la demande (sous la forme de couples access_key et secret_key).

N'ayant pas eu l'usage du secret backend AWS, je n'aborde que les deux autres intégrations dans les lignes qui suivent.

Les services AWS pour le stockage des données Vault

Autoriser Vault à écrire dans un bucket S3

La consommation des services AWS suppose généralement l'utilisation d'un couple de clés (access_key et secret_key), qu'il est possible de renseigner en paramètres dans la configuration de Vault. Dans ce cas, ces secrets resteraient sur le disque et ce n'est pas la manière la plus sécurisée de faire. D’autre part, le renouvellement de ces clés serait à notre charge et à effectuer régulièrement.

Vault permet de s'appuyer sur le système d'Instance Profile fourni par AWS, à savoir utiliser des credentials temporaires et générés pour une instance EC2 donnée. Ces credentials sont disponibles dans les métadonnées de l'instance. AWS gère la rotation de ces secrets, ainsi que leur expiration si les droits viennent à être mis à jour ou révoqués.

Application d'une instance EC2 qui accède à une ressource AWSDélégation de droits à une instance EC2

Les credentials sont générés spécifiquement pour l'instance EC2 courante, et sont limités aux droits que vous aurez donné à cette instance. AWS ne génèrera d'ailleurs les paires de clés que si un Instance Profile est attribué à l'instance EC2 en question.

Sans rentrer réellement dans les détails du modèle IAM d'Amazon, voici un exemple des ressources AWS et de leurs associations pour autoriser l'accès à un bucket S3 (écrit ici pour Terraform) :

Instance EC2, associée à son Instance Profile.

Instance Profile.

Le role, autorisant l'accès au service STS et donc à la génération de credentials pour les instances EC2.

Role policy, ajoutant les droits d'accès RW sur le bucket S3 'sbo-vault'.

Une fois ces ressources AWS allouées, nous sommes capables d'instancier une VM EC2 et de lui donner les droits en écriture sur le bucket S3 de notre choix (à créer par ailleurs).

Si vous voulez approfondir les arcanes de l'IAM AWS, voici quelques pointeurs dans la documentation :

S3 comme backend de stockage

Une fois la partie IAM préparée, la configuration de Vault est simplissime et se limite à définir la région AWS et le nom du bucket S3 :

backend "s3" {
  bucket = "sbo-vault"
  region = "eu-west-1"
}
listener "tcp" {
  address     = "127.0.0.1:8200"
  tls_disable = 1
}

Au démarrage Vault accède directement au bucket et y écrit ses données. Après l'initialisation de Vault le contenu du bucket ressemble à ceci :

Si vous souhaitez multiplier les instances de Vault, un bucket S3 est nécessaire pour chaque instance déployée. La concurrence en écriture n'est en effet pas gérée et vous risqueriez de corrompre des secrets.

Par ailleurs, S3 n'est pas éligible comme backend de HA : Vault s'appuie sur  son backend de stockage pour élire le nœud maître lorsque déployé en cluster, et S3 ne permet pas cette élection.

DynamoDB pour ajouter la Haute Dispo ... ou pas

Pour DynamoDB, le fonctionnement est identique à S3 : une fois les bons droits accordés à l'instance, Vault est capable de récupérer les credentials AWS et de se connecter à DynamoDB. Il y a quelques paramètres supplémentaires comparativement à S3 (disponibles ici [EN]), notamment liés au fonctionnement de la Haute Disponibilité.

Bien que référencé comme backend éligible à la HA, DynamoDB souffre d'une limitation nécessitant une intervention manuelle pour gérer la reprise sur erreur.

Si la haute disponibilité n'est pas critique pour votre cas d'usage (typiquement si Vault est utilisé comme PKI et ne fourni qu'un certificat de temps en temps), l'utilisation d'une instance seule "backée_"_ S3 est largement suffisante. Par ailleurs, l’utilisation d’un Autoscaling Group avec un min/max à 1 permet de maintenir cette unique instance up and running en permanence.

En revanche, si la haute disponibilité est essentielle, je vous invite à regarder Consul, etcd voir ZooKeeper comme backends de HA, tout en gardant S3 comme backend principal. En résumé, pour ce qui est de la HA :

Utiliser les services AWS pour s'authentifier sur Vault

Maintenant que nos secrets sont stockés dans S3, intéressons-nous à la façon de requêter ces secrets depuis l'environnement AWS. Comme décrit dans l'article précédent, Vault possède plusieurs secret backends. Et sur chacun de ces backends les ressources exposées peuvent être associées à un ensemble de  politiques de sécurité (policies).

Ces policies sont associées à des utilisateurs ou à des groupes d'utilisateurs, et permettent de définir leurs droits sur les ressources.

Petite subtilité : dans notre exemple du backend PKI, les roles représentent les ressources exposées par le backend PKI. Il ne faut donc pas confondre avec la notion commune du rôle au sens RBAC.

Création d'une policy Vault pour notre PKI

Afin de protéger l'émission de certificats, revenons sur ce que nous avions déjà fait :

$ vault list interca/roles/

Keys

aws-dot-octo

Voici le role que nous avions créé la dernière fois (Cf la PKI Vault sur le grill). Et pour mémoire, il suffit de requêter ce role pour obtenir un nouveau certificat :

$ vault write interca/issue/aws-dot-octo common_name=vault.aws.octo

Key                 Value ---                 ----- lease_id            interca/issue/aws-dot-octo/0d7a8b4f-7f36-c6e1-0ebb-f2f9b0dca194 lease_duration      71h59m59s lease_renewable     false ca_chain            [...] certificate         [...] issuing_ca          [...] private_key         [...] private_key_type    rsa serial_number       6c:98:f6:9b:80:bc:89:32:02:e2:47:34:dc:a9:8c:30:94:00:be:9f

Nous pouvons générer ce certificat car nous utilisons actuellement le token généré à l'initialisation de l'instance Vault. Autrement dit, nous sommes par défaut authentifiés comme root auprès de Vault et avons les droits correspondants.

$ env

[...] VAULT_ADDR=http://127.0.0.1:8200 VAULT_TOKEN=281963cf-88ae-1027-0dcb-ae0a1f0cf3e9

Dans un environnement de production, la création d'utilisateurs aux droits limités et dédiés à certains usages est indispensable, et c'est ce que la création d'une policy va nous permettre de faire.

Par défaut, un client authentifié (autre que root) n'a aucun droit. Il suffit donc de lui associer la policy suivante pour ne l'autoriser qu'à écrire sur notre role :

path "interca/issue/aws-dot-octo" {
  policy = "write"
}

Si vous êtes familier des règles de contrôle d'accès sur les ressources web, vous êtes en terrain connu : on associe un chemin de l'URL avec un droit d'accès. Et il n'y a pas de limite dans le nombre de règles dans une même policy. Vous trouverez dans la doc [EN] les différents verbes et capabilities applicables sur les ressources.

Il faut ensuite passer par un fichier pour enregistrer cette policy , que je nomme policy_aws-dot-octo :

$ vault policy-write policy_aws-dot-octo /tmp/pki-policy.hcl

Policy 'policy_aws-dot-octo' written.

Et voici comment la tester:

$ vault token-create -policy=policy_aws-dot-octo

Key                Value ---                ----- token              06c97184-3b53-8ddd-f927-7f1a358e8269 token_accessor     cc5063ff-2dde-2089-48b7-0f2a753ad985 token_duration     768h0m0s token_renewable    true token_policies     [default policy_aws-dot-octo]

$ export VAULT_TOKEN=06c97184-3b53-8ddd-f927-7f1a358e8269

$ vault write interca/issue/aws-dot-octo common_name=test-policy.aws.octo

Key                 Value ---                 ----- lease_id            interca/issue/aws-dot-octo/86eb0d30-8d59-27f1-4d04-e1a11a1ed40c lease_duration      71h59m59s lease_renewable     false ca_chain            [...] certificate         [...] issuing_ca          [...] private_key         [...] private_key_type    rsa serial_number       7e:9e:eb:2f:a7:ff:c7:4b:62:e6:f5:30:49:43:a7:21:2d:46:aa:c3

$ vault mounts

Error reading mounts: Error making API request.

URL: GET http://127.0.0.1:8200/v1/sys/mounts Code: 403. Errors:

Ce qui s'est passé :

  • Nous avons profité des droits root pour générer un token associé à la policy policy_aws-dot-octo.
  • Nous avons utilisé ce token pour générer un certificat tel qu'autorisé par la policy
  • Une autre commande habituellement possible avec le token root (ici le listing des secrets backends configurés) nous est refusé avec une erreur 403 : Forbidden.

Tadaaa !

Tokens Vault et authentification

Nous venons d'utiliser les privilèges accordés à root pour générer le token d'un utilisateur. Transposé dans le monde réel cela revient à passer par un administrateur pour demander la création de credentials de manière unitaire, et c'est éloigné de ce que l'on veut faire : automatisation / répudiation & expiration des credentials / passage à l'échelle etc.

Vault nous propose des backends d'authentification pour nous appuyer sur des solutions existantes. Au delà de la gestion de l'authentification par tokens (intégrée dans le cœur de Vault), vous pouvez utiliser les traditionnels login + mot de passe, un annuaire LDAP, les certificats x509 ou même GitHub. Dans le cas de GitHub, il est par exemple possible d'accorder des droits d'accès en fonction de l'organisation GitHub à laquelle est rattaché l'utilisateur.

Afin de revenir à un fonctionnement unique, tous les backends d'authentification permettent in fine d'obtenir un token Vault. Et comme dans notre exemple, le token obtenu est scopé sur une policy à sa création. La fin de la séquence est donc identique quelque soit le moyen d'authentification : requête sur l'API Vault avec le token en paramètre.

Le backend auth-ec2

Principes de fonctionnement

Vault nous propose de nous appuyer sur l'infrastructure d'Amazon pour réaliser l'authentification des machines EC2 clientes auprès de Vault.

Toute machine virtuelle du service EC2 peut requêter l'URL http://169.254.169.254/latest/dynamic/instance-identity/document :

$ curl http://169.254.169.254/latest/dynamic/instance-identity/document

{ "devpayProductCodes" : null, "availabilityZone" : "eu-west-1c", "privateIp" : "192.168.1.134", "version" : "2010-08-31", "region" : "eu-west-1", "instanceId" : "i-045d4683886353b08", "billingProducts" : null, "instanceType" : "t2.small", "accountId" : "218232161888", "architecture" : "x86_64", "kernelId" : null, "ramdiskId" : null, "imageId" : "ami-6f587e1c", "pendingTime" : "2017-03-24T15:13:59Z" }

Elle obtient ainsi quelques informations la concernant, comme son adresse IP, son ID et quelques autres métadonnées. De la même manière, avec l'URL http://169.254.169.254/latest/dynamic/instance-identity/pkcs7, les instances obtiennent la signature de cette même carte d'identité, au format PKCS7 et fournie par Amazon :

$ curl http://169.254.169.254/latest/dynamic/instance-identity/pkcs7

MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJBgUrDgMCGgUAMIAGCSqGSIb3DQEHAaCAJIAEggGwewog ICJkZXZwYXlQcm9kdWN0Q29kZXMiIDogbnVsbCwKICAiYXZhaWxhYmlsaXR5Wm9uZSIgOiAiZXUt d2VzdC0xYyIsCiAgInByaXZhdGVJcCIgOiAiMTkyLjE2OC4xLjEzNCIsCiAgInZlcnNpb24iIDog IjIwMTAtMDgtMzEiLAogICJyZWdpb24iIDogImV1LXdlc3QtMSIsCiAgImluc3RhbmNlSWQiIDog ImktMDQ1ZDQ2ODM4ODYzNTNiMDgiLAogICJiaWxsaW5nUHJvZHVjdHMiIDogbnVsbCwKICAiaW5z dGFuY2VUeXBlIiA6ICJ0Mi5zbWFsbCIsCiAgImFjY291bnRJZCIgOiAiMjE4MjMyMTYxODg4IiwK ICAiYXJjaGl0ZWN0dXJlIiA6ICJ4ODZfNjQiLAogICJrZXJuZWxJZCIgOiBudWxsLAogICJyYW1k aXNrSWQiIDogbnVsbCwKICAiaW1hZ2VJZCIgOiAiYW1pLTZmNTg3ZTFjIiwKICAicGVuZGluZ1Rp bWUiIDogIjIwMTctMDMtMjRUMTU6MTM6NTlaIgp9AAAAAAAAMYIBGDCCARQCAQEwaTBcMQswCQYD VQQGEwJVUzEZMBcGA1UECBMQV2FzaGluZ3RvbiBTdGF0ZTEQMA4GA1UEBxMHU2VhdHRsZTEgMB4G A1UEChMXQW1hem9uIFdlYiBTZXJ2aWNlcyBMTEMCCQCWukjZ5V4aZzAJBgUrDgMCGgUAoF0wGAYJ KoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcNMTcwMzI0MTUxNDAwWjAjBgkq hkiG9w0BCQQxFgQU+O2Cc6Uk3aEX7F4DLqAM84G9duAwCQYHKoZIzjgEAwQvMC0CFFgm3Pe+OEVq phaXs78dKkYNIfeyAhUArmf9jgRJLfubT7g/WhWqyx4+kKUAAAAAAAA=

AWS nous donne les moyens de vérifier la signature [EN] avec la clé publique correspondante, et Vault se base sur ces éléments pour authentifier une instance. La séquence :

  1. Vault reçoit une requête d'authentification avec la signature PKCS7 d'une instance EC2
  2. Vault vérifie la validité de la fiche et de sa signature à l'aide des clés publiques AWS (une par région)
  3. Vault confirme ensuite à partir des métadonnées de la fiche que l'instance existe et qu'elle est en cours d'exécution.
  4. Vault répond avec un token

La principale faiblesse de ce moyen d'authentification est le non renouvellement des fiches d'identité des instances EC2. Elles restent identiques jusqu'à la destruction des instances. Afin de prévenir le vol et le rejeu d'une fiche d'identité pendant la vie de l'instance, Vault ajoute la possibilité de créer un nonce [FR] à la première authentification. Une fois le nonce configuré, l'instance en question ne pourras plus s'authentifier auprès de Vault, sans fournir sa fiche d'identité et son nonce simultanément.

Au delà de la phase d'authentification, Vault permet d'ajouter une étape d'autorisation avant de fournir le token. La création d'un role (/!\ cette fois au sens RBAC) dans le backend d'autorisation aws-ec2 , permet de ségréger les instances EC2 à partir des éléments suivants :

  • bound_ami_id, n'autorise que les instances créées à partir d'une AMI donnée
  • bound_account_id, n'autorise que les instances d'un certain compte AWS (il est en effet possible d'utiliser le service STS d'Amazon pour fournir des credentials aux instances d'un autre compte)
  • bound_region, n'autorise que les instances d'une région AWS précise
  • bound_vpc_id, n'autorise que les instances d'un VPC
  • bound_subnet_id, n'autorise que les instances d'un subnet
  • bound_iam_role_arn & bound_iam_instance_profile_arn, n'autorise que les instances possédant un rôle AWS ou un Instance Profile donné.

Cette liste s'allonge et se complète régulièrement avec les nouvelles versions de Vault.

D'autres éléments sont configurables au niveau du role, comme le TTL des tokens générés pour ce role, ou la policy à associer au role. Vous trouverez le détails des paramètres dans la documentation de l'API du backend auth-ec2 [EN].

En pratique : l'authentification par le backend auth-ec2

La première étape consiste à étendre les droits AWS accordés à l'instance EC2 qui héberge notre Vault. Sans ça, Vault ne sera pas en mesure de vérifier l'état des instances EC2 du tenant. La policy AWS suivante vient donc compléter celle déjà créée pour permettre l'accès au bucket S3 :

{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Action": "ec2:DescribeInstances",
    "Resource": "*"
  }]
}

À cette étape, si nous essayons de nous authentifier à partir de l'instance cliente cela ne fonctionnera pas. Vault impose de créer au moins un role afin de spécifier la politique d'émission du token. Nous allons donc créer un role sur aws-ec2 pour nos instances clientes, et les autoriser selon l'AMI utilisée :

$ vault write auth/aws-ec2/role/vault-client bound_ami_id=ami-6f587e1c policies=policy_aws-dot-octo

Success! Data written to: auth/aws-ec2/role/vault-client

Maintenant, testons depuis l'instance cliente. D'abord la récupération de la fiche d'identité au format PKCS7 (en enlevant les sauts de ligne) :

$ curl -s http://169.254.169.254/latest/dynamic/instance-identity/pkcs7 | tr -d

MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJBgUrDgMCGgUAMIAGCSqGSIb3DQEHAaCAJIAEggGvewogICJkZXZwYXlQcm9kdWN0Q29kZXMiIDogbnVsbCwKICAiYXZhaWxhYmlsaXR5Wm9uZSIgOiAiZXUtd2VzdC0xYyIsCiAgInByaXZhdGVJcCIgOiAiMTkyLjE2OC4xLjg1IiwKICAidmVyc2lvbiIgOiAiMjAxMC0wOC0zMSIsCiAgInJlZ2lvbiIgOiAiZXUtd2VzdC0xIiwKICAiaW5zdGFuY2VJZCIgOiAiaS0wZTBjOWZlYmVjY2YzYTIwYiIsCiAgImJpbGxpbmdQcm9kdWN0cyIgOiBudWxsLAogICJpbnN0YW5jZVR5cGUiIDogInQyLnNtYWxsIiwKICAiYWNjb3VudElkIiA6ICIyMTgyMzIxNjE4ODgiLAogICJhcmNoaXRlY3R1cmUiIDogIng4Nl82NCIsCiAgImtlcm5lbElkIiA6IG51bGwsCiAgInJhbWRpc2tJZCIgOiBudWxsLAogICJpbWFnZUlkIiA6ICJhbWktNmY1ODdlMWMiLAogICJwZW5kaW5nVGltZSIgOiAiMjAxNy0wMy0yNFQxNToxMzo1OVoiCn0AAAAAAAAxggEXMIIBEwIBATBpMFwxCzAJBgNVBAYTAlVTMRkwFwYDVQQIExBXYXNoaW5ndG9uIFN0YXRlMRAwDgYDVQQHEwdTZWF0dGxlMSAwHgYDVQQKExdBbWF6b24gV2ViIFNlcnZpY2VzIExMQwIJAJa6SNnlXhpnMAkGBSsOAwIaBQCgXTAYBgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0xNzAzMjQxNTE0MDBaMCMGCSqGSIb3DQEJBDEWBBRhci4q0Js+77sS6PD2hE62+4kPOjAJBgcqhkjOOAQDBC4wLAIUFWPouht+AvoDDZNESGfiTyj5kfQCFFvNVOqgjJU+REbegK/sCYTUNv9RAAAAAAAA

Puis, toujours depuis l'instance cliente, authentification auprès de l'API Vault :

$ curl -X POST "https://vault.aws.octo/v1/auth/aws-ec2/login" -d '{ "role":"vault-client", "pkcs7":"MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJBgUrDgMCGgUAMIICJkZXZwYXlQcm9kdWN0Q29kZXMiIDogbnVsbCwKICAiYXZhaWxhYmlsaXR5Wm9uZSIgOiAiZXUtd2VzdC0xYyIsCiAgInByaXZhdGVJcCIgOiAiMTkyLjE2OC4xLjg1IiwKICAidmVyc2lvbiIgOiAiMjAxMC0wOC0zMSIsCiAgInJlZ2lvbiIgOiAiZXUtd2VzdC0xIiwKICAiaW5zdGFuY2VJZCIgOiAiaS0wZTBjOWZlYmVjY2YzYTIwYiIsCiAgImJpbGxpbmdQcm9kdWN0cyIgOiBudWxsLAogICJpbnN0YW5jZVR5cGUiIDogInQyLnNtYWxsIiwKICAiYWNjb3VudElkIiA6ICIyMTgyMzIxNjE4ODgiLAogICJhcmNoaXRlY3R1cmUiIDogIng4Nl82NCIsCiAgImtlcm5lbElkIiA6IG51bGwsCiAgInJhbWRpc2tJZCIgOiBudWxsLAogICJpbWFnZUlkIiA6ICJhbWktNmY1ODdlMWMiLAogICJwZW5kaW5nVGltZSIgOiAiMjAxNy0wMy0yNFQxNToxMzo1OVoiCn0AAAAAAAAxggEXMIIBEwIBATBpMFwxCzAJBgNVBAYTAlVTMRkwFwYDVQQIExBXYXNoaW5ndG9uIFN0YXRlMRAwDgYDVQQHEwdTZWF0dGxlMSAwHgYDVQQKExdBbWF6b24gV2ViIFNlcnZpY2VzIExMQwIJAJa6SNnlXhpnMAkGBSsOAwIaBQCgXTAYBgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0xNzAzMjQxNTE0MDBaMCMGCSqGSIb3DQEJBDEWBBRhci4q0Js+77sS6PD2hE62+4kPOjAJBgcqhkjOOAQDBC4wLAIUFWPouht+AvoDDZNESGfiTyj5kfQCFFvNVOqgjJU+REbegK/sCYTUNv9RAAAAAAAA", "nonce":"vault-client-nonce"}'

{ "request_id":"60567c2f-8e27-89e8-b4b9-90acfd4360d7", "lease_id":"", "renewable":false, "lease_duration":0, "data":null, "wrap_info":null, "warnings":null, "auth":{ "client_token":"2c23cd00-05b0-4227-5197-904918db742b", "accessor":"a683bd5e-0c0b-0604-fbd9-f944f5366d4c", "policies":["default","policy_aws-dot-octo"], "metadata":{ "account_id":"218232161888", "ami_id":"ami-6f587e1c", "instance_id":"i-0e0c9febeccf3a20b", "nonce":"vault-client-nonce", "region":"eu-west-1", "role":"vault-client", "role_tag_max_ttl":"0s" }, "lease_duration":2764800, "renewable":true } }

En version plus condensée et sans faire de copier coller :

$ curl -X POST "https://vault.aws.octo/v1/auth/aws-ec2/login" -d "{ \"role\":\"vault-client\", \"pkcs7\":\"$(curl -s http://169.254.169.254/latest/dynamic/instance-identity/pkcs7 | tr -d '\n')\", \"nonce\":\"vault-client-nonce\"}"

{ "request_id":"db499fab-f0c8-0a5a-e964-eca68d16b30b", "lease_id":"", "renewable":false, "lease_duration":0, "data":null, "wrap_info":null, "warnings":null, "auth":{ "client_token":"8846033c-3f05-3e7a-52ce-1de876efd2ff", "accessor":"3dfa5e3f-fe2c-dfc1-cd04-8554e894368b", "policies":["default","policy_aws-dot-octo"], "metadata":{ "account_id":"218232161888", "ami_id":"ami-6f587e1c", "instance_id":"i-0e0c9febeccf3a20b", "nonce":"vault-client-nonce", "region":"eu-west-1", "role":"vault-client", "role_tag_max_ttl":"0s" }, "lease_duration":2764800, "renewable":true } }

Dernière étape : générer un certificat en appelant l'API à l'aide du token obtenu :

$ curl -X POST "https://vault.aws.octo/v1/interca/issue/aws-dot-octo" -H "X-Vault-Token:8846033c-3f05-3e7a-52ce-1de876efd2ff" -d '{"common_name":"test.aws.octo","format":"pem"}'

{"request_id":"5df91a88-f1fd-c291-8b0f-06c78b8f3121", "lease_id":"interca/issue/aws-dot-octo/5ec630f0-b7ea-d606-488d-0058dc975ffc", "renewable":false, "lease_duration":259199, "data":{ "ca_chain": ["-----BEGIN CERTIFICATE-----\n [...]\n -----END CERTIFICATE-----"], "certificate": "-----BEGIN CERTIFICATE-----\n [...]\n -----END CERTIFICATE-----", "issuing_ca": "-----BEGIN CERTIFICATE-----\n [...]\n -----END CERTIFICATE-----", "private_key": "-----BEGIN RSA PRIVATE KEY-----\n [...]\n -----END RSA PRIVATE KEY-----", "private_key_type":"rsa", "serial_number":"6a:5a:04:81:97:e8:6e:b3:80:e8:bb:f0:2b:e0:87:24:2a:7b:2e:fd"}, "wrap_info":null, "warnings":null,"auth":null}

Takeaways

Le duo Ansible / Terraform fonctionne bien, et permet de prototyper plus rapidement qu'avec Puppet / Terraform. Dénominateur commun, Terraform reste dans tous les cas incontournable. Nous le préconisons d’ailleurs quasi-systématiquement sur nos missions AWS, malgré le langage HCL parfois bancal ou une gestion des state un peu fragile notamment.

En termes de maîtrise, difficile de se sentir expert Vault après ce POC tant les concepts changent en fonction des backends utilisés. Le produit évolue rapidement : aujourd'hui testé en 0.6.5, une part des fonctionnalités présentées ont déjà été complétées en 0.7.0 puis 0.7.1. (Un coup d'œil sur le changelog et vous verrez que le backend auth-ec2 étend déjà l'authentification aux personnes, aux lambdas, aux instances ECS etc. et non plus aux simples instances EC2).

Quant à l'intégration à AWS, il semble indispensable d’en comprendre les concepts de leur modèle de droits et d’identités (IAM) avant de se lancer en production. Cela rend la courbe d'apprentissage certes plus pentue, mais devrait éviter la fuite de secrets de votre coffre fort.

En bref, Vault répond à mes attentes en termes d'automatisation, d'intégration, de scalabilité et de fonctionnalités. Je m’attends à le re-croiser régulièrement dans de futures missions ...