@mavogel/awscdk-rootmail 0.0.336 → 0.1.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/.codegraph/.gitignore +5 -0
- package/.jsii +460 -8
- package/CLAUDE.md +1 -1
- package/README.md +6 -1
- package/docs/plans/2026-08-09-bump-mvc-projen-cdk-nag-v3.md +199 -0
- package/integ-tests/integ.rootmail-custom-santa.ts +2 -2
- package/integ-tests/integ.rootmail-filter-subject.ts +2 -2
- package/integ-tests/integ.rootmail.ts +2 -2
- package/lib/hosted-zone-dkim-propagation.js +46 -15
- package/lib/hosted-zone-dkim-verification-records.js +47 -12
- package/lib/rootmail-autowire-dns.js +47 -15
- package/lib/rootmail.js +13 -16
- package/lib/ses-receipt-ruleset-activation.js +53 -15
- package/lib/ses-receive.js +12 -12
- package/node_modules/cdk-nag/.jsii +6331 -2945
- package/node_modules/cdk-nag/.jsii.tabl.json +1 -1
- package/node_modules/cdk-nag/API.md +490 -1778
- package/node_modules/cdk-nag/MIGRATION.md +239 -0
- package/node_modules/cdk-nag/README.md +88 -513
- package/node_modules/cdk-nag/lib/index.d.ts +0 -3
- package/node_modules/cdk-nag/lib/index.js +1 -4
- package/node_modules/cdk-nag/lib/nag-logger.d.ts +5 -145
- package/node_modules/cdk-nag/lib/nag-logger.js +4 -199
- package/node_modules/cdk-nag/lib/nag-pack.d.ts +57 -44
- package/node_modules/cdk-nag/lib/nag-pack.js +140 -114
- package/node_modules/cdk-nag/lib/nag-rules.d.ts +0 -2
- package/node_modules/cdk-nag/lib/nag-rules.js +3 -5
- package/node_modules/cdk-nag/lib/packs/aws-solutions.d.ts +4 -15
- package/node_modules/cdk-nag/lib/packs/aws-solutions.js +21 -40
- package/node_modules/cdk-nag/lib/packs/hipaa-security.d.ts +4 -2
- package/node_modules/cdk-nag/lib/packs/hipaa-security.js +31 -37
- package/node_modules/cdk-nag/lib/packs/nist-800-53-r4.d.ts +4 -2
- package/node_modules/cdk-nag/lib/packs/nist-800-53-r4.js +29 -35
- package/node_modules/cdk-nag/lib/packs/nist-800-53-r5.d.ts +4 -2
- package/node_modules/cdk-nag/lib/packs/nist-800-53-r5.js +30 -36
- package/node_modules/cdk-nag/lib/packs/pci-dss-321.d.ts +4 -2
- package/node_modules/cdk-nag/lib/packs/pci-dss-321.js +29 -35
- package/node_modules/cdk-nag/lib/packs/serverless.d.ts +4 -2
- package/node_modules/cdk-nag/lib/packs/serverless.js +14 -20
- package/node_modules/cdk-nag/lib/rules/ec2/EC2IMDSv2Enabled.js +5 -1
- package/node_modules/cdk-nag/package.json +5 -5
- package/package.json +16 -17
- package/node_modules/cdk-nag/lib/ignore-suppression-conditions.d.ts +0 -59
- package/node_modules/cdk-nag/lib/ignore-suppression-conditions.js +0 -97
- package/node_modules/cdk-nag/lib/models/nag-suppression.d.ts +0 -30
- package/node_modules/cdk-nag/lib/models/nag-suppression.js +0 -7
- package/node_modules/cdk-nag/lib/nag-suppressions.d.ts +0 -30
- package/node_modules/cdk-nag/lib/nag-suppressions.js +0 -96
- package/node_modules/cdk-nag/lib/utils/nag-suppression-helper.d.ts +0 -20
- package/node_modules/cdk-nag/lib/utils/nag-suppression-helper.js +0 -119
package/CLAUDE.md
CHANGED
|
@@ -128,7 +128,7 @@ SES is not available in all regions. The construct validates deployment regions
|
|
|
128
128
|
- All resources follow AWS Well-Architected Framework principles
|
|
129
129
|
- S3 buckets have public access blocked and encryption enabled
|
|
130
130
|
- IAM policies follow principle of least privilege
|
|
131
|
-
- CDK Nag
|
|
131
|
+
- CDK Nag findings acknowledged via `Validations.of(construct).acknowledge({ id, reason })` (cdk-nag v3), documented with justifications
|
|
132
132
|
|
|
133
133
|
## Important Notes
|
|
134
134
|
|
package/README.md
CHANGED
|
@@ -145,7 +145,7 @@ and you create a separate `NodejsFunction` as follows with the additionally need
|
|
|
145
145
|
const customSesReceiveFunction = new NodejsFunction(stackUnderTest, 'custom-ses-receive-function', {
|
|
146
146
|
functionName: PhysicalName.GENERATE_IF_NEEDED,
|
|
147
147
|
entry: path.join(__dirname, 'functions', 'custom-ses-receive-function.ts'),
|
|
148
|
-
runtime: lambda.Runtime.
|
|
148
|
+
runtime: lambda.Runtime.NODEJS_24_X,
|
|
149
149
|
logRetention: 1,
|
|
150
150
|
timeout: Duration.seconds(30),
|
|
151
151
|
});
|
|
@@ -202,6 +202,11 @@ and fill out the parameters
|
|
|
202
202
|
|
|
203
203
|
## Known issues
|
|
204
204
|
- [jsii/2071](https://github.com/aws/jsii/issues/2071): so adding `compilerOptions."esModuleInterop": true,` in `tsconfig.json` is not possible. See aws-cdk usage with[typescript](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/#Usage_with_TypeScript). So we needed to change import from `import AWS from 'aws-sdk';` -> `import * as AWS from 'aws-sdk';` to be able to compile.
|
|
205
|
+
- Starting with this release, this construct requires `aws-cdk-lib` `>=2.263.0` and depends on `cdk-nag` `v3`, which replaced its suppression API (`NagSuppressions`) with CDK's native `Validations.of(construct).acknowledge(...)`. If you run `cdk-nag`'s `AwsSolutionsChecks` yourself against a stack containing this construct, be aware of the following gaps in what it can suppress on your behalf:
|
|
206
|
+
- `AwsSolutions-IAM4[Policy::...]` findings (AWS managed policies) cannot be acknowledged at all right now: `aws-cdk-lib`'s `Validations.acknowledge()` rejects any rule ID containing more than one `::`, and every AWS managed policy ARN contains one. This is a currently open upstream bug — see [cdklabs/cdk-nag#2359](https://github.com/cdklabs/cdk-nag/issues/2359) and [#2351](https://github.com/cdklabs/cdk-nag/issues/2351).
|
|
207
|
+
- `AwsSolutions-L1` (Lambda runtime), `AwsSolutions-SF1`/`SF2` (Step Functions logging/X-Ray on the internal custom-resource provider framework), and IAM findings on the shared `LogRetention` singleton are not suppressed by this construct — these were never checked before this release either.
|
|
208
|
+
- Granular `AwsSolutions-IAM5[Resource::<value>]` findings that embed a CDK-generated logical ID or your account/region are not portably suppressible by a shared construct library, since the acknowledged value is specific to how you instantiate `Rootmail` in your own app. Only the portable forms (`Resource::*`, a literal `Action::<name>`) are acknowledged internally.
|
|
209
|
+
- Synthesized CloudFormation templates no longer carry the v2-style `Metadata.cdk_nag.rules_to_suppress` block; acknowledgments are recorded as construct metadata instead. If you rely on that metadata for compliance tooling, run `cdk-nag` yourself with `writeSuppressionsToCloudFormation: true`.
|
|
205
210
|
|
|
206
211
|
## Related projects / questions
|
|
207
212
|
- [aws-account-factory-email](https://github.com/aws-samples/aws-account-factory-email): a similar approach with SES, however you need to manually configure it upfront and also it about delivering root mails for a specific account to a specific mailing list and mainly decouples the real email address from the one of the AWS account. The main difference is that we do not *hide* or decouple the email address, but more make those as unique and unguessable/bruteforable as possible (with `uuids`).
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
# mvc-projen 0.0.30 + cdk-nag v3 Migration Implementation Plan
|
|
2
|
+
|
|
3
|
+
Created: 2026-08-09
|
|
4
|
+
Author: info@manuel-vogel.de
|
|
5
|
+
Agent: Claude Code
|
|
6
|
+
Status: VERIFIED
|
|
7
|
+
Approved: Yes
|
|
8
|
+
Iterations: 0
|
|
9
|
+
Worktree: No
|
|
10
|
+
Type: Feature
|
|
11
|
+
|
|
12
|
+
## Summary
|
|
13
|
+
|
|
14
|
+
**Goal:** The library builds and publishes on `@mavogel/mvc-projen` 0.0.30 / `aws-cdk-lib` 2.263.0 / `cdk-nag` 3.x, with every cdk-nag suppression migrated to `Validations.of().acknowledge()` and proven effective by an un-skipped nag test.
|
|
15
|
+
|
|
16
|
+
## Out of Scope
|
|
17
|
+
|
|
18
|
+
- Adopting cdk-nag v3's `writeSuppressionsToCloudFormation` option. It is a *pack registration* flag, and this repo is a construct library that never registers the pack in shipped code — only a consuming app can set it. See Risks.
|
|
19
|
+
- Authoring a custom `NagPack`. The repo only consumes `AwsSolutionsChecks`, so the v3 `visit()` → `checkResource()` rewrite in the migration guide does not apply.
|
|
20
|
+
- Changing which rules are suppressed, or the security posture they encode. Reasons carry over verbatim; only the ID granularity changes.
|
|
21
|
+
|
|
22
|
+
## Approach
|
|
23
|
+
|
|
24
|
+
**Chosen:** Bump `cdkVersion` in `.projenrc.ts` and translate all 7 `NagSuppressions` call sites to `Validations.of(construct).acknowledge(...)` in one atomic change, then drive the exact acknowledgment IDs from a re-enabled nag test.
|
|
25
|
+
|
|
26
|
+
**Why:** cdk-nag v3 arrives automatically with mvc-projen 0.0.30 (which hardcodes `cdk-nag@^3.0.1`) and instantly breaks compilation, so the bump and the API migration cannot land separately — there is no green intermediate state. Splitting the *ID refinement* into its own task is possible because bare rule IDs compile fine; they are just ineffective for IAM4/IAM5, which the test then exposes. The cost is that Task 1's diff is large (toolchain + 6 source files + regenerated snapshots) and must be reviewed as one unit.
|
|
27
|
+
|
|
28
|
+
## Global Constraints
|
|
29
|
+
|
|
30
|
+
- `aws-cdk-lib` target: `2.263.0`. This becomes the published `peerDependencies` floor (`^2.263.0`).
|
|
31
|
+
- `constructs` floor: `^10.5.1` — the max of the two peer requirements: `node_modules/cdk-nag/package.json` `peerDependencies.constructs` is `^10.5.1`, and aws-cdk-lib 2.263.0's own is `^10.5.0`. `.projenrc.ts` currently declares `^10.4.2`.
|
|
32
|
+
- `package.json`, `tsconfig.json`, `.projen/*`, and all workflow files are **projen-generated**. Edit `.projenrc.ts` and run `npx projen`; never hand-edit the generated files.
|
|
33
|
+
- cdk-nag acknowledgment IDs are matched by **exact string equality** (`node_modules/cdk-nag/lib/nag-pack.js:141`, `ids.includes(ruleId)`). There is no prefix matching.
|
|
34
|
+
- Acknowledgment call shape: **one `Validations.of(construct).acknowledge({ id, reason })` call per (construct × rule) pair**, matching the examples in `node_modules/cdk-nag/MIGRATION.md:70-86`. `Validations` is imported from the `aws-cdk-lib` root.
|
|
35
|
+
|
|
36
|
+
## Context for Implementer
|
|
37
|
+
|
|
38
|
+
The working tree already carries a partial, non-working attempt at this bump from a prior `/fix` session: `@mavogel/mvc-projen@^0.0.30` is installed, `npx projen` has been run once (adding `projenrc/`, `tsconfig.json`, `test/tsconfig.json`, deleting `tsconfig.dev.json`), and `cdk-nag` resolved to 3.0.2 — which is why the build currently fails. Do not revert it; Task 1 builds forward from this state. `.projenrc.ts` itself is unmodified.
|
|
39
|
+
|
|
40
|
+
Two cdk-nag v3 semantics decide the whole migration, both verified by reading `node_modules/cdk-nag/lib/nag-pack.js`:
|
|
41
|
+
|
|
42
|
+
1. **Ancestor cascade is automatic.** `isAcknowledged` walks `current = current.node.scope` up the construct tree, so an acknowledgment on a parent covers all descendants. The v2 `applyToChildren` third argument (`true` at every call site here) has no v3 equivalent and simply drops.
|
|
43
|
+
2. **Findings-array rules need granular IDs.** When a rule returns an array rather than a `NagRuleCompliance`, the violation ID becomes `` `${ruleId}[${finding}]` `` (`nag-pack.js:87`). `AwsSolutions-IAM4` (`rules/iam/IAMNoManagedPolicies.js:28`) and `AwsSolutions-IAM5` (`rules/iam/IAMNoWildcardPermissions.js:29`) both do this, emitting IDs like `AwsSolutions-IAM4[Policy::arn:aws:iam::aws:policy/...]` and `AwsSolutions-IAM5[Resource::*]`. A bare `AwsSolutions-IAM5` acknowledgment matches **nothing**. `AwsSolutions-S1` and `AwsSolutions-S10` return plain compliance values, so their bare IDs work as-is.
|
|
44
|
+
|
|
45
|
+
Consequence: the exact IAM4/IAM5 finding IDs cannot be derived by reading code — they depend on the policies CDK generates. They must be harvested by running the pack (Task 2).
|
|
46
|
+
|
|
47
|
+
Do **not** collapse the 5-construct suppression arrays down to `this.provider` on the assumption that the cascade covers them. In `src/hosted-zone-dkim-propagation.ts:55-85` (and the sibling provider files) the handler functions are created as **siblings** of the `cr.Provider`, not children — `new NodejsFunction(this, 'is-complete-handler', …)` and `new cr.Provider(this, '…-provider', …)` share a scope. Translate one `acknowledge()` call per construct in each array.
|
|
48
|
+
|
|
49
|
+
## Runtime Environment
|
|
50
|
+
|
|
51
|
+
No running service. Verification is `npm run build` plus the Jest suite.
|
|
52
|
+
|
|
53
|
+
## Feature Inventory
|
|
54
|
+
|
|
55
|
+
Every `NagSuppressions` call site and its migration target. All 7 must be mapped; none are dropped.
|
|
56
|
+
|
|
57
|
+
| # | File:line | Constructs suppressed | Rule IDs | Granular IDs needed? |
|
|
58
|
+
|---|-----------|----------------------|----------|---------------------|
|
|
59
|
+
| 1 | `src/rootmail.ts:123` | `this.emailBucket` | S1, S10 | No — bare IDs match |
|
|
60
|
+
| 2 | `src/rootmail.ts:131` | `this.emailBucket.policy!` | S10 | No — bare ID matches |
|
|
61
|
+
| 3 | `src/ses-receive.ts:127` | `opsSantaFunctionRole` | IAM4, IAM5 | **Yes** |
|
|
62
|
+
| 4 | `src/rootmail-autowire-dns.ts:186` | provider, onEventHandler, its role, isCompleteHandler, its role (5) | IAM4, IAM5 | **Yes** |
|
|
63
|
+
| 5 | `src/hosted-zone-dkim-propagation.ts:87` | same 5-construct shape | IAM4, IAM5 | **Yes** |
|
|
64
|
+
| 6 | `src/hosted-zone-dkim-verification-records.ts:77` | provider, onEventHandler, its role (3) | IAM4, IAM5 | **Yes** |
|
|
65
|
+
| 7 | `src/ses-receipt-ruleset-activation.ts:113` | same 5-construct shape | IAM4, IAM5 | **Yes** |
|
|
66
|
+
|
|
67
|
+
Also migrating: `test/rootmail.test.ts:71` registers the pack via `Aspects.of(stack).add(new AwsSolutionsChecks({verbose: true}))` — v3 requires `new AwsSolutionsChecks(app, {verbose: true})` and `Validations.of(app).addPlugins(...)` / `validateScope(stack)`.
|
|
68
|
+
|
|
69
|
+
## Assumptions
|
|
70
|
+
|
|
71
|
+
- `AwsSolutionsChecks.validateScope(stack)` can be called directly from a Jest test without a full `app.synth()`, returning a `PolicyValidationPluginReport` whose `violations[].ruleName` carries the full granular ID. `validateScope` is documented as "the primary entry point for testing" (`nag-pack.d.ts:74-79`) and exists at `nag-pack.js:47`. Task 2 depends on this; if it proves false in practice, fall back to `app.synth()` and reading `policy-validation-report.json` from the cloud assembly.
|
|
72
|
+
- The `Validations` API details above were verified against a scratch install of aws-cdk-lib 2.263.0, since the currently-installed tree is 2.243.0 and predates `Validations` entirely. Task 1 re-confirms them the moment the bump lands and the code compiles.
|
|
73
|
+
- The v2→v3 upgrade drops the `Metadata.cdk_nag.rules_to_suppress` blocks currently present in the committed snapshots (158 in `rootmail.test.ts.snap`, 48 in `ses-receive.test.ts.snap`), because v3 writes acknowledgments to *construct* metadata (`aws:cdk:acknowledged-rules`) instead. Task 1 depends on this being an expected snapshot delta rather than a regression.
|
|
74
|
+
|
|
75
|
+
## Risks and Mitigations
|
|
76
|
+
|
|
77
|
+
| Risk | Likelihood | Impact | Mitigation |
|
|
78
|
+
|------|-----------|--------|------------|
|
|
79
|
+
| Consumers still on cdk-nag v2 lose this construct's suppressions, because the `cdk_nag` template metadata disappears and v2 reads only that | High | Medium | Document explicitly in README + CHANGELOG (Task 3) that cdk-nag v3 is now required to consume the bundled acknowledgments |
|
|
80
|
+
| Harvested granular IDs (e.g. `AwsSolutions-IAM5[Resource::<generated-arn>]`) embed CDK-generated values, so a future `aws-cdk-lib` bump silently reintroduces violations | Medium | Medium | The un-skipped Task 2 test fails loudly on the next bump instead of failing silently — this is the intended trade-off, recorded here so it is not "fixed" by re-skipping the test |
|
|
81
|
+
| Peer floor `^2.263.0` forces every consumer to upgrade aws-cdk-lib | High | Low | Unavoidable — cdk-nag v3 requires >=2.257.0; note it in the CHANGELOG as a breaking change (Task 3) |
|
|
82
|
+
|
|
83
|
+
## Progress Tracking
|
|
84
|
+
|
|
85
|
+
- [x] Task 1: Bump toolchain to mvc-projen 0.0.30 / aws-cdk-lib 2.263.0 and migrate all 7 suppression sites so the build compiles
|
|
86
|
+
- [x] Task 2: Re-enable the cdk-nag test against the v3 API and refine acknowledgments to exact finding IDs
|
|
87
|
+
- [x] Task 3: Document the consumer-visible breaking changes
|
|
88
|
+
- [x] Task 4: Record the scope gaps discovered while harvesting (IAM4 upstream bug, new v3 rule categories, non-portable IDs)
|
|
89
|
+
|
|
90
|
+
## Implementation Tasks
|
|
91
|
+
|
|
92
|
+
### Task 1: Bump toolchain and migrate suppression call sites
|
|
93
|
+
|
|
94
|
+
**Objective:** Move the project onto mvc-projen 0.0.30, aws-cdk-lib 2.263.0, and cdk-nag 3.x, and translate all 7 `NagSuppressions` call sites to `Validations.of(construct).acknowledge(...)` so that `npm run build` succeeds again. These land together because cdk-nag v3 arrives with the mvc-projen bump and removes the `NagSuppressions` export outright — there is no compiling intermediate state. Acknowledgment IDs stay as the current bare rule IDs here; Task 2 makes the IAM ones effective.
|
|
95
|
+
|
|
96
|
+
**Files:**
|
|
97
|
+
|
|
98
|
+
- Modify: `.projenrc.ts`
|
|
99
|
+
- Modify: `src/rootmail.ts`
|
|
100
|
+
- Modify: `src/ses-receive.ts`
|
|
101
|
+
- Modify: `src/rootmail-autowire-dns.ts`
|
|
102
|
+
- Modify: `src/hosted-zone-dkim-propagation.ts`
|
|
103
|
+
- Modify: `src/hosted-zone-dkim-verification-records.ts`
|
|
104
|
+
- Modify: `src/ses-receipt-ruleset-activation.ts`
|
|
105
|
+
- Modify: `test/__snapshots__/rootmail.test.ts.snap` (regenerated)
|
|
106
|
+
- Modify: `test/__snapshots__/ses-receive.test.ts.snap` (regenerated)
|
|
107
|
+
|
|
108
|
+
**Key Decisions / Notes:**
|
|
109
|
+
|
|
110
|
+
- `.projenrc.ts`: set `cdkVersion: '2.263.0'` and change the `deps` entry `'constructs@^10.4.2'` → `'constructs@^10.5.1'`. Do **not** add a `cdk-nag@…` pin to `bundledDeps` — mvc-projen re-adds `cdk-nag@^3.0.1` unconditionally after user options (`node_modules/@mavogel/mvc-projen/lib/projects/cdk-construct.js:274-275`), so a pin there is silently overridden. Leave `'cdk-nag'` unversioned in `bundledDeps`.
|
|
111
|
+
- Run `npx projen` after editing `.projenrc.ts`; it regenerates `package.json`, `tsconfig.json`, `.projen/*`, and the workflows. `@aws-cdk/integ-runner` auto-caps at `2.203.0` and the alpha packages normalize to `2.263.0-alpha.0` — all three versions are confirmed published.
|
|
112
|
+
- Per call site: replace one `NagSuppressions.addResourceSuppressions([a, b, c], [r1, r2], true)` with one `Validations.of(construct).acknowledge({ id, reason })` call per (construct × rule) pair — so a 5-construct × 2-rule site becomes 10 calls. Reasons carry over verbatim. The `true` third argument drops (cascade is now implicit). Per-rule calls are used rather than a single batched call because that is the shape cdk-nag's own migration guide documents; do not pass an array (`acknowledge([r1, r2])` is not supported).
|
|
113
|
+
- Swap the import: drop `import { NagSuppressions } from 'cdk-nag';` and add `Validations` to the existing `aws-cdk-lib` import in each of the 6 files. `Aspects` imports in `src/rootmail.ts:168` and `src/ses-receive.ts:187` serve `ApplyDestroyPolicyAspect` and must stay.
|
|
114
|
+
- Snapshots will lose all 206 `Metadata.cdk_nag` blocks (see Assumptions). Regenerate with `npx projen test -- -u` and skim the diff to confirm the removals are confined to `cdk_nag` metadata plus routine CDK-version drift — a change to actual resource properties is a regression, not drift.
|
|
115
|
+
|
|
116
|
+
**Definition of Done:**
|
|
117
|
+
|
|
118
|
+
- [x] `grep -rn "NagSuppressions" src/ test/` returns nothing.
|
|
119
|
+
- [x] `npm ls aws-cdk-lib cdk-nag constructs` reports aws-cdk-lib 2.263.0, cdk-nag 3.x, constructs >=10.5.1.
|
|
120
|
+
- [x] `package.json` `peerDependencies.aws-cdk-lib` is `^2.263.0`.
|
|
121
|
+
- [x] Regenerated snapshot diff: `Properties` changes are limited to asset references (`S3Key`, `SourceHash`), CDK-managed runtime/handler defaults, and custom-resource-framework assets. Any change to a property this construct sets explicitly — bucket policy, SES receipt rule, SSM parameter, IAM statements — is a regression and must be investigated before proceeding.
|
|
122
|
+
- [x] Verify: `npm run build` exits 0 (jsii compile, eslint, and the full Jest suite all green).
|
|
123
|
+
|
|
124
|
+
### Task 2: Re-enable the cdk-nag test and refine acknowledgments to exact finding IDs
|
|
125
|
+
|
|
126
|
+
**Objective:** Rewrite `test/rootmail.test.ts`'s nag block against cdk-nag v3's validation-plugin API, remove the `describe.skip`, use its output to harvest the exact granular finding IDs the IAM4/IAM5 rules emit, and update the five affected source files so the report comes back clean. This is what converts Task 1's bare IAM acknowledgments from decorative into effective.
|
|
127
|
+
|
|
128
|
+
**Files:**
|
|
129
|
+
|
|
130
|
+
- Modify: `test/rootmail.test.ts`
|
|
131
|
+
- Modify: `src/ses-receive.ts`
|
|
132
|
+
- Modify: `src/rootmail-autowire-dns.ts`
|
|
133
|
+
- Modify: `src/hosted-zone-dkim-propagation.ts`
|
|
134
|
+
- Modify: `src/hosted-zone-dkim-verification-records.ts`
|
|
135
|
+
- Modify: `src/ses-receipt-ruleset-activation.ts`
|
|
136
|
+
|
|
137
|
+
**Key Decisions / Notes:**
|
|
138
|
+
|
|
139
|
+
- Replace the v2 registration + `Annotations.fromStack()` assertions entirely — v3 emits no CDK Annotations (`MIGRATION.md:196-203`). Build the stack, then call `new AwsSolutionsChecks(app, { verbose: true }).validateScope(stack)` and assert on the returned report's `violations`.
|
|
140
|
+
- Collapse the two v2 tests (`No unsuppressed Warnings` / `No unsuppressed Errors`) into a single assertion that `violations` is empty; v3 reports both severities in one array. Drop the now-unused `Annotations`, `Match`, and `Aspects` imports if nothing else in the file uses them.
|
|
141
|
+
- On failure, print `violations.map(v => ({ id: v.ruleName, paths: v.violatingResources.map(r => r.constructPath) }))`. Field names are confirmed: `PolicyViolation.ruleName` and `PolicyViolatingResource.constructPath` exist on aws-cdk-lib 2.263.0's `core/lib/validation/report.d.ts`, and cdk-nag populates both (`nag-pack.js:111-114`, `constructPath: params.node.node.path`). If the first run prints `undefined` anyway, fall back to `JSON.stringify(report.violations, null, 2)` before guessing IDs.
|
|
142
|
+
- Add one additional `Validations.of(construct).acknowledge({ id: 'AwsSolutions-IAM5[...]', reason })` call per harvested finding ID, reusing that rule's existing reason string verbatim.
|
|
143
|
+
- **Remove the bare `AwsSolutions-IAM4` / `AwsSolutions-IAM5` acknowledgments** once the granular ones are in place. They match nothing today, but if a future cdk-nag release changes either rule to return a plain `NagRuleCompliance` instead of a findings array, the bare ID would begin blanket-suppressing every IAM4/IAM5 finding on that construct — silently widening the security posture this plan declares out of scope to change.
|
|
144
|
+
- Do not suppress a finding that the harvest surfaces on a construct outside the Feature Inventory's 7 sites. A new construct showing IAM violations is a finding to report, not to silence.
|
|
145
|
+
- Once green, check the reverse direction too: every acknowledgment added must correspond to a finding that appeared in the pre-fix harvest. An acknowledgment that never matched anything means the construct list is wrong (e.g. `cr.Provider`'s internal tree changed shape across the 60-version bump, making a handler a child rather than a sibling) — flag it rather than leaving dead entries.
|
|
146
|
+
- **Deviation from the approved DoD, discovered during implementation (documented per spec-implement's "surprise discovery" handling):** the harvest surfaced two problems the plan did not anticipate, both confirmed against real code/issues, not assumed:
|
|
147
|
+
1. **`AwsSolutions-IAM4[Policy::...]` is unacknowledgeable via the documented API at all.** aws-cdk-lib's `Validations.acknowledge()` (`qualifyId()`) throws `InvalidValidationId` for any id containing more than one `::`, and every AWS-managed-policy ARN contains one (`iam::aws:policy/...`). Confirmed as a currently-open upstream bug: cdklabs/cdk-nag#2359 and #2351. No IAM4 acknowledgment exists anywhere in `src/`.
|
|
148
|
+
2. **Granular `Resource::<value>` IDs are not portable across consumer deployments.** They embed either a CDK-generated logical id (unique per construct-tree shape, differs for any consumer who instantiates `Rootmail` under a different construct id) or, for the SSM parameter finding, the literal test account/region (`us-east-1:1234`). Acknowledging these in `src/` would silently suppress nothing for a real consumer. Only the portable forms — `Resource::*` and literal `Action::<name>` — are acknowledged.
|
|
149
|
+
3. The harvest also surfaced `AwsSolutions-L1` (nodejs18.x runtime deprecated), `AwsSolutions-SF1`/`SF2` (Step Functions logging/X-Ray on `cr.Provider`'s internal waiter state machine), and IAM4/IAM5 findings on the stack-level `LogRetention` singleton — none ever covered by the v2 suppressions (the v2 test was `describe.skip`ped, so these went unchecked). Out of scope for this plan; recorded as Task 4 follow-ups.
|
|
150
|
+
User-approved resolution: acknowledge only the portable, non-buggy IAM5 IDs; leave the rest genuinely unacknowledged; scope the test's assertion to the addressable subset instead of the full `violations` array.
|
|
151
|
+
|
|
152
|
+
**Definition of Done:**
|
|
153
|
+
|
|
154
|
+
- [x] `test/rootmail.test.ts` contains no `describe.skip` and no reference to `Annotations` or `Aspects` for nag purposes.
|
|
155
|
+
- [x] ~~The nag test asserts an empty `violations` array~~ — superseded by the deviation above: the test filters `report.violations` down to the addressable subset (IAM4/IAM5, portable IDs, outside `LogRetention`) and asserts that subset is empty; the full array retains expected findings from categories out of this plan's scope (Task 4).
|
|
156
|
+
- [x] Every acknowledgment added traces to a construct listed in the Feature Inventory, and every one matched a finding in the pre-fix harvest (no dead entries).
|
|
157
|
+
- [x] No bare `AwsSolutions-IAM4` / `AwsSolutions-IAM5` acknowledgment remains in `src/`.
|
|
158
|
+
- [x] Verify: `npx projen test` exits 0 with the nag test executed (not skipped).
|
|
159
|
+
|
|
160
|
+
### Task 3: Document the consumer-visible breaking changes
|
|
161
|
+
|
|
162
|
+
**Objective:** Record in the repo's docs that consuming this construct now requires aws-cdk-lib >=2.263.0 and cdk-nag v3, and that the bundled suppressions no longer appear as `cdk_nag` metadata in synthesized CloudFormation templates. Without this, a consumer on cdk-nag v2 silently starts seeing IAM4/IAM5 violations from this construct's resources with no explanation.
|
|
163
|
+
|
|
164
|
+
**Files:**
|
|
165
|
+
|
|
166
|
+
- Modify: `README.md`
|
|
167
|
+
- Modify: `CLAUDE.md`
|
|
168
|
+
|
|
169
|
+
**Key Decisions / Notes:**
|
|
170
|
+
|
|
171
|
+
- README: state the new `aws-cdk-lib` peer floor and that cdk-nag v3 is required for the bundled acknowledgments to apply. Keep it to the requirements/installation area — do not restructure surrounding prose.
|
|
172
|
+
- `CLAUDE.md` "Security and Compliance" says "CDK Nag suppressions documented with justifications"; update the mechanism name to `Validations.of().acknowledge()` so the repo guidance matches the code.
|
|
173
|
+
- Skip `API.md` — `grep -c "cdk-nag" API.md` is 0 and jsii-docgen regenerates it during build anyway.
|
|
174
|
+
- No CHANGELOG edit: releases are generated from conventional commits by the release workflow, so the breaking-change note belongs in the commit message, not a hand-edited file.
|
|
175
|
+
|
|
176
|
+
**Definition of Done:**
|
|
177
|
+
|
|
178
|
+
- [x] README names the `aws-cdk-lib` >=2.263.0 requirement and the cdk-nag v3 dependency.
|
|
179
|
+
- [x] No doc in the repo describes the *current* suppression mechanism as `NagSuppressions` — the one exception is the README's Known Issues entry, which correctly names `NagSuppressions` as the old API being replaced (necessary context, not a stale reference).
|
|
180
|
+
- [x] Verify: `grep -n "Validations.of(construct).acknowledge" README.md CLAUDE.md` returns a match in both files, confirming the current API is documented, not just the old one removed.
|
|
181
|
+
|
|
182
|
+
### Task 4: Record the scope gaps discovered while harvesting
|
|
183
|
+
|
|
184
|
+
**Objective:** Capture, in the codebase itself (not only this plan file), the three categories of cdk-nag findings this migration deliberately leaves unaddressed, so they are discoverable without re-reading `docs/plans/`. Task 2's Key Decisions documents the discovery and reasoning; this task makes it durable and points at concrete next steps.
|
|
185
|
+
|
|
186
|
+
**Files:**
|
|
187
|
+
|
|
188
|
+
- Modify: `README.md`
|
|
189
|
+
|
|
190
|
+
**Key Decisions / Notes:**
|
|
191
|
+
|
|
192
|
+
- Add a short subsection near the cdk-nag note from Task 3 (not a new top-level section) listing: (1) `AwsSolutions-IAM4[Policy::...]` findings cannot be acknowledged — link cdklabs/cdk-nag#2359 and #2351 as the upstream bug to watch; (2) `AwsSolutions-L1`/`SF1`/`SF2` and `LogRetention`-singleton findings are pre-existing gaps never checked before this migration (the v2 test was skipped) and are out of this plan's scope; (3) granular `Resource::<logical-id>` findings cannot be portably suppressed by a shared construct library under cdk-nag v3 at all — consumers who run cdk-nag themselves will see them and may acknowledge locally if desired.
|
|
193
|
+
- Do not open GitHub issues or file anything against cdklabs/cdk-nag as part of this task — linking the existing upstream issues is sufficient; filing new ones is a repo-maintainer decision outside this plan.
|
|
194
|
+
- Trivial: single doc addition, no new branch/loop/error path, no new public symbol — covered by the Task 4 DoD's grep check rather than a test.
|
|
195
|
+
|
|
196
|
+
**Definition of Done:**
|
|
197
|
+
|
|
198
|
+
- [x] README documents all three categories above with the two upstream issue references.
|
|
199
|
+
- [x] Verify: `grep -n "cdk-nag#2359\|cdk-nag#2351" README.md` returns a match.
|
|
@@ -27,7 +27,7 @@ const fullDomain = `${testSubdomain}.${testDomain}`;
|
|
|
27
27
|
const customSesReceiveFunction = new NodejsFunction(stackUnderTest, 'custom-ses-receive-function', {
|
|
28
28
|
functionName: PhysicalName.GENERATE_IF_NEEDED,
|
|
29
29
|
entry: path.join(__dirname, 'functions', 'custom-ses-receive-function.ts'),
|
|
30
|
-
runtime: lambda.Runtime.
|
|
30
|
+
runtime: lambda.Runtime.NODEJS_24_X,
|
|
31
31
|
logRetention: 1,
|
|
32
32
|
timeout: Duration.seconds(30),
|
|
33
33
|
});
|
|
@@ -75,7 +75,7 @@ const integ = new IntegTest(app, integStackName, {
|
|
|
75
75
|
const sendEmailHandler = new NodejsFunction(stackUnderTest, 'send-email-handler', {
|
|
76
76
|
functionName: PhysicalName.GENERATE_IF_NEEDED,
|
|
77
77
|
entry: path.join(__dirname, 'functions', 'send-email-handler.ts'),
|
|
78
|
-
runtime: lambda.Runtime.
|
|
78
|
+
runtime: lambda.Runtime.NODEJS_24_X,
|
|
79
79
|
logRetention: 1,
|
|
80
80
|
timeout: Duration.seconds(30),
|
|
81
81
|
initialPolicy: [
|
|
@@ -27,7 +27,7 @@ const fullDomain = `${testSubdomain}.${testDomain}`;
|
|
|
27
27
|
const customSesReceiveFunction = new NodejsFunction(stackUnderTest, 'custom-ses-receive-function', {
|
|
28
28
|
functionName: PhysicalName.GENERATE_IF_NEEDED,
|
|
29
29
|
entry: path.join(__dirname, 'functions', 'custom-ses-receive-function.ts'),
|
|
30
|
-
runtime: lambda.Runtime.
|
|
30
|
+
runtime: lambda.Runtime.NODEJS_24_X,
|
|
31
31
|
logRetention: 1,
|
|
32
32
|
timeout: Duration.seconds(30),
|
|
33
33
|
});
|
|
@@ -79,7 +79,7 @@ const integ = new IntegTest(app, integStackName, {
|
|
|
79
79
|
const sendEmailHandler = new NodejsFunction(stackUnderTest, 'send-email-handler', {
|
|
80
80
|
functionName: PhysicalName.GENERATE_IF_NEEDED,
|
|
81
81
|
entry: path.join(__dirname, 'functions', 'send-email-handler.ts'),
|
|
82
|
-
runtime: lambda.Runtime.
|
|
82
|
+
runtime: lambda.Runtime.NODEJS_24_X,
|
|
83
83
|
logRetention: 1,
|
|
84
84
|
timeout: Duration.seconds(30),
|
|
85
85
|
initialPolicy: [
|
|
@@ -59,7 +59,7 @@ const integ = new IntegTest(app, integStackName, {
|
|
|
59
59
|
const sendEmailHandler = new NodejsFunction(stackUnderTest, 'send-email-handler', {
|
|
60
60
|
functionName: PhysicalName.GENERATE_IF_NEEDED,
|
|
61
61
|
entry: path.join(__dirname, 'functions', 'send-email-handler.ts'),
|
|
62
|
-
runtime: lambda.Runtime.
|
|
62
|
+
runtime: lambda.Runtime.NODEJS_24_X,
|
|
63
63
|
logRetention: 1,
|
|
64
64
|
timeout: Duration.seconds(30),
|
|
65
65
|
initialPolicy: [
|
|
@@ -76,7 +76,7 @@ const sendEmailHandler = new NodejsFunction(stackUnderTest, 'send-email-handler'
|
|
|
76
76
|
const closeOpsItemHandler = new NodejsFunction(stackUnderTest, 'close-opsitem-handler', {
|
|
77
77
|
functionName: PhysicalName.GENERATE_IF_NEEDED,
|
|
78
78
|
entry: path.join(__dirname, 'functions', 'close-opsitem-handler.ts'),
|
|
79
|
-
runtime: lambda.Runtime.
|
|
79
|
+
runtime: lambda.Runtime.NODEJS_24_X,
|
|
80
80
|
logRetention: 1,
|
|
81
81
|
timeout: Duration.seconds(180),
|
|
82
82
|
initialPolicy: [
|
|
@@ -1,10 +1,42 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
2
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
36
|
exports.HostedZoneDKIMPropagation = void 0;
|
|
4
37
|
const aws_cdk_lib_1 = require("aws-cdk-lib");
|
|
5
38
|
const aws_lambda_nodejs_1 = require("aws-cdk-lib/aws-lambda-nodejs");
|
|
6
|
-
const cr = require("aws-cdk-lib/custom-resources");
|
|
7
|
-
const cdk_nag_1 = require("cdk-nag");
|
|
39
|
+
const cr = __importStar(require("aws-cdk-lib/custom-resources"));
|
|
8
40
|
const constructs_1 = require("constructs");
|
|
9
41
|
const hosted_zone_dkim_propagation_on_event_handler_1 = require("./hosted-zone-dkim-propagation.on-event-handler");
|
|
10
42
|
class HostedZoneDKIMPropagation extends constructs_1.Construct {
|
|
@@ -31,10 +63,11 @@ class HostedZoneDKIMPropagationProvider extends constructs_1.Construct {
|
|
|
31
63
|
|| new HostedZoneDKIMPropagationProvider(stack, id, props);
|
|
32
64
|
return x.provider.serviceToken;
|
|
33
65
|
}
|
|
66
|
+
provider;
|
|
34
67
|
constructor(scope, id, props) {
|
|
35
68
|
super(scope, id);
|
|
36
69
|
const isCompleteHandlerFunc = new aws_lambda_nodejs_1.NodejsFunction(this, 'is-complete-handler', {
|
|
37
|
-
runtime: aws_cdk_lib_1.aws_lambda.Runtime.
|
|
70
|
+
runtime: aws_cdk_lib_1.aws_lambda.Runtime.NODEJS_24_X,
|
|
38
71
|
logRetention: 1,
|
|
39
72
|
timeout: aws_cdk_lib_1.Duration.seconds(30),
|
|
40
73
|
});
|
|
@@ -49,7 +82,7 @@ class HostedZoneDKIMPropagationProvider extends constructs_1.Construct {
|
|
|
49
82
|
resources: ['*'],
|
|
50
83
|
}));
|
|
51
84
|
const onEventHandlerFunc = new aws_lambda_nodejs_1.NodejsFunction(this, 'on-event-handler', {
|
|
52
|
-
runtime: aws_cdk_lib_1.aws_lambda.Runtime.
|
|
85
|
+
runtime: aws_cdk_lib_1.aws_lambda.Runtime.NODEJS_24_X,
|
|
53
86
|
logRetention: 1,
|
|
54
87
|
timeout: aws_cdk_lib_1.Duration.seconds(10),
|
|
55
88
|
});
|
|
@@ -60,17 +93,15 @@ class HostedZoneDKIMPropagationProvider extends constructs_1.Construct {
|
|
|
60
93
|
onEventHandler: onEventHandlerFunc,
|
|
61
94
|
logRetention: 1,
|
|
62
95
|
});
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
{ id: 'AwsSolutions-IAM5', reason: 'wildcards are ok for the provider as the function has restrictions' },
|
|
72
|
-
], true);
|
|
96
|
+
// Granular findings only. Portable IDs only: Resource::* is constant across any deployment,
|
|
97
|
+
// Resource::<logical-id> findings are not. AwsSolutions-IAM4[Policy::...] cannot be
|
|
98
|
+
// acknowledged at all right now - aws-cdk-lib's Validations.acknowledge() rejects any id with
|
|
99
|
+
// more than one '::', and AWS managed policy ARNs always contain one (cdklabs/cdk-nag#2359,
|
|
100
|
+
// #2351, both open upstream). See docs/plans/2026-08-09-bump-mvc-projen-cdk-nag-v3.md Task 3.
|
|
101
|
+
const iam5ResourceStar = 'AwsSolutions-IAM5[Resource::*]';
|
|
102
|
+
const reasonIam5 = 'wildcards are ok for the provider as the function has restrictions';
|
|
103
|
+
aws_cdk_lib_1.Validations.of(this.provider.isCompleteHandler).acknowledge({ id: iam5ResourceStar, reason: reasonIam5 });
|
|
73
104
|
}
|
|
74
105
|
;
|
|
75
106
|
}
|
|
76
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
107
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaG9zdGVkLXpvbmUtZGtpbS1wcm9wYWdhdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9ob3N0ZWQtem9uZS1ka2ltLXByb3BhZ2F0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLDZDQU9xQjtBQUNyQixxRUFBK0Q7QUFDL0QsaUVBQW1EO0FBQ25ELDJDQUE2QztBQUM3QyxtSEFBOEU7QUFPOUUsTUFBYSx5QkFBMEIsU0FBUSxzQkFBUztJQUN0RCxZQUFZLEtBQWdCLEVBQUUsRUFBVSxFQUFFLEtBQXFDO1FBQzdFLEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFFakIsSUFBSSw0QkFBYyxDQUFDLElBQUksRUFBRSxVQUFVLEVBQUU7WUFDbkMsWUFBWSxFQUFFLGlDQUFpQyxDQUFDLFdBQVcsQ0FBQyxJQUFJLEVBQUUsRUFBRSxrQkFBa0IsRUFBRSxLQUFLLENBQUMsa0JBQWtCLEVBQUUsQ0FBQztZQUNuSCxZQUFZLEVBQUUsbUNBQW1DO1lBQ2pELFVBQVUsRUFBRTtnQkFDVixDQUFDLDJEQUFXLENBQUMsRUFBRSxLQUFLLENBQUMsTUFBTTthQUM1QjtTQUNGLENBQUMsQ0FBQztJQUNMLENBQUM7Q0FDRjtBQVpELDhEQVlDO0FBTUQsTUFBTSxpQ0FBa0MsU0FBUSxzQkFBUztJQUV2RDs7T0FFRztJQUNJLE1BQU0sQ0FBQyxXQUFXLENBQUMsS0FBZ0IsRUFBRSxLQUE2QztRQUN2RixNQUFNLEtBQUssR0FBRyxtQkFBSyxDQUFDLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUM5QixNQUFNLEVBQUUsR0FBRyxnREFBZ0QsQ0FBQztRQUM1RCxNQUFNLENBQUMsR0FBRyxpQkFBSSxDQUFDLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxZQUFZLENBQUMsRUFBRSxDQUFzQztlQUN6RSxJQUFJLGlDQUFpQyxDQUFDLEtBQUssRUFBRSxFQUFFLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDN0QsT0FBTyxDQUFDLENBQUMsUUFBUSxDQUFDLFlBQVksQ0FBQztJQUNqQyxDQUFDO0lBRWdCLFFBQVEsQ0FBYztJQUV2QyxZQUFZLEtBQWdCLEVBQUUsRUFBVSxFQUFFLEtBQTZDO1FBQ3JGLEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFFakIsTUFBTSxxQkFBcUIsR0FBRyxJQUFJLGtDQUFjLENBQUMsSUFBSSxFQUFFLHFCQUFxQixFQUFFO1lBQzVFLE9BQU8sRUFBRSx3QkFBTSxDQUFDLE9BQU8sQ0FBQyxXQUFXO1lBQ25DLFlBQVksRUFBRSxDQUFDO1lBQ2YsT0FBTyxFQUFFLHNCQUFRLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztTQUM5QixDQUFDLENBQUM7UUFFSCxxQkFBcUIsQ0FBQyxlQUFlLENBQ25DLElBQUkscUJBQUcsQ0FBQyxlQUFlLENBQUM7WUFDdEIsT0FBTyxFQUFFO2dCQUNQLHVDQUF1QztnQkFDdkMsOEJBQThCO2dCQUM5QiwrQkFBK0I7Z0JBQy9CLHVDQUF1QzthQUN4QztZQUNELE1BQU0sRUFBRSxxQkFBRyxDQUFDLE1BQU0sQ0FBQyxLQUFLO1lBQ3hCLFNBQVMsRUFBRSxDQUFDLEdBQUcsQ0FBQztTQUNqQixDQUFDLENBQ0gsQ0FBQztRQUVGLE1BQU0sa0JBQWtCLEdBQUcsSUFBSSxrQ0FBYyxDQUFDLElBQUksRUFBRSxrQkFBa0IsRUFBRTtZQUN0RSxPQUFPLEVBQUUsd0JBQU0sQ0FBQyxPQUFPLENBQUMsV0FBVztZQUNuQyxZQUFZLEVBQUUsQ0FBQztZQUNmLE9BQU8sRUFBRSxzQkFBUSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7U0FDOUIsQ0FBQyxDQUFDO1FBRUgsSUFBSSxDQUFDLFFBQVEsR0FBRyxJQUFJLEVBQUUsQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLHVDQUF1QyxFQUFFO1lBQzdFLGlCQUFpQixFQUFFLHFCQUFxQjtZQUN4QyxhQUFhLEVBQUUsc0JBQVEsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDO1lBQ25DLFlBQVksRUFBRSxLQUFLLENBQUMsa0JBQWtCO1lBQ3RDLGNBQWMsRUFBRSxrQkFBa0I7WUFDbEMsWUFBWSxFQUFFLENBQUM7U0FDaEIsQ0FBQyxDQUFDO1FBQ0gsNEZBQTRGO1FBQzVGLG9GQUFvRjtRQUNwRiw4RkFBOEY7UUFDOUYsNEZBQTRGO1FBQzVGLDhGQUE4RjtRQUM5RixNQUFNLGdCQUFnQixHQUFHLGdDQUFnQyxDQUFDO1FBQzFELE1BQU0sVUFBVSxHQUFHLG9FQUFvRSxDQUFDO1FBRXhGLHlCQUFXLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsaUJBQWtCLENBQUMsQ0FBQyxXQUFXLENBQUMsRUFBRSxFQUFFLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBRSxDQUFDLENBQUM7SUFDN0csQ0FBQztJQUFBLENBQUM7Q0FDSCIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIEN1c3RvbVJlc291cmNlLFxuICBEdXJhdGlvbixcbiAgU3RhY2ssXG4gIGF3c19pYW0gYXMgaWFtLFxuICBhd3NfbGFtYmRhIGFzIGxhbWJkYSxcbiAgVmFsaWRhdGlvbnMsXG59IGZyb20gJ2F3cy1jZGstbGliJztcbmltcG9ydCB7IE5vZGVqc0Z1bmN0aW9uIH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWxhbWJkYS1ub2RlanMnO1xuaW1wb3J0ICogYXMgY3IgZnJvbSAnYXdzLWNkay1saWIvY3VzdG9tLXJlc291cmNlcyc7XG5pbXBvcnQgeyBDb25zdHJ1Y3QsIE5vZGUgfSBmcm9tICdjb25zdHJ1Y3RzJztcbmltcG9ydCB7IFBST1BfRE9NQUlOIH0gZnJvbSAnLi9ob3N0ZWQtem9uZS1ka2ltLXByb3BhZ2F0aW9uLm9uLWV2ZW50LWhhbmRsZXInO1xuXG5leHBvcnQgaW50ZXJmYWNlIEhvc3RlZFpvbmVES0lNUHJvcGFnYXRpb25Qcm9wcyB7XG4gIHJlYWRvbmx5IGRvbWFpbjogc3RyaW5nO1xuICByZWFkb25seSB0b3RhbFRpbWVUb1dpcmVETlM/OiBEdXJhdGlvbjtcbn1cblxuZXhwb3J0IGNsYXNzIEhvc3RlZFpvbmVES0lNUHJvcGFnYXRpb24gZXh0ZW5kcyBDb25zdHJ1Y3Qge1xuICBjb25zdHJ1Y3RvcihzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBwcm9wczogSG9zdGVkWm9uZURLSU1Qcm9wYWdhdGlvblByb3BzKSB7XG4gICAgc3VwZXIoc2NvcGUsIGlkKTtcblxuICAgIG5ldyBDdXN0b21SZXNvdXJjZSh0aGlzLCAnUmVzb3VyY2UnLCB7XG4gICAgICBzZXJ2aWNlVG9rZW46IEhvc3RlZFpvbmVES0lNUHJvcGFnYXRpb25Qcm92aWRlci5nZXRPckNyZWF0ZSh0aGlzLCB7IHRvdGFsVGltZVRvV2lyZUROUzogcHJvcHMudG90YWxUaW1lVG9XaXJlRE5TIH0pLFxuICAgICAgcmVzb3VyY2VUeXBlOiAnQ3VzdG9tOjpIb3N0ZWRab25lREtJTVByb3BhZ2F0aW9uJyxcbiAgICAgIHByb3BlcnRpZXM6IHtcbiAgICAgICAgW1BST1BfRE9NQUlOXTogcHJvcHMuZG9tYWluLFxuICAgICAgfSxcbiAgICB9KTtcbiAgfVxufVxuXG5pbnRlcmZhY2UgSG9zdGVkWm9uZURLSU1Qcm9wYWdhdGlvblByb3ZpZGVyUHJvcHMge1xuICByZWFkb25seSB0b3RhbFRpbWVUb1dpcmVETlM/OiBEdXJhdGlvbjtcbn1cblxuY2xhc3MgSG9zdGVkWm9uZURLSU1Qcm9wYWdhdGlvblByb3ZpZGVyIGV4dGVuZHMgQ29uc3RydWN0IHtcblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgc2luZ2xldG9uIHByb3ZpZGVyLlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBnZXRPckNyZWF0ZShzY29wZTogQ29uc3RydWN0LCBwcm9wczogSG9zdGVkWm9uZURLSU1Qcm9wYWdhdGlvblByb3ZpZGVyUHJvcHMpIHtcbiAgICBjb25zdCBzdGFjayA9IFN0YWNrLm9mKHNjb3BlKTtcbiAgICBjb25zdCBpZCA9ICdyb290bWFpbC5ob3N0ZWQtem9uZS1ka2ltLXByb3BhZ2F0aW9uLXByb3ZpZGVyJztcbiAgICBjb25zdCB4ID0gTm9kZS5vZihzdGFjaykudHJ5RmluZENoaWxkKGlkKSBhcyBIb3N0ZWRab25lREtJTVByb3BhZ2F0aW9uUHJvdmlkZXJcbiAgICAgIHx8IG5ldyBIb3N0ZWRab25lREtJTVByb3BhZ2F0aW9uUHJvdmlkZXIoc3RhY2ssIGlkLCBwcm9wcyk7XG4gICAgcmV0dXJuIHgucHJvdmlkZXIuc2VydmljZVRva2VuO1xuICB9XG5cbiAgcHJpdmF0ZSByZWFkb25seSBwcm92aWRlcjogY3IuUHJvdmlkZXI7XG5cbiAgY29uc3RydWN0b3Ioc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgcHJvcHM6IEhvc3RlZFpvbmVES0lNUHJvcGFnYXRpb25Qcm92aWRlclByb3BzKSB7XG4gICAgc3VwZXIoc2NvcGUsIGlkKTtcblxuICAgIGNvbnN0IGlzQ29tcGxldGVIYW5kbGVyRnVuYyA9IG5ldyBOb2RlanNGdW5jdGlvbih0aGlzLCAnaXMtY29tcGxldGUtaGFuZGxlcicsIHtcbiAgICAgIHJ1bnRpbWU6IGxhbWJkYS5SdW50aW1lLk5PREVKU18yNF9YLFxuICAgICAgbG9nUmV0ZW50aW9uOiAxLFxuICAgICAgdGltZW91dDogRHVyYXRpb24uc2Vjb25kcygzMCksXG4gICAgfSk7XG5cbiAgICBpc0NvbXBsZXRlSGFuZGxlckZ1bmMuYWRkVG9Sb2xlUG9saWN5KFxuICAgICAgbmV3IGlhbS5Qb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgICBhY3Rpb25zOiBbXG4gICAgICAgICAgJ3NlczpHZXRJZGVudGl0eVZlcmlmaWNhdGlvbkF0dHJpYnV0ZXMnLFxuICAgICAgICAgICdzZXM6R2V0QWNjb3VudFNlbmRpbmdFbmFibGVkJyxcbiAgICAgICAgICAnc2VzOkdldElkZW50aXR5RGtpbUF0dHJpYnV0ZXMnLFxuICAgICAgICAgICdzZXM6R2V0SWRlbnRpdHlOb3RpZmljYXRpb25BdHRyaWJ1dGVzJyxcbiAgICAgICAgXSxcbiAgICAgICAgZWZmZWN0OiBpYW0uRWZmZWN0LkFMTE9XLFxuICAgICAgICByZXNvdXJjZXM6IFsnKiddLFxuICAgICAgfSksXG4gICAgKTtcblxuICAgIGNvbnN0IG9uRXZlbnRIYW5kbGVyRnVuYyA9IG5ldyBOb2RlanNGdW5jdGlvbih0aGlzLCAnb24tZXZlbnQtaGFuZGxlcicsIHtcbiAgICAgIHJ1bnRpbWU6IGxhbWJkYS5SdW50aW1lLk5PREVKU18yNF9YLFxuICAgICAgbG9nUmV0ZW50aW9uOiAxLFxuICAgICAgdGltZW91dDogRHVyYXRpb24uc2Vjb25kcygxMCksXG4gICAgfSk7XG5cbiAgICB0aGlzLnByb3ZpZGVyID0gbmV3IGNyLlByb3ZpZGVyKHRoaXMsICdob3N0ZWQtem9uZS1ka2ltLXByb3BhZ2F0aW9uLXByb3ZpZGVyJywge1xuICAgICAgaXNDb21wbGV0ZUhhbmRsZXI6IGlzQ29tcGxldGVIYW5kbGVyRnVuYyxcbiAgICAgIHF1ZXJ5SW50ZXJ2YWw6IER1cmF0aW9uLnNlY29uZHMoMTApLFxuICAgICAgdG90YWxUaW1lb3V0OiBwcm9wcy50b3RhbFRpbWVUb1dpcmVETlMsXG4gICAgICBvbkV2ZW50SGFuZGxlcjogb25FdmVudEhhbmRsZXJGdW5jLFxuICAgICAgbG9nUmV0ZW50aW9uOiAxLFxuICAgIH0pO1xuICAgIC8vIEdyYW51bGFyIGZpbmRpbmdzIG9ubHkuIFBvcnRhYmxlIElEcyBvbmx5OiBSZXNvdXJjZTo6KiBpcyBjb25zdGFudCBhY3Jvc3MgYW55IGRlcGxveW1lbnQsXG4gICAgLy8gUmVzb3VyY2U6Ojxsb2dpY2FsLWlkPiBmaW5kaW5ncyBhcmUgbm90LiBBd3NTb2x1dGlvbnMtSUFNNFtQb2xpY3k6Oi4uLl0gY2Fubm90IGJlXG4gICAgLy8gYWNrbm93bGVkZ2VkIGF0IGFsbCByaWdodCBub3cgLSBhd3MtY2RrLWxpYidzIFZhbGlkYXRpb25zLmFja25vd2xlZGdlKCkgcmVqZWN0cyBhbnkgaWQgd2l0aFxuICAgIC8vIG1vcmUgdGhhbiBvbmUgJzo6JywgYW5kIEFXUyBtYW5hZ2VkIHBvbGljeSBBUk5zIGFsd2F5cyBjb250YWluIG9uZSAoY2RrbGFicy9jZGstbmFnIzIzNTksXG4gICAgLy8gIzIzNTEsIGJvdGggb3BlbiB1cHN0cmVhbSkuIFNlZSBkb2NzL3BsYW5zLzIwMjYtMDgtMDktYnVtcC1tdmMtcHJvamVuLWNkay1uYWctdjMubWQgVGFzayAzLlxuICAgIGNvbnN0IGlhbTVSZXNvdXJjZVN0YXIgPSAnQXdzU29sdXRpb25zLUlBTTVbUmVzb3VyY2U6OipdJztcbiAgICBjb25zdCByZWFzb25JYW01ID0gJ3dpbGRjYXJkcyBhcmUgb2sgZm9yIHRoZSBwcm92aWRlciBhcyB0aGUgZnVuY3Rpb24gaGFzIHJlc3RyaWN0aW9ucyc7XG5cbiAgICBWYWxpZGF0aW9ucy5vZih0aGlzLnByb3ZpZGVyLmlzQ29tcGxldGVIYW5kbGVyISkuYWNrbm93bGVkZ2UoeyBpZDogaWFtNVJlc291cmNlU3RhciwgcmVhc29uOiByZWFzb25JYW01IH0pO1xuICB9O1xufVxuXG4iXX0=
|
|
@@ -1,13 +1,47 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
2
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
36
|
exports.HostedZoneDKIMAndVerificationRecords = void 0;
|
|
4
37
|
const aws_cdk_lib_1 = require("aws-cdk-lib");
|
|
5
38
|
const aws_lambda_nodejs_1 = require("aws-cdk-lib/aws-lambda-nodejs");
|
|
6
|
-
const cr = require("aws-cdk-lib/custom-resources");
|
|
7
|
-
const cdk_nag_1 = require("cdk-nag");
|
|
39
|
+
const cr = __importStar(require("aws-cdk-lib/custom-resources"));
|
|
8
40
|
const constructs_1 = require("constructs");
|
|
9
41
|
const hosted_zone_dkim_verification_records_on_event_handler_1 = require("./hosted-zone-dkim-verification-records.on-event-handler");
|
|
10
42
|
class HostedZoneDKIMAndVerificationRecords extends constructs_1.Construct {
|
|
43
|
+
verificationToken;
|
|
44
|
+
dkimTokens;
|
|
11
45
|
constructor(scope, id, props) {
|
|
12
46
|
super(scope, id);
|
|
13
47
|
const resource = new aws_cdk_lib_1.CustomResource(this, 'Resource', {
|
|
@@ -33,10 +67,11 @@ class HostedZoneDKIMAndVerificationRecordsProvider extends constructs_1.Construc
|
|
|
33
67
|
|| new HostedZoneDKIMAndVerificationRecordsProvider(stack, id);
|
|
34
68
|
return x.provider.serviceToken;
|
|
35
69
|
}
|
|
70
|
+
provider;
|
|
36
71
|
constructor(scope, id) {
|
|
37
72
|
super(scope, id);
|
|
38
73
|
const onEventHandlerFunc = new aws_lambda_nodejs_1.NodejsFunction(this, 'on-event-handler', {
|
|
39
|
-
runtime: aws_cdk_lib_1.aws_lambda.Runtime.
|
|
74
|
+
runtime: aws_cdk_lib_1.aws_lambda.Runtime.NODEJS_24_X,
|
|
40
75
|
logRetention: 1,
|
|
41
76
|
timeout: aws_cdk_lib_1.Duration.seconds(200),
|
|
42
77
|
});
|
|
@@ -52,15 +87,15 @@ class HostedZoneDKIMAndVerificationRecordsProvider extends constructs_1.Construc
|
|
|
52
87
|
onEventHandler: onEventHandlerFunc,
|
|
53
88
|
logRetention: 1,
|
|
54
89
|
});
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
90
|
+
// Granular findings only. Portable IDs only: Resource::* is constant across any deployment,
|
|
91
|
+
// Resource::<logical-id> findings are not. AwsSolutions-IAM4[Policy::...] cannot be
|
|
92
|
+
// acknowledged at all right now - aws-cdk-lib's Validations.acknowledge() rejects any id with
|
|
93
|
+
// more than one '::', and AWS managed policy ARNs always contain one (cdklabs/cdk-nag#2359,
|
|
94
|
+
// #2351, both open upstream). See docs/plans/2026-08-09-bump-mvc-projen-cdk-nag-v3.md Task 3.
|
|
95
|
+
const iam5ResourceStar = 'AwsSolutions-IAM5[Resource::*]';
|
|
96
|
+
const reasonIam5 = 'wildcards are ok for the provider as the function has restrictions';
|
|
97
|
+
aws_cdk_lib_1.Validations.of(this.provider.onEventHandler).acknowledge({ id: iam5ResourceStar, reason: reasonIam5 });
|
|
63
98
|
}
|
|
64
99
|
;
|
|
65
100
|
}
|
|
66
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
101
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaG9zdGVkLXpvbmUtZGtpbS12ZXJpZmljYXRpb24tcmVjb3Jkcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9ob3N0ZWQtem9uZS1ka2ltLXZlcmlmaWNhdGlvbi1yZWNvcmRzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLDZDQU9xQjtBQUNyQixxRUFBK0Q7QUFDL0QsaUVBQW1EO0FBQ25ELDJDQUE2QztBQUM3QyxxSUFBa0k7QUFNbEksTUFBYSxvQ0FBcUMsU0FBUSxzQkFBUztJQUNqRCxpQkFBaUIsQ0FBUztJQUMxQixVQUFVLENBQVc7SUFFckMsWUFBWSxLQUFnQixFQUFFLEVBQVUsRUFBRSxLQUFnRDtRQUN4RixLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBRWpCLE1BQU0sUUFBUSxHQUFHLElBQUksNEJBQWMsQ0FBQyxJQUFJLEVBQUUsVUFBVSxFQUFFO1lBQ3BELFlBQVksRUFBRSw0Q0FBNEMsQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDO1lBQzVFLFlBQVksRUFBRSw4Q0FBOEM7WUFDNUQsVUFBVSxFQUFFO2dCQUNWLENBQUMsb0VBQVcsQ0FBQyxFQUFFLEtBQUssQ0FBQyxNQUFNO2FBQzVCO1NBQ0YsQ0FBQyxDQUFDO1FBRUgsSUFBSSxDQUFDLGlCQUFpQixHQUFHLFFBQVEsQ0FBQyxZQUFZLENBQUMsZ0ZBQXVCLENBQUMsQ0FBQztRQUN4RSxJQUFJLENBQUMsVUFBVSxHQUFHLFFBQVEsQ0FBQyxNQUFNLENBQUMseUVBQWdCLENBQUMsQ0FBQyxZQUFZLEVBQUUsQ0FBQztJQUNyRSxDQUFDO0NBQ0Y7QUFsQkQsb0ZBa0JDO0FBRUQsTUFBTSw0Q0FBNkMsU0FBUSxzQkFBUztJQUVsRTs7T0FFRztJQUNJLE1BQU0sQ0FBQyxXQUFXLENBQUMsS0FBZ0I7UUFDeEMsTUFBTSxLQUFLLEdBQUcsbUJBQUssQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDOUIsTUFBTSxFQUFFLEdBQUcseURBQXlELENBQUM7UUFDckUsTUFBTSxDQUFDLEdBQUcsaUJBQUksQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLENBQUMsWUFBWSxDQUFDLEVBQUUsQ0FBaUQ7ZUFDcEYsSUFBSSw0Q0FBNEMsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFDakUsT0FBTyxDQUFDLENBQUMsUUFBUSxDQUFDLFlBQVksQ0FBQztJQUNqQyxDQUFDO0lBRWdCLFFBQVEsQ0FBYztJQUV2QyxZQUFZLEtBQWdCLEVBQUUsRUFBVTtRQUN0QyxLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBRWpCLE1BQU0sa0JBQWtCLEdBQUcsSUFBSSxrQ0FBYyxDQUFDLElBQUksRUFBRSxrQkFBa0IsRUFBRTtZQUN0RSxPQUFPLEVBQUUsd0JBQU0sQ0FBQyxPQUFPLENBQUMsV0FBVztZQUNuQyxZQUFZLEVBQUUsQ0FBQztZQUNmLE9BQU8sRUFBRSxzQkFBUSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUM7U0FDL0IsQ0FBQyxDQUFDO1FBRUgsa0JBQWtCLENBQUMsZUFBZSxDQUNoQyxJQUFJLHFCQUFHLENBQUMsZUFBZSxDQUFDO1lBQ3RCLE9BQU8sRUFBRTtnQkFDUCxzQkFBc0I7Z0JBQ3RCLDBCQUEwQjtnQkFDMUIsb0JBQW9CO2FBQ3JCO1lBQ0QsU0FBUyxFQUFFLENBQUMsR0FBRyxDQUFDO1NBQ2pCLENBQUMsQ0FDSCxDQUFDO1FBRUYsSUFBSSxDQUFDLFFBQVEsR0FBRyxJQUFJLEVBQUUsQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLGdEQUFnRCxFQUFFO1lBQ3RGLGNBQWMsRUFBRSxrQkFBa0I7WUFDbEMsWUFBWSxFQUFFLENBQUM7U0FDaEIsQ0FBQyxDQUFDO1FBQ0gsNEZBQTRGO1FBQzVGLG9GQUFvRjtRQUNwRiw4RkFBOEY7UUFDOUYsNEZBQTRGO1FBQzVGLDhGQUE4RjtRQUM5RixNQUFNLGdCQUFnQixHQUFHLGdDQUFnQyxDQUFDO1FBQzFELE1BQU0sVUFBVSxHQUFHLG9FQUFvRSxDQUFDO1FBRXhGLHlCQUFXLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsY0FBYyxDQUFDLENBQUMsV0FBVyxDQUFDLEVBQUUsRUFBRSxFQUFFLGdCQUFnQixFQUFFLE1BQU0sRUFBRSxVQUFVLEVBQUUsQ0FBQyxDQUFDO0lBQ3pHLENBQUM7SUFBQSxDQUFDO0NBQ0giLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBDdXN0b21SZXNvdXJjZSxcbiAgRHVyYXRpb24sXG4gIFN0YWNrLFxuICBhd3NfaWFtIGFzIGlhbSxcbiAgYXdzX2xhbWJkYSBhcyBsYW1iZGEsXG4gIFZhbGlkYXRpb25zLFxufSBmcm9tICdhd3MtY2RrLWxpYic7XG5pbXBvcnQgeyBOb2RlanNGdW5jdGlvbiB9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1sYW1iZGEtbm9kZWpzJztcbmltcG9ydCAqIGFzIGNyIGZyb20gJ2F3cy1jZGstbGliL2N1c3RvbS1yZXNvdXJjZXMnO1xuaW1wb3J0IHsgQ29uc3RydWN0LCBOb2RlIH0gZnJvbSAnY29uc3RydWN0cyc7XG5pbXBvcnQgeyBBVFRSX1ZFUklGSUNBVElPTl9UT0tFTiwgQVRUUl9ES0lNX1RPS0VOUywgUFJPUF9ET01BSU4gfSBmcm9tICcuL2hvc3RlZC16b25lLWRraW0tdmVyaWZpY2F0aW9uLXJlY29yZHMub24tZXZlbnQtaGFuZGxlcic7XG5cbmV4cG9ydCBpbnRlcmZhY2UgSG9zdGVkWm9uZURLSU1BbmRWZXJpZmljYXRpb25SZWNvcmRzUHJvcHMge1xuICByZWFkb25seSBkb21haW46IHN0cmluZztcbn1cblxuZXhwb3J0IGNsYXNzIEhvc3RlZFpvbmVES0lNQW5kVmVyaWZpY2F0aW9uUmVjb3JkcyBleHRlbmRzIENvbnN0cnVjdCB7XG4gIHB1YmxpYyByZWFkb25seSB2ZXJpZmljYXRpb25Ub2tlbjogc3RyaW5nO1xuICBwdWJsaWMgcmVhZG9ubHkgZGtpbVRva2Vuczogc3RyaW5nW107XG5cbiAgY29uc3RydWN0b3Ioc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgcHJvcHM6IEhvc3RlZFpvbmVES0lNQW5kVmVyaWZpY2F0aW9uUmVjb3Jkc1Byb3BzKSB7XG4gICAgc3VwZXIoc2NvcGUsIGlkKTtcblxuICAgIGNvbnN0IHJlc291cmNlID0gbmV3IEN1c3RvbVJlc291cmNlKHRoaXMsICdSZXNvdXJjZScsIHtcbiAgICAgIHNlcnZpY2VUb2tlbjogSG9zdGVkWm9uZURLSU1BbmRWZXJpZmljYXRpb25SZWNvcmRzUHJvdmlkZXIuZ2V0T3JDcmVhdGUodGhpcyksXG4gICAgICByZXNvdXJjZVR5cGU6ICdDdXN0b206Okhvc3RlZFpvbmVES0lNQW5kVmVyaWZpY2F0aW9uUmVjb3JkcycsXG4gICAgICBwcm9wZXJ0aWVzOiB7XG4gICAgICAgIFtQUk9QX0RPTUFJTl06IHByb3BzLmRvbWFpbixcbiAgICAgIH0sXG4gICAgfSk7XG5cbiAgICB0aGlzLnZlcmlmaWNhdGlvblRva2VuID0gcmVzb3VyY2UuZ2V0QXR0U3RyaW5nKEFUVFJfVkVSSUZJQ0FUSU9OX1RPS0VOKTtcbiAgICB0aGlzLmRraW1Ub2tlbnMgPSByZXNvdXJjZS5nZXRBdHQoQVRUUl9ES0lNX1RPS0VOUykudG9TdHJpbmdMaXN0KCk7XG4gIH1cbn1cblxuY2xhc3MgSG9zdGVkWm9uZURLSU1BbmRWZXJpZmljYXRpb25SZWNvcmRzUHJvdmlkZXIgZXh0ZW5kcyBDb25zdHJ1Y3Qge1xuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBzaW5nbGV0b24gcHJvdmlkZXIuXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGdldE9yQ3JlYXRlKHNjb3BlOiBDb25zdHJ1Y3QpIHtcbiAgICBjb25zdCBzdGFjayA9IFN0YWNrLm9mKHNjb3BlKTtcbiAgICBjb25zdCBpZCA9ICdyb290bWFpbC5ob3N0ZWQtem9uZS1ka2ltLXZlcmlmaWNhdGlvbi1yZWNvcmRzLXByb3ZpZGVyJztcbiAgICBjb25zdCB4ID0gTm9kZS5vZihzdGFjaykudHJ5RmluZENoaWxkKGlkKSBhcyBIb3N0ZWRab25lREtJTUFuZFZlcmlmaWNhdGlvblJlY29yZHNQcm92aWRlclxuICAgICAgfHwgbmV3IEhvc3RlZFpvbmVES0lNQW5kVmVyaWZpY2F0aW9uUmVjb3Jkc1Byb3ZpZGVyKHN0YWNrLCBpZCk7XG4gICAgcmV0dXJuIHgucHJvdmlkZXIuc2VydmljZVRva2VuO1xuICB9XG5cbiAgcHJpdmF0ZSByZWFkb25seSBwcm92aWRlcjogY3IuUHJvdmlkZXI7XG5cbiAgY29uc3RydWN0b3Ioc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZykge1xuICAgIHN1cGVyKHNjb3BlLCBpZCk7XG5cbiAgICBjb25zdCBvbkV2ZW50SGFuZGxlckZ1bmMgPSBuZXcgTm9kZWpzRnVuY3Rpb24odGhpcywgJ29uLWV2ZW50LWhhbmRsZXInLCB7XG4gICAgICBydW50aW1lOiBsYW1iZGEuUnVudGltZS5OT0RFSlNfMjRfWCxcbiAgICAgIGxvZ1JldGVudGlvbjogMSxcbiAgICAgIHRpbWVvdXQ6IER1cmF0aW9uLnNlY29uZHMoMjAwKSxcbiAgICB9KTtcblxuICAgIG9uRXZlbnRIYW5kbGVyRnVuYy5hZGRUb1JvbGVQb2xpY3koXG4gICAgICBuZXcgaWFtLlBvbGljeVN0YXRlbWVudCh7XG4gICAgICAgIGFjdGlvbnM6IFtcbiAgICAgICAgICAnc2VzOlZlcmlmeURvbWFpbkRraW0nLFxuICAgICAgICAgICdzZXM6VmVyaWZ5RG9tYWluSWRlbnRpdHknLFxuICAgICAgICAgICdzZXM6RGVsZXRlSWRlbnRpdHknLFxuICAgICAgICBdLFxuICAgICAgICByZXNvdXJjZXM6IFsnKiddLFxuICAgICAgfSksXG4gICAgKTtcblxuICAgIHRoaXMucHJvdmlkZXIgPSBuZXcgY3IuUHJvdmlkZXIodGhpcywgJ2hvc3RlZC16b25lLWRraW0tdmVyaWZpY2F0aW9uLXJlY29yZHMtcHJvdmlkZXInLCB7XG4gICAgICBvbkV2ZW50SGFuZGxlcjogb25FdmVudEhhbmRsZXJGdW5jLFxuICAgICAgbG9nUmV0ZW50aW9uOiAxLFxuICAgIH0pO1xuICAgIC8vIEdyYW51bGFyIGZpbmRpbmdzIG9ubHkuIFBvcnRhYmxlIElEcyBvbmx5OiBSZXNvdXJjZTo6KiBpcyBjb25zdGFudCBhY3Jvc3MgYW55IGRlcGxveW1lbnQsXG4gICAgLy8gUmVzb3VyY2U6Ojxsb2dpY2FsLWlkPiBmaW5kaW5ncyBhcmUgbm90LiBBd3NTb2x1dGlvbnMtSUFNNFtQb2xpY3k6Oi4uLl0gY2Fubm90IGJlXG4gICAgLy8gYWNrbm93bGVkZ2VkIGF0IGFsbCByaWdodCBub3cgLSBhd3MtY2RrLWxpYidzIFZhbGlkYXRpb25zLmFja25vd2xlZGdlKCkgcmVqZWN0cyBhbnkgaWQgd2l0aFxuICAgIC8vIG1vcmUgdGhhbiBvbmUgJzo6JywgYW5kIEFXUyBtYW5hZ2VkIHBvbGljeSBBUk5zIGFsd2F5cyBjb250YWluIG9uZSAoY2RrbGFicy9jZGstbmFnIzIzNTksXG4gICAgLy8gIzIzNTEsIGJvdGggb3BlbiB1cHN0cmVhbSkuIFNlZSBkb2NzL3BsYW5zLzIwMjYtMDgtMDktYnVtcC1tdmMtcHJvamVuLWNkay1uYWctdjMubWQgVGFzayAzLlxuICAgIGNvbnN0IGlhbTVSZXNvdXJjZVN0YXIgPSAnQXdzU29sdXRpb25zLUlBTTVbUmVzb3VyY2U6OipdJztcbiAgICBjb25zdCByZWFzb25JYW01ID0gJ3dpbGRjYXJkcyBhcmUgb2sgZm9yIHRoZSBwcm92aWRlciBhcyB0aGUgZnVuY3Rpb24gaGFzIHJlc3RyaWN0aW9ucyc7XG5cbiAgICBWYWxpZGF0aW9ucy5vZih0aGlzLnByb3ZpZGVyLm9uRXZlbnRIYW5kbGVyKS5hY2tub3dsZWRnZSh7IGlkOiBpYW01UmVzb3VyY2VTdGFyLCByZWFzb246IHJlYXNvbklhbTUgfSk7XG4gIH07XG59Il19
|