aws-cdk
aws-cdk copied to clipboard
feat(stepfunctions): add support for EncryptionConfiguration
Reason for this change
Allow customers to specify a customer managed KMS key and data key reuse period to encrypt state machine definition and execution history and activity inputs. The underlying AWS::StepFunctions::StateMachine and AWS::StepFunctions::Activity resources currently expose this through an optional EncryptionConfiguration property.
Description of changes
Activity and StateMachine accept two new fields in their respective props:
kmsKey:
- Type:
IKey - Description: Symmetric customer managed KMS key for server-side encryption of the state machine definition and execution history (when provided in StateMachine Props), and Activity Inputs (when provided in Activity Props)
- Default:
undefined
kmsDataKeyReusePeriodSeconds:
- Type:
Duration - Description: Maximum duration that Step Functions will reuse customer managed data keys. When the period expires, Step Functions will call
GenerateDataKey. Can only provide ifkmskeyis set. Must be a value between 60 and 900 seconds. - Default: 300 sec
Permission Changes
Activity:
- When the customer provides
kmsKey?the key policy will be updated with the following policy statement:
{
"Effect": "Allow",
"Principal": {
"Service": "states.amazonaws.com"
},
"Action": [
"kms:Decrypt",
"kms:GenerateDataKey"
],
"Resource": "*",
"Condition": {
"StringEquals": {
"kms:EncryptionContext:aws:states:activityArn": "arn:aws:states:<region><account_id>:activity:<activity_name>"
}
}
}
StateMachine:
- When the customer provides
kmsKey?the key policy will be updated with the following policy statement:
{
"Effect": "Allow",
"Principal": {
"Service": "states.amazonaws.com"
},
"Action": [
"kms:Decrypt",
"kms:GenerateDataKey"
],
"Resource": "*",
"Condition": {
"StringEquals": {
"kms:EncryptionContext:aws:states:stateMachineArn": "arn:aws:states:<region><account_id>:stateMachine:<statemachine_name>"
}
}
}
- If the state machine contains an activity which uses KMS encryption, the state machine execution role will be updated with the following permissions
{
"Effect": "Allow",
"Principal": {
"Service": "states.amazonaws.com"
},
"Action": [
"kms:Decrypt",
"kms:GenerateDataKey"
],
"Resource": "<activity_kmskey_arn>",
}
- Customers have the option to encrypt data sent to CloudWatch Logs. To support this, if the customer provides both the
kmsKey?andlogs?prop, the following key policy statement will be added to the key used by the StateMachine:
{
"Effect": "Allow",
"Principal": {
"Service": "delivery.logs.amazonaws.com"
},
"Action": [
"kms:Decrypt",
]
}
In addition the execution role will be updated to include a separate policy that includes kms actions and encryption context for logging (otherwise customer will not see logs)
{
"Effect": "Allow",
"Action": [
"kms:GenerateDataKey"
],
"Resource": "<state_machine_kms_key_arn>",
"Condition": {
"StringEquals": {
"kms:EncryptionContext:SourceArn": "arn:aws:logs:<region><account_id>:*"
}
}
}
Description of how you validated changes
Unit Test (scenarios):
-
Activity
- Creating an Activity with a KMS Key and without specifying kmsDataKeyReusePeriodSeconds defaults to 300 secs
- Creating an Activity with a KMS key and invalid
kmsDataKeyReusePeriodSecondsthrows a validation error - Creating an Activity with no KMS Key and specifying
kmsDataKeyReusePeriodSecondsthrows a validation error - Creating an Activity with a KMS Key results in the correct KMS key policy being generated which allows only the Activity to perform
'kms:Decrypt','kms:GenerateDataKey'actions on the associated KMS key.
-
StateMachine
- Creating a State Machine with a KMS Key and without specifying kmsDataKeyReusePeriodSeconds defaults to 300 secs
- Creating a State Machine with a KMS key and invalid
kmsDataKeyReusePeriodSecondsthrows a validation error - Creating a State Machine with no KMS Key and specifying
kmsDataKeyReusePeriodSecondsthrows a validation error - Creating a State Machine with a KMS Key allows only StateMachine execution role to perform
'kms:Decrypt','kms:GenerateDataKey'actions on the key. - Creating a State Machine with
logs?andkmsKey?:- Separate IAM policy statement (using encryption context for logging) being generated for the State Machine execution role
- KMS key policy statement which enables log service delivery for integrations
- Creating a State Machine which invokes an Activity using KMS encryption results in a IAM policy generated which allows the execution role to perform
'kms:Decrypt','kms:GenerateDataKey'actions on the Activity KMS key
Integration tests
- Create a State Machine and Activity which both have encryption enabled and assert the activity input is correct when calling
getActivityTaskAPI - Create a State Machine with encryption and logging enabled. Ensure decrypted logs are being pushed to the log group.
Code samples
-
Creating an Activity with Encryption using a Customer Managed Key
const kmsKey = new kms.Key(this, 'Key');
const activity = new sfn.Activity(this, 'ActivityWithCMKEncryptionConfiguration', {
activityName: 'ActivityWithCMKEncryptionConfiguration',
kmsKey: kmsKey,
kmsDataKeyReusePeriodSeconds: cdk.Duration.seconds(75),
});
-
Creating a StateMachine with Encryption using a Customer Managed Key
const kmsKey = new kms.Key(this, 'Key');
const stateMachine = new sfn.StateMachine(this, 'StateMachineWithCMKEncryptionConfiguration', {
stateMachineName: 'StateMachineWithCMKEncryptionConfiguration',
definitionBody: sfn.DefinitionBody.fromChainable(sfn.Chain.start(new sfn.Pass(this, 'Pass'))),
stateMachineType: sfn.StateMachineType.STANDARD,
kmsKey: kmsKey,
kmsDataKeyReusePeriodSeconds: cdk.Duration.seconds(60),
});
-
Creating a StateMachine with CWL Encryption using a Customer Managed Key
const stateMachineKmsKey = new kms.Key(this, 'StateMachine Key');
const logGroupKey = new kms.Key(this, 'LogGroup Key');
// To enable encrypted CloudWatch log integration for a state machine, you must add the following to your log group key policy
logGroupKey.addToResourcePolicy(new cdk.aws_iam.PolicyStatement({
resources: ['*'],
actions: ['kms:Encrypt*', 'kms:Decrypt*', 'kms:ReEncrypt*', 'kms:GenerateDataKey*', 'kms:Describe*'],
principals: [new cdk.aws_iam.ServicePrincipal(`logs.${cdk.Stack.of(this).region}.amazonaws.com`)],
conditions: {
ArnEquals: {
'kms:EncryptionContext:aws:logs:arn': cdk.Stack.of(this).formatArn({
service: 'logs',
resource: 'log-group',
sep: ':',
resourceName: '/aws/vendedlogs/states/MyLogGroup',
}),
},
},
}));
const logGroup = new logs.LogGroup(this, 'MyLogGroup', {
logGroupName: '/aws/vendedlogs/states/MyLogGroup',
encryptionKey: logGroupKey,
});
const stateMachine = new sfn.StateMachine(this, 'StateMachineWithCMKWithCWLEncryption', {
stateMachineName: 'StateMachineWithCMKWithCWLEncryption',
definitionBody: sfn.DefinitionBody.fromChainable(sfn.Chain.start(new sfn.Pass(this, 'PassState', {
result: sfn.Result.fromString('Hello World'),
}))),
stateMachineType: sfn.StateMachineType.STANDARD,
kmsKey: stateMachineKmsKey,
kmsDataKeyReusePeriodSeconds: cdk.Duration.seconds(300),
logs: {
destination: logGroup,
level: sfn.LogLevel.ALL,
includeExecutionData: true,
},
});
Checklist
- [X] My code adheres to the CONTRIBUTING GUIDE and DESIGN GUIDELINES
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license
Can you describe how the StateMachine and Activity constructs are actually being changed in the Description of changes section of the PR description?
Perhaps an example of these properties in use as well.
This PR has been in the CHANGES REQUESTED state for 3 weeks, and looks abandoned. To keep this PR from being closed, please continue work on it. If not, it will automatically be closed in a week.
@Mergifyio update
update
☑️ Nothing to do
- [ ]
#commits-behind > 0[📌 update requirement] - [X]
-closed[📌 update requirement] - [X]
-conflict[📌 update requirement] - [X]
queue-position = -1[📌 update requirement]
AWS CodeBuild CI Report
- CodeBuild project: AutoBuildv2Project1C6BFA3F-wQm2hXv2jqQv
- Commit ID: 17641e4e91c86af8e1d8faa8be47d6fddda070cb
- Result: SUCCEEDED
- Build Logs (available for 30 days)
Powered by github-codebuild-logs, available on the AWS Serverless Application Repository
Thank you for contributing! Your pull request will be updated from main and then merged automatically (do not update manually, and be sure to allow changes to be pushed to your fork).
Comments on closed issues and PRs are hard for our team to see. If you need help, please open a new issue that references this one.