Containers
Securing HAQM Elastic Container Service applications using Application Load Balancer and HAQM Cognito
Introduction
Designing and maintaining secure user management, authentication and other related features for applications is not an easy task. HAQM Cognito takes care of this work, which allows developers to focus on building the core business logic of the application.
HAQM Cognito provides user management, authentication, and authorization for applications where users can log in in directly or through their pre-existing social or corporate credentials.
HAQM Elastic Containers Service (HAQM ECS) is a fully managed container orchestration service that makes it easy for customers to deploy, manage, and scale their container-based applications. When building using HAQM ECS, it is common to use Application Load Balancer (ALB) for application high availability and other features like SSL/TLS offloading, host based routing, and other application-aware traffic handling.
Another benefit of using the ALB with HAQM ECS is that the ALB has in-built support for HAQM Cognito.
When setting up the ALB, you can chose if you want incoming user traffic to be redirected to HAQM Cognito for authentication. By building secure containerized applications using HAQM ECS, and using ALB and its HAQM Cognito integration, you get the benefits of the ease of container orchestration and user authentication and authorization.
Flow of how Application Load Balancer authenticates users using HAQM Cognito
For an application fronted by ALB that integrates with HAQM Cognito and has been set up to authenticate users, the following stepwise flow describes what happens when a user attempts to access the application.
For more information, see the example built by the AWS Elastic Load Balancing Demos.
You need to understand what the ALB is doing to secure user access with HAQM Cognito:
- A user sends a request to the application fronted by the ALB, which has a set of rules that it evaluates for all traffic to determine what action to carry out. The rule (such as the path-based rule saying all traffic for/
login
) when matched triggers the authentication action on the ALB. The ALB then inspects the user’s HTTP payload for an authentication cookie. - Because this is the user’s first visit, this cookie isn’t present. The ALB doesn’t see any cookie and redirects the user to the configured HAQM Cognito’s authorization endpoint.
- The user is presented with an authentication page from HAQM Cognito, where the user inputs their credentials. HAQM Cognito redirects the user back to the ALB and passes an authorization code to the user in the redirect URL.
- The load balancer takes this authorization code and makes a request to HAQM Cognito’s token endpoint.
- HAQM Cognito validates the authorization code and presents the ALB with an ID and access token.
- The ALB forwards the access token to HAQM Cognito’s user info endpoint.
- HAQM Cognito’s user information endpoint presents the ALB with user claims.
- The ALB redirects the user who is trying to access the application (step 1) to the same URL while inserting the authentication cookie in the redirect response.
- The user makes the request to the ALB with the cookie and the ALB validates it and forwards the request to the ALB’s target. The ALB inserts information (such as user claims, access token, and the subject field) into a set of
X-AMZN-OIDC-*
HTTP headers to the target. - The target generates a response and forwards to the ALB.
- The ALB sends the response to the authenticated user.
When the user makes subsequent requests for HTTP request and response, the flow will go through steps 9–11. If the user makes a new request without the authentication cookie, it goes through steps 1–11.
For more information, see the authentication flow between the ALB and HAQM Cognito.
Solution overview
You will use a PHP application built for demonstration purpose. The application is published and verified in the public docker hub. We use and configure HAQM Route 53 for Domain Name Service (DNS) handling and AWS Certificate Manager (ACM) to provision Transport Layer Security (TLS) Certificates for usage.
HAQM Cognito handles the Authentication flows and HAQM ECS handles the container scheduling and orchestration.
The following solution architecture diagram presents an overview of the solution.
Prerequisites
To complete this tutorial you need the following tools, which can be installed with the links:
- aws cliv2: The AWS Command Line Interface (AWS CLI) is an open source tool that allows you interact with AWS services using commands in your command-line shell.
- ecs-cli: The HAQM Elastic Container Service (HAQM ECS) CLI provides high-level commands to simplify creating, updating, and monitoring tasks and clusters from a local development environment.
Environment
In this post, I used the AWS Cloud9 as an Integrated Development Environment (IDE) to configure the settings in this tutorial. You can use AWS Cloud9 or your own IDE. The commands used were tested using HAQM Linux 2 running in the HAQM Cloud9 environment.
Follow the steps linked to install and configure HAQM Cloud9:
Create a workspace to deploy this solution, which includes creating an AWS Identity and Access Management (IAM) role that will be attached to the workspace instance.
Launch the base infrastructure platform that the resources reside in
The HAQM ECS needs to be launched into a Virtual Private Cloud (VPC) infrastructure. To create this infrastructure, you use an AWS CloudFormation template that automates the creation of the platform.
Download the zip file that contains an AWS CloudFormation yaml file: codebuild-vpc-cfn.yaml
.
Once deployed, the following resources are created into your AWS account: a Virtual Private Cloud (VPC), an internet gateway, two public subnets, two private subnets, two Network Address Translation (NAT) Gateways, and one security group.
To launch the stack, follow these steps:
- Sign in to the AWS Management Console.
- In your Region of choice, you will see the Region list in the top right-hand corner.
- Search for the AWS CloudFormation service in the Console search bar.
- Choose Create Stack and select with new resources (standard).
- To specify template, choose upload a template file.
- Upload the previously downloaded:
codebuild-vpc-cfn.yaml
file. - To create the stack and configure stack options, choose Next.
- Enter ecsplatform for stack name and ecsplatform for
EnvironmentName
. Choose Next. - Leave the rest of the default settings and choose Next.
- Choose Create Stack.
- When CloudFormation has completed its deployment its the resources, the status is CREATE_COMPLETE.
Next on your HAQM Cloud9 workspace terminal, set the below environment variables:
You will set additional variables later, but these are enough to begin building your solution.
Configure the security group rules needed for web traffic access
When users access the ALB, the security group attached to it needs to allow ingress port 443 (https) traffic. In addition, when the ALB forwards the web traffic to the HAQM ECS tasks there needs to be a ingress rules attached to the HAQM ECS container instances that allows ingress port 80 (http) traffic.
You can achieve this access with the following:
Create a public Application Load Balancer
As described earlier, the ALB will receive and terminate all client requests to validate for authentication using HAQM Cognito. The ALB also handles TLS offloading where the TLS certificates for the domain name will be deployed on it.
To create the ALB do the below:
Configure a Domain Name System
Clients will need a domain name that points to the ALB to type into their browsers.
In this post, the Domain Name System (DNS) name is registered using the DNS Resolution service, HAQM Route 53.
You can configure your domain name (such as www.example.com) where it‘s known as the record and placed in a Route 53-hosted zone.
Configure both the Route 53 hosted zone and record
If you already have a Route53
publicly hosted zone for the apex domain and this is the location where you plan to add the record, then you will set its host zone ID (AUTH_ECS_R53HZ
). For more information, see the hosted zone ID documentation.
The first command line shown below demonstrates how to identify a hosted zone ID. You can substitute example.com for your apex domain name. The other commands create a record that points to the ALB.
Request a public certificate
To ensure that web traffic sent by clients to the ALB is encrypted, integrate an ACM (AWS Certificate Manager) Certificate into the ALB’s listener. This ensures that the ALB serves HTTPS traffic and communications from clients to ALB is encrypted. Public SSL/TLS certificates provisioned through AWS Certificate Manager are free. You pay only for the AWS resources you create to run your application.
Provision an ACM certificate
When you create an SSL/TLS Certificate using ACM, it will try to confirm that you’re the owner of the domain name before fully provisioning the certificate for you to use. One method of confirmation is through DNS validation.
Through this method ACM creates two CNAME records that you must add in your Route53
hosted zone.
To add the ACM CNAME records in your Route53
hosted zones:
It takes some time before the certificate will change from ‘Pending Validation’ to ‘Success’.
Once the status shows ‘Issued’ on the ACM console then you can use the certificate.
Create an HTTPS listener and listener rule on the ALB
Now that you’ve created the ALB. In addition, you’ve also created a certificate to configure the HTTPS listener to accept incoming HTTPS request from clients and to terminate them.
You integrate the certificate into the listener and add a default rule action on the ALB:
Create an HAQM Cognito user pool
As previously described, HAQM Cognito provides user management, authentication and authorization for applications where users can login in directly or through their pre-existing social/corporate credentials.
Create a user pool, which is a user directory in HAQM Cognito that helps clients to access the website. Clients sign in with their credentials before they get access to the site.
To fully configure HAQM Cognito for integration with the ALB, create a user pool, a user pool application client, and a user pool domain. The following steps show you how to accomplish these tasks.
Create an HAQM Cognito user pool
Create an HAQM Cognito user pool application client
Create an HAQM Cognito user pool domain
Create and configure a target group for the ALB
Create a target group for the ALB. The target group is used to route requests to the HAQM ECS tasks.
When an ALB receives the HTTPS traffic from the web clients, it routes the requests to the target group (after authentication of the client has occurred) for a web response. (HAQM ECS tasks are registered to the target group in a later section “Configuring the ECS Service”).
Create an empty target group:
Host-based routing and an authentication rule on the ALB
The ALB routes requests based on the host name in the HTTP host header.
It is possible to configure multiple domains that all point to a single ALB because the ALB can route requests based on the incoming host header and forward the requests to the right target group for handling.
You can configure an authentication rule which tells the ALB what to do to the incoming requests. In this post, we want the requests to first be authenticated and, if successful, the request should get forwarded to the target group we created earlier.
Configure host-based routing and an authentication rule on the ALB
HAQM ECS configuration
The ALB and HAQM Cognito are now configured for processing incoming requests and authentication.
Next you will configure HAQM ECS to orchestrate and deploy running tasks to generate response for the client’s web request.
An HAQM ECS cluster is a logical grouping of tasks or services. HAQM ECS instances are part of the HAQM ECS infrastructure registered to a cluster that the HAQM ECS tasks run on.
Two t3.small
HAQM ECS instances will be configured to run the tasks. HAQM ECS will run and maintain two tasks, which are configured based on parameters and settings contained in the task definition (a JSON
text file).
For more information on HAQM ECS basics, constructs, and orchestration read the HAQM ECS components documentation.
Configure the HAQM ECS CLI
HAQM ECS CLI is the tool that you’d use to configure and launch the HAQM ECS components.
To download HAQM ECS CLI, follow the following steps:
HAQM ECS CLI needs a CLI profile, to proceed generate an access key ID, and access key using the AWS credentials documentation.
Set the $AWS_ACCESS_KEY_ID
and $AWS_SECRET_ACCESS_KEY
variables to the copied values generated by AWS IAM.
Configure the HAQM ECS CLI for a CLI profile
Create the HAQM ECS cluster
Create the HAQM ECS cluster, which consists of two t3.small
instance types deployed in the VPC and residing in the two private subnets from earlier. For the instance-role, use the AWS IAM role created when configuring the AWS Cloud9 environment workspace (ecsworkshop-admin
).
The first command creates a keypair and the second command configures the HAQM ECS cluster. The keypair is useful if you need to SSH into the HAQM ECS instances for troubleshooting.
Configure the HAQM EC2 key pair and bring up the ECS cluster
The cluster creation will take some time, when fully deployed the AWS CloudFormation stack status will output ‘Cluster creation succeeded’.
Configure the AWS Region and ECS cluster name using the configure command:
The EC2
launch type, with HAQM ECS instances, is created and launched in your VPC. If you prefer not to manage the underlying instances hosting the tasks, then Fargate
launch type is the option to use. Fargate is the serverless way to host your HAQM ECS workloads.
Create the ECS service
The ecs-cli compose service
up command will create the HAQM ECS service and tasks from a Docker Compose file (ecsauth-compose.yaml
) that you create. This service is configured to use the ALB that you created earlier. A task definition is created by the command.
The Docker Compose file contains the configuration settings that the HAQM ECS service is spun up with. This includes the Docker image to pull and use, the ports to expose on the HAQM ECS instance, and the HAQM ECS task for network forwarding. In this post, we configured it to use the AWS published sample demo PHP application verified and published to Docker Hub. Also, the Transmission Control Protocol (TCP) port 80
will be opened on the HAQM ECS instance and traffic received on this port will be forwarded to the task on TCP port 80
).
Configuring the ECS service
Testing the solution end to end
We now the have working components of the solution. To test the solution end to end, you can navigate to the https site of the domain name used in your browser (such as http://www.example.com).
The sequence of events that follows is as we described in the flow of how the ALB authenticates users using HAQM Cognito (section “Flow of how Application Load Balancer authenticates users using HAQM Cognito”).
After redirection by the ALB to the HAQM Cognito configured domain’s login page (a hosted UI by HAQM Cognito), enter input your credentials.
Since this is the first time the page is accessed we will sign up as a new user. HAQM Cognito stores this information in the user pool. If you navigate to the HAQM Cognito user pool console after, you’ll see this new user.
After signing in to the ALB, it redirects you to the landing page of the sample demonstration PHP application, which is shown in the diagram below.
User claims encoding and security
In this post, we configured the target group to use HTTP, because the ALB has handled the TLS offloading. However, for enhanced security, you should restrict the traffic getting to the HAQM ECS instances to only the load balancer using the security group.
After the load balancer authenticates a user successfully, it passes the claims of the user to the target. If you inspect traffic forwarded to the sample demonstration application through custom HTTP header logging in your access logs, you can see three HTTP headers. These headers contain information about the user claims and is signed by the ALB with a signature and algorithm that you can verify.
The three HTTP headers include the following:
The access token from the token endpoint, in plain text.
The subject field (sub) from the user info endpoint, in plain text.
The user claims, in JSON web tokens (JWT) format.
From information encoded in the x-amzn-oidc-data
, it is possible to extract information about the user.
The following is an example Python 3.x application that can decode the payload portion of the x-amzn-oidc-data
to reveal the user claims passed by HAQM Cognito.
Cleanup
Now that you are done building the solution and testing it to clean up all the resources you can run the following commands:
Conclusion
In this post, we showed you how to authenticate users accessing your containerized application without writing authentication code, using the ALB’s inbuilt integration with HAQM Cognito. Maintaining and securing user management and authentication is offloaded from the application, which allows you to focus on building core business logic into the application. You don’t need to worry about platform tasks for managing, scheduling, and scaling containers for the web traffic because HAQM ECS handles all of that.