Skip to content

Commit 94b0b53

Browse files
feat(s3files): new L2 constructs for FileSystem and AccessPoint
Adds L2 constructs for `AWS::S3Files::FileSystem`, `AWS::S3Files::AccessPoint`, `AWS::S3Files::MountTarget`, and `AWS::S3Files::FileSystemPolicy`. `FileSystem` auto-creates an IAM service role (with confused-deputy `aws:SourceAccount`/`aws:SourceArn` conditions) scoped to the backing bucket and optional `prefix`, attaches one `MountTarget` per AZ, exposes `connections`, and lazily emits a `CfnFileSystemPolicy` when `addToResourcePolicy` is used. `addAccessPoint()` returns the access-point L2. Permissions are exposed via a `FileSystemGrants` Facade (`fileSystem.grants.{mount,read,write,rootAccess,actions}`), generated from `grants.json` via the spec2cdk pipeline. Strong types: `Size` for `importDataRules.sizeLessThan`, `Duration` for `expirationDataRules.afterLastAccess`. Props accept `IBucketRef` / `IRoleRef` / `IKeyRef` / `IFileSystemRef` per the modern construct design guidelines. closes #37568
1 parent ffae861 commit 94b0b53

12 files changed

Lines changed: 1788 additions & 18 deletions

File tree

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import * as cdk from 'aws-cdk-lib';
2+
import { RemovalPolicies } from 'aws-cdk-lib';
3+
import * as ec2 from 'aws-cdk-lib/aws-ec2';
4+
import * as s3 from 'aws-cdk-lib/aws-s3';
5+
import { FileSystem } from 'aws-cdk-lib/aws-s3files';
6+
import * as integ from '@aws-cdk/integ-tests-alpha';
7+
8+
const app = new cdk.App();
9+
const stack = new cdk.Stack(app, 'test-s3files-filesystem-integ');
10+
11+
const vpc = new ec2.Vpc(stack, 'Vpc', { maxAzs: 2 });
12+
const bucket = new s3.Bucket(stack, 'Bucket', {
13+
autoDeleteObjects: true,
14+
});
15+
16+
const fileSystem = new FileSystem(stack, 'FileSystem', {
17+
bucket,
18+
vpc,
19+
});
20+
21+
fileSystem.addAccessPoint('AccessPoint', {
22+
path: '/data',
23+
createAcl: { ownerUid: '1000', ownerGid: '1000', permissions: '0755' },
24+
posixUser: { uid: '1000', gid: '1000' },
25+
});
26+
27+
RemovalPolicies.of(app).applyRemovalPolicy(cdk.RemovalPolicy.DESTROY);
28+
29+
new integ.IntegTest(app, 'test-s3files-filesystem-integ-test', {
30+
testCases: [stack],
31+
});
Lines changed: 177 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,199 @@
1-
# AWS::S3Files Construct Library
1+
# Amazon S3 Files Construct Library
22
<!--BEGIN STABILITY BANNER-->
33

44
---
55

