Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(stepfunctions): add support for EncryptionConfiguration #30959

Merged
merged 47 commits into from
Sep 20, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
3e29f48
Basic implementation for EncryptionConfiguration
Jul 15, 2024
4d63917
Merge branch 'aws:main' into main
VaidSaraswat Jul 18, 2024
f9b5d7a
Merge branch 'aws:main' into main
VaidSaraswat Jul 26, 2024
971290d
Adding support for KMS in StateMachine and Activity resources
Aug 1, 2024
a44a3e0
Update packages/aws-cdk-lib/aws-stepfunctions/lib/state-machine.ts
VaidSaraswat Aug 8, 2024
ec8865a
Update packages/aws-cdk-lib/aws-stepfunctions/lib/state-machine.ts
VaidSaraswat Aug 8, 2024
c1d25e9
Update packages/aws-cdk-lib/aws-stepfunctions/lib/state-machine.ts
VaidSaraswat Aug 8, 2024
61b69e1
Addressing second round of feedback
Aug 9, 2024
25521c4
Removed redunant optional chaining and created encryptionConfiguratio…
Aug 9, 2024
2373d5a
Adding integrations key policy & non-null assertion for kms key in util
Aug 9, 2024
8d605fe
Removing condition from KMS key policy for CWL encryption
Aug 11, 2024
b2dc0e9
Updating CWL encryption example to provide KMS key as prop
Aug 11, 2024
89a56ce
Adding back encryption context and updating CWL Log Group to use sepa…
Aug 12, 2024
5ab6f60
Adding ActivityProps type as accepted type for constructEncryptionCon…
Aug 13, 2024
ce62bb7
Update packages/aws-cdk-lib/aws-stepfunctions/lib/activity.ts
VaidSaraswat Aug 14, 2024
e57602a
Update packages/aws-cdk-lib/aws-stepfunctions/lib/util.ts
VaidSaraswat Aug 14, 2024
20bf8e5
Update packages/aws-cdk-lib/aws-stepfunctions/lib/util.ts
VaidSaraswat Aug 14, 2024
94a1783
Addressing third round of feedback
Aug 16, 2024
7f52d32
Adding assertions to snapshot tests
Aug 16, 2024
de3bbc4
Merge branch 'main' into feat-encryption-configuration
shivlaks Aug 17, 2024
d668d9b
LogGroup key uses narrower permissions in key policy && updating snap…
Aug 20, 2024
6042f32
Update packages/aws-cdk-lib/aws-stepfunctions/README.md
VaidSaraswat Aug 22, 2024
db31000
Update packages/aws-cdk-lib/aws-stepfunctions/README.md
VaidSaraswat Aug 22, 2024
1099973
- Add back unit tests for validating encryption configuration
Aug 26, 2024
1c3a816
Update packages/aws-cdk-lib/aws-stepfunctions/README.md
VaidSaraswat Aug 27, 2024
d6d5f0c
Update packages/aws-cdk-lib/aws-stepfunctions/README.md
VaidSaraswat Aug 27, 2024
aca062a
Update packages/aws-cdk-lib/aws-stepfunctions/README.md
VaidSaraswat Aug 27, 2024
e8c2808
Update packages/aws-cdk-lib/aws-stepfunctions/lib/activity.ts
VaidSaraswat Aug 27, 2024
e39dc89
- Updating README to include ts and fixed indentation
Aug 27, 2024
57483ac
Adding dependency imports for README examples
Aug 27, 2024
2aca3aa
- Fix indentation in code sample for README
Aug 27, 2024
8b3a07e
Rename aws-cdk-lib/kms to 'aws-cdk-lib/aws-kms'
Aug 28, 2024
b25b069
Removing unnecessary kms:Decrypt permissions for execution role when …
Aug 28, 2024
2868c02
Update packages/aws-cdk-lib/aws-stepfunctions/lib/util.ts
VaidSaraswat Aug 28, 2024
581739d
- Use stronger assertion Match.objectEquals
Aug 28, 2024
0a5b065
Removing unnecessary KMS:Decrypt permissions on Activity key for Send…
Aug 28, 2024
43d3dad
Update packages/aws-cdk-lib/aws-stepfunctions/README.md
VaidSaraswat Aug 29, 2024
b0b5674
- Use new EncryptionConfiguration object for customers who want to us…
Aug 30, 2024
fedf070
Adding missing comma
Aug 30, 2024
4c062d8
Update packages/aws-cdk-lib/aws-stepfunctions/README.md
VaidSaraswat Sep 2, 2024
f5f2396
Update packages/aws-cdk-lib/aws-stepfunctions/lib/state-machine.ts
VaidSaraswat Sep 2, 2024
130cd1f
- Created new abstract EncryptionConfiguration class which CustomerMa…
Sep 4, 2024
1ebeafe
Merge branch 'main' into feat-encryption-configuration
paulhcsun Sep 4, 2024
3d44c34
- Added new lines to files that didn't have them
Sep 6, 2024
74cd4fb
Update packages/aws-cdk-lib/aws-stepfunctions/README.md
VaidSaraswat Sep 19, 2024
339aa82
Update packages/aws-cdk-lib/aws-stepfunctions/README.md
VaidSaraswat Sep 19, 2024
17641e4
Merge branch 'main' into feat-encryption-configuration
paulhcsun Sep 20, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 22 additions & 1 deletion packages/aws-cdk-lib/aws-stepfunctions/lib/activity.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { Construct } from 'constructs';
import { EncryptionConfiguration } from './encryption-configuration';
import { StatesMetrics } from './stepfunctions-canned-metrics.generated';
import { CfnActivity } from './stepfunctions.generated';
import * as cloudwatch from '../../aws-cloudwatch';
import * as iam from '../../aws-iam';
import { ArnFormat, IResource, Lazy, Names, Resource, Stack } from '../../core';
export * from './encryption-configuration';

