aws / aws/aws-cdk

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

Open
#36,548 2 comments 0 reactions 0 assignees View on GitHub
@aws-cdk/aws-s3 effort/medium feature-request p2
Dominant language
TypeScript
Stars
12.9k
Forks
4.6k
Avg merge
2d 3h
Merged PRs (30d)
83

Description

### 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

```typescript
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

```ts
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

- [x] 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

Contributor guide

Open the contributing guide

Research direction

Start with the aws-s3express README and the existing CfnDirectoryBucket, CfnAccessPoint, and CfnBucketPolicy constructs, then compare the established standard S3 Bucket pattern. Done means providing DirectoryBucket and AccessPoint L2 constructs with the proposed configuration, validation, attributes, permissions helpers, and integration behavior, backed by appropriate tests.

Written by the indexing model from the issue text.

Assessment

Tech stack
aws, typescript
Domain
cloud, infrastructure
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.