@intentius/chant-lexicon-aws 0.18.12 → 0.18.13
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/dist/composites/agentcore-agent.d.ts +74 -0
- package/dist/composites/agentcore-agent.d.ts.map +1 -0
- package/dist/composites/agentcore-trust-policy.d.ts +11 -0
- package/dist/composites/agentcore-trust-policy.d.ts.map +1 -0
- package/dist/composites/index.d.ts +4 -0
- package/dist/composites/index.d.ts.map +1 -1
- package/dist/composites/microvm-app.d.ts +116 -0
- package/dist/composites/microvm-app.d.ts.map +1 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/integrity.json +22 -4
- package/dist/lint/audit-catalog.d.ts.map +1 -1
- package/dist/lint/post-synth/cf-refs.d.ts +14 -0
- package/dist/lint/post-synth/cf-refs.d.ts.map +1 -1
- package/dist/lint/post-synth/index.d.ts.map +1 -1
- package/dist/lint/post-synth/waw038.d.ts +12 -0
- package/dist/lint/post-synth/waw038.d.ts.map +1 -0
- package/dist/lint/post-synth/waw039.d.ts +11 -0
- package/dist/lint/post-synth/waw039.d.ts.map +1 -0
- package/dist/lint/post-synth/waw040.d.ts +13 -0
- package/dist/lint/post-synth/waw040.d.ts.map +1 -0
- package/dist/lint/post-synth/waw041.d.ts +10 -0
- package/dist/lint/post-synth/waw041.d.ts.map +1 -0
- package/dist/lint/post-synth/waw042.d.ts +12 -0
- package/dist/lint/post-synth/waw042.d.ts.map +1 -0
- package/dist/lint/post-synth/waw043.d.ts +11 -0
- package/dist/lint/post-synth/waw043.d.ts.map +1 -0
- package/dist/lint/post-synth/waw044.d.ts +18 -0
- package/dist/lint/post-synth/waw044.d.ts.map +1 -0
- package/dist/lint/post-synth/waw045.d.ts +11 -0
- package/dist/lint/post-synth/waw045.d.ts.map +1 -0
- package/dist/lint/post-synth/waw046.d.ts +12 -0
- package/dist/lint/post-synth/waw046.d.ts.map +1 -0
- package/dist/lint/post-synth/waw047.d.ts +11 -0
- package/dist/lint/post-synth/waw047.d.ts.map +1 -0
- package/dist/lint/post-synth/waw048.d.ts +11 -0
- package/dist/lint/post-synth/waw048.d.ts.map +1 -0
- package/dist/lint/post-synth/waw049.d.ts +21 -0
- package/dist/lint/post-synth/waw049.d.ts.map +1 -0
- package/dist/lint/post-synth/waw050.d.ts +11 -0
- package/dist/lint/post-synth/waw050.d.ts.map +1 -0
- package/dist/lint/post-synth/waw051.d.ts +11 -0
- package/dist/lint/post-synth/waw051.d.ts.map +1 -0
- package/dist/lint/post-synth/waw052.d.ts +12 -0
- package/dist/lint/post-synth/waw052.d.ts.map +1 -0
- package/dist/lint/post-synth/waw053.d.ts +10 -0
- package/dist/lint/post-synth/waw053.d.ts.map +1 -0
- package/dist/lint/post-synth/waw054.d.ts +11 -0
- package/dist/lint/post-synth/waw054.d.ts.map +1 -0
- package/dist/lint/post-synth/waw055.d.ts +11 -0
- package/dist/lint/post-synth/waw055.d.ts.map +1 -0
- package/dist/manifest.json +1 -1
- package/dist/op/activities/floci.d.ts +6 -0
- package/dist/op/activities/floci.d.ts.map +1 -1
- package/dist/plugin.d.ts.map +1 -1
- package/dist/rules/cf-refs.ts +23 -0
- package/dist/rules/waw038.ts +50 -0
- package/dist/rules/waw039.ts +51 -0
- package/dist/rules/waw040.ts +54 -0
- package/dist/rules/waw041.ts +48 -0
- package/dist/rules/waw042.ts +87 -0
- package/dist/rules/waw043.ts +57 -0
- package/dist/rules/waw044.ts +68 -0
- package/dist/rules/waw045.ts +58 -0
- package/dist/rules/waw046.ts +59 -0
- package/dist/rules/waw047.ts +50 -0
- package/dist/rules/waw048.ts +47 -0
- package/dist/rules/waw049.ts +100 -0
- package/dist/rules/waw050.ts +54 -0
- package/dist/rules/waw051.ts +49 -0
- package/dist/rules/waw052.ts +51 -0
- package/dist/rules/waw053.ts +53 -0
- package/dist/rules/waw054.ts +49 -0
- package/dist/rules/waw055.ts +49 -0
- package/dist/types/index.d.ts +11 -9
- package/package.json +2 -2
- package/src/composites/agentcore-agent.test.ts +188 -0
- package/src/composites/agentcore-agent.ts +195 -0
- package/src/composites/agentcore-trust-policy.ts +13 -0
- package/src/composites/index.ts +4 -0
- package/src/composites/microvm-app.test.ts +234 -0
- package/src/composites/microvm-app.ts +436 -0
- package/src/generated/index.d.ts +11 -9
- package/src/index.ts +2 -0
- package/src/lint/audit-catalog.ts +20 -0
- package/src/lint/post-synth/cf-refs.ts +23 -0
- package/src/lint/post-synth/index.ts +36 -0
- package/src/lint/post-synth/waw038.test.ts +78 -0
- package/src/lint/post-synth/waw038.ts +50 -0
- package/src/lint/post-synth/waw039.test.ts +72 -0
- package/src/lint/post-synth/waw039.ts +51 -0
- package/src/lint/post-synth/waw040.test.ts +71 -0
- package/src/lint/post-synth/waw040.ts +54 -0
- package/src/lint/post-synth/waw041.test.ts +72 -0
- package/src/lint/post-synth/waw041.ts +48 -0
- package/src/lint/post-synth/waw042.test.ts +138 -0
- package/src/lint/post-synth/waw042.ts +87 -0
- package/src/lint/post-synth/waw043.test.ts +84 -0
- package/src/lint/post-synth/waw043.ts +57 -0
- package/src/lint/post-synth/waw044.test.ts +112 -0
- package/src/lint/post-synth/waw044.ts +68 -0
- package/src/lint/post-synth/waw045.test.ts +101 -0
- package/src/lint/post-synth/waw045.ts +58 -0
- package/src/lint/post-synth/waw046.test.ts +112 -0
- package/src/lint/post-synth/waw046.ts +59 -0
- package/src/lint/post-synth/waw047.test.ts +64 -0
- package/src/lint/post-synth/waw047.ts +50 -0
- package/src/lint/post-synth/waw048.test.ts +77 -0
- package/src/lint/post-synth/waw048.ts +47 -0
- package/src/lint/post-synth/waw049.test.ts +139 -0
- package/src/lint/post-synth/waw049.ts +100 -0
- package/src/lint/post-synth/waw050.test.ts +75 -0
- package/src/lint/post-synth/waw050.ts +54 -0
- package/src/lint/post-synth/waw051.test.ts +78 -0
- package/src/lint/post-synth/waw051.ts +49 -0
- package/src/lint/post-synth/waw052.test.ts +54 -0
- package/src/lint/post-synth/waw052.ts +51 -0
- package/src/lint/post-synth/waw053.test.ts +59 -0
- package/src/lint/post-synth/waw053.ts +53 -0
- package/src/lint/post-synth/waw054.test.ts +49 -0
- package/src/lint/post-synth/waw054.ts +49 -0
- package/src/lint/post-synth/waw055.test.ts +43 -0
- package/src/lint/post-synth/waw055.ts +49 -0
- package/src/op/activities/floci.test.ts +26 -0
- package/src/op/activities/floci.ts +25 -9
- package/src/plugin.ts +3 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WAW051: Cognito Implicit OAuth Grant Allowed
|
|
3
|
+
*
|
|
4
|
+
* Flags UserPoolClients whose AllowedOAuthFlows include the deprecated
|
|
5
|
+
* "implicit" grant — it returns tokens directly in the redirect URL (exposed
|
|
6
|
+
* in browser history/referrer headers) instead of via a code exchange.
|
|
7
|
+
*/
|
|
8
|
+
import type { PostSynthCheck, PostSynthContext, PostSynthDiagnostic } from "@intentius/chant/lint/post-synth";
|
|
9
|
+
export declare function checkCognitoImplicitGrant(ctx: PostSynthContext): PostSynthDiagnostic[];
|
|
10
|
+
export declare const waw051: PostSynthCheck;
|
|
11
|
+
//# sourceMappingURL=waw051.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"waw051.d.ts","sourceRoot":"","sources":["../../../src/lint/post-synth/waw051.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AAG9G,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,gBAAgB,GAAG,mBAAmB,EAAE,CA4BtF;AAED,eAAO,MAAM,MAAM,EAAE,cAOpB,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WAW052: Cognito MFA Not Required (full tier)
|
|
3
|
+
*
|
|
4
|
+
* Flags UserPools without MfaConfiguration: ON. Tier-aware (#894), same
|
|
5
|
+
* seam as WAW040: a relaxed "light" stack (local/Floci, or no --env/
|
|
6
|
+
* ownership.env set) only warns; the strict "full"/production tier
|
|
7
|
+
* (ctx.env === "prod"/"production"/"full") fails the build.
|
|
8
|
+
*/
|
|
9
|
+
import type { PostSynthCheck, PostSynthContext, PostSynthDiagnostic } from "@intentius/chant/lint/post-synth";
|
|
10
|
+
export declare function checkCognitoMfaRequired(ctx: PostSynthContext): PostSynthDiagnostic[];
|
|
11
|
+
export declare const waw052: PostSynthCheck;
|
|
12
|
+
//# sourceMappingURL=waw052.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"waw052.d.ts","sourceRoot":"","sources":["../../../src/lint/post-synth/waw052.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AAG9G,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,gBAAgB,GAAG,mBAAmB,EAAE,CA6BpF;AAED,eAAO,MAAM,MAAM,EAAE,cAOpB,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WAW053: ECR Image Scanning Disabled
|
|
3
|
+
*
|
|
4
|
+
* Flags ECR repositories without ImageScanningConfiguration.ScanOnPush: true
|
|
5
|
+
* — pushed images aren't scanned for known CVEs.
|
|
6
|
+
*/
|
|
7
|
+
import type { PostSynthCheck, PostSynthContext, PostSynthDiagnostic } from "@intentius/chant/lint/post-synth";
|
|
8
|
+
export declare function checkEcrScanOnPush(ctx: PostSynthContext): PostSynthDiagnostic[];
|
|
9
|
+
export declare const waw053: PostSynthCheck;
|
|
10
|
+
//# sourceMappingURL=waw053.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"waw053.d.ts","sourceRoot":"","sources":["../../../src/lint/post-synth/waw053.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AAG9G,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,gBAAgB,GAAG,mBAAmB,EAAE,CAiC/E;AAED,eAAO,MAAM,MAAM,EAAE,cAOpB,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WAW054: ECR Tag Mutability Not Immutable
|
|
3
|
+
*
|
|
4
|
+
* Flags ECR repositories without ImageTagMutability: IMMUTABLE — mutable tags
|
|
5
|
+
* let a previously deployed/scanned/signed tag (e.g. "prod") silently point at
|
|
6
|
+
* different image content later.
|
|
7
|
+
*/
|
|
8
|
+
import type { PostSynthCheck, PostSynthContext, PostSynthDiagnostic } from "@intentius/chant/lint/post-synth";
|
|
9
|
+
export declare function checkEcrTagImmutability(ctx: PostSynthContext): PostSynthDiagnostic[];
|
|
10
|
+
export declare const waw054: PostSynthCheck;
|
|
11
|
+
//# sourceMappingURL=waw054.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"waw054.d.ts","sourceRoot":"","sources":["../../../src/lint/post-synth/waw054.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AAG9G,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,gBAAgB,GAAG,mBAAmB,EAAE,CA4BpF;AAED,eAAO,MAAM,MAAM,EAAE,cAOpB,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WAW055: CloudWatch Logs Retention Not Set
|
|
3
|
+
*
|
|
4
|
+
* Flags Logs::LogGroup resources without RetentionInDays — an unset
|
|
5
|
+
* retention means "Never expire," which is rarely the intended cost/
|
|
6
|
+
* compliance posture.
|
|
7
|
+
*/
|
|
8
|
+
import type { PostSynthCheck, PostSynthContext, PostSynthDiagnostic } from "@intentius/chant/lint/post-synth";
|
|
9
|
+
export declare function checkLogsRetention(ctx: PostSynthContext): PostSynthDiagnostic[];
|
|
10
|
+
export declare const waw055: PostSynthCheck;
|
|
11
|
+
//# sourceMappingURL=waw055.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"waw055.d.ts","sourceRoot":"","sources":["../../../src/lint/post-synth/waw055.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AAG9G,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,gBAAgB,GAAG,mBAAmB,EAAE,CA4B/E;AAED,eAAO,MAAM,MAAM,EAAE,cAOpB,CAAC"}
|
package/dist/manifest.json
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type EmulatorSpec, type EmulatorCapability } from "@intentius/chant/op";
|
|
1
2
|
export interface FlociUpArgs {
|
|
2
3
|
/** Container name. Default: `chant-floci`. */
|
|
3
4
|
name?: string;
|
|
@@ -24,6 +25,11 @@ export interface FlociDownArgs {
|
|
|
24
25
|
export declare function isFlociReady(healthBody: string, service: string): boolean;
|
|
25
26
|
/** The AWS env vars that point the `aws` CLI / SDK at a local Floci endpoint. */
|
|
26
27
|
export declare function flociEnv(port: number, region: string): Record<string, string>;
|
|
28
|
+
/** The Floci emulator spec — the aws plugin's `emulator` capability (#920). */
|
|
29
|
+
export declare const FLOCI_SPEC: EmulatorSpec;
|
|
30
|
+
/** The aws plugin's emulator capability (#920): Floci + the AWS env that points
|
|
31
|
+
* the SDK / `chant graph --live` / a triggered Op at it. */
|
|
32
|
+
export declare const FLOCI_EMULATOR: EmulatorCapability;
|
|
27
33
|
export declare const flociExistsCommand: (name: string) => string;
|
|
28
34
|
export declare const flociRmCommand: (name: string) => string;
|
|
29
35
|
export declare const flociHealthUrl: (port: number) => string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"floci.d.ts","sourceRoot":"","sources":["../../../src/op/activities/floci.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"floci.d.ts","sourceRoot":"","sources":["../../../src/op/activities/floci.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,YAAY,EAAE,KAAK,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AASpG,MAAM,WAAW,WAAW;IAC1B,8CAA8C;IAC9C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,mEAAmE;IACnE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,kDAAkD;IAClD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+FAA+F;IAC/F,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,wEAAwE;IACxE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,+EAA+E;IAC/E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iDAAiD;IACjD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mDAAmD;IACnD,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,aAAa;IAC5B,wDAAwD;IACxD,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,wFAAwF;AACxF,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAEzE;AAED,iFAAiF;AACjF,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAO7E;AAaD,+EAA+E;AAC/E,eAAO,MAAM,UAAU,EAAE,YAAkD,CAAC;AAE5E;4DAC4D;AAC5D,eAAO,MAAM,cAAc,EAAE,kBAQ5B,CAAC;AAMF,eAAO,MAAM,kBAAkB,0BAAyB,CAAC;AACzD,eAAO,MAAM,cAAc,0BAAqB,CAAC;AACjD,eAAO,MAAM,cAAc,0BAAqB,CAAC;AAEjD,uDAAuD;AACvD,wBAAgB,eAAe,CAAC,IAAI,GAAE,WAAgB,GAAG,MAAM,CAO9D;AAED;;;;;;;;GAQG;AACH,wBAAsB,OAAO,CAAC,IAAI,GAAE,WAAgB,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAgBzG;AAED,kFAAkF;AAClF,wBAAsB,SAAS,CAAC,IAAI,GAAE,aAAkB,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAE7F"}
|
package/dist/plugin.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAuF,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAuF,MAAM,0BAA0B,CAAC;AAuBnJ;;;;;GAKG;AACH,eAAO,MAAM,SAAS,EAAE,aA0qBvB,CAAC"}
|
package/dist/rules/cf-refs.ts
CHANGED
|
@@ -124,6 +124,29 @@ export function getSecurityGroupIngress(
|
|
|
124
124
|
return rules;
|
|
125
125
|
}
|
|
126
126
|
|
|
127
|
+
/**
|
|
128
|
+
* Extract an ECS TaskDefinition's container definitions (shared by the
|
|
129
|
+
* WAW046/047/048 ECS checks).
|
|
130
|
+
*/
|
|
131
|
+
export function getContainerDefinitions(resource: CFResource): Array<Record<string, unknown>> {
|
|
132
|
+
const props = resource.Properties ?? {};
|
|
133
|
+
const defs = props.ContainerDefinitions;
|
|
134
|
+
if (!Array.isArray(defs)) return [];
|
|
135
|
+
return defs.filter((d): d is Record<string, unknown> => typeof d === "object" && d !== null);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Whether a build's `env` (from `--env` or the project's `ownership.env`, see
|
|
140
|
+
* PostSynthContext#env and #201) should be treated as the strict "full"/
|
|
141
|
+
* production tier for tier-gated checks, vs a relaxed "light" tier acceptable
|
|
142
|
+
* for local/Floci-style stacks. Reuses the existing `ctx.env` seam — no new
|
|
143
|
+
* tier field. An undefined or unrecognized env is treated as non-strict so a
|
|
144
|
+
* project that never sets `--env`/`ownership.env` isn't unexpectedly hard-failed.
|
|
145
|
+
*/
|
|
146
|
+
export function isFullTierEnv(env: string | undefined): boolean {
|
|
147
|
+
return env === "prod" || env === "production" || env === "full";
|
|
148
|
+
}
|
|
149
|
+
|
|
127
150
|
/**
|
|
128
151
|
* Check if a port range [fromPort, toPort] contains any of the sensitive ports.
|
|
129
152
|
*/
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WAW038: RDS Publicly Accessible
|
|
3
|
+
*
|
|
4
|
+
* Flags RDS instances with PubliclyAccessible: true — the instance gets a
|
|
5
|
+
* public IP/DNS name reachable from the internet instead of staying inside
|
|
6
|
+
* the VPC. (DBCluster has no PubliclyAccessible property; that's set on the
|
|
7
|
+
* member DBInstance.)
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type { PostSynthCheck, PostSynthContext, PostSynthDiagnostic } from "@intentius/chant/lint/post-synth";
|
|
11
|
+
import { parseCFTemplate, isIntrinsic } from "./cf-refs";
|
|
12
|
+
|
|
13
|
+
export function checkRdsPubliclyAccessible(ctx: PostSynthContext): PostSynthDiagnostic[] {
|
|
14
|
+
const diagnostics: PostSynthDiagnostic[] = [];
|
|
15
|
+
|
|
16
|
+
for (const [_lexicon, output] of ctx.outputs) {
|
|
17
|
+
const template = parseCFTemplate(output);
|
|
18
|
+
if (!template?.Resources) continue;
|
|
19
|
+
|
|
20
|
+
for (const [logicalId, resource] of Object.entries(template.Resources)) {
|
|
21
|
+
if (resource.Type !== "AWS::RDS::DBInstance") continue;
|
|
22
|
+
|
|
23
|
+
const props = resource.Properties ?? {};
|
|
24
|
+
const publiclyAccessible = props.PubliclyAccessible;
|
|
25
|
+
|
|
26
|
+
if (isIntrinsic(publiclyAccessible)) continue;
|
|
27
|
+
|
|
28
|
+
if (publiclyAccessible === true) {
|
|
29
|
+
diagnostics.push({
|
|
30
|
+
checkId: "WAW038",
|
|
31
|
+
severity: "error",
|
|
32
|
+
message: `RDS instance "${logicalId}" has PubliclyAccessible: true — keep the database inside the VPC, unreachable from the internet`,
|
|
33
|
+
entity: logicalId,
|
|
34
|
+
lexicon: "aws",
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return diagnostics;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export const waw038: PostSynthCheck = {
|
|
44
|
+
id: "WAW038",
|
|
45
|
+
description: "RDS instance is publicly accessible — keep databases inside the VPC",
|
|
46
|
+
|
|
47
|
+
check(ctx: PostSynthContext): PostSynthDiagnostic[] {
|
|
48
|
+
return checkRdsPubliclyAccessible(ctx);
|
|
49
|
+
},
|
|
50
|
+
};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WAW039: RDS Backup Retention Not Set
|
|
3
|
+
*
|
|
4
|
+
* Flags RDS instances and clusters without a positive BackupRetentionPeriod —
|
|
5
|
+
* a retention of 0 (or an unset property on a resource that otherwise pins
|
|
6
|
+
* every other property explicitly) disables automated backups entirely.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type { PostSynthCheck, PostSynthContext, PostSynthDiagnostic } from "@intentius/chant/lint/post-synth";
|
|
10
|
+
import { parseCFTemplate, isIntrinsic } from "./cf-refs";
|
|
11
|
+
|
|
12
|
+
const RDS_TYPES = new Set(["AWS::RDS::DBInstance", "AWS::RDS::DBCluster"]);
|
|
13
|
+
|
|
14
|
+
export function checkRdsBackupRetention(ctx: PostSynthContext): PostSynthDiagnostic[] {
|
|
15
|
+
const diagnostics: PostSynthDiagnostic[] = [];
|
|
16
|
+
|
|
17
|
+
for (const [_lexicon, output] of ctx.outputs) {
|
|
18
|
+
const template = parseCFTemplate(output);
|
|
19
|
+
if (!template?.Resources) continue;
|
|
20
|
+
|
|
21
|
+
for (const [logicalId, resource] of Object.entries(template.Resources)) {
|
|
22
|
+
if (!RDS_TYPES.has(resource.Type)) continue;
|
|
23
|
+
|
|
24
|
+
const props = resource.Properties ?? {};
|
|
25
|
+
const retention = props.BackupRetentionPeriod;
|
|
26
|
+
|
|
27
|
+
if (isIntrinsic(retention)) continue;
|
|
28
|
+
|
|
29
|
+
if (retention === undefined || retention === 0) {
|
|
30
|
+
diagnostics.push({
|
|
31
|
+
checkId: "WAW039",
|
|
32
|
+
severity: "error",
|
|
33
|
+
message: `RDS resource "${logicalId}" (${resource.Type}) does not have a positive BackupRetentionPeriod — automated backups are disabled`,
|
|
34
|
+
entity: logicalId,
|
|
35
|
+
lexicon: "aws",
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return diagnostics;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export const waw039: PostSynthCheck = {
|
|
45
|
+
id: "WAW039",
|
|
46
|
+
description: "RDS instance or cluster has automated backups disabled — set a positive BackupRetentionPeriod",
|
|
47
|
+
|
|
48
|
+
check(ctx: PostSynthContext): PostSynthDiagnostic[] {
|
|
49
|
+
return checkRdsBackupRetention(ctx);
|
|
50
|
+
},
|
|
51
|
+
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WAW040: RDS Deletion Protection Disabled (full tier)
|
|
3
|
+
*
|
|
4
|
+
* Flags RDS instances and clusters without DeletionProtection: true. Tier-aware
|
|
5
|
+
* (#894): a relaxed "light" stack (local/Floci, or no --env/ownership.env set)
|
|
6
|
+
* only warns, since local/dev databases are routinely torn down on purpose; the
|
|
7
|
+
* strict "full"/production tier (ctx.env === "prod"/"production"/"full", the
|
|
8
|
+
* existing #201 env seam — see isFullTierEnv) fails the build.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import type { PostSynthCheck, PostSynthContext, PostSynthDiagnostic } from "@intentius/chant/lint/post-synth";
|
|
12
|
+
import { parseCFTemplate, isIntrinsic, isFullTierEnv } from "./cf-refs";
|
|
13
|
+
|
|
14
|
+
const RDS_TYPES = new Set(["AWS::RDS::DBInstance", "AWS::RDS::DBCluster"]);
|
|
15
|
+
|
|
16
|
+
export function checkRdsDeletionProtection(ctx: PostSynthContext): PostSynthDiagnostic[] {
|
|
17
|
+
const diagnostics: PostSynthDiagnostic[] = [];
|
|
18
|
+
const severity = isFullTierEnv(ctx.env) ? "error" : "warning";
|
|
19
|
+
|
|
20
|
+
for (const [_lexicon, output] of ctx.outputs) {
|
|
21
|
+
const template = parseCFTemplate(output);
|
|
22
|
+
if (!template?.Resources) continue;
|
|
23
|
+
|
|
24
|
+
for (const [logicalId, resource] of Object.entries(template.Resources)) {
|
|
25
|
+
if (!RDS_TYPES.has(resource.Type)) continue;
|
|
26
|
+
|
|
27
|
+
const props = resource.Properties ?? {};
|
|
28
|
+
const deletionProtection = props.DeletionProtection;
|
|
29
|
+
|
|
30
|
+
if (isIntrinsic(deletionProtection)) continue;
|
|
31
|
+
|
|
32
|
+
if (deletionProtection !== true) {
|
|
33
|
+
diagnostics.push({
|
|
34
|
+
checkId: "WAW040",
|
|
35
|
+
severity,
|
|
36
|
+
message: `RDS resource "${logicalId}" (${resource.Type}) does not have DeletionProtection: true — enable it on the full/production tier`,
|
|
37
|
+
entity: logicalId,
|
|
38
|
+
lexicon: "aws",
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return diagnostics;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export const waw040: PostSynthCheck = {
|
|
48
|
+
id: "WAW040",
|
|
49
|
+
description: "RDS instance or cluster does not have DeletionProtection enabled (full tier)",
|
|
50
|
+
|
|
51
|
+
check(ctx: PostSynthContext): PostSynthDiagnostic[] {
|
|
52
|
+
return checkRdsDeletionProtection(ctx);
|
|
53
|
+
},
|
|
54
|
+
};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WAW041: RDS Proxy TLS Not Required
|
|
3
|
+
*
|
|
4
|
+
* Flags RDS Proxy resources without RequireTLS: true — without it, a client
|
|
5
|
+
* can connect to the proxy over plaintext.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { PostSynthCheck, PostSynthContext, PostSynthDiagnostic } from "@intentius/chant/lint/post-synth";
|
|
9
|
+
import { parseCFTemplate, isIntrinsic } from "./cf-refs";
|
|
10
|
+
|
|
11
|
+
export function checkDbProxyTls(ctx: PostSynthContext): PostSynthDiagnostic[] {
|
|
12
|
+
const diagnostics: PostSynthDiagnostic[] = [];
|
|
13
|
+
|
|
14
|
+
for (const [_lexicon, output] of ctx.outputs) {
|
|
15
|
+
const template = parseCFTemplate(output);
|
|
16
|
+
if (!template?.Resources) continue;
|
|
17
|
+
|
|
18
|
+
for (const [logicalId, resource] of Object.entries(template.Resources)) {
|
|
19
|
+
if (resource.Type !== "AWS::RDS::DBProxy") continue;
|
|
20
|
+
|
|
21
|
+
const props = resource.Properties ?? {};
|
|
22
|
+
const requireTls = props.RequireTLS;
|
|
23
|
+
|
|
24
|
+
if (isIntrinsic(requireTls)) continue;
|
|
25
|
+
|
|
26
|
+
if (requireTls !== true) {
|
|
27
|
+
diagnostics.push({
|
|
28
|
+
checkId: "WAW041",
|
|
29
|
+
severity: "error",
|
|
30
|
+
message: `RDS Proxy "${logicalId}" does not have RequireTLS: true — clients can connect over plaintext`,
|
|
31
|
+
entity: logicalId,
|
|
32
|
+
lexicon: "aws",
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return diagnostics;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export const waw041: PostSynthCheck = {
|
|
42
|
+
id: "WAW041",
|
|
43
|
+
description: "RDS Proxy does not require TLS for client connections",
|
|
44
|
+
|
|
45
|
+
check(ctx: PostSynthContext): PostSynthDiagnostic[] {
|
|
46
|
+
return checkDbProxyTls(ctx);
|
|
47
|
+
},
|
|
48
|
+
};
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WAW042: S3 Bucket Missing TLS-Only Policy
|
|
3
|
+
*
|
|
4
|
+
* Flags S3 buckets without a companion BucketPolicy that denies requests made
|
|
5
|
+
* over plaintext (a Deny statement keyed on `aws:SecureTransport` being
|
|
6
|
+
* false). Encryption at rest is WAW006; the public-access block is WAW018;
|
|
7
|
+
* this covers encryption in transit.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type { PostSynthCheck, PostSynthContext, PostSynthDiagnostic } from "@intentius/chant/lint/post-synth";
|
|
11
|
+
import { parseCFTemplate, findResourceRefs, type CFResource } from "./cf-refs";
|
|
12
|
+
|
|
13
|
+
function statementDeniesInsecureTransport(stmt: Record<string, unknown>): boolean {
|
|
14
|
+
if (stmt.Effect !== "Deny") return false;
|
|
15
|
+
|
|
16
|
+
const condition = stmt.Condition;
|
|
17
|
+
if (typeof condition !== "object" || condition === null) return false;
|
|
18
|
+
|
|
19
|
+
const cond = condition as Record<string, unknown>;
|
|
20
|
+
for (const operator of ["Bool", "NumericLessThan"]) {
|
|
21
|
+
const clause = cond[operator];
|
|
22
|
+
if (typeof clause !== "object" || clause === null) continue;
|
|
23
|
+
const value = (clause as Record<string, unknown>)["aws:SecureTransport"];
|
|
24
|
+
if (value === "false" || value === false) return true;
|
|
25
|
+
}
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** Logical ids of every bucket a BucketPolicy's `Bucket` property resolves to. */
|
|
30
|
+
function bucketPolicyTargets(resource: CFResource): Set<string> {
|
|
31
|
+
const props = resource.Properties ?? {};
|
|
32
|
+
return findResourceRefs(props.Bucket);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function checkS3TlsOnlyPolicy(ctx: PostSynthContext): PostSynthDiagnostic[] {
|
|
36
|
+
const diagnostics: PostSynthDiagnostic[] = [];
|
|
37
|
+
|
|
38
|
+
for (const [_lexicon, output] of ctx.outputs) {
|
|
39
|
+
const template = parseCFTemplate(output);
|
|
40
|
+
if (!template?.Resources) continue;
|
|
41
|
+
|
|
42
|
+
const bucketsWithTlsPolicy = new Set<string>();
|
|
43
|
+
|
|
44
|
+
for (const resource of Object.values(template.Resources)) {
|
|
45
|
+
if (resource.Type !== "AWS::S3::BucketPolicy") continue;
|
|
46
|
+
|
|
47
|
+
const props = resource.Properties ?? {};
|
|
48
|
+
const policyDoc = props.PolicyDocument;
|
|
49
|
+
if (typeof policyDoc !== "object" || policyDoc === null) continue;
|
|
50
|
+
const statements = (policyDoc as Record<string, unknown>).Statement;
|
|
51
|
+
if (!Array.isArray(statements)) continue;
|
|
52
|
+
|
|
53
|
+
const hasTlsDeny = statements.some(
|
|
54
|
+
(stmt) => typeof stmt === "object" && stmt !== null && statementDeniesInsecureTransport(stmt as Record<string, unknown>),
|
|
55
|
+
);
|
|
56
|
+
if (!hasTlsDeny) continue;
|
|
57
|
+
|
|
58
|
+
for (const bucketId of bucketPolicyTargets(resource)) {
|
|
59
|
+
bucketsWithTlsPolicy.add(bucketId);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
for (const [logicalId, resource] of Object.entries(template.Resources)) {
|
|
64
|
+
if (resource.Type !== "AWS::S3::Bucket") continue;
|
|
65
|
+
if (bucketsWithTlsPolicy.has(logicalId)) continue;
|
|
66
|
+
|
|
67
|
+
diagnostics.push({
|
|
68
|
+
checkId: "WAW042",
|
|
69
|
+
severity: "error",
|
|
70
|
+
message: `S3 bucket "${logicalId}" has no bucket policy denying non-TLS requests — add a Deny statement on aws:SecureTransport = false`,
|
|
71
|
+
entity: logicalId,
|
|
72
|
+
lexicon: "aws",
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return diagnostics;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export const waw042: PostSynthCheck = {
|
|
81
|
+
id: "WAW042",
|
|
82
|
+
description: "S3 bucket missing a TLS-only bucket policy — deny requests over plaintext",
|
|
83
|
+
|
|
84
|
+
check(ctx: PostSynthContext): PostSynthDiagnostic[] {
|
|
85
|
+
return checkS3TlsOnlyPolicy(ctx);
|
|
86
|
+
},
|
|
87
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WAW043: KMS Key Rotation Disabled
|
|
3
|
+
*
|
|
4
|
+
* Flags customer-managed KMS keys without EnableKeyRotation: true. Skips
|
|
5
|
+
* asymmetric/HMAC keys (a non-default KeySpec) — AWS does not support
|
|
6
|
+
* automatic rotation for those.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type { PostSynthCheck, PostSynthContext, PostSynthDiagnostic } from "@intentius/chant/lint/post-synth";
|
|
10
|
+
import { parseCFTemplate, isIntrinsic } from "./cf-refs";
|
|
11
|
+
|
|
12
|
+
function supportsRotation(props: Record<string, unknown>): boolean {
|
|
13
|
+
const keySpec = props.KeySpec;
|
|
14
|
+
if (keySpec === undefined) return true; // default is SYMMETRIC_DEFAULT
|
|
15
|
+
if (isIntrinsic(keySpec)) return false; // can't statically verify — don't guess
|
|
16
|
+
return keySpec === "SYMMETRIC_DEFAULT";
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function checkKmsKeyRotation(ctx: PostSynthContext): PostSynthDiagnostic[] {
|
|
20
|
+
const diagnostics: PostSynthDiagnostic[] = [];
|
|
21
|
+
|
|
22
|
+
for (const [_lexicon, output] of ctx.outputs) {
|
|
23
|
+
const template = parseCFTemplate(output);
|
|
24
|
+
if (!template?.Resources) continue;
|
|
25
|
+
|
|
26
|
+
for (const [logicalId, resource] of Object.entries(template.Resources)) {
|
|
27
|
+
if (resource.Type !== "AWS::KMS::Key") continue;
|
|
28
|
+
|
|
29
|
+
const props = resource.Properties ?? {};
|
|
30
|
+
if (!supportsRotation(props)) continue;
|
|
31
|
+
|
|
32
|
+
const rotation = props.EnableKeyRotation;
|
|
33
|
+
if (isIntrinsic(rotation)) continue;
|
|
34
|
+
|
|
35
|
+
if (rotation !== true) {
|
|
36
|
+
diagnostics.push({
|
|
37
|
+
checkId: "WAW043",
|
|
38
|
+
severity: "warning",
|
|
39
|
+
message: `KMS key "${logicalId}" does not have EnableKeyRotation: true — enable automatic annual key rotation`,
|
|
40
|
+
entity: logicalId,
|
|
41
|
+
lexicon: "aws",
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return diagnostics;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export const waw043: PostSynthCheck = {
|
|
51
|
+
id: "WAW043",
|
|
52
|
+
description: "KMS customer-managed key does not have automatic key rotation enabled",
|
|
53
|
+
|
|
54
|
+
check(ctx: PostSynthContext): PostSynthDiagnostic[] {
|
|
55
|
+
return checkKmsKeyRotation(ctx);
|
|
56
|
+
},
|
|
57
|
+
};
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WAW044: ALB HTTP Listener Not Redirecting To HTTPS (full tier)
|
|
3
|
+
*
|
|
4
|
+
* Flags load balancer Listener resources on Protocol: HTTP whose
|
|
5
|
+
* DefaultActions don't redirect to HTTPS — the listener serves plaintext
|
|
6
|
+
* traffic instead of upgrading it. Access logging is WAW024; this covers
|
|
7
|
+
* transport security on the listener itself.
|
|
8
|
+
*
|
|
9
|
+
* Tier-aware (#917), same seam as WAW040/WAW052 (#894): a relaxed "light"
|
|
10
|
+
* stack (local/Floci, or no --env/ownership.env set) only warns, since the
|
|
11
|
+
* light tier is intentionally HTTP-only with no ACM cert to redirect to; the
|
|
12
|
+
* strict "full"/production tier (ctx.env === "prod"/"production"/"full", the
|
|
13
|
+
* existing #201 env seam — see isFullTierEnv) fails the build.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import type { PostSynthCheck, PostSynthContext, PostSynthDiagnostic } from "@intentius/chant/lint/post-synth";
|
|
17
|
+
import { parseCFTemplate, isIntrinsic, isFullTierEnv } from "./cf-refs";
|
|
18
|
+
|
|
19
|
+
function redirectsToHttps(actions: unknown): boolean {
|
|
20
|
+
if (!Array.isArray(actions)) return false;
|
|
21
|
+
return actions.some((action) => {
|
|
22
|
+
if (typeof action !== "object" || action === null) return false;
|
|
23
|
+
const a = action as Record<string, unknown>;
|
|
24
|
+
if (a.Type !== "redirect") return false;
|
|
25
|
+
const redirectConfig = a.RedirectConfig;
|
|
26
|
+
if (typeof redirectConfig !== "object" || redirectConfig === null) return false;
|
|
27
|
+
return (redirectConfig as Record<string, unknown>).Protocol === "HTTPS";
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function checkAlbHttpRedirect(ctx: PostSynthContext): PostSynthDiagnostic[] {
|
|
32
|
+
const diagnostics: PostSynthDiagnostic[] = [];
|
|
33
|
+
const severity = isFullTierEnv(ctx.env) ? "error" : "warning";
|
|
34
|
+
|
|
35
|
+
for (const [_lexicon, output] of ctx.outputs) {
|
|
36
|
+
const template = parseCFTemplate(output);
|
|
37
|
+
if (!template?.Resources) continue;
|
|
38
|
+
|
|
39
|
+
for (const [logicalId, resource] of Object.entries(template.Resources)) {
|
|
40
|
+
if (resource.Type !== "AWS::ElasticLoadBalancingV2::Listener") continue;
|
|
41
|
+
|
|
42
|
+
const props = resource.Properties ?? {};
|
|
43
|
+
const protocol = props.Protocol;
|
|
44
|
+
if (isIntrinsic(protocol) || protocol !== "HTTP") continue;
|
|
45
|
+
|
|
46
|
+
if (!redirectsToHttps(props.DefaultActions)) {
|
|
47
|
+
diagnostics.push({
|
|
48
|
+
checkId: "WAW044",
|
|
49
|
+
severity,
|
|
50
|
+
message: `Listener "${logicalId}" is HTTP and does not redirect to HTTPS — add a redirect DefaultAction (Protocol: HTTPS) on the full/production tier`,
|
|
51
|
+
entity: logicalId,
|
|
52
|
+
lexicon: "aws",
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return diagnostics;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export const waw044: PostSynthCheck = {
|
|
62
|
+
id: "WAW044",
|
|
63
|
+
description: "ALB HTTP listener does not redirect to HTTPS (full tier)",
|
|
64
|
+
|
|
65
|
+
check(ctx: PostSynthContext): PostSynthDiagnostic[] {
|
|
66
|
+
return checkAlbHttpRedirect(ctx);
|
|
67
|
+
},
|
|
68
|
+
};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WAW045: ALB Weak Or Missing TLS Policy
|
|
3
|
+
*
|
|
4
|
+
* Flags HTTPS/TLS listeners without a modern SslPolicy (TLS 1.2+). The
|
|
5
|
+
* account-wide default (`ELBSecurityPolicy-2016-08`) still allows TLS 1.0, so
|
|
6
|
+
* a missing SslPolicy is flagged the same as an explicit legacy one.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type { PostSynthCheck, PostSynthContext, PostSynthDiagnostic } from "@intentius/chant/lint/post-synth";
|
|
10
|
+
import { parseCFTemplate, isIntrinsic } from "./cf-refs";
|
|
11
|
+
|
|
12
|
+
const SECURE_PROTOCOLS = new Set(["HTTPS", "TLS"]);
|
|
13
|
+
|
|
14
|
+
/** AWS's predefined TLS 1.2+ policies all carry a "-1-2-" or "-1-3-" segment (FS/TLS13 variants included). */
|
|
15
|
+
function isModernTlsPolicy(policy: string): boolean {
|
|
16
|
+
return /-1-2-|-1-3-/.test(policy);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function checkAlbTlsPolicy(ctx: PostSynthContext): PostSynthDiagnostic[] {
|
|
20
|
+
const diagnostics: PostSynthDiagnostic[] = [];
|
|
21
|
+
|
|
22
|
+
for (const [_lexicon, output] of ctx.outputs) {
|
|
23
|
+
const template = parseCFTemplate(output);
|
|
24
|
+
if (!template?.Resources) continue;
|
|
25
|
+
|
|
26
|
+
for (const [logicalId, resource] of Object.entries(template.Resources)) {
|
|
27
|
+
if (resource.Type !== "AWS::ElasticLoadBalancingV2::Listener") continue;
|
|
28
|
+
|
|
29
|
+
const props = resource.Properties ?? {};
|
|
30
|
+
const protocol = props.Protocol;
|
|
31
|
+
if (isIntrinsic(protocol) || typeof protocol !== "string" || !SECURE_PROTOCOLS.has(protocol)) continue;
|
|
32
|
+
|
|
33
|
+
const sslPolicy = props.SslPolicy;
|
|
34
|
+
if (isIntrinsic(sslPolicy)) continue;
|
|
35
|
+
|
|
36
|
+
if (typeof sslPolicy !== "string" || !isModernTlsPolicy(sslPolicy)) {
|
|
37
|
+
diagnostics.push({
|
|
38
|
+
checkId: "WAW045",
|
|
39
|
+
severity: "error",
|
|
40
|
+
message: `Listener "${logicalId}" (${protocol}) ${sslPolicy ? `uses SslPolicy "${sslPolicy}"` : "has no SslPolicy set"} — use a TLS 1.2+ predefined policy (e.g. ELBSecurityPolicy-TLS13-1-2-2021-06)`,
|
|
41
|
+
entity: logicalId,
|
|
42
|
+
lexicon: "aws",
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return diagnostics;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export const waw045: PostSynthCheck = {
|
|
52
|
+
id: "WAW045",
|
|
53
|
+
description: "ALB HTTPS/TLS listener does not use a modern (TLS 1.2+) SslPolicy",
|
|
54
|
+
|
|
55
|
+
check(ctx: PostSynthContext): PostSynthDiagnostic[] {
|
|
56
|
+
return checkAlbTlsPolicy(ctx);
|
|
57
|
+
},
|
|
58
|
+
};
|