@intentius/chant-lexicon-terraform 0.101.0 → 0.102.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/codegen/package.d.ts +1 -1
- package/dist/config.d.ts +3 -3
- package/dist/hcl/jsonencode.d.ts +106 -0
- package/dist/hcl/jsonencode.d.ts.map +1 -0
- package/dist/hcl/marker.d.ts.map +1 -1
- package/dist/integrity.json +11 -2
- package/dist/lint/audit-catalog.d.ts.map +1 -1
- package/dist/lint/audit-lineage.d.ts +1 -1
- package/dist/lint/audit-lineage.d.ts.map +1 -1
- package/dist/lint/post-synth/flat-attributes.d.ts +69 -0
- package/dist/lint/post-synth/flat-attributes.d.ts.map +1 -0
- package/dist/lint/post-synth/index.d.ts.map +1 -1
- package/dist/lint/post-synth/tf030.d.ts +51 -0
- package/dist/lint/post-synth/tf030.d.ts.map +1 -0
- package/dist/lint/post-synth/tf031.d.ts +55 -0
- package/dist/lint/post-synth/tf031.d.ts.map +1 -0
- package/dist/lint/post-synth/tf032.d.ts +71 -0
- package/dist/lint/post-synth/tf032.d.ts.map +1 -0
- package/dist/lint/post-synth/tf033.d.ts +50 -0
- package/dist/lint/post-synth/tf033.d.ts.map +1 -0
- package/dist/lint/post-synth/tf034.d.ts +25 -0
- package/dist/lint/post-synth/tf034.d.ts.map +1 -0
- package/dist/lint/post-synth/tf035.d.ts +33 -0
- package/dist/lint/post-synth/tf035.d.ts.map +1 -0
- package/dist/lint/post-synth/tf036.d.ts +33 -0
- package/dist/lint/post-synth/tf036.d.ts.map +1 -0
- package/dist/lint/post-synth/tf037.d.ts +31 -0
- package/dist/lint/post-synth/tf037.d.ts.map +1 -0
- package/dist/manifest.json +1 -1
- package/dist/okf/index.md +8 -0
- package/dist/okf/rules/TF030.md +11 -0
- package/dist/okf/rules/TF031.md +11 -0
- package/dist/okf/rules/TF032.md +11 -0
- package/dist/okf/rules/TF033.md +11 -0
- package/dist/okf/rules/TF034.md +11 -0
- package/dist/okf/rules/TF035.md +11 -0
- package/dist/okf/rules/TF036.md +11 -0
- package/dist/okf/rules/TF037.md +11 -0
- package/dist/op/activity-contracts.d.ts +18 -18
- package/dist/op/builders.d.ts.map +1 -1
- package/dist/rules/flat-attributes.ts +146 -0
- package/dist/rules/tf030.ts +290 -0
- package/dist/rules/tf031.ts +370 -0
- package/dist/rules/tf032.ts +226 -0
- package/dist/rules/tf033.ts +160 -0
- package/dist/rules/tf034.ts +63 -0
- package/dist/rules/tf035.ts +74 -0
- package/dist/rules/tf036.ts +119 -0
- package/dist/rules/tf037.ts +101 -0
- package/package.json +3 -3
- package/src/hcl/jsonencode.test.ts +226 -0
- package/src/hcl/jsonencode.ts +454 -0
- package/src/lint/audit-catalog.ts +148 -0
- package/src/lint/audit-lineage.ts +155 -1
- package/src/lint/post-synth/estate-2284.test.ts +68 -0
- package/src/lint/post-synth/fixtures/TF030/negative-rules.tf +45 -0
- package/src/lint/post-synth/fixtures/TF030/negative.tf +55 -0
- package/src/lint/post-synth/fixtures/TF030/not-determined-port.tf +28 -0
- package/src/lint/post-synth/fixtures/TF030/not-determined-standalone.tf +32 -0
- package/src/lint/post-synth/fixtures/TF030/not-determined-vpc-rule.tf +21 -0
- package/src/lint/post-synth/fixtures/TF030/not-determined.tf +39 -0
- package/src/lint/post-synth/fixtures/TF030/positive-ipv6.tf +44 -0
- package/src/lint/post-synth/fixtures/TF030/positive-mixed.tf +36 -0
- package/src/lint/post-synth/fixtures/TF030/positive-standalone.tf +25 -0
- package/src/lint/post-synth/fixtures/TF030/positive.tf +43 -0
- package/src/lint/post-synth/fixtures/TF031/negative.tf +89 -0
- package/src/lint/post-synth/fixtures/TF031/not-determined.tf +139 -0
- package/src/lint/post-synth/fixtures/TF031/positive-data-source.tf +57 -0
- package/src/lint/post-synth/fixtures/TF031/positive-heredoc.tf +149 -0
- package/src/lint/post-synth/fixtures/TF031/positive-jsonencode.tf +115 -0
- package/src/lint/post-synth/fixtures/TF032/negative-heredoc.tf +20 -0
- package/src/lint/post-synth/fixtures/TF032/negative-references.tf +214 -0
- package/src/lint/post-synth/fixtures/TF032/negative.tf +99 -0
- package/src/lint/post-synth/fixtures/TF032/positive-heredoc.tf +22 -0
- package/src/lint/post-synth/fixtures/TF032/positive-sidecar.tf +197 -0
- package/src/lint/post-synth/fixtures/TF032/positive.tf +54 -0
- package/src/lint/post-synth/fixtures/TF033/negative.tf +39 -0
- package/src/lint/post-synth/fixtures/TF033/not-determined-aurora.tf +25 -0
- package/src/lint/post-synth/fixtures/TF033/positive-absent.tf +93 -0
- package/src/lint/post-synth/fixtures/TF033/positive.tf +50 -0
- package/src/lint/post-synth/fixtures/TF034/negative.tf +24 -0
- package/src/lint/post-synth/fixtures/TF034/positive-absent.tf +36 -0
- package/src/lint/post-synth/fixtures/TF034/positive.tf +14 -0
- package/src/lint/post-synth/fixtures/TF035/negative-absent.tf +43 -0
- package/src/lint/post-synth/fixtures/TF035/negative.tf +54 -0
- package/src/lint/post-synth/fixtures/TF035/positive.tf +37 -0
- package/src/lint/post-synth/fixtures/TF036/negative.tf +61 -0
- package/src/lint/post-synth/fixtures/TF036/not-determined.tf +28 -0
- package/src/lint/post-synth/fixtures/TF036/positive.tf +38 -0
- package/src/lint/post-synth/fixtures/TF037/negative-exclusion.tf +63 -0
- package/src/lint/post-synth/fixtures/TF037/negative.tf +27 -0
- package/src/lint/post-synth/fixtures/TF037/not-determined.tf +27 -0
- package/src/lint/post-synth/fixtures/TF037/positive-absent.tf +15 -0
- package/src/lint/post-synth/fixtures/TF037/positive.tf +26 -0
- package/src/lint/post-synth/fixtures/estate-2284/clean/main.tf +132 -0
- package/src/lint/post-synth/fixtures/estate-2284/violating/main.tf +112 -0
- package/src/lint/post-synth/flat-attributes.ts +146 -0
- package/src/lint/post-synth/index.ts +16 -0
- package/src/lint/post-synth/tf030.test.ts +219 -0
- package/src/lint/post-synth/tf030.ts +290 -0
- package/src/lint/post-synth/tf031.test.ts +229 -0
- package/src/lint/post-synth/tf031.ts +370 -0
- package/src/lint/post-synth/tf032.test.ts +127 -0
- package/src/lint/post-synth/tf032.ts +226 -0
- package/src/lint/post-synth/tf033.test.ts +126 -0
- package/src/lint/post-synth/tf033.ts +160 -0
- package/src/lint/post-synth/tf034.test.ts +71 -0
- package/src/lint/post-synth/tf034.ts +63 -0
- package/src/lint/post-synth/tf035.test.ts +68 -0
- package/src/lint/post-synth/tf035.ts +74 -0
- package/src/lint/post-synth/tf036.test.ts +87 -0
- package/src/lint/post-synth/tf036.ts +119 -0
- package/src/lint/post-synth/tf037.test.ts +88 -0
- package/src/lint/post-synth/tf037.ts +101 -0
package/dist/config.d.ts
CHANGED
|
@@ -101,9 +101,9 @@ export declare const terraformConfigSchema: z.ZodObject<{
|
|
|
101
101
|
* binary alone runs the root stock, exactly as `terraform`/`tofu` do.
|
|
102
102
|
*/
|
|
103
103
|
binary: z.ZodOptional<z.ZodEnum<{
|
|
104
|
+
choudoufu: "choudoufu";
|
|
104
105
|
terraform: "terraform";
|
|
105
106
|
tofu: "tofu";
|
|
106
|
-
choudoufu: "choudoufu";
|
|
107
107
|
}>>;
|
|
108
108
|
/**
|
|
109
109
|
* How far a root's parse follows its `module` calls (#2112), spelled the
|
|
@@ -114,9 +114,9 @@ export declare const terraformConfigSchema: z.ZodObject<{
|
|
|
114
114
|
* nothing. See `hcl/descend.ts`.
|
|
115
115
|
*/
|
|
116
116
|
callModuleType: z.ZodOptional<z.ZodEnum<{
|
|
117
|
-
none: "none";
|
|
118
|
-
local: "local";
|
|
119
117
|
all: "all";
|
|
118
|
+
local: "local";
|
|
119
|
+
none: "none";
|
|
120
120
|
}>>;
|
|
121
121
|
/**
|
|
122
122
|
* The directory a root's local module sources may resolve within (#2874),
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read the argument of a `jsonencode(...)` call as structure, when it is
|
|
3
|
+
* literal (chant #2286, shared with #2287).
|
|
4
|
+
*
|
|
5
|
+
* hcl2json does not evaluate expressions. `policy = jsonencode({...})` and
|
|
6
|
+
* `container_definitions = jsonencode([...])` both reach a block body as ONE
|
|
7
|
+
* string holding the expression's source text, wrapped as an interpolation:
|
|
8
|
+
*
|
|
9
|
+
* ```
|
|
10
|
+
* "${jsonencode({\n Version = \"2012-10-17\"\n Statement = [{ Action = \"*\" }]\n })}"
|
|
11
|
+
* ```
|
|
12
|
+
*
|
|
13
|
+
* The text inside is HCL object syntax, not JSON (`=` or `:` separators, bare
|
|
14
|
+
* keys, newline-separated items, `#` comments). A rule that wants the policy
|
|
15
|
+
* or the container definitions has to read that text itself. This file does
|
|
16
|
+
* so, narrowly: it accepts literal objects, tuples, quoted strings, numbers,
|
|
17
|
+
* `true`, `false` and `null`, and nothing else. Any expression in the
|
|
18
|
+
* argument (a reference, a function call, a for-expression, a splat, a
|
|
19
|
+
* conditional, an operator, a template interpolation inside a string, a
|
|
20
|
+
* heredoc, a parenthesised key) makes the whole read `not-determined`, with a
|
|
21
|
+
* reason naming what was found. It never evaluates anything, so it can never
|
|
22
|
+
* return a value Terraform would not also produce from the same text.
|
|
23
|
+
*
|
|
24
|
+
* Three answers:
|
|
25
|
+
* - `literal`: the value is a single whole-string `${jsonencode(...)}` and
|
|
26
|
+
* its argument is fully literal. `value` is the plain JS value
|
|
27
|
+
* `jsonencode` would encode.
|
|
28
|
+
* - `not-determined`: the value is a `${jsonencode(...)}` call, but the
|
|
29
|
+
* argument holds something this reader does not evaluate.
|
|
30
|
+
* - `not-jsonencode`: the value is not a `${jsonencode(...)}` call at all
|
|
31
|
+
* (a plain string, a reference, `file(...)`, a number, absent). Callers
|
|
32
|
+
* decide what that means for their attribute; a plain string, for example,
|
|
33
|
+
* may itself be JSON from a heredoc.
|
|
34
|
+
*
|
|
35
|
+
* The whole-string test is shape-based: the string starts `${jsonencode(` and
|
|
36
|
+
* ends `)}`. A string that matches that shape but is really a template with
|
|
37
|
+
* two interpolations (`${jsonencode(a)}-${jsonencode(b)}`) fails the literal
|
|
38
|
+
* parse at the point where the first call closes early, and reads as
|
|
39
|
+
* `not-determined`, never as `literal`.
|
|
40
|
+
*/
|
|
41
|
+
export type JsonencodeRead =
|
|
42
|
+
/** The argument is a fully literal HCL object/tuple/string/number/bool/null tree. */
|
|
43
|
+
{
|
|
44
|
+
kind: "literal";
|
|
45
|
+
value: unknown;
|
|
46
|
+
}
|
|
47
|
+
/** `jsonencode(...)` whose argument contains a reference, function call, for-expression, splat, conditional, etc. */
|
|
48
|
+
| {
|
|
49
|
+
kind: "not-determined";
|
|
50
|
+
reason: string;
|
|
51
|
+
}
|
|
52
|
+
/** The value is not a single whole-string `${jsonencode(...)}` at all. */
|
|
53
|
+
| {
|
|
54
|
+
kind: "not-jsonencode";
|
|
55
|
+
};
|
|
56
|
+
export interface ReadJsonencodeOptions {
|
|
57
|
+
/**
|
|
58
|
+
* Read past a non-literal VALUE instead of giving up on the whole argument.
|
|
59
|
+
* Each such value (a reference, a function call, a conditional, an
|
|
60
|
+
* interpolated string, a heredoc, any other expression) becomes an
|
|
61
|
+
* {@link UnknownLeaf} in the returned tree, so a rule can still read the
|
|
62
|
+
* literal fields beside it: `Action = "*"` next to
|
|
63
|
+
* `Resource = aws_s3_bucket.x.arn`, or a container's literal `environment`
|
|
64
|
+
* next to `image = var.image`.
|
|
65
|
+
*
|
|
66
|
+
* The skip is narrow. It consumes one value expression, balancing `()[]{}`
|
|
67
|
+
* and quoted strings, up to the next `,`, newline or closing bracket at its
|
|
68
|
+
* own depth. A member whose KEY is an expression (an interpolated quoted
|
|
69
|
+
* key or a parenthesised computed key) is dropped from its object and listed
|
|
70
|
+
* under {@link UNKNOWN_KEYS} on that object. Damage to the STRUCTURE is
|
|
71
|
+
* still `not-determined`: an expression as the whole argument, including
|
|
72
|
+
* a for-expression or a splat (`jsonencode(local.policy)`,
|
|
73
|
+
* `jsonencode(var.x[*])`), since then no key or element is known.
|
|
74
|
+
*/
|
|
75
|
+
unknownLeaves?: boolean;
|
|
76
|
+
}
|
|
77
|
+
/** Marks a value position `readJsonencode(raw, { unknownLeaves: true })` could not read. */
|
|
78
|
+
export declare const UNKNOWN: unique symbol;
|
|
79
|
+
/** A value position holding an expression; `reason` names what was found there. */
|
|
80
|
+
export interface UnknownLeaf {
|
|
81
|
+
readonly [UNKNOWN]: true;
|
|
82
|
+
readonly reason: string;
|
|
83
|
+
/**
|
|
84
|
+
* The skipped expression's own source text, trimmed (`aws_s3_bucket.x.arn`,
|
|
85
|
+
* `"arn:aws:s3:::${var.bucket}/*"` with its quotes). A rule may read it to
|
|
86
|
+
* rule a value OUT (a quoted template whose literal text already differs
|
|
87
|
+
* from the value it looks for), never to evaluate it.
|
|
88
|
+
*/
|
|
89
|
+
readonly source: string;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Marks an object, read with `unknownLeaves`, that had members whose KEY is an
|
|
93
|
+
* expression (`"router-${var.n}.rule" = ...`, `(var.k) = ...`). Those members
|
|
94
|
+
* are dropped from the object and their reasons listed here, so a reader can
|
|
95
|
+
* tell "this key is absent" from "some key here could not be read".
|
|
96
|
+
*/
|
|
97
|
+
export declare const UNKNOWN_KEYS: unique symbol;
|
|
98
|
+
/** Whether `obj` is an object that dropped one or more members with an expression key. */
|
|
99
|
+
export declare function hasUnknownKeys(obj: unknown): obj is Record<string, unknown> & {
|
|
100
|
+
[UNKNOWN_KEYS]: string[];
|
|
101
|
+
};
|
|
102
|
+
/** Whether `v` is a value position the reader skipped. */
|
|
103
|
+
export declare function isUnknown(v: unknown): v is UnknownLeaf;
|
|
104
|
+
/** Read `raw` (an hcl2json attribute value) as a `jsonencode(...)` call. */
|
|
105
|
+
export declare function readJsonencode(raw: unknown, options?: ReadJsonencodeOptions): JsonencodeRead;
|
|
106
|
+
//# sourceMappingURL=jsonencode.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jsonencode.d.ts","sourceRoot":"","sources":["../../src/hcl/jsonencode.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAEH,MAAM,MAAM,cAAc;AACxB,qFAAqF;AACnF;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE;AACrC,qHAAqH;GACnH;IAAE,IAAI,EAAE,gBAAgB,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE;AAC5C,0EAA0E;GACxE;IAAE,IAAI,EAAE,gBAAgB,CAAA;CAAE,CAAC;AAE/B,MAAM,WAAW,qBAAqB;IACpC;;;;;;;;;;;;;;;;;OAiBG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,4FAA4F;AAC5F,eAAO,MAAM,OAAO,EAAE,OAAO,MAAqC,CAAC;AAEnE,mFAAmF;AACnF,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,CAAC,OAAO,CAAC,EAAE,IAAI,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB;;;;;OAKG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED;;;;;GAKG;AACH,eAAO,MAAM,YAAY,EAAE,OAAO,MAAyC,CAAC;AAE5E,0FAA0F;AAC1F,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;IAAE,CAAC,YAAY,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,CAO1G;AAED,0DAA0D;AAC1D,wBAAgB,SAAS,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,IAAI,WAAW,CAEtD;AAKD,4EAA4E;AAC5E,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,GAAE,qBAA0B,GAAG,cAAc,CAmBhG"}
|
package/dist/hcl/marker.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"marker.d.ts","sourceRoot":"","sources":["../../src/hcl/marker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AAEH,oFAAoF;AACpF,eAAO,MAAM,iBAAiB,gBAAgB,CAAC;AAE/C,kGAAkG;AAClG,eAAO,MAAM,kBAAkB,iBAAiB,CAAC;AAEjD,mFAAmF;AACnF,eAAO,MAAM,eAAe,cAAc,CAAC;AAE3C;;;;GAIG;AACH,eAAO,MAAM,gCAAgC,
|
|
1
|
+
{"version":3,"file":"marker.d.ts","sourceRoot":"","sources":["../../src/hcl/marker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AAEH,oFAAoF;AACpF,eAAO,MAAM,iBAAiB,gBAAgB,CAAC;AAE/C,kGAAkG;AAClG,eAAO,MAAM,kBAAkB,iBAAiB,CAAC;AAEjD,mFAAmF;AACnF,eAAO,MAAM,eAAe,cAAc,CAAC;AAE3C;;;;GAIG;AACH,eAAO,MAAM,gCAAgC,YAC3C,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,CACR,CAAC;AA4CX;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEpD;AAkBD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAErD;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAO/D;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,eAAe,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAEjF;AAED,iEAAiE;AACjE,MAAM,MAAM,aAAa;AACvB,sFAAsF;AACpF;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE;AACnE,8FAA8F;GAC5F;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE;AACrB;;;;GAIG;GACD;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAE1D;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,GAAG,MAAM,GAAG,SAAS,CAgB9F;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,GAAG,SAAS,GAAG,aAAa,CAe9F"}
|
package/dist/integrity.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"algorithm": "sha256",
|
|
3
3
|
"artifacts": {
|
|
4
|
-
"manifest.json": "
|
|
4
|
+
"manifest.json": "d7619e357f8ddb66f17dd8331e2f4024d6a5b9d5e2bbf9fb1434d90eae5000a3",
|
|
5
5
|
"meta.json": "ca3d163bab055381827226140568f3bef7eaac187cebd76878e0b63e9e442356",
|
|
6
6
|
"types/index.d.ts": "022927e6a7b351cc4cf52d5f973f60ccd140e5810e17b32fb8868965aa1db161",
|
|
7
7
|
"rules/plan-before-apply.ts": "31b1b3176799fd365b2583fe3947edd187c2a863e3dc0094ed9e91ece2464c99",
|
|
8
8
|
"rules/blocks.ts": "d69f65c13b44ff425ccd465644f41c160e07b4c221bd60698d3ec84bf5d9cef8",
|
|
9
|
+
"rules/flat-attributes.ts": "135b4b118cb76ea7ef7a6f2851bb5c80d0907485b86a364c017f66388d0d4cb2",
|
|
9
10
|
"rules/module-source.ts": "147025cf53eba006473ddcb771bf7452928fc476e6daee10bbb86bcc7ee3848a",
|
|
10
11
|
"rules/scope.ts": "a6d327d821f219c98a9d4ae6e6eed6325f3d3edf6286f3622b41be591d190dc8",
|
|
11
12
|
"rules/tf001.ts": "1f07f0f9172a7ddb9c726ba4be1bea08e54e25701fbe59cc54c3cf4401aca999",
|
|
@@ -36,7 +37,15 @@
|
|
|
36
37
|
"rules/tf027.ts": "0a6062a230cdaa707f82b2353be4b34dff81322d24075d46f732a47bcef15893",
|
|
37
38
|
"rules/tf028.ts": "81ef95659c40ad1774c83e663473ed769143d894a4ba0517c3defa31f00ba723",
|
|
38
39
|
"rules/tf029.ts": "52e02b4921a64f3f928836896b8b80682400adb50bd7a0645f3fe2e8819433c2",
|
|
40
|
+
"rules/tf030.ts": "02aa051ad7ce95d2ed4df4f529a0d979bffe8765b54d0f402d2ced97a2d6c28b",
|
|
41
|
+
"rules/tf031.ts": "f4b05c45988ad816161c6c842e87206a3c3dd5bcefcfbed99451f5c582d8c453",
|
|
42
|
+
"rules/tf032.ts": "e31a5531d60c0bd42844b0600c9353d503f16cec9a74ca8a7b5001539d81dd7e",
|
|
43
|
+
"rules/tf033.ts": "84774cd31409f33325b09bfb1d3e9a6f20eeb961a52217948331cf801479c6f1",
|
|
44
|
+
"rules/tf034.ts": "7d5770d3f654e900b7275906646c541444bcdd5d92289b7bcc15bc10198d3a4c",
|
|
45
|
+
"rules/tf035.ts": "2514b58731114a29c1a447a173d138c7e442ecb2a180da49929e1899ac6fd188",
|
|
46
|
+
"rules/tf036.ts": "94fd91568341b6868ecd090772b93e675d2084547ae919586a496b9cb8a8f47b",
|
|
47
|
+
"rules/tf037.ts": "d6fc1e8ab4478f7983f28c6679f56a3fcfe5f6a5fb2402981bbca98114b486bf",
|
|
39
48
|
"skills/chant-terraform.md": "d9ca7b7c28aed0038ce775a3491150298492eed2858fd3651ed9bfca0e577ae8"
|
|
40
49
|
},
|
|
41
|
-
"composite": "
|
|
50
|
+
"composite": "5cedcb8fdfd0bee9e59a770470ef1207999c624e87595866029b40b70ad8c96b"
|
|
42
51
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audit-catalog.d.ts","sourceRoot":"","sources":["../../src/lint/audit-catalog.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAa,QAAQ,EAAE,MAAM,gCAAgC,CAAC;
|
|
1
|
+
{"version":3,"file":"audit-catalog.d.ts","sourceRoot":"","sources":["../../src/lint/audit-catalog.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAa,QAAQ,EAAE,MAAM,gCAAgC,CAAC;AA+D1E,eAAO,MAAM,qBAAqB,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CA8Y1D,CAAC"}
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
* | `tflint-ruleset-redeploy` | tflint-ruleset-redeploy | https://github.com/RedeployAB/tflint-ruleset-redeploy | 0BSD | scanner | Community ruleset; richest source of language-level rules outside the official set. Sweep: indexed from `docs/rules/README.md`, same table shape (33 rules). |
|
|
57
57
|
* | `tflint-ruleset-avm` | tflint-ruleset-avm | https://github.com/Azure/tflint-ruleset-avm | MIT | scanner | Azure Verified Modules conformance; two of its 33 rules are provider-agnostic. Sweep: indexed from the repository-root `RULES.md`, since `docs/` holds pages for only two rules (33 rules). |
|
|
58
58
|
* | `tfsec` | tfsec | https://github.com/aquasecurity/tfsec | MIT | scanner | Historical: not archived but effectively frozen (no release since 2025-05); its docs site 404s above v0.61.x, so cite pinned repository paths (`github.com/aquasecurity/tfsec/blob/master/docs/checks/...`), not the docs site. Sweep: indexed from the root `rules.md` on `master`, a flat table of all 152 check ids, because `docs/checks` nests a directory per provider, service and check. |
|
|
59
|
-
* | `trivy-checks` | trivy-checks | https://github.com/aquasecurity/trivy-checks | MIT (not the trivy scanner's own Apache-2.0; cite the checks repo's licence, not the engine's) | scanner | Where tfsec's rules live today (tfsec -> defsec -> trivy + trivy-checks). Cite rules by `long_id` (stable, human-readable); `AVD-*` ids are aliases now. Sweep:
|
|
59
|
+
* | `trivy-checks` | trivy-checks | https://github.com/aquasecurity/trivy-checks | MIT (not the trivy scanner's own Apache-2.0; cite the checks repo's licence, not the engine's) | scanner | Where tfsec's rules live today (tfsec -> defsec -> trivy + trivy-checks). Cite rules by `long_id` (stable, human-readable); `AVD-*` ids are aliases now. Sweep: registered in `PRIOR_ART` since TF030 (#2285) cited `aws-ec2-no-public-ingress-sgr` (TF032 also cites `aws-ecs-no-plaintext-secrets`, AWS-0036), but not swept: its `long_id`s live in Rego metadata under `checks/<kind>/<provider>/<service>/`, with no flat index. Check a cited id is live: TF031's counterpart, `aws-iam-no-policy-wildcards`, is a `deprecated: true` stub with no rule body, so TF031 does not cite it. |
|
|
60
60
|
* | `terraform-sentinel-policies` | HashiCorp reference Sentinel policies | https://github.com/hashicorp/terraform-sentinel-policies | MPL-2.0 | specification | HashiCorp's own example policy set; ships zero rules baked into HCP Terraform itself, so treat a cited policy as a documented pattern (`specification`) unless a future entry runs it as a real check (`scanner`); the `kind` union allows either. Sweep: indexed by listing the five per-cloud directories, whose `.sentinel` filenames are the policy ids credits cite (73 policies); the repository publishes no index page. |
|
|
61
61
|
* | `choudoufu` | choudoufu | https://github.com/INTENTIUS/choudoufu | MPL-2.0 | scanner | Its `internal/live/lint` package; experimental, AWS-only. Sweep: unsweepable, its rule ids are Go constants in `internal/live/lint/issue.go` and it publishes no rule index. |
|
|
62
62
|
* | `hashicorp-style-guide` | HashiCorp Terraform style guide | https://developer.hashicorp.com/terraform/language/style | n/a | specification | Sweep: unsweepable, one prose page of recommendations with no rule ids; a credit quotes the sentence and links its fragment. |
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audit-lineage.d.ts","sourceRoot":"","sources":["../../src/lint/audit-lineage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgHG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gCAAgC,CAAC;AAQ9D,eAAO,MAAM,qBAAqB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"audit-lineage.d.ts","sourceRoot":"","sources":["../../src/lint/audit-lineage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgHG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gCAAgC,CAAC;AAQ9D,eAAO,MAAM,qBAAqB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,CAob3D,CAAC"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared reading helpers for TF033-TF037, the five flat encryption and
|
|
3
|
+
* immutability rules (chant #2288, epic #2284).
|
|
4
|
+
*
|
|
5
|
+
* Each of those rules reads one or two scalar attributes of one resource type
|
|
6
|
+
* and answers a three-valued question: the literal proves the resource
|
|
7
|
+
* secure, the literal proves it insecure, or the parse cannot tell. This
|
|
8
|
+
* module is the reading half; each rule file holds its own answer for
|
|
9
|
+
* absence, because that answer differs per resource (see each rule's doc
|
|
10
|
+
* comment and its section of `docs/pages/lint-rules.mdx`). It exports no
|
|
11
|
+
* `PostSynthCheck`, so the generated barrel skips it.
|
|
12
|
+
*/
|
|
13
|
+
import type { PostSynthContext, PostSynthDiagnostic } from "@intentius/chant/lint/post-synth";
|
|
14
|
+
import { type BlockBody } from "../../hcl/parse.js";
|
|
15
|
+
import { nestedBodies, type TerraformBlock } from "./blocks.js";
|
|
16
|
+
/** What one attribute read settles. `reason` says why a value could not be read. */
|
|
17
|
+
export type Read<T> = {
|
|
18
|
+
kind: "known";
|
|
19
|
+
value: T;
|
|
20
|
+
} | {
|
|
21
|
+
kind: "absent";
|
|
22
|
+
} | {
|
|
23
|
+
kind: "unknown";
|
|
24
|
+
reason: string;
|
|
25
|
+
};
|
|
26
|
+
/** Every `resource` block of one provider type (`aws_sqs_queue`), in entity order. */
|
|
27
|
+
export declare function resourcesOfType(ctx: PostSynthContext, type: string): TerraformBlock[];
|
|
28
|
+
/**
|
|
29
|
+
* A bool attribute. Terraform converts the strings `"true"` and `"false"` to
|
|
30
|
+
* bool, so those read as the bool they convert to. Any other literal (a
|
|
31
|
+
* number, a list) is a plan-time type error, not this rule's concern, and
|
|
32
|
+
* reads as unknown.
|
|
33
|
+
*/
|
|
34
|
+
export declare function readBool(body: BlockBody, name: string): Read<boolean>;
|
|
35
|
+
/** A string attribute, literal or not. */
|
|
36
|
+
export declare function readString(body: BlockBody, name: string): Read<string>;
|
|
37
|
+
/**
|
|
38
|
+
* Whether a key-like argument (`kms_master_key_id`) is set to something.
|
|
39
|
+
*
|
|
40
|
+
* - absent, or `null`: `absent`.
|
|
41
|
+
* - a literal: `known`, with the string (`""` is a value, and a rule decides
|
|
42
|
+
* what an empty key means).
|
|
43
|
+
* - an attribute of a managed resource or data source (`aws_kms_key.x.arn`):
|
|
44
|
+
* `known` and non-empty. The provider computes a key's id or ARN; it is
|
|
45
|
+
* never the empty string, so the key is set whatever its value turns out to
|
|
46
|
+
* be.
|
|
47
|
+
* - a template with literal text (`"alias/${var.env}-sns"`): `known` and
|
|
48
|
+
* non-empty, for the same reason.
|
|
49
|
+
* - anything else (`var.kms_key`, `local.key`, a conditional, a function
|
|
50
|
+
* call): `unknown`. A variable can be `null` or `""`.
|
|
51
|
+
*/
|
|
52
|
+
export declare function readKeySet(body: BlockBody, name: string): Read<string>;
|
|
53
|
+
/**
|
|
54
|
+
* Whether an argument that names a source (`snapshot_identifier`,
|
|
55
|
+
* `replicate_source_db`) or a nested block (`restore_to_point_in_time`) is
|
|
56
|
+
* given. The provider reads these with `GetOk`, so a literal `""` is the same
|
|
57
|
+
* as leaving the argument out; anything else, a reference included, is given.
|
|
58
|
+
*/
|
|
59
|
+
export declare function isGiven(body: BlockBody, name: string): boolean;
|
|
60
|
+
/** The bodies of a nested block, re-exported for the rule files. */
|
|
61
|
+
export { nestedBodies };
|
|
62
|
+
/** A finding the literal proves. */
|
|
63
|
+
export declare function finding(checkId: string, severity: "error" | "warning", block: TerraformBlock, message: string): PostSynthDiagnostic;
|
|
64
|
+
/**
|
|
65
|
+
* The one `info` diagnostic a rule emits when it cannot read the value it
|
|
66
|
+
* needs. The message starts `Not determined:`, as #2284 fixed for TF030-TF037.
|
|
67
|
+
*/
|
|
68
|
+
export declare function notDetermined(checkId: string, block: TerraformBlock, reason: string, tail: string): PostSynthDiagnostic;
|
|
69
|
+
//# sourceMappingURL=flat-attributes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flat-attributes.d.ts","sourceRoot":"","sources":["../../../src/lint/post-synth/flat-attributes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AAC9F,OAAO,EAAiB,KAAK,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEhE,OAAO,EAAgB,YAAY,EAAE,KAAK,cAAc,EAAE,MAAM,UAAU,CAAC;AAE3E,oFAAoF;AACpF,MAAM,MAAM,IAAI,CAAC,CAAC,IAAI;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,CAAC,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAE7G,sFAAsF;AACtF,wBAAgB,eAAe,CAAC,GAAG,EAAE,gBAAgB,EAAE,IAAI,EAAE,MAAM,GAAG,cAAc,EAAE,CAErF;AASD;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,CASrE;AAED,0CAA0C;AAC1C,wBAAgB,UAAU,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,CAQtE;AAWD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,CAiBtE;AAED;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAQ9D;AAED,oEAAoE;AACpE,OAAO,EAAE,YAAY,EAAE,CAAC;AAExB,oCAAoC;AACpC,wBAAgB,OAAO,CACrB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,OAAO,GAAG,SAAS,EAC7B,KAAK,EAAE,cAAc,EACrB,OAAO,EAAE,MAAM,GACd,mBAAmB,CAErB;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,mBAAmB,CAQvH"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lint/post-synth/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lint/post-synth/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAsCvE,eAAO,MAAM,eAAe,EAAE,cAAc,EAqC3C,CAAC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TF030: a security group rule opens a sensitive port to the whole internet.
|
|
3
|
+
*
|
|
4
|
+
* The native Terraform counterpart of the aws lexicon's WAW019 (#2285, under
|
|
5
|
+
* #2284), with the same port list and the same two open CIDRs. It cannot be a
|
|
6
|
+
* bridge to WAW019: the probe (docs/design/waw-hcl-fidelity-probe.md) ran the
|
|
7
|
+
* shipped WAW019 over a root opening 22, 3389, 3306 and 5432 to the world and
|
|
8
|
+
* got nothing back, because none of the three Terraform shapes looks like
|
|
9
|
+
* CloudFormation's `SecurityGroupIngress[].CidrIp`:
|
|
10
|
+
*
|
|
11
|
+
* - `ingress` on `aws_security_group`. The AWS provider types it as an
|
|
12
|
+
* attribute, `set(object({...}))`, not a nested block, though HCL lets it
|
|
13
|
+
* be written either way. hcl2json renders both spellings as one array of
|
|
14
|
+
* rule objects, so one reader covers both. `cidr_blocks` and
|
|
15
|
+
* `ipv6_cidr_blocks` are lists where CloudFormation has a scalar.
|
|
16
|
+
* - `aws_security_group_rule`, which is ingress only when `type = "ingress"`.
|
|
17
|
+
* - `aws_vpc_security_group_ingress_rule`, which spells the CIDR as the
|
|
18
|
+
* scalars `cidr_ipv4` / `cidr_ipv6` and the protocol as `ip_protocol`.
|
|
19
|
+
*
|
|
20
|
+
* A rule is reported when three things are all proved by literals: it is
|
|
21
|
+
* ingress, a CIDR is `0.0.0.0/0` or `::/0`, and its ports reach a sensitive
|
|
22
|
+
* port. Protocol `-1` (or `"all"`) reaches every port whatever `from_port` and
|
|
23
|
+
* `to_port` say. `tcp`, `udp`, `6` and `17` reach the ports between
|
|
24
|
+
* `from_port` and `to_port` inclusive, so `0`-`65535` reaches all four.
|
|
25
|
+
* Anything else (`icmp`, `icmpv6`, a protocol number like `50`) has no ports
|
|
26
|
+
* and is never reported.
|
|
27
|
+
*
|
|
28
|
+
* Nothing here evaluates an expression. When the answer hangs on a value the
|
|
29
|
+
* parse hands back as a reference or a template (`cidr_blocks =
|
|
30
|
+
* var.allowed`, `from_port = var.ssh_port`, `ingress = local.rules`, a
|
|
31
|
+
* `dynamic "ingress"` block), the rule emits one `info` finding that starts
|
|
32
|
+
* `Not determined:` and names the attributes, per the convention fixed on
|
|
33
|
+
* #2284. It never guesses a warning or an error out of something it could
|
|
34
|
+
* not read. A fact that settles the rule on its own still settles it, so
|
|
35
|
+
* `cidr_blocks = var.x` on port 443 is silent: no CIDR makes 443 sensitive.
|
|
36
|
+
*
|
|
37
|
+
* Absence is safe for this rule, which is the easy case of #2284's
|
|
38
|
+
* three-valued question. An `aws_security_group` with no `ingress` admits
|
|
39
|
+
* nothing (the provider default is no rules), and its rules may live in
|
|
40
|
+
* standalone resources, which this check reads in their own right.
|
|
41
|
+
*
|
|
42
|
+
* Scope: root and child modules alike (#2112). The condition is a property
|
|
43
|
+
* of the block itself.
|
|
44
|
+
*/
|
|
45
|
+
import type { PostSynthCheck } from "@intentius/chant/lint/post-synth";
|
|
46
|
+
/** The ports WAW019 treats as sensitive, with the name a message gives each. */
|
|
47
|
+
export declare const SENSITIVE_PORTS: ReadonlyMap<number, string>;
|
|
48
|
+
/** The two CIDRs that mean "every address". */
|
|
49
|
+
export declare const OPEN_CIDRS: ReadonlySet<string>;
|
|
50
|
+
export declare const tf030: PostSynthCheck;
|
|
51
|
+
//# sourceMappingURL=tf030.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tf030.d.ts","sourceRoot":"","sources":["../../../src/lint/post-synth/tf030.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAEH,OAAO,KAAK,EACV,cAAc,EAGf,MAAM,kCAAkC,CAAC;AAK1C,gFAAgF;AAChF,eAAO,MAAM,eAAe,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAKtD,CAAC;AAEH,+CAA+C;AAC/C,eAAO,MAAM,UAAU,EAAE,WAAW,CAAC,MAAM,CAAkC,CAAC;AA0I9E,eAAO,MAAM,KAAK,EAAE,cAwFnB,CAAC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TF031: an IAM policy allows a wildcard Action or a wildcard Resource
|
|
3
|
+
* (chant #2286, epic #2284).
|
|
4
|
+
*
|
|
5
|
+
* The Terraform counterpart of the aws lexicon's WAW020, written natively
|
|
6
|
+
* against the parsed HCL rather than bridged (docs/design/waw-hcl-fidelity-probe.md
|
|
7
|
+
* explains why a bridge reported nothing here). WAW020 flags `Action: "*"`
|
|
8
|
+
* only; this rule also flags `Resource: "*"`, as #2286 asks and as tfsec's
|
|
9
|
+
* `aws-iam-no-policy-wildcards` does.
|
|
10
|
+
*
|
|
11
|
+
* What it reads. A policy argument in Terraform is a string, and hcl2json
|
|
12
|
+
* hands it over unevaluated, so the rule reads three shapes and no others:
|
|
13
|
+
*
|
|
14
|
+
* - `jsonencode({...})`: hcl2json keeps the call as the one string
|
|
15
|
+
* `"${jsonencode({...})}"` with HCL object syntax inside. `readJsonencode`
|
|
16
|
+
* (`../../hcl/jsonencode.ts`) reads the literal parts of that argument as
|
|
17
|
+
* structure, leaving each expression in it as an opaque leaf.
|
|
18
|
+
* - a literal string, which is what a heredoc with no interpolation becomes in
|
|
19
|
+
* the parse: the JSON text itself, read with `JSON.parse`.
|
|
20
|
+
* - a `data "aws_iam_policy_document"` block, whose `statement { actions,
|
|
21
|
+
* resources, effect }` arrive as plain structure. A policy argument that is
|
|
22
|
+
* exactly `data.aws_iam_policy_document.<name>.json` (or `.minified_json`)
|
|
23
|
+
* naming a document declared in the same module is not reported again: the
|
|
24
|
+
* document is checked where it is declared.
|
|
25
|
+
*
|
|
26
|
+
* The three-valued answer. A finding needs a literal that proves it: an
|
|
27
|
+
* `Allow` statement (the data source's default effect, or a literal
|
|
28
|
+
* `"Allow"`) whose Action or Resource is the literal `"*"` or a list holding
|
|
29
|
+
* it. A `Deny` statement never fires; `Deny` with `Action = "*"` is the usual
|
|
30
|
+
* guard rail. When the value the rule needs is not readable (a reference, a
|
|
31
|
+
* `file()` or `templatefile()` call, a template, a for-expression, a
|
|
32
|
+
* `dynamic "statement"`), the rule emits one `info` diagnostic starting
|
|
33
|
+
* `Not determined:` that names the attribute and why, and never a warning.
|
|
34
|
+
* A value that cannot be `"*"` whatever it evaluates to is not "not
|
|
35
|
+
* determined": an attribute of a managed resource or data source
|
|
36
|
+
* (`aws_s3_bucket.logs.arn`) or a template whose literal text already
|
|
37
|
+
* differs from `*` (`"arn:aws:s3:::${var.bucket}/*"`) is read as scoped.
|
|
38
|
+
*
|
|
39
|
+
* Absence. A resource with no policy argument, or a role with no
|
|
40
|
+
* `inline_policy`, is unconfigured, not insecure, and is not reported.
|
|
41
|
+
*
|
|
42
|
+
* In scope: `aws_iam_policy.policy`, `aws_iam_role_policy.policy`,
|
|
43
|
+
* `aws_iam_user_policy.policy`, `aws_iam_group_policy.policy`,
|
|
44
|
+
* `aws_iam_role.inline_policy[].policy`, `aws_iam_role.assume_role_policy`
|
|
45
|
+
* (WAW020 walks `AssumeRolePolicyDocument` too) and the
|
|
46
|
+
* `aws_iam_policy_document` data source. Resource-based policies (S3, SQS,
|
|
47
|
+
* KMS, VPC endpoint) are out of scope: there `Resource: "*"` usually means
|
|
48
|
+
* "this resource" and the risk sits in `Principal`.
|
|
49
|
+
*
|
|
50
|
+
* Scope: root and child modules alike (#2112). The condition is a property
|
|
51
|
+
* of the block itself.
|
|
52
|
+
*/
|
|
53
|
+
import type { PostSynthCheck } from "@intentius/chant/lint/post-synth";
|
|
54
|
+
export declare const tf031: PostSynthCheck;
|
|
55
|
+
//# sourceMappingURL=tf031.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tf031.d.ts","sourceRoot":"","sources":["../../../src/lint/post-synth/tf031.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AAEH,OAAO,KAAK,EACV,cAAc,EAGf,MAAM,kCAAkC,CAAC;AAsR1C,eAAO,MAAM,KAAK,EAAE,cAkCnB,CAAC"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TF032: an ECS container definition passes a credential as a plaintext
|
|
3
|
+
* environment value.
|
|
4
|
+
*
|
|
5
|
+
* The Terraform counterpart of the aws lexicon's WAW046. A value under a
|
|
6
|
+
* container's `environment` is stored verbatim in the task definition: it is
|
|
7
|
+
* readable by anyone with `ecs:DescribeTaskDefinition`, it shows in the
|
|
8
|
+
* console, and it is in Terraform state and plan output. ECS has a field for
|
|
9
|
+
* exactly this, `secrets`, whose `valueFrom` is a Secrets Manager or SSM
|
|
10
|
+
* Parameter Store ARN that the agent resolves at task start. A credential
|
|
11
|
+
* belongs there.
|
|
12
|
+
*
|
|
13
|
+
* Why this is a native rule and not WAW046 through a bridge
|
|
14
|
+
* (docs/design/waw-hcl-fidelity-probe.md): `container_definitions` is a JSON
|
|
15
|
+
* string. In HCL it is almost always `jsonencode([...])`, which hcl2json hands
|
|
16
|
+
* back as the call's unevaluated source text, so the structure WAW046 reads
|
|
17
|
+
* does not exist in the parse until something reads that text.
|
|
18
|
+
* `../../hcl/jsonencode.ts` does, for literal structure only, and never
|
|
19
|
+
* evaluates anything.
|
|
20
|
+
*
|
|
21
|
+
* The three answers, per task definition:
|
|
22
|
+
*
|
|
23
|
+
* - Readable. `container_definitions` is `jsonencode([...])` whose list and
|
|
24
|
+
* containers are literal, or a plain JSON string (a heredoc with no
|
|
25
|
+
* interpolation is one). A reference or function call in a leaf
|
|
26
|
+
* (`image = var.image`, `value = var.db_password`) does not stop the read:
|
|
27
|
+
* that leaf is unknown and the literal fields beside it are still read. An
|
|
28
|
+
* environment entry whose value is a reference is skipped, since a
|
|
29
|
+
* reference is not a committed literal (TF007 and TF022 judge where the
|
|
30
|
+
* referenced value comes from).
|
|
31
|
+
* - Violation. A readable environment entry whose `value` is a literal string
|
|
32
|
+
* and is secret-shaped by `../secret-shape.ts`: a credential-looking name
|
|
33
|
+
* with a literal of at least 8 characters that is not a placeholder, or a
|
|
34
|
+
* value that is a credential on its own (a vendor key shape, a JWT, a PEM
|
|
35
|
+
* key, a high-entropy token) whatever it is called.
|
|
36
|
+
* - Not determined. `container_definitions` is a reference
|
|
37
|
+
* (`local.defs`, `data.template_file.x.rendered`), `file()`,
|
|
38
|
+
* `templatefile()`, a heredoc or string with interpolation, a jsonencode
|
|
39
|
+
* argument that is not a literal list (`jsonencode(concat(...))`,
|
|
40
|
+
* `jsonencode(local.containers)`), or a container whose `environment` is an
|
|
41
|
+
* expression (`environment = local.env`). One `info` diagnostic starting
|
|
42
|
+
* `Not determined:` per task definition or container, never a warning.
|
|
43
|
+
*
|
|
44
|
+
* Absence: a container with no `environment` is not insecure, and a task
|
|
45
|
+
* definition with no `container_definitions` is not reported (the attribute
|
|
46
|
+
* is required, so that is a plan error, not this rule's finding). A name in
|
|
47
|
+
* `secrets` is never reported: `secrets` is not read at all.
|
|
48
|
+
*
|
|
49
|
+
* Findings never carry the value, only its length.
|
|
50
|
+
*/
|
|
51
|
+
import type { PostSynthCheck, PostSynthContext, PostSynthDiagnostic } from "@intentius/chant/lint/post-synth";
|
|
52
|
+
/** The container definitions of one task definition, or why they cannot be read. */
|
|
53
|
+
export type ContainerDefinitionsRead = {
|
|
54
|
+
kind: "readable";
|
|
55
|
+
containers: unknown;
|
|
56
|
+
} | {
|
|
57
|
+
kind: "not-determined";
|
|
58
|
+
reason: string;
|
|
59
|
+
} | {
|
|
60
|
+
kind: "absent";
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* Read `container_definitions` as structure without evaluating anything.
|
|
64
|
+
* `jsonencode(...)` goes through the shared reader with unknown leaves; a
|
|
65
|
+
* plain string with no interpolation is JSON (a heredoc arrives as one);
|
|
66
|
+
* everything else is named in the not-determined reason.
|
|
67
|
+
*/
|
|
68
|
+
export declare function readContainerDefinitions(body: Record<string, unknown>): ContainerDefinitionsRead;
|
|
69
|
+
export declare function checkEcsPlaintextCredentials(ctx: PostSynthContext): PostSynthDiagnostic[];
|
|
70
|
+
export declare const tf032: PostSynthCheck;
|
|
71
|
+
//# sourceMappingURL=tf032.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tf032.d.ts","sourceRoot":"","sources":["../../../src/lint/post-synth/tf032.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;AAEH,OAAO,KAAK,EACV,cAAc,EACd,gBAAgB,EAChB,mBAAmB,EACpB,MAAM,kCAAkC,CAAC;AAS1C,oFAAoF;AACpF,MAAM,MAAM,wBAAwB,GAChC;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,UAAU,EAAE,OAAO,CAAA;CAAE,GACzC;IAAE,IAAI,EAAE,gBAAgB,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC1C;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,CAAC;AAEvB;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,wBAAwB,CAsBhG;AA+BD,wBAAgB,4BAA4B,CAAC,GAAG,EAAE,gBAAgB,GAAG,mBAAmB,EAAE,CAuFzF;AAED,eAAO,MAAM,KAAK,EAAE,cAOnB,CAAC"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TF033: an RDS DB instance or cluster does not encrypt its storage
|
|
3
|
+
* (chant #2288, epic #2284).
|
|
4
|
+
*
|
|
5
|
+
* The Terraform counterpart of the aws lexicon's WAW021, written natively.
|
|
6
|
+
* WAW021 reads a template chant synthesized, where `StorageEncrypted` absent
|
|
7
|
+
* means false. Reading somebody else's HCL, absence means different things
|
|
8
|
+
* for the two resources and for how the database is created, so each case is
|
|
9
|
+
* decided here against the provider schema and the AWS default.
|
|
10
|
+
*
|
|
11
|
+
* `aws_db_instance` (provider `internal/service/rds/instance.go`, v6.67.0):
|
|
12
|
+
* `storage_encrypted` is optional, not computed, and the docs say "The
|
|
13
|
+
* default is `false` if not specified". The plain create path and `s3_import`
|
|
14
|
+
* send `StorageEncrypted: d.Get("storage_encrypted")`, so absent means false
|
|
15
|
+
* and is reported. The replica (`replicate_source_db`), snapshot
|
|
16
|
+
* (`snapshot_identifier`) and point-in-time (`restore_to_point_in_time`)
|
|
17
|
+
* paths never send it: the new instance takes its encryption from the source
|
|
18
|
+
* (and a cross-region replica from `kms_key_id`). For those the rule cannot
|
|
19
|
+
* know, and says so, unless `storage_encrypted = true` is written down.
|
|
20
|
+
*
|
|
21
|
+
* `aws_rds_cluster` (`cluster.go`): `storage_encrypted` is optional and
|
|
22
|
+
* computed, sent only when set, and "Terraform will only perform drift
|
|
23
|
+
* detection if a configuration value is provided". Two engine families:
|
|
24
|
+
*
|
|
25
|
+
* - Aurora (`engine` `aurora-mysql`/`aurora-postgresql`, or absent, which
|
|
26
|
+
* provider v5 defaulted to `aurora`). Since 2026-02-16 AWS encrypts every
|
|
27
|
+
* new Aurora cluster at rest with an AWS-owned key whatever
|
|
28
|
+
* `StorageEncrypted` says, and reports `StorageEncrypted: false` with
|
|
29
|
+
* `StorageEncryptionType: sse-rds` for it. A cluster created before that
|
|
30
|
+
* date with storage encryption off is unencrypted, and the configuration
|
|
31
|
+
* does not say when its cluster was created. So an Aurora cluster with
|
|
32
|
+
* `storage_encrypted` absent or `false` is not determined, not a finding.
|
|
33
|
+
* `engine_mode = "serverless"` (Serverless v1) was always encrypted and
|
|
34
|
+
* is not reported at all.
|
|
35
|
+
* - Multi-AZ DB clusters (`engine` `mysql`/`postgres`): the default is
|
|
36
|
+
* `false` and nothing changed it, so absent or `false` is a finding,
|
|
37
|
+
* unless the cluster is restored or replicated from a source
|
|
38
|
+
* (`snapshot_identifier`, `restore_to_point_in_time`,
|
|
39
|
+
* `replication_source_identifier`, `global_cluster_identifier`), which
|
|
40
|
+
* again decides the encryption.
|
|
41
|
+
*
|
|
42
|
+
* Not checked: `aws_rds_cluster_instance` (its `storage_encrypted` is
|
|
43
|
+
* computed-only and never appears in a body), `aws_rds_global_cluster`, and
|
|
44
|
+
* whether the key is customer managed.
|
|
45
|
+
*
|
|
46
|
+
* Scope: root and child modules alike (#2112).
|
|
47
|
+
*/
|
|
48
|
+
import type { PostSynthCheck } from "@intentius/chant/lint/post-synth";
|
|
49
|
+
export declare const tf033: PostSynthCheck;
|
|
50
|
+
//# sourceMappingURL=tf033.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tf033.d.ts","sourceRoot":"","sources":["../../../src/lint/post-synth/tf033.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAyC,MAAM,kCAAkC,CAAC;AA+F9G,eAAO,MAAM,KAAK,EAAE,cAgBnB,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TF034: an SNS topic has no server-side encryption (chant #2288, epic #2284).
|
|
3
|
+
*
|
|
4
|
+
* The Terraform counterpart of the aws lexicon's WAW025, written natively.
|
|
5
|
+
*
|
|
6
|
+
* Absence is insecure for this resource, and the rule reports it.
|
|
7
|
+
* `aws_sns_topic.kms_master_key_id` (provider `internal/service/sns/topic.go`,
|
|
8
|
+
* v6.67.0) is optional with no default, and SNS has no service-owned
|
|
9
|
+
* encryption that applies when no key is named: server-side encryption
|
|
10
|
+
* (https://docs.aws.amazon.com/sns/latest/dg/sns-server-side-encryption.html)
|
|
11
|
+
* is on only when the topic names a KMS key, either the AWS managed
|
|
12
|
+
* `alias/aws/sns` or a customer managed key. Unlike SQS (TF035), no AWS
|
|
13
|
+
* default turns it on for new topics. A literal `kms_master_key_id = ""`
|
|
14
|
+
* names no key and is the same finding.
|
|
15
|
+
*
|
|
16
|
+
* Present and secure: a non-empty literal, an attribute of a managed resource
|
|
17
|
+
* or data source (`aws_kms_key.sns.arn`, `aws_kms_alias.sns.arn`), or a
|
|
18
|
+
* template with literal text. Not determined: a variable, local, module
|
|
19
|
+
* output, conditional or function call, any of which can be `null` or `""`.
|
|
20
|
+
*
|
|
21
|
+
* Scope: root and child modules alike (#2112).
|
|
22
|
+
*/
|
|
23
|
+
import type { PostSynthCheck } from "@intentius/chant/lint/post-synth";
|
|
24
|
+
export declare const tf034: PostSynthCheck;
|
|
25
|
+
//# sourceMappingURL=tf034.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tf034.d.ts","sourceRoot":"","sources":["../../../src/lint/post-synth/tf034.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAyC,MAAM,kCAAkC,CAAC;AAK9G,eAAO,MAAM,KAAK,EAAE,cAkCnB,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TF035: an SQS queue turns its server-side encryption off (chant #2288,
|
|
3
|
+
* epic #2284).
|
|
4
|
+
*
|
|
5
|
+
* The Terraform counterpart of the aws lexicon's WAW026, and the case that
|
|
6
|
+
* shows why the five flat rules could not be bridged. WAW026 reports a queue
|
|
7
|
+
* with neither `SqsManagedSseEnabled: true` nor `KmsMasterKeyId`. Bridged onto
|
|
8
|
+
* HCL, that reports every correctly encrypted queue in an estate
|
|
9
|
+
* (docs/design/waw-hcl-fidelity-probe.md).
|
|
10
|
+
*
|
|
11
|
+
* Absence is secure for this resource, and the rule does not report it.
|
|
12
|
+
* `sqs_managed_sse_enabled` is optional and computed (provider
|
|
13
|
+
* `internal/service/sqs/queue.go`, v6.67.0), and the provider docs say
|
|
14
|
+
* Terraform "will only perform drift detection of its value when present in
|
|
15
|
+
* a configuration". Since October 2022 SQS encrypts every new queue with
|
|
16
|
+
* SSE-SQS unless the request turns it off
|
|
17
|
+
* (https://aws.amazon.com/blogs/compute/announcing-server-side-encryption-with-amazon-simple-queue-service-managed-encryption-keys-sse-sqs-by-default/),
|
|
18
|
+
* and the provider creates queues over HTTPS, so a queue that sets neither
|
|
19
|
+
* attribute is encrypted. A queue created before that date and never
|
|
20
|
+
* changed can still be unencrypted; the configuration cannot show that, and
|
|
21
|
+
* TF035 does not guess it.
|
|
22
|
+
*
|
|
23
|
+
* The finding: `sqs_managed_sse_enabled = false` with no KMS key. Present and
|
|
24
|
+
* secure: `sqs_managed_sse_enabled = true`, or a `kms_master_key_id` that is
|
|
25
|
+
* a non-empty literal, a managed key's attribute, or a template with literal
|
|
26
|
+
* text. Not determined: `sqs_managed_sse_enabled` from an expression with no
|
|
27
|
+
* key, or a key from a variable beside `sqs_managed_sse_enabled = false`.
|
|
28
|
+
*
|
|
29
|
+
* Scope: root and child modules alike (#2112).
|
|
30
|
+
*/
|
|
31
|
+
import type { PostSynthCheck } from "@intentius/chant/lint/post-synth";
|
|
32
|
+
export declare const tf035: PostSynthCheck;
|
|
33
|
+
//# sourceMappingURL=tf035.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tf035.d.ts","sourceRoot":"","sources":["../../../src/lint/post-synth/tf035.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAyC,MAAM,kCAAkC,CAAC;AAO9G,eAAO,MAAM,KAAK,EAAE,cAmCnB,CAAC"}
|