@intentius/chant-lexicon-terraform 0.100.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.
Files changed (115) hide show
  1. package/dist/codegen/package.d.ts +1 -1
  2. package/dist/config.d.ts +2 -2
  3. package/dist/hcl/jsonencode.d.ts +106 -0
  4. package/dist/hcl/jsonencode.d.ts.map +1 -0
  5. package/dist/hcl/marker.d.ts.map +1 -1
  6. package/dist/integrity.json +11 -2
  7. package/dist/lint/audit-catalog.d.ts.map +1 -1
  8. package/dist/lint/audit-lineage.d.ts +1 -1
  9. package/dist/lint/audit-lineage.d.ts.map +1 -1
  10. package/dist/lint/post-synth/flat-attributes.d.ts +69 -0
  11. package/dist/lint/post-synth/flat-attributes.d.ts.map +1 -0
  12. package/dist/lint/post-synth/index.d.ts.map +1 -1
  13. package/dist/lint/post-synth/tf030.d.ts +51 -0
  14. package/dist/lint/post-synth/tf030.d.ts.map +1 -0
  15. package/dist/lint/post-synth/tf031.d.ts +55 -0
  16. package/dist/lint/post-synth/tf031.d.ts.map +1 -0
  17. package/dist/lint/post-synth/tf032.d.ts +71 -0
  18. package/dist/lint/post-synth/tf032.d.ts.map +1 -0
  19. package/dist/lint/post-synth/tf033.d.ts +50 -0
  20. package/dist/lint/post-synth/tf033.d.ts.map +1 -0
  21. package/dist/lint/post-synth/tf034.d.ts +25 -0
  22. package/dist/lint/post-synth/tf034.d.ts.map +1 -0
  23. package/dist/lint/post-synth/tf035.d.ts +33 -0
  24. package/dist/lint/post-synth/tf035.d.ts.map +1 -0
  25. package/dist/lint/post-synth/tf036.d.ts +33 -0
  26. package/dist/lint/post-synth/tf036.d.ts.map +1 -0
  27. package/dist/lint/post-synth/tf037.d.ts +31 -0
  28. package/dist/lint/post-synth/tf037.d.ts.map +1 -0
  29. package/dist/manifest.json +1 -1
  30. package/dist/okf/index.md +8 -0
  31. package/dist/okf/rules/TF030.md +11 -0
  32. package/dist/okf/rules/TF031.md +11 -0
  33. package/dist/okf/rules/TF032.md +11 -0
  34. package/dist/okf/rules/TF033.md +11 -0
  35. package/dist/okf/rules/TF034.md +11 -0
  36. package/dist/okf/rules/TF035.md +11 -0
  37. package/dist/okf/rules/TF036.md +11 -0
  38. package/dist/okf/rules/TF037.md +11 -0
  39. package/dist/op/activity-contracts.d.ts +18 -18
  40. package/dist/op/builders.d.ts.map +1 -1
  41. package/dist/rules/flat-attributes.ts +146 -0
  42. package/dist/rules/tf030.ts +290 -0
  43. package/dist/rules/tf031.ts +370 -0
  44. package/dist/rules/tf032.ts +226 -0
  45. package/dist/rules/tf033.ts +160 -0
  46. package/dist/rules/tf034.ts +63 -0
  47. package/dist/rules/tf035.ts +74 -0
  48. package/dist/rules/tf036.ts +119 -0
  49. package/dist/rules/tf037.ts +101 -0
  50. package/package.json +3 -3
  51. package/src/hcl/jsonencode.test.ts +226 -0
  52. package/src/hcl/jsonencode.ts +454 -0
  53. package/src/lint/audit-catalog.ts +148 -0
  54. package/src/lint/audit-lineage.ts +155 -1
  55. package/src/lint/post-synth/estate-2284.test.ts +68 -0
  56. package/src/lint/post-synth/fixtures/TF030/negative-rules.tf +45 -0
  57. package/src/lint/post-synth/fixtures/TF030/negative.tf +55 -0
  58. package/src/lint/post-synth/fixtures/TF030/not-determined-port.tf +28 -0
  59. package/src/lint/post-synth/fixtures/TF030/not-determined-standalone.tf +32 -0
  60. package/src/lint/post-synth/fixtures/TF030/not-determined-vpc-rule.tf +21 -0
  61. package/src/lint/post-synth/fixtures/TF030/not-determined.tf +39 -0
  62. package/src/lint/post-synth/fixtures/TF030/positive-ipv6.tf +44 -0
  63. package/src/lint/post-synth/fixtures/TF030/positive-mixed.tf +36 -0
  64. package/src/lint/post-synth/fixtures/TF030/positive-standalone.tf +25 -0
  65. package/src/lint/post-synth/fixtures/TF030/positive.tf +43 -0
  66. package/src/lint/post-synth/fixtures/TF031/negative.tf +89 -0
  67. package/src/lint/post-synth/fixtures/TF031/not-determined.tf +139 -0
  68. package/src/lint/post-synth/fixtures/TF031/positive-data-source.tf +57 -0
  69. package/src/lint/post-synth/fixtures/TF031/positive-heredoc.tf +149 -0
  70. package/src/lint/post-synth/fixtures/TF031/positive-jsonencode.tf +115 -0
  71. package/src/lint/post-synth/fixtures/TF032/negative-heredoc.tf +20 -0
  72. package/src/lint/post-synth/fixtures/TF032/negative-references.tf +214 -0
  73. package/src/lint/post-synth/fixtures/TF032/negative.tf +99 -0
  74. package/src/lint/post-synth/fixtures/TF032/positive-heredoc.tf +22 -0
  75. package/src/lint/post-synth/fixtures/TF032/positive-sidecar.tf +197 -0
  76. package/src/lint/post-synth/fixtures/TF032/positive.tf +54 -0
  77. package/src/lint/post-synth/fixtures/TF033/negative.tf +39 -0
  78. package/src/lint/post-synth/fixtures/TF033/not-determined-aurora.tf +25 -0
  79. package/src/lint/post-synth/fixtures/TF033/positive-absent.tf +93 -0
  80. package/src/lint/post-synth/fixtures/TF033/positive.tf +50 -0
  81. package/src/lint/post-synth/fixtures/TF034/negative.tf +24 -0
  82. package/src/lint/post-synth/fixtures/TF034/positive-absent.tf +36 -0
  83. package/src/lint/post-synth/fixtures/TF034/positive.tf +14 -0
  84. package/src/lint/post-synth/fixtures/TF035/negative-absent.tf +43 -0
  85. package/src/lint/post-synth/fixtures/TF035/negative.tf +54 -0
  86. package/src/lint/post-synth/fixtures/TF035/positive.tf +37 -0
  87. package/src/lint/post-synth/fixtures/TF036/negative.tf +61 -0
  88. package/src/lint/post-synth/fixtures/TF036/not-determined.tf +28 -0
  89. package/src/lint/post-synth/fixtures/TF036/positive.tf +38 -0
  90. package/src/lint/post-synth/fixtures/TF037/negative-exclusion.tf +63 -0
  91. package/src/lint/post-synth/fixtures/TF037/negative.tf +27 -0
  92. package/src/lint/post-synth/fixtures/TF037/not-determined.tf +27 -0
  93. package/src/lint/post-synth/fixtures/TF037/positive-absent.tf +15 -0
  94. package/src/lint/post-synth/fixtures/TF037/positive.tf +26 -0
  95. package/src/lint/post-synth/fixtures/estate-2284/clean/main.tf +132 -0
  96. package/src/lint/post-synth/fixtures/estate-2284/violating/main.tf +112 -0
  97. package/src/lint/post-synth/flat-attributes.ts +146 -0
  98. package/src/lint/post-synth/index.ts +16 -0
  99. package/src/lint/post-synth/tf030.test.ts +219 -0
  100. package/src/lint/post-synth/tf030.ts +290 -0
  101. package/src/lint/post-synth/tf031.test.ts +229 -0
  102. package/src/lint/post-synth/tf031.ts +370 -0
  103. package/src/lint/post-synth/tf032.test.ts +127 -0
  104. package/src/lint/post-synth/tf032.ts +226 -0
  105. package/src/lint/post-synth/tf033.test.ts +126 -0
  106. package/src/lint/post-synth/tf033.ts +160 -0
  107. package/src/lint/post-synth/tf034.test.ts +71 -0
  108. package/src/lint/post-synth/tf034.ts +63 -0
  109. package/src/lint/post-synth/tf035.test.ts +68 -0
  110. package/src/lint/post-synth/tf035.ts +74 -0
  111. package/src/lint/post-synth/tf036.test.ts +87 -0
  112. package/src/lint/post-synth/tf036.ts +119 -0
  113. package/src/lint/post-synth/tf037.test.ts +88 -0
  114. package/src/lint/post-synth/tf037.ts +101 -0
  115. package/src/op/activities/terraform.test.ts +2 -2
