Automatización de la gestión de certificados SSL de Let's Encrypt mediante desafío DNS-01 y AWS

La publicación describe los pasos para automatizar la gestión de certificados SSL desde Cifremos CA utilizando Desafío DNS-01 и AWS.

acme-dns-ruta53 es una herramienta que nos permitirá implementar esta característica. Puede funcionar con certificados SSL de Let's Encrypt, guardarlos en Amazon Certificate Manager, usar la API Route53 para implementar el desafío DNS-01 y, finalmente, enviar notificaciones a SNS. EN acme-dns-ruta53 También hay una funcionalidad integrada para usar dentro de AWS Lambda, y esto es lo que necesitamos.

Este artículo se divide en 4 secciones:

  • crear un archivo zip;
  • crear un rol de IAM;
  • creando una función lambda que se ejecuta acme-dns-ruta53;
  • crear un temporizador CloudWatch que active una función 2 veces al día;

Nota: Antes de comenzar necesitas instalar GoLang 1.9+ и CLI de AWS

Creando un archivo zip

acme-dns-route53 está escrito en GoLang y admite una versión no inferior a 1.9.

Necesitamos crear un archivo zip con un binario. acme-dns-route53 adentro. Para hacer esto necesitas instalar acme-dns-route53 desde el repositorio de GitHub usando el comando go install:

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

El binario está instalado en $GOPATH/bin directorio. Tenga en cuenta que durante la instalación especificamos dos entornos modificados: GOOS=linux и GOARCH=amd64. Le dejan claro al compilador de Go que necesita crear un binario adecuado para el sistema operativo Linux y la arquitectura AMD64; esto es lo que se ejecuta en AWS.
AWS espera que nuestro programa se implemente en un archivo zip, así que creemos acme-dns-route53.zip archivo que contendrá el binario recién instalado:

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

Nota: El binario debe estar en la raíz del archivo zip. Para esto utilizamos -j bandera.

Ahora nuestro apodo zip está listo para su implementación, todo lo que queda es crear un rol con los derechos necesarios.

Crear un rol de IAM

Necesitamos configurar un rol de IAM con los derechos requeridos por nuestra lambda durante su ejecución.
Llamemos a esta política lambda-acme-dns-route53-executor e inmediatamente darle un papel básico AWSLambdaBasicExecutionRole. Esto permitirá que nuestra lambda se ejecute y escriba registros en el servicio AWS CloudWatch.
Primero, creamos un archivo JSON que describe nuestros derechos. Básicamente, esto permitirá que los servicios lambda utilicen el rol lambda-acme-dns-route53-executor:

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

El contenido de nuestro archivo es el siguiente:

{
    "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:${var.region}:<AWS_ACCOUNT_ID>:<TOPIC_NAME>",
                "arn:aws:route53:::hostedzone/*",
                "arn:aws:route53:::change/*",
                "arn:aws:acm:<AWS_REGION>:<AWS_ACCOUNT_ID>:certificate/*"
            ]
        }
    ]
}

Ahora ejecutemos el comando aws iam create-role para crear un rol:

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

Nota: Recuerde la política ARN (nombre del recurso de Amazon): la necesitaremos en los próximos pasos.

Papel lambda-acme-dns-route53-executor creado, ahora necesitamos especificar permisos para ello. La forma más sencilla de hacerlo es utilizar el comando aws iam attach-role-policy, pasando la política ARN AWSLambdaBasicExecutionRole следующим обрахом:

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

Nota: se puede encontrar una lista con otras políticas aquí.

Creando una función lambda que se ejecuta acme-dns-ruta53

¡Hurra! Ahora puede implementar nuestra función en AWS usando el comando aws lambda create-function. La lambda debe configurarse utilizando las siguientes variables de entorno:

  • AWS_LAMBDA - lo deja claro acme-dns-ruta53 esa ejecución ocurre dentro de AWS Lambda.
  • DOMAINS — una lista de dominios separados por comas.
  • LETSENCRYPT_EMAIL - contiene Cifremos el correo electrónico.
  • NOTIFICATION_TOPIC — nombre del tema de notificación del SNS (opcional).
  • STAGING - al valor 1 Se utiliza el entorno de puesta en escena.
  • 1024 MB: límite de memoria, se puede cambiar.
  • 900 segundos (15 min): tiempo de espera.
  • acme-dns-route53 — el nombre de nuestro binario, que está en el archivo.
  • fileb://~/acme-dns-route53.zip - la ruta al archivo que creamos.

Ahora implementemos:

$ 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",[email protected],STAGING=0,NOTIFICATION_TOPIC=acme-dns-route53-obtained}" 
 --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": "[email protected]", 
            "NOTIFICATION_TOPIC": "acme-dns-route53-obtained", 
            "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"
 }

Crear un temporizador de CloudWatch que active una función 2 veces al día

El último paso es configurar cron, que llama a nuestra función dos veces al día:

  • cree una regla de CloudWatch con el valor schedule_expression.
  • cree un objetivo de regla (lo que se debe ejecutar) especificando el ARN de la función lambda.
  • dar permiso a la regla para llamar a la función lambda.

A continuación adjunto mi configuración de Terraform, pero en realidad esto se hace de manera muy simple usando la consola de AWS o la CLI de AWS.

# 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}"
}

Ahora está configurado para crear y actualizar automáticamente certificados SSL

Fuente: habr.com

Añadir un comentario