Using aws secretsmanager with ecs
TypeScriptTo use AWS Secrets Manager with Amazon Elastic Container Service (ECS), you'll typically be managing secrets that your containerized applications need access to, such as database credentials or API keys.
AWS Secrets Manager enables you to replace hardcoded credentials in your code (including passwords, tokens, and API keys) with calls to Secrets Manager APIs to retrieve the sensitive data. This helps you protect access to databases, services, and other sensitive system resources.
Below is a Pulumi program written in TypeScript that demonstrates how to create a secret in AWS Secrets Manager and how to configure an ECS Fargate service to use that secret. This program assumes that you have AWS credentials configured for Pulumi to use and that you've installed the necessary Pulumi packages.
Program Explanation
-
Creating a Secret: We use AWS Secrets Manager to create a new secret. In this example, we're storing dummy data just to illustrate the concept.
-
ECS Task Definition: We define an ECS Task that describes the containers that form your application. It includes details such as the image used in the container, CPU/memory constraints, and importantly, we include the secret we created earlier.
-
Fargate Service: We then define a Fargate service which runs and maintains the desired task definition instances in an Amazon ECS cluster.
Throughout the code, we'll use inline comments to explain specific sections and steps.
import * as aws from "@pulumi/aws"; import * as pulumi from "@pulumi/pulumi"; // Step 1: Create a secret in AWS Secrets Manager. const mySecret = new aws.secretsmanager.Secret("mySecret", { name: "MySecret", description: "This is an example secret" }); // Dummy data for the secret, typically you will have key-value pairs for your credentials. const secretValue = new aws.secretsmanager.SecretVersion("secretValue", { secretId: mySecret.id, secretString: JSON.stringify({ username: "admin", password: "T0p$3cret", }), }); // Step 2: Define an ECS Task Definition with the necessary containers and configurations. // In this task definition, we reference the secret that we created above. const myTaskDefinition = new aws.ecs.TaskDefinition("myTaskDef", { family: "myTaskFamily", cpu: "256", // Set according to your needs. memory: "512", // Set according to your needs. networkMode: "awsvpc", // Using AWS VPC Networking Mode. requiresCompatibilities: ["FARGATE"], executionRoleArn: aws.iam.Role.get("ecsTaskExecutionRole", "ecsTaskExecutionRole").arn, containerDefinitions: pulumi.all([mySecret.arn, secretValue.version, secretValue.secretString]).apply(([arn, version, secretString]) => JSON.stringify([{ name: "myContainer", image: "nginx", // Specify the image you want to use here. cpu: 256, memory: 512, secrets: [{ name: "MY_SECRET", // The environment variable your application will use to access the secret. valueFrom: arn, // ARN of the secret. }], }])) }); // Step 3: Define a Fargate Service to run and manage the task above on ECS. const myService = new aws.ecs.Service("myService", { cluster: "myClusterId", // Replace with your cluster's ARN or name. desiredCount: 1, // Run one instance of our task definition by default. launchType: "FARGATE", taskDefinition: myTaskDefinition.arn, // Reference to the task definition we defined. networkConfiguration: { // Define the network configuration (subnets, security groups, etc.). subnets: ["subnet-12345678"], securityGroups: ["sg-12345678"], }, waitForSteadyState: false, // Depending on your deployment you may want to wait for steady state. }); // Export the service name and ARN to be accessible outside of Pulumi. export const serviceName = myService.name; export const serviceArn = myService.arn;
Each resource in this program is created and managed by Pulumi, and references between resources are handled automatically. For instance,
myTaskDefinition
references the secret's ARN created by Pulumi inmySecret
.When this Pulumi program is deployed, it will provision the required AWS resources. Should the user ever choose to change the secrets or any other component, they can simply update the program and rerun Pulumi to perform the update.
-