Securing Database Credentials for WordPress on Amazon ECS Fargate with AWS Secrets Manager and KMS Encryption

The solution involves storing database credentials securely using AWS Secrets Manager and encrypting them with AWS KMS, follow these steps:

  1. Create an AWS Secrets Manager Secret:
  • Log in to the AWS Management Console.
  • Navigate to the AWS Secrets Manager service.
  • Click “Store a new secret.”
  • Choose “Credentials for RDS database” or a similar option, and enter the database credentials.
  1. Encrypt the Secret with AWS KMS:
  • In the Secrets Manager, select the secret you created.
  • Click on “Edit,” and under the “Secret encryption” section, choose the option to “Rotate automatically” for better security.
  • Select your KMS key for encryption and click “Save.”
  1. Create an IAM Role for ECS Task Execution Role:
  • In the AWS Management Console, navigate to the IAM service.
  • Create a new IAM role or update your existing ECS task execution role.
  • Attach the necessary policies to the role, such as:
    • AmazonECSTaskExecutionRolePolicy to allow ECS tasks to be executed.
    • SecretsManagerReadWrite and KMSDecrypt to allow access to Secrets Manager and KMS.
  • Make sure the role has a trust relationship with the ECS service.
  1. Create or Update Your Task Definition:
  • In the ECS service, create a new task definition or update an existing one.
  • Specify the IAM role you created for the “Task Role” in your task definition.
  1. Define Secrets in Your Container Definition:
  • In your task definition, under the container definition, you should specify the secrets. Each secret should have a name (the environment variable name) and the ARN of the Secrets Manager secret:
   "secrets": [
      {
        "name": "DB_PASSWORD",
        "valueFrom": "arn:aws:secretsmanager:REGION:ACCOUNT_ID:secret:SECRET_NAME"
      }
   ]

Replace DB_PASSWORD with the name of the environment variable you want to set in your container and provide the correct ARN for the Secrets Manager secret.

  1. Create an ECS Service:
  • In the ECS service, create a new service using your updated task definition.

With these steps, your WordPress container running on ECS with the Fargate launch type will have access to the database credentials securely stored in AWS Secrets Manager and encrypted with AWS KMS. The credentials will be provided to the container as environment variables without being directly exposed to the cluster, ensuring security and key rotation as required.

AWS CLI solution

To implement the solution using the AWS Command Line Interface (CLI), you will need to perform several steps, including creating a Secrets Manager secret, setting up an IAM role, updating your task definition, and creating an ECS service. Below, I’ll provide the commands and explain the parameters in detail for each step:

Step 1: Create an AWS Secrets Manager Secret

Use the AWS CLI to create a Secrets Manager secret with your database credentials. Replace placeholders with your actual values.

aws secretsmanager create-secret --name MyDBSecret --secret-string '{"username":"your_db_username", "password":"your_db_password"}'
  • MyDBSecret: Replace this with a meaningful name for your secret.
  • --secret-string: This parameter specifies the secret value. Replace your_db_username and your_db_password with your actual database username and password.

Step 2: Encrypt the Secret with AWS KMS

This step requires that you already have a KMS key created. If not, you should create one in the AWS Management Console.

aws secretsmanager update-secret --secret-id MyDBSecret --kms-key-id YOUR_KMS_KEY_ID
  • MyDBSecret: Replace this with the name of your secret.
  • YOUR_KMS_KEY_ID: Replace this with the actual ID of your KMS key.

Step 3: Create an IAM Role for ECS Task Execution

Use the AWS CLI to create an IAM role with the necessary permissions. Create a JSON file (e.g., ecs-task-execution-role-policy.json) with the following policy document:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "ecs:RunTask",
        "secretsmanager:GetSecretValue",
        "kms:Decrypt"
      ],
      "Resource": "*"
    }
  ]
}

Then, create the IAM role using the AWS CLI:

aws iam create-role --role-name MyECSTaskExecutionRole --assume-role-policy-document file://ecs-task-execution-role-trust-policy.json
  • MyECSTaskExecutionRole: Replace this with a meaningful name for your role.
  • file://ecs-task-execution-role-trust-policy.json: Specify the file path for the trust policy document you created.

Step 4: Create or Update Your Task Definition

Edit your task definition JSON file and specify the “executionRoleArn” with the IAM role created in the previous step. Make sure to also define the secrets as environment variables. Here’s an example snippet of a task definition:

