ืื•ื˜ื•ืžืฆื™ื” ืฉืœ ื ื™ื”ื•ืœ ืชืขื•ื“ื•ืช SSL ืฉืœ Let's Encrypt ื‘ืืžืฆืขื•ืช ืืชื’ืจ DNS-01 ื•-AWS

ื”ืคื•ืกื˜ ืžืชืืจ ืฉืœื‘ื™ื ืœืื•ื˜ื•ืžืฆื™ื” ืฉืœ ื ื™ื”ื•ืœ ืชืขื•ื“ื•ืช SSL ืž ื‘ื•ืื• ืœื”ืฆืคื™ืŸ CA ื‘ืืžืฆืขื•ืช ืืชื’ืจ DNS-01 ะธ AWS.

acme-dns-route53 ื”ื•ื ื›ืœื™ ืฉื™ืืคืฉืจ ืœื ื• ืœื™ื™ืฉื ืชื›ื•ื ื” ื–ื•. ื–ื” ื™ื›ื•ืœ ืœืขื‘ื•ื“ ืขื ืื™ืฉื•ืจื™ SSL ืž-Let's Encrypt, ืœืฉืžื•ืจ ืื•ืชื ื‘ืžื ื”ืœ ื”ืชืขื•ื“ื•ืช ืฉืœ Amazon, ืœื”ืฉืชืžืฉ ื‘-API ืฉืœ Route53 ื›ื“ื™ ืœื™ื™ืฉื ืืช ืืชื’ืจ ื”-DNS-01, ื•ืœื‘ืกื•ืฃ, ืœื“ื—ื•ืฃ ื”ืชืจืื•ืช ืœ-SNS. IN acme-dns-route53 ื™ืฉ ื’ื ืคื•ื ืงืฆื™ื•ื ืœื™ื•ืช ืžื•ื‘ื ื™ืช ืœืฉื™ืžื•ืฉ ื‘ืชื•ืš AWS Lambda, ื•ื–ื” ืžื” ืฉืื ื—ื ื• ืฆืจื™ื›ื™ื.

ืžืืžืจ ื–ื” ืžื—ื•ืœืง ืœ-4 ื—ืœืงื™ื:

  • ื™ืฆื™ืจืช ืงื•ื‘ืฅ zip;
  • ื™ืฆื™ืจืช ืชืคืงื™ื“ IAM;
  • ื™ืฆื™ืจืช ืคื•ื ืงืฆื™ื™ืช ืœืžื‘ื“ื” ืฉืคื•ืขืœืช acme-dns-route53;
  • ื™ืฆื™ืจืช ื˜ื™ื™ืžืจ CloudWatch ืฉืžืคืขื™ืœ ืคื•ื ืงืฆื™ื” 2 ืคืขืžื™ื ื‘ื™ื•ื;

ื”ืขืจื”: ืœืคื ื™ ืฉืชืชื—ื™ืœ ืืชื” ืฆืจื™ืš ืœื”ืชืงื™ืŸ GoLang 1.9+ ะธ AWS CLI

ื™ืฆื™ืจืช ืงื•ื‘ืฅ zip

acme-dns-route53 ื›ืชื•ื‘ ื‘-GoLang ื•ืชื•ืžืš ื‘ื’ืจืกื” ืฉืื™ื ื” ื ืžื•ื›ื” ืž-1.9.

ืื ื—ื ื• ืฆืจื™ื›ื™ื ืœื™ืฆื•ืจ ืงื•ื‘ืฅ zip ืขื ืงื•ื‘ืฅ ื‘ื™ื ืืจื™ acme-dns-route53 ื‘ึผึฐืชื•ึนืš. ื›ื“ื™ ืœืขืฉื•ืช ื–ืืช ืืชื” ืฆืจื™ืš ืœื”ืชืงื™ืŸ acme-dns-route53 ืžืžืื’ืจ GitHub ื‘ืืžืฆืขื•ืช ื”ืคืงื•ื“ื” go install:

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

