Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 0 additions & 1 deletion examples/basic-usage.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#!/usr/bin/env node
import 'source-map-support/register';
import { App, Stack } from 'aws-cdk-lib';

import { SecureBucket, SecurityLevel } from '../src';
Expand Down
1 change: 0 additions & 1 deletion examples/blueprints-usage.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#!/usr/bin/env node
import 'source-map-support/register';
import { App, Stack, PropertyInjectors } from 'aws-cdk-lib';
import { Bucket } from 'aws-cdk-lib/aws-s3';

Expand Down
20 changes: 20 additions & 0 deletions src/resources/s3-bucket/secure-bucket.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,26 @@ export class SecureBucket extends Construct {
/** The underlying hardened bucket. */
public readonly bucket: Bucket;

/** The bucket's ARN. Convenience pass-through for `this.bucket.bucketArn`. */
public get bucketArn(): string {
return this.bucket.bucketArn;
}

/** The bucket's name. Convenience pass-through for `this.bucket.bucketName`. */
public get bucketName(): string {
return this.bucket.bucketName;
}

/** The bucket's domain name. Convenience pass-through for `this.bucket.bucketDomainName`. */
public get bucketDomainName(): string {
return this.bucket.bucketDomainName;
}

/** The bucket's regional domain name. Convenience pass-through for `this.bucket.bucketRegionalDomainName`. */
public get bucketRegionalDomainName(): string {
return this.bucket.bucketRegionalDomainName;
}

constructor(scope: Construct, id: string, props: SecureBucketProps = {}) {
super(scope, id);

Expand Down
23 changes: 23 additions & 0 deletions test/resources/s3-bucket/secure-bucket.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
});

describe('default configuration (HIGH)', () => {
it('should create a bucket with CIS-critical settings enforced', () => {

Check warning on line 15 in test/resources/s3-bucket/secure-bucket.test.ts

View workflow job for this annotation

GitHub Actions / Lint & format

Test has no assertions
new SecureBucket(stack, 'TestBucket');

const template = Template.fromStack(stack);
Expand All @@ -35,7 +35,7 @@
});
});

it('should enforce SSL via a bucket policy', () => {

Check warning on line 38 in test/resources/s3-bucket/secure-bucket.test.ts

View workflow job for this annotation

GitHub Actions / Lint & format

Test has no assertions
new SecureBucket(stack, 'TestBucket');

const template = Template.fromStack(stack);
Expand Down Expand Up @@ -81,12 +81,12 @@
);
expect(mainBucket).toBeDefined();
// tier-variable: versioning off at LOW
expect(mainBucket!['Properties'].VersioningConfiguration).toBeUndefined();

Check warning on line 84 in test/resources/s3-bucket/secure-bucket.test.ts

View workflow job for this annotation

GitHub Actions / Lint & format

Forbidden non-null assertion
// CIS-critical: encryption still enforced at LOW
expect(mainBucket!['Properties'].BucketEncryption).toBeDefined();

Check warning on line 86 in test/resources/s3-bucket/secure-bucket.test.ts

View workflow job for this annotation

GitHub Actions / Lint & format

Forbidden non-null assertion
});

it('LOW does not provision an access-log bucket', () => {

Check warning on line 89 in test/resources/s3-bucket/secure-bucket.test.ts

View workflow job for this annotation

GitHub Actions / Lint & format

Test has no assertions
new SecureBucket(stack, 'TestBucket', { securityLevel: SecurityLevel.LOW });

const template = Template.fromStack(stack);
Expand All @@ -95,7 +95,7 @@
});

describe('custom configuration', () => {
it('should allow overriding bucket name', () => {

Check warning on line 98 in test/resources/s3-bucket/secure-bucket.test.ts

View workflow job for this annotation

GitHub Actions / Lint & format

Test has no assertions
new SecureBucket(stack, 'TestBucket', { bucketName: 'my-custom-bucket-name' });

const template = Template.fromStack(stack);
Expand All @@ -111,7 +111,7 @@
b => b['Properties']?.OwnershipControls && !b['Properties']?.AccessControl
);
expect(mainBucket).toBeDefined();
expect(mainBucket!['Properties'].VersioningConfiguration).toBeUndefined();

Check warning on line 114 in test/resources/s3-bucket/secure-bucket.test.ts

View workflow job for this annotation

GitHub Actions / Lint & format

Forbidden non-null assertion
});

it('should not be able to disable encryption (CIS-critical)', () => {
Expand Down Expand Up @@ -184,4 +184,27 @@
expect(secureBucket.bucket.node.id).toBe('Bucket');
});
});

describe('attribute pass-through getters', () => {
it('exposes bucketArn and bucketName directly on the construct', () => {
const bucket = new SecureBucket(stack, 'TestBucket', {
bucketName: 'my-secure-bucket',
});

expect(bucket.bucketArn).toBeDefined();
expect(bucket.bucketArn).toBe(bucket.bucket.bucketArn);
expect(bucket.bucketName).toBe(bucket.bucket.bucketName);
expect(bucket.bucketDomainName).toBe(bucket.bucket.bucketDomainName);
expect(bucket.bucketRegionalDomainName).toBe(bucket.bucket.bucketRegionalDomainName);
});

it('resolves getters to the same values as the wrapped bucket', () => {
const bucket = new SecureBucket(stack, 'TestBucket', {
bucketName: 'direct-access',
});

expect(bucket.bucketArn).toBe(bucket.bucket.bucketArn);
expect(bucket.bucketName).toBe(bucket.bucket.bucketName);
});
});
});
Loading