@composurecdk/ec2 0.5.0
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 +201 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/instance-alarm-config.d.ts +62 -0
- package/dist/instance-alarm-config.d.ts.map +1 -0
- package/dist/instance-alarm-config.js +2 -0
- package/dist/instance-alarm-config.js.map +1 -0
- package/dist/instance-alarm-defaults.d.ts +20 -0
- package/dist/instance-alarm-defaults.d.ts.map +1 -0
- package/dist/instance-alarm-defaults.js +62 -0
- package/dist/instance-alarm-defaults.js.map +1 -0
- package/dist/instance-alarms.d.ts +28 -0
- package/dist/instance-alarms.d.ts.map +1 -0
- package/dist/instance-alarms.js +128 -0
- package/dist/instance-alarms.js.map +1 -0
- package/dist/instance-builder.d.ts +185 -0
- package/dist/instance-builder.d.ts.map +1 -0
- package/dist/instance-builder.js +87 -0
- package/dist/instance-builder.js.map +1 -0
- package/dist/instance-defaults.d.ts +14 -0
- package/dist/instance-defaults.d.ts.map +1 -0
- package/dist/instance-defaults.js +59 -0
- package/dist/instance-defaults.js.map +1 -0
- package/dist/vpc-builder.d.ts +109 -0
- package/dist/vpc-builder.d.ts.map +1 -0
- package/dist/vpc-builder.js +79 -0
- package/dist/vpc-builder.js.map +1 -0
- package/dist/vpc-defaults.d.ts +15 -0
- package/dist/vpc-defaults.d.ts.map +1 -0
- package/dist/vpc-defaults.js +55 -0
- package/dist/vpc-defaults.js.map +1 -0
- package/package.json +51 -0
package/README.md
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
# @composurecdk/ec2
|
|
2
|
+
|
|
3
|
+
EC2 and VPC builders for [ComposureCDK](../../README.md).
|
|
4
|
+
|
|
5
|
+
This package provides fluent builders for AWS EC2 instances and VPCs with secure, AWS-recommended defaults. It wraps the CDK [Instance](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.Instance.html) and [Vpc](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.Vpc.html) constructs — refer to the CDK documentation for the full set of configurable properties.
|
|
6
|
+
|
|
7
|
+
## Instance Builder
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
import { createInstanceBuilder } from "@composurecdk/ec2";
|
|
11
|
+
import { InstanceClass, InstanceSize, InstanceType, MachineImage } from "aws-cdk-lib/aws-ec2";
|
|
12
|
+
|
|
13
|
+
const server = createInstanceBuilder()
|
|
14
|
+
.vpc(vpc)
|
|
15
|
+
.instanceType(InstanceType.of(InstanceClass.T3, InstanceSize.MICRO))
|
|
16
|
+
.machineImage(MachineImage.latestAmazonLinux2023())
|
|
17
|
+
.build(stack, "MyInstance");
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Every [InstanceProps](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.InstanceProps.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>(...)`.
|
|
21
|
+
|
|
22
|
+
## Secure Defaults
|
|
23
|
+
|
|
24
|
+
`createInstanceBuilder` applies the following defaults. Each can be overridden via the builder's fluent API.
|
|
25
|
+
|
|
26
|
+
| Property | Default | Rationale |
|
|
27
|
+
| ----------------------- | ----------------------------------------------- | --------------------------------------------------------------------------------------------------------- |
|
|
28
|
+
| `requireImdsv2` | `true` | IMDSv2 requires a session token, blocking the SSRF-based credential exfiltration common to IMDSv1. |
|
|
29
|
+
| `detailedMonitoring` | `true` | 1-minute CloudWatch metric granularity is required for short-window alarm evaluation. |
|
|
30
|
+
| `ssmSessionPermissions` | `true` | Attaches `AmazonSSMManagedInstanceCore` — Session Manager replaces SSH entirely (no key pairs, bastions). |
|
|
31
|
+
| `ebsOptimized` | `true` | Dedicated EBS bandwidth. Free on current-generation instance types. |
|
|
32
|
+
| `blockDevices` | 8 GiB GP3 root volume at `/dev/xvda`, encrypted | Encrypted at rest with the account's default EBS KMS key. |
|
|
33
|
+
|
|
34
|
+
Three properties intentionally have no default — they are application-specific and must be supplied explicitly:
|
|
35
|
+
|
|
36
|
+
- `vpc` (via the `.vpc()` method)
|
|
37
|
+
- `instanceType`
|
|
38
|
+
- `machineImage`
|
|
39
|
+
|
|
40
|
+
The defaults are exported as `INSTANCE_DEFAULTS` for visibility and testing:
|
|
41
|
+
|
|
42
|
+
```ts
|
|
43
|
+
import { INSTANCE_DEFAULTS } from "@composurecdk/ec2";
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Recommended Alarms
|
|
47
|
+
|
|
48
|
+
The builder creates [AWS-recommended CloudWatch alarms](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Best_Practice_Recommended_Alarms_AWS_Services.html#EC2) by default. No alarm actions are configured — wire actions via `alarmActionsPolicy` from `@composurecdk/cloudwatch`, or by accessing alarms from the build result.
|
|
49
|
+
|
|
50
|
+
| Alarm | Metric | Default threshold | Created when |
|
|
51
|
+
| ------------------------------ | ---------------------------------------------- | ------------------- | ----------------------------------------------------- |
|
|
52
|
+
| `cpuUtilization` | CPUUtilization (Average, 1 min) | > 80% over 5 min | Always |
|
|
53
|
+
| `statusCheckFailed` | StatusCheckFailed (Sum, 1 min) | > 0 over 2 min | Always |
|
|
54
|
+
| `attachedEbsStatusCheckFailed` | StatusCheckFailed_AttachedEBS (Maximum, 1 min) | >= 1 over 10 min | Always |
|
|
55
|
+
| `cpuCreditBalance` | CPUCreditBalance (Minimum, 5 min) | < 50 over 3 x 5 min | `instanceType` is burstable (T2, T3, T3a, T4g family) |
|
|
56
|
+
|
|
57
|
+
The defaults are exported as `INSTANCE_ALARM_DEFAULTS` for visibility and testing:
|
|
58
|
+
|
|
59
|
+
```ts
|
|
60
|
+
import { INSTANCE_ALARM_DEFAULTS } from "@composurecdk/ec2";
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Customizing thresholds
|
|
64
|
+
|
|
65
|
+
Override individual alarm properties via `recommendedAlarms`. Unspecified fields keep their defaults.
|
|
66
|
+
|
|
67
|
+
```ts
|
|
68
|
+
const server = createInstanceBuilder()
|
|
69
|
+
.vpc(vpc)
|
|
70
|
+
.instanceType(InstanceType.of(InstanceClass.T3, InstanceSize.MICRO))
|
|
71
|
+
.machineImage(MachineImage.latestAmazonLinux2023())
|
|
72
|
+
.recommendedAlarms({
|
|
73
|
+
cpuUtilization: { threshold: 90, evaluationPeriods: 3, datapointsToAlarm: 3 },
|
|
74
|
+
});
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Disabling alarms
|
|
78
|
+
|
|
79
|
+
Disable all recommended alarms:
|
|
80
|
+
|
|
81
|
+
```ts
|
|
82
|
+
builder.recommendedAlarms(false);
|
|
83
|
+
// or
|
|
84
|
+
builder.recommendedAlarms({ enabled: false });
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Disable individual alarms:
|
|
88
|
+
|
|
89
|
+
```ts
|
|
90
|
+
builder.recommendedAlarms({ cpuCreditBalance: false });
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Custom alarms
|
|
94
|
+
|
|
95
|
+
Add custom alarms alongside the recommended ones via `addAlarm`. The callback receives an `AlarmDefinitionBuilder` typed to the `Instance`.
|
|
96
|
+
|
|
97
|
+
```ts
|
|
98
|
+
import { Metric, Stats } from "aws-cdk-lib/aws-cloudwatch";
|
|
99
|
+
import { Duration } from "aws-cdk-lib";
|
|
100
|
+
|
|
101
|
+
const server = createInstanceBuilder()
|
|
102
|
+
.vpc(vpc)
|
|
103
|
+
.instanceType(InstanceType.of(InstanceClass.T3, InstanceSize.MICRO))
|
|
104
|
+
.machineImage(MachineImage.latestAmazonLinux2023())
|
|
105
|
+
.addAlarm("networkIn", (alarm) =>
|
|
106
|
+
alarm
|
|
107
|
+
.metric(
|
|
108
|
+
(instance) =>
|
|
109
|
+
new Metric({
|
|
110
|
+
namespace: "AWS/EC2",
|
|
111
|
+
metricName: "NetworkIn",
|
|
112
|
+
dimensionsMap: { InstanceId: instance.instanceId },
|
|
113
|
+
statistic: Stats.AVERAGE,
|
|
114
|
+
period: Duration.minutes(1),
|
|
115
|
+
}),
|
|
116
|
+
)
|
|
117
|
+
.threshold(1_000_000_000)
|
|
118
|
+
.greaterThanOrEqual()
|
|
119
|
+
.description("Inbound network traffic is unusually high"),
|
|
120
|
+
);
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## VPC Builder
|
|
124
|
+
|
|
125
|
+
```ts
|
|
126
|
+
import { createVpcBuilder } from "@composurecdk/ec2";
|
|
127
|
+
|
|
128
|
+
const network = createVpcBuilder().maxAzs(3).natGateways(3).build(stack, "Network");
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Every [VpcProps](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.VpcProps.html) property is available as a fluent setter on the builder.
|
|
132
|
+
|
|
133
|
+
### VPC Defaults
|
|
134
|
+
|
|
135
|
+
| Property | Default | Rationale |
|
|
136
|
+
| ------------------------------ | --------------------------------- | -------------------------------------------------------------------------------------------------- |
|
|
137
|
+
| `maxAzs` | `2` | Meaningful HA without overspending. Override to 3+ for stricter production guarantees. |
|
|
138
|
+
| `natGateways` | `1` | Cost-conscious default. Production HA workloads should set `natGateways` to match `maxAzs`. |
|
|
139
|
+
| `enableDnsSupport` | `true` | Required for most AWS managed services (ALB, RDS, VPC endpoints). |
|
|
140
|
+
| `enableDnsHostnames` | `true` | Required for instances to receive public DNS hostnames. |
|
|
141
|
+
| `restrictDefaultSecurityGroup` | `true` | Strips rules from the default SG, forcing explicit SG design. |
|
|
142
|
+
| Flow logs | Auto-created CloudWatch log group | Network audit trail with well-architected retention and removal policies via `@composurecdk/logs`. |
|
|
143
|
+
|
|
144
|
+
The defaults are exported as `VPC_DEFAULTS` for visibility and testing:
|
|
145
|
+
|
|
146
|
+
```ts
|
|
147
|
+
import { VPC_DEFAULTS } from "@composurecdk/ec2";
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### Flow logs
|
|
151
|
+
|
|
152
|
+
By default, the builder auto-creates a CloudWatch-Logs-backed flow log with a managed `LogGroup` from `@composurecdk/logs` (two-year retention, `RemovalPolicy.RETAIN`).
|
|
153
|
+
|
|
154
|
+
Customize the auto-created LogGroup:
|
|
155
|
+
|
|
156
|
+
```ts
|
|
157
|
+
createVpcBuilder().flowLogs({
|
|
158
|
+
configure: (lg) => lg.retention(RetentionDays.NINETY_DAYS).removalPolicy(RemovalPolicy.DESTROY),
|
|
159
|
+
});
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
Use a user-managed destination (e.g. an S3 bucket):
|
|
163
|
+
|
|
164
|
+
```ts
|
|
165
|
+
createVpcBuilder().flowLogs({
|
|
166
|
+
destination: FlowLogDestination.toS3(myBucket),
|
|
167
|
+
});
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
Disable flow logs entirely:
|
|
171
|
+
|
|
172
|
+
```ts
|
|
173
|
+
createVpcBuilder().flowLogs(false);
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
For multiple flow logs against the same VPC, omit this config and create additional `FlowLog` constructs directly against the returned `vpc`.
|
|
177
|
+
|
|
178
|
+
## Composing EC2 + VPC
|
|
179
|
+
|
|
180
|
+
Compose the builders into a single system — the instance is wired to the VPC via `ref`:
|
|
181
|
+
|
|
182
|
+
```ts
|
|
183
|
+
import { compose, ref } from "@composurecdk/core";
|
|
184
|
+
import { createInstanceBuilder, createVpcBuilder, type VpcBuilderResult } from "@composurecdk/ec2";
|
|
185
|
+
import type { Vpc } from "aws-cdk-lib/aws-ec2";
|
|
186
|
+
|
|
187
|
+
compose(
|
|
188
|
+
{
|
|
189
|
+
network: createVpcBuilder(),
|
|
190
|
+
server: createInstanceBuilder()
|
|
191
|
+
.vpc(ref<VpcBuilderResult>("network").map((r): Vpc => r.vpc))
|
|
192
|
+
.instanceType(InstanceType.of(InstanceClass.T3, InstanceSize.MICRO))
|
|
193
|
+
.machineImage(MachineImage.latestAmazonLinux2023()),
|
|
194
|
+
},
|
|
195
|
+
{ network: [], server: ["network"] },
|
|
196
|
+
).build(stack, "Ec2App");
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
## Examples
|
|
200
|
+
|
|
201
|
+
- [Ec2Stack](../examples/src/ec2-app.ts) — VPC + EC2 instance with alarms wired to an SNS topic via `alarmActionsPolicy`.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { createInstanceBuilder, type IInstanceBuilder, type InstanceBuilderProps, type InstanceBuilderResult, } from "./instance-builder.js";
|
|
2
|
+
export { INSTANCE_DEFAULTS } from "./instance-defaults.js";
|
|
3
|
+
export { type InstanceAlarmConfig } from "./instance-alarm-config.js";
|
|
4
|
+
export { INSTANCE_ALARM_DEFAULTS } from "./instance-alarm-defaults.js";
|
|
5
|
+
export { createVpcBuilder, type FlowLogsConfig, type IVpcBuilder, type VpcBuilderProps, type VpcBuilderResult, } from "./vpc-builder.js";
|
|
6
|
+
export { VPC_DEFAULTS } from "./vpc-defaults.js";
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +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;AAEvE,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"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { createInstanceBuilder, } from "./instance-builder.js";
|
|
2
|
+
export { INSTANCE_DEFAULTS } from "./instance-defaults.js";
|
|
3
|
+
export { INSTANCE_ALARM_DEFAULTS } from "./instance-alarm-defaults.js";
|
|
4
|
+
export { createVpcBuilder, } from "./vpc-builder.js";
|
|
5
|
+
export { VPC_DEFAULTS } from "./vpc-defaults.js";
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +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;AAEvE,OAAO,EACL,gBAAgB,GAKjB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { AlarmConfig } from "@composurecdk/cloudwatch";
|
|
2
|
+
/**
|
|
3
|
+
* Controls which recommended alarms are created for an EC2 instance.
|
|
4
|
+
* All alarms are enabled by default with AWS-recommended thresholds.
|
|
5
|
+
* Set individual alarms to `false` to disable them, or provide an
|
|
6
|
+
* {@link AlarmConfig} to tune thresholds.
|
|
7
|
+
*
|
|
8
|
+
* @see https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Best_Practice_Recommended_Alarms_AWS_Services.html#EC2
|
|
9
|
+
*/
|
|
10
|
+
export interface InstanceAlarmConfig {
|
|
11
|
+
/**
|
|
12
|
+
* Master switch: set to `false` to disable all recommended alarms.
|
|
13
|
+
* Individual alarms can also be disabled via their own entry.
|
|
14
|
+
* @default true
|
|
15
|
+
*/
|
|
16
|
+
enabled?: boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Alarm when CPU utilization is sustained at a high level.
|
|
19
|
+
*
|
|
20
|
+
* Metric: `AWS/EC2 CPUUtilization`, statistic Average, period 1 minute.
|
|
21
|
+
* Default threshold: > 80% over 5 consecutive minutes.
|
|
22
|
+
*
|
|
23
|
+
* @see https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Best_Practice_Recommended_Alarms_AWS_Services.html#EC2
|
|
24
|
+
*/
|
|
25
|
+
cpuUtilization?: AlarmConfig | false;
|
|
26
|
+
/**
|
|
27
|
+
* Alarm when the instance fails its EC2 or system status checks.
|
|
28
|
+
*
|
|
29
|
+
* Metric: `AWS/EC2 StatusCheckFailed`, statistic Sum, period 1 minute.
|
|
30
|
+
* Default threshold: > 0 failures over 2 consecutive minutes.
|
|
31
|
+
*
|
|
32
|
+
* @see https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Best_Practice_Recommended_Alarms_AWS_Services.html#EC2
|
|
33
|
+
*/
|
|
34
|
+
statusCheckFailed?: AlarmConfig | false;
|
|
35
|
+
/**
|
|
36
|
+
* Alarm when the instance's attached EBS volumes are unreachable or
|
|
37
|
+
* unable to complete I/O — typically a host or storage-subsystem issue.
|
|
38
|
+
*
|
|
39
|
+
* Metric: `AWS/EC2 StatusCheckFailed_AttachedEBS`, statistic Maximum,
|
|
40
|
+
* period 1 minute. Default threshold: >= 1 over 10 consecutive minutes
|
|
41
|
+
* (the longer window reflects that EBS infrastructure usually self-heals
|
|
42
|
+
* within a few minutes).
|
|
43
|
+
*
|
|
44
|
+
* @see https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Best_Practice_Recommended_Alarms_AWS_Services.html#EC2
|
|
45
|
+
*/
|
|
46
|
+
attachedEbsStatusCheckFailed?: AlarmConfig | false;
|
|
47
|
+
/**
|
|
48
|
+
* Alarm when burstable (T-family) CPU credit balance falls low,
|
|
49
|
+
* indicating the instance is about to be throttled to baseline.
|
|
50
|
+
*
|
|
51
|
+
* Only created when the `instanceType` family is one of: t2, t3, t3a, t4g.
|
|
52
|
+
* For other instance types this alarm is skipped entirely.
|
|
53
|
+
*
|
|
54
|
+
* Metric: `AWS/EC2 CPUCreditBalance`, statistic Minimum, period 5 minutes.
|
|
55
|
+
* Default threshold: < 50 credits over 3 consecutive 5-minute windows.
|
|
56
|
+
*
|
|
57
|
+
* @see https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Best_Practice_Recommended_Alarms_AWS_Services.html#EC2
|
|
58
|
+
* @see https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/burstable-credits-baseline-concepts.html
|
|
59
|
+
*/
|
|
60
|
+
cpuCreditBalance?: AlarmConfig | false;
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=instance-alarm-config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instance-alarm-config.d.ts","sourceRoot":"","sources":["../src/instance-alarm-config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAE5D;;;;;;;GAOG;AACH,MAAM,WAAW,mBAAmB;IAClC;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB;;;;;;;OAOG;IACH,cAAc,CAAC,EAAE,WAAW,GAAG,KAAK,CAAC;IAErC;;;;;;;OAOG;IACH,iBAAiB,CAAC,EAAE,WAAW,GAAG,KAAK,CAAC;IAExC;;;;;;;;;;OAUG;IACH,4BAA4B,CAAC,EAAE,WAAW,GAAG,KAAK,CAAC;IAEnD;;;;;;;;;;;;OAYG;IACH,gBAAgB,CAAC,EAAE,WAAW,GAAG,KAAK,CAAC;CACxC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instance-alarm-config.js","sourceRoot":"","sources":["../src/instance-alarm-config.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { AlarmConfigDefaults } from "@composurecdk/cloudwatch";
|
|
2
|
+
interface InstanceAlarmDefaults {
|
|
3
|
+
enabled: true;
|
|
4
|
+
cpuUtilization: AlarmConfigDefaults;
|
|
5
|
+
statusCheckFailed: AlarmConfigDefaults;
|
|
6
|
+
attachedEbsStatusCheckFailed: AlarmConfigDefaults;
|
|
7
|
+
cpuCreditBalance: AlarmConfigDefaults;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* AWS-recommended default alarm configuration for EC2 instances.
|
|
11
|
+
*
|
|
12
|
+
* Thresholds are sourced from the CloudWatch Best Practice Recommended
|
|
13
|
+
* Alarms guide. Thresholds may reasonably be tuned per-workload; defaults
|
|
14
|
+
* bias toward catching obvious issues without excessive noise.
|
|
15
|
+
*
|
|
16
|
+
* @see https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Best_Practice_Recommended_Alarms_AWS_Services.html#EC2
|
|
17
|
+
*/
|
|
18
|
+
export declare const INSTANCE_ALARM_DEFAULTS: InstanceAlarmDefaults;
|
|
19
|
+
export {};
|
|
20
|
+
//# sourceMappingURL=instance-alarm-defaults.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instance-alarm-defaults.d.ts","sourceRoot":"","sources":["../src/instance-alarm-defaults.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAEpE,UAAU,qBAAqB;IAC7B,OAAO,EAAE,IAAI,CAAC;IACd,cAAc,EAAE,mBAAmB,CAAC;IACpC,iBAAiB,EAAE,mBAAmB,CAAC;IACvC,4BAA4B,EAAE,mBAAmB,CAAC;IAClD,gBAAgB,EAAE,mBAAmB,CAAC;CACvC;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,uBAAuB,EAAE,qBAsDrC,CAAC"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { TreatMissingData } from "aws-cdk-lib/aws-cloudwatch";
|
|
2
|
+
/**
|
|
3
|
+
* AWS-recommended default alarm configuration for EC2 instances.
|
|
4
|
+
*
|
|
5
|
+
* Thresholds are sourced from the CloudWatch Best Practice Recommended
|
|
6
|
+
* Alarms guide. Thresholds may reasonably be tuned per-workload; defaults
|
|
7
|
+
* bias toward catching obvious issues without excessive noise.
|
|
8
|
+
*
|
|
9
|
+
* @see https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Best_Practice_Recommended_Alarms_AWS_Services.html#EC2
|
|
10
|
+
*/
|
|
11
|
+
export const INSTANCE_ALARM_DEFAULTS = {
|
|
12
|
+
enabled: true,
|
|
13
|
+
/**
|
|
14
|
+
* Sustained high CPU indicates the instance is a bottleneck and may
|
|
15
|
+
* need to be scaled up. 80% over 5 consecutive minutes avoids
|
|
16
|
+
* alarming on brief workload spikes.
|
|
17
|
+
*/
|
|
18
|
+
cpuUtilization: {
|
|
19
|
+
threshold: 80,
|
|
20
|
+
evaluationPeriods: 5,
|
|
21
|
+
datapointsToAlarm: 5,
|
|
22
|
+
treatMissingData: TreatMissingData.NOT_BREACHING,
|
|
23
|
+
},
|
|
24
|
+
/**
|
|
25
|
+
* Any status check failure is actionable — it indicates instance or
|
|
26
|
+
* host impairment. 2-of-2 evaluation filters transient single-minute
|
|
27
|
+
* noise while keeping time-to-detect low.
|
|
28
|
+
*/
|
|
29
|
+
statusCheckFailed: {
|
|
30
|
+
threshold: 0,
|
|
31
|
+
evaluationPeriods: 2,
|
|
32
|
+
datapointsToAlarm: 2,
|
|
33
|
+
treatMissingData: TreatMissingData.NOT_BREACHING,
|
|
34
|
+
},
|
|
35
|
+
/**
|
|
36
|
+
* Attached EBS volumes are unreachable or unable to complete I/O —
|
|
37
|
+
* typically a host or storage-subsystem issue. The 10-of-10 evaluation
|
|
38
|
+
* window matches AWS guidance: EBS infrastructure usually self-heals
|
|
39
|
+
* within a few minutes, so a longer window avoids paging on transient
|
|
40
|
+
* issues that resolve without intervention.
|
|
41
|
+
*/
|
|
42
|
+
attachedEbsStatusCheckFailed: {
|
|
43
|
+
threshold: 1,
|
|
44
|
+
evaluationPeriods: 10,
|
|
45
|
+
datapointsToAlarm: 10,
|
|
46
|
+
treatMissingData: TreatMissingData.NOT_BREACHING,
|
|
47
|
+
},
|
|
48
|
+
/**
|
|
49
|
+
* Low CPU credit balance on burstable instances means imminent
|
|
50
|
+
* throttling to baseline performance. Threshold < 50 at 5-minute
|
|
51
|
+
* minimum gives an early warning to investigate or switch instance
|
|
52
|
+
* family. Credit balance metrics are only emitted at 5-minute
|
|
53
|
+
* granularity regardless of detailed monitoring.
|
|
54
|
+
*/
|
|
55
|
+
cpuCreditBalance: {
|
|
56
|
+
threshold: 50,
|
|
57
|
+
evaluationPeriods: 3,
|
|
58
|
+
datapointsToAlarm: 3,
|
|
59
|
+
treatMissingData: TreatMissingData.NOT_BREACHING,
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
//# sourceMappingURL=instance-alarm-defaults.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instance-alarm-defaults.js","sourceRoot":"","sources":["../src/instance-alarm-defaults.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAW9D;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAA0B;IAC5D,OAAO,EAAE,IAAI;IAEb;;;;OAIG;IACH,cAAc,EAAE;QACd,SAAS,EAAE,EAAE;QACb,iBAAiB,EAAE,CAAC;QACpB,iBAAiB,EAAE,CAAC;QACpB,gBAAgB,EAAE,gBAAgB,CAAC,aAAa;KACjD;IAED;;;;OAIG;IACH,iBAAiB,EAAE;QACjB,SAAS,EAAE,CAAC;QACZ,iBAAiB,EAAE,CAAC;QACpB,iBAAiB,EAAE,CAAC;QACpB,gBAAgB,EAAE,gBAAgB,CAAC,aAAa;KACjD;IAED;;;;;;OAMG;IACH,4BAA4B,EAAE;QAC5B,SAAS,EAAE,CAAC;QACZ,iBAAiB,EAAE,EAAE;QACrB,iBAAiB,EAAE,EAAE;QACrB,gBAAgB,EAAE,gBAAgB,CAAC,aAAa;KACjD;IAED;;;;;;OAMG;IACH,gBAAgB,EAAE;QAChB,SAAS,EAAE,EAAE;QACb,iBAAiB,EAAE,CAAC;QACpB,iBAAiB,EAAE,CAAC;QACpB,gBAAgB,EAAE,gBAAgB,CAAC,aAAa;KACjD;CACF,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { type Alarm } from "aws-cdk-lib/aws-cloudwatch";
|
|
2
|
+
import type { Instance, InstanceProps } from "aws-cdk-lib/aws-ec2";
|
|
3
|
+
import type { IConstruct } from "constructs";
|
|
4
|
+
import type { AlarmDefinition } from "@composurecdk/cloudwatch";
|
|
5
|
+
import { AlarmDefinitionBuilder } from "@composurecdk/cloudwatch";
|
|
6
|
+
import type { InstanceAlarmConfig } from "./instance-alarm-config.js";
|
|
7
|
+
/**
|
|
8
|
+
* Resolves the recommended alarm configuration into fully-resolved
|
|
9
|
+
* {@link AlarmDefinition}s, applying contextual logic for the
|
|
10
|
+
* burstable-only CPU credit alarm.
|
|
11
|
+
*/
|
|
12
|
+
export declare function resolveInstanceAlarmDefinitions(instance: Instance, config: InstanceAlarmConfig | undefined, props: Pick<InstanceProps, "instanceType">): AlarmDefinition[];
|
|
13
|
+
/**
|
|
14
|
+
* Creates AWS-recommended CloudWatch alarms for an EC2 instance,
|
|
15
|
+
* merging recommended definitions with any custom alarm builders.
|
|
16
|
+
*
|
|
17
|
+
* @param scope - CDK construct scope for creating alarm constructs.
|
|
18
|
+
* @param id - Base identifier for alarm construct ids.
|
|
19
|
+
* @param instance - The EC2 instance to create alarms for.
|
|
20
|
+
* @param config - User-provided alarm configuration, or `false` to disable all.
|
|
21
|
+
* @param props - The merged instance props, used for contextual alarm thresholds.
|
|
22
|
+
* @param customAlarms - Custom alarm builders added via `addAlarm()`.
|
|
23
|
+
* @returns A record mapping alarm keys to their created Alarm constructs.
|
|
24
|
+
*
|
|
25
|
+
* @see https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Best_Practice_Recommended_Alarms_AWS_Services.html#EC2
|
|
26
|
+
*/
|
|
27
|
+
export declare function createInstanceAlarms(scope: IConstruct, id: string, instance: Instance, config: InstanceAlarmConfig | false | undefined, props: Pick<InstanceProps, "instanceType">, customAlarms?: AlarmDefinitionBuilder<Instance>[]): Record<string, Alarm>;
|
|
28
|
+
//# sourceMappingURL=instance-alarms.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instance-alarms.d.ts","sourceRoot":"","sources":["../src/instance-alarms.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,KAAK,EAAqC,MAAM,4BAA4B,CAAC;AAC3F,OAAO,KAAK,EAAa,QAAQ,EAAE,aAAa,EAAgB,MAAM,qBAAqB,CAAC;AAC5F,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,EAAE,sBAAsB,EAAoC,MAAM,0BAA0B,CAAC;AACpG,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AA6CtE;;;;GAIG;AACH,wBAAgB,+BAA+B,CAC7C,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,mBAAmB,GAAG,SAAS,EACvC,KAAK,EAAE,IAAI,CAAC,aAAa,EAAE,cAAc,CAAC,GACzC,eAAe,EAAE,CA2EnB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,UAAU,EACjB,EAAE,EAAE,MAAM,EACV,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,mBAAmB,GAAG,KAAK,GAAG,SAAS,EAC/C,KAAK,EAAE,IAAI,CAAC,aAAa,EAAE,cAAc,CAAC,EAC1C,YAAY,GAAE,sBAAsB,CAAC,QAAQ,CAAC,EAAO,GACpD,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAUvB"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { Duration } from "aws-cdk-lib";
|
|
2
|
+
import { ComparisonOperator, Metric, Stats } from "aws-cdk-lib/aws-cloudwatch";
|
|
3
|
+
import { createAlarms, resolveAlarmConfig } from "@composurecdk/cloudwatch";
|
|
4
|
+
import { INSTANCE_ALARM_DEFAULTS } from "./instance-alarm-defaults.js";
|
|
5
|
+
const METRIC_PERIOD = Duration.minutes(1);
|
|
6
|
+
const METRIC_PERIOD_LABEL = `${String(METRIC_PERIOD.toMinutes())} minute`;
|
|
7
|
+
/**
|
|
8
|
+
* CPU credit metrics are emitted by EC2 at 5-minute granularity regardless
|
|
9
|
+
* of whether detailed monitoring is enabled. Using a shorter period yields
|
|
10
|
+
* missing data rather than higher resolution.
|
|
11
|
+
*
|
|
12
|
+
* @see https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/viewing_credits_CPU.html
|
|
13
|
+
*/
|
|
14
|
+
const CREDIT_METRIC_PERIOD = Duration.minutes(5);
|
|
15
|
+
const CREDIT_METRIC_PERIOD_LABEL = `${String(CREDIT_METRIC_PERIOD.toMinutes())} minute`;
|
|
16
|
+
/**
|
|
17
|
+
* Instance type family prefixes that accrue CPU credits (burstable).
|
|
18
|
+
* Used to decide whether to emit the contextual {@link InstanceAlarmConfig.cpuCreditBalance}
|
|
19
|
+
* alarm. Other families bill at a flat CPU rate and have no credit metric.
|
|
20
|
+
*
|
|
21
|
+
* @see https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/burstable-performance-instances.html
|
|
22
|
+
*/
|
|
23
|
+
const BURSTABLE_FAMILY_PREFIXES = ["t2.", "t3.", "t3a.", "t4g."];
|
|
24
|
+
function isBurstableInstanceType(instanceType) {
|
|
25
|
+
const identifier = instanceType.toString();
|
|
26
|
+
return BURSTABLE_FAMILY_PREFIXES.some((prefix) => identifier.startsWith(prefix));
|
|
27
|
+
}
|
|
28
|
+
function instanceMetric(instance, metricName, statistic, period = METRIC_PERIOD) {
|
|
29
|
+
return new Metric({
|
|
30
|
+
namespace: "AWS/EC2",
|
|
31
|
+
metricName,
|
|
32
|
+
dimensionsMap: { InstanceId: instance.instanceId },
|
|
33
|
+
statistic,
|
|
34
|
+
period,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Resolves the recommended alarm configuration into fully-resolved
|
|
39
|
+
* {@link AlarmDefinition}s, applying contextual logic for the
|
|
40
|
+
* burstable-only CPU credit alarm.
|
|
41
|
+
*/
|
|
42
|
+
export function resolveInstanceAlarmDefinitions(instance, config, props) {
|
|
43
|
+
if (config?.enabled === false)
|
|
44
|
+
return [];
|
|
45
|
+
const definitions = [];
|
|
46
|
+
if (config?.cpuUtilization !== false) {
|
|
47
|
+
const cfg = resolveAlarmConfig(config?.cpuUtilization, INSTANCE_ALARM_DEFAULTS.cpuUtilization);
|
|
48
|
+
definitions.push({
|
|
49
|
+
key: "cpuUtilization",
|
|
50
|
+
alarmName: cfg.alarmName,
|
|
51
|
+
metric: instanceMetric(instance, "CPUUtilization", Stats.AVERAGE),
|
|
52
|
+
threshold: cfg.threshold,
|
|
53
|
+
comparisonOperator: ComparisonOperator.GREATER_THAN_THRESHOLD,
|
|
54
|
+
evaluationPeriods: cfg.evaluationPeriods,
|
|
55
|
+
datapointsToAlarm: cfg.datapointsToAlarm,
|
|
56
|
+
treatMissingData: cfg.treatMissingData,
|
|
57
|
+
description: `EC2 instance CPU utilization is sustained at a high level. Threshold: > ${String(cfg.threshold)}% average over ${String(cfg.evaluationPeriods)} x ${METRIC_PERIOD_LABEL}.`,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
if (config?.statusCheckFailed !== false) {
|
|
61
|
+
const cfg = resolveAlarmConfig(config?.statusCheckFailed, INSTANCE_ALARM_DEFAULTS.statusCheckFailed);
|
|
62
|
+
definitions.push({
|
|
63
|
+
key: "statusCheckFailed",
|
|
64
|
+
alarmName: cfg.alarmName,
|
|
65
|
+
metric: instanceMetric(instance, "StatusCheckFailed", Stats.SUM),
|
|
66
|
+
threshold: cfg.threshold,
|
|
67
|
+
comparisonOperator: ComparisonOperator.GREATER_THAN_THRESHOLD,
|
|
68
|
+
evaluationPeriods: cfg.evaluationPeriods,
|
|
69
|
+
datapointsToAlarm: cfg.datapointsToAlarm,
|
|
70
|
+
treatMissingData: cfg.treatMissingData,
|
|
71
|
+
description: `EC2 instance is failing its status checks. Threshold: > ${String(cfg.threshold)} failed checks over ${String(cfg.evaluationPeriods)} x ${METRIC_PERIOD_LABEL}.`,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
if (config?.attachedEbsStatusCheckFailed !== false) {
|
|
75
|
+
const cfg = resolveAlarmConfig(config?.attachedEbsStatusCheckFailed, INSTANCE_ALARM_DEFAULTS.attachedEbsStatusCheckFailed);
|
|
76
|
+
definitions.push({
|
|
77
|
+
key: "attachedEbsStatusCheckFailed",
|
|
78
|
+
alarmName: cfg.alarmName,
|
|
79
|
+
metric: instanceMetric(instance, "StatusCheckFailed_AttachedEBS", Stats.MAXIMUM),
|
|
80
|
+
threshold: cfg.threshold,
|
|
81
|
+
comparisonOperator: ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD,
|
|
82
|
+
evaluationPeriods: cfg.evaluationPeriods,
|
|
83
|
+
datapointsToAlarm: cfg.datapointsToAlarm,
|
|
84
|
+
treatMissingData: cfg.treatMissingData,
|
|
85
|
+
description: `EC2 instance attached EBS volume(s) are unreachable or unable to complete I/O. Threshold: >= ${String(cfg.threshold)} failed checks (max) over ${String(cfg.evaluationPeriods)} x ${METRIC_PERIOD_LABEL}.`,
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
if (config?.cpuCreditBalance !== false && isBurstableInstanceType(props.instanceType)) {
|
|
89
|
+
const cfg = resolveAlarmConfig(config?.cpuCreditBalance, INSTANCE_ALARM_DEFAULTS.cpuCreditBalance);
|
|
90
|
+
definitions.push({
|
|
91
|
+
key: "cpuCreditBalance",
|
|
92
|
+
alarmName: cfg.alarmName,
|
|
93
|
+
metric: instanceMetric(instance, "CPUCreditBalance", Stats.MINIMUM, CREDIT_METRIC_PERIOD),
|
|
94
|
+
threshold: cfg.threshold,
|
|
95
|
+
comparisonOperator: ComparisonOperator.LESS_THAN_THRESHOLD,
|
|
96
|
+
evaluationPeriods: cfg.evaluationPeriods,
|
|
97
|
+
datapointsToAlarm: cfg.datapointsToAlarm,
|
|
98
|
+
treatMissingData: cfg.treatMissingData,
|
|
99
|
+
description: `EC2 burstable instance CPU credit balance is low — baseline throttling is imminent. Threshold: < ${String(cfg.threshold)} credits (minimum) over ${String(cfg.evaluationPeriods)} x ${CREDIT_METRIC_PERIOD_LABEL}.`,
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
return definitions;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Creates AWS-recommended CloudWatch alarms for an EC2 instance,
|
|
106
|
+
* merging recommended definitions with any custom alarm builders.
|
|
107
|
+
*
|
|
108
|
+
* @param scope - CDK construct scope for creating alarm constructs.
|
|
109
|
+
* @param id - Base identifier for alarm construct ids.
|
|
110
|
+
* @param instance - The EC2 instance to create alarms for.
|
|
111
|
+
* @param config - User-provided alarm configuration, or `false` to disable all.
|
|
112
|
+
* @param props - The merged instance props, used for contextual alarm thresholds.
|
|
113
|
+
* @param customAlarms - Custom alarm builders added via `addAlarm()`.
|
|
114
|
+
* @returns A record mapping alarm keys to their created Alarm constructs.
|
|
115
|
+
*
|
|
116
|
+
* @see https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Best_Practice_Recommended_Alarms_AWS_Services.html#EC2
|
|
117
|
+
*/
|
|
118
|
+
export function createInstanceAlarms(scope, id, instance, config, props, customAlarms = []) {
|
|
119
|
+
if (config === false)
|
|
120
|
+
return {};
|
|
121
|
+
const enabled = config?.enabled ?? INSTANCE_ALARM_DEFAULTS.enabled;
|
|
122
|
+
if (!enabled)
|
|
123
|
+
return {};
|
|
124
|
+
const recommended = resolveInstanceAlarmDefinitions(instance, config, props);
|
|
125
|
+
const custom = customAlarms.map((b) => b.resolve(instance));
|
|
126
|
+
return createAlarms(scope, id, [...recommended, ...custom]);
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=instance-alarms.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instance-alarms.js","sourceRoot":"","sources":["../src/instance-alarms.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { type Alarm } from "aws-cdk-lib/aws-cloudwatch";
|
|
2
|
+
import { Instance, type IKeyPair, type ISecurityGroup, type IVpc, type InstanceProps } from "aws-cdk-lib/aws-ec2";
|
|
3
|
+
import { type IRole } from "aws-cdk-lib/aws-iam";
|
|
4
|
+
import { type IConstruct } from "constructs";
|
|
5
|
+
import { type IBuilder, type Lifecycle, type Resolvable } from "@composurecdk/core";
|
|
6
|
+
import { AlarmDefinitionBuilder } from "@composurecdk/cloudwatch";
|
|
7
|
+
import type { InstanceAlarmConfig } from "./instance-alarm-config.js";
|
|
8
|
+
/**
|
|
9
|
+
* Configuration properties for the EC2 instance builder.
|
|
10
|
+
*
|
|
11
|
+
* Extends the CDK {@link InstanceProps} but lifts the cross-component-wiring
|
|
12
|
+
* props to {@link Resolvable} so they can be supplied as either concrete
|
|
13
|
+
* values or {@link Ref}s to sibling components in a {@link compose}d system:
|
|
14
|
+
*
|
|
15
|
+
* - `vpc` is supplied via the dedicated
|
|
16
|
+
* {@link IInstanceBuilder.vpc | .vpc()} method.
|
|
17
|
+
* - `role`, `keyPair`, and `securityGroup` are exposed on the builder as
|
|
18
|
+
* `Resolvable<T>` setters.
|
|
19
|
+
*
|
|
20
|
+
* Other props (`instanceType`, `machineImage`, `userData`, `blockDevices`,
|
|
21
|
+
* etc.) are passed through with their CDK types unchanged because they are
|
|
22
|
+
* almost always constructed inline rather than referenced from another
|
|
23
|
+
* component.
|
|
24
|
+
*/
|
|
25
|
+
export interface InstanceBuilderProps extends Omit<InstanceProps, "vpc" | "role" | "keyPair" | "securityGroup"> {
|
|
26
|
+
/**
|
|
27
|
+
* IAM role assumed by the instance via its instance profile.
|
|
28
|
+
*
|
|
29
|
+
* Accepts a concrete {@link IRole} or a {@link Ref} that resolves to one
|
|
30
|
+
* at build time, e.g. a sibling `RoleBuilder` in the same composed system.
|
|
31
|
+
*
|
|
32
|
+
* @default - CDK creates a role and attaches `AmazonSSMManagedInstanceCore`,
|
|
33
|
+
* driven by the `ssmSessionPermissions: true` default in
|
|
34
|
+
* {@link INSTANCE_DEFAULTS}.
|
|
35
|
+
*/
|
|
36
|
+
role?: Resolvable<IRole>;
|
|
37
|
+
/**
|
|
38
|
+
* Key pair to associate with the instance.
|
|
39
|
+
*
|
|
40
|
+
* Accepts a concrete {@link IKeyPair} or a {@link Ref} that resolves to
|
|
41
|
+
* one at build time.
|
|
42
|
+
*
|
|
43
|
+
* @default - no key pair is associated; SSM Session Manager is the
|
|
44
|
+
* recommended access path.
|
|
45
|
+
*/
|
|
46
|
+
keyPair?: Resolvable<IKeyPair>;
|
|
47
|
+
/**
|
|
48
|
+
* Primary security group for the instance.
|
|
49
|
+
*
|
|
50
|
+
* Accepts a concrete {@link ISecurityGroup} or a {@link Ref} that resolves
|
|
51
|
+
* to one at build time. Additional security groups can be attached via
|
|
52
|
+
* `instance.addSecurityGroup()` after build.
|
|
53
|
+
*
|
|
54
|
+
* @default - CDK creates a security group allowing all outbound traffic.
|
|
55
|
+
*/
|
|
56
|
+
securityGroup?: Resolvable<ISecurityGroup>;
|
|
57
|
+
/**
|
|
58
|
+
* Configuration for AWS-recommended CloudWatch alarms.
|
|
59
|
+
*
|
|
60
|
+
* By default, the builder creates recommended alarms with sensible
|
|
61
|
+
* thresholds for every applicable metric. Individual alarms can be
|
|
62
|
+
* customized or disabled. Set to `false` to disable all alarms.
|
|
63
|
+
*
|
|
64
|
+
* No alarm actions are configured by default since notification methods
|
|
65
|
+
* are user-specific. Access alarms from the build result or use an
|
|
66
|
+
* `afterBuild` hook to apply actions.
|
|
67
|
+
*
|
|
68
|
+
* Contextual alarms (`cpuCreditBalance`) are only created when the
|
|
69
|
+
* corresponding instance configuration is present — e.g., burstable
|
|
70
|
+
* T-family instance types.
|
|
71
|
+
*
|
|
72
|
+
* @see https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Best_Practice_Recommended_Alarms_AWS_Services.html#EC2
|
|
73
|
+
*/
|
|
74
|
+
recommendedAlarms?: InstanceAlarmConfig | false;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* The build output of a {@link IInstanceBuilder}. Contains the CDK
|
|
78
|
+
* constructs created during {@link Lifecycle.build}, keyed by role.
|
|
79
|
+
*/
|
|
80
|
+
export interface InstanceBuilderResult {
|
|
81
|
+
instance: Instance;
|
|
82
|
+
/**
|
|
83
|
+
* CloudWatch alarms created for the instance, keyed by alarm name.
|
|
84
|
+
*
|
|
85
|
+
* Includes both AWS-recommended alarms and any custom alarms added
|
|
86
|
+
* via {@link IInstanceBuilder.addAlarm}. Access individual alarms by
|
|
87
|
+
* key (e.g., `result.alarms.cpuUtilization`).
|
|
88
|
+
*
|
|
89
|
+
* No alarm actions are configured — apply them via the result or an
|
|
90
|
+
* `afterBuild` hook.
|
|
91
|
+
*
|
|
92
|
+
* @see https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Best_Practice_Recommended_Alarms_AWS_Services.html#EC2
|
|
93
|
+
*/
|
|
94
|
+
alarms: Record<string, Alarm>;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* A fluent builder for configuring and creating an AWS EC2 instance.
|
|
98
|
+
*
|
|
99
|
+
* Each configuration property from the CDK {@link InstanceProps} is exposed
|
|
100
|
+
* as an overloaded method: call with a value to set it (returns the builder
|
|
101
|
+
* for chaining), or call with no arguments to read the current value.
|
|
102
|
+
*
|
|
103
|
+
* The `vpc` is set via the dedicated {@link IInstanceBuilder.vpc | .vpc()}
|
|
104
|
+
* method that accepts a {@link Resolvable} value for cross-component wiring
|
|
105
|
+
* (e.g., to a sibling {@link IVpcBuilder}). The `role`, `keyPair`, and
|
|
106
|
+
* `securityGroup` setters likewise accept {@link Resolvable} values so they
|
|
107
|
+
* can be supplied by sibling builders' outputs via {@link ref}.
|
|
108
|
+
*
|
|
109
|
+
* The builder implements {@link Lifecycle}, so it can be used directly as a
|
|
110
|
+
* component in a {@link compose | composed system}. When built, it creates
|
|
111
|
+
* an EC2 instance with the configured properties and returns an
|
|
112
|
+
* {@link InstanceBuilderResult}.
|
|
113
|
+
*
|
|
114
|
+
* AWS-recommended CloudWatch alarms are created by default. Alarms can be
|
|
115
|
+
* customized or disabled via the `recommendedAlarms` property. Custom
|
|
116
|
+
* alarms can be added via the {@link addAlarm} method.
|
|
117
|
+
*
|
|
118
|
+
* @see https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2-readme.html
|
|
119
|
+
*
|
|
120
|
+
* @example
|
|
121
|
+
* ```ts
|
|
122
|
+
* const server = createInstanceBuilder()
|
|
123
|
+
* .vpc(vpc)
|
|
124
|
+
* .instanceType(InstanceType.of(InstanceClass.T3, InstanceSize.MICRO))
|
|
125
|
+
* .machineImage(MachineImage.latestAmazonLinux2023());
|
|
126
|
+
* ```
|
|
127
|
+
*/
|
|
128
|
+
export type IInstanceBuilder = IBuilder<InstanceBuilderProps, InstanceBuilder>;
|
|
129
|
+
declare class InstanceBuilder implements Lifecycle<InstanceBuilderResult> {
|
|
130
|
+
#private;
|
|
131
|
+
props: Partial<InstanceBuilderProps>;
|
|
132
|
+
/**
|
|
133
|
+
* Sets the VPC the instance will be launched into.
|
|
134
|
+
*
|
|
135
|
+
* Accepts a concrete {@link IVpc} or a {@link Ref} that resolves to one
|
|
136
|
+
* at build time. This is how cross-component wiring works — e.g., to a
|
|
137
|
+
* sibling {@link IVpcBuilder} in the same composed system.
|
|
138
|
+
*
|
|
139
|
+
* @param vpc - The VPC or a Ref to one.
|
|
140
|
+
* @returns This builder for chaining.
|
|
141
|
+
*/
|
|
142
|
+
vpc(vpc: Resolvable<IVpc>): this;
|
|
143
|
+
/**
|
|
144
|
+
* Adds a custom CloudWatch alarm to be created alongside the recommended
|
|
145
|
+
* alarms. The provided callback receives an {@link AlarmDefinitionBuilder}
|
|
146
|
+
* scoped to the built {@link Instance}; configure it fluently and return it.
|
|
147
|
+
*
|
|
148
|
+
* @param key - A unique key for the alarm (used to generate the alarm id).
|
|
149
|
+
* @param configure - Callback that configures the alarm definition.
|
|
150
|
+
* @returns This builder for chaining.
|
|
151
|
+
*/
|
|
152
|
+
addAlarm(key: string, configure: (alarm: AlarmDefinitionBuilder<Instance>) => AlarmDefinitionBuilder<Instance>): this;
|
|
153
|
+
build(scope: IConstruct, id: string, context?: Record<string, object>): InstanceBuilderResult;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Creates a new {@link IInstanceBuilder} for configuring an AWS EC2 instance.
|
|
157
|
+
*
|
|
158
|
+
* This is the entry point for defining an EC2 instance component. The
|
|
159
|
+
* returned builder exposes every {@link InstanceBuilderProps} property as a
|
|
160
|
+
* fluent setter/getter, plus {@link IInstanceBuilder.vpc | .vpc()} for
|
|
161
|
+
* cross-component VPC wiring with Ref support. It implements
|
|
162
|
+
* {@link Lifecycle} for use with {@link compose}.
|
|
163
|
+
*
|
|
164
|
+
* @returns A fluent builder for an AWS EC2 instance.
|
|
165
|
+
*
|
|
166
|
+
* @example
|
|
167
|
+
* ```ts
|
|
168
|
+
* const server = createInstanceBuilder()
|
|
169
|
+
* .vpc(ref<VpcBuilderResult>("network").get("vpc"))
|
|
170
|
+
* .instanceType(InstanceType.of(InstanceClass.T3, InstanceSize.MICRO))
|
|
171
|
+
* .machineImage(MachineImage.latestAmazonLinux2023());
|
|
172
|
+
*
|
|
173
|
+
* // Use standalone:
|
|
174
|
+
* const result = server.build(stack, "MyInstance");
|
|
175
|
+
*
|
|
176
|
+
* // Or compose into a system:
|
|
177
|
+
* const system = compose(
|
|
178
|
+
* { network: createVpcBuilder(), server },
|
|
179
|
+
* { network: [], server: ["network"] },
|
|
180
|
+
* );
|
|
181
|
+
* ```
|
|
182
|
+
*/
|
|
183
|
+
export declare function createInstanceBuilder(): IInstanceBuilder;
|
|
184
|
+
export {};
|
|
185
|
+
//# sourceMappingURL=instance-builder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instance-builder.d.ts","sourceRoot":"","sources":["../src/instance-builder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,4BAA4B,CAAC;AACxD,OAAO,EACL,QAAQ,EACR,KAAK,QAAQ,EACb,KAAK,cAAc,EACnB,KAAK,IAAI,EACT,KAAK,aAAa,EACnB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAEL,KAAK,QAAQ,EACb,KAAK,SAAS,EAEd,KAAK,UAAU,EAChB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAItE;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,WAAW,oBAAqB,SAAQ,IAAI,CAChD,aAAa,EACb,KAAK,GAAG,MAAM,GAAG,SAAS,GAAG,eAAe,CAC7C;IACC;;;;;;;;;OASG;IACH,IAAI,CAAC,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC;IAEzB;;;;;;;;OAQG;IACH,OAAO,CAAC,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC;IAE/B;;;;;;;;OAQG;IACH,aAAa,CAAC,EAAE,UAAU,CAAC,cAAc,CAAC,CAAC;IAE3C;;;;;;;;;;;;;;;;OAgBG;IACH,iBAAiB,CAAC,EAAE,mBAAmB,GAAG,KAAK,CAAC;CACjD;AAED;;;GAGG;AACH,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,QAAQ,CAAC;IAEnB;;;;;;;;;;;OAWG;IACH,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;CAC/B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,MAAM,MAAM,gBAAgB,GAAG,QAAQ,CAAC,oBAAoB,EAAE,eAAe,CAAC,CAAC;AAE/E,cAAM,eAAgB,YAAW,SAAS,CAAC,qBAAqB,CAAC;;IAC/D,KAAK,EAAE,OAAO,CAAC,oBAAoB,CAAC,CAAM;IAI1C;;;;;;;;;OASG;IACH,GAAG,CAAC,GAAG,EAAE,UAAU,CAAC,IAAI,CAAC,GAAG,IAAI;IAKhC;;;;;;;;OAQG;IACH,QAAQ,CACN,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,CAAC,KAAK,EAAE,sBAAsB,CAAC,QAAQ,CAAC,KAAK,sBAAsB,CAAC,QAAQ,CAAC,GACvF,IAAI;IAKP,KAAK,CAAC,KAAK,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,qBAAqB;CAuC9F;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,qBAAqB,IAAI,gBAAgB,CAExD"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { Instance, } from "aws-cdk-lib/aws-ec2";
|
|
2
|
+
import { Builder, resolve, } from "@composurecdk/core";
|
|
3
|
+
import { AlarmDefinitionBuilder } from "@composurecdk/cloudwatch";
|
|
4
|
+
import { createInstanceAlarms } from "./instance-alarms.js";
|
|
5
|
+
import { INSTANCE_DEFAULTS } from "./instance-defaults.js";
|
|
6
|
+
class InstanceBuilder {
|
|
7
|
+
props = {};
|
|
8
|
+
#customAlarms = [];
|
|
9
|
+
#vpc;
|
|
10
|
+
/**
|
|
11
|
+
* Sets the VPC the instance will be launched into.
|
|
12
|
+
*
|
|
13
|
+
* Accepts a concrete {@link IVpc} or a {@link Ref} that resolves to one
|
|
14
|
+
* at build time. This is how cross-component wiring works — e.g., to a
|
|
15
|
+
* sibling {@link IVpcBuilder} in the same 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 a custom CloudWatch alarm to be created alongside the recommended
|
|
26
|
+
* alarms. The provided callback receives an {@link AlarmDefinitionBuilder}
|
|
27
|
+
* scoped to the built {@link Instance}; configure it fluently and return it.
|
|
28
|
+
*
|
|
29
|
+
* @param key - A unique key for the alarm (used to generate the alarm id).
|
|
30
|
+
* @param configure - Callback that configures the alarm definition.
|
|
31
|
+
* @returns This builder for chaining.
|
|
32
|
+
*/
|
|
33
|
+
addAlarm(key, configure) {
|
|
34
|
+
this.#customAlarms.push(configure(new AlarmDefinitionBuilder(key)));
|
|
35
|
+
return this;
|
|
36
|
+
}
|
|
37
|
+
build(scope, id, context) {
|
|
38
|
+
const resolvedVpc = this.#vpc ? resolve(this.#vpc, context) : undefined;
|
|
39
|
+
if (!resolvedVpc) {
|
|
40
|
+
throw new Error(`InstanceBuilder "${id}" requires a VPC. Call .vpc() with an IVpc or a Ref to one.`);
|
|
41
|
+
}
|
|
42
|
+
const { recommendedAlarms: alarmConfig, role, keyPair, securityGroup, ...instanceProps } = this.props;
|
|
43
|
+
const mergedProps = {
|
|
44
|
+
...INSTANCE_DEFAULTS,
|
|
45
|
+
...instanceProps,
|
|
46
|
+
vpc: resolvedVpc,
|
|
47
|
+
...(role !== undefined ? { role: resolve(role, context) } : {}),
|
|
48
|
+
...(keyPair !== undefined ? { keyPair: resolve(keyPair, context) } : {}),
|
|
49
|
+
...(securityGroup !== undefined ? { securityGroup: resolve(securityGroup, context) } : {}),
|
|
50
|
+
};
|
|
51
|
+
const instance = new Instance(scope, id, mergedProps);
|
|
52
|
+
const alarms = createInstanceAlarms(scope, id, instance, alarmConfig, mergedProps, this.#customAlarms);
|
|
53
|
+
return { instance, alarms };
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Creates a new {@link IInstanceBuilder} for configuring an AWS EC2 instance.
|
|
58
|
+
*
|
|
59
|
+
* This is the entry point for defining an EC2 instance component. The
|
|
60
|
+
* returned builder exposes every {@link InstanceBuilderProps} property as a
|
|
61
|
+
* fluent setter/getter, plus {@link IInstanceBuilder.vpc | .vpc()} for
|
|
62
|
+
* cross-component VPC wiring with Ref support. It implements
|
|
63
|
+
* {@link Lifecycle} for use with {@link compose}.
|
|
64
|
+
*
|
|
65
|
+
* @returns A fluent builder for an AWS EC2 instance.
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* ```ts
|
|
69
|
+
* const server = createInstanceBuilder()
|
|
70
|
+
* .vpc(ref<VpcBuilderResult>("network").get("vpc"))
|
|
71
|
+
* .instanceType(InstanceType.of(InstanceClass.T3, InstanceSize.MICRO))
|
|
72
|
+
* .machineImage(MachineImage.latestAmazonLinux2023());
|
|
73
|
+
*
|
|
74
|
+
* // Use standalone:
|
|
75
|
+
* const result = server.build(stack, "MyInstance");
|
|
76
|
+
*
|
|
77
|
+
* // Or compose into a system:
|
|
78
|
+
* const system = compose(
|
|
79
|
+
* { network: createVpcBuilder(), server },
|
|
80
|
+
* { network: [], server: ["network"] },
|
|
81
|
+
* );
|
|
82
|
+
* ```
|
|
83
|
+
*/
|
|
84
|
+
export function createInstanceBuilder() {
|
|
85
|
+
return Builder(InstanceBuilder);
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=instance-builder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instance-builder.js","sourceRoot":"","sources":["../src/instance-builder.ts"],"names":[],"mappings":"AACA,OAAO,EACL,QAAQ,GAKT,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EACL,OAAO,EAGP,OAAO,GAER,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAElE,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAqI3D,MAAM,eAAe;IACnB,KAAK,GAAkC,EAAE,CAAC;IACjC,aAAa,GAAuC,EAAE,CAAC;IAChE,IAAI,CAAoB;IAExB;;;;;;;;;OASG;IACH,GAAG,CAAC,GAAqB;QACvB,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC;QAChB,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;;;;;;OAQG;IACH,QAAQ,CACN,GAAW,EACX,SAAwF;QAExF,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,sBAAsB,CAAW,GAAG,CAAC,CAAC,CAAC,CAAC;QAC9E,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK,CAAC,KAAiB,EAAE,EAAU,EAAE,OAAgC;QACnE,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAExE,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CACb,oBAAoB,EAAE,6DAA6D,CACpF,CAAC;QACJ,CAAC;QAED,MAAM,EACJ,iBAAiB,EAAE,WAAW,EAC9B,IAAI,EACJ,OAAO,EACP,aAAa,EACb,GAAG,aAAa,EACjB,GAAG,IAAI,CAAC,KAAK,CAAC;QAEf,MAAM,WAAW,GAAG;YAClB,GAAG,iBAAiB;YACpB,GAAG,aAAa;YAChB,GAAG,EAAE,WAAW;YAChB,GAAG,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC/D,GAAG,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACxE,GAAG,CAAC,aAAa,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,OAAO,CAAC,aAAa,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC1E,CAAC;QAEnB,MAAM,QAAQ,GAAG,IAAI,QAAQ,CAAC,KAAK,EAAE,EAAE,EAAE,WAAW,CAAC,CAAC;QAEtD,MAAM,MAAM,GAAG,oBAAoB,CACjC,KAAK,EACL,EAAE,EACF,QAAQ,EACR,WAAW,EACX,WAAW,EACX,IAAI,CAAC,aAAa,CACnB,CAAC;QAEF,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;IAC9B,CAAC;CACF;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,UAAU,qBAAqB;IACnC,OAAO,OAAO,CAAwC,eAAe,CAAC,CAAC;AACzE,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type InstanceProps } from "aws-cdk-lib/aws-ec2";
|
|
2
|
+
/**
|
|
3
|
+
* Secure, AWS-recommended defaults applied to every EC2 instance built with
|
|
4
|
+
* {@link createInstanceBuilder}. Each property can be individually overridden
|
|
5
|
+
* via the builder's fluent API.
|
|
6
|
+
*
|
|
7
|
+
* Three required properties intentionally have no default — they are
|
|
8
|
+
* application-specific and must be supplied explicitly:
|
|
9
|
+
* - `vpc` (via the builder's `.vpc()` method)
|
|
10
|
+
* - `instanceType`
|
|
11
|
+
* - `machineImage`
|
|
12
|
+
*/
|
|
13
|
+
export declare const INSTANCE_DEFAULTS: Partial<InstanceProps>;
|
|
14
|
+
//# sourceMappingURL=instance-defaults.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instance-defaults.d.ts","sourceRoot":"","sources":["../src/instance-defaults.ts"],"names":[],"mappings":"AAAA,OAAO,EAA0C,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEjG;;;;;;;;;;GAUG;AACH,eAAO,MAAM,iBAAiB,EAAE,OAAO,CAAC,aAAa,CAiDpD,CAAC"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { BlockDeviceVolume, EbsDeviceVolumeType } from "aws-cdk-lib/aws-ec2";
|
|
2
|
+
/**
|
|
3
|
+
* Secure, AWS-recommended defaults applied to every EC2 instance built with
|
|
4
|
+
* {@link createInstanceBuilder}. Each property can be individually overridden
|
|
5
|
+
* via the builder's fluent API.
|
|
6
|
+
*
|
|
7
|
+
* Three required properties intentionally have no default — they are
|
|
8
|
+
* application-specific and must be supplied explicitly:
|
|
9
|
+
* - `vpc` (via the builder's `.vpc()` method)
|
|
10
|
+
* - `instanceType`
|
|
11
|
+
* - `machineImage`
|
|
12
|
+
*/
|
|
13
|
+
export const INSTANCE_DEFAULTS = {
|
|
14
|
+
/**
|
|
15
|
+
* Require IMDSv2. IMDSv1 is vulnerable to SSRF-based credential exfiltration;
|
|
16
|
+
* IMDSv2 requires a session token and blocks the common attack pattern.
|
|
17
|
+
* @see https://docs.aws.amazon.com/wellarchitected/latest/security-pillar/sec_detect_investigate_events_app_service_logging.html
|
|
18
|
+
* @see https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html
|
|
19
|
+
*/
|
|
20
|
+
requireImdsv2: true,
|
|
21
|
+
/**
|
|
22
|
+
* Enable detailed (1-minute) CloudWatch metrics. Without this, instance
|
|
23
|
+
* metrics are emitted at 5-minute granularity, which makes short-window
|
|
24
|
+
* alarm evaluation unreliable.
|
|
25
|
+
* @see https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-cloudwatch-new.html
|
|
26
|
+
*/
|
|
27
|
+
detailedMonitoring: true,
|
|
28
|
+
/**
|
|
29
|
+
* Attach the AmazonSSMManagedInstanceCore managed policy so Session Manager
|
|
30
|
+
* can be used in place of SSH. Removes the need for key pairs, bastion
|
|
31
|
+
* hosts, or inbound SSH access.
|
|
32
|
+
* @see https://docs.aws.amazon.com/systems-manager/latest/userguide/session-manager.html
|
|
33
|
+
*/
|
|
34
|
+
ssmSessionPermissions: true,
|
|
35
|
+
/**
|
|
36
|
+
* EBS-optimized networking — dedicated bandwidth between the instance and
|
|
37
|
+
* its EBS volumes. Free and on-by-default for current-generation instance
|
|
38
|
+
* types; set explicitly for consistency.
|
|
39
|
+
* @see https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ebs-optimized.html
|
|
40
|
+
*/
|
|
41
|
+
ebsOptimized: true,
|
|
42
|
+
/**
|
|
43
|
+
* Encrypt the root EBS volume at rest using the account's default EBS KMS
|
|
44
|
+
* key. GP3 is the current-generation general-purpose volume type — cheaper
|
|
45
|
+
* and faster than GP2 at equivalent sizes. Users override this to change
|
|
46
|
+
* volume size, IOPS, throughput, or to add additional block devices.
|
|
47
|
+
* @see https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EBSEncryption.html
|
|
48
|
+
*/
|
|
49
|
+
blockDevices: [
|
|
50
|
+
{
|
|
51
|
+
deviceName: "/dev/xvda",
|
|
52
|
+
volume: BlockDeviceVolume.ebs(8, {
|
|
53
|
+
encrypted: true,
|
|
54
|
+
volumeType: EbsDeviceVolumeType.GP3,
|
|
55
|
+
}),
|
|
56
|
+
},
|
|
57
|
+
],
|
|
58
|
+
};
|
|
59
|
+
//# sourceMappingURL=instance-defaults.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instance-defaults.js","sourceRoot":"","sources":["../src/instance-defaults.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAsB,MAAM,qBAAqB,CAAC;AAEjG;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAA2B;IACvD;;;;;OAKG;IACH,aAAa,EAAE,IAAI;IAEnB;;;;;OAKG;IACH,kBAAkB,EAAE,IAAI;IAExB;;;;;OAKG;IACH,qBAAqB,EAAE,IAAI;IAE3B;;;;;OAKG;IACH,YAAY,EAAE,IAAI;IAElB;;;;;;OAMG;IACH,YAAY,EAAE;QACZ;YACE,UAAU,EAAE,WAAW;YACvB,MAAM,EAAE,iBAAiB,CAAC,GAAG,CAAC,CAAC,EAAE;gBAC/B,SAAS,EAAE,IAAI;gBACf,UAAU,EAAE,mBAAmB,CAAC,GAAG;aACpC,CAAC;SACH;KACF;CACF,CAAC"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { FlowLogDestination, Vpc, type VpcProps } from "aws-cdk-lib/aws-ec2";
|
|
2
|
+
import { type LogGroup } from "aws-cdk-lib/aws-logs";
|
|
3
|
+
import { type IConstruct } from "constructs";
|
|
4
|
+
import { type IBuilder, type Lifecycle } from "@composurecdk/core";
|
|
5
|
+
import { type ILogGroupBuilder } from "@composurecdk/logs";
|
|
6
|
+
/**
|
|
7
|
+
* Configures how VPC flow logs are handled. Pass `false` to disable flow
|
|
8
|
+
* logs; pass an object to wire a destination or customize the auto-created
|
|
9
|
+
* LogGroup sub-builder.
|
|
10
|
+
*
|
|
11
|
+
* `configure` cannot be combined with `destination` — a user-managed
|
|
12
|
+
* destination is not built by this builder.
|
|
13
|
+
*
|
|
14
|
+
* For multiple flow logs against the same VPC, omit this config and create
|
|
15
|
+
* additional `FlowLog` constructs directly against the returned `vpc`.
|
|
16
|
+
*
|
|
17
|
+
* @see https://docs.aws.amazon.com/vpc/latest/userguide/flow-logs.html
|
|
18
|
+
*/
|
|
19
|
+
export type FlowLogsConfig = false | {
|
|
20
|
+
/** A user-managed flow log destination. Cannot be combined with `configure`. */
|
|
21
|
+
destination?: FlowLogDestination;
|
|
22
|
+
/**
|
|
23
|
+
* Customize the auto-created LogGroup sub-builder. Receives a builder
|
|
24
|
+
* pre-seeded with the well-architected log retention/removal defaults
|
|
25
|
+
* from {@link createLogGroupBuilder}.
|
|
26
|
+
*/
|
|
27
|
+
configure?: (b: ILogGroupBuilder) => ILogGroupBuilder;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Configuration properties for the VPC builder.
|
|
31
|
+
*
|
|
32
|
+
* Hides the CDK `flowLogs` map field in favor of {@link flowLogs} — a
|
|
33
|
+
* discriminated config that supports an `false` opt-out, a user-managed
|
|
34
|
+
* destination, or a customizable auto-managed LogGroup.
|
|
35
|
+
*/
|
|
36
|
+
export interface VpcBuilderProps extends Omit<VpcProps, "flowLogs"> {
|
|
37
|
+
/** See {@link FlowLogsConfig}. Defaults to an auto-managed LogGroup-backed flow log. */
|
|
38
|
+
flowLogs?: FlowLogsConfig;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* The build output of a {@link IVpcBuilder}. Contains the CDK constructs
|
|
42
|
+
* created during {@link Lifecycle.build}, keyed by role.
|
|
43
|
+
*/
|
|
44
|
+
export interface VpcBuilderResult {
|
|
45
|
+
vpc: Vpc;
|
|
46
|
+
/**
|
|
47
|
+
* The CloudWatch LogGroup created for the auto-managed flow log, or
|
|
48
|
+
* `undefined` when the user supplied their own `destination` or
|
|
49
|
+
* disabled flow logs entirely.
|
|
50
|
+
*
|
|
51
|
+
* @see https://docs.aws.amazon.com/vpc/latest/userguide/flow-logs.html
|
|
52
|
+
*/
|
|
53
|
+
flowLogsLogGroup?: LogGroup;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* A fluent builder for configuring and creating an AWS VPC.
|
|
57
|
+
*
|
|
58
|
+
* Each configuration property from the CDK {@link VpcProps} is exposed as an
|
|
59
|
+
* overloaded method: call with a value to set it (returns the builder for
|
|
60
|
+
* chaining), or call with no arguments to read the current value.
|
|
61
|
+
*
|
|
62
|
+
* The builder implements {@link Lifecycle}, so it can be used directly as a
|
|
63
|
+
* component in a {@link compose | composed system}. When built, it creates
|
|
64
|
+
* a VPC with {@link VPC_DEFAULTS | well-architected defaults} and returns a
|
|
65
|
+
* {@link VpcBuilderResult}.
|
|
66
|
+
*
|
|
67
|
+
* By default the builder auto-creates a CloudWatch-Logs-backed flow log
|
|
68
|
+
* using a managed {@link LogGroup} so every VPC gets baseline network audit
|
|
69
|
+
* logging. Customize via {@link FlowLogsConfig} or disable with
|
|
70
|
+
* `flowLogs(false)`.
|
|
71
|
+
*
|
|
72
|
+
* @see https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.Vpc.html
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* ```ts
|
|
76
|
+
* const network = createVpcBuilder().maxAzs(3).natGateways(3);
|
|
77
|
+
* ```
|
|
78
|
+
*/
|
|
79
|
+
export type IVpcBuilder = IBuilder<VpcBuilderProps, VpcBuilder>;
|
|
80
|
+
declare class VpcBuilder implements Lifecycle<VpcBuilderResult> {
|
|
81
|
+
props: Partial<VpcBuilderProps>;
|
|
82
|
+
build(scope: IConstruct, id: string): VpcBuilderResult;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Creates a new {@link IVpcBuilder} for configuring an AWS VPC.
|
|
86
|
+
*
|
|
87
|
+
* This is the entry point for defining a VPC component. The returned builder
|
|
88
|
+
* exposes every {@link VpcBuilderProps} property as a fluent setter/getter
|
|
89
|
+
* and implements {@link Lifecycle} for use with {@link compose}.
|
|
90
|
+
*
|
|
91
|
+
* @returns A fluent builder for an AWS VPC.
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* ```ts
|
|
95
|
+
* const network = createVpcBuilder().maxAzs(3).natGateways(3);
|
|
96
|
+
*
|
|
97
|
+
* // Use standalone:
|
|
98
|
+
* const result = network.build(stack, "Network");
|
|
99
|
+
*
|
|
100
|
+
* // Or compose into a system:
|
|
101
|
+
* const system = compose(
|
|
102
|
+
* { network, server: createInstanceBuilder() },
|
|
103
|
+
* { network: [], server: ["network"] },
|
|
104
|
+
* );
|
|
105
|
+
* ```
|
|
106
|
+
*/
|
|
107
|
+
export declare function createVpcBuilder(): IVpcBuilder;
|
|
108
|
+
export {};
|
|
109
|
+
//# sourceMappingURL=vpc-builder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vpc-builder.d.ts","sourceRoot":"","sources":["../src/vpc-builder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,GAAG,EAAE,KAAK,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC7E,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAW,KAAK,QAAQ,EAAE,KAAK,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC5E,OAAO,EAAyB,KAAK,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAGlF;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,cAAc,GACtB,KAAK,GACL;IACE,gFAAgF;IAChF,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC;;;;OAIG;IACH,SAAS,CAAC,EAAE,CAAC,CAAC,EAAE,gBAAgB,KAAK,gBAAgB,CAAC;CACvD,CAAC;AAEN;;;;;;GAMG;AACH,MAAM,WAAW,eAAgB,SAAQ,IAAI,CAAC,QAAQ,EAAE,UAAU,CAAC;IACjE,wFAAwF;IACxF,QAAQ,CAAC,EAAE,cAAc,CAAC;CAC3B;AAED;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,GAAG,CAAC;IAET;;;;;;OAMG;IACH,gBAAgB,CAAC,EAAE,QAAQ,CAAC;CAC7B;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,MAAM,WAAW,GAAG,QAAQ,CAAC,eAAe,EAAE,UAAU,CAAC,CAAC;AAIhE,cAAM,UAAW,YAAW,SAAS,CAAC,gBAAgB,CAAC;IACrD,KAAK,EAAE,OAAO,CAAC,eAAe,CAAC,CAAM;IAErC,KAAK,CAAC,KAAK,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,GAAG,gBAAgB;CAgBvD;AA2CD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,gBAAgB,IAAI,WAAW,CAE9C"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { FlowLogDestination, Vpc } from "aws-cdk-lib/aws-ec2";
|
|
2
|
+
import { Builder } from "@composurecdk/core";
|
|
3
|
+
import { createLogGroupBuilder } from "@composurecdk/logs";
|
|
4
|
+
import { VPC_DEFAULTS } from "./vpc-defaults.js";
|
|
5
|
+
const DEFAULT_FLOW_LOG_KEY = "DefaultFlowLog";
|
|
6
|
+
class VpcBuilder {
|
|
7
|
+
props = {};
|
|
8
|
+
build(scope, id) {
|
|
9
|
+
const { flowLogs: flowLogsConfig, ...vpcProps } = this.props;
|
|
10
|
+
const { flowLogsLogGroup, flowLogProps } = resolveFlowLogs(scope, id, flowLogsConfig);
|
|
11
|
+
const mergedProps = {
|
|
12
|
+
...VPC_DEFAULTS,
|
|
13
|
+
...flowLogProps,
|
|
14
|
+
...vpcProps,
|
|
15
|
+
};
|
|
16
|
+
return {
|
|
17
|
+
vpc: new Vpc(scope, id, mergedProps),
|
|
18
|
+
flowLogsLogGroup,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
function resolveFlowLogs(scope, id, cfg) {
|
|
23
|
+
if (cfg === false) {
|
|
24
|
+
return { flowLogProps: {} };
|
|
25
|
+
}
|
|
26
|
+
if (cfg?.destination !== undefined) {
|
|
27
|
+
if (cfg.configure !== undefined) {
|
|
28
|
+
throw new Error("flowLogs: 'configure' cannot be combined with 'destination' — " +
|
|
29
|
+
"the destination is user-managed and not built by this builder.");
|
|
30
|
+
}
|
|
31
|
+
return {
|
|
32
|
+
flowLogProps: {
|
|
33
|
+
flowLogs: { [DEFAULT_FLOW_LOG_KEY]: { destination: cfg.destination } },
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
let subBuilder = createLogGroupBuilder();
|
|
38
|
+
if (cfg?.configure) {
|
|
39
|
+
subBuilder = cfg.configure(subBuilder);
|
|
40
|
+
}
|
|
41
|
+
const flowLogsLogGroup = subBuilder.build(scope, `${id}FlowLogsLogGroup`).logGroup;
|
|
42
|
+
return {
|
|
43
|
+
flowLogsLogGroup,
|
|
44
|
+
flowLogProps: {
|
|
45
|
+
flowLogs: {
|
|
46
|
+
[DEFAULT_FLOW_LOG_KEY]: {
|
|
47
|
+
destination: FlowLogDestination.toCloudWatchLogs(flowLogsLogGroup),
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Creates a new {@link IVpcBuilder} for configuring an AWS VPC.
|
|
55
|
+
*
|
|
56
|
+
* This is the entry point for defining a VPC component. The returned builder
|
|
57
|
+
* exposes every {@link VpcBuilderProps} property as a fluent setter/getter
|
|
58
|
+
* and implements {@link Lifecycle} for use with {@link compose}.
|
|
59
|
+
*
|
|
60
|
+
* @returns A fluent builder for an AWS VPC.
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* ```ts
|
|
64
|
+
* const network = createVpcBuilder().maxAzs(3).natGateways(3);
|
|
65
|
+
*
|
|
66
|
+
* // Use standalone:
|
|
67
|
+
* const result = network.build(stack, "Network");
|
|
68
|
+
*
|
|
69
|
+
* // Or compose into a system:
|
|
70
|
+
* const system = compose(
|
|
71
|
+
* { network, server: createInstanceBuilder() },
|
|
72
|
+
* { network: [], server: ["network"] },
|
|
73
|
+
* );
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
76
|
+
export function createVpcBuilder() {
|
|
77
|
+
return Builder(VpcBuilder);
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=vpc-builder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vpc-builder.js","sourceRoot":"","sources":["../src/vpc-builder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,GAAG,EAAiB,MAAM,qBAAqB,CAAC;AAG7E,OAAO,EAAE,OAAO,EAAiC,MAAM,oBAAoB,CAAC;AAC5E,OAAO,EAAE,qBAAqB,EAAyB,MAAM,oBAAoB,CAAC;AAClF,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAmFjD,MAAM,oBAAoB,GAAG,gBAAgB,CAAC;AAE9C,MAAM,UAAU;IACd,KAAK,GAA6B,EAAE,CAAC;IAErC,KAAK,CAAC,KAAiB,EAAE,EAAU;QACjC,MAAM,EAAE,QAAQ,EAAE,cAAc,EAAE,GAAG,QAAQ,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC;QAE7D,MAAM,EAAE,gBAAgB,EAAE,YAAY,EAAE,GAAG,eAAe,CAAC,KAAK,EAAE,EAAE,EAAE,cAAc,CAAC,CAAC;QAEtF,MAAM,WAAW,GAAG;YAClB,GAAG,YAAY;YACf,GAAG,YAAY;YACf,GAAG,QAAQ;SACZ,CAAC;QAEF,OAAO;YACL,GAAG,EAAE,IAAI,GAAG,CAAC,KAAK,EAAE,EAAE,EAAE,WAAW,CAAC;YACpC,gBAAgB;SACjB,CAAC;IACJ,CAAC;CACF;AAED,SAAS,eAAe,CACtB,KAAiB,EACjB,EAAU,EACV,GAA+B;IAE/B,IAAI,GAAG,KAAK,KAAK,EAAE,CAAC;QAClB,OAAO,EAAE,YAAY,EAAE,EAAE,EAAE,CAAC;IAC9B,CAAC;IAED,IAAI,GAAG,EAAE,WAAW,KAAK,SAAS,EAAE,CAAC;QACnC,IAAI,GAAG,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;YAChC,MAAM,IAAI,KAAK,CACb,gEAAgE;gBAC9D,gEAAgE,CACnE,CAAC;QACJ,CAAC;QACD,OAAO;YACL,YAAY,EAAE;gBACZ,QAAQ,EAAE,EAAE,CAAC,oBAAoB,CAAC,EAAE,EAAE,WAAW,EAAE,GAAG,CAAC,WAAW,EAAE,EAAE;aACvE;SACF,CAAC;IACJ,CAAC;IAED,IAAI,UAAU,GAAG,qBAAqB,EAAE,CAAC;IACzC,IAAI,GAAG,EAAE,SAAS,EAAE,CAAC;QACnB,UAAU,GAAG,GAAG,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;IACzC,CAAC;IACD,MAAM,gBAAgB,GAAG,UAAU,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,EAAE,kBAAkB,CAAC,CAAC,QAAQ,CAAC;IAEnF,OAAO;QACL,gBAAgB;QAChB,YAAY,EAAE;YACZ,QAAQ,EAAE;gBACR,CAAC,oBAAoB,CAAC,EAAE;oBACtB,WAAW,EAAE,kBAAkB,CAAC,gBAAgB,CAAC,gBAAgB,CAAC;iBACnE;aACF;SACF;KACF,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,UAAU,gBAAgB;IAC9B,OAAO,OAAO,CAA8B,UAAU,CAAC,CAAC;AAC1D,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { VpcProps } from "aws-cdk-lib/aws-ec2";
|
|
2
|
+
/**
|
|
3
|
+
* Secure, cost-conscious defaults applied to every VPC built with
|
|
4
|
+
* {@link createVpcBuilder}. Each property can be individually overridden
|
|
5
|
+
* via the builder's fluent API.
|
|
6
|
+
*
|
|
7
|
+
* Subnet layout uses CDK defaults (one public + one private-with-egress
|
|
8
|
+
* subnet per AZ) — override `subnetConfiguration` for custom topologies.
|
|
9
|
+
*
|
|
10
|
+
* Flow logs are created separately by the builder (not via this defaults
|
|
11
|
+
* object) so the destination log group can be auto-managed with
|
|
12
|
+
* well-architected retention/removal policies.
|
|
13
|
+
*/
|
|
14
|
+
export declare const VPC_DEFAULTS: Partial<VpcProps>;
|
|
15
|
+
//# sourceMappingURL=vpc-defaults.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vpc-defaults.d.ts","sourceRoot":"","sources":["../src/vpc-defaults.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAEpD;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,YAAY,EAAE,OAAO,CAAC,QAAQ,CA6C1C,CAAC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Secure, cost-conscious defaults applied to every VPC built with
|
|
3
|
+
* {@link createVpcBuilder}. Each property can be individually overridden
|
|
4
|
+
* via the builder's fluent API.
|
|
5
|
+
*
|
|
6
|
+
* Subnet layout uses CDK defaults (one public + one private-with-egress
|
|
7
|
+
* subnet per AZ) — override `subnetConfiguration` for custom topologies.
|
|
8
|
+
*
|
|
9
|
+
* Flow logs are created separately by the builder (not via this defaults
|
|
10
|
+
* object) so the destination log group can be auto-managed with
|
|
11
|
+
* well-architected retention/removal policies.
|
|
12
|
+
*/
|
|
13
|
+
export const VPC_DEFAULTS = {
|
|
14
|
+
/**
|
|
15
|
+
* Two availability zones strike a balance between high availability
|
|
16
|
+
* and cost. Override to 3+ AZs for production workloads that need
|
|
17
|
+
* stricter HA guarantees.
|
|
18
|
+
* @see https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html
|
|
19
|
+
*/
|
|
20
|
+
maxAzs: 2,
|
|
21
|
+
/**
|
|
22
|
+
* Single NAT gateway is a cost-conscious default. Production HA
|
|
23
|
+
* workloads should override this to match `maxAzs` so a single-AZ
|
|
24
|
+
* NAT failure does not partition private-subnet egress.
|
|
25
|
+
* @see https://docs.aws.amazon.com/vpc/latest/userguide/vpc-nat-gateway.html
|
|
26
|
+
*/
|
|
27
|
+
natGateways: 1,
|
|
28
|
+
/**
|
|
29
|
+
* Required for internal DNS resolution for most AWS managed services
|
|
30
|
+
* (ALB, RDS, VPC endpoints). Default-on in AWS but set explicitly for
|
|
31
|
+
* safety across CDK feature-flag configurations.
|
|
32
|
+
* @see https://docs.aws.amazon.com/vpc/latest/userguide/vpc-dns.html
|
|
33
|
+
*/
|
|
34
|
+
enableDnsSupport: true,
|
|
35
|
+
/**
|
|
36
|
+
* Required alongside DNS support for instances to receive public DNS
|
|
37
|
+
* hostnames. Needed for most hostname-based TLS and service discovery
|
|
38
|
+
* scenarios.
|
|
39
|
+
* @see https://docs.aws.amazon.com/vpc/latest/userguide/vpc-dns.html
|
|
40
|
+
*/
|
|
41
|
+
enableDnsHostnames: true,
|
|
42
|
+
/**
|
|
43
|
+
* Strip all rules from the default security group. This prevents
|
|
44
|
+
* accidentally using the default SG (which allows all intra-SG
|
|
45
|
+
* traffic and no ingress) and forces explicit SG design — a
|
|
46
|
+
* foundational well-architected security practice.
|
|
47
|
+
*
|
|
48
|
+
* Also enabled by the `@aws-cdk/aws-ec2:restrictDefaultSecurityGroup`
|
|
49
|
+
* feature flag; we set it explicitly so the guarantee holds regardless
|
|
50
|
+
* of CDK context configuration.
|
|
51
|
+
* @see https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.Vpc.html#restrictdefaultsecuritygroup
|
|
52
|
+
*/
|
|
53
|
+
restrictDefaultSecurityGroup: true,
|
|
54
|
+
};
|
|
55
|
+
//# sourceMappingURL=vpc-defaults.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vpc-defaults.js","sourceRoot":"","sources":["../src/vpc-defaults.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,YAAY,GAAsB;IAC7C;;;;;OAKG;IACH,MAAM,EAAE,CAAC;IAET;;;;;OAKG;IACH,WAAW,EAAE,CAAC;IAEd;;;;;OAKG;IACH,gBAAgB,EAAE,IAAI;IAEtB;;;;;OAKG;IACH,kBAAkB,EAAE,IAAI;IAExB;;;;;;;;;;OAUG;IACH,4BAA4B,EAAE,IAAI;CACnC,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@composurecdk/ec2",
|
|
3
|
+
"version": "0.5.0",
|
|
4
|
+
"description": "Composable EC2 instance and VPC builders with well-architected defaults",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "https://github.com/laazyj/composureCDK",
|
|
8
|
+
"directory": "packages/ec2"
|
|
9
|
+
},
|
|
10
|
+
"main": "./dist/index.js",
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"import": "./dist/index.js",
|
|
15
|
+
"types": "./dist/index.d.ts"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"dist",
|
|
20
|
+
"README.md",
|
|
21
|
+
"LICENSE"
|
|
22
|
+
],
|
|
23
|
+
"scripts": {
|
|
24
|
+
"clean": "rm -rf dist",
|
|
25
|
+
"build": "tsc -p tsconfig.build.json",
|
|
26
|
+
"typecheck": "tsc --noEmit",
|
|
27
|
+
"test": "vitest run --passWithNoTests",
|
|
28
|
+
"test:watch": "vitest"
|
|
29
|
+
},
|
|
30
|
+
"keywords": [],
|
|
31
|
+
"author": "Jason Duffett (https://github.com/laazyj)",
|
|
32
|
+
"license": "MIT",
|
|
33
|
+
"publishConfig": {
|
|
34
|
+
"access": "public"
|
|
35
|
+
},
|
|
36
|
+
"type": "module",
|
|
37
|
+
"peerDependencies": {
|
|
38
|
+
"@composurecdk/cloudwatch": "^0.5.0",
|
|
39
|
+
"@composurecdk/core": "^0.5.0",
|
|
40
|
+
"@composurecdk/logs": "^0.5.0",
|
|
41
|
+
"aws-cdk-lib": "^2.0.0",
|
|
42
|
+
"constructs": "^10.0.0"
|
|
43
|
+
},
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"@types/node": "^25.5.0",
|
|
46
|
+
"aws-cdk-lib": "^2.245.0",
|
|
47
|
+
"constructs": "^10.6.0",
|
|
48
|
+
"typescript": "^6.0.2",
|
|
49
|
+
"vitest": "^4.1.2"
|
|
50
|
+
}
|
|
51
|
+
}
|