@composurecdk/s3 0.4.8 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -18,15 +18,15 @@ Every [BucketProps](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_
18
18
 
19
19
  `createBucketBuilder` applies the following defaults. Each can be overridden via the builder's fluent API.
20
20
 
21
- | Property | Default | Rationale |
22
- | ------------------- | ------------ | ---------------------------------------------------------------- |
23
- | `accessLogging` | `true` | Auto-creates a logging bucket for server access log audit trail. |
24
- | `accessLogsPrefix` | `"logs/"` | Default prefix for access log object keys. |
25
- | `blockPublicAccess` | `BLOCK_ALL` | Prevents public access unless explicitly required. |
26
- | `encryption` | `S3_MANAGED` | Enables server-side encryption with S3-managed keys (SSE-S3). |
27
- | `enforceSSL` | `true` | Requires SSL/TLS for all requests to the bucket. |
28
- | `versioned` | `true` | Protects against accidental deletions and supports rollback. |
29
- | `removalPolicy` | `RETAIN` | Retains the bucket on stack deletion to prevent data loss. |
21
+ | Property | Default | Rationale |
22
+ | ------------------- | -------------------------------- | ----------------------------------------------------------------------------------------------------- |
23
+ | `serverAccessLogs` | `{ prefix: "logs/" }` | Auto-creates a logging bucket for the server access log audit trail under the `logs/` prefix. |
24
+ | `blockPublicAccess` | `BLOCK_ALL` | Prevents public access unless explicitly required. |
25
+ | `encryption` | `S3_MANAGED` | Enables server-side encryption with S3-managed keys (SSE-S3). |
26
+ | `enforceSSL` | `true` | Requires SSL/TLS for all requests to the bucket. |
27
+ | `versioned` | `true` | Protects against accidental deletions and supports rollback. |
28
+ | `removalPolicy` | `RETAIN` | Retains the bucket on stack deletion to prevent data loss. |
29
+ | `lifecycleRules` | `DEFAULT_BUCKET_LIFECYCLE_RULES` | Aborts incomplete multipart uploads after 7 days and expires noncurrent object versions after 1 year. |
30
30
 
31
31
  These defaults are guided by the [AWS Well-Architected Security Pillar](https://docs.aws.amazon.com/wellarchitected/latest/security-pillar/protecting-data-at-rest.html).
32
32
 
@@ -53,7 +53,7 @@ When `removalPolicy` is set to `DESTROY`, the builder automatically enables `aut
53
53
 
54
54
  ### Access logging
55
55
 
56
- By default, the builder creates a dedicated logging bucket with secure defaults and configures it as the server access logs destination. The created bucket is returned in the build result:
56
+ Server access logging is configured through a single `.serverAccessLogs(config)` setting. By default, the builder creates a dedicated logging bucket with secure defaults and writes logs under `logs/`. The created bucket is returned in the build result:
57
57
 
58
58
  ```ts
59
59
  const result = createBucketBuilder().build(stack, "MyBucket");
@@ -62,7 +62,30 @@ result.bucket; // Bucket
62
62
  result.accessLogsBucket; // Bucket | undefined
63
63
  ```
64
64
 
65
- To provide your own destination instead, set `serverAccessLogsBucket` the auto-created logging bucket is skipped. To disable access logging entirely, set `.accessLogging(false)`.
65
+ `.serverAccessLogs(config)` accepts either `false` to disable access logging, or an object describing how to handle logs:
66
+
67
+ ```ts
68
+ import { Duration } from "aws-cdk-lib";
69
+
70
+ // Disable access logging entirely
71
+ createBucketBuilder().serverAccessLogs(false);
72
+
73
+ // Auto-create a logging bucket with a custom prefix
74
+ createBucketBuilder().serverAccessLogs({ prefix: "audit/" });
75
+
76
+ // Auto-create and customize the logging sub-builder
77
+ createBucketBuilder().serverAccessLogs({
78
+ configure: (sub) => sub.lifecycleRules([{ id: "ShortLogs", expiration: Duration.days(180) }]),
79
+ });
80
+
81
+ // Bring your own destination bucket
82
+ createBucketBuilder().serverAccessLogs({ destination: myBucket });
83
+
84
+ // Bring your own destination with a prefix
85
+ createBucketBuilder().serverAccessLogs({ destination: myBucket, prefix: "x/" });
86
+ ```
87
+
88
+ `destination` and `configure` cannot be combined — the destination bucket is user-managed and is not built by this builder.
66
89
 
67
90
  ## Recommended Alarms
68
91
 
@@ -1,43 +1,34 @@
1
1
  import { type Alarm } from "aws-cdk-lib/aws-cloudwatch";
2
- import { Bucket, type BucketProps } from "aws-cdk-lib/aws-s3";
2
+ import { Bucket, type BucketProps, type IBucket } from "aws-cdk-lib/aws-s3";
3
3
  import { type IConstruct } from "constructs";
4
4
  import { type IBuilder, type Lifecycle } from "@composurecdk/core";
5
5
  import { AlarmDefinitionBuilder } from "@composurecdk/cloudwatch";
6
6
  import type { BucketAlarmConfig } from "./alarm-config.js";
7
7
  /**
8
- * Configuration properties for the S3 bucket builder.
8
+ * Configures how server access logs are handled. Pass `false` to disable
9
+ * logging; pass an object to wire a destination, prefix, or customize the
10
+ * auto-created sub-builder.
9
11
  *
10
- * Extends the CDK {@link BucketProps} with additional builder-specific options.
12
+ * `configure` cannot be combined with `destination` — a user-managed
13
+ * destination is not built by this builder.
11
14
  */
12
- export interface BucketBuilderProps extends BucketProps {
15
+ export type ServerAccessLogsConfig = false | {
16
+ destination?: IBucket;
17
+ prefix?: string;
13
18
  /**
14
- * Whether to automatically create an S3 access logging bucket.
15
- *
16
- * When `true`, the builder creates a dedicated logging bucket using
17
- * {@link createBucketBuilder} (with secure defaults appropriate for log
18
- * storage) and configures it as the server access logs destination. The
19
- * logging bucket inherits secure defaults (block public access, encryption,
20
- * enforceSSL, versioning for log integrity) with `removalPolicy: RETAIN`
21
- * and access logging disabled to avoid recursion. The created logging
22
- * bucket is returned in the build result as `accessLogsBucket`.
23
- *
24
- * When `false`, no logging bucket is created. You can still provide your
25
- * own destination via `serverAccessLogsBucket`.
26
- *
27
- * This setting is ignored when `serverAccessLogsBucket` is provided — the
28
- * user-supplied destination takes precedence.
19
+ * Customize the auto-created logging sub-builder. Receives a builder
20
+ * pre-seeded with `versioned: false`, `removalPolicy: RETAIN`, and
21
+ * recursive access logging disabled.
29
22
  */
30
- accessLogging?: boolean;
31
- /**
32
- * The prefix applied to server access log object keys when the builder
33
- * auto-creates a logging bucket.
34
- *
35
- * This setting is only used when {@link accessLogging} is `true` and no
36
- * user-provided `serverAccessLogsBucket` is set.
37
- *
38
- * @default "logs/"
39
- */
40
- accessLogsPrefix?: string;
23
+ configure?: (b: IBucketBuilder) => IBucketBuilder;
24
+ };
25
+ /**
26
+ * Configuration properties for the S3 bucket builder. Extends CDK
27
+ * {@link BucketProps} with builder-specific options.
28
+ */
29
+ export interface BucketBuilderProps extends Omit<BucketProps, "serverAccessLogsBucket" | "serverAccessLogsPrefix"> {
30
+ /** See {@link ServerAccessLogsConfig}. Defaults to `{ prefix: "logs/" }`. */
31
+ serverAccessLogs?: ServerAccessLogsConfig;
41
32
  /**
42
33
  * Configuration for AWS-recommended CloudWatch alarms.
43
34
  *
@@ -1 +1 @@
1
- {"version":3,"file":"bucket-builder.d.ts","sourceRoot":"","sources":["../src/bucket-builder.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,4BAA4B,CAAC;AACxD,OAAO,EAAE,MAAM,EAAE,KAAK,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAW,KAAK,QAAQ,EAAE,KAAK,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC5E,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAI3D;;;;GAIG;AACH,MAAM,WAAW,kBAAmB,SAAQ,WAAW;IACrD;;;;;;;;;;;;;;;;OAgBG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IAExB;;;;;;;;OAQG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B;;;;;;;;;;;;;OAaG;IACH,iBAAiB,CAAC,EAAE,iBAAiB,GAAG,KAAK,CAAC;CAC/C;AAED;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC,sDAAsD;IACtD,MAAM,EAAE,MAAM,CAAC;IAEf;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B;;;;;;;;;;;OAWG;IACH,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;CAC/B;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,MAAM,cAAc,GAAG,QAAQ,CAAC,kBAAkB,EAAE,aAAa,CAAC,CAAC;AAEzE,cAAM,aAAc,YAAW,SAAS,CAAC,mBAAmB,CAAC;;IAC3D,KAAK,EAAE,OAAO,CAAC,kBAAkB,CAAC,CAAM;IAGxC,QAAQ,CACN,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,CAAC,KAAK,EAAE,sBAAsB,CAAC,MAAM,CAAC,KAAK,sBAAsB,CAAC,MAAM,CAAC,GACnF,IAAI;IAKP,KAAK,CAAC,KAAK,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,GAAG,mBAAmB;CA8D1D;AAqBD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,mBAAmB,IAAI,cAAc,CAEpD"}
1
+ {"version":3,"file":"bucket-builder.d.ts","sourceRoot":"","sources":["../src/bucket-builder.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,4BAA4B,CAAC;AACxD,OAAO,EAAE,MAAM,EAAE,KAAK,WAAW,EAAE,KAAK,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC5E,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAW,KAAK,QAAQ,EAAE,KAAK,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC5E,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAI3D;;;;;;;GAOG;AACH,MAAM,MAAM,sBAAsB,GAC9B,KAAK,GACL;IACE,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,SAAS,CAAC,EAAE,CAAC,CAAC,EAAE,cAAc,KAAK,cAAc,CAAC;CACnD,CAAC;AAEN;;;GAGG;AACH,MAAM,WAAW,kBAAmB,SAAQ,IAAI,CAC9C,WAAW,EACX,wBAAwB,GAAG,wBAAwB,CACpD;IACC,6EAA6E;IAC7E,gBAAgB,CAAC,EAAE,sBAAsB,CAAC;IAE1C;;;;;;;;;;;;;OAaG;IACH,iBAAiB,CAAC,EAAE,iBAAiB,GAAG,KAAK,CAAC;CAC/C;AAED;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC,sDAAsD;IACtD,MAAM,EAAE,MAAM,CAAC;IAEf;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B;;;;;;;;;;;OAWG;IACH,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;CAC/B;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,MAAM,cAAc,GAAG,QAAQ,CAAC,kBAAkB,EAAE,aAAa,CAAC,CAAC;AAEzE,cAAM,aAAc,YAAW,SAAS,CAAC,mBAAmB,CAAC;;IAC3D,KAAK,EAAE,OAAO,CAAC,kBAAkB,CAAC,CAAM;IAGxC,QAAQ,CACN,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,CAAC,KAAK,EAAE,sBAAsB,CAAC,MAAM,CAAC,KAAK,sBAAsB,CAAC,MAAM,CAAC,GACnF,IAAI;IAKP,KAAK,CAAC,KAAK,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,GAAG,mBAAmB;CA+B1D;AAgED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,mBAAmB,IAAI,cAAc,CAEpD"}
@@ -3,7 +3,7 @@ import { Bucket } from "aws-cdk-lib/aws-s3";
3
3
  import { Builder } from "@composurecdk/core";
4
4
  import { AlarmDefinitionBuilder } from "@composurecdk/cloudwatch";
5
5
  import { createBucketAlarms } from "./bucket-alarms.js";
6
- import { BUCKET_DEFAULTS } from "./defaults.js";
6
+ import { DEFAULT_ACCESS_LOG_BUCKET_LIFECYCLE_RULES, BUCKET_DEFAULTS } from "./defaults.js";
7
7
  class BucketBuilder {
8
8
  props = {};
9
9
  #customAlarms = [];
@@ -12,27 +12,10 @@ class BucketBuilder {
12
12
  return this;
13
13
  }
14
14
  build(scope, id) {
15
- const { accessLogging, accessLogsPrefix, recommendedAlarms: alarmConfig, ...bucketProps } = this.props;
16
- const { accessLogging: defaultAccessLogging, accessLogsPrefix: defaultLogsPrefix, ...cdkDefaults } = BUCKET_DEFAULTS;
17
- const autoAccessLog = (accessLogging ?? defaultAccessLogging) && !bucketProps.serverAccessLogsBucket;
18
- if (accessLogsPrefix !== undefined && !autoAccessLog) {
19
- throw new Error("Cannot set 'accessLogsPrefix' when access logging is disabled or " +
20
- "'serverAccessLogsBucket' is provided. Set 'serverAccessLogsPrefix' " +
21
- "directly when using your own logging bucket.");
22
- }
23
- let accessLogsBucket;
24
- let accessLogProps = {};
25
- if (autoAccessLog) {
26
- accessLogsBucket = createBucketBuilder()
27
- .accessLogging(false)
28
- .versioned(false)
29
- .removalPolicy(RemovalPolicy.RETAIN)
30
- .build(scope, `${id}AccessLogs`).bucket;
31
- accessLogProps = {
32
- serverAccessLogsBucket: accessLogsBucket,
33
- serverAccessLogsPrefix: accessLogsPrefix ?? defaultLogsPrefix,
34
- };
35
- }
15
+ const { serverAccessLogs, recommendedAlarms: alarmConfig, ...bucketProps } = this.props;
16
+ const { serverAccessLogs: defaultServerAccessLogs, ...cdkDefaults } = BUCKET_DEFAULTS;
17
+ const cfg = serverAccessLogs ?? defaultServerAccessLogs;
18
+ const { accessLogsBucket, accessLogProps } = resolveAccessLogs(scope, id, cfg);
36
19
  const mergedProps = {
37
20
  ...cdkDefaults,
38
21
  ...accessLogProps,
@@ -48,6 +31,39 @@ class BucketBuilder {
48
31
  };
49
32
  }
50
33
  }
34
+ function resolveAccessLogs(scope, id, cfg) {
35
+ if (cfg === false || cfg === undefined) {
36
+ return { accessLogProps: {} };
37
+ }
38
+ if (cfg.destination !== undefined) {
39
+ if (cfg.configure !== undefined) {
40
+ throw new Error("serverAccessLogs: 'configure' cannot be combined with 'destination' — " +
41
+ "the destination bucket is user-managed and not built by this builder.");
42
+ }
43
+ return {
44
+ accessLogProps: {
45
+ serverAccessLogsBucket: cfg.destination,
46
+ ...(cfg.prefix !== undefined ? { serverAccessLogsPrefix: cfg.prefix } : {}),
47
+ },
48
+ };
49
+ }
50
+ let subBuilder = createBucketBuilder()
51
+ .serverAccessLogs(false)
52
+ .versioned(false)
53
+ .removalPolicy(RemovalPolicy.RETAIN)
54
+ .lifecycleRules(DEFAULT_ACCESS_LOG_BUCKET_LIFECYCLE_RULES);
55
+ if (cfg.configure) {
56
+ subBuilder = cfg.configure(subBuilder);
57
+ }
58
+ const accessLogsBucket = subBuilder.build(scope, `${id}AccessLogs`).bucket;
59
+ return {
60
+ accessLogsBucket,
61
+ accessLogProps: {
62
+ serverAccessLogsBucket: accessLogsBucket,
63
+ ...(cfg.prefix !== undefined ? { serverAccessLogsPrefix: cfg.prefix } : {}),
64
+ },
65
+ };
66
+ }
51
67
  /**
52
68
  * Returns `{ autoDeleteObjects: true }` when the effective removal policy is
53
69
  * `DESTROY` and the user has not explicitly set `autoDeleteObjects`.
@@ -1 +1 @@
1
- {"version":3,"file":"bucket-builder.js","sourceRoot":"","sources":["../src/bucket-builder.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"bucket-builder.js","sourceRoot":"","sources":["../src/bucket-builder.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,24 @@
1
+ import { type LifecycleRule } from "aws-cdk-lib/aws-s3";
1
2
  import type { BucketBuilderProps } from "./bucket-builder.js";
3
+ /**
4
+ * Lifecycle rules applied to general-purpose buckets built with
5
+ * {@link createBucketBuilder}. Bounds storage cost from orphaned multipart
6
+ * parts and from accumulated noncurrent versions of objects in versioned
7
+ * buckets, while preserving a generous recovery window.
8
+ *
9
+ * Users who need different rules can override the entire set via the
10
+ * `.lifecycleRules([...])` builder method.
11
+ */
12
+ export declare const DEFAULT_BUCKET_LIFECYCLE_RULES: LifecycleRule[];
13
+ /**
14
+ * Lifecycle rules applied to auto-created S3 server access log buckets and
15
+ * CloudFront access log buckets. Mirrors the 2-year retention used by
16
+ * {@link LOG_GROUP_DEFAULTS} so the audit window is consistent across log
17
+ * destinations in the library.
18
+ *
19
+ * @see https://docs.aws.amazon.com/wellarchitected/latest/security-pillar/sec_detect_investigate_events_app_service_logging.html
20
+ */
21
+ export declare const DEFAULT_ACCESS_LOG_BUCKET_LIFECYCLE_RULES: LifecycleRule[];
2
22
  /**
3
23
  * Secure, AWS-recommended defaults applied to every S3 bucket built
4
24
  * with {@link createBucketBuilder}. Each property can be individually
@@ -1 +1 @@
1
- {"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../src/defaults.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAE9D;;;;GAIG;AACH,eAAO,MAAM,eAAe,EAAE,OAAO,CAAC,kBAAkB,CAqDvD,CAAC"}
1
+ {"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../src/defaults.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuC,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAE7F,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAe9D;;;;;;;;GAQG;AACH,eAAO,MAAM,8BAA8B,EAAE,aAAa,EAczD,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,yCAAyC,EAAE,aAAa,EAMpE,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,eAAe,EAAE,OAAO,CAAC,kBAAkB,CA6DvD,CAAC"}
package/dist/defaults.js CHANGED
@@ -1,5 +1,56 @@
1
1
  import { BlockPublicAccess, BucketEncryption } from "aws-cdk-lib/aws-s3";
2
- import { RemovalPolicy } from "aws-cdk-lib";
2
+ import { Duration, RemovalPolicy } from "aws-cdk-lib";
3
+ /**
4
+ * Aborts multipart uploads that have not completed within 7 days. AWS recommends
5
+ * this rule on every bucket — orphaned upload parts are billed as storage but
6
+ * never become objects, so the rule is pure cost hygiene with no functional
7
+ * downside.
8
+ *
9
+ * @see https://docs.aws.amazon.com/AmazonS3/latest/userguide/mpu-abort-incomplete-mpu-lifecycle-config.html
10
+ */
11
+ const ABORT_INCOMPLETE_MULTIPART_UPLOADS = {
12
+ id: "AbortIncompleteMultipartUploadAfter7Days",
13
+ abortIncompleteMultipartUploadAfter: Duration.days(7),
14
+ };
15
+ /**
16
+ * Lifecycle rules applied to general-purpose buckets built with
17
+ * {@link createBucketBuilder}. Bounds storage cost from orphaned multipart
18
+ * parts and from accumulated noncurrent versions of objects in versioned
19
+ * buckets, while preserving a generous recovery window.
20
+ *
21
+ * Users who need different rules can override the entire set via the
22
+ * `.lifecycleRules([...])` builder method.
23
+ */
24
+ export const DEFAULT_BUCKET_LIFECYCLE_RULES = [
25
+ ABORT_INCOMPLETE_MULTIPART_UPLOADS,
26
+ {
27
+ /**
28
+ * Buckets default to `versioned: true`, so replaced and deleted objects
29
+ * accumulate as noncurrent versions indefinitely. Expiring them after a
30
+ * year preserves a long recovery window for "oops" deletions while
31
+ * preventing unbounded storage growth.
32
+ *
33
+ * @see https://docs.aws.amazon.com/AmazonS3/latest/userguide/lifecycle-configuration-examples.html
34
+ */
35
+ id: "ExpireNoncurrentVersionsAfter365Days",
36
+ noncurrentVersionExpiration: Duration.days(365),
37
+ },
38
+ ];
39
+ /**
40
+ * Lifecycle rules applied to auto-created S3 server access log buckets and
41
+ * CloudFront access log buckets. Mirrors the 2-year retention used by
42
+ * {@link LOG_GROUP_DEFAULTS} so the audit window is consistent across log
43
+ * destinations in the library.
44
+ *
45
+ * @see https://docs.aws.amazon.com/wellarchitected/latest/security-pillar/sec_detect_investigate_events_app_service_logging.html
46
+ */
47
+ export const DEFAULT_ACCESS_LOG_BUCKET_LIFECYCLE_RULES = [
48
+ ABORT_INCOMPLETE_MULTIPART_UPLOADS,
49
+ {
50
+ id: "ExpireAccessLogsAfter2Years",
51
+ expiration: Duration.days(731),
52
+ },
53
+ ];
3
54
  /**
4
55
  * Secure, AWS-recommended defaults applied to every S3 bucket built
5
56
  * with {@link createBucketBuilder}. Each property can be individually
@@ -7,17 +58,14 @@ import { RemovalPolicy } from "aws-cdk-lib";
7
58
  */
8
59
  export const BUCKET_DEFAULTS = {
9
60
  /**
10
- * Automatically create an access logging bucket for S3 server access logs.
11
- * Access logging provides an audit trail of all object-level operations for
12
- * security monitoring and troubleshooting.
61
+ * Auto-create a dedicated logging bucket and write S3 server access logs
62
+ * to it under the `logs/` prefix. Access logging provides an audit trail
63
+ * of all object-level operations for security monitoring and
64
+ * troubleshooting.
65
+ *
13
66
  * @see https://docs.aws.amazon.com/wellarchitected/latest/security-pillar/sec_detect_investigate_events_app_service_logging.html
14
67
  */
15
- accessLogging: true,
16
- /**
17
- * Default prefix for server access log object keys in the auto-created
18
- * logging bucket.
19
- */
20
- accessLogsPrefix: "logs/",
68
+ serverAccessLogs: { prefix: "logs/" },
21
69
  /**
22
70
  * Block all public access to the bucket. S3 buckets should not be
23
71
  * publicly accessible unless explicitly required (e.g. static website
@@ -42,6 +90,17 @@ export const BUCKET_DEFAULTS = {
42
90
  * @see https://docs.aws.amazon.com/AmazonS3/latest/userguide/Versioning.html
43
91
  */
44
92
  versioned: true,
93
+ /**
94
+ * Bound storage cost on every bucket: abort orphaned multipart uploads
95
+ * after 7 days and expire noncurrent object versions after 365 days.
96
+ *
97
+ * Override with `.lifecycleRules([...])` to supply your own rule set —
98
+ * the array is replaced wholesale, consistent with how every other
99
+ * builder default is overridden.
100
+ *
101
+ * @see {@link DEFAULT_BUCKET_LIFECYCLE_RULES}
102
+ */
103
+ lifecycleRules: DEFAULT_BUCKET_LIFECYCLE_RULES,
45
104
  /**
46
105
  * Retain the bucket on stack deletion to prevent data loss.
47
106
  *
@@ -1 +1 @@
1
- {"version":3,"file":"defaults.js","sourceRoot":"","sources":["../src/defaults.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACzE,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAG5C;;;;GAIG;AACH,MAAM,CAAC,MAAM,eAAe,GAAgC;IAC1D;;;;;OAKG;IACH,aAAa,EAAE,IAAI;IAEnB;;;OAGG;IACH,gBAAgB,EAAE,OAAO;IAEzB;;;;;OAKG;IACH,iBAAiB,EAAE,iBAAiB,CAAC,SAAS;IAE9C;;;;OAIG;IACH,UAAU,EAAE,gBAAgB,CAAC,UAAU;IAEvC;;;OAGG;IACH,UAAU,EAAE,IAAI;IAEhB;;;;OAIG;IACH,SAAS,EAAE,IAAI;IAEf;;;;;;;;OAQG;IACH,aAAa,EAAE,aAAa,CAAC,MAAM;CACpC,CAAC"}
1
+ {"version":3,"file":"defaults.js","sourceRoot":"","sources":["../src/defaults.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAsB,MAAM,oBAAoB,CAAC;AAC7F,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAGtD;;;;;;;GAOG;AACH,MAAM,kCAAkC,GAAkB;IACxD,EAAE,EAAE,0CAA0C;IAC9C,mCAAmC,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;CACtD,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,8BAA8B,GAAoB;IAC7D,kCAAkC;IAClC;QACE;;;;;;;WAOG;QACH,EAAE,EAAE,sCAAsC;QAC1C,2BAA2B,EAAE,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC;KAChD;CACF,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,yCAAyC,GAAoB;IACxE,kCAAkC;IAClC;QACE,EAAE,EAAE,6BAA6B;QACjC,UAAU,EAAE,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC;KAC/B;CACF,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,eAAe,GAAgC;IAC1D;;;;;;;OAOG;IACH,gBAAgB,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE;IAErC;;;;;OAKG;IACH,iBAAiB,EAAE,iBAAiB,CAAC,SAAS;IAE9C;;;;OAIG;IACH,UAAU,EAAE,gBAAgB,CAAC,UAAU;IAEvC;;;OAGG;IACH,UAAU,EAAE,IAAI;IAEhB;;;;OAIG;IACH,SAAS,EAAE,IAAI;IAEf;;;;;;;;;OASG;IACH,cAAc,EAAE,8BAA8B;IAE9C;;;;;;;;OAQG;IACH,aAAa,EAAE,aAAa,CAAC,MAAM;CACpC,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- export { createBucketBuilder, type BucketBuilderProps, type BucketBuilderResult, type IBucketBuilder, } from "./bucket-builder.js";
2
- export { BUCKET_DEFAULTS } from "./defaults.js";
1
+ export { createBucketBuilder, type BucketBuilderProps, type BucketBuilderResult, type IBucketBuilder, type ServerAccessLogsConfig, } from "./bucket-builder.js";
2
+ export { BUCKET_DEFAULTS, DEFAULT_ACCESS_LOG_BUCKET_LIFECYCLE_RULES, DEFAULT_BUCKET_LIFECYCLE_RULES, } from "./defaults.js";
3
3
  export { type BucketAlarmConfig } from "./alarm-config.js";
4
4
  export { BUCKET_ALARM_DEFAULTS } from "./alarm-defaults.js";
5
5
  export { createBucketDeploymentBuilder, type BucketDeploymentBuilderResult, type IBucketDeploymentBuilder, } from "./bucket-deployment-builder.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACxB,KAAK,cAAc,GACpB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EACL,6BAA6B,EAC7B,KAAK,6BAA6B,EAClC,KAAK,wBAAwB,GAC9B,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAAE,KAAK,4BAA4B,EAAE,MAAM,8BAA8B,CAAC;AACjF,OAAO,EAAE,0BAA0B,EAAE,MAAM,iCAAiC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACxB,KAAK,cAAc,EACnB,KAAK,sBAAsB,GAC5B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,eAAe,EACf,yCAAyC,EACzC,8BAA8B,GAC/B,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EACL,6BAA6B,EAC7B,KAAK,6BAA6B,EAClC,KAAK,wBAAwB,GAC9B,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAAE,KAAK,4BAA4B,EAAE,MAAM,8BAA8B,CAAC;AACjF,OAAO,EAAE,0BAA0B,EAAE,MAAM,iCAAiC,CAAC"}
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  export { createBucketBuilder, } from "./bucket-builder.js";
2
- export { BUCKET_DEFAULTS } from "./defaults.js";
2
+ export { BUCKET_DEFAULTS, DEFAULT_ACCESS_LOG_BUCKET_LIFECYCLE_RULES, DEFAULT_BUCKET_LIFECYCLE_RULES, } from "./defaults.js";
3
3
  export { BUCKET_ALARM_DEFAULTS } from "./alarm-defaults.js";
4
4
  export { createBucketDeploymentBuilder, } from "./bucket-deployment-builder.js";
5
5
  export { BUCKET_DEPLOYMENT_DEFAULTS } from "./bucket-deployment-defaults.js";
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,GAIpB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhD,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EACL,6BAA6B,GAG9B,MAAM,gCAAgC,CAAC;AAExC,OAAO,EAAE,0BAA0B,EAAE,MAAM,iCAAiC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,GAKpB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,eAAe,EACf,yCAAyC,EACzC,8BAA8B,GAC/B,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EACL,6BAA6B,GAG9B,MAAM,gCAAgC,CAAC;AAExC,OAAO,EAAE,0BAA0B,EAAE,MAAM,iCAAiC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@composurecdk/s3",
3
- "version": "0.4.8",
3
+ "version": "0.5.1",
4
4
  "description": "Composable S3 bucket builder with well-architected defaults",
5
5
  "repository": {
6
6
  "type": "git",
@@ -35,9 +35,9 @@
35
35
  },
36
36
  "type": "module",
37
37
  "peerDependencies": {
38
- "@composurecdk/cloudwatch": "^0.4.0",
39
- "@composurecdk/core": "^0.4.0",
40
- "@composurecdk/logs": "^0.4.0",
38
+ "@composurecdk/cloudwatch": "^0.5.0",
39
+ "@composurecdk/core": "^0.5.0",
40
+ "@composurecdk/logs": "^0.5.0",
41
41
  "aws-cdk-lib": "^2.0.0",
42
42
  "constructs": "^10.0.0"
43
43
  },