Skip to content

Commit 639f473

Browse files
authored
feat(s3-stepfunctions): removed CloudTrail dependency after new S3 feature (#529)
* enabled eventbridge in bucket creation * updated README * empty commit * updated README and readded deploy CloudTrail * fixed eslint errors * updated README doc by removing properties and improvinng notes * updated README and enabled eventbridge in bucket test * enabled eventbridge in bucket for pre-existing tests * updated pre-existing-bucket test
1 parent f0fe619 commit 639f473

20 files changed

+123
-231
lines changed

Diff for: source/patterns/@aws-solutions-constructs/aws-s3-step-function/README.md

+16-10
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@
2222

2323
This AWS Solutions Construct implements an Amazon S3 bucket connected to an AWS Step Function.
2424

25-
*Note - This construct uses Amazon EventBridge (Amazon CloudWatch Events) to trigger AWS Step Functions. EventBridge is more flexible, but triggering Step Functions with S3 Event Notifications has less latency and is more cost effective. If cost and/or latency is an issue, you should consider deploy aws-s3-lambda and aws-lambda-stepfunctions in place of this construct.*
25+
*Note - This constructs sends S3 Event Notification to EventBridge, then triggers AWS Step Functions State Machine executions from EventBridge.*
26+
27+
*An alternative architecture can be built that triggers a Lambda function from S3 Event notifications using aws-s3-lambda and aws-lambda-stepfunctions. Channelling the S3 events through Lambda is less flexible than EventBridge, but is more cost effective and has lower latency.*
2628

2729
Here is a minimal deployable pattern definition in Typescript:
2830

@@ -55,12 +57,12 @@ _Parameters_
5557

5658
| **Name** | **Type** | **Description** |
5759
|:-------------|:----------------|-----------------|
58-
|existingBucketObj?|[`s3.IBucket`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-s3.IBucket.html)|Existing instance of S3 Bucket object. If this is provided, then also providing bucketProps is an error. |
60+
|existingBucketObj?|[`s3.IBucket`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-s3.IBucket.html)|Existing instance of S3 Bucket object. The existing bucket must have [EventBridge enabled](https://docs.aws.amazon.com/AmazonS3/latest/userguide/enable-event-notifications-eventbridge.html) for this to work. If this is provided, then also providing bucketProps is an error. |
5961
|bucketProps?|[`s3.BucketProps`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-s3.BucketProps.html)|Optional user provided props to override the default props for the S3 Bucket.|
6062
|stateMachineProps|[`sfn.StateMachineProps`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-stepfunctions.StateMachineProps.html)|User provided props to override the default props for sfn.StateMachine|
6163
|eventRuleProps?|[`events.RuleProps`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-events.RuleProps.html)|Optional user provided eventRuleProps to override the defaults|
62-
|deployCloudTrail?|`boolean`|Whether to deploy a Trail in AWS CloudTrail to log API events in Amazon S3. Defaults to `true`.|
63-
|createCloudWatchAlarms|`boolean`|Whether to create recommended CloudWatch alarms|
64+
|deployCloudTrail?|`boolean`|Whether to deploy a Trail in AWS CloudTrail to log API events in Amazon S3. Defaults to `true`. <span style="color:red">**This is now deprecated and ignored because the construct no longer needs CloudTrail since it uses S3 Event Notifications**</span>.|
65+
|createCloudWatchAlarms|`boolean`|Whether to create recommended CloudWatch alarms.|
6466
|logGroupProps?|[`logs.LogGroupProps`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-logs.LogGroupProps.html)|User provided props to override the default props for for the CloudWatchLogs LogGroup.|
6567
|loggingBucketProps?|[`s3.BucketProps`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-s3.BucketProps.html)|Optional user provided props to override the default props for the S3 Logging Bucket.|
6668
|logS3AccessLogs?| boolean|Whether to turn on Access Logging for the S3 bucket. Creates an S3 bucket with associated storage costs for the logs. Enabling Access Logging is a best practice. default - true|
@@ -71,18 +73,22 @@ _Parameters_
7173
|:-------------|:----------------|-----------------|
7274
|stateMachine|[`sfn.StateMachine`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-stepfunctions.StateMachine.html)|Returns an instance of sfn.StateMachine created by the construct|
7375
|stateMachineLogGroup|[`logs.ILogGroup`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-logs.ILogGroup.html)|Returns an instance of the ILogGroup created by the construct for StateMachine|
74-
|cloudwatchAlarms?|[`cloudwatch.Alarm[]`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-cloudwatch.Alarm.html)|Returns a list of cloudwatch.Alarm created by the construct|
76+
|cloudwatchAlarms?|[`cloudwatch.Alarm[]`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-cloudwatch.Alarm.html)|Returns a list of cloudwatch.Alarm created by the construct.|
7577
|s3Bucket?|[`s3.Bucket`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-s3.Bucket.html)|Returns an instance of the s3.Bucket created by the construct|
7678
|s3LoggingBucket?|[`s3.Bucket`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-s3.Bucket.html)|Returns an instance of s3.Bucket created by the construct as the logging bucket for the primary bucket.|
77-
|cloudtrail|[`cloudtrail.Trail`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-cloudtrail.Trail.html)|Returns an instance of the cloudtrail.Trail created by the construct|
78-
|cloudtrailBucket|[`s3.Bucket`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-s3.Bucket.html)|Returns an instance of the s3.Bucket created by the construct for CloudTrail|
79-
|cloudtrailLoggingBucket|[`s3.Bucket`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-s3.Bucket.html)|Returns an instance of s3.Bucket created by the construct as the logging bucket for the primary CloudTrail bucket.|
8079
|s3BucketInterface|[`s3.IBucket`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-s3.IBucket.html)|Returns an instance of s3.IBucket created by the construct.|
80+
81+
*Note - with the release of Enable EventBridge for Amazon S3, AWS CloudTrail is no longer required to implement this construct. Because of this, the following properties have been removed:*
82+
- cloudtrail
83+
- cloudtrailBucket
84+
- cloudtrailLoggingBucket
85+
8186
## Default settings
8287

8388
Out of the box implementation of the Construct without any override will set the following defaults:
8489

8590
### Amazon S3 Bucket
91+
* Enable EventBridge to send events from the S3 Bucket
8692
* Configure Access logging for S3 Bucket
8793
* Enable server-side encryption for S3 Bucket using AWS managed KMS Key
8894
* Enforce encryption of data in transit
@@ -91,8 +97,8 @@ Out of the box implementation of the Construct without any override will set the
9197
* Retain the S3 Bucket when deleting the CloudFormation stack
9298
* Applies Lifecycle rule to move noncurrent object versions to Glacier storage after 90 days
9399

94-
### AWS CloudTrail
95-
* Configure a Trail in AWS CloudTrail to log API events in Amazon S3 related to the Bucket created by the Construct
100+
### AWS S3 Event Notification
101+
* Enable S3 to send events to EventBridge when an object is created.
96102

97103
### Amazon CloudWatch Events Rule
98104
* Grant least privilege permissions to CloudWatch Events to trigger the Lambda Function
Loading

Diff for: source/patterns/@aws-solutions-constructs/aws-s3-step-function/lib/index.ts

-7
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ import { S3ToStepfunctions } from '@aws-solutions-constructs/aws-s3-stepfunction
1717
// Note: To ensure CDKv2 compatibility, keep the import statement for Construct separate
1818
import { Construct } from '@aws-cdk/core';
1919
import * as cloudwatch from '@aws-cdk/aws-cloudwatch';
20-
import * as cloudtrail from '@aws-cdk/aws-cloudtrail';
2120
import * as events from '@aws-cdk/aws-events';
2221
import * as logs from '@aws-cdk/aws-logs';
2322

@@ -88,9 +87,6 @@ export class S3ToStepFunction extends Construct {
8887
public readonly s3Bucket?: s3.Bucket;
8988
public readonly s3LoggingBucket?: s3.Bucket;
9089
public readonly cloudwatchAlarms?: cloudwatch.Alarm[];
91-
public readonly cloudtrail?: cloudtrail.Trail;
92-
public readonly cloudtrailBucket?: s3.Bucket;
93-
public readonly cloudtrailLoggingBucket?: s3.Bucket;
9490
public readonly s3BucketInterface: s3.IBucket;
9591

9692
/**
@@ -115,9 +111,6 @@ export class S3ToStepFunction extends Construct {
115111
this.s3Bucket = wrappedConstruct.s3Bucket;
116112
this.s3LoggingBucket = wrappedConstruct.s3LoggingBucket;
117113
this.cloudwatchAlarms = wrappedConstruct.cloudwatchAlarms;
118-
this.cloudtrail = wrappedConstruct.cloudtrail;
119-
this.cloudtrailBucket = wrappedConstruct.cloudtrailBucket;
120-
this.cloudtrailLoggingBucket = wrappedConstruct.cloudtrailLoggingBucket;
121114
this.s3BucketInterface = wrappedConstruct.s3BucketInterface;
122115
}
123116
}

Diff for: source/patterns/@aws-solutions-constructs/aws-s3-step-function/test/integ.customLoggingBucket.expected.json

+8-11
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,11 @@
115115
"Ref": "tests3stepfunctiontests3stepfunctionWS3LoggingBucketB716417C"
116116
}
117117
},
118+
"NotificationConfiguration": {
119+
"EventBridgeConfiguration": {
120+
"EventBridgeEnabled": true
121+
}
122+
},
118123
"PublicAccessBlockConfiguration": {
119124
"BlockPublicAcls": true,
120125
"BlockPublicPolicy": true,
@@ -370,19 +375,11 @@
370375
"aws.s3"
371376
],
372377
"detail-type": [
373-
"AWS API Call via CloudTrail"
378+
"Object Created"
374379
],
375380
"detail": {
376-
"eventSource": [
377-
"s3.amazonaws.com"
378-
],
379-
"eventName": [
380-
"PutObject",
381-
"CopyObject",
382-
"CompleteMultipartUpload"
383-
],
384-
"requestParameters": {
385-
"bucketName": [
381+
"bucket": {
382+
"name": [
386383
{
387384
"Ref": "tests3stepfunctiontests3stepfunctionWS3Bucket9BE64924"
388385
}

Diff for: source/patterns/@aws-solutions-constructs/aws-s3-step-function/test/integ.customLoggingBucket.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ new S3ToStepFunction(stack, 'test-s3-step-function', {
4040
},
4141
logGroupProps: {
4242
removalPolicy: RemovalPolicy.DESTROY
43-
},
44-
deployCloudTrail: false
43+
}
4544
});
4645
app.synth();

Diff for: source/patterns/@aws-solutions-constructs/aws-s3-step-function/test/integ.pre-existing-bucket.expected.json

+8-11
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@
1212
}
1313
]
1414
},
15+
"NotificationConfiguration": {
16+
"EventBridgeConfiguration": {
17+
"EventBridgeEnabled": true
18+
}
19+
},
1520
"VersioningConfiguration": {
1621
"Status": "Enabled"
1722
}
@@ -231,19 +236,11 @@
231236
"aws.s3"
232237
],
233238
"detail-type": [
234-
"AWS API Call via CloudTrail"
239+
"Object Created"
235240
],
236241
"detail": {
237-
"eventSource": [
238-
"s3.amazonaws.com"
239-
],
240-
"eventName": [
241-
"PutObject",
242-
"CopyObject",
243-
"CompleteMultipartUpload"
244-
],
245-
"requestParameters": {
246-
"bucketName": [
242+
"bucket": {
243+
"name": [
247244
{
248245
"Ref": "existingScriptLocation845F3C51"
249246
}

Diff for: source/patterns/@aws-solutions-constructs/aws-s3-step-function/test/integ.pre-existing-bucket.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -23,19 +23,19 @@ const app = new App();
2323
const stack = new Stack(app, generateIntegStackName(__filename));
2424

2525
const existingBucket = CreateScrapBucket(stack, {});
26+
const cfnBucket = existingBucket.node.defaultChild as s3.CfnBucket;
27+
cfnBucket.addPropertyOverride('NotificationConfiguration.EventBridgeConfiguration.EventBridgeEnabled', true);
2628

27-
const mybucket: s3.IBucket = s3.Bucket.fromBucketName(stack, 'mybucket', existingBucket.bucketName);
2829
const startState = new stepfunctions.Pass(stack, 'StartState');
2930

3031
const props: S3ToStepFunctionProps = {
31-
existingBucketObj: mybucket,
32+
existingBucketObj: existingBucket,
3233
stateMachineProps: {
3334
definition: startState
3435
},
3536
logGroupProps: {
3637
removalPolicy: RemovalPolicy.DESTROY
37-
},
38-
deployCloudTrail: false
38+
}
3939
};
4040

4141
new S3ToStepFunction(stack, 'test-s3-step-function-pre-existing-bucket-construct', props);

Diff for: source/patterns/@aws-solutions-constructs/aws-s3-step-function/test/integ.s3-step-function-no-argument.expected.json

+8-11
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@
2525
}
2626
]
2727
},
28+
"NotificationConfiguration": {
29+
"EventBridgeConfiguration": {
30+
"EventBridgeEnabled": true
31+
}
32+
},
2833
"PublicAccessBlockConfiguration": {
2934
"BlockPublicAcls": true,
3035
"BlockPublicPolicy": true,
@@ -290,19 +295,11 @@
290295
"aws.s3"
291296
],
292297
"detail-type": [
293-
"AWS API Call via CloudTrail"
298+
"Object Created"
294299
],
295300
"detail": {
296-
"eventSource": [
297-
"s3.amazonaws.com"
298-
],
299-
"eventName": [
300-
"PutObject",
301-
"CopyObject",
302-
"CompleteMultipartUpload"
303-
],
304-
"requestParameters": {
305-
"bucketName": [
301+
"bucket": {
302+
"name": [
306303
{
307304
"Ref": "tests3stepfunctionconstructtests3stepfunctionconstructWS3Bucket474FE3A1"
308305
}

Diff for: source/patterns/@aws-solutions-constructs/aws-s3-step-function/test/integ.s3-step-function-no-argument.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,7 @@ const props: S3ToStepFunctionProps = {
3434
logGroupProps: {
3535
removalPolicy: RemovalPolicy.DESTROY
3636
},
37-
logS3AccessLogs: false,
38-
deployCloudTrail: false
37+
logS3AccessLogs: false
3938
};
4039

4140
const construct = new S3ToStepFunction(stack, 'test-s3-step-function-construct', props);

Diff for: source/patterns/@aws-solutions-constructs/aws-s3-step-function/test/s3-step-function.test.ts

+8-44
Original file line numberDiff line numberDiff line change
@@ -30,23 +30,6 @@ function deployNewStateMachine(stack: cdk.Stack) {
3030
return new S3ToStepFunction(stack, 'test-s3-step-function', props);
3131
}
3232

33-
test('check deployCloudTrail = false', () => {
34-
const stack = new cdk.Stack();
35-
36-
const startState = new sfn.Pass(stack, 'StartState');
37-
38-
const props: S3ToStepFunctionProps = {
39-
stateMachineProps: {
40-
definition: startState
41-
},
42-
deployCloudTrail: false
43-
};
44-
45-
const construct = new S3ToStepFunction(stack, 'test-s3-step-function', props);
46-
47-
expect(construct.cloudtrail === undefined);
48-
});
49-
5033
test('override eventRuleProps', () => {
5134
const stack = new cdk.Stack();
5235

@@ -61,18 +44,10 @@ test('override eventRuleProps', () => {
6144
eventRuleProps: {
6245
eventPattern: {
6346
source: ['aws.s3'],
64-
detailType: ['AWS API Call via CloudTrail'],
47+
detailType: ['Object Created'],
6548
detail: {
66-
eventSource: [
67-
"s3.amazonaws.com"
68-
],
69-
eventName: [
70-
"GetObject"
71-
],
72-
requestParameters: {
73-
bucketName: [
74-
mybucket.bucketName
75-
]
49+
bucket: {
50+
name: [mybucket.bucketName]
7651
}
7752
}
7853
}
@@ -87,20 +62,13 @@ test('override eventRuleProps', () => {
8762
"aws.s3"
8863
],
8964
"detail-type": [
90-
"AWS API Call via CloudTrail"
65+
"Object Created"
9166
],
9267
"detail": {
93-
eventSource: [
94-
"s3.amazonaws.com"
95-
],
96-
eventName: [
97-
"GetObject"
98-
],
99-
requestParameters: {
100-
bucketName: [
101-
{
102-
Ref: "mybucket160F8132"
103-
}
68+
bucket: {
69+
name: [{
70+
Ref: "mybucket160F8132"
71+
}
10472
]
10573
}
10674
}
@@ -128,15 +96,11 @@ test('check properties', () => {
12896

12997
const construct: S3ToStepFunction = deployNewStateMachine(stack);
13098

131-
expect(construct.cloudtrail !== null);
13299
expect(construct.stateMachine !== null);
133100
expect(construct.s3Bucket !== null);
134101
expect(construct.cloudwatchAlarms !== null);
135102
expect(construct.stateMachineLogGroup !== null);
136103
expect(construct.s3LoggingBucket !== null);
137-
expect(construct.cloudtrail !== null);
138-
expect(construct.cloudtrailBucket !== null);
139-
expect(construct.cloudtrailLoggingBucket !== null);
140104
});
141105

142106
// --------------------------------------------------------------

0 commit comments

Comments
 (0)