Skip to content

Latest commit

 

History

History
482 lines (342 loc) · 13.2 KB

File metadata and controls

482 lines (342 loc) · 13.2 KB

API Reference

Public API for aws-cdk-secure-constructs. Currently covers S3 only. Requires aws-cdk-lib >= 2.196.0.

Table of Contents

SecurityLevel

Operational security tier applied to tier-variable fields. CIS-critical settings are always enforced regardless of tier.

enum SecurityLevel {
  HIGH = 'high', // library default
  MEDIUM = 'medium',
  LOW = 'low',
}

SecurityLevels.strictest(a?, b?) returns the stronger of two tiers (defaulting to HIGH), implementing the tighten-only precedence rule.

SecureBucket

A secure S3 bucket construct that enforces security best practices by default.

Constructor

new SecureBucket(scope: Construct, id: string, props?: SecureBucketProps)

Properties

SecureBucketProps

Extends BucketProps with additional security-focused properties. CIS-critical settings (encryption, blockPublicAccess, enforceSSL, objectOwnership) are always enforced and any conflicting values supplied here are ignored.

Property Type Default Description
securityLevel SecurityLevel HIGH Operational tier for tier-variable fields
versioned boolean tier (true for HIGH/MEDIUM) Whether to enable versioning
enableAccessLogging boolean tier (true for HIGH/MEDIUM) Whether to provision an access-log bucket
lifecycleRules LifecycleRule[] Default cost optimization rules Lifecycle rules for the bucket
removalPolicy RemovalPolicy tier (RETAIN for HIGH) Removal policy for the bucket
enableEncryption boolean ignored Deprecated; encryption is always enforced (CIS-critical)

Methods

grantRead(grantee, objectsKeyPattern?)

Grants read permissions to the specified principal.

grantRead(grantee: IGrantable, objectsKeyPattern?: string): Grant

grantWrite(grantee, objectsKeyPattern?)

Grants write permissions to the specified principal.

grantWrite(grantee: IGrantable, objectsKeyPattern?: string): Grant

grantReadWrite(grantee, objectsKeyPattern?)

Grants read/write permissions to the specified principal.

grantReadWrite(grantee: IGrantable, objectsKeyPattern?: string): Grant

grantDelete(grantee, objectsKeyPattern?)

Grants delete permissions to the specified principal.

grantDelete(grantee: IGrantable, objectsKeyPattern?: string): Grant

Examples

Basic Usage

import { SecureBucket } from 'aws-cdk-secure-constructs';

const secureBucket = new SecureBucket(this, 'MySecureBucket', {
  bucketName: 'my-secure-bucket-name',
});

Custom Configuration

const customBucket = new SecureBucket(this, 'CustomBucket', {
  bucketName: 'my-custom-bucket',
  versioned: true,
  enableAccessLogging: true,
  lifecycleRules: [
    {
      id: 'custom-rule',
      enabled: true,
      expiration: { days: 30 },
    },
  ],
});

Granting Permissions

import { Role, ServicePrincipal } from 'aws-cdk-lib/aws-iam';

const lambdaRole = new Role(this, 'LambdaRole', {
  assumedBy: new ServicePrincipal('lambda.amazonaws.com'),
});

// Grant read access to Lambda function
secureBucket.grantRead(lambdaRole, 'data/*');

// Grant write access to specific prefix
secureBucket.grantWrite(lambdaRole, 'uploads/*');

SecureBucketDefaults

Property injector that applies secure defaults to all S3 buckets in the construct tree.

Constructor

new SecureBucketDefaults();

Properties

Property Type Description
constructUniqueId string The unique identifier for S3 bucket constructs

Methods

inject(originalProps, context)

Injects secure default properties into S3 bucket configurations.

inject(originalProps: BucketProps, context: InjectionContext): BucketProps

Applied Defaults

The following security defaults are applied:

  • Encryption: BucketEncryption.S3_MANAGED
  • Block Public Access: BlockPublicAccess.BLOCK_ALL
  • SSL Enforcement: true
  • Versioning: true
  • Object Ownership: 'BucketOwnerEnforced'
  • Intelligent Tiering: Enabled with default configuration

