DEV Community

Kamil Kujawiński
Kamil Kujawiński

Posted on

Using Cloudflare SSL with Elastic Beanstalk instances

Motivation:

To obtain a free SSL certificate (by Let's Encrypt) for your web application without the hassle of renewing it every three months, consider the following approach.

The simplest solution is to use a Load Balancer and attach an SSL certificate from AWS Certificate Manager (ACM) to it. However, relying on a Load Balancer solely for HTTPS may be costly. To address this, I’ve outlined a much more affordable alternative that requires a bit of configuration.

Additionally, in this post, I explain how to configure SSL for an Elastic Beanstalk instance, as I found the existing documentation and available resources to be somewhat outdated.


Keyword of the solution is Cloudflare.

Cloudflare offers a proxy feature that enables you to set up a free SSL certificate while securely proxying traffic to your host.

In Flexible mode, the communication between Cloudflare and AWS is not encrypted. If you prefer end-to-end encryption, you can opt for Full mode instead.

Steps

1. Add your domain to Cloudflare.

  • In the DNS settings, configure your domain as proxied.
  • In the SSL/TLS settings, select Full (strict) mode for end-to-end encryption.

2. Generate an Origin Certificate in Cloudflare

  • Go to the SSL/TLS > Origin Server section in Cloudflare.
  • Generate a certificate valid for up to 15 years.
  • Use this certificate to configure SSL in AWS Elastic Beanstalk.

3. Store Certificates in AWS Secrets Manager:

  • Save the server.crt and server.key files as secrets in AWS Secrets Manager.
  • Use the following secret names: /app/ssl/server-crt and /app/ssl/server-key

4. Grant IAM Role Access to Secrets:

  • In AWS IAM add a new policy named ReadSSLSecretKeys for the role aws-elasticbeanstalk-ec2-role with the following permissions:
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "ssm:GetParameter",
      "Resource": "arn:aws:ssm:region:account_id:parameter/app/ssl/server-crt"
    },
    {
      "Effect": "Allow",
      "Action": "ssm:GetParameter",
      "Resource": "arn:aws:ssm:region:account_id:parameter/app/ssl/server-key"
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

5. Configure your Elastic Beanstalk deployment to listen on port 443 and use the Origin Certificate generated in Cloudflare (stored in AWS Secrets Manager) do changes in the following files:

  • .ebextensions/01_https-instance-securitygroup.config
Resources:
  sslSecurityGroupIngress:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: {"Fn::GetAtt" : ["AWSEBSecurityGroup", "GroupId"]}
      IpProtocol: tcp
      ToPort: 443
      FromPort: 443
      CidrIp: 0.0.0.0/0
Enter fullscreen mode Exit fullscreen mode
  • .ebextensions/02_https-instance.config
files:
  /etc/pki/tls/certs/server.crt:
    mode: "000400"
    owner: root
    group: root
    content: |
      -----BEGIN CERTIFICATE-----
      certificate file contents
      -----END CERTIFICATE-----

  /etc/pki/tls/certs/server.key:
    mode: "000400"
    owner: root
    group: root
    content: |
      -----BEGIN RSA PRIVATE KEY-----
      private key contents # See note below.
      -----END RSA PRIVATE KEY-----

container_commands:
  01_fetch_server_crt:
    command: |
      aws ssm get-parameter --name "/app/ssl/server-crt" --with-decryption --query "Parameter.Value" --output text > /etc/pki/tls/certs/server.crt
  02_fetch_server_key:
    command: |
      aws ssm get-parameter --name "/app/ssl/server-key" --with-decryption --query "Parameter.Value" --output text > /etc/pki/tls/certs/server.key

Enter fullscreen mode Exit fullscreen mode
  • .platform/nginx/conf.d/https.conf
server {
    listen 443 ssl;

    ssl_certificate /etc/pki/tls/certs/server.crt;
    ssl_certificate_key /etc/pki/tls/certs/server.key;

    ssl_session_timeout 5m;

    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on;

    location / {
      proxy_pass http://127.0.0.1:8000;
      proxy_http_version 1.1;

      proxy_set_header Connection "";
      proxy_set_header Host $host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Forwarded-Proto https;
    }
}
Enter fullscreen mode Exit fullscreen mode

Image of Docusign

Bring your solution into Docusign. Reach over 1.6M customers.

Docusign is now extensible. Overcome challenges with disconnected products and inaccessible data by bringing your solutions into Docusign and publishing to 1.6M customers in the App Center.

Learn more

Top comments (0)

AWS Security LIVE!

Tune in for AWS Security LIVE!

Join AWS Security LIVE! for expert insights and actionable tips to protect your organization and keep security teams prepared.

Learn More

👋 Kindness is contagious

Immerse yourself in a wealth of knowledge with this piece, supported by the inclusive DEV Community—every developer, no matter where they are in their journey, is invited to contribute to our collective wisdom.

A simple “thank you” goes a long way—express your gratitude below in the comments!

Gathering insights enriches our journey on DEV and fortifies our community ties. Did you find this article valuable? Taking a moment to thank the author can have a significant impact.

Okay