ื”ื‘ื™ื ืืจื™ ืžื•ืชืงืŸ ื‘ $GOPATH/bin ืžึทื“ืจึดื™ืš. ืฉื™ืžื• ืœื‘ ืฉื‘ืžื”ืœืš ื”ื”ืชืงื ื” ืฆื™ื™ื ื• ืฉืชื™ ืกื‘ื™ื‘ื•ืช ืฉื”ืฉืชื ื•: GOOS=linux ะธ GOARCH=amd64. ื”ื ืžื‘ื”ื™ืจื™ื ืœืžื”ื“ืจ ืฉืœ Go ืฉื”ื•ื ืฆืจื™ืš ืœื™ืฆื•ืจ ืงื•ื‘ืฅ ื‘ื™ื ืืจื™ ื”ืžืชืื™ื ืœืืจื›ื™ื˜ืงื˜ื•ืจืช ืœื™ื ื•ืงืก ื•-amd64 - ื–ื” ืžื” ืฉืจืฅ ืขืœ AWS.
AWS ืžืฆืคื” ืฉื”ืชื•ื›ื ื™ืช ืฉืœื ื• ืชื™ืคืจืก ื‘ืงื•ื‘ืฅ zip, ืื– ื‘ื•ืื• ื ื™ืฆื•ืจ acme-dns-route53.zip ืืจื›ื™ื•ืŸ ืฉื™ื›ื™ืœ ืืช ื”ื‘ื™ื ืืจื™ ืฉื”ื•ืชืงืŸ ืœืื—ืจื•ื ื”:

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

ื”ืขืจื”: ื”ืงื•ื‘ืฅ ื”ื‘ื™ื ืืจื™ ืฆืจื™ืš ืœื”ื™ื•ืช ื‘ืฉื•ืจืฉ ืฉืœ ืืจื›ื™ื•ืŸ ื”-zip. ื‘ืฉื‘ื™ืœ ื–ื” ืื ื—ื ื• ืžืฉืชืžืฉื™ื -j ื“ึถื’ึถืœ.

ื›ืขืช ื›ื™ื ื•ื™ ื”-zip ืฉืœื ื• ืžื•ื›ืŸ ืœืคืจื™ืกื”, ื›ืœ ืžื” ืฉื ื•ืชืจ ื”ื•ื ืœื™ืฆื•ืจ ืชืคืงื™ื“ ืขื ื”ื–ื›ื•ื™ื•ืช ื”ื“ืจื•ืฉื•ืช.

ื™ืฆื™ืจืช ืชืคืงื™ื“ IAM

ืื ื—ื ื• ืฆืจื™ื›ื™ื ืœื”ืงื™ื ืชืคืงื™ื“ IAM ืขื ื”ื–ื›ื•ื™ื•ืช ื”ื ื“ืจืฉื•ืช ืขืœ ื™ื“ื™ ื”ืœืžื‘ื“ื” ืฉืœื ื• ื‘ืžื”ืœืš ื‘ื™ืฆื•ืขื•.
ื‘ื•ืื• ื ืงืจื ืœื–ื” ืžื“ื™ื ื™ื•ืช lambda-acme-dns-route53-executor ื•ืžื™ื“ ืœืชืช ืœื” ืชืคืงื™ื“ ื‘ืกื™ืกื™ AWSLambdaBasicExecutionRole. ื–ื” ื™ืืคืฉืจ ืœืžื‘ื“ื” ืฉืœื ื• ืœื”ืคืขื™ืœ ื•ืœื›ืชื•ื‘ ื™ื•ืžื ื™ื ืœืฉื™ืจื•ืช AWS CloudWatch.
ืจืืฉื™ืช, ืื ื• ื™ื•ืฆืจื™ื ืงื•ื‘ืฅ JSON ืฉืžืชืืจ ืืช ื”ื–ื›ื•ื™ื•ืช ืฉืœื ื•. ื–ื” ื‘ืขืฆื ื™ืืคืฉืจ ืœืฉื™ืจื•ืชื™ ืœืžื‘ื“ื” ืœื”ืฉืชืžืฉ ื‘ืชืคืงื™ื“ lambda-acme-dns-route53-executor:

$ touch ~/lambda-acme-dns-route53-executor-policy.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:${var.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 (ืฉื ืžืฉืื‘ ืืžื–ื•ืŸ) - ื ืฆื˜ืจืš ืื•ืชื” ื‘ืฉืœื‘ื™ื ื”ื‘ืื™ื.

ืชืคืงื™ื“ื• ืฉืœ lambda-acme-dns-route53-executor ื ื•ืฆืจ, ื›ืขืช ืขืœื™ื ื• ืœืฆื™ื™ืŸ ื”ืจืฉืื•ืช ืขื‘ื•ืจื•. ื”ื“ืจืš ื”ืงืœื” ื‘ื™ื•ืชืจ ืœืขืฉื•ืช ื–ืืช ื”ื™ื ืœื”ืฉืชืžืฉ ื‘ืคืงื•ื“ื” aws iam attach-role-policyืขืœ ื™ื“ื™ ื”ืขื‘ืจืช ื”ืคื•ืœื™ืกื” 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

ื”ื™ื“ื“! ืขื›ืฉื™ื• ืืชื” ื™ื›ื•ืœ ืœืคืจื•ืก ืืช ื”ืคื•ื ืงืฆื™ื” ืฉืœื ื• ืœ-AWS ื‘ืืžืฆืขื•ืช ื”ืคืงื•ื“ื” aws lambda create-function. ื™ืฉ ืœื”ื’ื“ื™ืจ ืืช ื”ืœืžื‘ื“ื” ื‘ืืžืฆืขื•ืช ืžืฉืชื ื™ ื”ืกื‘ื™ื‘ื” ื”ื‘ืื™ื:

  • AWS_LAMBDA - ืžื‘ื”ื™ืจ acme-dns-route53 ืฉื”ื‘ื™ืฆื•ืข ืžืชืจื—ืฉ ื‘ืชื•ืš AWS Lambda.
  • DOMAINS - ืจืฉื™ืžื” ืฉืœ ืชื—ื•ืžื™ื ืžื•ืคืจื“ื™ื ื‘ืคืกื™ืงื™ื.
  • LETSENCRYPT_EMAIL - ืžื›ื™ืœ ื‘ื•ืื• ืœื”ืฆืคื™ืŸ ืื™ืžื™ื™ืœ.
  • NOTIFICATION_TOPIC - ืฉื ื ื•ืฉื ื”ื•ื“ืขืช SNS (ืื•ืคืฆื™ื•ื ืœื™).
  • STAGING - ืœืคื™ ื”ืขืจืš 1 ื ืขืฉื” ืฉื™ืžื•ืฉ ื‘ืกื‘ื™ื‘ืช ื”ื‘ืžื”.
  • 1024 MB - ืžื’ื‘ืœืช ื–ื™ื›ืจื•ืŸ, ื ื™ืชืŸ ืœืฉื™ื ื•ื™.
  • 900 ืฉื ื™ื•ืช (15 ื“ืงื•ืช) - ืคืกืง ื–ืžืŸ.
  • acme-dns-route53 - ืฉื ื”ื‘ื™ื ืืจื™ ืฉืœื ื•, ืฉื ืžืฆื ื‘ืืจื›ื™ื•ืŸ.
  • fileb://~/acme-dns-route53.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",[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"
 }

ื™ืฆื™ืจืช ื˜ื™ื™ืžืจ CloudWatch ืฉืžืคืขื™ืœ ืคื•ื ืงืฆื™ื” 2 ืคืขืžื™ื ื‘ื™ื•ื

ื”ืฉืœื‘ ื”ืื—ืจื•ืŸ ื”ื•ื ืœื”ื’ื“ื™ืจ ืืช cron, ืฉืงื•ืจื ืœืคื•ื ืงืฆื™ื” ืฉืœื ื• ืคืขืžื™ื™ื ื‘ื™ื•ื:

  • ืฆื•ืจ ื›ืœืœ CloudWatch ืขื ื”ืขืจืš schedule_expression.
  • ืฆื•ืจ ื™ืขื“ ื›ืœืœ (ืžื” ื™ืฉ ืœื‘ืฆืข) ืขืœ ื™ื“ื™ ืฆื™ื•ืŸ ื”-ARN ืฉืœ ืคื•ื ืงืฆื™ื™ืช lambda.
  • ืœืชืช ืจืฉื•ืช ืœื›ืœืœ ืœืงืจื•ื ืœืคื•ื ืงืฆื™ื™ืช lambda.

ืœืžื˜ื” ืฆื™ืจืคืชื™ ืืช ืชืฆื•ืจืช ื”- Terraform ืฉืœื™, ืื‘ืœ ืœืžืขืฉื” ื–ื” ื ืขืฉื” ื‘ืฆื•ืจื” ืคืฉื•ื˜ื” ืžืื•ื“ ื‘ืืžืฆืขื•ืช ืงื•ื ืกื•ืœืช AWS ืื• 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}"
}

ื›ืขืช ืืชื” ืžื•ื’ื“ืจ ืœื™ืฆื•ืจ ื•ืœืขื“ื›ืŸ ื‘ืื•ืคืŸ ืื•ื˜ื•ืžื˜ื™ ืชืขื•ื“ื•ืช SSL

ืžืงื•ืจ: www.habr.com

ื”ื•ืกืคืช ืชื’ื•ื‘ื”