66
![cfn-resources: Stable](https://img.shields.io/badge/cfn--resources-stable-success.svg?style=for-the-badge)
77

8-
> All classes with the `Cfn` prefix in this module ([CFN Resources]) are always stable and safe to use.
9-
>
10-
> [CFN Resources]: https://docs.aws.amazon.com/cdk/latest/guide/constructs.html#constructs_lib
8+
![cdk-constructs: Stable](https://img.shields.io/badge/cdk--constructs-stable-success.svg?style=for-the-badge)
119

1210
---
1311

1412
<!--END STABILITY BANNER-->
1513

16-
This module is part of the [AWS Cloud Development Kit](https://github.com/aws/aws-cdk) project.
14+
[Amazon S3 Files](https://aws.amazon.com/s3/) lets you mount an Amazon S3 bucket as
15+
a POSIX file system on EC2 instances in a VPC. This module provides L2 constructs for the
16+
`AWS::S3Files::FileSystem`, `AWS::S3Files::AccessPoint`, `AWS::S3Files::MountTarget`, and
17+
`AWS::S3Files::FileSystemPolicy` CloudFormation resources.
1718

18-
```ts nofixture
19-
import * as s3files from 'aws-cdk-lib/aws-s3files';
19+
## Create an S3 Files file system
20+
21+
In its simplest form, an S3 Files file system needs an S3 bucket and a VPC. A mount target
22+
is created in each Availability Zone of the VPC, and an IAM service role is generated
23+
automatically with read/write access to the bucket.
24+
25+
```ts
26+
const vpc = new ec2.Vpc(this, 'Vpc');
27+
const bucket = new s3.Bucket(this, 'Bucket');
28+
29+
const fileSystem = new s3files.FileSystem(this, 'FileSystem', {
30+
bucket,
31+
vpc,
32+
});
33+
```
34+
35+
By default, the file system has a `RemovalPolicy.RETAIN` removal policy. To allow CDK
36+
to delete the file system on stack removal, set `removalPolicy` to `DESTROY`.
37+
38+
```ts
39+
declare const bucket: s3.IBucket;
40+
declare const vpc: ec2.IVpc;
41+
42+
new s3files.FileSystem(this, 'FileSystem', {
43+
bucket,
44+
vpc,
45+
removalPolicy: RemovalPolicy.DESTROY,
46+
});
47+
```
48+
49+
## Limit the file system to a bucket prefix
50+
51+
Use `prefix` to scope the file system to a key prefix within the bucket. Set
52+
`acceptBucketWarning` if the AWS service emits a warning that the bucket has properties
53+
that may incur additional cost or latency.
54+
55+
```ts
56+
declare const bucket: s3.IBucket;
57+
declare const vpc: ec2.IVpc;
58+
59+
new s3files.FileSystem(this, 'FileSystem', {
60+
bucket,
61+
vpc,
62+
prefix: 'projects/team-a',
63+
acceptBucketWarning: true,
64+
});
65+
```
66+
67+
## Synchronization configuration
68+
69+
Synchronization rules describe which objects to import into the file system and when to
70+
expire them. Sizes are expressed with `Size`, durations with `Duration`.
71+
72+
```ts
73+
declare const bucket: s3.IBucket;
74+
declare const vpc: ec2.IVpc;
75+
76+
new s3files.FileSystem(this, 'FileSystem', {
77+
bucket,
78+
vpc,
79+
synchronizationConfiguration: {
80+
importDataRules: [{
81+
prefix: 'incoming',
82+
sizeLessThan: Size.gibibytes(10),
83+
trigger: s3files.ImportDataTrigger.CONTINUOUS,
84+
}],
85+
expirationDataRules: [{
86+
afterLastAccess: Duration.days(30),
87+
}],
88+
},
89+
});
2090
```
2191

22-
<!--BEGIN CFNONLY DISCLAIMER-->
92+
## Custom IAM role
2393

24-
There are no official hand-written ([L2](https://docs.aws.amazon.com/cdk/latest/guide/constructs.html#constructs_lib)) constructs for this service yet. Here are some suggestions on how to proceed:
94+
By default, a service role is created with permissions scoped to the bucket (and
95+
`prefix` when set). To use an existing role, pass it via `role`.
96+
97+
```ts
98+
declare const bucket: s3.IBucket;
99+
declare const vpc: ec2.IVpc;
100+
declare const role: iam.IRole;
101+
102+
new s3files.FileSystem(this, 'FileSystem', {
103+
bucket,
104+
vpc,
105+
role,
106+
});
107+
```
25108

26-
- Search [Construct Hub for S3Files construct libraries](https://constructs.dev/search?q=s3files)
27-
- Use the automatically generated [L1](https://docs.aws.amazon.com/cdk/latest/guide/constructs.html#constructs_l1_using) constructs, in the same way you would use [the CloudFormation AWS::S3Files resources](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/AWS_S3Files.html) directly.
109+
## Encryption with a customer managed KMS key
28110

111+
Provide a KMS key when the bucket is encrypted with SSE-KMS. The service role is granted
112+
`kms:Decrypt` and `kms:GenerateDataKey` scoped via the `kms:ViaService` condition.
29113

30-
<!--BEGIN CFNONLY DISCLAIMER-->
114+
```ts
115+
declare const bucket: s3.IBucket;
116+
declare const vpc: ec2.IVpc;
117+
declare const key: kms.IKey;
31118

32-
There are no hand-written ([L2](https://docs.aws.amazon.com/cdk/latest/guide/constructs.html#constructs_lib)) constructs for this service yet.
33-
However, you can still use the automatically generated [L1](https://docs.aws.amazon.com/cdk/latest/guide/constructs.html#constructs_l1_using) constructs, and use this service exactly as you would using CloudFormation directly.
119+
new s3files.FileSystem(this, 'FileSystem', {
120+
bucket,
121+
vpc,
122+
kmsKey: key,
123+
});
124+
```
125+
126+
## Resource (file system) policy
127+
128+
A file system can have an attached resource policy. You can pass an initial document
129+
through `resourcePolicy`, and add statements later with `addToResourcePolicy()`.
130+
131+
```ts fixture=with-filesystem
132+
fileSystem.addToResourcePolicy(new iam.PolicyStatement({
133+
actions: ['s3files:ClientMount'],
134+
principals: [new iam.AccountPrincipal('123456789012')],
135+
resources: ['*'],
136+
}));
137+
```
34138

35-
For more information on the resources and properties available for this service, see the [CloudFormation documentation for AWS::S3Files](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/AWS_S3Files.html).
139+
## Granting permissions
36140

37-
(Read the [CDK Contributing Guide](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and submit an RFC if you are interested in contributing to this construct library.)
141+
Grants are exposed as a Facade on the file system: `fileSystem.grants`. Each method
142+
returns an `iam.Grant`.
38143

39-
<!--END CFNONLY DISCLAIMER-->
144+
```ts fixture=with-filesystem
145+
declare const taskRole: iam.IRole;
146+
147+
fileSystem.grants.mount(taskRole);
148+
fileSystem.grants.write(taskRole);
149+
fileSystem.grants.rootAccess(taskRole);
150+
```
151+
152+
For custom action sets, use `actions()`:
153+
154+
```ts fixture=with-filesystem
155+
declare const taskRole: iam.IRole;
156+
157+
fileSystem.grants.actions(taskRole, ['s3files:DescribeFileSystem']);
158+
```
159+
160+
## Access points
161+
162+
An access point exposes a sub-tree of the file system with a fixed POSIX identity. Use
163+
`addAccessPoint()` to create one against an existing file system.
164+
165+
```ts fixture=with-filesystem
166+
fileSystem.addAccessPoint('AccessPoint', {
167+
path: '/projects/team-a',
168+
createAcl: { ownerUid: '1000', ownerGid: '1000', permissions: '0755' },
169+
posixUser: { uid: '1000', gid: '1000' },
170+
});
171+
```
172+
173+
You can also import an existing access point.
174+
175+
```ts
176+
const ap = s3files.AccessPoint.fromAccessPointId(this, 'ImportedAP', 'fsap-1234567890abcdef0');
177+
```
178+
179+
## Connecting from EC2
180+
181+
The file system is `IConnectable` and exposes a security group through `connections`.
182+
Allow traffic from your instances on the default port (NFS/2049):
183+
184+
```ts fixture=with-filesystem
185+
declare const instance: ec2.Instance;
186+
fileSystem.connections.allowDefaultPortFrom(instance);
187+
```
188+
189+
## Importing an existing file system
190+
191+
```ts
192+
declare const vpc: ec2.IVpc;
193+
const sg = new ec2.SecurityGroup(this, 'SG', { vpc });
194+
195+
const imported = s3files.FileSystem.fromFileSystemAttributes(this, 'Imported', {
196+
fileSystemId: 'fs-1234567890abcdef0',
197+
securityGroup: sg,
198+
});
199+
```
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
{
2+
"resources": {
3+
"FileSystem": {
4+
"hasResourcePolicy": true,
5+
"grants": {
6+
"mount": {
7+
"actions": [
8+
"s3files:ClientMount"
9+
],
10+
"docSummary": "Grant the ability to mount this file system"
11+
},
12+
"read": {
13+
"actions": [
14+
"s3files:ClientMount"
15+
],
16+
"docSummary": "Grant read (mount) access to this file system"
17+
},
18+
"write": {
19+
"actions": [
20+
"s3files:ClientMount",
21+
"s3files:ClientWrite"
22+
],
23+
"docSummary": "Grant read/write access to this file system"
24+
},
25+
"rootAccess": {
26+
"actions": [
27+
"s3files:ClientMount",
28+
"s3files:ClientWrite",
29+
"s3files:ClientRootAccess"
30+
],
31+
"docSummary": "Grant root-level access to this file system"
32+
}
33+
}
34+
}
35+
}
36+
}

0 commit comments

Comments
 (0)