{
  "family": "my-wordpress-task",
  "executionRoleArn": "arn:aws:iam::YOUR_ACCOUNT_ID:role/MyECSTaskExecutionRole",
  "containerDefinitions": [
    {
      "name": "wordpress-container",
      "image": "wordpress:latest",
      "secrets": [
        {
          "name": "DB_PASSWORD",
          "valueFrom": "arn:aws:secretsmanager:REGION:ACCOUNT_ID:secret:MyDBSecret"
        }
      ]
    }
  ]
}
  • "my-wordpress-task": Replace with a unique name for your task family.
  • "arn:aws:iam::YOUR_ACCOUNT_ID:role/MyECSTaskExecutionRole": Replace with the ARN of the IAM role you created.
  • "arn:aws:secretsmanager:REGION:ACCOUNT_ID:secret:MyDBSecret": Replace with the ARN of your Secrets Manager secret.

Step 5: Create an ECS Service

Use the AWS CLI to create an ECS service using your updated task definition:

aws ecs create-service --cluster MyCluster --service-name MyWordPressService --task-definition my-wordpress-task:1 --launch-type FARGATE --network-configuration "awsvpcConfiguration={subnets=[subnet-XXXXXX],securityGroups=[sg-XXXXXX]}"
  • MyCluster: Replace with your ECS cluster name.
  • MyWordPressService: Choose a meaningful name for your service.
  • my-wordpress-task:1: Replace with the task definition name and revision.
  • subnet-XXXXXX: Replace with the subnet ID where you want to deploy the service.
  • sg-XXXXXX: Replace with the security group ID.

With these commands, you can implement the solution using the AWS CLI, and you’ve learned the parameters and options involved in each step.

Using boto3

To implement the solution described above using AWS SDK for Python (Boto3), you can follow these steps. Make sure you have the Boto3 library installed and configured with your AWS credentials.

Step 1: Create an AWS Secrets Manager Secret

Use Boto3 to create a Secrets Manager secret with your database credentials. Replace placeholders with your actual values.

import boto3

client = boto3.client('secretsmanager')

secret_name = "MyDBSecret"
username = "your_db_username"
password = "your_db_password"

response = client.create_secret(
    Name=secret_name,
    SecretString='{"username": "' + username + '", "password": "' + password + '"}'
)

Step 2: Encrypt the Secret with AWS KMS

Assuming you already have a KMS key, you can use Boto3 to update the secret and specify the KMS key for encryption.

kms_key_id = "YOUR_KMS_KEY_ID"

response = client.update_secret(
    SecretId=secret_name,
    KmsKeyId=kms_key_id
)

Step 3: Create an IAM Role for ECS Task Execution

Use Boto3 to create an IAM role with the necessary permissions for ECS task execution.

import json

iam = boto3.client('iam')

role_name = "MyECSTaskExecutionRole"
trust_policy = {
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "ecs-tasks.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}

role_policy = {
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ecs:RunTask",
                "secretsmanager:GetSecretValue",
                "kms:Decrypt"
            ],
            "Resource": "*"
        }
    ]
}

response = iam.create_role(
    RoleName=role_name,
    AssumeRolePolicyDocument=json.dumps(trust_policy)
)

# Attach the required policies to the role
iam.put_role_policy(
    RoleName=role_name,
    PolicyName="MyECSTaskExecutionRolePolicy",
    PolicyDocument=json.dumps(role_policy)
)

Step 4: Create or Update Your Task Definition

Using Boto3, you can create or update your task definition with the IAM role and secrets.

ecs = boto3.client('ecs')

task_definition_name = "my-wordpress-task"
execution_role_arn = "arn:aws:iam::YOUR_ACCOUNT_ID:role/MyECSTaskExecutionRole"
secrets = [
    {
        "name": "DB_PASSWORD",
        "valueFrom": "arn:aws:secretsmanager:REGION:ACCOUNT_ID:secret:MyDBSecret"
    }
]

task_definition = {
    "family": task_definition_name,
    "executionRoleArn": execution_role_arn,
    "containerDefinitions": [
        {
            "name": "wordpress-container",
            "image": "wordpress:latest",
            "secrets": secrets
        }
    ]
}

response = ecs.register_task_definition(
    family=task_definition_name,
    networkMode="awsvpc",
    containerDefinitions=task_definition["containerDefinitions"]
)

Step 5: Create an ECS Service

Use Boto3 to create an ECS service that references your task definition.

cluster_name = "MyCluster"
service_name = "MyWordPressService"
subnet_id = "subnet-XXXXXX"
security_group_id = "sg-XXXXXX"

response = ecs.create_service(
    cluster=cluster_name,
    serviceName=service_name,
    taskDefinition=task_definition_name,
    launchType="FARGATE",
    networkConfiguration={
        "awsvpcConfiguration": {
            "subnets": [subnet_id],
            "securityGroups": [security_group_id]
        }
    }
)

Make sure to replace placeholders like YOUR_ACCOUNT_ID, REGION, YOUR_KMS_KEY_ID, subnet-XXXXXX, and sg-XXXXXX with your actual values. This Python script uses Boto3 to perform each step in the solution using the AWS SDK for Python.

Leave a Comment

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

Scroll to Top