Skip to content

Ercan Ermis

notes for everyone

Menu
  • AWS
  • Kubernetes
  • Linux
  • DevOps
  • Docker
  • GCP
  • Uncategorized
  • Contact Me
Menu

Automate Let’s Encrypt SSL on AWS Application Load Balancer

Posted on July 2, 2022July 2, 2022 by Ercan
Share this...
Tweet about this on Twitter
Twitter
Share on LinkedIn
Linkedin
Share on Reddit
Reddit
Email this to someone
email
Share on StumbleUpon
StumbleUpon
Share on Facebook
Facebook

Most of the time, we don’t need anything except AWS Certificate Manager (ACM) but in some cases, if you are hosting your customer’s domain with ALB and you don’t have a chance to get an SSL certificate from your customer, you should do some workaround. In this article, we will issue a Let’s Encrypt SSL on AWS Application Load Balancer and automatize it!

When you request an SSL certificate from Let’s Encrypt, the LE has some verification methods such as web-challenge, route53, etc. In this scenario, I decided to use web-challenge because domains’ DNS management is not on me. I just host the application and need to issue an SSL.

When you request an SSL with web-challenge, the Let’s Encrypt is checking the https://domain.com/.well-known/acme-challenge path to make sure and verify. What does it mean? It means, that Let’s Encrypt will send a request to the domain with port 80 and make verification. Hmm, we need do some adjusting on our Load Balancer config and need another Target Group for redirect the acme-challenge requests specifically.

Step 1: Run a new EC2 and Create a New Target Group

Clone The Repository

I wrote a bash script for easy management and keep the standards in the same way for every domain. You can check out my GitHub repository or clone the repository under the /opt/ path into acme-challange-server

Tip: # git clone https://github.com/flightlesstux/alble.git

Install nginx, Let’s Encrypt and configure them

