How can I configure HTTPS for my Elastic Beanstalk environment?

Last updated: 2019-10-17

How can I configure HTTPS for my AWS Elastic Beanstalk environment so that I can encrypt data from my load balancer to my Amazon Elastic Compute Cloud (Amazon EC2) instance?

Short Description

If you purchased and configured a custom domain name for your Elastic Beanstalk environment, you can use HTTPS to allow users to connect to your website securely. If you don't own a domain name, you can still use HTTPS with a self-signed certificate for development and testing purposes.

The AWS Certificate Manager (ACM) is the preferred tool for provisioning, managing, and deploying your server certificates programmatically. You can also use the AWS Command Line Interface (AWS CLI). If ACM isn't available in your AWS Region, you can upload a third-party or self-signed certificate and private key to AWS Identity and Access Management (IAM) using the AWS CLI.

Resolution

Prepare your Elastic Beanstalk environment

1.    Register a new domain using Amazon Route 53, or another domain provider, to route traffic to your Elastic Beanstalk environment.

2.    Create an alias name if your environment's URL includes an AWS Region, or create a CNAME record if your environment's URL doesn't include an AWS Region.

Important: You can use CNAME records for environments created before early 2016. You can't use a CNAME record with a zone apex domain (also known as a root domain or naked domain). For more information, see Choosing Between Alias and Non-Alias Records.

3.    Create a certificate in ACM, or upload a third-party or self-signed certificate and private key to IAM.

Terminate HTTPS on the load balancer

1.    Open the Elastic Beanstalk console, and then select your environment.

2.    In the navigation pane, choose Configuration.

3.    In the Load balancer category, choose Modify.

4.    To add the listener for port 443, choose one of the following sets of steps based on the type of load balancer that your Elastic Beanstalk environment has.

To add a listener for a Classic Load Balancer:

1.    Choose Add Listener.

2.    For Port, enter the incoming traffic port (typically 443).

3.    For Protocol, choose HTTPS.

4.    For Instance Port, enter 80.

5.    For Instance Protocol, choose HTTP.

6.    For SSL certificate, choose your certificate, and then choose the SSL policy that you want to use from the drop-down menu.

7.    Choose Add, and then choose Apply.

To add a listener for an Application Load Balancer:

1.    Choose Add Listener.

2.    For Port, enter the incoming traffic port (typically 443).

3.    For Protocol, choose HTTPS.

4.    For SSL certificate, choose your certificate, and then choose the SSL policy that you want to use from the drop-down menu.

5.    Choose Add, and then choose Apply.

To add a listener for a Network Load Balancer:

1.    Choose Add Listener.

2.    For Port, enter the incoming traffic port (typically 443).

3.    Choose Add, and then choose Apply.

Terminate HTTPs on the instance (end-to-end HTTPS) in a load balanced environment

To configure your instances to terminate HTTPS connections, you must use configuration files to modify the software running on the instances, and to modify security groups to allow secure connections.

Important: If you're using a single-instance environment, skip the following steps, and complete the steps in the Terminate HTTPs on the instance (end-to-end HTTPS) in a single-instance environment section.

1.    Add a secure listener to your load balancer by using one of the following configuration files, based on the type of load balancer that your Elastic Beanstalk environment has.

For a Classic Load Balancer, use a .ebextensions/https-reencrypt-clb.config file:

option_settings:
  aws:elb:listener:443:
    InstancePort: 443
    InstanceProtocol: HTTPS
  aws:elasticbeanstalk:application:
    Application Healthcheck URL: HTTPS:443/

For an Application Load Balancer, use a .ebextensions/https-reencrypt-alb.config file:

option_settings:
  aws:elbv2:listener:443:
    DefaultProcess: https
    ListenerEnabled: 'true'
    Protocol: HTTPS
  aws:elasticbeanstalk:environment:process:https:
    Port: '443'
    Protocol: HTTPS

For a Network Load Balancer, use a .ebextensions/https-reencrypt-nlb.config file:

option_settings:
  aws:elbv2:listener:443:
    DefaultProcess: https
    ListenerEnabled: 'true'
  aws:elasticbeanstalk:environment:process:https:
    Port: '443'

2.    Update the load balancer to receive traffic on port 443.

