Public API for aws-cdk-secure-constructs. Currently covers S3 only.
Requires aws-cdk-lib >= 2.196.0.
- SecurityLevel
- SecureBucket
- SecureBucketDefaults
- StrictSecureBucketDefaults
- TieredSecureBucketDefaults
- Compliance reporting
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.
A secure S3 bucket construct that enforces security best practices by default.
new SecureBucket(scope: Construct, id: string, props?: 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) |
Grants read permissions to the specified principal.
grantRead(grantee: IGrantable, objectsKeyPattern?: string): GrantGrants write permissions to the specified principal.
grantWrite(grantee: IGrantable, objectsKeyPattern?: string): GrantGrants read/write permissions to the specified principal.
grantReadWrite(grantee: IGrantable, objectsKeyPattern?: string): GrantGrants delete permissions to the specified principal.
grantDelete(grantee: IGrantable, objectsKeyPattern?: string): Grantimport { SecureBucket } from 'aws-cdk-secure-constructs';
const secureBucket = new SecureBucket(this, 'MySecureBucket', {
bucketName: 'my-secure-bucket-name',
});const customBucket = new SecureBucket(this, 'CustomBucket', {
bucketName: 'my-custom-bucket',
versioned: true,
enableAccessLogging: true,
lifecycleRules: [
{
id: 'custom-rule',
enabled: true,
expiration: { days: 30 },
},
],
});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/*');Property injector that applies secure defaults to all S3 buckets in the construct tree.
new SecureBucketDefaults()| Property | Type | Description |
|---|---|---|
constructUniqueId |
string |
The unique identifier for S3 bucket constructs |
Injects secure default properties into S3 bucket configurations.
inject(originalProps: BucketProps, context: InjectionContext): BucketPropsThe 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
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');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',
});Property injector that applies strict security defaults that cannot be overridden.
new StrictSecureBucketDefaults()| Property | Type | Description |
|---|---|---|
constructUniqueId |
string |
The unique identifier for S3 bucket constructs |
Injects strict security defaults that override any conflicting settings.
inject(originalProps: BucketProps, context: InjectionContext): BucketPropsThe 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'
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');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
});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.
new TieredSecureBucketDefaults(options?: TieredSecureBucketOptions)
interface TieredSecureBucketOptions {
readonly securityLevel?: SecurityLevel; // default HIGH
}- 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 isstrictest(constructTier, injectorTier)- the injector is an org-wide floor.
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 });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.
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
BucketPropsdirectly (noOmit) to remain jsii-compatible. CIS-critical fields inherited fromBucketPropsare applied internally and cannot be weakened.
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),
},
];If property injection fails, check:
- CDK Version: Ensure you're using CDK v2.196.0 or later
- Construct ID: Verify the construct unique ID is correct
- Property Conflicts: Check for conflicting property definitions
Common security configuration issues:
- Encryption Conflicts: Ensure encryption settings are compatible
- Access Control Conflicts: Verify public access block settings
- Lifecycle Rule Conflicts: Check for overlapping lifecycle rules
Enable debug logging for property injection:
// Enable debug logging
process.env.CDK_DEBUG = '1';
const app = new App({
propertyInjectors: [new SecureBucketDefaults()],
});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',
});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- You need a single secure bucket with custom configuration
- You want explicit control over security settings
- You're building a specific use case
- You want consistent security across multiple buckets
- You want to allow developers to override settings when needed
- You're building organizational standards
- You need to enforce compliance requirements
- You want to prevent security setting overrides
- You're in a highly regulated environment
- 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
- 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.