When we get a /.well-known/acme-challenge/* request, the nginx installed EC2 will handle all acme-challenge requests and issue an SSL for us.

Install nginx and configure for /.well-known/acme-challenge/

You can easily install nginx with amazon-linux-extras install nginx1 command. After the installation, you should put a new location block on the nginx roof config. The root config file is located in /etc/nginx/nginx.conf

        location /.well-known/acme-challenge {
           root /opt/alble/certbot-challange;
        }

server_name value should be _; for all domains. We can’t set a static DNS name.

Install Certbot with the nginx module

First of all, we will install certbot from epel repository and we need to install epel first. For epel installation, you can use amazon-linux-extras install -y epel command and after just run yum install -y nginx certbot python2-certbot-nginx jq dig command to cover pre-requisites.

IAM Role Policy for acme-challenge Server

This acme-challenge the server has an IAM Role for accessing ACM and ALB operations with Let’s Encrypt SSLs. You can see the IAM Policy below.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AWSLEPolicy1",
            "Effect": "Allow",
            "Action": [
                "acm:DescribeCertificate",
                "acm:RemoveTagsFromCertificate",
                "acm:GetCertificate",
                "acm:AddTagsToCertificate",
                "acm:ListCertificates",
                "acm:ImportCertificate",
                "acm:ListTagsForCertificate"
            ],
            "Resource": "*",
            "Condition": {
                "IpAddress": {
                    "aws:SourceIp": "acme-challenge-server-Elastic-IP/32"
                }
            }
        },
        {
            "Sid": "AWSLEPolicy2",
            "Effect": "Allow",
            "Action": [
                "elasticloadbalancing:RemoveTags",
                "elasticloadbalancing:DescribeTags",
                "elasticloadbalancing:AddTags",
                "elasticloadbalancing:AddListenerCertificates"
            ],
            "Resource": "AWS::ALB::ARN",
            "Condition": {
                "IpAddress": {
                    "aws:SourceIp": "acme-challenge-server-Elastic-IP/32"
                }
            }
        },
        {
            "Sid": "AWSLEPolicy3",
            "Effect": "Allow",
            "Action": [
                "elasticloadbalancing:DescribeSSLPolicies",
                "elasticloadbalancing:DescribeListeners",
                "elasticloadbalancing:DescribeListenerCertificates"
            ],
            "Resource": "*",
            "Condition": {
                "IpAddress": {
                    "aws:SourceIp": "acme-challenge-server-Elastic-IP/32"
                }
            }
        },
        {
            "Sid": "AWSLEPolicy4",
            "Effect": "Allow",
            "Action": [
                "elasticloadbalancing:RemoveTags",
                "elasticloadbalancing:DescribeTags",
                "elasticloadbalancing:AddTags"
            ],
            "Resource": "AWS::ALB::ARN",
            "Condition": {
                "IpAddress": {
                    "aws:SourceIp": "acme-challenge-server-Elastic-IP/32"
                }
            }
        },
        {
            "Sid": "AWSLEPolicy5",
            "Effect": "Allow",
            "Action": [
                "elasticloadbalancing:DescribeSSLPolicies",
                "elasticloadbalancing:DescribeListeners",
                "elasticloadbalancing:AddListenerCertificates",
                "elasticloadbalancing:DescribeListenerCertificates"
            ],
            "Resource": "*",
            "Condition": {
                "IpAddress": {
                    "aws:SourceIp": "acme-challenge-server-Elastic-IP/32"
                }
            }
        }
    ]
}

You can attach this policy directly to the acme-challenge server without any security issue and leak after assigning an Elastic IP to it. If you want to use local credentials, you can also use the same IAM Policy.

Create a New Target Group

After EC2 instance configuration, I created a Target Group which name is acme-challenge and I redirect the request to the nginx installed EC2 which name is acme-challange-server and I register ours acme-challenge-server as a target. If everything goes without any problem, your screen will look like this below.

Step 2: Create an Application Load Balancer Listener Rule

We need to edit and create a new listener rule to accept and redirect the /.well-known/acme-challenge/* requests to the acme-challenge Target Group. When you did this step, you screen will look like this below.

Now, we are ready to request a Let’s Encrypt SSL from ACME and issue without any problem and import to ACM and assign to AWS ALB : ) This operation contains three different steps for issuing.

  1. Request an SSL from Let’s Encrypt
  2. Import requested SSL if domain or subdomain matched with AWS ALB CNAME record
  3. Assign the imported SSL certificate to the AWS ALB for use in production

Let’s Issue and Request a Let’s Encrypt SSL from ACME

When you clone the git repository, you should move /opt/alble/renewal-hooks the folder to under /etc/letsencrypt/ path. Otherwise, you can’t renew the certificate on the ACM and your and your customers’ security be failed. You can copy and paste mv /opt/alble/renewal-hooks /etc/letsencrypt/

Just read the README.md file on the git repository and write your variables to the env file. After that, you can easily run/manage/create the Let’s Encrypt SSL certificates on AWS Application Load Balancer. I recommend an AWS SSM to run the command to acme-challange-server for issue an SSL. For this, you should add AmazonEC2RoleforSSM the policy to your IAM Role.

I decided to use a subdomain for testing but it doesn’t matter. You can also use a root domain. My test domains are awsle-1.ercanermis.com and awsle-2.ercanermis.com

When you are in /opt/alble/ path, you can run the command like ./create-new-site.sh awsle-1.ercanermis.com and you will see the output like below.

My ALBLe script is checking the CNAME record first for the domain and/or subdomain and making sure before continuing. If you write a wrong domain/subdomain or made a typo, it will warn you via Slack alerts. Alerts are really important to the automation things. You can set Slack Alerts on env file. Here is the example of if you issue the Let’s Encrypt SSL before;

Production

My AWS ALB DNS name is web-application-elb-1302305711.us-east-1.elb.amazonaws.com and I can access it via https://web-app.ercanermis.com It’s using AWS Certificate Manager to get an SSL.

My test domains are https://awsle-1.ercanermis.com and https://awsle-2.ercanermis.com and they are using Let’s Encrypt with AWS Application Load Balancer, yeah! : )

https://web-app.ercanermis.com is using Amazon provided SSL
https://awsle-1.ercanermis.com is using Let’s Encrypt provided SSL
https://awsle-2.ercanermis.com is using Let’s Encrypt provided SSL

How AWS ALB SSL Certificates and ACM look like?

Here is the screenshot of ALB SSL Certificates
Here is the screenshot in Amazon Certificate Manager

I hope, this article will help you! P.S. Don’t forget to set a cron for renewal requests.
Source code: https://github.com/flightlesstux/alble/

Share on Social Media
twitter facebook linkedin reddit
Share this...
Tweet about this on Twitter
Twitter
Share on LinkedIn
Linkedin
Share on Reddit
Reddit
Email this to someone
email
Share on StumbleUpon
StumbleUpon
Share on Facebook
Facebook

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Recent Posts

  • Scaling PHP Applications on AWS
  • Create an S3 Bucket and Set a Policy via CLI
  • Issue a Let’s Encrypt SSL with the AWS Route53
  • Automate Let’s Encrypt SSL on AWS Application Load Balancer
  • Let’s Learn Kubernetes – Part 3
  • Deploy a website to S3 and CloudFront with Bitbucket Pipelines
  • Let’s Learn Kubernetes – Part 2
  • Protect your AWS Account with specified IPs
  • Let’s Learn Kubernetes – Part 1
  • Differences between AWS CLI v1 and v2
  • SSL CA Problem on CentOS7 Docker and Solution
  • What do I have?
  • Deploy HA nginx to AWS ECS with Geolocation Routing via Terraform
  • Deploy nginx docker to AWS ECS with Terraform Automation
  • How to Install Node Exporter on Linux Server
  • FortiClient Problem on M1 MacBookPro Problem Solution
  • Connect your AWS to GCP with Terraform via IPSec Site-to-Site VPN
  • Google Cloud Platform Automation with Terraform Easily
  • How to secure your Amazon Web Services account
  • Install UGREEN USB Ethernet Adapter on macOS
  • Redirect 301 HTTPS on App Engine with nginx on Google Cloud Platform
  • Set two different Target Groups on AWS Load Balancer with Terraform
  • Extend your ec2 Linux disk without reboot on Amazon Web Services
  • Create a New Grant User on AWS RDS (MariaDB)
  • Amazon S3 CORS Settings with CloudFront on Amazon Web Services
  • Take your GitLab backup everyday if it works in Docker
  • Find large files in CentOS, ubuntu and MacOS easily
  • Fix “Error: rpmdb open failed” on CentOS or Amazon Linux 2
  • Error: No space left on the device when starting/stopping services only
  • Juniper SRX110H-VA VDSL2 Configuration Step by Step
  • Enable Logrotation for Docker Containers
  • Download specific file extension via wget easily on terminal
  • Find the exact size of certain files in Linux via terminal
  • Disable SELinux on CentOS 7 or CentOS 8
  • Hello Blog!

Tag Cloud

active-active amazon linux 2 amazon web services automation aws basics bucket policy bug centos centos7 cloud cloudfront container container management curl deployment devops docker ec2 ecs fargate file size gcp gitlab google cloud platform internet k8s kubernetes kubernetes architecture kubernetes basics linux macos monitoring node exporter pipeline prometheus reliability router s3 security terraform ubuntu verification method wget yum

Archive

  • August 2022 (1)
  • July 2022 (3)
  • June 2022 (6)
  • March 2022 (1)
  • July 2021 (1)
  • May 2021 (5)
  • April 2021 (5)
  • February 2021 (1)
  • January 2021 (1)
  • September 2020 (2)
  • July 2020 (1)
  • April 2020 (1)
  • March 2020 (1)
  • February 2020 (1)
  • November 2019 (5)
©2022 Ercan Ermis | Built using WordPress and Responsive Blogily theme by Superb