Examples

Basic Usage

import { App, PropertyInjectors } from 'aws-cdk-lib';
import { SecureBucketDefaults } from 'aws-cdk-secure-constructs';

const app = new App();
PropertyInjectors.of(app).add(new SecureBucketDefaults());

// All buckets created in this app will get secure defaults
const bucket = new Bucket(stack, 'MyBucket');

With Custom Overrides

PropertyInjectors.of(app).add(new SecureBucketDefaults());

// This bucket will have secure defaults but allow custom overrides
const bucket = new Bucket(stack, 'MyBucket', {
  versioned: false, // Override default versioning
  bucketName: 'my-custom-bucket',
});

StrictSecureBucketDefaults

Property injector that applies strict security defaults that cannot be overridden.

Constructor

new StrictSecureBucketDefaults();

Properties

Property Type Description
constructUniqueId string The unique identifier for S3 bucket constructs

Methods

inject(originalProps, context)

Injects strict security defaults that override any conflicting settings.

inject(originalProps: BucketProps, context: InjectionContext): BucketProps

Enforced Settings

The following security settings are enforced and cannot be overridden:

  • Encryption: BucketEncryption.S3_MANAGED
  • Block Public Access: BlockPublicAccess.BLOCK_ALL
  • SSL Enforcement: true
  • Object Ownership: 'BucketOwnerEnforced'

Examples

Basic Usage

import { App, PropertyInjectors } from 'aws-cdk-lib';
import { StrictSecureBucketDefaults } from 'aws-cdk-secure-constructs';

const app = new App();
PropertyInjectors.of(app).add(new StrictSecureBucketDefaults());

// All buckets will have strict security settings enforced
const bucket = new Bucket(stack, 'MyBucket');

Attempting Override (Will Be Ignored)

PropertyInjectors.of(app).add(new StrictSecureBucketDefaults());

// These settings will be ignored due to strict enforcement
const bucket = new Bucket(stack, 'MyBucket', {
  enforceSSL: false, // Will be overridden to true
  blockPublicAccess: BlockPublicAccess.BLOCK_ACLS, // Will be overridden to BLOCK_ALL
});

TieredSecureBucketDefaults

Tier-aware, tighten-only property injector. Applies the chosen SecurityLevel to tier-variable fields using a field-level "secure-max" merge (it can only tighten, never loosen incoming values) and always re-asserts the CIS-critical settings - so buckets stay CIS-compliant at every tier.

Constructor

new TieredSecureBucketDefaults(options?: TieredSecureBucketOptions)

interface TieredSecureBucketOptions {
  readonly securityLevel?: SecurityLevel; // default HIGH
}

Behaviour

  • Tier-variable fields (versioned, removalPolicy) are set to the strictest of the tier default and any incoming value.
  • CIS-critical fields (encryption, blockPublicAccess, enforceSSL, objectOwnership) are always enforced.
  • Combined with SecureBucket, the effective tier is strictest(constructTier, injectorTier) - the injector is an org-wide floor.

Example

import { PropertyInjectors } from 'aws-cdk-lib';
import { TieredSecureBucketDefaults, SecurityLevel } from 'aws-cdk-secure-constructs';

PropertyInjectors.of(app).add(
  new TieredSecureBucketDefaults({ securityLevel: SecurityLevel.MEDIUM })
);

// Even with weaker requests, CIS-critical settings are enforced and tier
// defaults are applied (tighten-only).
new Bucket(stack, 'MyBucket', { enforceSSL: false, versioned: false });

Compliance reporting

Each resource exposes a CIS compliance report; ComplianceRegistry aggregates all exposed resources.

import { S3BucketCompliance, ComplianceRegistry, ControlStatus } from 'aws-cdk-secure-constructs';

const s3Report = S3BucketCompliance.report();
const allReports = ComplianceRegistry.all();

