Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
added logS3AccessLogs and updated tests
Browse files Browse the repository at this point in the history
mickychetta committed Nov 8, 2021
1 parent 85b5f7a commit a805d51
Showing 13 changed files with 94 additions and 206 deletions.
Original file line number Diff line number Diff line change
@@ -61,6 +61,7 @@ _Parameters_
|deployVpc?|`boolean`|Whether to create a new VPC based on `vpcProps` into which to deploy this pattern. Setting this to true will deploy the minimal, most private VPC to run the pattern:<ul><li> One isolated subnet in each Availability Zone used by the CDK program</li><li>`enableDnsHostnames` and `enableDnsSupport` will both be set to true</li></ul>If this property is `true` then `existingVpc` cannot be specified. Defaults to `false`.|
|bucketEnvironmentVariableName?|`string`|Optional name for the S3 bucket environment variable set for the Lambda function.|
|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.|
|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|

## Pattern Properties

@@ -70,6 +71,7 @@ _Parameters_
|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 pattern.|
|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.|
|vpc?|[`ec2.IVpc`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-ec2.IVpc.html)|Returns an interface on the VPC used by the pattern (if any). This may be a VPC created by the pattern or the VPC supplied to the pattern constructor.|
|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|

## Default settings

Original file line number Diff line number Diff line change
@@ -80,6 +80,13 @@ export interface LambdaToS3Props {
* @default - Default props are used
*/
readonly loggingBucketProps?: s3.BucketProps
/**
* Whether to turn on Access Logs for the S3 bucket with the associated storage costs.
* Enabling Access Logging is a best practice.
*
* @default - true
*/
readonly logS3AccessLogs?: boolean;
}

