Obtention automatique de certificats SSL par Let's Encrypt en utilisant le défi DNS-01 et AWS

Cet article décrit les étapes nécessaires pour configurer la création et le renouvellement automatiques des certificats SSL, en utilisant Let's Encrypt en tant qu'autorité de certification automatisée, qui fournit une API bien entretenue.
acme-dns-route53 est l'outil pour obtenir des certificats SSL à partir de Let's Encrypt en utilisant le défi DNS-01 avec Route53 et Amazon Certificate Manager par AWS. acme-dns-route53 également la fonctionnalité intégrée pour utiliser cet outil dans AWS Lambda, et c'est ce que nous allons faire.


Ce message est divisé en 4 sections:


  • créer un fichier zip autonome et déployable
  • la création d'un rôle IAM pour la fonction lambda qui lui donne les autorisations nécessaires pour exécuter
  • création d'une fonction lambda qui exécute acme-dns-route53
  • créer une minuterie CloudWatch qui déclenche une fonction lambda deux fois par jour

Remarque: avant de commencer, assurez-vous que GoLang 1.9+ et AWS CLI sont déjà installés.


Construit un fichier zip autonome et déployable


acme-dns-route53 est écrit en GoLang et prend en charge la version au moins 1.9. Nous devons créer un fichier zip autonome et déployable contenant à l'intérieur l' acme-dns-route53 outil acme-dns-route53 .


La première étape consiste à créer un exécutable à partir du acme-dns-route53 GitHub distant de l'outil acme-dns-route53 aide de la commande go install :


 $ env GOOS=linux GOARCH=amd64 go install github.com/begmaroman/acme-dns-route53 

L'exécutable sera installé dans le $GOPATH/bin . Important: dans le cadre de cette commande, nous utilisons env pour définir temporairement deux variables d'environnement pour la durée de la commande ( GOOS=linux et GOARCH=amd64 ). Ceux-ci indiquent au compilateur Go de créer un exécutable adapté à une utilisation avec un système d'exploitation Linux et une architecture amd64 - sur quoi il s'exécutera lorsque nous le déploierons sur AWS.
AWS nous oblige à télécharger nos fonctions lambda dans un fichier zip, alors acme-dns-route53.zip un fichier zip acme-dns-route53.zip contenant l'exécutable que nous venons de créer:


 $ zip -j ~/acme-dns-route53.zip $GOPATH/bin/acme-dns-route53 

Notez que l'exécutable doit se trouver à la racine du fichier zip - pas dans un dossier du fichier zip. Pour garantir cela, j'ai utilisé l'indicateur -j dans l'extrait ci-dessus pour supprimer les noms de répertoires.


Le fichier zip peut maintenant être déployé, mais il a encore besoin d'autorisations pour s'exécuter.


Création d'un rôle IAM pour la fonction lambda qui lui donne les autorisations nécessaires pour s'exécuter


Nous devons configurer un rôle IAM qui définit l'autorisation que notre fonction lambda aura lorsqu'elle est en cours d'exécution.
Pour l'instant, configurons un rôle lambda-acme-dns-route53-executor et attachons-lui la AWSLambdaBasicExecutionRole gérée AWSLambdaBasicExecutionRole . Cela donnera à notre fonction lambda les autorisations de base dont elle a besoin pour s'exécuter et se connecter au service AWS CloudWatch.
Tout d'abord, nous devons créer un fichier JSON de stratégie de confiance. Cela demandera essentiellement à AWS d'autoriser les services lambda à assumer le rôle d' lambda-acme-dns-route53-executor :


 $ touch ~/lambda-acme-dns-route53-executor-policy.json 

Le contenu du fichier JSON créé doit être le suivant:


 { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "logs:CreateLogGroup" ], "Resource": "arn:aws:logs:<AWS_REGION>:<AWS_ACCOUNT_ID>:*" }, { "Effect": "Allow", "Action": [ "logs:PutLogEvents", "logs:CreateLogStream" ], "Resource": "arn:aws:logs:<AWS_REGION>:<AWS_ACCOUNT_ID>:log-group:/aws/lambda/acme-dns-route53:*" }, { "Sid": "", "Effect": "Allow", "Action": [ "route53:ListHostedZones", "cloudwatch:PutMetricData", "acm:ImportCertificate", "acm:ListCertificates" ], "Resource": "*" }, { "Sid": "", "Effect": "Allow", "Action": [ "sns:Publish", "route53:GetChange", "route53:ChangeResourceRecordSets", "acm:ImportCertificate", "acm:DescribeCertificate" ], "Resource": [ "arn:aws:sns:<AWS_REGION>:<AWS_ACCOUNT_ID>:<TOPIC_NAME>", "arn:aws:route53:::hostedzone/*", "arn:aws:route53:::change/*", "arn:aws:acm:<AWS_REGION>:<AWS_ACCOUNT_ID>:certificate/*" ] } ] } 

Utilisez ensuite la commande aws iam create-role pour créer le rôle avec cette stratégie d'approbation:


 $ aws iam create-role --role-name lambda-acme-dns-route53-executor \ --assume-role-policy-document ~/lambda-acme-dns-route53-executor-policy.json 

Prenez note de l'ARN retourné (Amazon Resource Name) - vous en aurez besoin à l'étape suivante.


