Skip to content

(aws-s3express): Add L2 constructs for S3 Express One Zone #36548

@yasomaru

Description

@yasomaru

Describe the feature

CDK includes the L1 constructs CfnDirectoryBucket, CfnAccessPoint, and CfnBucketPolicy in the aws-s3express package, there are currently no L2 constructs for these resource types. This forces developers to work with low-level CloudFormation constructs, missing out on the benefits of CDK's higher-level abstractions.

The aws-s3express README explicitly states:

"There are no official hand-written (L2) constructs for this service yet."

Use Case

Developers building latency-sensitive applications need type-safe, intuitive CDK constructs that:

  1. Simplify configuration - Provides sensible defaults and validation for directory bucket naming, location selection, and encryption
  2. Improve discoverability - Easy to find through IDE autocomplete alongside the standard Bucket construct
  3. Enable integration - Works seamlessly with other CDK constructs (IAM, Lambda, ECS, etc.)
  4. Reduce boilerplate - Abstracts common patterns like grant permissions, bucket policies, and access points
  5. Provide type safety - Strong typing for bucket names (with required suffix validation), availability zones, and configuration options

Currently, using CfnDirectoryBucket requires:

  • Manual bucket name formatting with --zone-id--x-s3 suffix
  • Explicit configuration of all properties with no defaults
  • No helper methods for grants or permissions
  • Manual ARN construction for cross-service integration
  • No type-safe access to bucket attributes

Proposed Solution

Introduce DirectoryBucket and AccessPoint L2 constructs that follow the established pattern of the standard S3 Bucket construct.

Proposed API: DirectoryBucket

import * as s3express from 'aws-cdk-lib/aws-s3express';
import * as kms from 'aws-cdk-lib/aws-kms';
import * as lambda from 'aws-cdk-lib/aws-lambda';

// Simple directory bucket creation
const bucket = new s3express.DirectoryBucket(this, 'MyExpressBucket', {
  location: 'usw2-az1',  // Availability Zone ID
});

// With custom configuration
const customBucket = new s3express.DirectoryBucket(this, 'CustomBucket', {
  bucketName: 'my-express-bucket--usw2-az1--x-s3',
  location: 'usw2-az1',
  
  // Encryption options
  encryption: s3express.DirectoryBucketEncryption.KMS,
  encryptionKey: new kms.Key(this, 'BucketKey'),
  
  // Data redundancy
  dataRedundancy: s3express.DataRedundancy.SINGLE_AVAILABILITY_ZONE,
  
  // Lifecycle rules
  lifecycleRules: [{
    id: 'expire-old-data',
    enabled: true,
    expirationDays: 30,
    prefix: 'temp/',
  }],
  
  // Removal policy
  removalPolicy: cdk.RemovalPolicy.DESTROY,
});

// Grant permissions (similar to standard S3 Bucket)
const fn = new lambda.Function(this, 'Function', {
  // ... function configuration
});

bucket.grantRead(fn);
bucket.grantWrite(fn);
bucket.grantReadWrite(fn);

// Access bucket properties
console.log(bucket.bucketArn);
console.log(bucket.bucketName);
console.log(bucket.availabilityZone);

Proposed API: AccessPoint

import * as s3express from 'aws-cdk-lib/aws-s3express';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import * as iam from 'aws-cdk-lib/aws-iam';

declare const bucket: s3express.DirectoryBucket;
declare const vpc: ec2.Vpc;

// Create access point for directory bucket
const accessPoint = new s3express.AccessPoint(this, 'MyAccessPoint', {
  bucket,
  accessPointName: 'analytics-access',
  
  // VPC-only access
  vpcConfiguration: {
    vpcId: vpc.vpcId,
  },
  
  // Access point policy
  policy: new iam.PolicyDocument({
    statements: [
      new iam.PolicyStatement({
        actions: ['s3express:GetObject'],
        resources: [`${bucket.bucketArn}/*`],
        principals: [new iam.AccountPrincipal('123456789012')],
        conditions: {
          StringLike: {
            's3express:prefix': ['analytics/*'],
          },
        },
      }),
    ],
  }),
});

// Grant through access point
accessPoint.grantRead(fn);

// Access properties
console.log(accessPoint.accessPointArn);
console.log(accessPoint.accessPointName);

Other Information

No response

Acknowledgements

  • I may be able to implement this feature request
  • This feature might incur a breaking change

AWS CDK Library version (aws-cdk-lib)

2.x

AWS CDK CLI version

2.x

Environment details (OS name and version, etc.)

all

Metadata

Metadata

Assignees

No one assigned

    Labels

    @aws-cdk/aws-s3Related to Amazon S3effort/mediumMedium work item – several days of effortfeature-requestA feature should be added or improved.p2

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions