Create ACM Certificate

In this section you will create an ACM certificate for your domain so that you can terminate TLS at your ALB.

Choose one of the following options to create an ACM certificate for your desired domain:

Check Your Environment

To create the ACM certificate, you are going to deploy a CloudFormation stack. When working with AWS CloudFormation stacks to manage resources, not only do you need sufficient permissions on AWS CloudFormation, but also on the underlying resources that are defined in the template.

In order to create an ACM certificate for your domain using AWS CloudFormation you need permissions for the following actions:

  • Deploy AWS CloudFormation stacks.
  • Request ACM certificates.
  • Describe ACM certificates.
  • Change resource record sets on Route 53.

Note

If you do not have the above permissions, contact your AWS administrator to grant sufficient permissions to your IAM user or deploy the below AWS CloudFormation stack for you.

Option 1: Create ACM Certificate Automatically (preferred)

Create an ACM certificate by following the on-screen instructions on the rok-deploy user interface.

If rok-deploy is not already running, start it with:

root@rok-tools:~# rok-deploy --run-from eks-alb-acm
../../../../_images/eks-alb-acm.png

Proceed to the Summary section.

Option 2: Create ACM Certificate Manually

If you want to create an ACM certificate manually, follow the instructions below.

Procedure

  1. Go to your GitOps repository, inside your rok-tools management environment:

    root@rok-tools:~# cd ~/ops/deployments
  2. Restore the required context from previous sections:

    root@rok-tools:~/ops/deployments# source <(cat deploy/env.{envvars-aws,eks-cluster,eks-alb-zone})
    root@rok-tools:~/ops/deployments# export AWS_DEFAULT_REGION EKS_CLUSTER \ > EKS_ALB_ZONE_DOMAIN EKS_ALB_ZONE_ID
  3. Decide on the desired subdomain for your Load Balancer:

    root@rok-tools:~/ops/deployments# export EKS_ALB_ACM_SUBDOMAIN=<YOUR_SUBDOMAIN>.${EKS_ALB_ZONE_DOMAIN?}

    Replace <YOUR_SUBDOMAIN> with your desired subdomain. For example:

    root@rok-tools:~/ops/deployments# export EKS_ALB_ACM_SUBDOMAIN=${EKS_CLUSTER?}.${EKS_ALB_ZONE_DOMAIN?} \ > && echo ${EKS_ALB_ACM_SUBDOMAIN?} arrikto-cluster.apps.example.com
  4. Set the name of the CloudFormation stack you will deploy:

    root@rok-tools:~/ops/deployments# export EKS_ALB_ACM_CF=rok-${AWS_DEFAULT_REGION?}\ > -${EKS_CLUSTER?}-acm
  5. Verify that the CloudFormation stack name you specified is not longer than 128 characters:

    root@rok-tools:~/ops/deployments# [[ ${#EKS_ALB_ACM_CF} -le 128 ]] && echo OK || echo FAIL OK

    Troubleshooting

    The output of the command is FAIL

    Go back to step 4 and specify a shorter name. Ensure that the new name is not already in use.

  6. Generate the AWS CloudFormation stack:

    root@rok-tools:~/ops/deployments# j2 rok/eks/eks-alb-acm.yaml.j2 \ > -o rok/eks/eks-alb-acm.yaml

    Alternatively, download the eks-alb-acm CloudFormation template provided below and use it locally.

    eks-alb-acm.yaml.j2
    1AWSTemplateFormatVersion: "2010-09-09"
    2
    3Description: Amazon EKS - ACM Certificate
    4-20
    4
    5Metadata:
    6 Rok::StackName: {{EKS_ALB_ACM_CF}}
    7
    8Resources:
    9 Certificate:
    10 Type: AWS::CertificateManager::Certificate
    11 Properties:
    12 DomainName: {{EKS_ALB_ACM_SUBDOMAIN}}
    13 DomainValidationOptions:
    14 - DomainName: {{EKS_ALB_ACM_SUBDOMAIN}}
    15 HostedZoneId: {{EKS_ALB_ZONE_ID|replace("/hostedzone/", "")}}
    16 SubjectAlternativeNames:
    17 - "*.{{EKS_ALB_ACM_SUBDOMAIN}}"
    18 ValidationMethod: DNS
    19
    20Outputs:
    21 CertificateArn:
    22 Description: The ACM certificate
    23 Value: !Ref Certificate

    Note

    We request for a wildcard certificate so that we can expose multiple virtual hosts behind the same ALB.

  7. Commit your changes:

    root@rok-tools:~/ops/deployments# git commit -am "Create ACM Certificate"
  8. Deploy the CloudFormation stack:

    root@rok-tools:~/ops/deployments# aws cloudformation deploy \ > --stack-name ${EKS_ALB_ACM_CF?} \ > --template-file rok/eks/eks-alb-acm.yaml Waiting for changeset to be created.. Waiting for stack create/update to complete Successfully created/updated stack - rok-us-west-2-arrikto-cluster-acm

    Troubleshooting

    AccessDenied

    If the above command fails with an error message similar to the following:

    An error occurred (AccessDenied) when calling the DescribeStacks operation: User: arn:aws:iam::123456789012:user/user is not authorized to perform: cloudformation:DescribeStacks on resource: arn:aws:cloudformation:us-west-2:123456789012:stack/rok-us-west-2-arrikto-cluster-acm

    it means that your IAM user does not have sufficient permissions to perform an action necessary to deploy an AWS CloudFormation stack.

    To proceed, Check Your Environment and contact your AWS administrator to grant sufficient permissions to your IAM user or deploy the AWS CloudFormation stack for you.

    Failed to create/update the stack

    If the above command fails with an error message similar to the following:

    Failed to create/update the stack. Run the following command to fetch the list of events leading up to the failure aws cloudformation describe-stack-events --stack-name rok-us-west-2-arrikto-cluster-acm

    describe the events of the CloudFormation stack to identify the root cause of the failure:

    root@rok-tools:~/ops/deployments# aws cloudformation describe-stack-events --stack-name ${EKS_ALB_ACM_CF?}
    • A stack event like the following:

      { "StackId": "arn:aws:cloudformation:us-west-2:123456789012:stack/rok-us-west-2-arrikto-cluster-acm/415eef80-7b46-11eb-b047-06980f530fec", "EventId": "Certificate-CREATE_FAILED-2021-03-02T10:58:54.216Z", "StackName": "rok-us-west-2-arrikto-cluster-acm", "LogicalResourceId": "Certificate", "PhysicalResourceId": "", "ResourceType": "AWS::CertificateManager::Certificate", "Timestamp": "2021-03-02T10:58:54.216000+00:00", "ResourceStatus": "CREATE_FAILED", "ResourceStatusReason": "User: arn:aws:sts::123456789012:assumed-role/user/AWSCloudFormation is not authorized to perform: acm:RequestCertificate on resource: arn:aws:acm:us-west-2:123456789012:certificate/* (Service: AWSCertificateManager; Status Code: 400; Error Code: AccessDeniedException; Request ID: fb0ddfb6-299a-4887-9b67-d71b7e0a9dcc; Proxy: null)", "ResourceProperties": "{\"DomainValidationOptions\":[{\"DomainName\":\"arrikto-cluster.apps.example.com\",\"HostedZoneId\":\"/hostedzone/Z08893681AKMCJZ2MRWZ4\"}],\"DomainName\":\"arrikto-cluster.apps.example.com\",\"ValidationMethod\":\"DNS\",\"SubjectAlternativeNames\":[\"*.arrikto-cluster.apps.example.com\"]}" }

      means that your IAM user does not have sufficient permissions to create the resources that the AWS CloudFormation stack defines.

      To proceed, Check Your Environment and contact your AWS administrator to grant your IAM user sufficient permissions or deploy the AWS CloudFormation stack for you.

    ValidationError

    If the above command fails with an error message similar to the following:

    An error occurred (ValidationError) when calling the CreateChangeSet operation: Stack:arn:aws:cloudformation:us-west-2:123456789012:stack/rok-us-west-2-arrikto-cluster-acm/671606f0-eb2b-11eb-8afb-0217413c9ed2 is in ROLLBACK_COMPLETE state and can not be updated.

    delete the stack and deploy it again.

  9. Obtain the ARN of the ACM certificate:

    root@rok-tools:~/ops/deployments# export EKS_ALB_ACM_CERT=$(aws cloudformation describe-stacks \ > --stack-name ${EKS_ALB_ACM_CF?} \ > --query 'Stacks[].Outputs[?OutputKey==`CertificateArn`].OutputValue' \ > --output text) \ > && echo ${EKS_ALB_ACM_CERT?} arn:aws:acm:us-west-2:123456789012:certificate/4c7701a1-ad67-4757-b444-e1c5155fd5e9
  10. Save your state:

    root@rok-tools:~/ops/deployments# rok-j2 deploy/env.eks-alb-acm.j2 \ > -o deploy/env.eks-alb-acm
  11. Commit your changes:

    root@rok-tools:~/ops/deployments# git commit -am "Create ACM Certificate - context"
  12. Mark your progress:

    root@rok-tools:~/ops/deployments# export DATE=$(date -u "+%Y-%m-%dT%H.%M.%SZ")
    root@rok-tools:~/ops/deployments# git tag \ > -a deploy/${DATE?}/release-2.0/eks-alb-acm \ > -m "Create ACM Certificate"

