@infoxchange/make-it-so 2.18.0 → 2.19.0-internal-testing-add-tag-setup-4d301bb.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +114 -0
- package/dist/deployConfig.d.ts +4 -0
- package/dist/deployConfig.d.ts.map +1 -1
- package/dist/deployConfig.js +3 -0
- package/dist/lib/tags/ConditionalTags.d.ts +11 -0
- package/dist/lib/tags/ConditionalTags.d.ts.map +1 -0
- package/dist/lib/tags/ConditionalTags.js +12 -0
- package/dist/lib/tags/index.d.ts +3 -0
- package/dist/lib/tags/index.d.ts.map +1 -0
- package/dist/lib/tags/index.js +2 -0
- package/dist/lib/tags/setupTags.d.ts +18 -0
- package/dist/lib/tags/setupTags.d.ts.map +1 -0
- package/dist/lib/tags/setupTags.js +33 -0
- package/package.json +3 -2
- package/src/deployConfig.ts +3 -0
- package/src/lib/tags/ConditionalTags.ts +16 -0
- package/src/lib/tags/index.ts +2 -0
- package/src/lib/tags/setupTags.ts +55 -0
package/README.md
CHANGED
|
@@ -57,6 +57,55 @@ console.log(getDeployConfig());
|
|
|
57
57
|
| smtpHost | SMTP host for the app to use | string | string |
|
|
58
58
|
| smtpPort | SMTP port for the app to use | number | number \| undefined |
|
|
59
59
|
| clamAVUrl | ClamAV instance url for the app to use | string | string |
|
|
60
|
+
| vpcHttpProxy | HTTP proxy URL for the VPC | string | string |
|
|
61
|
+
| alarmSnsTopic | SNS topic ARN for CloudWatch alarms | string | string |
|
|
62
|
+
| tags | Tags to apply to AWS resources | Record<string, string> | Record<string, string> |
|
|
63
|
+
|
|
64
|
+
</details>
|
|
65
|
+
|
|
66
|
+
### setupTags
|
|
67
|
+
|
|
68
|
+
Automatically applies various AWS tags to CDK constructs in your stack and can be customized with your own tagging
|
|
69
|
+
logic. Default behaviour:
|
|
70
|
+
|
|
71
|
+
- Applies tags from `deployConfig.tags` to the root construct
|
|
72
|
+
- Adds `guardduty-suppress: true` tag to SST "live lambda" Functions (to prevent false positive GuardDuty alerts)
|
|
73
|
+
|
|
74
|
+
```typescript
|
|
75
|
+
import { setupTags } from "@infoxchange/make-it-so/lib/tags";
|
|
76
|
+
|
|
77
|
+
// Basic usage - automatically applies tags from deployConfig
|
|
78
|
+
setupTags(app);
|
|
79
|
+
|
|
80
|
+
// Advanced usage - customize tags based on construct properties
|
|
81
|
+
setupTags(app, {
|
|
82
|
+
modifyTags: ({ node, isLeafNode, isRootNode, currentTags }) => {
|
|
83
|
+
// Add custom tags for specific construct types
|
|
84
|
+
if (node instanceof IxNextjsSite) {
|
|
85
|
+
return [...currentTags, { key: "ResourceType", value: "NextjsSite" }];
|
|
86
|
+
}
|
|
87
|
+
return currentTags;
|
|
88
|
+
},
|
|
89
|
+
});
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
<details>
|
|
93
|
+
<summary><strong>Options</strong></summary>
|
|
94
|
+
|
|
95
|
+
| Prop | Type | Description |
|
|
96
|
+
| ------------------ | --------------------------------------------------------------- | ------------------------------------------------------------------------- |
|
|
97
|
+
| scope | IConstruct | The CDK construct to apply tags to (usually your app or stack) |
|
|
98
|
+
| options | SetupTagsOptions | (optional) Configuration options |
|
|
99
|
+
| options.modifyTags | (props: ModifyTagsProps) => Array<{key: string, value: string}> | (optional) Function to customize tags based on the construct being tagged |
|
|
100
|
+
|
|
101
|
+
#### ModifyTagsProps:
|
|
102
|
+
|
|
103
|
+
| Property | Type | Description |
|
|
104
|
+
| ----------- | ----------------------------------- | ---------------------------------------- |
|
|
105
|
+
| node | IConstruct | The current construct being tagged |
|
|
106
|
+
| isLeafNode | boolean | Whether this construct has no children |
|
|
107
|
+
| isRootNode | boolean | Whether this is the root scope construct |
|
|
108
|
+
| currentTags | Array<{key: string, value: string}> | The tags that have already been applied |
|
|
60
109
|
|
|
61
110
|
</details>
|
|
62
111
|
|
|
@@ -232,6 +281,71 @@ const domainCert = new IxCertificate(scope, "ExampleDotComCertificate", {
|
|
|
232
281
|
|
|
233
282
|
</details>
|
|
234
283
|
|
|
284
|
+
<details>
|
|
285
|
+
<summary><strong>IxCloudWatchAlarm</strong> - Creates a CloudWatch alarm with IX-specific defaults.</summary>
|
|
286
|
+
|
|
287
|
+
IxCloudWatchAlarm extends AWS CDK's CloudWatch Alarm functionality with IX-specific defaults and special handling for
|
|
288
|
+
CloudFront alarms (which must be created in us-east-1). If no actions are specified, the alarm will automatically use
|
|
289
|
+
the IX alarm SNS topic which sends alerts to MS Teams. Who is tagged in these alerts can be configured with the
|
|
290
|
+
`toNotify` property.
|
|
291
|
+
|
|
292
|
+
```typescript
|
|
293
|
+
import { IxCloudWatchAlarm } from "@infoxchange/make-it-so/cdk-constructs";
|
|
294
|
+
|
|
295
|
+
new IxCloudWatchAlarm(scope, "ApiErrorAlarm", {
|
|
296
|
+
alarmName: "high-error-rate",
|
|
297
|
+
alarmDescription: "Alert when API error rate is too high",
|
|
298
|
+
metric: {
|
|
299
|
+
namespace: "AWS/ApiGateway",
|
|
300
|
+
metricName: "5XXError",
|
|
301
|
+
dimensionsMap: {
|
|
302
|
+
ApiName: "my-api",
|
|
303
|
+
},
|
|
304
|
+
period: (Duration) => Duration.minutes(5),
|
|
305
|
+
statistic: (Stats) => Stats.AVERAGE,
|
|
306
|
+
},
|
|
307
|
+
threshold: 10,
|
|
308
|
+
evaluationPeriods: 2,
|
|
309
|
+
comparisonOperator: (ComparisonOperator) =>
|
|
310
|
+
ComparisonOperator.GREATER_THAN_THRESHOLD,
|
|
311
|
+
toNotify: ["Receiver Name", "Second Receiver"], // Receivers are defined in aws-gov under components/infra-event-notification
|
|
312
|
+
});
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
#### Options:
|
|
316
|
+
|
|
317
|
+
| Prop | Type | Description |
|
|
318
|
+
| -------------------------- | ------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
319
|
+
| metric | object | Metric configuration |
|
|
320
|
+
| metric.namespace | string | The namespace of the metric (e.g., "AWS/ApiGateway") |
|
|
321
|
+
| metric.metricName | string | The name of the metric |
|
|
322
|
+
| metric.dimensionsMap | Record<string, string> | (optional) Dimensions for the metric |
|
|
323
|
+
| metric.period | Duration \| ((Duration) => Duration) | (optional) The period over which the statistic is applied. Can be a function for easier access to CDK Duration helpers |
|
|
324
|
+
| metric.statistic | string \| ((Stats) => string) | (optional) The statistic to apply (e.g., "Average", "Sum"). Can be a function for easier access to CloudWatch.Stats helpers |
|
|
325
|
+
| comparisonOperator | ComparisonOperator \| ((ComparisonOperator) => ComparisonOperator) | How to compare the metric to the threshold. Can be a function for easier access to CloudWatch.ComparisonOperator helpers |
|
|
326
|
+
| threshold | number | The value to compare the metric against |
|
|
327
|
+
| evaluationPeriods | number | The number of periods over which data is compared to the threshold |
|
|
328
|
+
| treatMissingData | TreatMissingData \| ((TreatMissingData) => TreatMissingData) | (optional) How to treat missing data points. Can be a function for easier access to CloudWatch.TreatMissingData helpers |
|
|
329
|
+
| alarmName | string | (optional) Name of the alarm |
|
|
330
|
+
| alarmDescription | string | (optional) Description of the alarm |
|
|
331
|
+
| toNotify | string[] | (optional) List receivers to be notified on alarm state changes. Receivers are defined in aws-gov under components/infra-event-notification |
|
|
332
|
+
| actions | object | (optional) Actions to take when alarm state changes. If not provided, defaults to IX alarm SNS topic |
|
|
333
|
+
| actions.onOk | (string \| IAlarmAction)[] | (optional) Actions to take when alarm goes to OK state |
|
|
334
|
+
| actions.onAlarm | (string \| IAlarmAction)[] | (optional) Actions to take when alarm goes to ALARM state |
|
|
335
|
+
| actions.onInsufficientData | (string \| IAlarmAction)[] | (optional) Actions to take when alarm goes to INSUFFICIENT_DATA state |
|
|
336
|
+
| [...CloudWatch.AlarmProps] | | Any other props accepted by [CloudWatch.Alarm](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_cloudwatch.Alarm.html) |
|
|
337
|
+
|
|
338
|
+
#### Static Properties:
|
|
339
|
+
|
|
340
|
+
IxCloudWatchAlarm provides access to various CloudWatch constants:
|
|
341
|
+
|
|
342
|
+
- `IxCloudWatchAlarm.Stats` - CloudWatch.Stats for metric statistics
|
|
343
|
+
- `IxCloudWatchAlarm.Duration` - CDK.Duration for time periods
|
|
344
|
+
- `IxCloudWatchAlarm.TreatMissingData` - CloudWatch.TreatMissingData for handling missing data
|
|
345
|
+
- `IxCloudWatchAlarm.ComparisonOperator` - CloudWatch.ComparisonOperator for comparison operations
|
|
346
|
+
|
|
347
|
+
</details>
|
|
348
|
+
|
|
235
349
|
<details>
|
|
236
350
|
<summary><strong>IxDnsRecord</strong> - Creates a DNS record for a domain managed by IX.</summary>
|
|
237
351
|
|
package/dist/deployConfig.d.ts
CHANGED
|
@@ -16,6 +16,7 @@ declare const _default: {
|
|
|
16
16
|
clamAVUrl: string;
|
|
17
17
|
vpcHttpProxy: string;
|
|
18
18
|
alarmSnsTopic: string;
|
|
19
|
+
tags: Record<string, string>;
|
|
19
20
|
} | {
|
|
20
21
|
isIxDeploy: false;
|
|
21
22
|
appName: string;
|
|
@@ -32,6 +33,7 @@ declare const _default: {
|
|
|
32
33
|
clamAVUrl: string;
|
|
33
34
|
vpcHttpProxy: string;
|
|
34
35
|
alarmSnsTopic: string;
|
|
36
|
+
tags: Record<string, string>;
|
|
35
37
|
isInternalApp?: boolean | undefined;
|
|
36
38
|
smtpPort?: number | undefined;
|
|
37
39
|
};
|
|
@@ -54,6 +56,7 @@ export declare const getDeployConfig: () => {
|
|
|
54
56
|
clamAVUrl: string;
|
|
55
57
|
vpcHttpProxy: string;
|
|
56
58
|
alarmSnsTopic: string;
|
|
59
|
+
tags: Record<string, string>;
|
|
57
60
|
} | {
|
|
58
61
|
isIxDeploy: false;
|
|
59
62
|
appName: string;
|
|
@@ -70,6 +73,7 @@ export declare const getDeployConfig: () => {
|
|
|
70
73
|
clamAVUrl: string;
|
|
71
74
|
vpcHttpProxy: string;
|
|
72
75
|
alarmSnsTopic: string;
|
|
76
|
+
tags: Record<string, string>;
|
|
73
77
|
isInternalApp?: boolean | undefined;
|
|
74
78
|
smtpPort?: number | undefined;
|
|
75
79
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deployConfig.d.ts","sourceRoot":"","sources":["../src/deployConfig.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"deployConfig.d.ts","sourceRoot":"","sources":["../src/deployConfig.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyFA,wBAA0C;AAG1C,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAAmC,CAAC"}
|
package/dist/deployConfig.js
CHANGED
|
@@ -17,6 +17,7 @@ const getEnvVars = () => ({
|
|
|
17
17
|
clamAVUrl: process.env.CLAMAV_URL ?? "",
|
|
18
18
|
vpcHttpProxy: process.env.VPC_HTTP_PROXY ?? "",
|
|
19
19
|
alarmSnsTopic: process.env.IX_ALARM_SNS_TOPIC ?? "",
|
|
20
|
+
tags: JSON.parse(process.env.IX_TAGS ?? "{}"),
|
|
20
21
|
});
|
|
21
22
|
const ixDeployConfigSchema = z
|
|
22
23
|
.object({
|
|
@@ -41,6 +42,7 @@ const ixDeployConfigSchema = z
|
|
|
41
42
|
clamAVUrl: z.string().url(),
|
|
42
43
|
vpcHttpProxy: z.string().url(),
|
|
43
44
|
alarmSnsTopic: z.string().min(1),
|
|
45
|
+
tags: z.record(z.string(), z.string()),
|
|
44
46
|
})
|
|
45
47
|
.strip();
|
|
46
48
|
const nonIxDeployConfigSchema = z
|
|
@@ -70,6 +72,7 @@ const nonIxDeployConfigSchema = z
|
|
|
70
72
|
clamAVUrl: z.string(),
|
|
71
73
|
vpcHttpProxy: z.string(),
|
|
72
74
|
alarmSnsTopic: z.string(),
|
|
75
|
+
tags: z.record(z.string(), z.string()),
|
|
73
76
|
})
|
|
74
77
|
.strip();
|
|
75
78
|
const schema = z.discriminatedUnion("isIxDeploy", [
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { IAspect } from "aws-cdk-lib";
|
|
2
|
+
import { IConstruct } from "constructs";
|
|
3
|
+
export declare class ConditionalTags implements IAspect {
|
|
4
|
+
private getTags;
|
|
5
|
+
constructor(getTags: (node: IConstruct) => Array<{
|
|
6
|
+
key: string;
|
|
7
|
+
value: string;
|
|
8
|
+
}> | undefined | null);
|
|
9
|
+
visit(node: IConstruct): void;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=ConditionalTags.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConditionalTags.d.ts","sourceRoot":"","sources":["../../../src/lib/tags/ConditionalTags.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAQ,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAExC,qBAAa,eAAgB,YAAW,OAAO;IAE3C,OAAO,CAAC,OAAO;gBAAP,OAAO,EAAE,CACf,IAAI,EAAE,UAAU,KACb,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,GAAG,SAAS,GAAG,IAAI;IAG/D,KAAK,CAAC,IAAI,EAAE,UAAU;CAKvB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/tags/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { IConstruct } from "constructs";
|
|
2
|
+
export type ModifyTagsProps = {
|
|
3
|
+
node: IConstruct;
|
|
4
|
+
isLeafNode: boolean;
|
|
5
|
+
isRootNode: boolean;
|
|
6
|
+
currentTags: Array<{
|
|
7
|
+
key: string;
|
|
8
|
+
value: string;
|
|
9
|
+
}>;
|
|
10
|
+
};
|
|
11
|
+
export type SetupTagsOptions = {
|
|
12
|
+
modifyTags?: (props: ModifyTagsProps) => Array<{
|
|
13
|
+
key: string;
|
|
14
|
+
value: string;
|
|
15
|
+
}>;
|
|
16
|
+
};
|
|
17
|
+
export declare function setupTags(scope: IConstruct, { modifyTags }?: SetupTagsOptions): void;
|
|
18
|
+
//# sourceMappingURL=setupTags.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setupTags.d.ts","sourceRoot":"","sources":["../../../src/lib/tags/setupTags.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAKxC,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,UAAU,CAAC;IACjB,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,EAAE,OAAO,CAAC;IACpB,WAAW,EAAE,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACpD,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,UAAU,CAAC,EAAE,CACX,KAAK,EAAE,eAAe,KACnB,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC5C,CAAC;AAEF,wBAAgB,SAAS,CACvB,KAAK,EAAE,UAAU,EACjB,EAAE,UAAU,EAAE,GAAE,gBAAqB,QAiCtC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { Aspects } from "aws-cdk-lib";
|
|
2
|
+
import { Function } from "sst/constructs";
|
|
3
|
+
import { ConditionalTags } from "./ConditionalTags.js";
|
|
4
|
+
import deployConfig from "../../deployConfig.js";
|
|
5
|
+
export function setupTags(scope, { modifyTags } = {}) {
|
|
6
|
+
const conditionalTags = new ConditionalTags((node) => {
|
|
7
|
+
let tags = [];
|
|
8
|
+
const isLeafNode = node.node.children.length === 0;
|
|
9
|
+
const isRootNode = node === scope;
|
|
10
|
+
// Add tags from deploy config to all constructs
|
|
11
|
+
if (isRootNode) {
|
|
12
|
+
Object.entries(deployConfig.tags).forEach(([key, value]) => {
|
|
13
|
+
tags.push({ key, value });
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
// SST v2's live lambda feature means that the local machine that `sst dev` is run on may use AWS creds that were
|
|
17
|
+
// setup for a lambda. This triggers a false positive in GuardDuty, so we suppress that finding for any lambda that
|
|
18
|
+
// has live dev enabled.
|
|
19
|
+
if (node instanceof Function && node._isLiveDevEnabled) {
|
|
20
|
+
tags.push({ key: "guardduty-suppress", value: "true" });
|
|
21
|
+
}
|
|
22
|
+
tags = modifyTags
|
|
23
|
+
? modifyTags({
|
|
24
|
+
node,
|
|
25
|
+
isLeafNode,
|
|
26
|
+
isRootNode,
|
|
27
|
+
currentTags: tags,
|
|
28
|
+
})
|
|
29
|
+
: tags;
|
|
30
|
+
return tags;
|
|
31
|
+
});
|
|
32
|
+
Aspects.of(scope).add(conditionalTags);
|
|
33
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@infoxchange/make-it-so",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.19.0-internal-testing-add-tag-setup-4d301bb.1",
|
|
4
4
|
"description": "Makes deploying services to IX infra easy",
|
|
5
5
|
"repository": "github:infoxchange/make-it-so",
|
|
6
6
|
"publishConfig": {
|
|
@@ -21,7 +21,8 @@
|
|
|
21
21
|
"./cdk-constructs": "./dist/cdk-constructs/index.js",
|
|
22
22
|
"./deployConfig": "./dist/deployConfig.js",
|
|
23
23
|
"./auth": "./dist/lib/auth/index.js",
|
|
24
|
-
"./proxy": "./dist/lib/proxy/index.js"
|
|
24
|
+
"./proxy": "./dist/lib/proxy/index.js",
|
|
25
|
+
"./tags": "./dist/lib/tags/index.js"
|
|
25
26
|
},
|
|
26
27
|
"lint-staged": {
|
|
27
28
|
"**/*": [
|
package/src/deployConfig.ts
CHANGED
|
@@ -19,6 +19,7 @@ const getEnvVars = () =>
|
|
|
19
19
|
clamAVUrl: process.env.CLAMAV_URL ?? "",
|
|
20
20
|
vpcHttpProxy: process.env.VPC_HTTP_PROXY ?? "",
|
|
21
21
|
alarmSnsTopic: process.env.IX_ALARM_SNS_TOPIC ?? "",
|
|
22
|
+
tags: JSON.parse(process.env.IX_TAGS ?? "{}"),
|
|
22
23
|
}) satisfies Record<string, string | boolean>;
|
|
23
24
|
|
|
24
25
|
const ixDeployConfigSchema = z
|
|
@@ -44,6 +45,7 @@ const ixDeployConfigSchema = z
|
|
|
44
45
|
clamAVUrl: z.string().url(),
|
|
45
46
|
vpcHttpProxy: z.string().url(),
|
|
46
47
|
alarmSnsTopic: z.string().min(1),
|
|
48
|
+
tags: z.record(z.string(), z.string()),
|
|
47
49
|
} satisfies Record<keyof ReturnType<typeof getEnvVars>, unknown>)
|
|
48
50
|
.strip();
|
|
49
51
|
|
|
@@ -76,6 +78,7 @@ const nonIxDeployConfigSchema = z
|
|
|
76
78
|
clamAVUrl: z.string(),
|
|
77
79
|
vpcHttpProxy: z.string(),
|
|
78
80
|
alarmSnsTopic: z.string(),
|
|
81
|
+
tags: z.record(z.string(), z.string()),
|
|
79
82
|
} satisfies Record<keyof ReturnType<typeof getEnvVars>, unknown>)
|
|
80
83
|
.strip();
|
|
81
84
|
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { IAspect, Tags } from "aws-cdk-lib";
|
|
2
|
+
import { IConstruct } from "constructs";
|
|
3
|
+
|
|
4
|
+
export class ConditionalTags implements IAspect {
|
|
5
|
+
constructor(
|
|
6
|
+
private getTags: (
|
|
7
|
+
node: IConstruct,
|
|
8
|
+
) => Array<{ key: string; value: string }> | undefined | null,
|
|
9
|
+
) {}
|
|
10
|
+
|
|
11
|
+
visit(node: IConstruct) {
|
|
12
|
+
this.getTags(node)?.forEach(({ key, value }) => {
|
|
13
|
+
Tags.of(node).add(key, value);
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { Aspects } from "aws-cdk-lib";
|
|
2
|
+
import { IConstruct } from "constructs";
|
|
3
|
+
import { Function } from "sst/constructs";
|
|
4
|
+
import { ConditionalTags } from "./ConditionalTags.js";
|
|
5
|
+
import deployConfig from "../../deployConfig.js";
|
|
6
|
+
|
|
7
|
+
export type ModifyTagsProps = {
|
|
8
|
+
node: IConstruct;
|
|
9
|
+
isLeafNode: boolean;
|
|
10
|
+
isRootNode: boolean;
|
|
11
|
+
currentTags: Array<{ key: string; value: string }>;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export type SetupTagsOptions = {
|
|
15
|
+
modifyTags?: (
|
|
16
|
+
props: ModifyTagsProps,
|
|
17
|
+
) => Array<{ key: string; value: string }>;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export function setupTags(
|
|
21
|
+
scope: IConstruct,
|
|
22
|
+
{ modifyTags }: SetupTagsOptions = {},
|
|
23
|
+
) {
|
|
24
|
+
const conditionalTags = new ConditionalTags((node) => {
|
|
25
|
+
let tags = [];
|
|
26
|
+
const isLeafNode = node.node.children.length === 0;
|
|
27
|
+
const isRootNode = node === scope;
|
|
28
|
+
|
|
29
|
+
// Add tags from deploy config to all constructs
|
|
30
|
+
if (isRootNode) {
|
|
31
|
+
Object.entries(deployConfig.tags).forEach(([key, value]) => {
|
|
32
|
+
tags.push({ key, value });
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// SST v2's live lambda feature means that the local machine that `sst dev` is run on may use AWS creds that were
|
|
37
|
+
// setup for a lambda. This triggers a false positive in GuardDuty, so we suppress that finding for any lambda that
|
|
38
|
+
// has live dev enabled.
|
|
39
|
+
if (node instanceof Function && node._isLiveDevEnabled) {
|
|
40
|
+
tags.push({ key: "guardduty-suppress", value: "true" });
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
tags = modifyTags
|
|
44
|
+
? modifyTags({
|
|
45
|
+
node,
|
|
46
|
+
isLeafNode,
|
|
47
|
+
isRootNode,
|
|
48
|
+
currentTags: tags,
|
|
49
|
+
})
|
|
50
|
+
: tags;
|
|
51
|
+
return tags;
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
Aspects.of(scope).add(conditionalTags);
|
|
55
|
+
}
|