让我们通过使用DNS-01挑战和AWS进行加密自动获取SSL证书

这篇文章介绍了使用Let's Encrypt作为自动证书颁发机构(它提供维护良好的API)来设置自动SSL证书创建和更新所需的步骤。
acme-dns-route53是一种工具,可通过带有Route53的 DNS-01质询和AWS的Amazon Certificate ManagerLet's Encrypt获得SSL证书。 acme-dns-route53还具有内置功能,可以在AWS Lambda中使用此工具,这就是我们要做的。


这篇文章分为4个部分:


  • 建立一个独立的,可部署的zip文件
  • 为lambda函数创建一个IAM角色,使其具有执行所需的权限
  • 创建一个执行acme-dns-route53的lambda函数
  • 创建每天两次触发lambda函数的CloudWatch计时器

注意:开始之前,请确保已安装GoLang 1.9+和AWS CLI。


构建一个独立的,可部署的zip文件


acme-dns-route53acme-dns-route53编写,支持版本不少于1.9。 我们需要创建一个独立的,可部署的zip文件,其中包含acme-dns-route53工具的可执行文件。


第一步是使用go install命令从acme-dns-route53工具的远程GitHub存储库中构建可执行文件:


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

该可执行文件将安装在$GOPATH/bin目录中。 重要提示:作为此命令的一部分,我们使用env在命令持续时间内临时设置两个环境变量( GOOS=linuxGOARCH=amd64 )。 这些指令指示Go编译器创建适用于Linux OS和amd64架构的可执行文件-当我们将其部署到AWS时,它将在运行该可执行文件。
AWS要求我们将lambda函数上传到一个zip文件中,因此让我们制作一个acme-dns-route53.zip zip文件,其中包含我们刚刚创建的可执行文件:


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

请注意,可执行文件必须位于zip文件的根目录中-而不是zip文件中的文件夹中。 为了确保这一点,我在上面的片段中使用了-j标志来填充目录名。


现在可以部署该zip文件,但是它仍然需要运行权限。


为lambda函数创建一个IAM角色,使其具有执行所需的权限


我们需要设置一个IAM角色,该角色定义lambda函数在运行时将具有的权限。
现在,让我们设置一个lambda-acme-dns-route53-executor角色,并将AWSLambdaBasicExecutionRole托管策略附加到该角色。 这将为我们的lambda函数提供运行和登录到AWS CloudWatch服务所需的基本权限。
首先,我们必须创建一个信任策略JSON文件。 这实际上将指示AWS允许lambda服务承担lambda-acme-dns-route53-executor角色:


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

创建的JSON文件的内容应为以下内容:


 { "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/*" ] } ] } 

然后使用aws iam create-role命令使用此信任策略创建角色:


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

记下返回的ARN(Amazon资源名称)-下一步将需要它。


现在,已经创建了lambda-acme-dns-route53-executor角色,我们需要指定该角色具有的权限。 最简单的方法是使用aws iam attach-role-policy命令,传入AWSLambdaBasicExecutionRole权限策略的ARN, AWSLambdaBasicExecutionRole所示:


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

注意:您可以在此处找到其他可能有用的权限策略列表。


创建一个执行acme-dns-route53的lambda函数


现在,我们准备将lambda函数实际部署到AWS,我们可以使用aws lambda create-function命令来完成。 lambda函数需要配置以下选项:


  • 值为1 AWS_LAMBDA环境变量,用于调整在Lambda内部函数中使用的工具。
  • DOMAINS是环境变量,包含要为其颁发证书的域的逗号分隔列表。
  • LETSENCRYPT_EMAIL是环境变量,其中包含“让我们加密到期电子邮件”。
  • NOTIFICATION_TOPIC是包含SNS通知主题ARN的环境变量。
  • STAGING是环境变量,使用暂存“加密环境”时必须包含1值,而对于生产环境则必须包含0 1值。
  • RENEW_BEFORE是定义过期前必须更新证书的期限的天数。
  • 1024 MB是内存限制(可以根据需要更改)。
  • 最大超时时间为900秒(15分钟)。
  • acme-dns-route53是lambda函数的处理程序名称。
  • fileb://~/acme-dns-route53.zip是上面创建的.zip文件。

继续尝试部署它:


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

创建每天触发一次lambda函数的CloudWatch计时器


最后一步是为该功能创建每日触发器。 为此,我们可以:


  • 使用所需的schedule_expression (何时运行)创建CloudWatch规则。
  • 创建一个指定lambda函数的ARN的规则目标(应该运行的目标)。
  • 授予CloudWatch规则权限以调用lambda函数。

我在下面为其粘贴了Terraform配置,但是从AWS控制台或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}" } 

现在您也可以100%自动执行TLS证书续订!

Source: https://habr.com/ru/post/zh-CN451200/


All Articles