/**
* Properties for defining a new Step Functions Activity
Expand All @@ -15,6 +17,12 @@ export interface ActivityProps {
* @default - If not supplied, a name is generated
*/
readonly activityName?: string;
/**
* The EncryptionConfiguration for this activity.
*
* @default - no EncryptionConfiguration
*/
VaidSaraswat marked this conversation as resolved.
Show resolved Hide resolved
readonly encryptionConfiguration?: EncryptionConfiguration;
}

/**
Expand Down Expand Up @@ -57,14 +65,20 @@ export class Activity extends Resource implements IActivity {
*/
public readonly activityName: string;

/**
* @attribute
*/
VaidSaraswat marked this conversation as resolved.
Show resolved Hide resolved
public readonly encryptionConfiguration?: EncryptionConfiguration;

constructor(scope: Construct, id: string, props: ActivityProps = {}) {
super(scope, id, {
physicalName: props.activityName ||
Lazy.string({ produce: () => this.generateName() }),
Lazy.string({ produce: () => this.generateName() }),
});

const resource = new CfnActivity(this, 'Resource', {
name: this.physicalName!, // not null because of above call to `super`
encryptionConfiguration: props.encryptionConfiguration ?? undefined,
});

this.activityArn = this.getResourceArnAttribute(resource.ref, {
Expand Down Expand Up @@ -222,4 +236,11 @@ export interface IActivity extends IResource {
* @attribute
*/
readonly activityName: string;

/**
* The EncryptioConfiguration of the activity
*
* @attribute
*/
VaidSaraswat marked this conversation as resolved.
Show resolved Hide resolved
readonly encryptionConfiguration?: EncryptionConfiguration;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/**
* Define an EncryptionConfiguration
*/
export interface EncryptionConfiguration {
VaidSaraswat marked this conversation as resolved.
Show resolved Hide resolved
/**
* Identifier for KMS key, which can in the format of key ARN, key ID, alias ARN or alias name
VaidSaraswat marked this conversation as resolved.
Show resolved Hide resolved
* @default - no kmsKeyId is associated
*/
readonly kmsKeyId?: string;
VaidSaraswat marked this conversation as resolved.
Show resolved Hide resolved
/**
* Maximum duration for which SFN will reuse data keys. When the period expires,
* SFN will call GenerateDataKey. This setting only applies to customer managed KMS key and does not apply to AWS owned KMS key.
VaidSaraswat marked this conversation as resolved.
Show resolved Hide resolved
* @default - 300s
*/
readonly kmsDataKeyReusePeriodSeconds?: number;
VaidSaraswat marked this conversation as resolved.
Show resolved Hide resolved
/**
* The encryption option specified for the state machine
* @default - AWS_OWNED_KEY
*/
readonly type: EncryptionType;
}
/**
* Define an EncryptionType
*/
export enum EncryptionType {
/**
* SFN owned key
*/
AWS_OWNED_KEY = 'AWS_OWNED_KEY',
/**
* Customer managed key
*/
CUSTOMER_MANAGED_KMS_KEY = 'CUSTOMER_MANAGED_KMS_KEY',
}
54 changes: 51 additions & 3 deletions packages/aws-cdk-lib/aws-stepfunctions/lib/state-machine.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Construct } from 'constructs';
import { EncryptionConfiguration } from './encryption-configuration';
import { StateGraph } from './state-graph';
import { StatesMetrics } from './stepfunctions-canned-metrics.generated';
import { CfnStateMachine } from './stepfunctions.generated';
Expand All @@ -8,6 +9,7 @@ import * as iam from '../../aws-iam';
import * as logs from '../../aws-logs';
import * as s3_assets from '../../aws-s3-assets';
import { Arn, ArnFormat, Duration, IResource, RemovalPolicy, Resource, Stack, Token } from '../../core';
export * from './encryption-configuration';

/**
* Two types of state machines are available in AWS Step Functions: EXPRESS AND STANDARD.
Expand Down Expand Up @@ -153,6 +155,12 @@ export interface StateMachineProps {
* @default RemovalPolicy.DESTROY
*/
readonly removalPolicy?: RemovalPolicy;

/**
* EncryptionConfiguration for this state machine
* @default No EncryptionConfiguration
*/
readonly encryptionConfiguration?: EncryptionConfiguration;
}

/**
Expand All @@ -164,6 +172,7 @@ abstract class StateMachineBase extends Resource implements IStateMachine {
*/
public static fromStateMachineArn(scope: Construct, id: string, stateMachineArn: string): IStateMachine {
class Import extends StateMachineBase {
public encryptionConfiguration?: EncryptionConfiguration | undefined;
public readonly stateMachineArn = stateMachineArn;
public readonly grantPrincipal = new iam.UnknownPrincipal({ resource: this });
}
Expand All @@ -187,19 +196,41 @@ abstract class StateMachineBase extends Resource implements IStateMachine {

public abstract readonly stateMachineArn: string;

public abstract readonly encryptionConfiguration?: EncryptionConfiguration;

/**
* The principal this state machine is running as
*/
public abstract readonly grantPrincipal: iam.IPrincipal;

VaidSaraswat marked this conversation as resolved.
Show resolved Hide resolved
private isEncryptionConfigurationSet() {
return this.encryptionConfiguration !== undefined;
}

private getKmsGenerateDataKeyAndDecryptActions() {
if (this.isEncryptionConfigurationSet()) {
return ['kms:GenerateDataKey', 'kms:Decrypt'];
} else {
return [];
}
}

private getKmsDecryptAction() {
if (this.isEncryptionConfigurationSet()) {
return ['kms:Decrypt'];
} else {
return [];
}
}

/**
* Grant the given identity permissions to start an execution of this state
* machine.
*/
public grantStartExecution(identity: iam.IGrantable): iam.Grant {
VaidSaraswat marked this conversation as resolved.
Show resolved Hide resolved
return iam.Grant.addToPrincipal({
grantee: identity,
actions: ['states:StartExecution'],
actions: ['states:StartExecution', ... this.getKmsGenerateDataKeyAndDecryptActions()],
resourceArns: [this.stateMachineArn],
});
}
Expand All @@ -211,7 +242,7 @@ abstract class StateMachineBase extends Resource implements IStateMachine {
public grantStartSyncExecution(identity: iam.IGrantable): iam.Grant {
return iam.Grant.addToPrincipal({
grantee: identity,
actions: ['states:StartSyncExecution'],
actions: ['states:StartSyncExecution', ...this.getKmsDecryptAction()],
resourceArns: [this.stateMachineArn],
});
}
Expand All @@ -235,6 +266,7 @@ abstract class StateMachineBase extends Resource implements IStateMachine {
'states:DescribeExecution',
'states:DescribeStateMachineForExecution',
'states:GetExecutionHistory',
...this.getKmsDecryptAction(),
],
resourceArns: [`${this.executionArn()}:*`],
});
Expand All @@ -244,6 +276,7 @@ abstract class StateMachineBase extends Resource implements IStateMachine {
'states:ListActivities',
'states:DescribeStateMachine',
'states:DescribeActivity',
...this.getKmsDecryptAction(),
],
resourceArns: ['*'],
});
Expand All @@ -259,6 +292,7 @@ abstract class StateMachineBase extends Resource implements IStateMachine {
'states:SendTaskSuccess',
'states:SendTaskFailure',
'states:SendTaskHeartbeat',
...this.getKmsDecryptAction(),
],
resourceArns: [this.stateMachineArn],
});
Expand Down Expand Up @@ -413,6 +447,12 @@ export class StateMachine extends StateMachineBase {
*/
public readonly stateMachineType: StateMachineType;

/**
* Type of the EncryptionConfiguration
* @attribute
*/
public readonly encryptionConfiguration?: EncryptionConfiguration;

/**
* Identifier for the state machine revision, which is an immutable, read-only snapshot of a state machine’s definition and configuration.
* @attribute
Expand Down Expand Up @@ -460,11 +500,12 @@ export class StateMachine extends StateMachineBase {
tracingConfiguration: props.tracingEnabled ? this.buildTracingConfiguration() : undefined,
...definitionBody.bind(this, this.role, props, graph),
definitionSubstitutions: props.definitionSubstitutions,
encryptionConfiguration: props.encryptionConfiguration,
VaidSaraswat marked this conversation as resolved.
Show resolved Hide resolved
});
resource.applyRemovalPolicy(props.removalPolicy, { default: RemovalPolicy.DESTROY });

resource.node.addDependency(this.role);

this.encryptionConfiguration = props.encryptionConfiguration;
this.stateMachineName = this.getResourceNameAttribute(resource.attrName);
this.stateMachineArn = this.getResourceArnAttribute(resource.ref, {
service: 'states',
Expand Down Expand Up @@ -561,6 +602,13 @@ export interface IStateMachine extends IResource, iam.IGrantable {
*/
readonly stateMachineArn: string;

/**
* The EncryptioConfiguration of the activity
*
* @attribute
*/
readonly encryptionConfiguration?: EncryptionConfiguration;

/**
* Grant the given identity permissions to start an execution of this state
* machine.
Expand Down
49 changes: 49 additions & 0 deletions packages/aws-cdk-lib/aws-stepfunctions/test/activity.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { Match, Template } from '../../assertions';
import * as iam from '../../aws-iam';
import * as kms from '../../aws-kms';
import * as cdk from '../../core';
import * as stepfunctions from '../lib';
import { EncryptionType } from '../lib/encryption-configuration';

describe('Activity', () => {
test('instantiate Activity', () => {
Expand Down Expand Up @@ -70,4 +72,51 @@ describe('Activity', () => {
});

});

VaidSaraswat marked this conversation as resolved.
Show resolved Hide resolved
test('instantiate Activity with EncryptionConfiguration using Customer Managed Key', () => {
// GIVEN
const stack = new cdk.Stack();
const kmsKey = new kms.Key(stack, 'Key');

// WHEN
new stepfunctions.Activity(stack, 'Activity', {
encryptionConfiguration: {
kmsKeyId: kmsKey.keyId,
kmsDataKeyReusePeriodSeconds: 75,
type: EncryptionType.CUSTOMER_MANAGED_KMS_KEY,
},
});

// THEN
Template.fromStack(stack).hasResourceProperties('AWS::StepFunctions::Activity', {
Name: 'Activity',
EncryptionConfiguration: Match.objectLike({
KmsKeyId: {
Ref: 'Key961B73FD',
},
KmsDataKeyReusePeriodSeconds: 75,
Type: EncryptionType.CUSTOMER_MANAGED_KMS_KEY,
}),
});
});

test('instantiate Activity with EncryptionConfiguration using AWS Owned Key', () => {
// GIVEN
const stack = new cdk.Stack();

// WHEN
new stepfunctions.Activity(stack, 'Activity', {
encryptionConfiguration: {
type: EncryptionType.AWS_OWNED_KEY,
},
});

// THEN
Template.fromStack(stack).hasResourceProperties('AWS::StepFunctions::Activity', {
Name: 'Activity',
EncryptionConfiguration: Match.objectLike({
Type: EncryptionType.AWS_OWNED_KEY,
}),
});
});
});
VaidSaraswat marked this conversation as resolved.
Show resolved Hide resolved
Loading
Loading