@@ -5,7 +5,7 @@ export declare function packageLexicon(options?: {
5
5
  verbose?: boolean;
6
6
  force?: boolean;
7
7
  }): Promise<{
8
- spec: import("packages/core/src").BundleSpec;
8
+ spec: import("@intentius/chant").BundleSpec;
9
9
  stats: {
10
10
  resources: number;
11
11
  properties: number;
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
+ all: "all";
117
118
  local: "local";
118
119
  none: "none";
119
- all: "all";
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"}
@@ -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,iEAInC,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"}
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"}
@@ -1,11 +1,12 @@
1
1
  {
2
2
  "algorithm": "sha256",
3
3
  "artifacts": {
4
- "manifest.json": "47d5fc0e15ac6577d9de832f62dfe0e9d1b225826577eafd012c55fb157d1507",
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": "6b8d2cc394ccb12b199efead8a644e6562412cbb3f0dad67f9dea675b4c4622f"
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;AAe1E,eAAO,MAAM,qBAAqB,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CA0S1D,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: not registered in `PRIOR_ART` (no rule cites it yet) and its `long_id`s live in Rego metadata under `checks/<kind>/<provider>/<service>/`, with no flat index. |
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,CA0R3D,CAAC"}
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;AA8BvE,eAAO,MAAM,eAAe,EAAE,cAAc,EA6B3C,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"}