Verify

  1. Go to your GitOps repository, inside your rok-tools management environment:

    root@rok-tools:~# cd ~/ops/deployments
  2. Restore the required context from previous sections:

    root@rok-tools:~/ops/deployments# source <(cat deploy/env.eks-alb-acm)
    root@rok-tools:~/ops/deployments# export EKS_ALB_ACM_SUBDOMAIN EKS_ALB_ACM_CERT
  3. Verify that the certificate exists:

    root@rok-tools:~/ops/deployments# aws acm describe-certificate \ > --certificate-arn ${EKS_ALB_ACM_CERT?} \ > --query Certificate.CertificateArn \ > --output text \ > && echo OK arn:aws:acm:us-west-2:123456789012:certificate/57da23e0-4964-4511-9082-a47d425e7c2a OK
  4. Verify that the status of the certificate is ISSUED:

    root@rok-tools:~/ops/deployments# aws acm describe-certificate \ > --certificate-arn ${EKS_ALB_ACM_CERT?} \ > --query Certificate.Status \ > --output text ISSUED

    Troubleshooting

    ‘PENDING_VALIDATION’

    If the output of the above command is PENDING_VALIDATION, then ACM has not yet validated the certificate. To proceed, validate your certificate, or create a new one by following the instructions in the Procedure.

    See also

  5. Verify that the domain that this certificate protects is the desired one:

    root@rok-tools:~/ops/deployments# aws acm describe-certificate \ > --certificate-arn ${EKS_ALB_ACM_CERT?} \ > --query "Certificate.DomainName=='${EKS_ALB_ACM_SUBDOMAIN?}'" true
  6. Verify that the wildcard domain is in the list of subject alternative names:

    root@rok-tools:~/ops/deployments# # aws acm describe-certificate \ > --certificate-arn ${EKS_ALB_ACM_CERT?} \ > --query "contains(Certificate.SubjectAlternativeNames, '*.${EKS_ALB_ACM_SUBDOMAIN?}')" true

Summary

You have successfully created an ACM certificate for your subdomain.

What’s Next

The next step is to deploy cert-manager since this is required by AWS Load Balancer Controller.