/**
@@ -90,6 +97,7 @@ export class LambdaToS3 extends Construct {
public readonly s3Bucket?: s3.Bucket;
public readonly s3LoggingBucket?: s3.Bucket;
public readonly vpc?: ec2.IVpc;
public readonly s3BucketInterface: s3.IBucket;

/**
* @summary Constructs a new instance of the LambdaToS3 class.
@@ -105,15 +113,7 @@ export class LambdaToS3 extends Construct {

let bucket: s3.IBucket;

if (props.existingBucketObj && props.bucketProps) {
throw new Error('Cannot specify both bucket properties and an existing bucket');
}

if (props.deployVpc || props.existingVpc) {
if (props.deployVpc && props.existingVpc) {
throw new Error("More than 1 VPC specified in the properties");
}

this.vpc = defaults.buildVpc(scope, {
defaultVpcProps: defaults.DefaultIsolatedVpcProps(),
existingVpc: props.existingVpc,
@@ -138,13 +138,16 @@ export class LambdaToS3 extends Construct {
if (!props.existingBucketObj) {
[this.s3Bucket, this.s3LoggingBucket] = defaults.buildS3Bucket(this, {
bucketProps: props.bucketProps,
loggingBucketProps: props.loggingBucketProps
loggingBucketProps: props.loggingBucketProps,
logS3AccessLogs: props.logS3AccessLogs
});
bucket = this.s3Bucket;
} else {
bucket = props.existingBucketObj;
}

this.s3BucketInterface = bucket;

// Configure environment variables
const bucketEnvironmentVariableName = props.bucketEnvironmentVariableName || 'S3_BUCKET_NAME';
this.lambdaFunction.addEnvironment(bucketEnvironmentVariableName, bucket.bucketName);
Original file line number Diff line number Diff line change
@@ -146,7 +146,7 @@
}
},
"Handler": "index.handler",
"Runtime": "nodejs10.x",
"Runtime": "nodejs14.x",
"TracingConfig": {
"Mode": "Active"
}
Original file line number Diff line number Diff line change
@@ -25,7 +25,7 @@ const stack = new Stack(app, generateIntegStackName(__filename));

new LambdaToS3(stack, 'test-lambda-s3', {
lambdaFunctionProps: {
runtime: lambda.Runtime.NODEJS_10_X,
runtime: lambda.Runtime.NODEJS_14_X,
handler: 'index.handler',
code: lambda.Code.fromAsset(`${__dirname}/lambda`)
},
Original file line number Diff line number Diff line change
@@ -147,7 +147,7 @@
}
},
"Handler": "index.handler",
"Runtime": "nodejs10.x",
"Runtime": "nodejs14.x",
"TracingConfig": {
"Mode": "Active"
}
@@ -175,90 +175,6 @@
}
}
},
"testlambdas3S3LoggingBucketD42FC73D": {
"Type": "AWS::S3::Bucket",
"Properties": {
"AccessControl": "LogDeliveryWrite",
"BucketEncryption": {
"ServerSideEncryptionConfiguration": [
{
"ServerSideEncryptionByDefault": {
"SSEAlgorithm": "AES256"
}
}
]
},
"PublicAccessBlockConfiguration": {
"BlockPublicAcls": true,
"BlockPublicPolicy": true,
"IgnorePublicAcls": true,
"RestrictPublicBuckets": true
},
"VersioningConfiguration": {
"Status": "Enabled"
}
},
"UpdateReplacePolicy": "Delete",
"DeletionPolicy": "Delete",
"Metadata": {
"cfn_nag": {
"rules_to_suppress": [
{
"id": "W35",
"reason": "This S3 bucket is used as the access logging bucket for another bucket"
}
]
}
}
},
"testlambdas3S3LoggingBucketPolicyCEAFB213": {
"Type": "AWS::S3::BucketPolicy",
"Properties": {
"Bucket": {
"Ref": "testlambdas3S3LoggingBucketD42FC73D"
},
"PolicyDocument": {
"Statement": [
{
"Action": "*",
"Condition": {
"Bool": {
"aws:SecureTransport": "false"
}
},
"Effect": "Deny",
"Principal": {
"AWS": "*"
},
"Resource": [
{
"Fn::Join": [
"",
[
{
"Fn::GetAtt": [
"testlambdas3S3LoggingBucketD42FC73D",
"Arn"
]
},
"/*"
]
]
},
{
"Fn::GetAtt": [
"testlambdas3S3LoggingBucketD42FC73D",
"Arn"
]
}
],
"Sid": "HttpsOnly"
}
],
"Version": "2012-10-17"
}
}
},
"testlambdas3S3Bucket179A52E6": {
"Type": "AWS::S3::Bucket",
"Properties": {
@@ -284,11 +200,6 @@
}
]
},
"LoggingConfiguration": {
"DestinationBucketName": {
"Ref": "testlambdas3S3LoggingBucketD42FC73D"
}
},
"PublicAccessBlockConfiguration": {
"BlockPublicAcls": true,
"BlockPublicPolicy": true,
@@ -300,7 +211,17 @@
}
},
"UpdateReplacePolicy": "Delete",
"DeletionPolicy": "Delete"
"DeletionPolicy": "Delete",
"Metadata": {
"cfn_nag": {
"rules_to_suppress": [
{
"id": "W35",
"reason": "This S3 bucket is created for unit/ integration testing purposes only."
}
]
}
}
},
"testlambdas3S3BucketPolicyE899B211": {
"Type": "AWS::S3::BucketPolicy",
Original file line number Diff line number Diff line change
@@ -16,6 +16,8 @@ import { App, Stack, RemovalPolicy } from "@aws-cdk/core";
import { LambdaToS3, LambdaToS3Props } from "../lib";
import * as lambda from '@aws-cdk/aws-lambda';
import { generateIntegStackName } from '@aws-solutions-constructs/core';
import * as s3 from "@aws-cdk/aws-s3";
import * as defaults from '@aws-solutions-constructs/core';

// Setup
const app = new App();
@@ -25,16 +27,24 @@ stack.templateOptions.description = 'Integration Test for aws-lambda-s3';
// Definitions
const props: LambdaToS3Props = {
lambdaFunctionProps: {
runtime: lambda.Runtime.NODEJS_10_X,
runtime: lambda.Runtime.NODEJS_14_X,
handler: 'index.handler',
code: lambda.Code.fromAsset(`${__dirname}/lambda`)
},
bucketProps: {
removalPolicy: RemovalPolicy.DESTROY,
}
},
logS3AccessLogs: false
};

new LambdaToS3(stack, 'test-lambda-s3', props);
const construct = new LambdaToS3(stack, 'test-lambda-s3', props);

const s3Bucket = construct.s3Bucket as s3.Bucket;

defaults.addCfnSuppressRules(s3Bucket, [
{ id: 'W35',
reason: 'This S3 bucket is created for unit/ integration testing purposes only.' },
]);

// Synth
app.synth();
Original file line number Diff line number Diff line change
@@ -188,7 +188,7 @@
}
},
"Handler": "index.handler",
"Runtime": "nodejs10.x",
"Runtime": "nodejs14.x",
"TracingConfig": {
"Mode": "Active"
},
@@ -237,90 +237,6 @@
}
}
},
"testlambdas3S3LoggingBucketD42FC73D": {
"Type": "AWS::S3::Bucket",
"Properties": {
"AccessControl": "LogDeliveryWrite",
"BucketEncryption": {
"ServerSideEncryptionConfiguration": [
{
"ServerSideEncryptionByDefault": {
"SSEAlgorithm": "AES256"
}
}
]
},
"PublicAccessBlockConfiguration": {
"BlockPublicAcls": true,
"BlockPublicPolicy": true,
"IgnorePublicAcls": true,
"RestrictPublicBuckets": true
},
"VersioningConfiguration": {
"Status": "Enabled"
}
},
"UpdateReplacePolicy": "Delete",
"DeletionPolicy": "Delete",
"Metadata": {
"cfn_nag": {
"rules_to_suppress": [
{
"id": "W35",
"reason": "This S3 bucket is used as the access logging bucket for another bucket"
}
]
}
}
},
"testlambdas3S3LoggingBucketPolicyCEAFB213": {
"Type": "AWS::S3::BucketPolicy",
"Properties": {
"Bucket": {
"Ref": "testlambdas3S3LoggingBucketD42FC73D"
},
"PolicyDocument": {
"Statement": [
{
"Action": "*",
"Condition": {
"Bool": {
"aws:SecureTransport": "false"
}
},
"Effect": "Deny",
"Principal": {
"AWS": "*"
},
"Resource": [
{
"Fn::Join": [
"",
[
{
"Fn::GetAtt": [
"testlambdas3S3LoggingBucketD42FC73D",
"Arn"
]
},
"/*"
]
]
},
{
"Fn::GetAtt": [
"testlambdas3S3LoggingBucketD42FC73D",
"Arn"
]
}
],
"Sid": "HttpsOnly"
}
],
"Version": "2012-10-17"
}
}
},
"testlambdas3S3Bucket179A52E6": {
"Type": "AWS::S3::Bucket",
"Properties": {
@@ -346,11 +262,6 @@
}
]
},
"LoggingConfiguration": {
"DestinationBucketName": {
"Ref": "testlambdas3S3LoggingBucketD42FC73D"
}
},
"PublicAccessBlockConfiguration": {
"BlockPublicAcls": true,
"BlockPublicPolicy": true,
@@ -362,7 +273,17 @@
}
},
"UpdateReplacePolicy": "Delete",
"DeletionPolicy": "Delete"
"DeletionPolicy": "Delete",
"Metadata": {
"cfn_nag": {
"rules_to_suppress": [
{
"id": "W35",
"reason": "This S3 bucket is created for unit/ integration testing purposes only."
}
]
}
}
},
"testlambdas3S3BucketPolicyE899B211": {
"Type": "AWS::S3::BucketPolicy",
Original file line number Diff line number Diff line change
@@ -21,21 +21,31 @@ import { generateIntegStackName } from '@aws-solutions-constructs/core';
const app = new App();
const stack = new Stack(app, generateIntegStackName(__filename));
stack.templateOptions.description = "Integration Test for aws-lambda-s3";
import * as s3 from "@aws-cdk/aws-s3";
import * as defaults from '@aws-solutions-constructs/core';

// Definitions
const props: LambdaToS3Props = {
lambdaFunctionProps: {
runtime: lambda.Runtime.NODEJS_10_X,
runtime: lambda.Runtime.NODEJS_14_X,
handler: "index.handler",
code: lambda.Code.fromAsset(`${__dirname}/lambda`),
},
deployVpc: true,
bucketProps: {
removalPolicy: RemovalPolicy.DESTROY,
}
},
logS3AccessLogs: false
};

new LambdaToS3(stack, "test-lambda-s3", props);
const construct = new LambdaToS3(stack, "test-lambda-s3", props);

const s3Bucket = construct.s3Bucket as s3.Bucket;

defaults.addCfnSuppressRules(s3Bucket, [
{ id: 'W35',
reason: 'This S3 bucket is created for unit/ integration testing purposes only.' },
]);

// Synth
app.synth();
Original file line number Diff line number Diff line change
@@ -147,7 +147,7 @@
}
},
"Handler": "index.handler",
"Runtime": "nodejs10.x",
"Runtime": "nodejs14.x",
"TracingConfig": {
"Mode": "Active"
}
Original file line number Diff line number Diff line change
@@ -25,7 +25,7 @@ stack.templateOptions.description = 'Integration Test for aws-lambda-s3';

// Definitions
const lambdaFunctionProps = {
runtime: lambda.Runtime.NODEJS_10_X,
runtime: lambda.Runtime.NODEJS_14_X,
handler: 'index.handler',
code: lambda.Code.fromAsset(`${__dirname}/lambda`)
};
Original file line number Diff line number Diff line change
@@ -195,7 +195,7 @@
}
},
"Handler": "index.handler",
"Runtime": "nodejs10.x",
"Runtime": "nodejs14.x",
"TracingConfig": {
"Mode": "Active"
}
Original file line number Diff line number Diff line change
@@ -30,10 +30,10 @@ const mybucket: s3.IBucket = s3.Bucket.fromBucketName(stack, 'mybucket', existin
const props: LambdaToS3Props = {
existingBucketObj: mybucket,
lambdaFunctionProps: {
runtime: lambda.Runtime.NODEJS_10_X,
runtime: lambda.Runtime.NODEJS_14_X,
handler: 'index.handler',
code: lambda.Code.fromAsset(`${__dirname}/lambda`)
},
}
};

new LambdaToS3(stack, 'test-lambda-s3-pre-existing-bucket', props);
Original file line number Diff line number Diff line change
@@ -33,7 +33,7 @@ test('Test the properties', () => {
handler: 'index.handler',
code: lambda.Code.fromAsset(`${__dirname}/lambda`)
},
bucketPermissions: ['Write']
bucketPermissions: ['Write', 'Delete', 'Put', 'Read', 'ReadWrite']
});
// Assertion 1
const func = pattern.lambdaFunction;
@@ -273,7 +273,7 @@ test("Test bad call with existingVpc and deployVpc", () => {
});
};
// Assertion
expect(app).toThrowError();
expect(app).toThrowError('Error - Either provide an existingVpc or some combination of deployVpc and vpcProps, but not both.\n');
});

// --------------------------------------------------------------
@@ -402,4 +402,25 @@ test('s3 bucket with bucket, loggingBucket, and auto delete objects', () => {
Ref: "lambdas3S3LoggingBucket498F3BDD"
}
});
});

// --------------------------------------------------------------
// s3 bucket with one content bucket and no logging bucket
// --------------------------------------------------------------
test('s3 bucket with one content bucket and no logging bucket', () => {
const stack = new Stack();

new LambdaToS3(stack, 'lambda-s3', {
lambdaFunctionProps: {
code: lambda.Code.fromAsset(`${__dirname}/lambda`),
runtime: lambda.Runtime.NODEJS_12_X,
handler: 'index.handler'
},
bucketProps: {
removalPolicy: RemovalPolicy.DESTROY,
},
logS3AccessLogs: false
});

expect(stack).toCountResources("AWS::S3::Bucket", 1);
});

0 comments on commit a805d51

Please sign in to comment.