@intentius/chant-lexicon-aws 0.56.0 → 0.58.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/dist/agentcore/trace-fetch.d.ts +5 -4
- package/dist/agentcore/trace-fetch.d.ts.map +1 -1
- package/dist/condition.d.ts +27 -0
- package/dist/condition.d.ts.map +1 -0
- package/dist/generated/index.d.ts +1 -1
- package/dist/generated/index.d.ts.map +1 -1
- package/dist/import/generator.d.ts +19 -0
- package/dist/import/generator.d.ts.map +1 -1
- package/dist/import/parser.d.ts +19 -0
- package/dist/import/parser.d.ts.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/integrity.json +4 -3
- package/dist/intrinsics.d.ts +77 -3
- package/dist/intrinsics.d.ts.map +1 -1
- package/dist/lint/audit-catalog.d.ts.map +1 -1
- package/dist/lint/audit-lineage.d.ts +10 -0
- package/dist/lint/audit-lineage.d.ts.map +1 -0
- package/dist/lint/post-synth/index.d.ts.map +1 -1
- package/dist/lint/post-synth/waw069.d.ts +15 -0
- package/dist/lint/post-synth/waw069.d.ts.map +1 -0
- package/dist/manifest.json +29 -1
- package/dist/okf/index.md +1 -0
- package/dist/okf/rules/WAW069.md +11 -0
- package/dist/op/activities/aws-apply.d.ts.map +1 -1
- package/dist/op/activities/floci.d.ts +3 -2
- package/dist/op/activities/floci.d.ts.map +1 -1
- package/dist/op/builders.d.ts +4 -4
- package/dist/plugin.d.ts.map +1 -1
- package/dist/rules/waw069.ts +0 -0
- package/dist/serializer.d.ts.map +1 -1
- package/dist/types/index.d.ts +3 -3
- package/package.json +2 -2
- package/src/agentcore/trace-fetch.ts +5 -4
- package/src/codegen/docs.ts +3 -3
- package/src/codegen/generate-typescript.ts +3 -3
- package/src/codegen/generate.ts +1 -1
- package/src/condition.test.ts +129 -0
- package/src/condition.ts +40 -0
- package/src/deep-observe.test.ts +23 -15
- package/src/deep-topology.test.ts +7 -3
- package/src/generated/index.d.ts +3 -3
- package/src/generated/index.ts +1 -1
- package/src/import/generator.ts +131 -50
- package/src/import/parser.test.ts +96 -0
- package/src/import/parser.ts +86 -1
- package/src/import/roundtrip-fixtures.test.ts +50 -0
- package/src/index.ts +15 -3
- package/src/intrinsics.ts +130 -5
- package/src/lint/audit-catalog.ts +6 -1
- package/src/lint/audit-lineage.ts +159 -0
- package/src/lint/post-synth/index.ts +2 -0
- package/src/lint/post-synth/waw069.test.ts +94 -0
- package/src/lint/post-synth/waw069.ts +0 -0
- package/src/op/activities/aws-apply.ts +1 -3
- package/src/op/activities/floci.ts +3 -2
- package/src/op/builders.ts +4 -4
- package/src/plugin.test.ts +5 -1
- package/src/plugin.ts +4 -0
- package/src/serializer.ts +24 -3
- package/src/testdata/roundtrip/with-conditions.json +16 -0
package/src/import/parser.ts
CHANGED
|
@@ -3,6 +3,8 @@ import type {
|
|
|
3
3
|
TemplateIR,
|
|
4
4
|
ResourceIR,
|
|
5
5
|
ParameterIR,
|
|
6
|
+
ConditionIR,
|
|
7
|
+
OutputIR,
|
|
6
8
|
} from "@intentius/chant/import/parser";
|
|
7
9
|
import { BaseValueParser } from "@intentius/chant/import/base-parser";
|
|
8
10
|
import yaml from "js-yaml";
|
|
@@ -114,8 +116,19 @@ interface CFTemplate {
|
|
|
114
116
|
AWSTemplateFormatVersion?: string;
|
|
115
117
|
Description?: string;
|
|
116
118
|
Parameters?: Record<string, CFParameter>;
|
|
119
|
+
Conditions?: Record<string, unknown>;
|
|
117
120
|
Resources?: Record<string, CFResource>;
|
|
118
|
-
Outputs?: Record<string,
|
|
121
|
+
Outputs?: Record<string, CFOutput>;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* CloudFormation output
|
|
126
|
+
*/
|
|
127
|
+
interface CFOutput {
|
|
128
|
+
Value: unknown;
|
|
129
|
+
Description?: string;
|
|
130
|
+
Export?: { Name?: unknown };
|
|
131
|
+
Condition?: string;
|
|
119
132
|
}
|
|
120
133
|
|
|
121
134
|
/**
|
|
@@ -135,6 +148,7 @@ interface CFResource {
|
|
|
135
148
|
Properties?: Record<string, unknown>;
|
|
136
149
|
Metadata?: Record<string, unknown>;
|
|
137
150
|
DependsOn?: string | string[];
|
|
151
|
+
Condition?: string;
|
|
138
152
|
}
|
|
139
153
|
|
|
140
154
|
/**
|
|
@@ -156,11 +170,17 @@ export class CFParser extends BaseValueParser implements TemplateParser {
|
|
|
156
170
|
const template = parsed as CFTemplate;
|
|
157
171
|
|
|
158
172
|
const parameters = this.parseParameters(template.Parameters ?? {});
|
|
173
|
+
const conditions = this.parseConditions(template.Conditions ?? {});
|
|
159
174
|
const resources = this.parseResources(template.Resources ?? {});
|
|
175
|
+
const outputs = this.parseOutputs(template.Outputs ?? {});
|
|
176
|
+
const warnings = this.collectDroppedSectionWarnings(template as unknown as Record<string, unknown>);
|
|
160
177
|
|
|
161
178
|
return {
|
|
162
179
|
parameters,
|
|
180
|
+
conditions: conditions.length > 0 ? conditions : undefined,
|
|
163
181
|
resources,
|
|
182
|
+
outputs: outputs.length > 0 ? outputs : undefined,
|
|
183
|
+
warnings: warnings.length > 0 ? warnings : undefined,
|
|
164
184
|
metadata: {
|
|
165
185
|
version: template.AWSTemplateFormatVersion ?? "2010-09-09",
|
|
166
186
|
description: template.Description,
|
|
@@ -168,6 +188,64 @@ export class CFParser extends BaseValueParser implements TemplateParser {
|
|
|
168
188
|
};
|
|
169
189
|
}
|
|
170
190
|
|
|
191
|
+
/**
|
|
192
|
+
* Template sections import carries. Anything else is named in a warning
|
|
193
|
+
* rather than dropped silently (#2069).
|
|
194
|
+
*/
|
|
195
|
+
private static readonly CARRIED_SECTIONS = new Set([
|
|
196
|
+
"AWSTemplateFormatVersion",
|
|
197
|
+
"Description",
|
|
198
|
+
"Parameters",
|
|
199
|
+
"Conditions",
|
|
200
|
+
"Resources",
|
|
201
|
+
"Outputs",
|
|
202
|
+
]);
|
|
203
|
+
|
|
204
|
+
private collectDroppedSectionWarnings(template: Record<string, unknown>): string[] {
|
|
205
|
+
const warnings: string[] = [];
|
|
206
|
+
for (const key of Object.keys(template)) {
|
|
207
|
+
if (!CFParser.CARRIED_SECTIONS.has(key)) {
|
|
208
|
+
warnings.push(`Template section "${key}" is not carried by import — it is dropped from the generated source`);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
return warnings;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Parse the Conditions section (#2069). Inside a condition expression the
|
|
216
|
+
* single-key `{ "Condition": "<name>" }` form references another declared
|
|
217
|
+
* condition; `inConditionExpression` scopes that dispatch to this section
|
|
218
|
+
* so a resource property that happens to hold a single-key `Condition`
|
|
219
|
+
* object is left alone.
|
|
220
|
+
*/
|
|
221
|
+
private inConditionExpression = false;
|
|
222
|
+
|
|
223
|
+
private parseConditions(conditions: Record<string, unknown>): ConditionIR[] {
|
|
224
|
+
return Object.entries(conditions).map(([name, expression]) => {
|
|
225
|
+
this.inConditionExpression = true;
|
|
226
|
+
try {
|
|
227
|
+
return { name, expression: this.parseValue(expression) };
|
|
228
|
+
} finally {
|
|
229
|
+
this.inConditionExpression = false;
|
|
230
|
+
}
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Parse the Outputs section (#2069).
|
|
236
|
+
*/
|
|
237
|
+
private parseOutputs(outputs: Record<string, CFOutput>): OutputIR[] {
|
|
238
|
+
return Object.entries(outputs)
|
|
239
|
+
.filter(([_, output]) => typeof output === "object" && output !== null)
|
|
240
|
+
.map(([name, output]) => ({
|
|
241
|
+
name,
|
|
242
|
+
value: this.parseValue(output.Value),
|
|
243
|
+
description: output.Description,
|
|
244
|
+
exportName: output.Export?.Name !== undefined ? this.parseValue(output.Export.Name) : undefined,
|
|
245
|
+
condition: typeof output.Condition === "string" ? output.Condition : undefined,
|
|
246
|
+
}));
|
|
247
|
+
}
|
|
248
|
+
|
|
171
249
|
/**
|
|
172
250
|
* Parse parameters section
|
|
173
251
|
*/
|
|
@@ -192,6 +270,7 @@ export class CFParser extends BaseValueParser implements TemplateParser {
|
|
|
192
270
|
type: resource.Type,
|
|
193
271
|
properties: this.parseProperties(resource.Properties ?? {}),
|
|
194
272
|
metadata: resource.Metadata,
|
|
273
|
+
condition: typeof resource.Condition === "string" ? resource.Condition : undefined,
|
|
195
274
|
}));
|
|
196
275
|
}
|
|
197
276
|
|
|
@@ -212,6 +291,12 @@ export class CFParser extends BaseValueParser implements TemplateParser {
|
|
|
212
291
|
* CFN-specific intrinsic dispatch table.
|
|
213
292
|
*/
|
|
214
293
|
protected dispatchIntrinsic(key: string, value: unknown, _obj: Record<string, unknown>): unknown | null {
|
|
294
|
+
// `{ "Condition": "<name>" }` — only valid inside the Conditions section
|
|
295
|
+
// (#2069); see parseConditions for the scoping.
|
|
296
|
+
if (key === "Condition" && this.inConditionExpression && typeof value === "string") {
|
|
297
|
+
return { __intrinsic: "ConditionRef", name: value };
|
|
298
|
+
}
|
|
299
|
+
|
|
215
300
|
if (key === "Ref") {
|
|
216
301
|
return { __intrinsic: "Ref", name: value };
|
|
217
302
|
}
|
|
@@ -112,6 +112,56 @@ describe("parameters.json build roundtrip", () => {
|
|
|
112
112
|
});
|
|
113
113
|
});
|
|
114
114
|
|
|
115
|
+
describe("with-conditions.json build roundtrip (#2069)", () => {
|
|
116
|
+
test("Conditions, Condition keys, and the conditioned output round-trip exactly", async () => {
|
|
117
|
+
const content = readFileSync(join(roundtripDir, "with-conditions.json"), "utf-8");
|
|
118
|
+
const source = JSON.parse(content);
|
|
119
|
+
|
|
120
|
+
const ir = parser.parse(content);
|
|
121
|
+
const files = generator.generate(ir);
|
|
122
|
+
const mainFile = files.find((f) => f.path === "main.ts")!;
|
|
123
|
+
|
|
124
|
+
// The generated source declares both conditions and keeps the references
|
|
125
|
+
expect(mainFile.content).toContain("new Condition(Equals(Ref(Cutover), \"true\"))");
|
|
126
|
+
expect(mainFile.content).toContain("new Condition(Not(DoCutover))");
|
|
127
|
+
expect(mainFile.content).toContain("{ Condition: DoCutover }");
|
|
128
|
+
expect(mainFile.content).toContain("stackOutput(Ref(Rule), { condition: DoCutover })");
|
|
129
|
+
|
|
130
|
+
const dir = mkdtempSync(join(import.meta.dirname, "../../.roundtrip-tmp-"));
|
|
131
|
+
try {
|
|
132
|
+
const srcDir = join(dir, "src");
|
|
133
|
+
mkdirSync(srcDir);
|
|
134
|
+
writeFileSync(join(srcDir, "main.ts"), mainFile.content);
|
|
135
|
+
|
|
136
|
+
const result = await build(srcDir, [awsSerializer]);
|
|
137
|
+
expect(result.errors).toHaveLength(0);
|
|
138
|
+
|
|
139
|
+
const template = JSON.parse(result.outputs.get("aws") as string);
|
|
140
|
+
|
|
141
|
+
// The Conditions section round-trips exactly, {Condition: ...} ref included
|
|
142
|
+
expect(template.Conditions).toEqual(source.Conditions);
|
|
143
|
+
// The resource keeps its Condition key and its Fn::If
|
|
144
|
+
expect(template.Resources.Rule.Condition).toBe("DoCutover");
|
|
145
|
+
expect(template.Resources.Rule.Properties.LogGroupName).toEqual(
|
|
146
|
+
source.Resources.Rule.Properties.LogGroupName,
|
|
147
|
+
);
|
|
148
|
+
// The conditioned output round-trips exactly
|
|
149
|
+
expect(template.Outputs).toEqual(source.Outputs);
|
|
150
|
+
} finally {
|
|
151
|
+
rmSync(dir, { recursive: true, force: true });
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
test("a section import cannot carry is named in a warning, never dropped silently", () => {
|
|
156
|
+
const template = JSON.parse(readFileSync(join(roundtripDir, "with-conditions.json"), "utf-8"));
|
|
157
|
+
template.Mappings = { RegionMap: { "us-east-1": { AMI: "ami-123" } } };
|
|
158
|
+
const ir = parser.parse(JSON.stringify(template));
|
|
159
|
+
expect(ir.warnings).toEqual([
|
|
160
|
+
'Template section "Mappings" is not carried by import — it is dropped from the generated source',
|
|
161
|
+
]);
|
|
162
|
+
});
|
|
163
|
+
});
|
|
164
|
+
|
|
115
165
|
describe("SAM roundtrip fixtures", () => {
|
|
116
166
|
const fixtures = readdirSync(samDir).filter(
|
|
117
167
|
(f) => f.endsWith(".yaml") || f.endsWith(".yml"),
|
package/src/index.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
// Parameter
|
|
2
2
|
export { Parameter } from "./parameter";
|
|
3
3
|
|
|
4
|
+
// Condition (#2068) — the Conditions-section declarable
|
|
5
|
+
export { Condition, isCondition, CONDITION_ENTITY_TYPE } from "./condition";
|
|
6
|
+
|
|
4
7
|
// Default Tags
|
|
5
8
|
export { defaultTags, isDefaultTags, DEFAULT_TAGS_MARKER } from "./default-tags";
|
|
6
9
|
export type { DefaultTags, TagEntry } from "./default-tags";
|
|
@@ -25,9 +28,9 @@ export type { AwsReceiptStoreOptions, ReceiptRowObservation } from "./receipt-st
|
|
|
25
28
|
// Typed Op step-builder wrappers (chant #1288 Stage 2) — awsApply/awsDelete/
|
|
26
29
|
// flociUp/flociDown with authoring-time types derived from this lexicon's
|
|
27
30
|
// own *Args interfaces (see ./op/builders.ts's module doc for why these live
|
|
28
|
-
// here rather than in core
|
|
29
|
-
//
|
|
30
|
-
//
|
|
31
|
+
// here rather than in core). Opt-in: `@intentius/chant/op`'s same-named
|
|
32
|
+
// exports are core's original untyped builders, unchanged, for
|
|
33
|
+
// cloud-agnostic authoring.
|
|
31
34
|
export { awsApply, awsDelete, flociUp, flociDown } from "./op/builders";
|
|
32
35
|
|
|
33
36
|
// Serializer
|
|
@@ -105,6 +108,10 @@ export {
|
|
|
105
108
|
Split,
|
|
106
109
|
Base64,
|
|
107
110
|
GetAZs,
|
|
111
|
+
Equals,
|
|
112
|
+
And,
|
|
113
|
+
Or,
|
|
114
|
+
Not,
|
|
108
115
|
SubIntrinsic,
|
|
109
116
|
RefIntrinsic,
|
|
110
117
|
GetAttIntrinsic,
|
|
@@ -114,7 +121,12 @@ export {
|
|
|
114
121
|
SplitIntrinsic,
|
|
115
122
|
Base64Intrinsic,
|
|
116
123
|
GetAZsIntrinsic,
|
|
124
|
+
EqualsIntrinsic,
|
|
125
|
+
AndIntrinsic,
|
|
126
|
+
OrIntrinsic,
|
|
127
|
+
NotIntrinsic,
|
|
117
128
|
} from "./intrinsics";
|
|
129
|
+
export type { ConditionOperand } from "./intrinsics";
|
|
118
130
|
|
|
119
131
|
// Pseudo-parameters
|
|
120
132
|
export {
|
package/src/intrinsics.ts
CHANGED
|
@@ -2,6 +2,25 @@ import { INTRINSIC_MARKER, resolveIntrinsicValue, isIntrinsic, type Intrinsic }
|
|
|
2
2
|
import { buildInterpolatedString, defaultInterpolationSerializer } from "@intentius/chant/intrinsic-interpolation";
|
|
3
3
|
import { type Declarable } from "@intentius/chant/declarable";
|
|
4
4
|
import { getLogicalName } from "@intentius/chant/utils";
|
|
5
|
+
import { isCondition, type Condition } from "./condition";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* An operand allowed where CloudFormation expects a condition (#2068): a
|
|
9
|
+
* nested condition intrinsic (`Equals`/`And`/`Or`/`Not`), the `Condition`
|
|
10
|
+
* declarable itself, or a condition name string. The latter two both emit
|
|
11
|
+
* the `{ "Condition": "<name>" }` reference form.
|
|
12
|
+
*/
|
|
13
|
+
export type ConditionOperand = Intrinsic | Condition | string;
|
|
14
|
+
|
|
15
|
+
function resolveConditionOperand(operand: ConditionOperand): unknown {
|
|
16
|
+
if (typeof operand === "string") {
|
|
17
|
+
return { Condition: operand };
|
|
18
|
+
}
|
|
19
|
+
if (isCondition(operand)) {
|
|
20
|
+
return { Condition: getLogicalName(operand) };
|
|
21
|
+
}
|
|
22
|
+
return resolveIntrinsicValue(operand);
|
|
23
|
+
}
|
|
5
24
|
|
|
6
25
|
/**
|
|
7
26
|
* Fn::Sub intrinsic function implementation
|
|
@@ -99,29 +118,135 @@ export function GetAtt(logicalName: string, attribute: string): GetAttIntrinsic
|
|
|
99
118
|
*/
|
|
100
119
|
export class IfIntrinsic implements Intrinsic {
|
|
101
120
|
readonly [INTRINSIC_MARKER] = true as const;
|
|
102
|
-
private conditionName: string;
|
|
121
|
+
private conditionName: string | Condition;
|
|
103
122
|
private valueIfTrue: unknown;
|
|
104
123
|
private valueIfFalse: unknown;
|
|
105
124
|
|
|
106
|
-
constructor(conditionName: string, valueIfTrue: unknown, valueIfFalse: unknown) {
|
|
125
|
+
constructor(conditionName: string | Condition, valueIfTrue: unknown, valueIfFalse: unknown) {
|
|
107
126
|
this.conditionName = conditionName;
|
|
108
127
|
this.valueIfTrue = valueIfTrue;
|
|
109
128
|
this.valueIfFalse = valueIfFalse;
|
|
110
129
|
}
|
|
111
130
|
|
|
112
131
|
toJSON(): { "Fn::If": [string, unknown, unknown] } {
|
|
113
|
-
|
|
132
|
+
const name = typeof this.conditionName === "string" ? this.conditionName : getLogicalName(this.conditionName);
|
|
133
|
+
return { "Fn::If": [name, resolveIntrinsicValue(this.valueIfTrue), resolveIntrinsicValue(this.valueIfFalse)] };
|
|
114
134
|
}
|
|
115
135
|
}
|
|
116
136
|
|
|
117
137
|
|
|
118
138
|
/**
|
|
119
|
-
* Create an If intrinsic
|
|
139
|
+
* Create an If intrinsic. The condition is a name string, or the `Condition`
|
|
140
|
+
* declarable itself (resolved to its logical name at serialization, #2068).
|
|
120
141
|
*/
|
|
121
|
-
export function If(conditionName: string, valueIfTrue: unknown, valueIfFalse: unknown): IfIntrinsic {
|
|
142
|
+
export function If(conditionName: string | Condition, valueIfTrue: unknown, valueIfFalse: unknown): IfIntrinsic {
|
|
122
143
|
return new IfIntrinsic(conditionName, valueIfTrue, valueIfFalse);
|
|
123
144
|
}
|
|
124
145
|
|
|
146
|
+
/**
|
|
147
|
+
* Fn::Equals condition intrinsic (#2068).
|
|
148
|
+
* Compares two values; each may be a literal or a value intrinsic (Ref etc.).
|
|
149
|
+
*/
|
|
150
|
+
export class EqualsIntrinsic implements Intrinsic {
|
|
151
|
+
readonly [INTRINSIC_MARKER] = true as const;
|
|
152
|
+
private left: unknown;
|
|
153
|
+
private right: unknown;
|
|
154
|
+
|
|
155
|
+
constructor(left: unknown, right: unknown) {
|
|
156
|
+
this.left = left;
|
|
157
|
+
this.right = right;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
toJSON(): { "Fn::Equals": [unknown, unknown] } {
|
|
161
|
+
return { "Fn::Equals": [resolveIntrinsicValue(this.left), resolveIntrinsicValue(this.right)] };
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Create an Equals condition intrinsic: `Equals(Ref(cutover), "true")`.
|
|
167
|
+
*/
|
|
168
|
+
export function Equals(left: unknown, right: unknown): EqualsIntrinsic {
|
|
169
|
+
return new EqualsIntrinsic(left, right);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Fn::And condition intrinsic (#2068).
|
|
174
|
+
*/
|
|
175
|
+
export class AndIntrinsic implements Intrinsic {
|
|
176
|
+
readonly [INTRINSIC_MARKER] = true as const;
|
|
177
|
+
private conditions: ConditionOperand[];
|
|
178
|
+
|
|
179
|
+
constructor(conditions: ConditionOperand[]) {
|
|
180
|
+
this.conditions = conditions;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
toJSON(): { "Fn::And": unknown[] } {
|
|
184
|
+
return { "Fn::And": this.conditions.map(resolveConditionOperand) };
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Create an And condition intrinsic over 2–10 operands, each a nested
|
|
190
|
+
* condition intrinsic, a `Condition` declarable, or a condition name.
|
|
191
|
+
*/
|
|
192
|
+
export function And(...conditions: ConditionOperand[]): AndIntrinsic {
|
|
193
|
+
if (conditions.length < 2 || conditions.length > 10) {
|
|
194
|
+
throw new Error("And(...conditions): Fn::And takes between 2 and 10 conditions");
|
|
195
|
+
}
|
|
196
|
+
return new AndIntrinsic(conditions);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Fn::Or condition intrinsic (#2068).
|
|
201
|
+
*/
|
|
202
|
+
export class OrIntrinsic implements Intrinsic {
|
|
203
|
+
readonly [INTRINSIC_MARKER] = true as const;
|
|
204
|
+
private conditions: ConditionOperand[];
|
|
205
|
+
|
|
206
|
+
constructor(conditions: ConditionOperand[]) {
|
|
207
|
+
this.conditions = conditions;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
toJSON(): { "Fn::Or": unknown[] } {
|
|
211
|
+
return { "Fn::Or": this.conditions.map(resolveConditionOperand) };
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Create an Or condition intrinsic over 2–10 operands, each a nested
|
|
217
|
+
* condition intrinsic, a `Condition` declarable, or a condition name.
|
|
218
|
+
*/
|
|
219
|
+
export function Or(...conditions: ConditionOperand[]): OrIntrinsic {
|
|
220
|
+
if (conditions.length < 2 || conditions.length > 10) {
|
|
221
|
+
throw new Error("Or(...conditions): Fn::Or takes between 2 and 10 conditions");
|
|
222
|
+
}
|
|
223
|
+
return new OrIntrinsic(conditions);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Fn::Not condition intrinsic (#2068).
|
|
228
|
+
*/
|
|
229
|
+
export class NotIntrinsic implements Intrinsic {
|
|
230
|
+
readonly [INTRINSIC_MARKER] = true as const;
|
|
231
|
+
private condition: ConditionOperand;
|
|
232
|
+
|
|
233
|
+
constructor(condition: ConditionOperand) {
|
|
234
|
+
this.condition = condition;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
toJSON(): { "Fn::Not": [unknown] } {
|
|
238
|
+
return { "Fn::Not": [resolveConditionOperand(this.condition)] };
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Create a Not condition intrinsic over a nested condition intrinsic, a
|
|
244
|
+
* `Condition` declarable, or a condition name.
|
|
245
|
+
*/
|
|
246
|
+
export function Not(condition: ConditionOperand): NotIntrinsic {
|
|
247
|
+
return new NotIntrinsic(condition);
|
|
248
|
+
}
|
|
249
|
+
|
|
125
250
|
/**
|
|
126
251
|
* Fn::Join intrinsic function
|
|
127
252
|
* Joins values with a delimiter
|
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
* #350); core keeps only the generic catalog machinery + cross-cutting ids.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import { auditRule, type RuleMeta, type Authority } from "@intentius/chant/audit/catalog";
|
|
8
|
+
import { auditRule, type RuleMeta, type Authority, applyLineage } from "@intentius/chant/audit/catalog";
|
|
9
|
+
import { awsAuditLineage } from "./audit-lineage";
|
|
9
10
|
|
|
10
11
|
/** AWS Well-Architected Security Pillar — the authority chant cites for AWS security findings. */
|
|
11
12
|
const AWS_SEC: Authority = {
|
|
@@ -88,4 +89,8 @@ export const awsAuditCatalog: Record<string, RuleMeta> = {
|
|
|
88
89
|
WAW066: auditRule("WAW066", "merge-worthy", "guidance", "Private subnet's route table has no working default route", "Add a 0.0.0.0/0 route to a NAT gateway/Transit Gateway that exists in the template.", { category: "correctness" }),
|
|
89
90
|
WAW067: auditRule("WAW067", "report-only", "guidance", "Single-AZ NAT gateway serves multi-AZ private subnets", "Add one NAT gateway per Availability Zone and point each AZ's subnets at its own.", { category: "best-practice" }),
|
|
90
91
|
WAW068: auditRule("WAW068", "report-only", "guidance", "VPN Gateway or Transit Gateway has only one attached VPN Connection", "Attach a second VPNConnection (ideally to a separate Customer Gateway) for redundancy.", { category: "best-practice" }),
|
|
92
|
+
WAW069: auditRule("WAW069", "merge-worthy", "guidance", "Template references a condition it never declares", "Declare the condition in the Conditions section (new Condition(...)), or fix the referenced name.", { category: "correctness" }),
|
|
91
93
|
};
|
|
94
|
+
|
|
95
|
+
// Prior art credits live beside the rules in ./audit-lineage.ts (see core audit/prior-art.ts).
|
|
96
|
+
applyLineage(awsAuditCatalog, awsAuditLineage);
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Prior art for these audit rules: the open-source tools whose checks cover the
|
|
3
|
+
* same condition, credited per rule. See packages/core/src/audit/prior-art.ts for
|
|
4
|
+
* the registry, the relation vocabulary, and why this is credit rather than
|
|
5
|
+
* authority. Kept by hand; the prior-art sweep (scripts/prior-art-sweep.ts) reports
|
|
6
|
+
* when a credited tool's index no longer lists a rule cited here.
|
|
7
|
+
*/
|
|
8
|
+
import type { Lineage } from "@intentius/chant/audit/catalog";
|
|
9
|
+
|
|
10
|
+
export const awsAuditLineage: Record<string, Lineage[]> = {
|
|
11
|
+
WAW010: [
|
|
12
|
+
{ tool: "cfn-lint", rule: "W3005", url: "https://github.com/aws-cloudformation/cfn-lint/blob/main/docs/rules.md#W3005", relation: "equivalent" },
|
|
13
|
+
],
|
|
14
|
+
WAW011: [
|
|
15
|
+
{ tool: "cfn-lint", rule: "W2531", url: "https://github.com/aws-cloudformation/cfn-lint/blob/main/docs/rules.md#W2531", relation: "equivalent" },
|
|
16
|
+
{ tool: "checkov", rule: "CKV_AWS_363", url: "https://www.checkov.io/5.Policy%20Index/cloudformation.html", relation: "equivalent" },
|
|
17
|
+
],
|
|
18
|
+
WAW017: [
|
|
19
|
+
{ tool: "kics", rule: "Lambda Function Without Tags", url: "https://docs.kics.io/latest/queries/cloudformation-queries/aws/8df8e857-bd59-44fa-9f4c-d77594b95b46/", relation: "extends" },
|
|
20
|
+
{ tool: "kics", rule: "EFS Without Tags", url: "https://docs.kics.io/latest/queries/cloudformation-queries/aws/08e39832-5e42-4304-98a0-aa5b43393162/", relation: "extends" },
|
|
21
|
+
],
|
|
22
|
+
WAW018: [
|
|
23
|
+
{ tool: "guard-rules-registry", rule: "S3_BUCKET_LEVEL_PUBLIC_ACCESS_PROHIBITED", url: "https://github.com/aws-cloudformation/aws-guard-rules-registry/blob/main/rules/aws/amazon_s3/s3_bucket_level_public_access_prohibited.guard", relation: "equivalent" },
|
|
24
|
+
{ tool: "checkov", rule: "CKV_AWS_53", url: "https://www.checkov.io/5.Policy%20Index/cloudformation.html", relation: "extends" },
|
|
25
|
+
{ tool: "checkov", rule: "CKV_AWS_56", url: "https://www.checkov.io/5.Policy%20Index/cloudformation.html", relation: "extends" },
|
|
26
|
+
],
|
|
27
|
+
WAW019: [
|
|
28
|
+
{ tool: "guard-rules-registry", rule: "RESTRICTED_INCOMING_TRAFFIC", url: "https://github.com/aws-cloudformation/aws-guard-rules-registry/blob/main/rules/aws/amazon_ec2/restricted_common_ports.guard", relation: "overlaps" },
|
|
29
|
+
{ tool: "kics", rule: "EC2 Sensitive Port Is Publicly Exposed", url: "https://docs.kics.io/latest/queries/cloudformation-queries/aws/494b03d3-bf40-4464-8524-7c56ad0700ed/", relation: "overlaps" },
|
|
30
|
+
{ tool: "checkov", rule: "CKV_AWS_24", url: "https://www.checkov.io/5.Policy%20Index/cloudformation.html", relation: "extends" },
|
|
31
|
+
],
|
|
32
|
+
WAW020: [
|
|
33
|
+
{ tool: "checkov", rule: "CKV_AWS_63", url: "https://www.checkov.io/5.Policy%20Index/cloudformation.html", relation: "equivalent" },
|
|
34
|
+
{ tool: "cfn-nag", rule: "F4", url: "https://github.com/stelligent/cfn_nag/blob/master/lib/cfn-nag/custom_rules/IamPolicyWildcardActionRule.rb", relation: "overlaps" },
|
|
35
|
+
{ tool: "guard-rules-registry", rule: "IAM_ROLE_NO_WILDCARD_ACTIONS_ON_PERMISSIONS", url: "https://github.com/aws-cloudformation/aws-guard-rules-registry/blob/main/rules/aws/iam/iam_role_no_wildcard_actions_on_permissions.guard", relation: "overlaps" },
|
|
36
|
+
],
|
|
37
|
+
WAW021: [
|
|
38
|
+
{ tool: "cfn-nag", rule: "F27", url: "https://github.com/stelligent/cfn_nag/blob/master/lib/cfn-nag/custom_rules/RDSDBInstanceStorageEncryptedRule.rb", relation: "equivalent" },
|
|
39
|
+
{ tool: "checkov", rule: "CKV_AWS_16", url: "https://www.checkov.io/5.Policy%20Index/cloudformation.html", relation: "equivalent" },
|
|
40
|
+
{ tool: "guard-rules-registry", rule: "RDS_STORAGE_ENCRYPTED", url: "https://github.com/aws-cloudformation/aws-guard-rules-registry/blob/main/rules/aws/amazon_rds/rds_storage_encrypted.guard", relation: "equivalent" },
|
|
41
|
+
],
|
|
42
|
+
WAW022: [
|
|
43
|
+
{ tool: "cfn-nag", rule: "W89", url: "https://github.com/stelligent/cfn_nag/blob/master/lib/cfn-nag/custom_rules/LambdaFunctionInsideVPCRule.rb", relation: "equivalent" },
|
|
44
|
+
{ tool: "checkov", rule: "CKV_AWS_117", url: "https://www.checkov.io/5.Policy%20Index/cloudformation.html", relation: "equivalent" },
|
|
45
|
+
{ tool: "guard-rules-registry", rule: "LAMBDA_INSIDE_VPC", url: "https://github.com/aws-cloudformation/aws-guard-rules-registry/blob/main/rules/aws/lambda/lambda_inside_vpc.guard", relation: "equivalent" },
|
|
46
|
+
],
|
|
47
|
+
WAW023: [
|
|
48
|
+
{ tool: "checkov", rule: "CKV_AWS_68", url: "https://www.checkov.io/5.Policy%20Index/cloudformation.html", relation: "equivalent" },
|
|
49
|
+
{ tool: "kics", rule: "CloudFront Without WAF", url: "https://docs.kics.io/latest/queries/cloudformation-queries/aws/0f139403-303f-467c-96bd-e717e6cfd62d/", relation: "equivalent" },
|
|
50
|
+
],
|
|
51
|
+
WAW024: [
|
|
52
|
+
{ tool: "cfn-nag", rule: "W52", url: "https://github.com/stelligent/cfn_nag/blob/master/lib/cfn-nag/custom_rules/ElasticLoadBalancerV2AccessLoggingRule.rb", relation: "equivalent" },
|
|
53
|
+
{ tool: "checkov", rule: "CKV_AWS_91", url: "https://www.checkov.io/5.Policy%20Index/cloudformation.html", relation: "equivalent" },
|
|
54
|
+
{ tool: "kics", rule: "ELBv2 ALB Access Log Disabled", url: "https://docs.kics.io/latest/queries/cloudformation-queries/aws/c62e8b7d-1fdf-4050-ac4c-76ba9e1d9621/", relation: "equivalent" },
|
|
55
|
+
],
|
|
56
|
+
WAW025: [
|
|
57
|
+
{ tool: "cfn-nag", rule: "W47", url: "https://github.com/stelligent/cfn_nag/blob/master/lib/cfn-nag/custom_rules/SnsTopicKmsMasterKeyIdRule.rb", relation: "equivalent" },
|
|
58
|
+
{ tool: "checkov", rule: "CKV_AWS_26", url: "https://www.checkov.io/5.Policy%20Index/cloudformation.html", relation: "equivalent" },
|
|
59
|
+
{ tool: "guard-rules-registry", rule: "SNS_ENCRYPTED_KMS", url: "https://github.com/aws-cloudformation/aws-guard-rules-registry/blob/main/rules/aws/amazon_sns/sns_encrypted_kms.guard", relation: "equivalent" },
|
|
60
|
+
],
|
|
61
|
+
WAW026: [
|
|
62
|
+
{ tool: "checkov", rule: "CKV_AWS_27", url: "https://www.checkov.io/5.Policy%20Index/cloudformation.html", relation: "equivalent" },
|
|
63
|
+
{ tool: "kics", rule: "SQS With SSE Disabled", url: "https://docs.kics.io/latest/queries/cloudformation-queries/aws/12726829-93ed-4d51-9cbe-13423f4299e1/", relation: "equivalent" },
|
|
64
|
+
{ tool: "cfn-nag", rule: "W48", url: "https://github.com/stelligent/cfn_nag/blob/master/lib/cfn-nag/custom_rules/SqsQueueKmsMasterKeyIdRule.rb", relation: "overlaps" },
|
|
65
|
+
],
|
|
66
|
+
WAW027: [
|
|
67
|
+
{ tool: "cfn-nag", rule: "W78", url: "https://github.com/stelligent/cfn_nag/blob/master/lib/cfn-nag/custom_rules/DynamoDBBackupRule.rb", relation: "equivalent" },
|
|
68
|
+
{ tool: "checkov", rule: "CKV_AWS_28", url: "https://www.checkov.io/5.Policy%20Index/cloudformation.html", relation: "equivalent" },
|
|
69
|
+
{ tool: "guard-rules-registry", rule: "DYNAMODB_PITR_ENABLED", url: "https://github.com/aws-cloudformation/aws-guard-rules-registry/blob/main/rules/aws/dynamodb/dynamodb_pitr_enabled.guard", relation: "equivalent" },
|
|
70
|
+
],
|
|
71
|
+
WAW028: [
|
|
72
|
+
{ tool: "cfn-nag", rule: "F1", url: "https://github.com/stelligent/cfn_nag/blob/master/lib/cfn-nag/custom_rules/EbsVolumeHasSseRule.rb", relation: "equivalent" },
|
|
73
|
+
{ tool: "checkov", rule: "CKV_AWS_3", url: "https://www.checkov.io/5.Policy%20Index/cloudformation.html", relation: "equivalent" },
|
|
74
|
+
{ tool: "guard-rules-registry", rule: "ENCRYPTED_VOLUMES", url: "https://github.com/aws-cloudformation/aws-guard-rules-registry/blob/main/rules/aws/amazon_ec2/encrypted_volumes.guard", relation: "equivalent" },
|
|
75
|
+
],
|
|
76
|
+
WAW029: [
|
|
77
|
+
{ tool: "cfn-lint", rule: "E3005", url: "https://github.com/aws-cloudformation/cfn-lint/blob/main/docs/rules.md#E3005", relation: "equivalent" },
|
|
78
|
+
],
|
|
79
|
+
WAW032: [
|
|
80
|
+
{ tool: "checkov", rule: "CKV_AWS_97", url: "https://www.checkov.io/5.Policy%20Index/cloudformation.html", relation: "equivalent" },
|
|
81
|
+
{ tool: "kics", rule: "EFS Volume With Disabled Transit Encryption", url: "https://docs.kics.io/latest/queries/cloudformation-queries/aws/c1282e03-b285-4637-aee7-eefe3a7bb658/", relation: "equivalent" },
|
|
82
|
+
],
|
|
83
|
+
WAW038: [
|
|
84
|
+
{ tool: "cfn-nag", rule: "F22", url: "https://github.com/stelligent/cfn_nag/blob/master/lib/cfn-nag/custom_rules/RDSInstancePubliclyAccessibleRule.rb", relation: "equivalent" },
|
|
85
|
+
{ tool: "checkov", rule: "CKV_AWS_17", url: "https://www.checkov.io/5.Policy%20Index/cloudformation.html", relation: "equivalent" },
|
|
86
|
+
{ tool: "kics", rule: "RDS DB Instance Publicly Accessible", url: "https://docs.kics.io/latest/queries/cloudformation-queries/aws/de38e1d5-54cb-4111-a868-6f7722695007/", relation: "equivalent" },
|
|
87
|
+
],
|
|
88
|
+
WAW039: [
|
|
89
|
+
{ tool: "cfn-nag", rule: "W75", url: "https://github.com/stelligent/cfn_nag/blob/master/lib/cfn-nag/custom_rules/RDSInstanceBackupRetentionPeriodRule.rb", relation: "equivalent" },
|
|
90
|
+
{ tool: "guard-rules-registry", rule: "DB_INSTANCE_BACKUP_ENABLED", url: "https://github.com/aws-cloudformation/aws-guard-rules-registry/blob/main/rules/aws/amazon_rds/db_instance_backup_enabled.guard", relation: "equivalent" },
|
|
91
|
+
{ tool: "kics", rule: "RDS With Backup Disabled", url: "https://docs.kics.io/latest/queries/cloudformation-queries/aws/8c415f6f-7b90-4a27-a44a-51047e1506f9/", relation: "equivalent" },
|
|
92
|
+
],
|
|
93
|
+
WAW040: [
|
|
94
|
+
{ tool: "cfn-nag", rule: "F80", url: "https://github.com/stelligent/cfn_nag/blob/master/lib/cfn-nag/custom_rules/RDSInstanceDeletionProtectionRule.rb", relation: "equivalent" },
|
|
95
|
+
{ tool: "guard-rules-registry", rule: "RDS_INSTANCE_DELETION_PROTECTION_ENABLED", url: "https://github.com/aws-cloudformation/aws-guard-rules-registry/blob/main/rules/aws/amazon_rds/rds_instance_deletion_protection_enabled.guard", relation: "equivalent" },
|
|
96
|
+
{ tool: "kics", rule: "RDS DB Instance With Deletion Protection Disabled", url: "https://docs.kics.io/latest/queries/cloudformation-queries/aws/2c161e58-cb52-454f-abea-6470c37b5e6e/", relation: "equivalent" },
|
|
97
|
+
],
|
|
98
|
+
WAW042: [
|
|
99
|
+
{ tool: "guard-rules-registry", rule: "S3_BUCKET_SSL_REQUESTS_ONLY", url: "https://github.com/aws-cloudformation/aws-guard-rules-registry/blob/main/rules/aws/amazon_s3/s3_bucket_ssl_requests_only.guard", relation: "equivalent" },
|
|
100
|
+
{ tool: "kics", rule: "S3 Bucket Without SSL In Write Actions", url: "https://docs.kics.io/latest/queries/cloudformation-queries/aws/38c64e76-c71e-4d92-a337-60174d1de1c9/", relation: "overlaps" },
|
|
101
|
+
],
|
|
102
|
+
WAW043: [
|
|
103
|
+
{ tool: "cfn-nag", rule: "F19", url: "https://github.com/stelligent/cfn_nag/blob/master/lib/cfn-nag/custom_rules/KMSKeyRotationRule.rb", relation: "equivalent" },
|
|
104
|
+
{ tool: "checkov", rule: "CKV_AWS_7", url: "https://www.checkov.io/5.Policy%20Index/cloudformation.html", relation: "equivalent" },
|
|
105
|
+
{ tool: "guard-rules-registry", rule: "CMK_BACKING_KEY_ROTATION_ENABLED", url: "https://github.com/aws-cloudformation/aws-guard-rules-registry/blob/main/rules/aws/aws_kms/cmk_backing_key_rotation_enabled.guard", relation: "equivalent" },
|
|
106
|
+
],
|
|
107
|
+
WAW044: [
|
|
108
|
+
{ tool: "checkov", rule: "CKV_AWS_2", url: "https://www.checkov.io/5.Policy%20Index/cloudformation.html", relation: "overlaps" },
|
|
109
|
+
{ tool: "cfn-nag", rule: "W56", url: "https://github.com/stelligent/cfn_nag/blob/master/lib/cfn-nag/custom_rules/ElasticLoadBalancerV2ListenerProtocolRule.rb", relation: "overlaps" },
|
|
110
|
+
],
|
|
111
|
+
WAW045: [
|
|
112
|
+
{ tool: "cfn-nag", rule: "W55", url: "https://github.com/stelligent/cfn_nag/blob/master/lib/cfn-nag/custom_rules/ElasticLoadBalancerV2ListenerSslPolicyRule.rb", relation: "equivalent" },
|
|
113
|
+
{ tool: "checkov", rule: "CKV_AWS_103", url: "https://www.checkov.io/5.Policy%20Index/cloudformation.html", relation: "equivalent" },
|
|
114
|
+
{ tool: "guard-rules-registry", rule: "ELBV2_LISTENER_SSL_POLICY_RULE", url: "https://github.com/aws-cloudformation/aws-guard-rules-registry/blob/main/rules/aws/elastic_load_balancing_v2/elbv2_listener_ssl_policy_rule.guard", relation: "equivalent" },
|
|
115
|
+
],
|
|
116
|
+
WAW049: [
|
|
117
|
+
{ tool: "cfn-nag", rule: "W2", url: "https://github.com/stelligent/cfn_nag/blob/master/lib/cfn-nag/custom_rules/SecurityGroupIngressOpenToWorldRule.rb", relation: "overlaps" },
|
|
118
|
+
{ tool: "guard-rules-registry", rule: "EC2_SECURITY_GROUP_INGRESS_OPEN_TO_WORLD_RULE", url: "https://github.com/aws-cloudformation/aws-guard-rules-registry/blob/main/rules/aws/amazon_ec2/ec2_security_group_ingress_open_to_world_rule.guard", relation: "overlaps" },
|
|
119
|
+
{ tool: "kics", rule: "Unrestricted Security Group Ingress", url: "https://docs.kics.io/latest/queries/cloudformation-queries/aws/4a1e6b34-1008-4e61-a5f2-1f7c276f8d14/", relation: "overlaps" },
|
|
120
|
+
],
|
|
121
|
+
WAW052: [
|
|
122
|
+
{ tool: "cfn-nag", rule: "F78", url: "https://github.com/stelligent/cfn_nag/blob/master/lib/cfn-nag/custom_rules/CognitoUserPoolMfaConfigurationOnorOptionalRule.rb", relation: "overlaps" },
|
|
123
|
+
{ tool: "guard-rules-registry", rule: "COGNITO_USER_POOL_MFA_CONFIGURATION_RULE", url: "https://github.com/aws-cloudformation/aws-guard-rules-registry/blob/main/rules/aws/aws_cognito/cognito_user_pool_mfa_configuration_rule.guard", relation: "overlaps" },
|
|
124
|
+
{ tool: "kics", rule: "Cognito UserPool Without MFA", url: "https://docs.kics.io/latest/queries/cloudformation-queries/aws/74a18d1a-cf02-4a31-8791-ed0967ad7fdc/", relation: "overlaps" },
|
|
125
|
+
],
|
|
126
|
+
WAW053: [
|
|
127
|
+
{ tool: "cfn-nag", rule: "W79", url: "https://github.com/stelligent/cfn_nag/blob/master/lib/cfn-nag/custom_rules/ECRRepositoryScanOnPushRule.rb", relation: "equivalent" },
|
|
128
|
+
{ tool: "checkov", rule: "CKV_AWS_163", url: "https://www.checkov.io/5.Policy%20Index/cloudformation.html", relation: "equivalent" },
|
|
129
|
+
{ tool: "guard-rules-registry", rule: "ECR_REPO_SCAN_ON_PUSH", url: "https://github.com/aws-cloudformation/aws-guard-rules-registry/blob/main/rules/aws/aws_ecr/ecr_repo_scan_on_push_rule.guard", relation: "equivalent" },
|
|
130
|
+
],
|
|
131
|
+
WAW054: [
|
|
132
|
+
{ tool: "checkov", rule: "CKV_AWS_51", url: "https://www.checkov.io/5.Policy%20Index/cloudformation.html", relation: "equivalent" },
|
|
133
|
+
{ tool: "kics", rule: "ECR Image Tag Not Immutable", url: "https://docs.kics.io/latest/queries/cloudformation-queries/aws/33f41d31-86b1-46a4-81f7-9c9a671f59ac/", relation: "equivalent" },
|
|
134
|
+
],
|
|
135
|
+
WAW055: [
|
|
136
|
+
{ tool: "cfn-nag", rule: "W86", url: "https://github.com/stelligent/cfn_nag/blob/master/lib/cfn-nag/custom_rules/LogsLogGroupRetentionRule.rb", relation: "equivalent" },
|
|
137
|
+
{ tool: "checkov", rule: "CKV_AWS_66", url: "https://www.checkov.io/5.Policy%20Index/cloudformation.html", relation: "equivalent" },
|
|
138
|
+
{ tool: "guard-rules-registry", rule: "CW_LOGGROUP_RETENTION_PERIOD_CHECK", url: "https://github.com/aws-cloudformation/aws-guard-rules-registry/blob/main/rules/aws/cloudwatch/cw_loggroup_retention_period_check.guard", relation: "equivalent" },
|
|
139
|
+
],
|
|
140
|
+
WAW058: [
|
|
141
|
+
{ tool: "guard-rules-registry", rule: "MULTI_REGION_CLOUD_TRAIL_ENABLED", url: "https://github.com/aws-cloudformation/aws-guard-rules-registry/blob/main/rules/aws/cloudtrail/multi_region_cloud_trail_enabled.guard", relation: "overlaps" },
|
|
142
|
+
{ tool: "checkov", rule: "CKV_AWS_67", url: "https://www.checkov.io/5.Policy%20Index/cloudformation.html", relation: "overlaps" },
|
|
143
|
+
{ tool: "kics", rule: "CloudTrail Logging Disabled", url: "https://docs.kics.io/latest/queries/cloudformation-queries/aws/5c0b06d5-b7a4-484c-aeb0-75a836269ff0/", relation: "overlaps" },
|
|
144
|
+
],
|
|
145
|
+
WAW059: [
|
|
146
|
+
{ tool: "cfn-nag", rule: "W12", url: "https://github.com/stelligent/cfn_nag/blob/master/lib/cfn-nag/custom_rules/IamPolicyWildcardResourceRule.rb", relation: "overlaps" },
|
|
147
|
+
{ tool: "cfn-nag", rule: "W11", url: "https://github.com/stelligent/cfn_nag/blob/master/lib/cfn-nag/custom_rules/IamRoleWildcardResourceOnPermissionsPolicyRule.rb", relation: "overlaps" },
|
|
148
|
+
{ tool: "guard-rules-registry", rule: "IAM_POLICYDOCUMENT_NO_WILDCARD_RESOURCE", url: "https://github.com/aws-cloudformation/aws-guard-rules-registry/blob/main/rules/aws/iam/iam_policydocument_no_wildcard_resource.guard", relation: "overlaps" },
|
|
149
|
+
],
|
|
150
|
+
WAW061: [
|
|
151
|
+
{ tool: "cfn-lint", rule: "E3059", url: "https://github.com/aws-cloudformation/cfn-lint/blob/main/docs/rules.md#E3059", relation: "equivalent" },
|
|
152
|
+
],
|
|
153
|
+
WAW062: [
|
|
154
|
+
{ tool: "cfn-lint", rule: "E3019", url: "https://github.com/aws-cloudformation/cfn-lint/blob/main/docs/rules.md#E3019", relation: "overlaps" },
|
|
155
|
+
],
|
|
156
|
+
WAW069: [
|
|
157
|
+
{ tool: "cfn-lint", rule: "E8002", url: "https://github.com/aws-cloudformation/cfn-lint/blob/main/docs/rules.md#E8002", relation: "equivalent" },
|
|
158
|
+
],
|
|
159
|
+
};
|
|
@@ -60,6 +60,7 @@ import { waw065 } from "./waw065";
|
|
|
60
60
|
import { waw066 } from "./waw066";
|
|
61
61
|
import { waw067 } from "./waw067";
|
|
62
62
|
import { waw068 } from "./waw068";
|
|
63
|
+
import { waw069 } from "./waw069";
|
|
63
64
|
|
|
64
65
|
export const postSynthChecks: PostSynthCheck[] = [
|
|
65
66
|
cor020,
|
|
@@ -122,4 +123,5 @@ export const postSynthChecks: PostSynthCheck[] = [
|
|
|
122
123
|
waw066,
|
|
123
124
|
waw067,
|
|
124
125
|
waw068,
|
|
126
|
+
waw069,
|
|
125
127
|
];
|