MongoDB Passwordless Authentication : Spring Boot App in ECS
In this article, we will explore how to authenticate MongoDB from an Amazon Elastic Container Service (ECS) Fargate-hosted Spring Boot application using Service Connect.
We’ll leverage the capabilities of ECS Fargate for container orchestration and Service Connect for intercommunication of services while managing authentication with AWS Identity and Access Management (IAM) roles.
Pre-requisites
- A MongoDB Atlas cluster: You will need to have a MongoDB Atlas cluster set up in your MongoDB Atlas account. ( M10 or above )
- A VPC in your AWS account: You will need to have a Virtual Private Cloud (VPC) set up in your AWS account that will be used to connect your application with the MongoDB Atlas cluster. The VPC should have at least one subnet in a private IP address range.
- Private Endpoint or VPC Peering between AWS and MongoDB refers to setting up a direct, private network connection between an AWS Virtual Private Cloud (VPC) and a MongoDB database hosted on MongoDB Atlas. This allows traffic between the VPC and the database to travel securely and efficiently, without traversing the public internet.
- IAM roles: You will need to configure IAM roles to allow your AWS application to access the MongoDB Atlas cluster. You should create an IAM role with the necessary permissions and attach it to the Task & Task Execution containers running your application.
- Install AWS CLI (Command Line Interface), a tool that allows you to interact with AWS services from the command line. It provides a command-line interface for managing AWS resources. This will be used for authenticating AWS ECR from your system
- Install Docker Desktop for Windows or macOS, a software application that allows developers to build, test, and deploy containerized applications using Docker.
- Spring Boot Application with Spring Data for MongoDB that makes it easy to work with MongoDB from Spring Boot applications.
Connectivity
To connect to AWS Atlas from AWS, you can use VPC peering or a private endpoint.
VPC Peering
To set up peering between AWS and MongoDB Atlas, you will need to:
- Configure a VPC peering connection between your AWS VPC and the MongoDB Atlas VPC.
- Configure the security groups for both the AWS VPC and the MongoDB Atlas VPC to allow traffic to flow between them.
- Configure the routing tables for both the VPCs to enable traffic to flow between them.
- Verify connectivity: Use the Network Manager connectivity test to verify connectivity between the network devices in your AWS VPC and MongoDB VPC.
Private Endpoint
To set up a private endpoint between AWS and MongoDB Atlas, you will need to:
- Create a private endpoint: Create a private endpoint for MongoDB in your AWS VPC by creating an interface endpoint. You will need to provide the necessary details, such as the service name and the subnet IDs.
- Verify connectivity: Use the Network Manager connectivity test to verify connectivity between the network devices in your AWS VPC and MongoDB VPC.
The exact steps for setting up peering can be done through the MongoDB Atlas web console by providing the necessary details.
AWS ECR
ECR (Amazon Elastic Container Registry) is a fully-managed Docker container registry that makes it easy for developers to store, manage, and deploy Docker container images on AWS.
With ECR, you can easily store and manage container images for use in AWS services like Amazon ECS (Elastic Container Service) and Amazon EKS (Elastic Kubernetes Service).
aws ecr create-repository \
--repository-name repositoryName \
--image-scanning-configuration scanOnPush=true \
--region region
Retrieve an authentication token and authenticate your Docker client to your registry. Use the AWS CLI and enter the below commands:
aws ecr get-login-password --region us-east-1 |
docker login --username AWS --password-stdin accountName.dkr.ecr.us-east-1.amazonaws.com
ECR will be used to store and manage your Spring Boot application images
AWS ECS Fargate
Create Roles
In Amazon Elastic Container Service (ECS), there are two types of roles that you can associate with your ECS cluster: Task and Task execution role.
Task Role: A task role is an AWS Identity and Access Management (IAM) role that you can assign to a task. It allows the containers within the task to access AWS services and resources securely.For example, the task role can grant permissions for accessing an Amazon S3 bucket
Task Execution Role: A task execution role is an IAM role that grants permissions to the ECS service to perform actions on your behalf, such as pulling container images from a registry or writing logs to CloudWatch.
Create ECS Cluster
Once you’re logged in, navigate to the ECS service by searching for “ECS” in the AWS services search bar.
Configure cluster: Provide a name for your cluster in the “Cluster name” field. You can also customize the VPC, subnets, and security group settings under the “Networking” section.
Enable CloudWatch container insights (optional): You have the option to enable CloudWatch container insights, which provides detailed monitoring and logging for your containers.
Create Task Definition
In AWS ECS (Elastic Container Service) Fargate, a task definition is a blueprint that defines how a containerized application should run. It includes configuration details for one or more containers that are grouped together as part of a task. Each container definition includes details such as the Docker image to use, CPU and memory limits, port mappings, environment variables, logging options, and more.
Volumes: Task definitions can also include volume definitions, allowing containers to have persistent storage. Volumes can be specified as Amazon Elastic File System (EFS) volumes, Amazon Elastic Block Store (EBS) volumes, or Docker volumes. Containers within the task can mount and access these volumes as needed.
Once you have defined your task definition, you can use it to create and run tasks within your ECS Fargate cluster. Task definitions are versioned, allowing you to make updates and roll back to previous versions if needed.
I created two task definitions for the LoadGen project, one for API and one for UI tasks.
Create Task
After creating the task definition, you can now create a task based on that definition.
- In the cluster dashboard, click on “Task Definitions" in the sidebar and then click the “Run new Task” button. Select the task definition you created from the list.
- Specify the desired number of tasks to run, the VPC and subnets to launch the tasks in, and any other necessary configurations.
- Click the “Run Task” button to create and run the tasks in your Fargate cluster.
Create Service
In AWS ECS (Elastic Container Service), tasks are typically created as part of a service. A service in ECS is responsible for managing and maintaining a specified number of instances of a task definition. It ensures that the desired number of tasks are running and replaces any failed or unhealthy instances.
When you create a service in ECS, you specify the task definition to use, the desired number of tasks to run, and other configuration settings such as load balancing and auto scaling. The service takes care of creating and managing tasks based on the provided configuration.
Services in ECS are designed to ensure the long-running availability of your application by continuously monitoring and maintaining the desired number of tasks. They provide features such as load balancing, automatic scaling, and health checks to keep your application highly available and resilient.
It is common practice to create a service in ECS to manage the tasks rather than create them independently. The service provides the necessary orchestration and lifecycle management capabilities for your tasks.
In the ECS dashboard, select your cluster where you want to create the service and choose the task definition you created earlier from the dropdown list. Configure the desired number of tasks to run in the service. You can specify a fixed number or configure automatic scaling.
Under “Load balancing,” you can select an existing load balancer or create a new one. This step is optional but recommended for load balancing traffic across tasks.
Create Load Balancer( optional )
To enable load balancing for your service, you need to create a load balancer that distributes traffic across the tasks in your service. You can use Application Load Balancer (ALB) or Network Load Balancer (NLB), depending on your requirements.
- Navigate to the EC2 service, and under the “Load Balancers” section, click on “Create Load Balancer.”
- Choose the appropriate load balancer type (ALB or NLB) based on your needs.
- Configure the load balancer settings, such as selecting a VPC, defining listener rules, and specifying target groups.
Once you have a task definition and a load balancer, you can proceed to create a service that uses the load balancer to distribute traffic
In scenarios where you want to simplify service discovery, facilitate communication between microservices, and enhance security within your ECS environment, we can optionally configure Service Connect.
Create Service Connect Workflow( optional )
Service Connect simplifies the service discovery process within ECS. It provides a mechanism to reference and connect to ECS services using logical names instead of having to rely on IP addresses or DNS configurations. This makes it easier to manage and scale your services.Below are the steps for setting up Service Connect within your ECS Cluster
a. Namespace Configuration:
- Select the desired discovery namespace from the list of AWS Cloud Map namespaces available in your AWS account and region.
- The discovery namespace is used for service discovery within Service Connect.
b. Port Mapping Configuration:
- Click the “Add more port mappings and applications” button to create a new row for port mapping configuration.
- Select a port alias for the new row. The port alias is a logical name that represents a specific port in your task definition.
- You can assign a discovery name, DNS name, and port number for the port mapping if needed. These fields are optional.
- The discovery name is used by ECS to create an AWS Cloud Map service name. If not provided, the port alias name is used as the service name.
- The DNS name is configured in the Service Connect proxy for every task in the namespace. If not provided, the port alias is used in the proxy configuration.
- The port number field allows you to specify a different port number to be used in the Service Connect proxy configuration for this name.
- If you want to resolve multiple names to connect to the same port, create multiple rows with unique discovery names.
c. Advanced Configuration:
- Under the Advanced section, you can configure log collection for the Service Connect components.
- These logs contain startup and access logs for the managed Envoy proxy.
I created two services for the LoadGen project, one for API and UI tasks.
Configure MongoDB Atlas
In the MongoDB Atlas dashboard, go to Database Access under Security and choose Add New Database User.
Next, choose AWS IAM as your authentication method.
Select the IAM Role as an AWS IAM type and paste the ARN of the role associated with the Task Execution Role in the associated field. Then click Add user.
Connection String
- In the “Connect to Cluster” modal, click on the “Connect your application” button.
- Choose the connectionType to be Private Endpoint
- Choose the private Link Type( this step is applicable only for sharded cluster )
Atlas can generate an optimized SRV connection string for sharded clusters using the load balancers from your private endpoint service. When you use an optimized connection string, Atlas limits the number of connections per
mongos
between your application and your sharded cluster. The limited connections permongos
improve performance during spikes in connection counts.
Choose to connect your application to your cluster using MongoDB’s native drivers, you will be able to see the connection string format and notice that it has an AWS_SESSION_TOKEN
in the end. This is part of the temporary credentials that will be required when you try connecting to MongoDB.
As you already have a role assigned to the Task Execution Role, you don’t need to pass the temporary credentials. It’ll be done automatically when you connect to the MongoDB cluster using the Mongo client by the Java driver.
mongodb+srv://clusterName-pl-0-lb.domain.mongodb.net/
?authSource=%24external&authMechanism=MONGODB-AWS&retryWrites=true&w=majority
Spring Boot Application: mTest
mTest is a solution accelerator that helps customers generate large volumes of customizable, close-to-real world test data for specific customer schemas and understand MongoDB query performance.
This application has two components: the UI, where the user can provide templates and load definitions; using this configuration, the backend component scales up or down to generate the required volume of data and test query performance.
With the above deployment setup, ECS will manage the scaling and availability of both the UI and backend components independently.
The UI-service can be load-balanced to handle user traffic, while the backend-service can automatically scale based on the configured rules to generate the required volume of data. We can configure communication between the two components using environment variables, network configuration, and service discovery mechanisms provided by ECS.
UI/Backend Service Communication
Using Service Connect configuration in AWS ECS, we have successfully created an endpoint for the UI to securely make calls to the backend API. This allows for secure communication and data exchange between the UI and backend components of your application.
Conclusion
We created a secure and efficient application architecture by combining MongoDB Atlas and AWS IAM passwordless authentication with Service Connect and load balancing in ECS.
This setup ensures that your Spring Boot application can securely connect to MongoDB Atlas and that your services can communicate with each other reliably, making your application more robust and scalable.
AWS + MongoDB provide limitless possibilities!