Skip to content

Commit

Permalink
fix(batch): Allow ECS JobDefinition Containers to pass Secrets as Env…
Browse files Browse the repository at this point in the history
…ironment Variables & Enable Kubernetes Secret Volumes (#26126)

Changes the type of `secrets` from `ISecret[]` to `{ [key: string]: ISecret }`. The `key` is the name of the environment variable to expose to the container. 

Also enables the specification of EKS Kubernetes volumes, which our README documented but wasn't actually supported because of a CFN issue that has since been fixed.

Closes #25559.

----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
  • Loading branch information
comcalvi committed Jun 29, 2023
1 parent edad593 commit dc6f120
Show file tree
Hide file tree
Showing 23 changed files with 317 additions and 167 deletions.
23 changes: 23 additions & 0 deletions packages/@aws-cdk/aws-batch-alpha/README.md
Expand Up @@ -495,6 +495,29 @@ jobDefn.container.addVolume(batch.EcsVolume.efs({
}));
```

### Secrets

You can expose SecretsManager Secret ARNs to your container as environment variables.
The following example defines the `MY_SECRET_ENV_VAR` environment variable that contains the
ARN of the Secret defined by `mySecret`:

```ts
import * as cdk from 'aws-cdk-lib';

declare const mySecret: secretsmanager.ISecret;

const jobDefn = new batch.EcsJobDefinition(this, 'JobDefn', {
container: new batch.EcsEc2ContainerDefinition(this, 'containerDefn', {
image: ecs.ContainerImage.fromRegistry('public.ecr.aws/amazonlinux/amazonlinux:latest'),
memory: cdk.Size.mebibytes(2048),
cpu: 256,
secrets: {
MY_SECRET_ENV_VAR: mySecret,
}
}),
});
```

### Running Kubernetes Workflows

Batch also supports running workflows on EKS. The following example creates a `JobDefinition` that runs on EKS:
Expand Down
18 changes: 10 additions & 8 deletions packages/@aws-cdk/aws-batch-alpha/lib/ecs-container-definition.ts
Expand Up @@ -342,13 +342,14 @@ export interface IEcsContainerDefinition extends IConstruct {
readonly readonlyRootFilesystem?: boolean;

/**
* The secrets for the container. Can be referenced in your job definition.
* A map from environment variable names to the secrets for the container. Allows your job definitions
* to reference the secret by the environment variable name defined in this property.
*
* @see https://docs.aws.amazon.com/batch/latest/userguide/specifying-sensitive-data.html
*
* @default - no secrets
*/
readonly secrets?: secretsmanager.ISecret[];
readonly secrets?: { [envVarName: string]: secretsmanager.ISecret };

/**
* The user name to use inside the container
Expand Down Expand Up @@ -458,13 +459,14 @@ export interface EcsContainerDefinitionProps {
readonly readonlyRootFilesystem?: boolean;

/**
* The secrets for the container. Can be referenced in your job definition.
* A map from environment variable names to the secrets for the container. Allows your job definitions
* to reference the secret by the environment variable name defined in this property.
*
* @see https://docs.aws.amazon.com/batch/latest/userguide/specifying-sensitive-data.html
*
* @default - no secrets
*/
readonly secrets?: secretsmanager.ISecret[];
readonly secrets?: { [envVarName: string]: secretsmanager.ISecret };

/**
* The user name to use inside the container
Expand Down Expand Up @@ -495,7 +497,7 @@ abstract class EcsContainerDefinitionBase extends Construct implements IEcsConta
public readonly linuxParameters?: LinuxParameters;
public readonly logDriverConfig?: ecs.LogDriverConfig;
public readonly readonlyRootFilesystem?: boolean;
public readonly secrets?: secretsmanager.ISecret[];
public readonly secrets?: { [envVarName: string]: secretsmanager.ISecret };
public readonly user?: string;
public readonly volumes: EcsVolume[];

Expand Down Expand Up @@ -553,12 +555,12 @@ abstract class EcsContainerDefinitionBase extends Construct implements IEcsConta
logConfiguration: this.logDriverConfig,
readonlyRootFilesystem: this.readonlyRootFilesystem,
resourceRequirements: this._renderResourceRequirements(),
secrets: this.secrets?.map((secret) => {
secrets: this.secrets ? Object.entries(this.secrets).map(([name, secret]) => {
return {
name: secret.secretName,
name,
valueFrom: secret.secretArn,
};
}),
}) : undefined,
mountPoints: Lazy.any({
produce: () => {
if (this.volumes.length === 0) {
Expand Down
Expand Up @@ -647,9 +647,9 @@ export interface EksVolumeOptions {
readonly name: string;

/**
* The path on the container where the container is mounted.
* The path on the container where the volume is mounted.
*
* @default - the container is not mounted
* @default - the volume is not mounted
*/
readonly mountPath?: string;

Expand Down Expand Up @@ -902,7 +902,7 @@ export class SecretPathVolume extends EksVolume {
constructor(options: SecretPathVolumeOptions) {
super(options);
this.secretName = options.secretName;
this.optional = options.optional;
this.optional = options.optional ?? true;
}
}

Expand Down
3 changes: 1 addition & 2 deletions packages/@aws-cdk/aws-batch-alpha/lib/eks-job-definition.ts
Expand Up @@ -192,14 +192,13 @@ export class EksJobDefinition extends JobDefinitionBase implements IEksJobDefini
};
}
if (SecretPathVolume.isSecretPathVolume(volume)) {
/*return {
return {
name: volume.name,
secret: {
optional: volume.optional,
secretName: volume.secretName,
},
};
*/
}

throw new Error('unknown volume type');
Expand Down
Expand Up @@ -255,9 +255,9 @@ describe.each([EcsEc2ContainerDefinition, EcsFargateContainerDefinition])('%p',
new EcsJobDefinition(stack, 'ECSJobDefn', {
container: new ContainerDefinition(stack, 'EcsContainer', {
...defaultContainerProps,
secrets: [
new Secret(stack, 'testSecret'),
],
secrets: {
envName: new Secret(stack, 'testSecret'),
},
}),
});

Expand All @@ -268,59 +268,7 @@ describe.each([EcsEc2ContainerDefinition, EcsFargateContainerDefinition])('%p',
...pascalCaseExpectedProps.ContainerProperties,
Secrets: [
{
Name: {
'Fn::Join': [
'-',
[
{
'Fn::Select': [
0,
{
'Fn::Split': [
'-',
{
'Fn::Select': [
6,
{
'Fn::Split': [
':',
{
Ref: 'testSecretB96AD12C',
},
],
},
],
},
],
},
],
},
{
'Fn::Select': [
1,
{
'Fn::Split': [
'-',
{
'Fn::Select': [
6,
{
'Fn::Split': [
':',
{
Ref: 'testSecretB96AD12C',
},
],
},
],
},
],
},
],
},
],
],
},
Name: 'envName',
ValueFrom: { Ref: 'testSecretB96AD12C' },
},
],
Expand Down

0 comments on commit dc6f120

Please sign in to comment.