You can create a new security group, and then have Elastic Beanstalk use that security group to receive traffic on port 443. For example, the following .ebextensions/https-lbsecuritygroup.config file creates a security group and attaches that security group to the load balancer.

option_settings:
  # Use the custom security group for the load balancer
  aws:elb:loadbalancer:
    SecurityGroups: '`{ "Ref" : "loadbalancersg" }`'
    ManagedSecurityGroup: '`{ "Ref" : "loadbalancersg" }`'
Resources:
  loadbalancersg:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: load balancer security group
      VpcId: vpc-#######
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 443
          ToPort: 443
          CidrIp: 0.0.0.0/0
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: 0.0.0.0/0
      SecurityGroupEgress:
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: 0.0.0.0/0

In the preceding configuration file, replace VpcId with the correct value for your environment.

Note: The preceding example includes ingress and egress over port 80 to allow HTTP connections. To allow only secure connections, remove the configuration for port 80 in the SecurityGroupIngress section.

3.    Add ingress and egress rules that allow communication over port 443 between the load balancer's security group and the security group of the instances.

For example, you can use the following .ebextensions/https-backendsecurity.config file:

Resources:
  # Add 443-inbound to instance security group (AWSEBSecurityGroup)
  httpsFromLoadBalancerSG: 
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: {"Fn::GetAtt" : ["AWSEBSecurityGroup", "GroupId"]}
      IpProtocol: tcp
      ToPort: 443
      FromPort: 443
      SourceSecurityGroupId: {"Fn::GetAtt" : ["loadbalancersg", "GroupId"]}
  # Add 443-outbound to load balancer security group (loadbalancersg)
  httpsToBackendInstances: 
    Type: AWS::EC2::SecurityGroupEgress
    Properties:
      GroupId: {"Fn::GetAtt" : ["loadbalancersg", "GroupId"]}
      IpProtocol: tcp
      ToPort: 443
      FromPort: 443
      DestinationSecurityGroupId: {"Fn::GetAtt" : ["AWSEBSecurityGroup", "GroupId"]}

Now, the load balancer connects to your backend instances securely using HTTPS. The load balancer accepts any certificate from the instance, whether or not the certificate is self-signed or issued by a trusted certificate authority.

Note: You can add policies to the load balancer that tell it to trust only a specific certificate. For example, the following .ebextensions/https-backendauth.config file creates two policies. One policy specifies a public certificate, and the other policy tells the load balancer to only trust that certificate for connections to instance port 443.

option_settings:
  # Backend Encryption Policy
  aws:elb:policies:backendencryption:
    PublicKeyPolicyNames: backendkey
    InstancePorts:  443
  # Public Key Policy
  aws:elb:policies:backendkey:
    PublicKey: |
      -----BEGIN CERTIFICATE-----
      ################################################################
      ################################################################
      ################################################################
      ################################################################
      ################################################
      -----END CERTIFICATE-----

In the preceding configuration file, update the contents of your EC2 instance's public certificate between -----BEGIN CERTIFICATE----- and -----END CERTIFICATE-----.

4.    Configure the proxy server that runs on the instance to terminate HTTPS.

Note: The configuration varies depending on your solution stack.

5.    To deploy configuration files to your environment, add the configuration files to a directory named .ebextensions at the root of your application bundle. Then, deploy the source code that includes these configuration files.

Terminate HTTPs on the instance (end-to-end HTTPS) in a single-instance environment

1.    Allow incoming traffic on port 443 to the EC2 instance that your Elastic Beanstalk application is running on.

The following example uses .ebextensions to allow incoming traffic on port 443:

Resources:
  sslSecurityGroupIngress: 
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: {"Fn::GetAtt" : ["AWSEBSecurityGroup", "GroupId"]}
      IpProtocol: tcp
      ToPort: 443
      FromPort: 443
      CidrIp: 0.0.0.0/0

2.    Configure the proxy server that runs on the instance to terminate HTTPS.

Note: The configuration varies depending on your solution stack.

3.    To deploy configuration files to your environment, add the configuration files to a directory named .ebextensions at the root of your application bundle. Then, deploy the source code that includes these configuration files.


Did this article help you?

Anything we could improve?


Need more help?