Maintenant que le rôle lambda-acme-dns-route53-executor a été créé, nous devons spécifier les autorisations dont le rôle dispose. La façon la plus simple de procéder consiste à utiliser la commande aws iam attach-role-policy , en transmettant l'ARN de la AWSLambdaBasicExecutionRole autorisation AWSLambdaBasicExecutionRole comme AWSLambdaBasicExecutionRole :


 $ aws iam attach-role-policy --role-name lambda-acme-dns-route53-executor \ --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole 

Remarque: vous pouvez trouver une liste d'autres politiques d'autorisation qui pourraient être utiles ici .


Création d'une fonction lambda qui exécute acme-dns-route53


Nous sommes maintenant prêts à déployer réellement la fonction lambda sur AWS, ce que nous pouvons faire en utilisant la commande aws lambda create-function . La fonction lambda doit être configurée avec les options suivantes:


  • AWS_LAMBDA environnement AWS_LAMBDA avec la valeur 1 qui ajuste l'outil pour l'utilisation à l'intérieur de la fonction Lambda.
  • DOMAINS est la variable d'environnement qui contient une liste de domaines séparés par des virgules pour lesquels des certificats seront émis.
  • LETSENCRYPT_EMAIL est la variable d'environnement qui contient l'e-mail d'expiration Let's Encrypt.
  • NOTIFICATION_TOPIC est la variable d'environnement qui contient le SNN Notification Topic ARN.
  • STAGING est la variable d'environnement qui doit contenir 1 valeur pour l'utilisation de l'environnement Let's Encrypt intermédiaire ou 0 pour l'environnement de production.
  • RENEW_BEFORE est le nombre de jours définissant la période avant expiration au cours de laquelle un certificat doit être renouvelé.
  • 1024 Mo est la limite de mémoire (peut être modifiée si nécessaire).
  • 900 secondes (15 min) est le délai maximum.
  • acme-dns-route53 est le nom du gestionnaire de la fonction lambda.
  • fileb://~/acme-dns-route53.zip est le fichier .zip créé ci-dessus.

Allez-y et essayez de le déployer:


 $ aws lambda create-function \ --function-name acme-dns-route53 \ --runtime go1.x \ --role arn:aws:iam::<AWS_ACCOUNT_ID>:role/lambda-acme-dns-route53-executor \ --environment Variables="{AWS_LAMBDA=1,DOMAINS=\"example1.com,example2.com\",LETSENCRYPT_EMAIL=begmaroman@gmail.com,STAGING=0,NOTIFICATION_TOPIC=acme-dns-route53-obtained,RENEW_BEFORE=7}" \ --memory-size 1024 \ --timeout 900 \ --handler acme-dns-route53 \ --zip-file fileb://~/acme-dns-route53.zip { "FunctionName": "acme-dns-route53", "LastModified": "2019-05-03T19:07:09.325+0000", "RevisionId": "e3fadec9-2180-4bff-bb9a-999b1b71a558", "MemorySize": 1024, "Environment": { "Variables": { "DOMAINS": "example1.com,example2.com", "STAGING": "1", "LETSENCRYPT_EMAIL": "your@email.com", "NOTIFICATION_TOPIC": "acme-dns-route53-obtained", "RENEW_BEFORE": "7", "AWS_LAMBDA": "1" } }, "Version": "$LATEST", "Role": "arn:aws:iam::<AWS_ACCOUNT_ID>:role/lambda-acme-dns-route53-executor", "Timeout": 900, "Runtime": "go1.x", "TracingConfig": { "Mode": "PassThrough" }, "CodeSha256": "+2KgE5mh5LGaOsni36pdmPP9O35wgZ6TbddspyaIXXw=", "Description": "", "CodeSize": 8456317, "FunctionArn": "arn:aws:lambda:us-east-1:<AWS_ACCOUNT_ID>:function:acme-dns-route53", "Handler": "acme-dns-route53" } 

Création d'une minuterie CloudWatch qui déclenche une fonction lambda une fois par jour


La dernière étape consiste à créer un déclencheur quotidien pour la fonction. Pour ce faire, nous pouvons:


  • créez une règle CloudWatch avec l'expression_horaire souhaitée (quand doit-elle s'exécuter).
  • créer une cible de règle (ce qui doit s'exécuter) en spécifiant l'ARN de la fonction lambda.
  • donner à la règle CloudWatch l'autorisation d'invoquer la fonction lambda.

J'ai collé ma configuration Terraform pour cela ci-dessous, mais il est également très simple de le faire à partir de la console AWS ou de la CLI.


 # Cloudwatch event rule that runs acme-dns-route53 lambda every 12 hours resource "aws_cloudwatch_event_rule" "acme_dns_route53_sheduler" { name = "acme-dns-route53-issuer-scheduler" schedule_expression = "cron(0 */12 * * ? *)" } # Specify the lambda function to run resource "aws_cloudwatch_event_target" "acme_dns_route53_sheduler_target" { rule = "${aws_cloudwatch_event_rule.acme_dns_route53_sheduler.name}" arn = "${aws_lambda_function.acme_dns_route53.arn}" } # Give CloudWatch permission to invoke the function resource "aws_lambda_permission" "permission" { action = "lambda:InvokeFunction" function_name = "${aws_lambda_function.acme_dns_route53.function_name}" principal = "events.amazonaws.com" source_arn = "${aws_cloudwatch_event_rule.acme_dns_route53_sheduler.arn}" } 

Maintenant, vous aussi pouvez avoir des renouvellements de certificats TLS 100% automatisés!

Source: https://habr.com/ru/post/fr451200/


All Articles