@composurecdk/ec2 0.8.0 → 0.8.2
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 +68 -0
- package/dist/commonjs/index.d.ts +2 -0
- package/dist/commonjs/index.d.ts.map +1 -1
- package/dist/commonjs/index.js +5 -1
- package/dist/commonjs/index.js.map +1 -1
- package/dist/commonjs/security-group-builder.d.ts +148 -0
- package/dist/commonjs/security-group-builder.d.ts.map +1 -0
- package/dist/commonjs/security-group-builder.js +146 -0
- package/dist/commonjs/security-group-builder.js.map +1 -0
- package/dist/commonjs/security-group-defaults.d.ts +13 -0
- package/dist/commonjs/security-group-defaults.d.ts.map +1 -0
- package/dist/commonjs/security-group-defaults.js +27 -0
- package/dist/commonjs/security-group-defaults.js.map +1 -0
- package/dist/esm/index.d.ts +2 -0
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +2 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/security-group-builder.d.ts +148 -0
- package/dist/esm/security-group-builder.d.ts.map +1 -0
- package/dist/esm/security-group-builder.js +143 -0
- package/dist/esm/security-group-builder.js.map +1 -0
- package/dist/esm/security-group-defaults.d.ts +13 -0
- package/dist/esm/security-group-defaults.d.ts.map +1 -0
- package/dist/esm/security-group-defaults.js +24 -0
- package/dist/esm/security-group-defaults.js.map +1 -0
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -220,6 +220,74 @@ createVpcBuilder().flowLogs(false);
|
|
|
220
220
|
|
|
221
221
|
For multiple flow logs against the same VPC, omit this config and create additional `FlowLog` constructs directly against the returned `vpc`.
|
|
222
222
|
|
|
223
|
+
## Security Group Builder
|
|
224
|
+
|
|
225
|
+
```ts
|
|
226
|
+
import { createSecurityGroupBuilder } from "@composurecdk/ec2";
|
|
227
|
+
import { Peer, Port } from "aws-cdk-lib/aws-ec2";
|
|
228
|
+
|
|
229
|
+
const web = createSecurityGroupBuilder()
|
|
230
|
+
.vpc(vpc)
|
|
231
|
+
.description("Public web tier")
|
|
232
|
+
.addIngressRule(Peer.anyIpv4(), Port.tcp(443), "Public HTTPS")
|
|
233
|
+
.addEgressRule(Peer.anyIpv4(), Port.tcp(443), "HTTPS to origin")
|
|
234
|
+
.build(stack, "WebSg");
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
Every [SecurityGroupProps](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.SecurityGroupProps.html) property is available as a fluent setter on the builder, except `vpc` which is set via the dedicated `.vpc()` method to support cross-component wiring with `ref<T>(...)`.
|
|
238
|
+
|
|
239
|
+
Ingress and egress rules are accumulated via `addIngressRule`, `addEgressRule`, and `addSelfIngress` (for the intra-SG "allow within the cluster" pattern). Each peer is a `Resolvable<IPeer>`, so it can be a concrete `IPeer` (a CIDR via `Peer.ipv4(...)`, another `ISecurityGroup`, a prefix list, …) or a `Ref` to a sibling component's output.
|
|
240
|
+
|
|
241
|
+
### Security Group Defaults
|
|
242
|
+
|
|
243
|
+
| Property | Default | Rationale |
|
|
244
|
+
| ------------------ | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
245
|
+
| `allowAllOutbound` | `false` | Closes the implicit `0.0.0.0/0` egress rule CDK ships by default. Every outbound flow becomes an explicit `addEgressRule` — the least-privilege default. |
|
|
246
|
+
|
|
247
|
+
Two properties intentionally have no default — they are application-specific and must be supplied explicitly:
|
|
248
|
+
|
|
249
|
+
- `vpc` (via the `.vpc()` method)
|
|
250
|
+
- `description` (a short, human-readable summary of the SG's purpose; whitespace-only values are rejected)
|
|
251
|
+
|
|
252
|
+
The defaults are exported as `SECURITY_GROUP_DEFAULTS` for visibility and testing:
|
|
253
|
+
|
|
254
|
+
```ts
|
|
255
|
+
import { SECURITY_GROUP_DEFAULTS } from "@composurecdk/ec2";
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
### Wiring two SGs via `ref`
|
|
259
|
+
|
|
260
|
+
The canonical cross-component pattern — a bastion SG and a database SG that talks to it — declares the dependency in `compose()` and resolves the peer at build time:
|
|
261
|
+
|
|
262
|
+
```ts
|
|
263
|
+
import { compose, ref } from "@composurecdk/core";
|
|
264
|
+
import { createSecurityGroupBuilder, createVpcBuilder } from "@composurecdk/ec2";
|
|
265
|
+
import type { SecurityGroupBuilderResult, VpcBuilderResult } from "@composurecdk/ec2";
|
|
266
|
+
import { Port } from "aws-cdk-lib/aws-ec2";
|
|
267
|
+
|
|
268
|
+
compose(
|
|
269
|
+
{
|
|
270
|
+
network: createVpcBuilder(),
|
|
271
|
+
bastion: createSecurityGroupBuilder()
|
|
272
|
+
.vpc(ref<VpcBuilderResult>("network").get("vpc"))
|
|
273
|
+
.description("Bastion host"),
|
|
274
|
+
database: createSecurityGroupBuilder()
|
|
275
|
+
.vpc(ref<VpcBuilderResult>("network").get("vpc"))
|
|
276
|
+
.description("Database")
|
|
277
|
+
.addIngressRule(
|
|
278
|
+
ref<SecurityGroupBuilderResult>("bastion").get("securityGroup"),
|
|
279
|
+
Port.tcp(5432),
|
|
280
|
+
"Bastion to Postgres",
|
|
281
|
+
),
|
|
282
|
+
},
|
|
283
|
+
{ network: [], bastion: ["network"], database: ["network", "bastion"] },
|
|
284
|
+
).build(stack, "App");
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
### Recommended Alarms
|
|
288
|
+
|
|
289
|
+
The Security Group builder does **not** create CloudWatch alarms. Security groups do not emit CloudWatch metrics — the [AWS recommended-alarms reference](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Best_Practice_Recommended_Alarms_AWS_Services.html) has no SG entry. Operational visibility for SGs comes from adjacent signals (VPC Flow Logs, GuardDuty findings, CloudTrail `AuthorizeSecurityGroupIngress`/`Egress` events), none of which belong on the builder result.
|
|
290
|
+
|
|
223
291
|
## Volume Builder
|
|
224
292
|
|
|
225
293
|
```ts
|
package/dist/commonjs/index.d.ts
CHANGED
|
@@ -11,4 +11,6 @@ export { type VolumeAlarmConfig } from "./volume-alarm-config.js";
|
|
|
11
11
|
export { VOLUME_ALARM_DEFAULTS } from "./volume-alarm-defaults.js";
|
|
12
12
|
export { createVpcBuilder, type FlowLogsConfig, type IVpcBuilder, type VpcBuilderProps, type VpcBuilderResult, } from "./vpc-builder.js";
|
|
13
13
|
export { VPC_DEFAULTS } from "./vpc-defaults.js";
|
|
14
|
+
export { createSecurityGroupBuilder, type ISecurityGroupBuilder, type SecurityGroupBuilderProps, type SecurityGroupBuilderResult, } from "./security-group-builder.js";
|
|
15
|
+
export { SECURITY_GROUP_DEFAULTS } from "./security-group-defaults.js";
|
|
14
16
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,EACrB,KAAK,gBAAgB,EACrB,KAAK,oBAAoB,EACzB,KAAK,qBAAqB,GAC3B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,KAAK,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACtE,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AACvE,OAAO,EAAE,KAAK,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AAC5E,OAAO,EAAE,KAAK,2BAA2B,EAAE,MAAM,wCAAwC,CAAC;AAC1F,OAAO,EAAE,gCAAgC,EAAE,MAAM,0CAA0C,CAAC;AAE5F,OAAO,EACL,mBAAmB,EACnB,KAAK,cAAc,EACnB,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,GACzB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAEnE,OAAO,EACL,gBAAgB,EAChB,KAAK,cAAc,EACnB,KAAK,WAAW,EAChB,KAAK,eAAe,EACpB,KAAK,gBAAgB,GACtB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,EACrB,KAAK,gBAAgB,EACrB,KAAK,oBAAoB,EACzB,KAAK,qBAAqB,GAC3B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,KAAK,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACtE,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AACvE,OAAO,EAAE,KAAK,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AAC5E,OAAO,EAAE,KAAK,2BAA2B,EAAE,MAAM,wCAAwC,CAAC;AAC1F,OAAO,EAAE,gCAAgC,EAAE,MAAM,0CAA0C,CAAC;AAE5F,OAAO,EACL,mBAAmB,EACnB,KAAK,cAAc,EACnB,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,GACzB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAEnE,OAAO,EACL,gBAAgB,EAChB,KAAK,cAAc,EACnB,KAAK,WAAW,EAChB,KAAK,eAAe,EACpB,KAAK,gBAAgB,GACtB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,OAAO,EACL,0BAA0B,EAC1B,KAAK,qBAAqB,EAC1B,KAAK,yBAAyB,EAC9B,KAAK,0BAA0B,GAChC,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC"}
|
package/dist/commonjs/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.VPC_DEFAULTS = exports.createVpcBuilder = exports.VOLUME_ALARM_DEFAULTS = exports.VOLUME_DEFAULTS = exports.createVolumeBuilder = exports.VOLUME_ATTACHMENT_ALARM_DEFAULTS = exports.INSTANCE_ALARM_DEFAULTS = exports.INSTANCE_DEFAULTS = exports.createInstanceBuilder = void 0;
|
|
3
|
+
exports.SECURITY_GROUP_DEFAULTS = exports.createSecurityGroupBuilder = exports.VPC_DEFAULTS = exports.createVpcBuilder = exports.VOLUME_ALARM_DEFAULTS = exports.VOLUME_DEFAULTS = exports.createVolumeBuilder = exports.VOLUME_ATTACHMENT_ALARM_DEFAULTS = exports.INSTANCE_ALARM_DEFAULTS = exports.INSTANCE_DEFAULTS = exports.createInstanceBuilder = void 0;
|
|
4
4
|
var instance_builder_js_1 = require("./instance-builder.js");
|
|
5
5
|
Object.defineProperty(exports, "createInstanceBuilder", { enumerable: true, get: function () { return instance_builder_js_1.createInstanceBuilder; } });
|
|
6
6
|
var instance_defaults_js_1 = require("./instance-defaults.js");
|
|
@@ -19,4 +19,8 @@ var vpc_builder_js_1 = require("./vpc-builder.js");
|
|
|
19
19
|
Object.defineProperty(exports, "createVpcBuilder", { enumerable: true, get: function () { return vpc_builder_js_1.createVpcBuilder; } });
|
|
20
20
|
var vpc_defaults_js_1 = require("./vpc-defaults.js");
|
|
21
21
|
Object.defineProperty(exports, "VPC_DEFAULTS", { enumerable: true, get: function () { return vpc_defaults_js_1.VPC_DEFAULTS; } });
|
|
22
|
+
var security_group_builder_js_1 = require("./security-group-builder.js");
|
|
23
|
+
Object.defineProperty(exports, "createSecurityGroupBuilder", { enumerable: true, get: function () { return security_group_builder_js_1.createSecurityGroupBuilder; } });
|
|
24
|
+
var security_group_defaults_js_1 = require("./security-group-defaults.js");
|
|
25
|
+
Object.defineProperty(exports, "SECURITY_GROUP_DEFAULTS", { enumerable: true, get: function () { return security_group_defaults_js_1.SECURITY_GROUP_DEFAULTS; } });
|
|
22
26
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;AAAA,6DAK+B;AAJ7B,4HAAA,qBAAqB,OAAA;AAKvB,+DAA2D;AAAlD,yHAAA,iBAAiB,OAAA;AAE1B,2EAAuE;AAA9D,qIAAA,uBAAuB,OAAA;AAGhC,mGAA4F;AAAnF,0JAAA,gCAAgC,OAAA;AAEzC,yDAK6B;AAJ3B,wHAAA,mBAAmB,OAAA;AAKrB,2DAAuD;AAA9C,qHAAA,eAAe,OAAA;AAExB,uEAAmE;AAA1D,iIAAA,qBAAqB,OAAA;AAE9B,mDAM0B;AALxB,kHAAA,gBAAgB,OAAA;AAMlB,qDAAiD;AAAxC,+GAAA,YAAY,OAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;AAAA,6DAK+B;AAJ7B,4HAAA,qBAAqB,OAAA;AAKvB,+DAA2D;AAAlD,yHAAA,iBAAiB,OAAA;AAE1B,2EAAuE;AAA9D,qIAAA,uBAAuB,OAAA;AAGhC,mGAA4F;AAAnF,0JAAA,gCAAgC,OAAA;AAEzC,yDAK6B;AAJ3B,wHAAA,mBAAmB,OAAA;AAKrB,2DAAuD;AAA9C,qHAAA,eAAe,OAAA;AAExB,uEAAmE;AAA1D,iIAAA,qBAAqB,OAAA;AAE9B,mDAM0B;AALxB,kHAAA,gBAAgB,OAAA;AAMlB,qDAAiD;AAAxC,+GAAA,YAAY,OAAA;AAErB,yEAKqC;AAJnC,uIAAA,0BAA0B,OAAA;AAK5B,2EAAuE;AAA9D,qIAAA,uBAAuB,OAAA"}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { type IPeer, type IVpc, type Port, SecurityGroup, type SecurityGroupProps } from "aws-cdk-lib/aws-ec2";
|
|
2
|
+
import { type IConstruct } from "constructs";
|
|
3
|
+
import { COPY_STATE, type Lifecycle, type Resolvable } from "@composurecdk/core";
|
|
4
|
+
import { type ITaggedBuilder } from "@composurecdk/cloudformation";
|
|
5
|
+
/**
|
|
6
|
+
* Configuration properties for the security group builder.
|
|
7
|
+
*
|
|
8
|
+
* Extends the CDK {@link SecurityGroupProps} but lifts `vpc` off the props
|
|
9
|
+
* object — it is supplied via the dedicated
|
|
10
|
+
* {@link ISecurityGroupBuilder.vpc | .vpc()} method so it can accept a
|
|
11
|
+
* {@link Resolvable} for cross-component wiring (e.g. a sibling
|
|
12
|
+
* `VpcBuilder`).
|
|
13
|
+
*
|
|
14
|
+
* Ingress and egress rules are added imperatively via
|
|
15
|
+
* {@link ISecurityGroupBuilder.addIngressRule | .addIngressRule()},
|
|
16
|
+
* {@link ISecurityGroupBuilder.addEgressRule | .addEgressRule()}, and
|
|
17
|
+
* {@link ISecurityGroupBuilder.addSelfIngress | .addSelfIngress()} so each
|
|
18
|
+
* peer can also be a {@link Resolvable}.
|
|
19
|
+
*/
|
|
20
|
+
export type SecurityGroupBuilderProps = Omit<SecurityGroupProps, "vpc">;
|
|
21
|
+
/**
|
|
22
|
+
* The build output of an {@link ISecurityGroupBuilder}. Contains the CDK
|
|
23
|
+
* constructs created during {@link Lifecycle.build}, keyed by role.
|
|
24
|
+
*
|
|
25
|
+
* The `securityGroup` is itself an `IConnectable` and `IPeer`, so consumers
|
|
26
|
+
* compose against it directly — there is no separate `connections` field on
|
|
27
|
+
* the result.
|
|
28
|
+
*
|
|
29
|
+
* The builder creates no CloudWatch alarms. Security groups do not emit
|
|
30
|
+
* CloudWatch metrics, so the
|
|
31
|
+
* [recommended-alarms reference](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Best_Practice_Recommended_Alarms_AWS_Services.html)
|
|
32
|
+
* has no SG entry. Operational visibility comes from adjacent signals —
|
|
33
|
+
* VPC Flow Logs, GuardDuty findings, CloudTrail authorize-events.
|
|
34
|
+
*/
|
|
35
|
+
export interface SecurityGroupBuilderResult {
|
|
36
|
+
securityGroup: SecurityGroup;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* A fluent builder for configuring and creating an AWS EC2 security group.
|
|
40
|
+
*
|
|
41
|
+
* Each configuration property from the CDK {@link SecurityGroupProps} (other
|
|
42
|
+
* than `vpc`) is exposed as an overloaded method: call with a value to set
|
|
43
|
+
* it, or with no arguments to read it. The `vpc` is set via the dedicated
|
|
44
|
+
* {@link ISecurityGroupBuilder.vpc | .vpc()} method that accepts a
|
|
45
|
+
* {@link Resolvable} for cross-component wiring with sibling builders.
|
|
46
|
+
*
|
|
47
|
+
* Ingress and egress rules are accumulated via
|
|
48
|
+
* {@link ISecurityGroupBuilder.addIngressRule | .addIngressRule()},
|
|
49
|
+
* {@link ISecurityGroupBuilder.addEgressRule | .addEgressRule()}, and
|
|
50
|
+
* {@link ISecurityGroupBuilder.addSelfIngress | .addSelfIngress()} and
|
|
51
|
+
* applied when {@link Lifecycle.build | build()} runs. Each peer is a
|
|
52
|
+
* {@link Resolvable} so it can be a concrete `IPeer` (including another
|
|
53
|
+
* `ISecurityGroup`) or a {@link ref | Ref} to a sibling component's output.
|
|
54
|
+
*
|
|
55
|
+
* The builder implements {@link Lifecycle}, so it can be used directly as a
|
|
56
|
+
* component in a {@link compose | composed system}.
|
|
57
|
+
*
|
|
58
|
+
* @see https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.SecurityGroup.html
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* ```ts
|
|
62
|
+
* compose(
|
|
63
|
+
* {
|
|
64
|
+
* network: createVpcBuilder(),
|
|
65
|
+
* bastion: createSecurityGroupBuilder()
|
|
66
|
+
* .vpc(ref<VpcBuilderResult>("network").get("vpc"))
|
|
67
|
+
* .description("Bastion host"),
|
|
68
|
+
* database: createSecurityGroupBuilder()
|
|
69
|
+
* .vpc(ref<VpcBuilderResult>("network").get("vpc"))
|
|
70
|
+
* .description("Database")
|
|
71
|
+
* .addIngressRule(
|
|
72
|
+
* ref<SecurityGroupBuilderResult>("bastion").get("securityGroup"),
|
|
73
|
+
* Port.tcp(5432),
|
|
74
|
+
* "Bastion to Postgres",
|
|
75
|
+
* ),
|
|
76
|
+
* },
|
|
77
|
+
* { network: [], bastion: ["network"], database: ["network", "bastion"] },
|
|
78
|
+
* );
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
81
|
+
export type ISecurityGroupBuilder = ITaggedBuilder<SecurityGroupBuilderProps, SecurityGroupBuilder>;
|
|
82
|
+
declare class SecurityGroupBuilder implements Lifecycle<SecurityGroupBuilderResult> {
|
|
83
|
+
#private;
|
|
84
|
+
props: Partial<SecurityGroupBuilderProps>;
|
|
85
|
+
/**
|
|
86
|
+
* Sets the VPC the security group is created in.
|
|
87
|
+
*
|
|
88
|
+
* Accepts a concrete {@link IVpc} or a {@link Ref} that resolves to one
|
|
89
|
+
* at build time — e.g. a sibling {@link IVpcBuilder} in the same
|
|
90
|
+
* composed system.
|
|
91
|
+
*
|
|
92
|
+
* @param vpc - The VPC or a Ref to one.
|
|
93
|
+
* @returns This builder for chaining.
|
|
94
|
+
*/
|
|
95
|
+
vpc(vpc: Resolvable<IVpc>): this;
|
|
96
|
+
/**
|
|
97
|
+
* Adds an ingress rule. The peer accepts any {@link IPeer} — a concrete
|
|
98
|
+
* `Peer.ipv4(...)`, another `ISecurityGroup`, a prefix list — or a
|
|
99
|
+
* {@link Ref} that resolves to one.
|
|
100
|
+
*
|
|
101
|
+
* @param peer - The source of the allowed traffic.
|
|
102
|
+
* @param port - The port or port range.
|
|
103
|
+
* @param description - Optional human-readable description of the rule.
|
|
104
|
+
* @returns This builder for chaining.
|
|
105
|
+
*/
|
|
106
|
+
addIngressRule(peer: Resolvable<IPeer>, port: Port, description?: string): this;
|
|
107
|
+
/**
|
|
108
|
+
* Adds an egress rule. Required when `allowAllOutbound` is `false`
|
|
109
|
+
* (the builder default — see {@link SECURITY_GROUP_DEFAULTS}). The peer
|
|
110
|
+
* accepts any {@link IPeer} or a {@link Ref} that resolves to one.
|
|
111
|
+
*
|
|
112
|
+
* @param peer - The destination of the allowed traffic.
|
|
113
|
+
* @param port - The port or port range.
|
|
114
|
+
* @param description - Optional human-readable description of the rule.
|
|
115
|
+
* @returns This builder for chaining.
|
|
116
|
+
*/
|
|
117
|
+
addEgressRule(peer: Resolvable<IPeer>, port: Port, description?: string): this;
|
|
118
|
+
/**
|
|
119
|
+
* Adds an ingress rule whose peer is the security group itself —
|
|
120
|
+
* the canonical "allow intra-SG traffic on port N" pattern. The peer
|
|
121
|
+
* cannot be expressed at configuration time because the security group
|
|
122
|
+
* identity does not exist yet; the builder wires it after the SG is
|
|
123
|
+
* constructed.
|
|
124
|
+
*
|
|
125
|
+
* @param port - The port or port range.
|
|
126
|
+
* @param description - Optional human-readable description of the rule.
|
|
127
|
+
* @returns This builder for chaining.
|
|
128
|
+
*/
|
|
129
|
+
addSelfIngress(port: Port, description?: string): this;
|
|
130
|
+
/** @internal — see ADR-0005. */
|
|
131
|
+
[COPY_STATE](target: SecurityGroupBuilder): void;
|
|
132
|
+
build(scope: IConstruct, id: string, context?: Record<string, object>): SecurityGroupBuilderResult;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Creates a new {@link ISecurityGroupBuilder} for configuring an AWS EC2
|
|
136
|
+
* security group.
|
|
137
|
+
*
|
|
138
|
+
* The returned builder exposes every {@link SecurityGroupBuilderProps}
|
|
139
|
+
* property as a fluent setter/getter, plus
|
|
140
|
+
* {@link ISecurityGroupBuilder.vpc | .vpc()} for cross-component VPC wiring
|
|
141
|
+
* and the `addIngressRule` / `addEgressRule` / `addSelfIngress` accumulators.
|
|
142
|
+
* It implements {@link Lifecycle} for use with {@link compose}.
|
|
143
|
+
*
|
|
144
|
+
* @returns A fluent builder for an AWS EC2 security group.
|
|
145
|
+
*/
|
|
146
|
+
export declare function createSecurityGroupBuilder(): ISecurityGroupBuilder;
|
|
147
|
+
export {};
|
|
148
|
+
//# sourceMappingURL=security-group-builder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"security-group-builder.d.ts","sourceRoot":"","sources":["../../src/security-group-builder.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,KAAK,EACV,KAAK,IAAI,EACT,KAAK,IAAI,EACT,aAAa,EACb,KAAK,kBAAkB,EACxB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,KAAK,SAAS,EAAW,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAC1F,OAAO,EAAE,KAAK,cAAc,EAAiB,MAAM,8BAA8B,CAAC;AAGlF;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,yBAAyB,GAAG,IAAI,CAAC,kBAAkB,EAAE,KAAK,CAAC,CAAC;AAExE;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,0BAA0B;IACzC,aAAa,EAAE,aAAa,CAAC;CAC9B;AAcD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,MAAM,MAAM,qBAAqB,GAAG,cAAc,CAAC,yBAAyB,EAAE,oBAAoB,CAAC,CAAC;AAEpG,cAAM,oBAAqB,YAAW,SAAS,CAAC,0BAA0B,CAAC;;IACzE,KAAK,EAAE,OAAO,CAAC,yBAAyB,CAAC,CAAM;IAK/C;;;;;;;;;OASG;IACH,GAAG,CAAC,GAAG,EAAE,UAAU,CAAC,IAAI,CAAC,GAAG,IAAI;IAKhC;;;;;;;;;OASG;IACH,cAAc,CAAC,IAAI,EAAE,UAAU,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI;IAU/E;;;;;;;;;OASG;IACH,aAAa,CAAC,IAAI,EAAE,UAAU,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI;IAU9E;;;;;;;;;;OAUG;IACH,cAAc,CAAC,IAAI,EAAE,IAAI,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI;IAQtD,gCAAgC;IAChC,CAAC,UAAU,CAAC,CAAC,MAAM,EAAE,oBAAoB,GAAG,IAAI;IAMhD,KAAK,CACH,KAAK,EAAE,UAAU,EACjB,EAAE,EAAE,MAAM,EACV,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,0BAA0B;CAiD9B;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,0BAA0B,IAAI,qBAAqB,CAElE"}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createSecurityGroupBuilder = createSecurityGroupBuilder;
|
|
4
|
+
const aws_ec2_1 = require("aws-cdk-lib/aws-ec2");
|
|
5
|
+
const core_1 = require("@composurecdk/core");
|
|
6
|
+
const cloudformation_1 = require("@composurecdk/cloudformation");
|
|
7
|
+
const security_group_defaults_js_1 = require("./security-group-defaults.js");
|
|
8
|
+
class SecurityGroupBuilder {
|
|
9
|
+
props = {};
|
|
10
|
+
#peerRules = [];
|
|
11
|
+
#selfIngress = [];
|
|
12
|
+
#vpc;
|
|
13
|
+
/**
|
|
14
|
+
* Sets the VPC the security group is created in.
|
|
15
|
+
*
|
|
16
|
+
* Accepts a concrete {@link IVpc} or a {@link Ref} that resolves to one
|
|
17
|
+
* at build time — e.g. a sibling {@link IVpcBuilder} in the same
|
|
18
|
+
* composed system.
|
|
19
|
+
*
|
|
20
|
+
* @param vpc - The VPC or a Ref to one.
|
|
21
|
+
* @returns This builder for chaining.
|
|
22
|
+
*/
|
|
23
|
+
vpc(vpc) {
|
|
24
|
+
this.#vpc = vpc;
|
|
25
|
+
return this;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Adds an ingress rule. The peer accepts any {@link IPeer} — a concrete
|
|
29
|
+
* `Peer.ipv4(...)`, another `ISecurityGroup`, a prefix list — or a
|
|
30
|
+
* {@link Ref} that resolves to one.
|
|
31
|
+
*
|
|
32
|
+
* @param peer - The source of the allowed traffic.
|
|
33
|
+
* @param port - The port or port range.
|
|
34
|
+
* @param description - Optional human-readable description of the rule.
|
|
35
|
+
* @returns This builder for chaining.
|
|
36
|
+
*/
|
|
37
|
+
addIngressRule(peer, port, description) {
|
|
38
|
+
this.#peerRules.push({
|
|
39
|
+
direction: "ingress",
|
|
40
|
+
peer,
|
|
41
|
+
port,
|
|
42
|
+
...(description !== undefined ? { description } : {}),
|
|
43
|
+
});
|
|
44
|
+
return this;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Adds an egress rule. Required when `allowAllOutbound` is `false`
|
|
48
|
+
* (the builder default — see {@link SECURITY_GROUP_DEFAULTS}). The peer
|
|
49
|
+
* accepts any {@link IPeer} or a {@link Ref} that resolves to one.
|
|
50
|
+
*
|
|
51
|
+
* @param peer - The destination of the allowed traffic.
|
|
52
|
+
* @param port - The port or port range.
|
|
53
|
+
* @param description - Optional human-readable description of the rule.
|
|
54
|
+
* @returns This builder for chaining.
|
|
55
|
+
*/
|
|
56
|
+
addEgressRule(peer, port, description) {
|
|
57
|
+
this.#peerRules.push({
|
|
58
|
+
direction: "egress",
|
|
59
|
+
peer,
|
|
60
|
+
port,
|
|
61
|
+
...(description !== undefined ? { description } : {}),
|
|
62
|
+
});
|
|
63
|
+
return this;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Adds an ingress rule whose peer is the security group itself —
|
|
67
|
+
* the canonical "allow intra-SG traffic on port N" pattern. The peer
|
|
68
|
+
* cannot be expressed at configuration time because the security group
|
|
69
|
+
* identity does not exist yet; the builder wires it after the SG is
|
|
70
|
+
* constructed.
|
|
71
|
+
*
|
|
72
|
+
* @param port - The port or port range.
|
|
73
|
+
* @param description - Optional human-readable description of the rule.
|
|
74
|
+
* @returns This builder for chaining.
|
|
75
|
+
*/
|
|
76
|
+
addSelfIngress(port, description) {
|
|
77
|
+
this.#selfIngress.push({
|
|
78
|
+
port,
|
|
79
|
+
...(description !== undefined ? { description } : {}),
|
|
80
|
+
});
|
|
81
|
+
return this;
|
|
82
|
+
}
|
|
83
|
+
/** @internal — see ADR-0005. */
|
|
84
|
+
[core_1.COPY_STATE](target) {
|
|
85
|
+
target.#vpc = this.#vpc;
|
|
86
|
+
target.#peerRules.push(...this.#peerRules);
|
|
87
|
+
target.#selfIngress.push(...this.#selfIngress);
|
|
88
|
+
}
|
|
89
|
+
build(scope, id, context) {
|
|
90
|
+
const resolvedVpc = this.#vpc ? (0, core_1.resolve)(this.#vpc, context) : undefined;
|
|
91
|
+
if (!resolvedVpc) {
|
|
92
|
+
throw new Error(`SecurityGroupBuilder "${id}" requires a VPC. ` +
|
|
93
|
+
"Call .vpc() with an IVpc or a Ref to one.");
|
|
94
|
+
}
|
|
95
|
+
if (this.props.description === undefined || this.props.description.trim() === "") {
|
|
96
|
+
throw new Error(`SecurityGroupBuilder "${id}" requires a description. ` +
|
|
97
|
+
"Call .description() with a short summary of the SG's purpose.");
|
|
98
|
+
}
|
|
99
|
+
// Drop keys whose value is `undefined` so a fluent call like
|
|
100
|
+
// `.allowAllOutbound(undefined)` (common in "optional override" code:
|
|
101
|
+
// `b.allowAllOutbound(cfg?.allowAllOutbound)`) does not clobber the
|
|
102
|
+
// closed-egress default with explicit `undefined`.
|
|
103
|
+
const userProps = {};
|
|
104
|
+
for (const key of Object.keys(this.props)) {
|
|
105
|
+
const value = this.props[key];
|
|
106
|
+
if (value !== undefined) {
|
|
107
|
+
userProps[key] = value;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
const mergedProps = {
|
|
111
|
+
...security_group_defaults_js_1.SECURITY_GROUP_DEFAULTS,
|
|
112
|
+
...userProps,
|
|
113
|
+
vpc: resolvedVpc,
|
|
114
|
+
};
|
|
115
|
+
const securityGroup = new aws_ec2_1.SecurityGroup(scope, id, mergedProps);
|
|
116
|
+
for (const rule of this.#peerRules) {
|
|
117
|
+
const peer = (0, core_1.resolve)(rule.peer, context);
|
|
118
|
+
if (rule.direction === "ingress") {
|
|
119
|
+
securityGroup.addIngressRule(peer, rule.port, rule.description);
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
securityGroup.addEgressRule(peer, rule.port, rule.description);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
for (const rule of this.#selfIngress) {
|
|
126
|
+
securityGroup.addIngressRule(securityGroup, rule.port, rule.description);
|
|
127
|
+
}
|
|
128
|
+
return { securityGroup };
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Creates a new {@link ISecurityGroupBuilder} for configuring an AWS EC2
|
|
133
|
+
* security group.
|
|
134
|
+
*
|
|
135
|
+
* The returned builder exposes every {@link SecurityGroupBuilderProps}
|
|
136
|
+
* property as a fluent setter/getter, plus
|
|
137
|
+
* {@link ISecurityGroupBuilder.vpc | .vpc()} for cross-component VPC wiring
|
|
138
|
+
* and the `addIngressRule` / `addEgressRule` / `addSelfIngress` accumulators.
|
|
139
|
+
* It implements {@link Lifecycle} for use with {@link compose}.
|
|
140
|
+
*
|
|
141
|
+
* @returns A fluent builder for an AWS EC2 security group.
|
|
142
|
+
*/
|
|
143
|
+
function createSecurityGroupBuilder() {
|
|
144
|
+
return (0, cloudformation_1.taggedBuilder)(SecurityGroupBuilder);
|
|
145
|
+
}
|
|
146
|
+
//# sourceMappingURL=security-group-builder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"security-group-builder.js","sourceRoot":"","sources":["../../src/security-group-builder.ts"],"names":[],"mappings":";;AAkQA,gEAEC;AApQD,iDAM6B;AAE7B,6CAA0F;AAC1F,iEAAkF;AAClF,6EAAuE;AA8FvE,MAAM,oBAAoB;IACxB,KAAK,GAAuC,EAAE,CAAC;IACtC,UAAU,GAAmB,EAAE,CAAC;IAChC,YAAY,GAAsB,EAAE,CAAC;IAC9C,IAAI,CAAoB;IAExB;;;;;;;;;OASG;IACH,GAAG,CAAC,GAAqB;QACvB,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC;QAChB,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;;;;;;;OASG;IACH,cAAc,CAAC,IAAuB,EAAE,IAAU,EAAE,WAAoB;QACtE,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;YACnB,SAAS,EAAE,SAAS;YACpB,IAAI;YACJ,IAAI;YACJ,GAAG,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACtD,CAAC,CAAC;QACH,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;;;;;;;OASG;IACH,aAAa,CAAC,IAAuB,EAAE,IAAU,EAAE,WAAoB;QACrE,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;YACnB,SAAS,EAAE,QAAQ;YACnB,IAAI;YACJ,IAAI;YACJ,GAAG,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACtD,CAAC,CAAC;QACH,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;;;;;;;;OAUG;IACH,cAAc,CAAC,IAAU,EAAE,WAAoB;QAC7C,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC;YACrB,IAAI;YACJ,GAAG,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACtD,CAAC,CAAC;QACH,OAAO,IAAI,CAAC;IACd,CAAC;IAED,gCAAgC;IAChC,CAAC,iBAAU,CAAC,CAAC,MAA4B;QACvC,MAAM,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;QACxB,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC;QAC3C,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC;IACjD,CAAC;IAED,KAAK,CACH,KAAiB,EACjB,EAAU,EACV,OAAgC;QAEhC,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAA,cAAO,EAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QACxE,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CACb,yBAAyB,EAAE,oBAAoB;gBAC7C,2CAA2C,CAC9C,CAAC;QACJ,CAAC;QACD,IAAI,IAAI,CAAC,KAAK,CAAC,WAAW,KAAK,SAAS,IAAI,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;YACjF,MAAM,IAAI,KAAK,CACb,yBAAyB,EAAE,4BAA4B;gBACrD,+DAA+D,CAClE,CAAC;QACJ,CAAC;QAED,6DAA6D;QAC7D,sEAAsE;QACtE,oEAAoE;QACpE,mDAAmD;QACnD,MAAM,SAAS,GAAuC,EAAE,CAAC;QACzD,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAwC,EAAE,CAAC;YACjF,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAC9B,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gBACvB,SAAqC,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;YACtD,CAAC;QACH,CAAC;QAED,MAAM,WAAW,GAAG;YAClB,GAAG,oDAAuB;YAC1B,GAAG,SAAS;YACZ,GAAG,EAAE,WAAW;SACK,CAAC;QAExB,MAAM,aAAa,GAAG,IAAI,uBAAa,CAAC,KAAK,EAAE,EAAE,EAAE,WAAW,CAAC,CAAC;QAEhE,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACnC,MAAM,IAAI,GAAG,IAAA,cAAO,EAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;YACzC,IAAI,IAAI,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;gBACjC,aAAa,CAAC,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;YAClE,CAAC;iBAAM,CAAC;gBACN,aAAa,CAAC,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;YACjE,CAAC;QACH,CAAC;QACD,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACrC,aAAa,CAAC,cAAc,CAAC,aAAa,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;QAC3E,CAAC;QAED,OAAO,EAAE,aAAa,EAAE,CAAC;IAC3B,CAAC;CACF;AAED;;;;;;;;;;;GAWG;AACH,SAAgB,0BAA0B;IACxC,OAAO,IAAA,8BAAa,EAAkD,oBAAoB,CAAC,CAAC;AAC9F,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { SecurityGroupProps } from "aws-cdk-lib/aws-ec2";
|
|
2
|
+
/**
|
|
3
|
+
* Secure, AWS-recommended defaults applied to every security group built
|
|
4
|
+
* with {@link createSecurityGroupBuilder}. Each property can be individually
|
|
5
|
+
* overridden via the builder's fluent API.
|
|
6
|
+
*
|
|
7
|
+
* Two properties intentionally have no default — they are application-
|
|
8
|
+
* specific and must be supplied explicitly:
|
|
9
|
+
* - `vpc` (via the builder's `.vpc()` method)
|
|
10
|
+
* - `description` (a short, human-readable summary of the SG's purpose)
|
|
11
|
+
*/
|
|
12
|
+
export declare const SECURITY_GROUP_DEFAULTS: Partial<SecurityGroupProps>;
|
|
13
|
+
//# sourceMappingURL=security-group-defaults.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"security-group-defaults.d.ts","sourceRoot":"","sources":["../../src/security-group-defaults.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAE9D;;;;;;;;;GASG;AACH,eAAO,MAAM,uBAAuB,EAAE,OAAO,CAAC,kBAAkB,CAY/D,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SECURITY_GROUP_DEFAULTS = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Secure, AWS-recommended defaults applied to every security group built
|
|
6
|
+
* with {@link createSecurityGroupBuilder}. Each property can be individually
|
|
7
|
+
* overridden via the builder's fluent API.
|
|
8
|
+
*
|
|
9
|
+
* Two properties intentionally have no default — they are application-
|
|
10
|
+
* specific and must be supplied explicitly:
|
|
11
|
+
* - `vpc` (via the builder's `.vpc()` method)
|
|
12
|
+
* - `description` (a short, human-readable summary of the SG's purpose)
|
|
13
|
+
*/
|
|
14
|
+
exports.SECURITY_GROUP_DEFAULTS = {
|
|
15
|
+
/**
|
|
16
|
+
* Closed-by-default egress. CDK's stock default is `true`, which creates
|
|
17
|
+
* an implicit `0.0.0.0/0` outbound rule on every SG — flagged by
|
|
18
|
+
* compliance scanners and incompatible with the project's least-privilege
|
|
19
|
+
* stance. Closing egress forces every outbound flow to be expressed as
|
|
20
|
+
* an explicit `addEgressRule` (or `.allowAllOutbound(true)` to opt back
|
|
21
|
+
* into the CDK default).
|
|
22
|
+
*
|
|
23
|
+
* @see https://docs.aws.amazon.com/wellarchitected/latest/security-pillar/sec_network_protection_layered.html
|
|
24
|
+
*/
|
|
25
|
+
allowAllOutbound: false,
|
|
26
|
+
};
|
|
27
|
+
//# sourceMappingURL=security-group-defaults.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"security-group-defaults.js","sourceRoot":"","sources":["../../src/security-group-defaults.ts"],"names":[],"mappings":";;;AAEA;;;;;;;;;GASG;AACU,QAAA,uBAAuB,GAAgC;IAClE;;;;;;;;;OASG;IACH,gBAAgB,EAAE,KAAK;CACxB,CAAC"}
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -11,4 +11,6 @@ export { type VolumeAlarmConfig } from "./volume-alarm-config.js";
|
|
|
11
11
|
export { VOLUME_ALARM_DEFAULTS } from "./volume-alarm-defaults.js";
|
|
12
12
|
export { createVpcBuilder, type FlowLogsConfig, type IVpcBuilder, type VpcBuilderProps, type VpcBuilderResult, } from "./vpc-builder.js";
|
|
13
13
|
export { VPC_DEFAULTS } from "./vpc-defaults.js";
|
|
14
|
+
export { createSecurityGroupBuilder, type ISecurityGroupBuilder, type SecurityGroupBuilderProps, type SecurityGroupBuilderResult, } from "./security-group-builder.js";
|
|
15
|
+
export { SECURITY_GROUP_DEFAULTS } from "./security-group-defaults.js";
|
|
14
16
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/esm/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,EACrB,KAAK,gBAAgB,EACrB,KAAK,oBAAoB,EACzB,KAAK,qBAAqB,GAC3B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,KAAK,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACtE,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AACvE,OAAO,EAAE,KAAK,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AAC5E,OAAO,EAAE,KAAK,2BAA2B,EAAE,MAAM,wCAAwC,CAAC;AAC1F,OAAO,EAAE,gCAAgC,EAAE,MAAM,0CAA0C,CAAC;AAE5F,OAAO,EACL,mBAAmB,EACnB,KAAK,cAAc,EACnB,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,GACzB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAEnE,OAAO,EACL,gBAAgB,EAChB,KAAK,cAAc,EACnB,KAAK,WAAW,EAChB,KAAK,eAAe,EACpB,KAAK,gBAAgB,GACtB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,EACrB,KAAK,gBAAgB,EACrB,KAAK,oBAAoB,EACzB,KAAK,qBAAqB,GAC3B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,KAAK,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACtE,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AACvE,OAAO,EAAE,KAAK,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AAC5E,OAAO,EAAE,KAAK,2BAA2B,EAAE,MAAM,wCAAwC,CAAC;AAC1F,OAAO,EAAE,gCAAgC,EAAE,MAAM,0CAA0C,CAAC;AAE5F,OAAO,EACL,mBAAmB,EACnB,KAAK,cAAc,EACnB,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,GACzB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAEnE,OAAO,EACL,gBAAgB,EAChB,KAAK,cAAc,EACnB,KAAK,WAAW,EAChB,KAAK,eAAe,EACpB,KAAK,gBAAgB,GACtB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,OAAO,EACL,0BAA0B,EAC1B,KAAK,qBAAqB,EAC1B,KAAK,yBAAyB,EAC9B,KAAK,0BAA0B,GAChC,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC"}
|
package/dist/esm/index.js
CHANGED
|
@@ -7,4 +7,6 @@ export { VOLUME_DEFAULTS } from "./volume-defaults.js";
|
|
|
7
7
|
export { VOLUME_ALARM_DEFAULTS } from "./volume-alarm-defaults.js";
|
|
8
8
|
export { createVpcBuilder, } from "./vpc-builder.js";
|
|
9
9
|
export { VPC_DEFAULTS } from "./vpc-defaults.js";
|
|
10
|
+
export { createSecurityGroupBuilder, } from "./security-group-builder.js";
|
|
11
|
+
export { SECURITY_GROUP_DEFAULTS } from "./security-group-defaults.js";
|
|
10
12
|
//# sourceMappingURL=index.js.map
|
package/dist/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,GAItB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAE3D,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAGvE,OAAO,EAAE,gCAAgC,EAAE,MAAM,0CAA0C,CAAC;AAE5F,OAAO,EACL,mBAAmB,GAIpB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAEnE,OAAO,EACL,gBAAgB,GAKjB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,GAItB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAE3D,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAGvE,OAAO,EAAE,gCAAgC,EAAE,MAAM,0CAA0C,CAAC;AAE5F,OAAO,EACL,mBAAmB,GAIpB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAEnE,OAAO,EACL,gBAAgB,GAKjB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,OAAO,EACL,0BAA0B,GAI3B,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC"}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { type IPeer, type IVpc, type Port, SecurityGroup, type SecurityGroupProps } from "aws-cdk-lib/aws-ec2";
|
|
2
|
+
import { type IConstruct } from "constructs";
|
|
3
|
+
import { COPY_STATE, type Lifecycle, type Resolvable } from "@composurecdk/core";
|
|
4
|
+
import { type ITaggedBuilder } from "@composurecdk/cloudformation";
|
|
5
|
+
/**
|
|
6
|
+
* Configuration properties for the security group builder.
|
|
7
|
+
*
|
|
8
|
+
* Extends the CDK {@link SecurityGroupProps} but lifts `vpc` off the props
|
|
9
|
+
* object — it is supplied via the dedicated
|
|
10
|
+
* {@link ISecurityGroupBuilder.vpc | .vpc()} method so it can accept a
|
|
11
|
+
* {@link Resolvable} for cross-component wiring (e.g. a sibling
|
|
12
|
+
* `VpcBuilder`).
|
|
13
|
+
*
|
|
14
|
+
* Ingress and egress rules are added imperatively via
|
|
15
|
+
* {@link ISecurityGroupBuilder.addIngressRule | .addIngressRule()},
|
|
16
|
+
* {@link ISecurityGroupBuilder.addEgressRule | .addEgressRule()}, and
|
|
17
|
+
* {@link ISecurityGroupBuilder.addSelfIngress | .addSelfIngress()} so each
|
|
18
|
+
* peer can also be a {@link Resolvable}.
|
|
19
|
+
*/
|
|
20
|
+
export type SecurityGroupBuilderProps = Omit<SecurityGroupProps, "vpc">;
|
|
21
|
+
/**
|
|
22
|
+
* The build output of an {@link ISecurityGroupBuilder}. Contains the CDK
|
|
23
|
+
* constructs created during {@link Lifecycle.build}, keyed by role.
|
|
24
|
+
*
|
|
25
|
+
* The `securityGroup` is itself an `IConnectable` and `IPeer`, so consumers
|
|
26
|
+
* compose against it directly — there is no separate `connections` field on
|
|
27
|
+
* the result.
|
|
28
|
+
*
|
|
29
|
+
* The builder creates no CloudWatch alarms. Security groups do not emit
|
|
30
|
+
* CloudWatch metrics, so the
|
|
31
|
+
* [recommended-alarms reference](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Best_Practice_Recommended_Alarms_AWS_Services.html)
|
|
32
|
+
* has no SG entry. Operational visibility comes from adjacent signals —
|
|
33
|
+
* VPC Flow Logs, GuardDuty findings, CloudTrail authorize-events.
|
|
34
|
+
*/
|
|
35
|
+
export interface SecurityGroupBuilderResult {
|
|
36
|
+
securityGroup: SecurityGroup;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* A fluent builder for configuring and creating an AWS EC2 security group.
|
|
40
|
+
*
|
|
41
|
+
* Each configuration property from the CDK {@link SecurityGroupProps} (other
|
|
42
|
+
* than `vpc`) is exposed as an overloaded method: call with a value to set
|
|
43
|
+
* it, or with no arguments to read it. The `vpc` is set via the dedicated
|
|
44
|
+
* {@link ISecurityGroupBuilder.vpc | .vpc()} method that accepts a
|
|
45
|
+
* {@link Resolvable} for cross-component wiring with sibling builders.
|
|
46
|
+
*
|
|
47
|
+
* Ingress and egress rules are accumulated via
|
|
48
|
+
* {@link ISecurityGroupBuilder.addIngressRule | .addIngressRule()},
|
|
49
|
+
* {@link ISecurityGroupBuilder.addEgressRule | .addEgressRule()}, and
|
|
50
|
+
* {@link ISecurityGroupBuilder.addSelfIngress | .addSelfIngress()} and
|
|
51
|
+
* applied when {@link Lifecycle.build | build()} runs. Each peer is a
|
|
52
|
+
* {@link Resolvable} so it can be a concrete `IPeer` (including another
|
|
53
|
+
* `ISecurityGroup`) or a {@link ref | Ref} to a sibling component's output.
|
|
54
|
+
*
|
|
55
|
+
* The builder implements {@link Lifecycle}, so it can be used directly as a
|
|
56
|
+
* component in a {@link compose | composed system}.
|
|
57
|
+
*
|
|
58
|
+
* @see https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.SecurityGroup.html
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* ```ts
|
|
62
|
+
* compose(
|
|
63
|
+
* {
|
|
64
|
+
* network: createVpcBuilder(),
|
|
65
|
+
* bastion: createSecurityGroupBuilder()
|
|
66
|
+
* .vpc(ref<VpcBuilderResult>("network").get("vpc"))
|
|
67
|
+
* .description("Bastion host"),
|
|
68
|
+
* database: createSecurityGroupBuilder()
|
|
69
|
+
* .vpc(ref<VpcBuilderResult>("network").get("vpc"))
|
|
70
|
+
* .description("Database")
|
|
71
|
+
* .addIngressRule(
|
|
72
|
+
* ref<SecurityGroupBuilderResult>("bastion").get("securityGroup"),
|
|
73
|
+
* Port.tcp(5432),
|
|
74
|
+
* "Bastion to Postgres",
|
|
75
|
+
* ),
|
|
76
|
+
* },
|
|
77
|
+
* { network: [], bastion: ["network"], database: ["network", "bastion"] },
|
|
78
|
+
* );
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
81
|
+
export type ISecurityGroupBuilder = ITaggedBuilder<SecurityGroupBuilderProps, SecurityGroupBuilder>;
|
|
82
|
+
declare class SecurityGroupBuilder implements Lifecycle<SecurityGroupBuilderResult> {
|
|
83
|
+
#private;
|
|
84
|
+
props: Partial<SecurityGroupBuilderProps>;
|
|
85
|
+
/**
|
|
86
|
+
* Sets the VPC the security group is created in.
|
|
87
|
+
*
|
|
88
|
+
* Accepts a concrete {@link IVpc} or a {@link Ref} that resolves to one
|
|
89
|
+
* at build time — e.g. a sibling {@link IVpcBuilder} in the same
|
|
90
|
+
* composed system.
|
|
91
|
+
*
|
|
92
|
+
* @param vpc - The VPC or a Ref to one.
|
|
93
|
+
* @returns This builder for chaining.
|
|
94
|
+
*/
|
|
95
|
+
vpc(vpc: Resolvable<IVpc>): this;
|
|
96
|
+
/**
|
|
97
|
+
* Adds an ingress rule. The peer accepts any {@link IPeer} — a concrete
|
|
98
|
+
* `Peer.ipv4(...)`, another `ISecurityGroup`, a prefix list — or a
|
|
99
|
+
* {@link Ref} that resolves to one.
|
|
100
|
+
*
|
|
101
|
+
* @param peer - The source of the allowed traffic.
|
|
102
|
+
* @param port - The port or port range.
|
|
103
|
+
* @param description - Optional human-readable description of the rule.
|
|
104
|
+
* @returns This builder for chaining.
|
|
105
|
+
*/
|
|
106
|
+
addIngressRule(peer: Resolvable<IPeer>, port: Port, description?: string): this;
|
|
107
|
+
/**
|
|
108
|
+
* Adds an egress rule. Required when `allowAllOutbound` is `false`
|
|
109
|
+
* (the builder default — see {@link SECURITY_GROUP_DEFAULTS}). The peer
|
|
110
|
+
* accepts any {@link IPeer} or a {@link Ref} that resolves to one.
|
|
111
|
+
*
|
|
112
|
+
* @param peer - The destination of the allowed traffic.
|
|
113
|
+
* @param port - The port or port range.
|
|
114
|
+
* @param description - Optional human-readable description of the rule.
|
|
115
|
+
* @returns This builder for chaining.
|
|
116
|
+
*/
|
|
117
|
+
addEgressRule(peer: Resolvable<IPeer>, port: Port, description?: string): this;
|
|
118
|
+
/**
|
|
119
|
+
* Adds an ingress rule whose peer is the security group itself —
|
|
120
|
+
* the canonical "allow intra-SG traffic on port N" pattern. The peer
|
|
121
|
+
* cannot be expressed at configuration time because the security group
|
|
122
|
+
* identity does not exist yet; the builder wires it after the SG is
|
|
123
|
+
* constructed.
|
|
124
|
+
*
|
|
125
|
+
* @param port - The port or port range.
|
|
126
|
+
* @param description - Optional human-readable description of the rule.
|
|
127
|
+
* @returns This builder for chaining.
|
|
128
|
+
*/
|
|
129
|
+
addSelfIngress(port: Port, description?: string): this;
|
|
130
|
+
/** @internal — see ADR-0005. */
|
|
131
|
+
[COPY_STATE](target: SecurityGroupBuilder): void;
|
|
132
|
+
build(scope: IConstruct, id: string, context?: Record<string, object>): SecurityGroupBuilderResult;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Creates a new {@link ISecurityGroupBuilder} for configuring an AWS EC2
|
|
136
|
+
* security group.
|
|
137
|
+
*
|
|
138
|
+
* The returned builder exposes every {@link SecurityGroupBuilderProps}
|
|
139
|
+
* property as a fluent setter/getter, plus
|
|
140
|
+
* {@link ISecurityGroupBuilder.vpc | .vpc()} for cross-component VPC wiring
|
|
141
|
+
* and the `addIngressRule` / `addEgressRule` / `addSelfIngress` accumulators.
|
|
142
|
+
* It implements {@link Lifecycle} for use with {@link compose}.
|
|
143
|
+
*
|
|
144
|
+
* @returns A fluent builder for an AWS EC2 security group.
|
|
145
|
+
*/
|
|
146
|
+
export declare function createSecurityGroupBuilder(): ISecurityGroupBuilder;
|
|
147
|
+
export {};
|
|
148
|
+
//# sourceMappingURL=security-group-builder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"security-group-builder.d.ts","sourceRoot":"","sources":["../../src/security-group-builder.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,KAAK,EACV,KAAK,IAAI,EACT,KAAK,IAAI,EACT,aAAa,EACb,KAAK,kBAAkB,EACxB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,KAAK,SAAS,EAAW,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAC1F,OAAO,EAAE,KAAK,cAAc,EAAiB,MAAM,8BAA8B,CAAC;AAGlF;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,yBAAyB,GAAG,IAAI,CAAC,kBAAkB,EAAE,KAAK,CAAC,CAAC;AAExE;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,0BAA0B;IACzC,aAAa,EAAE,aAAa,CAAC;CAC9B;AAcD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,MAAM,MAAM,qBAAqB,GAAG,cAAc,CAAC,yBAAyB,EAAE,oBAAoB,CAAC,CAAC;AAEpG,cAAM,oBAAqB,YAAW,SAAS,CAAC,0BAA0B,CAAC;;IACzE,KAAK,EAAE,OAAO,CAAC,yBAAyB,CAAC,CAAM;IAK/C;;;;;;;;;OASG;IACH,GAAG,CAAC,GAAG,EAAE,UAAU,CAAC,IAAI,CAAC,GAAG,IAAI;IAKhC;;;;;;;;;OASG;IACH,cAAc,CAAC,IAAI,EAAE,UAAU,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI;IAU/E;;;;;;;;;OASG;IACH,aAAa,CAAC,IAAI,EAAE,UAAU,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI;IAU9E;;;;;;;;;;OAUG;IACH,cAAc,CAAC,IAAI,EAAE,IAAI,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI;IAQtD,gCAAgC;IAChC,CAAC,UAAU,CAAC,CAAC,MAAM,EAAE,oBAAoB,GAAG,IAAI;IAMhD,KAAK,CACH,KAAK,EAAE,UAAU,EACjB,EAAE,EAAE,MAAM,EACV,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,0BAA0B;CAiD9B;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,0BAA0B,IAAI,qBAAqB,CAElE"}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { SecurityGroup, } from "aws-cdk-lib/aws-ec2";
|
|
2
|
+
import { COPY_STATE, resolve } from "@composurecdk/core";
|
|
3
|
+
import { taggedBuilder } from "@composurecdk/cloudformation";
|
|
4
|
+
import { SECURITY_GROUP_DEFAULTS } from "./security-group-defaults.js";
|
|
5
|
+
class SecurityGroupBuilder {
|
|
6
|
+
props = {};
|
|
7
|
+
#peerRules = [];
|
|
8
|
+
#selfIngress = [];
|
|
9
|
+
#vpc;
|
|
10
|
+
/**
|
|
11
|
+
* Sets the VPC the security group is created in.
|
|
12
|
+
*
|
|
13
|
+
* Accepts a concrete {@link IVpc} or a {@link Ref} that resolves to one
|
|
14
|
+
* at build time — e.g. a sibling {@link IVpcBuilder} in the same
|
|
15
|
+
* composed system.
|
|
16
|
+
*
|
|
17
|
+
* @param vpc - The VPC or a Ref to one.
|
|
18
|
+
* @returns This builder for chaining.
|
|
19
|
+
*/
|
|
20
|
+
vpc(vpc) {
|
|
21
|
+
this.#vpc = vpc;
|
|
22
|
+
return this;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Adds an ingress rule. The peer accepts any {@link IPeer} — a concrete
|
|
26
|
+
* `Peer.ipv4(...)`, another `ISecurityGroup`, a prefix list — or a
|
|
27
|
+
* {@link Ref} that resolves to one.
|
|
28
|
+
*
|
|
29
|
+
* @param peer - The source of the allowed traffic.
|
|
30
|
+
* @param port - The port or port range.
|
|
31
|
+
* @param description - Optional human-readable description of the rule.
|
|
32
|
+
* @returns This builder for chaining.
|
|
33
|
+
*/
|
|
34
|
+
addIngressRule(peer, port, description) {
|
|
35
|
+
this.#peerRules.push({
|
|
36
|
+
direction: "ingress",
|
|
37
|
+
peer,
|
|
38
|
+
port,
|
|
39
|
+
...(description !== undefined ? { description } : {}),
|
|
40
|
+
});
|
|
41
|
+
return this;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Adds an egress rule. Required when `allowAllOutbound` is `false`
|
|
45
|
+
* (the builder default — see {@link SECURITY_GROUP_DEFAULTS}). The peer
|
|
46
|
+
* accepts any {@link IPeer} or a {@link Ref} that resolves to one.
|
|
47
|
+
*
|
|
48
|
+
* @param peer - The destination of the allowed traffic.
|
|
49
|
+
* @param port - The port or port range.
|
|
50
|
+
* @param description - Optional human-readable description of the rule.
|
|
51
|
+
* @returns This builder for chaining.
|
|
52
|
+
*/
|
|
53
|
+
addEgressRule(peer, port, description) {
|
|
54
|
+
this.#peerRules.push({
|
|
55
|
+
direction: "egress",
|
|
56
|
+
peer,
|
|
57
|
+
port,
|
|
58
|
+
...(description !== undefined ? { description } : {}),
|
|
59
|
+
});
|
|
60
|
+
return this;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Adds an ingress rule whose peer is the security group itself —
|
|
64
|
+
* the canonical "allow intra-SG traffic on port N" pattern. The peer
|
|
65
|
+
* cannot be expressed at configuration time because the security group
|
|
66
|
+
* identity does not exist yet; the builder wires it after the SG is
|
|
67
|
+
* constructed.
|
|
68
|
+
*
|
|
69
|
+
* @param port - The port or port range.
|
|
70
|
+
* @param description - Optional human-readable description of the rule.
|
|
71
|
+
* @returns This builder for chaining.
|
|
72
|
+
*/
|
|
73
|
+
addSelfIngress(port, description) {
|
|
74
|
+
this.#selfIngress.push({
|
|
75
|
+
port,
|
|
76
|
+
...(description !== undefined ? { description } : {}),
|
|
77
|
+
});
|
|
78
|
+
return this;
|
|
79
|
+
}
|
|
80
|
+
/** @internal — see ADR-0005. */
|
|
81
|
+
[COPY_STATE](target) {
|
|
82
|
+
target.#vpc = this.#vpc;
|
|
83
|
+
target.#peerRules.push(...this.#peerRules);
|
|
84
|
+
target.#selfIngress.push(...this.#selfIngress);
|
|
85
|
+
}
|
|
86
|
+
build(scope, id, context) {
|
|
87
|
+
const resolvedVpc = this.#vpc ? resolve(this.#vpc, context) : undefined;
|
|
88
|
+
if (!resolvedVpc) {
|
|
89
|
+
throw new Error(`SecurityGroupBuilder "${id}" requires a VPC. ` +
|
|
90
|
+
"Call .vpc() with an IVpc or a Ref to one.");
|
|
91
|
+
}
|
|
92
|
+
if (this.props.description === undefined || this.props.description.trim() === "") {
|
|
93
|
+
throw new Error(`SecurityGroupBuilder "${id}" requires a description. ` +
|
|
94
|
+
"Call .description() with a short summary of the SG's purpose.");
|
|
95
|
+
}
|
|
96
|
+
// Drop keys whose value is `undefined` so a fluent call like
|
|
97
|
+
// `.allowAllOutbound(undefined)` (common in "optional override" code:
|
|
98
|
+
// `b.allowAllOutbound(cfg?.allowAllOutbound)`) does not clobber the
|
|
99
|
+
// closed-egress default with explicit `undefined`.
|
|
100
|
+
const userProps = {};
|
|
101
|
+
for (const key of Object.keys(this.props)) {
|
|
102
|
+
const value = this.props[key];
|
|
103
|
+
if (value !== undefined) {
|
|
104
|
+
userProps[key] = value;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
const mergedProps = {
|
|
108
|
+
...SECURITY_GROUP_DEFAULTS,
|
|
109
|
+
...userProps,
|
|
110
|
+
vpc: resolvedVpc,
|
|
111
|
+
};
|
|
112
|
+
const securityGroup = new SecurityGroup(scope, id, mergedProps);
|
|
113
|
+
for (const rule of this.#peerRules) {
|
|
114
|
+
const peer = resolve(rule.peer, context);
|
|
115
|
+
if (rule.direction === "ingress") {
|
|
116
|
+
securityGroup.addIngressRule(peer, rule.port, rule.description);
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
securityGroup.addEgressRule(peer, rule.port, rule.description);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
for (const rule of this.#selfIngress) {
|
|
123
|
+
securityGroup.addIngressRule(securityGroup, rule.port, rule.description);
|
|
124
|
+
}
|
|
125
|
+
return { securityGroup };
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Creates a new {@link ISecurityGroupBuilder} for configuring an AWS EC2
|
|
130
|
+
* security group.
|
|
131
|
+
*
|
|
132
|
+
* The returned builder exposes every {@link SecurityGroupBuilderProps}
|
|
133
|
+
* property as a fluent setter/getter, plus
|
|
134
|
+
* {@link ISecurityGroupBuilder.vpc | .vpc()} for cross-component VPC wiring
|
|
135
|
+
* and the `addIngressRule` / `addEgressRule` / `addSelfIngress` accumulators.
|
|
136
|
+
* It implements {@link Lifecycle} for use with {@link compose}.
|
|
137
|
+
*
|
|
138
|
+
* @returns A fluent builder for an AWS EC2 security group.
|
|
139
|
+
*/
|
|
140
|
+
export function createSecurityGroupBuilder() {
|
|
141
|
+
return taggedBuilder(SecurityGroupBuilder);
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=security-group-builder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"security-group-builder.js","sourceRoot":"","sources":["../../src/security-group-builder.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { SecurityGroupProps } from "aws-cdk-lib/aws-ec2";
|
|
2
|
+
/**
|
|
3
|
+
* Secure, AWS-recommended defaults applied to every security group built
|
|
4
|
+
* with {@link createSecurityGroupBuilder}. Each property can be individually
|
|
5
|
+
* overridden via the builder's fluent API.
|
|
6
|
+
*
|
|
7
|
+
* Two properties intentionally have no default — they are application-
|
|
8
|
+
* specific and must be supplied explicitly:
|
|
9
|
+
* - `vpc` (via the builder's `.vpc()` method)
|
|
10
|
+
* - `description` (a short, human-readable summary of the SG's purpose)
|
|
11
|
+
*/
|
|
12
|
+
export declare const SECURITY_GROUP_DEFAULTS: Partial<SecurityGroupProps>;
|
|
13
|
+
//# sourceMappingURL=security-group-defaults.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"security-group-defaults.d.ts","sourceRoot":"","sources":["../../src/security-group-defaults.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAE9D;;;;;;;;;GASG;AACH,eAAO,MAAM,uBAAuB,EAAE,OAAO,CAAC,kBAAkB,CAY/D,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Secure, AWS-recommended defaults applied to every security group built
|
|
3
|
+
* with {@link createSecurityGroupBuilder}. Each property can be individually
|
|
4
|
+
* overridden via the builder's fluent API.
|
|
5
|
+
*
|
|
6
|
+
* Two properties intentionally have no default — they are application-
|
|
7
|
+
* specific and must be supplied explicitly:
|
|
8
|
+
* - `vpc` (via the builder's `.vpc()` method)
|
|
9
|
+
* - `description` (a short, human-readable summary of the SG's purpose)
|
|
10
|
+
*/
|
|
11
|
+
export const SECURITY_GROUP_DEFAULTS = {
|
|
12
|
+
/**
|
|
13
|
+
* Closed-by-default egress. CDK's stock default is `true`, which creates
|
|
14
|
+
* an implicit `0.0.0.0/0` outbound rule on every SG — flagged by
|
|
15
|
+
* compliance scanners and incompatible with the project's least-privilege
|
|
16
|
+
* stance. Closing egress forces every outbound flow to be expressed as
|
|
17
|
+
* an explicit `addEgressRule` (or `.allowAllOutbound(true)` to opt back
|
|
18
|
+
* into the CDK default).
|
|
19
|
+
*
|
|
20
|
+
* @see https://docs.aws.amazon.com/wellarchitected/latest/security-pillar/sec_network_protection_layered.html
|
|
21
|
+
*/
|
|
22
|
+
allowAllOutbound: false,
|
|
23
|
+
};
|
|
24
|
+
//# sourceMappingURL=security-group-defaults.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"security-group-defaults.js","sourceRoot":"","sources":["../../src/security-group-defaults.ts"],"names":[],"mappings":"AAEA;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAgC;IAClE;;;;;;;;;OASG;IACH,gBAAgB,EAAE,KAAK;CACxB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@composurecdk/ec2",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.2",
|
|
4
4
|
"description": "Composable EC2 instance and VPC builders with well-architected defaults",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -41,15 +41,15 @@
|
|
|
41
41
|
"@composurecdk/cloudwatch": "^0.8.0",
|
|
42
42
|
"@composurecdk/core": "^0.8.0",
|
|
43
43
|
"@composurecdk/logs": "^0.8.0",
|
|
44
|
-
"aws-cdk-lib": "^2.
|
|
44
|
+
"aws-cdk-lib": "^2.54.0",
|
|
45
45
|
"constructs": "^10.0.0"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
|
-
"@types/node": "^25.
|
|
49
|
-
"aws-cdk-lib": "^2.
|
|
48
|
+
"@types/node": "^25.9.1",
|
|
49
|
+
"aws-cdk-lib": "^2.257.0",
|
|
50
50
|
"constructs": "^10.6.0",
|
|
51
51
|
"typescript": "^6.0.2",
|
|
52
|
-
"vitest": "^4.1.
|
|
52
|
+
"vitest": "^4.1.7"
|
|
53
53
|
},
|
|
54
54
|
"exports": {
|
|
55
55
|
"./package.json": "./package.json",
|