const enforced = s3Report.controls.filter(c => c.status === ControlStatus.ENFORCED);

Every ENFORCED control is backed by a synthesis test (see test/resources/s3-bucket/compliance.test.ts) so the report cannot claim a control that the code does not actually enforce.

Type Definitions

SecureBucketProps

interface SecureBucketProps extends BucketProps {
  readonly securityLevel?: SecurityLevel;
  readonly enableAccessLogging?: boolean;
  /** @deprecated Encryption is always enforced (CIS-critical); has no effect. */
  readonly enableEncryption?: boolean;
}

Note: the interface extends BucketProps directly (no Omit) to remain jsii-compatible. CIS-critical fields inherited from BucketProps are applied internally and cannot be weakened.

Default Lifecycle Rules

The default lifecycle rules provide cost optimization:

const defaultLifecycleRules: LifecycleRule[] = [
  {
    id: 'transition-to-ia',
    enabled: true,
    transitions: [
      {
        storageClass: StorageClass.STANDARD_IA,
        transitionAfter: Duration.days(30),
      },
      {
        storageClass: StorageClass.GLACIER,
        transitionAfter: Duration.days(90),
      },
      {
        storageClass: StorageClass.DEEP_ARCHIVE,
        transitionAfter: Duration.days(365),
      },
    ],
  },
  {
    id: 'delete-old-versions',
    enabled: true,
    noncurrentVersionTransitions: [
      {
        storageClass: StorageClass.GLACIER,
        transitionAfter: Duration.days(30),
      },
    ],
    noncurrentVersionExpiration: Duration.days(365),
  },
];

Error Handling

Common Errors

Property Injection Errors

If property injection fails, check:

  1. CDK Version: Ensure you're using CDK v2.196.0 or later
  2. Construct ID: Verify the construct unique ID is correct
  3. Property Conflicts: Check for conflicting property definitions

Security Configuration Errors

Common security configuration issues:

  1. Encryption Conflicts: Ensure encryption settings are compatible
  2. Access Control Conflicts: Verify public access block settings
  3. Lifecycle Rule Conflicts: Check for overlapping lifecycle rules

Debugging

Enable debug logging for property injection:

// Enable debug logging
process.env.CDK_DEBUG = '1';

const app = new App({
  propertyInjectors: [new SecureBucketDefaults()],
});

Migration Guide

From Standard S3 Buckets

To migrate from standard S3 buckets to secure constructs:

// Before
const bucket = new Bucket(this, 'MyBucket', {
  bucketName: 'my-bucket',
});

// After
const secureBucket = new SecureBucket(this, 'MyBucket', {
  bucketName: 'my-bucket',
});

From Custom Security Configurations

To migrate from custom security configurations:

// Before
const bucket = new Bucket(this, 'MyBucket', {
  encryption: BucketEncryption.S3_MANAGED,
  blockPublicAccess: BlockPublicAccess.BLOCK_ALL,
  enforceSSL: true,
  versioned: true,
});

// After
const secureBucket = new SecureBucket(this, 'MyBucket');
// All security settings are applied automatically

Best Practices

When to Use Each Construct

Use SecureBucket when:

  • You need a single secure bucket with custom configuration
  • You want explicit control over security settings
  • You're building a specific use case

Use SecureBucketDefaults when:

  • You want consistent security across multiple buckets
  • You want to allow developers to override settings when needed
  • You're building organizational standards

Use StrictSecureBucketDefaults when:

  • You need to enforce compliance requirements
  • You want to prevent security setting overrides
  • You're in a highly regulated environment

Performance Considerations

  • Access Logging: May impact performance for high-traffic buckets
  • Versioning: Increases storage costs but provides data protection
  • Lifecycle Rules: Minimal performance impact, significant cost savings

Cost Optimization

  • Intelligent Tiering: Automatically optimizes storage costs
  • Lifecycle Rules: Transition data to cheaper storage classes
  • Versioning: Only enable when data protection is required

For more information, see the README and Security Documentation.