@fjall/components-infrastructure 0.73.17 → 0.74.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 (51) hide show
  1. package/dist/lib/__tests__/patterns/__snapshots__/compute.test.js.snap +433 -0
  2. package/dist/lib/__tests__/patterns/compute.test.d.ts +1 -0
  3. package/dist/lib/__tests__/patterns/compute.test.js +137 -0
  4. package/dist/lib/__tests__/simple.test.d.ts +0 -0
  5. package/dist/lib/__tests__/simple.test.js +12 -0
  6. package/dist/lib/config/aws/disasterRecovery.d.ts +27 -0
  7. package/dist/lib/config/aws/disasterRecovery.js +227 -0
  8. package/dist/lib/patterns/aws/managedAccount.js +15 -2
  9. package/dist/lib/resources/aws/backup/backupPlan.d.ts +19 -0
  10. package/dist/lib/resources/aws/backup/backupPlan.js +71 -0
  11. package/dist/lib/resources/aws/backup/backupVault.d.ts +19 -0
  12. package/dist/lib/resources/aws/backup/backupVault.js +43 -0
  13. package/dist/lib/resources/aws/backup/index.d.ts +2 -0
  14. package/dist/lib/resources/aws/backup/index.js +19 -0
  15. package/dist/lib/resources/aws/index.d.ts +1 -0
  16. package/dist/lib/resources/aws/index.js +2 -1
  17. package/dist/lib/resources/aws/organisations/account.d.ts +37 -0
  18. package/dist/lib/resources/aws/organisations/account.js +220 -0
  19. package/dist/lib/resources/aws/organisations/delegatedAdministrator.d.ts +14 -0
  20. package/dist/lib/resources/aws/organisations/delegatedAdministrator.js +61 -0
  21. package/dist/lib/resources/aws/organisations/index.d.ts +8 -0
  22. package/dist/lib/resources/aws/organisations/index.js +22 -0
  23. package/dist/lib/resources/aws/organisations/interfaces.d.ts +105 -0
  24. package/dist/lib/resources/aws/organisations/interfaces.js +3 -0
  25. package/dist/lib/resources/aws/organisations/organisation.d.ts +47 -0
  26. package/dist/lib/resources/aws/organisations/organisation.js +263 -0
  27. package/dist/lib/resources/aws/organisations/organisationalUnit.d.ts +28 -0
  28. package/dist/lib/resources/aws/organisations/organisationalUnit.js +170 -0
  29. package/dist/lib/resources/aws/organisations/policy.d.ts +17 -0
  30. package/dist/lib/resources/aws/organisations/policy.js +93 -0
  31. package/dist/lib/resources/aws/organisations/trustedServiceAccess.d.ts +13 -0
  32. package/dist/lib/resources/aws/organisations/trustedServiceAccess.js +58 -0
  33. package/dist/lib/resources/aws/organisations/types.d.ts +165 -0
  34. package/dist/lib/resources/aws/organisations/types.js +36 -0
  35. package/dist/lib/utils/directTagging.d.ts +31 -0
  36. package/dist/lib/utils/directTagging.js +86 -0
  37. package/dist/lib/utils/fjallConstruct.d.ts +8 -0
  38. package/dist/lib/utils/fjallConstruct.js +18 -0
  39. package/dist/lib/utils/fjallStackSynthesizer.d.ts +9 -0
  40. package/dist/lib/utils/fjallStackSynthesizer.js +22 -0
  41. package/dist/lib/utils/getConfig.d.ts +1 -0
  42. package/dist/lib/utils/getConfig.js +2 -1
  43. package/dist/lib/utils/tagContext.d.ts +28 -0
  44. package/dist/lib/utils/tagContext.js +53 -0
  45. package/dist/lib/utils/tagSynthesizer.d.ts +13 -0
  46. package/dist/lib/utils/tagSynthesizer.js +55 -0
  47. package/package.json +3 -3
  48. package/dist/lib/patterns/aws/ec2.d.ts +0 -43
  49. package/dist/lib/patterns/aws/ec2.js +0 -123
  50. package/dist/lib/utils/getCidr.d.ts +0 -8
  51. package/dist/lib/utils/getCidr.js +0 -40
@@ -0,0 +1,227 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DisasterRecovery = void 0;
4
+ const aws_cdk_lib_1 = require("aws-cdk-lib");
5
+ const constructs_1 = require("constructs");
6
+ const backup_1 = require("../../resources/aws/backup");
7
+ const aws_backup_1 = require("aws-cdk-lib/aws-backup");
8
+ const events = require("aws-cdk-lib/aws-events");
9
+ const aws_iam_1 = require("aws-cdk-lib/aws-iam");
10
+ const util_1 = require("@fjall/util");
11
+ // Backup retention constants (in days)
12
+ const RETENTION_PERIODS = {
13
+ STANDARD: 90,
14
+ RESILIENT: 365,
15
+ ENTERPRISE_CONTINUOUS: 35, // AWS max for continuous backup
16
+ ENTERPRISE_COMPLIANCE: 2555, // 7 years
17
+ COLD_STORAGE_MINIMUM: 90, // AWS minimum
18
+ COLD_STORAGE_ONE_YEAR: 365
19
+ };
20
+ class DisasterRecovery extends constructs_1.Construct {
21
+ constructor(scope, id, props) {
22
+ super(scope, id);
23
+ const fjallConfig = util_1.Config.loadConfig();
24
+ // Determine if this is a compliance account
25
+ const account = fjallConfig.getProviderAccountById(props.accountId);
26
+ const isComplianceAccount = account?.environment === "compliance";
27
+ // Get DR configuration
28
+ const disasterRecoveryRegion = fjallConfig.getDisasterRecoveryRegion();
29
+ // Look up compliance account for cross-account replication
30
+ // Skip if the compliance account (prevent self-replication)
31
+ const disasterRecoveryAccount = isComplianceAccount
32
+ ? undefined
33
+ : fjallConfig.getAccountByEnvironment("compliance");
34
+ // Construct cross-account DR vault ARN (compliance account in DR region)
35
+ const disasterRecoveryVaultArn = disasterRecoveryAccount && disasterRecoveryRegion
36
+ ? `arn:aws:backup:${disasterRecoveryRegion}:${disasterRecoveryAccount.id}:backup-vault:backupVault`
37
+ : undefined;
38
+ // Compliance accounts get vault locks for protection
39
+ const lockConfiguration = isComplianceAccount
40
+ ? {
41
+ minRetention: aws_cdk_lib_1.Duration.days(365), // Minimum 1 year retention
42
+ maxRetention: aws_cdk_lib_1.Duration.days(36500), // Maximum ~100 years
43
+ changeableFor: aws_cdk_lib_1.Duration.days(3) // 3-day grace period to modify lock
44
+ }
45
+ : undefined;
46
+ // Create primary backup vault
47
+ this.backupVault = new backup_1.BackupVault(this, "BackupVault", {
48
+ vaultName: "backupVault",
49
+ removalPolicy: aws_cdk_lib_1.RemovalPolicy.RETAIN,
50
+ lockConfiguration: lockConfiguration
51
+ });
52
+ // Configure cross-account access policies
53
+ if (disasterRecoveryAccount) {
54
+ // Production vaults: Allow compliance account to restore FROM this vault
55
+ const restoreStatement = new aws_iam_1.PolicyStatement({
56
+ effect: aws_iam_1.Effect.ALLOW,
57
+ principals: [new aws_iam_1.AccountPrincipal(disasterRecoveryAccount.id)],
58
+ actions: [
59
+ "backup:DescribeBackupVault",
60
+ "backup:ListRecoveryPointsByBackupVault",
61
+ "backup:GetRecoveryPointRestoreMetadata",
62
+ "backup:StartRestoreJob",
63
+ "backup:DescribeRestoreJob"
64
+ ],
65
+ resources: ["*"]
66
+ });
67
+ this.backupVault.vault.addToAccessPolicy(restoreStatement);
68
+ }
69
+ if (isComplianceAccount) {
70
+ // Compliance vaults: Allow production accounts to copy TO this vault
71
+ const allAccounts = fjallConfig.rootConfig.providerAccounts || [];
72
+ const productionAccounts = allAccounts.filter((acc) => acc.environment === "production");
73
+ if (productionAccounts.length > 0) {
74
+ const copyStatement = new aws_iam_1.PolicyStatement({
75
+ effect: aws_iam_1.Effect.ALLOW,
76
+ principals: productionAccounts.map((acc) => new aws_iam_1.AccountPrincipal(acc.id)),
77
+ actions: ["backup:CopyIntoBackupVault"],
78
+ resources: ["*"]
79
+ });
80
+ this.backupVault.vault.addToAccessPolicy(copyStatement);
81
+ }
82
+ }
83
+ // Construct cross-region replication vault ARN (same account, DR region)
84
+ // Only replicate if DR region exists AND is different from current region
85
+ const replicationVaultArn = disasterRecoveryRegion && disasterRecoveryRegion !== props.region
86
+ ? `arn:aws:backup:${disasterRecoveryRegion}:${props.accountId}:backup-vault:backupVault`
87
+ : undefined;
88
+ // Create all three backup plans
89
+ this.backupPlans = {
90
+ standard: new backup_1.BackupPlan(this, "StandardBackupPlan", {
91
+ planName: "standard",
92
+ rules: this.createStandardBackupRules("standard"),
93
+ tagValue: "default",
94
+ backupVault: this.backupVault
95
+ }),
96
+ resilient: new backup_1.BackupPlan(this, "ResilientBackupPlan", {
97
+ planName: "resilient",
98
+ rules: this.createResilientBackupRules("resilient", replicationVaultArn),
99
+ tagValue: "resilient",
100
+ backupVault: this.backupVault
101
+ }),
102
+ enterprise: new backup_1.BackupPlan(this, "EnterpriseBackupPlan", {
103
+ planName: "enterprise",
104
+ rules: this.createEnterpriseBackupRules("enterprise", replicationVaultArn, disasterRecoveryVaultArn),
105
+ tagValue: "enterprise",
106
+ backupVault: this.backupVault
107
+ })
108
+ };
109
+ // Create custom backup plans if provided
110
+ if (props.customBackupPlans && props.customBackupPlans.length > 0) {
111
+ this.customBackupPlans = props.customBackupPlans.map((config, index) => {
112
+ return new backup_1.BackupPlan(this, `CustomBackupPlan${index}`, {
113
+ planName: config.planName,
114
+ rules: config.rules,
115
+ tagValue: config.tagValue,
116
+ backupVault: this.backupVault
117
+ });
118
+ });
119
+ }
120
+ // Export disaster recovery configuration
121
+ new aws_cdk_lib_1.CfnOutput(this, "DisasterRecoveryEnabled", {
122
+ key: "DisasterRecoveryEnabled",
123
+ value: "true",
124
+ exportName: "DisasterRecoveryEnabled"
125
+ });
126
+ if (disasterRecoveryRegion) {
127
+ new aws_cdk_lib_1.CfnOutput(this, "ReplicationRegion", {
128
+ key: "ReplicationRegion",
129
+ value: disasterRecoveryRegion,
130
+ exportName: "BackupReplicationRegion"
131
+ });
132
+ }
133
+ if (isComplianceAccount) {
134
+ new aws_cdk_lib_1.CfnOutput(this, "VaultLockEnabled", {
135
+ key: "VaultLockEnabled",
136
+ value: "true",
137
+ exportName: "VaultLockEnabled"
138
+ });
139
+ }
140
+ }
141
+ createStandardBackupRules(planName) {
142
+ return [
143
+ new aws_backup_1.BackupPlanRule({
144
+ ruleName: `${planName}Daily`,
145
+ scheduleExpression: events.Schedule.cron({ hour: "2", minute: "0" }), // 2 AM daily
146
+ deleteAfter: aws_cdk_lib_1.Duration.days(RETENTION_PERIODS.STANDARD),
147
+ startWindow: aws_cdk_lib_1.Duration.minutes(60),
148
+ completionWindow: aws_cdk_lib_1.Duration.hours(12)
149
+ })
150
+ ];
151
+ }
152
+ createResilientBackupRules(planName, replicationVaultArn) {
153
+ const copyActions = this.createCopyActions(planName, replicationVaultArn, undefined, aws_cdk_lib_1.Duration.days(RETENTION_PERIODS.RESILIENT), aws_cdk_lib_1.Duration.days(RETENTION_PERIODS.COLD_STORAGE_MINIMUM));
154
+ return [
155
+ new aws_backup_1.BackupPlanRule({
156
+ ruleName: `${planName}Daily`,
157
+ scheduleExpression: events.Schedule.cron({ hour: "2", minute: "0" }), // 2 AM daily
158
+ deleteAfter: aws_cdk_lib_1.Duration.days(RETENTION_PERIODS.RESILIENT),
159
+ moveToColdStorageAfter: aws_cdk_lib_1.Duration.days(RETENTION_PERIODS.COLD_STORAGE_MINIMUM),
160
+ enableContinuousBackup: true,
161
+ startWindow: aws_cdk_lib_1.Duration.minutes(60),
162
+ completionWindow: aws_cdk_lib_1.Duration.hours(12),
163
+ copyActions
164
+ })
165
+ ];
166
+ }
167
+ createEnterpriseBackupRules(planName, replicationVaultArn, disasterRecoveryVaultArn) {
168
+ const continuousCopyActions = this.createCopyActions(planName, replicationVaultArn, disasterRecoveryVaultArn, aws_cdk_lib_1.Duration.days(RETENTION_PERIODS.ENTERPRISE_CONTINUOUS), undefined);
169
+ const complianceCopyActions = this.createCopyActions(planName, replicationVaultArn, disasterRecoveryVaultArn, aws_cdk_lib_1.Duration.days(RETENTION_PERIODS.ENTERPRISE_COMPLIANCE), aws_cdk_lib_1.Duration.days(RETENTION_PERIODS.COLD_STORAGE_ONE_YEAR));
170
+ return [
171
+ // Continuous backup (35-day max PITR window)
172
+ new aws_backup_1.BackupPlanRule({
173
+ ruleName: `${planName}Continuous`,
174
+ scheduleExpression: events.Schedule.cron({ hour: "2", minute: "0" }), // Daily for continuous backup
175
+ deleteAfter: aws_cdk_lib_1.Duration.days(RETENTION_PERIODS.ENTERPRISE_CONTINUOUS),
176
+ enableContinuousBackup: true,
177
+ startWindow: aws_cdk_lib_1.Duration.minutes(60),
178
+ completionWindow: aws_cdk_lib_1.Duration.hours(12),
179
+ copyActions: continuousCopyActions
180
+ }),
181
+ // Hourly snapshots for long-term compliance (7 years)
182
+ new aws_backup_1.BackupPlanRule({
183
+ ruleName: `${planName}HourlyCompliance`,
184
+ scheduleExpression: events.Schedule.cron({ minute: "0" }), // Every hour
185
+ deleteAfter: aws_cdk_lib_1.Duration.days(RETENTION_PERIODS.ENTERPRISE_COMPLIANCE),
186
+ moveToColdStorageAfter: aws_cdk_lib_1.Duration.days(RETENTION_PERIODS.COLD_STORAGE_ONE_YEAR),
187
+ startWindow: aws_cdk_lib_1.Duration.minutes(60),
188
+ completionWindow: aws_cdk_lib_1.Duration.hours(2),
189
+ copyActions: complianceCopyActions
190
+ })
191
+ ];
192
+ }
193
+ createCopyActions(planName, replicationVaultArn, disasterRecoveryVaultArn, deleteAfter, moveToColdStorageAfter) {
194
+ const actions = [];
195
+ // Cross-region replication
196
+ if (replicationVaultArn) {
197
+ const replicationAction = {
198
+ destinationBackupVault: aws_backup_1.BackupVault.fromBackupVaultArn(this, `${planName}ReplicationVaultRef`, replicationVaultArn),
199
+ ...(deleteAfter && { deleteAfter }),
200
+ // Only add cold storage if specified and >= 90 days
201
+ ...(moveToColdStorageAfter &&
202
+ moveToColdStorageAfter.toDays() >=
203
+ RETENTION_PERIODS.COLD_STORAGE_MINIMUM
204
+ ? { moveToColdStorageAfter }
205
+ : {})
206
+ };
207
+ actions.push(replicationAction);
208
+ }
209
+ // Cross-account DR vault
210
+ if (disasterRecoveryVaultArn) {
211
+ const drAction = {
212
+ destinationBackupVault: aws_backup_1.BackupVault.fromBackupVaultArn(this, `${planName}DisasterRecoveryVaultRef`, disasterRecoveryVaultArn),
213
+ ...(deleteAfter && { deleteAfter }),
214
+ // Only add cold storage if specified and >= 90 days
215
+ ...(moveToColdStorageAfter &&
216
+ moveToColdStorageAfter.toDays() >=
217
+ RETENTION_PERIODS.COLD_STORAGE_MINIMUM
218
+ ? { moveToColdStorageAfter }
219
+ : {})
220
+ };
221
+ actions.push(drAction);
222
+ }
223
+ return actions.length > 0 ? actions : undefined;
224
+ }
225
+ }
226
+ exports.DisasterRecovery = DisasterRecovery;
227
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGlzYXN0ZXJSZWNvdmVyeS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9jb25maWcvYXdzL2Rpc2FzdGVyUmVjb3ZlcnkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsNkNBQWlFO0FBQ2pFLDJDQUF1QztBQUN2Qyx1REFBcUU7QUFDckUsdURBSWdDO0FBQ2hDLGlEQUFpRDtBQUNqRCxpREFBZ0Y7QUFDaEYsc0NBQW9EO0FBRXBELHVDQUF1QztBQUN2QyxNQUFNLGlCQUFpQixHQUFHO0lBQ3hCLFFBQVEsRUFBRSxFQUFFO0lBQ1osU0FBUyxFQUFFLEdBQUc7SUFDZCxxQkFBcUIsRUFBRSxFQUFFLEVBQUUsZ0NBQWdDO0lBQzNELHFCQUFxQixFQUFFLElBQUksRUFBRSxVQUFVO0lBQ3ZDLG9CQUFvQixFQUFFLEVBQUUsRUFBRSxjQUFjO0lBQ3hDLHFCQUFxQixFQUFFLEdBQUc7Q0FDbEIsQ0FBQztBQWNYLE1BQWEsZ0JBQWlCLFNBQVEsc0JBQVM7SUFTN0MsWUFBWSxLQUFnQixFQUFFLEVBQVUsRUFBRSxLQUE0QjtRQUNwRSxLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBRWpCLE1BQU0sV0FBVyxHQUFHLGFBQVcsQ0FBQyxVQUFVLEVBQUUsQ0FBQztRQUU3Qyw0Q0FBNEM7UUFDNUMsTUFBTSxPQUFPLEdBQUcsV0FBVyxDQUFDLHNCQUFzQixDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUNwRSxNQUFNLG1CQUFtQixHQUFHLE9BQU8sRUFBRSxXQUFXLEtBQUssWUFBWSxDQUFDO1FBRWxFLHVCQUF1QjtRQUN2QixNQUFNLHNCQUFzQixHQUFHLFdBQVcsQ0FBQyx5QkFBeUIsRUFBRSxDQUFDO1FBRXZFLDJEQUEyRDtRQUMzRCw0REFBNEQ7UUFDNUQsTUFBTSx1QkFBdUIsR0FBRyxtQkFBbUI7WUFDakQsQ0FBQyxDQUFDLFNBQVM7WUFDWCxDQUFDLENBQUMsV0FBVyxDQUFDLHVC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QUN6QjtnQkFDRCxHQUFHLENBQUMsV0FBVyxJQUFJLEVBQUUsV0FBVyxFQUFFLENBQUM7Z0JBQ25DLG9EQUFvRDtnQkFDcEQsR0FBRyxDQUFDLHNCQUFzQjtvQkFDMUIsc0JBQXNCLENBQUMsTUFBTSxFQUFFO3dCQUM3QixpQkFBaUIsQ0FBQyxvQkFBb0I7b0JBQ3RDLENBQUMsQ0FBQyxFQUFFLHNCQUFzQixFQUFFO29CQUM1QixDQUFDLENBQUMsRUFBRSxDQUFDO2FBQ1IsQ0FBQztZQUNGLE9BQU8sQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDekIsQ0FBQztRQUVELE9BQU8sT0FBTyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDO0lBQ2xELENBQUM7Q0FDRjtBQXZTRCw0Q0F1U0MiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDZm5PdXRwdXQsIER1cmF0aW9uLCBSZW1vdmFsUG9saWN5IH0gZnJvbSBcImF3cy1jZGstbGliXCI7XG5pbXBvcnQgeyBDb25zdHJ1Y3QgfSBmcm9tIFwiY29uc3RydWN0c1wiO1xuaW1wb3J0IHsgQmFja3VwVmF1bHQsIEJhY2t1cFBsYW4gfSBmcm9tIFwiLi4vLi4vcmVzb3VyY2VzL2F3cy9iYWNrdXBcIjtcbmltcG9ydCB7XG4gIEJhY2t1cFBsYW5SdWxlLFxuICBCYWNrdXBQbGFuQ29weUFjdGlvblByb3BzLFxuICBCYWNrdXBWYXVsdCBhcyBWYXVsdFxufSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWJhY2t1cFwiO1xuaW1wb3J0ICogYXMgZXZlbnRzIGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtZXZlbnRzXCI7XG5pbXBvcnQgeyBBY2NvdW50UHJpbmNpcGFsLCBFZmZlY3QsIFBvbGljeVN0YXRlbWVudCB9IGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtaWFtXCI7XG5pbXBvcnQgeyBDb25maWcgYXMgRmphbGxDb25maWcgfSBmcm9tIFwiQGZqYWxsL3V0aWxcIjtcblxuLy8gQmFja3VwIHJldGVudGlvbiBjb25zdGFudHMgKGluIGRheXMpXG5jb25zdCBSRVRFTlRJT05fUEVSSU9EUyA9IHtcbiAgU1RBTkRBUkQ6IDkwLFxuICBSRVNJTElFTlQ6IDM2NSxcbiAgRU5URVJQUklTRV9DT05USU5VT1VTOiAzNSwgLy8gQVdTIG1heCBmb3IgY29udGludW91cyBiYWNrdXBcbiAgRU5URVJQUklTRV9DT01QTElBTkNFOiAyNTU1LCAvLyA3IHllYXJzXG4gIENPTERfU1RPUkFHRV9NSU5JTVVNOiA5MCwgLy8gQVdTIG1pbmltdW1cbiAgQ09MRF9TVE9SQUdFX09ORV9ZRUFSOiAzNjVcbn0gYXMgY29uc3Q7XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ3VzdG9tQmFja3VwUGxhbkNvbmZpZyB7XG4gIHBsYW5OYW1lOiBzdHJpbmc7XG4gIHJ1bGVzOiBCYWNrdXBQbGFuUnVsZVtdO1xuICB0YWdWYWx1ZTogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIERpc2FzdGVyUmVjb3ZlcnlQcm9wcyB7XG4gIHJlZ2lvbjogc3RyaW5nO1xuICBhY2NvdW50SWQ6IHN0cmluZztcbiAgY3VzdG9tQmFja3VwUGxhbnM/OiBDdXN0b21CYWNrdXBQbGFuQ29uZmlnW107XG59XG5cbmV4cG9ydCBjbGFzcyBEaXNhc3RlclJlY292ZXJ5IGV4dGVuZHMgQ29uc3RydWN0IHtcbiAgcHVibGljIHJlYWRvbmx5IGJhY2t1cFZhdWx0OiBCYWNrdXBWYXVsdDtcbiAgcHVibGljIHJlYWRvbmx5IGJhY2t1cFBsYW5zOiB7XG4gICAgc3RhbmRhcmQ6IEJhY2t1cFBsYW47XG4gICAgcmVzaWxpZW50OiBCYWNrdXBQbGFuO1xuICAgIGVudGVycHJpc2U6IEJhY2t1cFBsYW47XG4gIH07XG4gIHB1YmxpYyByZWFkb25seSBjdXN0b21CYWNrdXBQbGFucz86IEJhY2t1cFBsYW5bXTtcblxuICBjb25zdHJ1Y3RvcihzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBwcm9wczogRGlzYXN0ZXJSZWNvdmVyeVByb3BzKSB7XG4gICAgc3VwZXIoc2NvcGUsIGlkKTtcblxuICAgIGNvbnN0IGZqYWxsQ29uZmlnID0gRmphbGxDb25maWcubG9hZENvbmZpZygpO1xuXG4gICAgLy8gRGV0ZXJtaW5lIGlmIHRoaXMgaXMgYSBjb21wbGlhbmNlIGFjY291bnRcbiAgICBjb25zdCBhY2NvdW50ID0gZmphbGxDb25maWcuZ2V0UHJvdmlkZXJBY2NvdW50QnlJZChwcm9wcy5hY2NvdW50SWQpO1xuICAgIGNvbnN0IGlzQ29tcGxpYW5jZUFjY291bnQgPSBhY2NvdW50Py5lbnZpcm9ubWVudCA9PT0gXCJjb21wbGlhbmNlXCI7XG5cbiAgICAvLyBHZXQgRFIgY29uZmlndXJhdGlvblxuICAgIGNvbnN0IGRpc2FzdGVyUmVjb3ZlcnlSZWdpb24gPSBmamFsbENvbmZpZy5nZXREaXNhc3RlclJlY292ZXJ5UmVnaW9uKCk7XG5cbiAgICAvLyBMb29rIHVwIGNvbXBsaWFuY2UgYWNjb3VudCBmb3IgY3Jvc3MtYWNjb3VudCByZXBsaWNhdGlvblxuICAgIC8vIFNraXAgaWYgdGhlIGNvbXBsaWFuY2UgYWNjb3VudCAocHJldmVudCBzZWxmLXJlcGxpY2F0aW9uKVxuICAgIGNvbnN0IGRpc2FzdGVyUmVjb3ZlcnlBY2NvdW50ID0gaXNDb21wbGlhbmNlQWNjb3VudFxuICAgICAgPyB1bmRlZmluZWRcbiAgICAgIDogZmphbGxDb25maWcuZ2V0QWNjb3VudEJ5RW52aXJvbm1lbnQoXCJjb21wbGlhbmNlXCIpO1xuXG4gICAgLy8gQ29uc3RydWN0IGNyb3NzLWFjY291bnQgRFIgdmF1bHQgQVJOIChjb21wbGlhbmNlIGFjY291bnQgaW4gRFIgcmVnaW9uKVxuICAgIGNvbnN0IGRpc2FzdGVyUmVjb3ZlcnlWYXVsdEFybiA9XG4gICAgICBkaXNhc3RlclJlY292ZXJ5QWNjb3VudCAmJiBkaXNhc3RlclJlY292ZXJ5UmVnaW9uXG4gICAgICAgID8gYGFybjphd3M6YmFja3VwOiR7ZGlzYXN0ZXJSZWNvdmVyeVJlZ2lvbn06JHtkaXNhc3RlclJlY292ZXJ5QWNjb3VudC5pZH06YmFja3VwLXZhdWx0OmJhY2t1cFZhdWx0YFxuICAgICAgICA6IHVuZGVmaW5lZDtcblxuICAgIC8vIENvbXBsaWFuY2UgYWNjb3VudHMgZ2V0IHZhdWx0IGxvY2tzIGZvciBwcm90ZWN0aW9uXG4gICAgY29uc3QgbG9ja0NvbmZpZ3VyYXRpb24gPSBpc0NvbXBsaWFuY2VBY2NvdW50XG4gICAgICA/IHtcbiAgICAgICAgICBtaW5SZXRlbnRpb246IER1cmF0aW9uLmRheXMoMzY1KSwgLy8gTWluaW11bSAxIHllYXIgcmV0ZW50aW9uXG4gICAgICAgICAgbWF4UmV0ZW50aW9uOiBEdXJhdGlvbi5kYXlzKDM2NTAwKSwgLy8gTWF4aW11bSB+MTAwIHllYXJzXG4gICAgICAgICAgY2hhbmdlYWJsZUZvcjogRHVyYXRpb24uZGF5cygzKSAvLyAzLWRheSBncmFjZSBwZXJpb2QgdG8gbW9kaWZ5IGxvY2tcbiAgICAgICAgfVxuICAgICAgOiB1bmRlZmluZWQ7XG5cbiAgICAvLyBDcmVhdGUgcHJpbWFyeSBiYWNrdXAgdmF1bHRcbiAgICB0aGlzLmJhY2t1cFZhdWx0ID0gbmV3IEJhY2t1cFZhdWx0KHRoaXMsIFwiQmFja3VwVmF1bHRcIiwge1xuICAgICAgdmF1bHROYW1lOiBcImJhY2t1cFZhdWx0XCIsXG4gICAgICByZW1vdmFsUG9saWN5OiBSZW1vdmFsUG9saWN5LlJFVEFJTixcbiAgICAgIGxvY2tDb25maWd1cmF0aW9uOiBsb2NrQ29uZmlndXJhdGlvblxuICAgIH0pO1xuXG4gICAgLy8gQ29uZmlndXJlIGNyb3NzLWFjY291bnQgYWNjZXNzIHBvbGljaWVzXG4gICAgaWYgKGRpc2FzdGVyUmVjb3ZlcnlBY2NvdW50KSB7XG4gICAgICAvLyBQcm9kdWN0aW9uIHZhdWx0czogQWxsb3cgY29tcGxpYW5jZSBhY2NvdW50IHRvIHJlc3RvcmUgRlJPTSB0aGlzIHZhdWx0XG4gICAgICBjb25zdCByZXN0b3JlU3RhdGVtZW50ID0gbmV3IFBvbGljeVN0YXRlbWVudCh7XG4gICAgICAgIGVmZmVjdDogRWZmZWN0LkFMTE9XLFxuICAgICAgICBwcmluY2lwYWxzOiBbbmV3IEFjY291bnRQcmluY2lwYWwoZGlzYXN0ZXJSZWNvdmVyeUFjY291bnQuaWQpXSxcbiAgICAgICAgYWN0aW9uczogW1xuICAgICAgICAgIFwiYmFja3VwOkRlc2NyaWJlQmFja3VwVmF1bHRcIixcbiAgICAgICAgICBcImJhY2t1cDpMaXN0UmVjb3ZlcnlQb2ludHNCeUJhY2t1cFZhdWx0XCIsXG4gICAgICAgICAgXCJiYWNrdXA6R2V0UmVjb3ZlcnlQb2ludFJlc3RvcmVNZXRhZGF0YVwiLFxuICAgICAgICAgIFwiYmFja3VwOlN0YXJ0UmVzdG9yZUpvYlwiLFxuICAgICAgICAgIFwiYmFja3VwOkRlc2NyaWJlUmVzdG9yZUpvYlwiXG4gICAgICAgIF0sXG4gICAgICAgIHJlc291cmNlczogW1wiKlwiXVxuICAgICAgfSk7XG4gICAgICB0aGlzLmJhY2t1cFZhdWx0LnZhdWx0LmFkZFRvQWNjZXNzUG9saWN5KHJlc3RvcmVTdGF0ZW1lbnQpO1xuICAgIH1cblxuICAgIGlmIChpc0NvbXBsaWFuY2VBY2NvdW50KSB7XG4gICAgICAvLyBDb21wbGlhbmNlIHZhdWx0czogQWxsb3cgcHJvZHVjdGlvbiBhY2NvdW50cyB0byBjb3B5IFRPIHRoaXMgdmF1bHRcbiAgICAgIGNvbnN0IGFsbEFjY291bnRzID0gZmphbGxDb25maWcucm9vdENvbmZpZy5wcm92aWRlckFjY291bnRzIHx8IFtdO1xuICAgICAgY29uc3QgcHJvZHVjdGlvbkFjY291bnRzID0gYWxsQWNjb3VudHMuZmlsdGVyKFxuICAgICAgICAoYWNjKSA9PiBhY2MuZW52aXJvbm1lbnQgPT09IFwicHJvZHVjdGlvblwiXG4gICAgICApO1xuXG4gICAgICBpZiAocHJvZHVjdGlvbkFjY291bnRzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgY29uc3QgY29weVN0YXRlbWVudCA9IG5ldyBQb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgICAgIGVmZmVjdDogRWZmZWN0LkFMTE9XLFxuICAgICAgICAgIHByaW5jaXBhbHM6IHByb2R1Y3Rpb25BY2NvdW50cy5tYXAoXG4gICAgICAgICAgICAoYWNjKSA9PiBuZXcgQWNjb3VudFByaW5jaXBhbChhY2MuaWQpXG4gICAgICAgICAgKSxcbiAgICAgICAgICBhY3Rpb25zOiBbXCJiYWNrdXA6Q29weUludG9CYWNrdXBWYXVsdFwiXSxcbiAgICAgICAgICByZXNvdXJjZXM6IFtcIipcIl1cbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuYmFja3VwVmF1bHQudmF1bHQuYWRkVG9BY2Nlc3NQb2xpY3koY29weVN0YXRlbWVudCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gQ29uc3RydWN0IGNyb3NzLXJlZ2lvbiByZXBsaWNhdGlvbiB2YXVsdCBBUk4gKHNhbWUgYWNjb3VudCwgRFIgcmVnaW9uKVxuICAgIC8vIE9ubHkgcmVwbGljYXRlIGlmIERSIHJlZ2lvbiBleGlzdHMgQU5EIGlzIGRpZmZlcmVudCBmcm9tIGN1cnJlbnQgcmVnaW9uXG4gICAgY29uc3QgcmVwbGljYXRpb25WYXVsdEFybiA9XG4gICAgICBkaXNhc3RlclJlY292ZXJ5UmVnaW9uICYmIGRpc2FzdGVyUmVjb3ZlcnlSZWdpb24gIT09IHByb3BzLnJlZ2lvblxuICAgICAgICA/IGBhcm46YXdzOmJhY2t1cDoke2Rpc2FzdGVyUmVjb3ZlcnlSZWdpb259OiR7cHJvcHMuYWNjb3VudElkfTpiYWNrdXAtdmF1bHQ6YmFja3VwVmF1bHRgXG4gICAgICAgIDogdW5kZWZpbmVkO1xuXG4gICAgLy8gQ3JlYXRlIGFsbCB0aHJlZSBiYWNrdXAgcGxhbnNcbiAgICB0aGlzLmJhY2t1cFBsYW5zID0ge1xuICAgICAgc3RhbmRhcmQ6IG5ldyBCYWNrdXBQbGFuKHRoaXMsIFwiU3RhbmRhcmRCYWNrdXBQbGFuXCIsIHtcbiAgICAgICAgcGxhbk5hbWU6IFwic3RhbmRhcmRcIixcbiAgICAgICAgcnVsZXM6IHRoaXMuY3JlYXRlU3RhbmRhcmRCYWNrdXBSdWxlcyhcInN0YW5kYXJkXCIpLFxuICAgICAgICB0YWdWYWx1ZTogXCJkZWZhdWx0XCIsXG4gICAgICAgIGJhY2t1cFZhdWx0OiB0aGlzLmJhY2t1cFZhdWx0XG4gICAgICB9KSxcbiAgICAgIHJlc2lsaWVudDogbmV3IEJhY2t1cFBsYW4odGhpcywgXCJSZXNpbGllbnRCYWNrdXBQbGFuXCIsIHtcbiAgICAgICAgcGxhbk5hbWU6IFwicmVzaWxpZW50XCIsXG4gICAgICAgIHJ1bGVzOiB0aGlzLmNyZWF0ZVJlc2lsaWVudEJhY2t1cFJ1bGVzKFxuICAgICAgICAgIFwicmVzaWxpZW50XCIsXG4gICAgICAgICAgcmVwbGljYXRpb25WYXVsdEFyblxuICAgICAgICApLFxuICAgICAgICB0YWdWYWx1ZTogXCJyZXNpbGllbnRcIixcbiAgICAgICAgYmFja3VwVmF1bHQ6IHRoaXMuYmFja3VwVmF1bHRcbiAgICAgIH0pLFxuICAgICAgZW50ZXJwcmlzZTogbmV3IEJhY2t1cFBsYW4odGhpcywgXCJFbnRlcnByaXNlQmFja3VwUGxhblwiLCB7XG4gICAgICAgIHBsYW5OYW1lOiBcImVudGVycHJpc2VcIixcbiAgICAgICAgcnVsZXM6IHRoaXMuY3JlYXRlRW50ZXJwcmlzZUJhY2t1cFJ1bGVzKFxuICAgICAgICAgIFwiZW50ZXJwcmlzZVwiLFxuICAgICAgICAgIHJlcGxpY2F0aW9uVmF1bHRBcm4sXG4gICAgICAgICAgZGlzYXN0ZXJSZWNvdmVyeVZhdWx0QXJuXG4gICAgICAgICksXG4gICAgICAgIHRhZ1ZhbHVlOiBcImVudGVycHJpc2VcIixcbiAgICAgICAgYmFja3VwVmF1bHQ6IHRoaXMuYmFja3VwVmF1bHRcbiAgICAgIH0pXG4gICAgfTtcblxuICAgIC8vIENyZWF0ZSBjdXN0b20gYmFja3VwIHBsYW5zIGlmIHByb3ZpZGVkXG4gICAgaWYgKHByb3BzLmN1c3RvbUJhY2t1cFBsYW5zICYmIHByb3BzLmN1c3RvbUJhY2t1cFBsYW5zLmxlbmd0aCA+IDApIHtcbiAgICAgIHRoaXMuY3VzdG9tQmFja3VwUGxhbnMgPSBwcm9wcy5jdXN0b21CYWNrdXBQbGFucy5tYXAoKGNvbmZpZywgaW5kZXgpID0+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBCYWNrdXBQbGFuKHRoaXMsIGBDdXN0b21CYWNrdXBQbGFuJHtpbmRleH1gLCB7XG4gICAgICAgICAgcGxhbk5hbWU6IGNvbmZpZy5wbGFuTmFtZSxcbiAgICAgICAgICBydWxlczogY29uZmlnLnJ1bGVzLFxuICAgICAgICAgIHRhZ1ZhbHVlOiBjb25maWcudGFnVmFsdWUsXG4gICAgICAgICAgYmFja3VwVmF1bHQ6IHRoaXMuYmFja3VwVmF1bHRcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvLyBFeHBvcnQgZGlzYXN0ZXIgcmVjb3ZlcnkgY29uZmlndXJhdGlvblxuICAgIG5ldyBDZm5PdXRwdXQodGhpcywgXCJEaXNhc3RlclJlY292ZXJ5RW5hYmxlZFwiLCB7XG4gICAgICBrZXk6IFwiRGlzYXN0ZXJSZWNvdmVyeUVuYWJsZWRcIixcbiAgICAgIHZhbHVlOiBcInRydWVcIixcbiAgICAgIGV4cG9ydE5hbWU6IFwiRGlzYXN0ZXJSZWNvdmVyeUVuYWJsZWRcIlxuICAgIH0pO1xuXG4gICAgaWYgKGRpc2FzdGVyUmVjb3ZlcnlSZWdpb24pIHtcbiAgICAgIG5ldyBDZm5PdXRwdXQodGhpcywgXCJSZXBsaWNhdGlvblJlZ2lvblwiLCB7XG4gICAgICAgIGtleTogXCJSZXBsaWNhdGlvblJlZ2lvblwiLFxuICAgICAgICB2YWx1ZTogZGlzYXN0ZXJSZWNvdmVyeVJlZ2lvbixcbiAgICAgICAgZXhwb3J0TmFtZTogXCJCYWNrdXBSZXBsaWNhdGlvblJlZ2lvblwiXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBpZiAoaXNDb21wbGlhbmNlQWNjb3VudCkge1xuICAgICAgbmV3IENmbk91dHB1dCh0aGlzLCBcIlZhdWx0TG9ja0VuYWJsZWRcIiwge1xuICAgICAgICBrZXk6IFwiVmF1bHRMb2NrRW5hYmxlZFwiLFxuICAgICAgICB2YWx1ZTogXCJ0cnVlXCIsXG4gICAgICAgIGV4cG9ydE5hbWU6IFwiVmF1bHRMb2NrRW5hYmxlZFwiXG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGNyZWF0ZVN0YW5kYXJkQmFja3VwUnVsZXMocGxhbk5hbWU6IHN0cmluZyk6IEJhY2t1cFBsYW5SdWxlW10ge1xuICAgIHJldHVybiBbXG4gICAgICBuZXcgQmFja3VwUGxhblJ1bGUoe1xuICAgICAgICBydWxlTmFtZTogYCR7cGxhbk5hbWV9RGFpbHlgLFxuICAgICAgICBzY2hlZHVsZUV4cHJlc3Npb246IGV2ZW50cy5TY2hlZHVsZS5jcm9uKHsgaG91cjogXCIyXCIsIG1pbnV0ZTogXCIwXCIgfSksIC8vIDIgQU0gZGFpbHlcbiAgICAgICAgZGVsZXRlQWZ0ZXI6IER1cmF0aW9uLmRheXMoUkVURU5USU9OX1BFUklPRFMuU1RBTkRBUkQpLFxuICAgICAgICBzdGFydFdpbmRvdzogRHVyYXRpb24ubWludXRlcyg2MCksXG4gICAgICAgIGNvbXBsZXRpb25XaW5kb3c6IER1cmF0aW9uLmhvdXJzKDEyKVxuICAgICAgfSlcbiAgICBdO1xuICB9XG5cbiAgcHJpdmF0ZSBjcmVhdGVSZXNpbGllbnRCYWNrdXBSdWxlcyhcbiAgICBwbGFuTmFtZTogc3RyaW5nLFxuICAgIHJlcGxpY2F0aW9uVmF1bHRBcm4/OiBzdHJpbmdcbiAgKTogQmFja3VwUGxhblJ1bGVbXSB7XG4gICAgY29uc3QgY29weUFjdGlvbnMgPSB0aGlzLmNyZWF0ZUNvcHlBY3Rpb25zKFxuICAgICAgcGxhbk5hbWUsXG4gICAgICByZXBsaWNhdGlvblZhdWx0QXJuLFxuICAgICAgdW5kZWZpbmVkLFxuICAgICAgRHVyYXRpb24uZGF5cyhSRVRFTlRJT05fUEVSSU9EUy5SRVNJTElFTlQpLFxuICAgICAgRHVyYXRpb24uZGF5cyhSRVRFTlRJT05fUEVSSU9EUy5DT0xEX1NUT1JBR0VfTUlOSU1VTSlcbiAgICApO1xuXG4gICAgcmV0dXJuIFtcbiAgICAgIG5ldyBCYWNrdXBQbGFuUnVsZSh7XG4gICAgICAgIHJ1bGVOYW1lOiBgJHtwbGFuTmFtZX1EYWlseWAsXG4gICAgICAgIHNjaGVkdWxlRXhwcmVzc2lvbjogZXZlbnRzLlNjaGVkdWxlLmNyb24oeyBob3VyOiBcIjJcIiwgbWludXRlOiBcIjBcIiB9KSwgLy8gMiBBTSBkYWlseVxuICAgICAgICBkZWxldGVBZnRlcjogRHVyYXRpb24uZGF5cyhSRVRFTlRJT05fUEVSSU9EUy5SRVNJTElFTlQpLFxuICAgICAgICBtb3ZlVG9Db2xkU3RvcmFnZUFmdGVyOiBEdXJhdGlvbi5kYXlzKFxuICAgICAgICAgIFJFVEVOVElPTl9QRVJJT0RTLkNPTERfU1RPUkFHRV9NSU5JTVVNXG4gICAgICAgICksXG4gICAgICAgIGVuYWJsZUNvbnRpbnVvdXNCYWNrdXA6IHRydWUsXG4gICAgICAgIHN0YXJ0V2luZG93OiBEdXJhdGlvbi5taW51dGVzKDYwKSxcbiAgICAgICAgY29tcGxldGlvbldpbmRvdzogRHVyYXRpb24uaG91cnMoMTIpLFxuICAgICAgICBjb3B5QWN0aW9uc1xuICAgICAgfSlcbiAgICBdO1xuICB9XG5cbiAgcHJpdmF0ZSBjcmVhdGVFbnRlcnByaXNlQmFja3VwUnVsZXMoXG4gICAgcGxhbk5hbWU6IHN0cmluZyxcbiAgICByZXBsaWNhdGlvblZhdWx0QXJuPzogc3RyaW5nLFxuICAgIGRpc2FzdGVyUmVjb3ZlcnlWYXVsdEFybj86IHN0cmluZ1xuICApOiBCYWNrdXBQbGFuUnVsZVtdIHtcbiAgICBjb25zdCBjb250aW51b3VzQ29weUFjdGlvbnMgPSB0aGlzLmNyZWF0ZUNvcHlBY3Rpb25zKFxuICAgICAgcGxhbk5hbWUsXG4gICAgICByZXBsaWNhdGlvblZhdWx0QXJuLFxuICAgICAgZGlzYXN0ZXJSZWNvdmVyeVZhdWx0QXJuLFxuICAgICAgRHVyYXRpb24uZGF5cyhSRVRFTlRJT05fUEVSSU9EUy5FTlRFUlBSSVNFX0NPTlRJTlVPVVMpLFxuICAgICAgdW5kZWZpbmVkXG4gICAgKTtcblxuICAgIGNvbnN0IGNvbXBsaWFuY2VDb3B5QWN0aW9ucyA9IHRoaXMuY3JlYXRlQ29weUFjdGlvbnMoXG4gICAgICBwbGFuTmFtZSxcbiAgICAgIHJlcGxpY2F0aW9uVmF1bHRBcm4sXG4gICAgICBkaXNhc3RlclJlY292ZXJ5VmF1bHRBcm4sXG4gICAgICBEdXJhdGlvbi5kYXlzKFJFVEVOVElPTl9QRVJJT0RTLkVOVEVSUFJJU0VfQ09NUExJQU5DRSksXG4gICAgICBEdXJhdGlvbi5kYXlzKFJFVEVOVElPTl9QRVJJT0RTLkNPTERfU1RPUkFHRV9PTkVfWUVBUilcbiAgICApO1xuXG4gICAgcmV0dXJuIFtcbiAgICAgIC8vIENvbnRpbnVvdXMgYmFja3VwICgzNS1kYXkgbWF4IFBJVFIgd2luZG93KVxuICAgICAgbmV3IEJhY2t1cFBsYW5SdWxlKHtcbiAgICAgICAgcnVsZU5hbWU6IGAke3BsYW5OYW1lfUNvbnRpbnVvdXNgLFxuICAgICAgICBzY2hlZHVsZUV4cHJlc3Npb246IGV2ZW50cy5TY2hlZHVsZS5jcm9uKHsgaG91cjogXCIyXCIsIG1pbnV0ZTogXCIwXCIgfSksIC8vIERhaWx5IGZvciBjb250aW51b3VzIGJhY2t1cFxuICAgICAgICBkZWxldGVBZnRlcjogRHVyYXRpb24uZGF5cyhSRVRFTlRJT05fUEVSSU9EUy5FTlRFUlBSSVNFX0NPTlRJTlVPVVMpLFxuICAgICAgICBlbmFibGVDb250aW51b3VzQmFja3VwOiB0cnVlLFxuICAgICAgICBzdGFydFdpbmRvdzogRHVyYXRpb24ubWludXRlcyg2MCksXG4gICAgICAgIGNvbXBsZXRpb25XaW5kb3c6IER1cmF0aW9uLmhvdXJzKDEyKSxcbiAgICAgICAgY29weUFjdGlvbnM6IGNvbnRpbnVvdXNDb3B5QWN0aW9uc1xuICAgICAgfSksXG4gICAgICAvLyBIb3VybHkgc25hcHNob3RzIGZvciBsb25nLXRlcm0gY29tcGxpYW5jZSAoNyB5ZWFycylcbiAgICAgIG5ldyBCYWNrdXBQbGFuUnVsZSh7XG4gICAgICAgIHJ1bGVOYW1lOiBgJHtwbGFuTmFtZX1Ib3VybHlDb21wbGlhbmNlYCxcbiAgICAgICAgc2NoZWR1bGVFeHByZXNzaW9uOiBldmVudHMuU2NoZWR1bGUuY3Jvbih7IG1pbnV0ZTogXCIwXCIgfSksIC8vIEV2ZXJ5IGhvdXJcbiAgICAgICAgZGVsZXRlQWZ0ZXI6IER1cmF0aW9uLmRheXMoUkVURU5USU9OX1BFUklPRFMuRU5URVJQUklTRV9DT01QTElBTkNFKSxcbiAgICAgICAgbW92ZVRvQ29sZFN0b3JhZ2VBZnRlcjogRHVyYXRpb24uZGF5cyhcbiAgICAgICAgICBSRVRFTlRJT05fUEVSSU9EUy5DT0xEX1NUT1JBR0VfT05FX1lFQVJcbiAgICAgICAgKSxcbiAgICAgICAgc3RhcnRXaW5kb3c6IER1cmF0aW9uLm1pbnV0ZXMoNjApLFxuICAgICAgICBjb21wbGV0aW9uV2luZG93OiBEdXJhdGlvbi5ob3VycygyKSxcbiAgICAgICAgY29weUFjdGlvbnM6IGNvbXBsaWFuY2VDb3B5QWN0aW9uc1xuICAgICAgfSlcbiAgICBdO1xuICB9XG5cbiAgcHJpdmF0ZSBjcmVhdGVDb3B5QWN0aW9ucyhcbiAgICBwbGFuTmFtZTogc3RyaW5nLFxuICAgIHJlcGxpY2F0aW9uVmF1bHRBcm4/OiBzdHJpbmcsXG4gICAgZGlzYXN0ZXJSZWNvdmVyeVZhdWx0QXJuPzogc3RyaW5nLFxuICAgIGRlbGV0ZUFmdGVyPzogRHVyYXRpb24sXG4gICAgbW92ZVRvQ29sZFN0b3JhZ2VBZnRlcj86IER1cmF0aW9uXG4gICk6IEJhY2t1cFBsYW5Db3B5QWN0aW9uUHJvcHNbXSB8IHVuZGVmaW5lZCB7XG4gICAgY29uc3QgYWN0aW9uczogQmFja3VwUGxhbkNvcHlBY3Rpb25Qcm9wc1tdID0gW107XG5cbiAgICAvLyBDcm9zcy1yZWdpb24gcmVwbGljYXRpb25cbiAgICBpZiAocmVwbGljYXRpb25WYXVsdEFybikge1xuICAgICAgY29uc3QgcmVwbGljYXRpb25BY3Rpb246IEJhY2t1cFBsYW5Db3B5QWN0aW9uUHJvcHMgPSB7XG4gICAgICAgIGRlc3RpbmF0aW9uQmFja3VwVmF1bHQ6IFZhdWx0LmZyb21CYWNrdXBWYXVsdEFybihcbiAgICAgICAgICB0aGlzLFxuICAgICAgICAgIGAke3BsYW5OYW1lfVJlcGxpY2F0aW9uVmF1bHRSZWZgLFxuICAgICAgICAgIHJlcGxpY2F0aW9uVmF1bHRBcm5cbiAgICAgICAgKSxcbiAgICAgICAgLi4uKGRlbGV0ZUFmdGVyICYmIHsgZGVsZXRlQWZ0ZXIgfSksXG4gICAgICAgIC8vIE9ubHkgYWRkIGNvbGQgc3RvcmFnZSBpZiBzcGVjaWZpZWQgYW5kID49IDkwIGRheXNcbiAgICAgICAgLi4uKG1vdmVUb0NvbGRTdG9yYWdlQWZ0ZXIgJiZcbiAgICAgICAgbW92ZVRvQ29sZFN0b3JhZ2VBZnRlci50b0RheXMoKSA+PVxuICAgICAgICAgIFJFVEVOVElPTl9QRVJJT0RTLkNPTERfU1RPUkFHRV9NSU5JTVVNXG4gICAgICAgICAgPyB7IG1vdmVUb0NvbGRTdG9yYWdlQWZ0ZXIgfVxuICAgICAgICAgIDoge30pXG4gICAgICB9O1xuICAgICAgYWN0aW9ucy5wdXNoKHJlcGxpY2F0aW9uQWN0aW9uKTtcbiAgICB9XG5cbiAgICAvLyBDcm9zcy1hY2NvdW50IERSIHZhdWx0XG4gICAgaWYgKGRpc2FzdGVyUmVjb3ZlcnlWYXVsdEFybikge1xuICAgICAgY29uc3QgZHJBY3Rpb246IEJhY2t1cFBsYW5Db3B5QWN0aW9uUHJvcHMgPSB7XG4gICAgICAgIGRlc3RpbmF0aW9uQmFja3VwVmF1bHQ6IFZhdWx0LmZyb21CYWNrdXBWYXVsdEFybihcbiAgICAgICAgICB0aGlzLFxuICAgICAgICAgIGAke3BsYW5OYW1lfURpc2FzdGVyUmVjb3ZlcnlWYXVsdFJlZmAsXG4gICAgICAgICAgZGlzYXN0ZXJSZWNvdmVyeVZhdWx0QXJuXG4gICAgICAgICksXG4gICAgICAgIC4uLihkZWxldGVBZnRlciAmJiB7IGRlbGV0ZUFmdGVyIH0pLFxuICAgICAgICAvLyBPbmx5IGFkZCBjb2xkIHN0b3JhZ2UgaWYgc3BlY2lmaWVkIGFuZCA+PSA5MCBkYXlzXG4gICAgICAgIC4uLihtb3ZlVG9Db2xkU3RvcmFnZUFmdGVyICYmXG4gICAgICAgIG1vdmVUb0NvbGRTdG9yYWdlQWZ0ZXIudG9EYXlzKCkgPj1cbiAgICAgICAgICBSRVRFTlRJT05fUEVSSU9EUy5DT0xEX1NUT1JBR0VfTUlOSU1VTVxuICAgICAgICAgID8geyBtb3ZlVG9Db2xkU3RvcmFnZUFmdGVyIH1cbiAgICAgICAgICA6IHt9KVxuICAgICAgfTtcbiAgICAgIGFjdGlvbnMucHVzaChkckFjdGlvbik7XG4gICAgfVxuXG4gICAgcmV0dXJuIGFjdGlvbnMubGVuZ3RoID4gMCA/IGFjdGlvbnMgOiB1bmRlZmluZWQ7XG4gIH1cbn1cbiJdfQ==
@@ -6,6 +6,8 @@ const aws_1 = require("../../config/aws");
6
6
  const cloudTrail_1 = require("../../config/aws/cloudTrail");
7
7
  const aws_cdk_lib_2 = require("aws-cdk-lib");
8
8
  const getConfig_1 = require("../../utils/getConfig");
9
+ const disasterRecovery_1 = require("../../config/aws/disasterRecovery");
10
+ const util_1 = require("@fjall/util");
9
11
  class ManagedAccount extends aws_cdk_lib_1.Stack {
10
12
  constructor(scope, id, props) {
11
13
  super(scope, id, props);
@@ -28,9 +30,20 @@ class ManagedAccount extends aws_cdk_lib_1.Stack {
28
30
  accountId: account.accountId.value,
29
31
  eventBusArn: eventBus.defaultEventBusArn.value
30
32
  });
31
- // Export environment for applications to use in tags
32
33
  const config = (0, getConfig_1.getConfig)();
33
34
  const environment = config.environment || "unknown";
35
+ const fjallConfig = util_1.Config.loadConfig();
36
+ const isComplianceAccount = environment === "compliance";
37
+ const isReplicationRegion = config.disasterRecoveryRegion &&
38
+ props.region === config.disasterRecoveryRegion;
39
+ if (environment === "production" ||
40
+ isComplianceAccount ||
41
+ isReplicationRegion) {
42
+ new disasterRecovery_1.DisasterRecovery(this, "DisasterRecovery", {
43
+ region: props.region,
44
+ accountId: props.accountId
45
+ });
46
+ }
34
47
  new aws_cdk_lib_2.CfnOutput(this, "Environment", {
35
48
  key: "Environment",
36
49
  value: environment,
@@ -40,4 +53,4 @@ class ManagedAccount extends aws_cdk_lib_1.Stack {
40
53
  }
41
54
  }
42
55
  exports.ManagedAccount = ManagedAccount;
43
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFuYWdlZEFjY291bnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9saWIvcGF0dGVybnMvYXdzL21hbmFnZWRBY2NvdW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLDZDQUFnRDtBQUNoRCwwQ0FNMEI7QUFHMUIsNERBQW9FO0FBQ3BFLDZDQUF3QztBQUN4QyxxREFBa0Q7QUFPbEQsTUFBYSxjQUFlLFNBQVEsbUJBQUs7SUFDdkMsWUFBWSxLQUFnQixFQUFFLEVBQVUsRUFBRSxLQUEwQjtRQUNsRSxLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsRUFBRSxLQUFLLENBQUMsQ0FBQztRQUV4QixNQUFNLFlBQVksR0FBRyxJQUFJLG9CQUFjLENBQUMsSUFBSSxFQUFFLGdCQUFnQixDQUFDLENBQUM7UUFFaEUsTUFBTSxPQUFPLEdBQUcsSUFBSSxlQUFTLENBQUMsSUFBSSxFQUFFLFdBQVcsQ0FBQyxDQUFDO1FBRWpELE1BQU0sUUFBUSxHQUFHLElBQUkscUJBQWUsQ0FBQyxJQUFJLEVBQUUsVUFBVSxDQUFDLENBQUM7UUFFdkQsSUFBSSxFQUFFLEtBQUssZ0JBQWdCLEVBQUUsQ0FBQztZQUM1QixJQUFJLGdCQUFVLENBQUMsSUFBSSxFQUFFLFlBQVksRUFBRTtnQkFDakMsU0FBUyxFQUFFLEtBQUssQ0FBQyxTQUFTO2dCQUMxQixNQUFNLEVBQUUsS0FBSyxDQUFDLE1BQU07Z0JBQ3BCLE9BQU8sRUFBRSxZQUFZLENBQUMsc0JBQXNCLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUM7YUFDakUsQ0FBQyxDQUFDO1FBQ0wsQ0FBQztRQUVELElBQUksa0NBQXFCLENBQUMsSUFBSSxFQUFFLFlBQVksRUFBRTtZQUM1QyxTQUFTLEVBQUUsT0FBTyxDQUFDLFNBQVMsQ0FBQyxLQUFLO1lBQ2xDLE1BQU0sRUFBRSxLQUFLLENBQUMsTUFBTTtTQUNyQixDQUFDLENBQUM7UUFFSCxJQUFJLHFCQUFlLENBQUMsSUFBSSxFQUFFLGlCQUFpQixFQUFFO1lBQzNDLE1BQU0sRUFBRSxLQUFLLENBQUMsTUFBTTtZQUNwQixTQUFTLEVBQUUsT0FBTyxDQUFDLFNBQVMsQ0FBQyxLQUFLO1lBQ2xDLFdBQVcsRUFBRSxRQUFRLENBQUMsa0JBQWtCLENBQUMsS0FBSztTQUMvQyxDQUFDLENBQUM7UUFFSCxxREFBcUQ7UUFDckQsTUFBTSxNQUFNLEdBQUcsSUFBQSxxQkFBUyxHQUFFLENBQUM7UUFDM0IsTUFBTSxXQUFXLEdBQUcsTUFBTSxDQUFDLFdBQVcsSUFBSSxTQUFTLENBQUM7UUFFcEQsSUFBSSx1QkFBUyxDQUFDLElBQUksRUFBRSxhQUFhLEVBQUU7WUFDakMsR0FBRyxFQUFFLGFBQWE7WUFDbEIsS0FBSyxFQUFFLFdBQVc7WUFDbEIsVUFBVSxFQUFFLGFBQWE7WUFDekIsV0FBVyxFQUNULDRFQUE0RTtTQUMvRSxDQUFDLENBQUM7SUFDTCxDQUFDO0NBQ0Y7QUF6Q0Qsd0NBeUNDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgU3RhY2ssIFN0YWNrUHJvcHMgfSBmcm9tIFwiYXdzLWNkay1saWJcIjtcbmltcG9ydCB7XG4gIE9yZ2FuaXNhdGlvbklkLFxuICBBY2NvdW50SWQsXG4gIElwYW1Qb29sSWQsXG4gIEVjckRlZmF1bHRJbWFnZSxcbiAgRGVmYXVsdEV2ZW50QnVzXG59IGZyb20gXCIuLi8uLi9jb25maWcvYXdzXCI7XG5pbXBvcnQge30gZnJvbSBcImF3cy1jZGstbGliL2F3cy1ldmVudHNcIjtcbmltcG9ydCB7IENvbnN0cnVjdCB9IGZyb20gXCJjb25zdHJ1Y3RzXCI7XG5pbXBvcnQgeyBNYW5hZ2VtZW50RXZlbnRzVHJhaWwgfSBmcm9tIFwiLi4vLi4vY29uZmlnL2F3cy9jbG91ZFRyYWlsXCI7XG5pbXBvcnQgeyBDZm5PdXRwdXQgfSBmcm9tIFwiYXdzLWNkay1saWJcIjtcbmltcG9ydCB7IGdldENvbmZpZyB9IGZyb20gXCIuLi8uLi91dGlscy9nZXRDb25maWdcIjtcblxuZXhwb3J0IGludGVyZmFjZSBNYW5hZ2VkQWNjb3VudFByb3BzIGV4dGVuZHMgU3RhY2tQcm9wcyB7XG4gIGFjY291bnRJZDogc3RyaW5nO1xuICByZWdpb246IHN0cmluZztcbn1cblxuZXhwb3J0IGNsYXNzIE1hbmFnZWRBY2NvdW50IGV4dGVuZHMgU3RhY2sge1xuICBjb25zdHJ1Y3RvcihzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBwcm9wczogTWFuYWdlZEFjY291bnRQcm9wcykge1xuICAgIHN1cGVyKHNjb3BlLCBpZCwgcHJvcHMpO1xuXG4gICAgY29uc3Qgb3JnYW5pc2F0aW9uID0gbmV3IE9yZ2FuaXNhdGlvbklkKHRoaXMsIFwiT3JnYW5pc2F0aW9uSWRcIik7XG5cbiAgICBjb25zdCBhY2NvdW50ID0gbmV3IEFjY291bnRJZCh0aGlzLCBcIkFjY291bnRJZFwiKTtcblxuICAgIGNvbnN0IGV2ZW50QnVzID0gbmV3IERlZmF1bHRFdmVudEJ1cyh0aGlzLCBcIkV2ZW50QnVzXCIpO1xuXG4gICAgaWYgKGlkID09PSBcIk1hbmFnZWRBY2NvdW50XCIpIHtcbiAgICAgIG5ldyBJcGFtUG9vbElkKHRoaXMsIFwiSXBhbVBvb2xJZFwiLCB7XG4gICAgICAgIGFjY291bnRJZDogcHJvcHMuYWNjb3VudElkLFxuICAgICAgICByZWdpb246IHByb3BzLnJlZ2lvbixcbiAgICAgICAgb3duZXJJZDogb3JnYW5pc2F0aW9uLm9yZ2FuaXNhdGlvbkFjY291bnRBcm4udmFsdWUuc3BsaXQoXCI6XCIpWzRdXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBuZXcgTWFuYWdlbWVudEV2ZW50c1RyYWlsKHRoaXMsIFwiQ2xvdWRUcmFpbFwiLCB7XG4gICAgICBhY2NvdW50SWQ6IGFjY291bnQuYWNjb3VudElkLnZhbHVlLFxuICAgICAgcmVnaW9uOiBwcm9wcy5yZWdpb25cbiAgICB9KTtcblxuICAgIG5ldyBFY3JEZWZhdWx0SW1hZ2UodGhpcywgXCJFY3JEZWZhdWx0SW1hZ2VcIiwge1xuICAgICAgcmVnaW9uOiBwcm9wcy5yZWdpb24sXG4gICAgICBhY2NvdW50SWQ6IGFjY291bnQuYWNjb3VudElkLnZhbHVlLFxuICAgICAgZXZlbnRCdXNBcm46IGV2ZW50QnVzLmRlZmF1bHRFdmVudEJ1c0Fybi52YWx1ZVxuICAgIH0pO1xuXG4gICAgLy8gRXhwb3J0IGVudmlyb25tZW50IGZvciBhcHBsaWNhdGlvbnMgdG8gdXNlIGluIHRhZ3NcbiAgICBjb25zdCBjb25maWcgPSBnZXRDb25maWcoKTtcbiAgICBjb25zdCBlbnZpcm9ubWVudCA9IGNvbmZpZy5lbnZpcm9ubWVudCB8fCBcInVua25vd25cIjtcblxuICAgIG5ldyBDZm5PdXRwdXQodGhpcywgXCJFbnZpcm9ubWVudFwiLCB7XG4gICAgICBrZXk6IFwiRW52aXJvbm1lbnRcIixcbiAgICAgIHZhbHVlOiBlbnZpcm9ubWVudCxcbiAgICAgIGV4cG9ydE5hbWU6IFwiRW52aXJvbm1lbnRcIixcbiAgICAgIGRlc2NyaXB0aW9uOlxuICAgICAgICBcIkVudmlyb25tZW50IHR5cGUgZm9yIHRoaXMgYWNjb3VudCAoZS5nLiwgcHJvZHVjdGlvbiwgc3RhZ2luZywgZGV2ZWxvcG1lbnQpXCJcbiAgICB9KTtcbiAgfVxufVxuIl19
56
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFuYWdlZEFjY291bnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9saWIvcGF0dGVybnMvYXdzL21hbmFnZWRBY2NvdW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLDZDQUFnRDtBQUNoRCwwQ0FNMEI7QUFFMUIsNERBQW9FO0FBQ3BFLDZDQUF3QztBQUN4QyxxREFBa0Q7QUFDbEQsd0VBQXFFO0FBQ3JFLHNDQUFvRDtBQU9wRCxNQUFhLGNBQWUsU0FBUSxtQkFBSztJQUN2QyxZQUFZLEtBQWdCLEVBQUUsRUFBVSxFQUFFLEtBQTBCO1FBQ2xFLEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxFQUFFLEtBQUssQ0FBQyxDQUFDO1FBRXhCLE1BQU0sWUFBWSxHQUFHLElBQUksb0JBQWMsQ0FBQyxJQUFJLEVBQUUsZ0JBQWdCLENBQUMsQ0FBQztRQUVoRSxNQUFNLE9BQU8sR0FBRyxJQUFJLGVBQVMsQ0FBQyxJQUFJLEVBQUUsV0FBVyxDQUFDLENBQUM7UUFFakQsTUFBTSxRQUFRLEdBQUcsSUFBSSxxQkFBZSxDQUFDLElBQUksRUFBRSxVQUFVLENBQUMsQ0FBQztRQUV2RCxJQUFJLEVBQUUsS0FBSyxnQkFBZ0IsRUFBRSxDQUFDO1lBQzVCLElBQUksZ0JBQVUsQ0FBQyxJQUFJLEVBQUUsWUFBWSxFQUFFO2dCQUNqQyxTQUFTLEVBQUUsS0FBSyxDQUFDLFNBQVM7Z0JBQzFCLE1BQU0sRUFBRSxLQUFLLENBQUMsTUFBTTtnQkFDcEIsT0FBTyxFQUFFLFlBQVksQ0FBQyxzQkFBc0IsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQzthQUNqRSxDQUFDLENBQUM7UUFDTCxDQUFDO1FBRUQsSUFBSSxrQ0FBcUIsQ0FBQyxJQUFJLEVBQUUsWUFBWSxFQUFFO1lBQzVDLFNBQVMsRUFBRSxPQUFPLENBQUMsU0FBUyxDQUFDLEtBQUs7WUFDbEMsTUFBTSxFQUFFLEtBQUssQ0FBQyxNQUFNO1NBQ3JCLENBQUMsQ0FBQztRQUVILElBQUkscUJBQWUsQ0FBQyxJQUFJLEVBQUUsaUJBQWlCLEVBQUU7WUFDM0MsTUFBTSxFQUFFLEtBQUssQ0FBQyxNQUFNO1lBQ3BCLFNBQVMsRUFBRSxPQUFPLENBQUMsU0FBUyxDQUFDLEtBQUs7WUFDbEMsV0FBVyxFQUFFLFFBQVEsQ0FBQyxrQkFBa0IsQ0FBQyxLQUFLO1NBQy9DLENBQUMsQ0FBQztRQUVILE1BQU0sTUFBTSxHQUFHLElBQUEscUJBQVMsR0FBRSxDQUFDO1FBQzNCLE1BQU0sV0FBVyxHQUFHLE1BQU0sQ0FBQyxXQUFXLElBQUksU0FBUyxDQUFDO1FBQ3BELE1BQU0sV0FBVyxHQUFHLGFBQVcsQ0FBQyxVQUFVLEVBQUUsQ0FBQztRQUU3QyxNQUFNLG1CQUFtQixHQUFHLFdBQVcsS0FBSyxZQUFZLENBQUM7UUFDekQsTUFBTSxtQkFBbUIsR0FDdkIsTUFBTSxDQUFDLHNCQUFzQjtZQUM3QixLQUFLLENBQUMsTUFBTSxLQUFLLE1BQU0sQ0FBQyxzQkFBc0IsQ0FBQztRQUVqRCxJQUNFLFdBQVcsS0FBSyxZQUFZO1lBQzVCLG1CQUFtQjtZQUNuQixtQkFBbUIsRUFDbkIsQ0FBQztZQUNELElBQUksbUNBQWdCLENBQUMsSUFBSSxFQUFFLGtCQUFrQixFQUFFO2dCQUM3QyxNQUFNLEVBQUUsS0FBSyxDQUFDLE1BQU07Z0JBQ3BCLFNBQVMsRUFBRSxLQUFLLENBQUMsU0FBUzthQUMzQixDQUFDLENBQUM7UUFDTCxDQUFDO1FBRUQsSUFBSSx1QkFBUyxDQUFDLElBQUksRUFBRSxhQUFhLEVBQUU7WUFDakMsR0FBRyxFQUFFLGFBQWE7WUFDbEIsS0FBSyxFQUFFLFdBQVc7WUFDbEIsVUFBVSxFQUFFLGFBQWE7WUFDekIsV0FBVyxFQUNULDRFQUE0RTtTQUMvRSxDQUFDLENBQUM7SUFDTCxDQUFDO0NBQ0Y7QUF6REQsd0NBeURDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgU3RhY2ssIFN0YWNrUHJvcHMgfSBmcm9tIFwiYXdzLWNkay1saWJcIjtcbmltcG9ydCB7XG4gIE9yZ2FuaXNhdGlvbklkLFxuICBBY2NvdW50SWQsXG4gIElwYW1Qb29sSWQsXG4gIEVjckRlZmF1bHRJbWFnZSxcbiAgRGVmYXVsdEV2ZW50QnVzXG59IGZyb20gXCIuLi8uLi9jb25maWcvYXdzXCI7XG5pbXBvcnQgeyBDb25zdHJ1Y3QgfSBmcm9tIFwiY29uc3RydWN0c1wiO1xuaW1wb3J0IHsgTWFuYWdlbWVudEV2ZW50c1RyYWlsIH0gZnJvbSBcIi4uLy4uL2NvbmZpZy9hd3MvY2xvdWRUcmFpbFwiO1xuaW1wb3J0IHsgQ2ZuT3V0cHV0IH0gZnJvbSBcImF3cy1jZGstbGliXCI7XG5pbXBvcnQgeyBnZXRDb25maWcgfSBmcm9tIFwiLi4vLi4vdXRpbHMvZ2V0Q29uZmlnXCI7XG5pbXBvcnQgeyBEaXNhc3RlclJlY292ZXJ5IH0gZnJvbSBcIi4uLy4uL2NvbmZpZy9hd3MvZGlzYXN0ZXJSZWNvdmVyeVwiO1xuaW1wb3J0IHsgQ29uZmlnIGFzIEZqYWxsQ29uZmlnIH0gZnJvbSBcIkBmamFsbC91dGlsXCI7XG5cbmV4cG9ydCBpbnRlcmZhY2UgTWFuYWdlZEFjY291bnRQcm9wcyBleHRlbmRzIFN0YWNrUHJvcHMge1xuICBhY2NvdW50SWQ6IHN0cmluZztcbiAgcmVnaW9uOiBzdHJpbmc7XG59XG5cbmV4cG9ydCBjbGFzcyBNYW5hZ2VkQWNjb3VudCBleHRlbmRzIFN0YWNrIHtcbiAgY29uc3RydWN0b3Ioc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgcHJvcHM6IE1hbmFnZWRBY2NvdW50UHJvcHMpIHtcbiAgICBzdXBlcihzY29wZSwgaWQsIHByb3BzKTtcblxuICAgIGNvbnN0IG9yZ2FuaXNhdGlvbiA9IG5ldyBPcmdhbmlzYXRpb25JZCh0aGlzLCBcIk9yZ2FuaXNhdGlvbklkXCIpO1xuXG4gICAgY29uc3QgYWNjb3VudCA9IG5ldyBBY2NvdW50SWQodGhpcywgXCJBY2NvdW50SWRcIik7XG5cbiAgICBjb25zdCBldmVudEJ1cyA9IG5ldyBEZWZhdWx0RXZlbnRCdXModGhpcywgXCJFdmVudEJ1c1wiKTtcblxuICAgIGlmIChpZCA9PT0gXCJNYW5hZ2VkQWNjb3VudFwiKSB7XG4gICAgICBuZXcgSXBhbVBvb2xJZCh0aGlzLCBcIklwYW1Qb29sSWRcIiwge1xuICAgICAgICBhY2NvdW50SWQ6IHByb3BzLmFjY291bnRJZCxcbiAgICAgICAgcmVnaW9uOiBwcm9wcy5yZWdpb24sXG4gICAgICAgIG93bmVySWQ6IG9yZ2FuaXNhdGlvbi5vcmdhbmlzYXRpb25BY2NvdW50QXJuLnZhbHVlLnNwbGl0KFwiOlwiKVs0XVxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgbmV3IE1hbmFnZW1lbnRFdmVudHNUcmFpbCh0aGlzLCBcIkNsb3VkVHJhaWxcIiwge1xuICAgICAgYWNjb3VudElkOiBhY2NvdW50LmFjY291bnRJZC52YWx1ZSxcbiAgICAgIHJlZ2lvbjogcHJvcHMucmVnaW9uXG4gICAgfSk7XG5cbiAgICBuZXcgRWNyRGVmYXVsdEltYWdlKHRoaXMsIFwiRWNyRGVmYXVsdEltYWdlXCIsIHtcbiAgICAgIHJlZ2lvbjogcHJvcHMucmVnaW9uLFxuICAgICAgYWNjb3VudElkOiBhY2NvdW50LmFjY291bnRJZC52YWx1ZSxcbiAgICAgIGV2ZW50QnVzQXJuOiBldmVudEJ1cy5kZWZhdWx0RXZlbnRCdXNBcm4udmFsdWVcbiAgICB9KTtcblxuICAgIGNvbnN0IGNvbmZpZyA9IGdldENvbmZpZygpO1xuICAgIGNvbnN0IGVudmlyb25tZW50ID0gY29uZmlnLmVudmlyb25tZW50IHx8IFwidW5rbm93blwiO1xuICAgIGNvbnN0IGZqYWxsQ29uZmlnID0gRmphbGxDb25maWcubG9hZENvbmZpZygpO1xuXG4gICAgY29uc3QgaXNDb21wbGlhbmNlQWNjb3VudCA9IGVudmlyb25tZW50ID09PSBcImNvbXBsaWFuY2VcIjtcbiAgICBjb25zdCBpc1JlcGxpY2F0aW9uUmVnaW9uID1cbiAgICAgIGNvbmZpZy5kaXNhc3RlclJlY292ZXJ5UmVnaW9uICYmXG4gICAgICBwcm9wcy5yZWdpb24gPT09IGNvbmZpZy5kaXNhc3RlclJlY292ZXJ5UmVnaW9uO1xuXG4gICAgaWYgKFxuICAgICAgZW52aXJvbm1lbnQgPT09IFwicHJvZHVjdGlvblwiIHx8XG4gICAgICBpc0NvbXBsaWFuY2VBY2NvdW50IHx8XG4gICAgICBpc1JlcGxpY2F0aW9uUmVnaW9uXG4gICAgKSB7XG4gICAgICBuZXcgRGlzYXN0ZXJSZWNvdmVyeSh0aGlzLCBcIkRpc2FzdGVyUmVjb3ZlcnlcIiwge1xuICAgICAgICByZWdpb246IHByb3BzLnJlZ2lvbixcbiAgICAgICAgYWNjb3VudElkOiBwcm9wcy5hY2NvdW50SWRcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIG5ldyBDZm5PdXRwdXQodGhpcywgXCJFbnZpcm9ubWVudFwiLCB7XG4gICAgICBrZXk6IFwiRW52aXJvbm1lbnRcIixcbiAgICAgIHZhbHVlOiBlbnZpcm9ubWVudCxcbiAgICAgIGV4cG9ydE5hbWU6IFwiRW52aXJvbm1lbnRcIixcbiAgICAgIGRlc2NyaXB0aW9uOlxuICAgICAgICBcIkVudmlyb25tZW50IHR5cGUgZm9yIHRoaXMgYWNjb3VudCAoZS5nLiwgcHJvZHVjdGlvbiwgc3RhZ2luZywgZGV2ZWxvcG1lbnQpXCJcbiAgICB9KTtcbiAgfVxufVxuIl19
@@ -0,0 +1,19 @@
1
+ import { Construct } from "constructs";
2
+ import { CfnOutput } from "aws-cdk-lib";
3
+ import { BackupPlan as Plan, BackupSelection, BackupPlanRule } from "aws-cdk-lib/aws-backup";
4
+ import { BackupVault } from "./backupVault";
5
+ export interface BackupPlanProps {
6
+ planName: string;
7
+ rules: BackupPlanRule[];
8
+ backupVault: BackupVault;
9
+ tagValue: string;
10
+ tagKey?: string;
11
+ }
12
+ export declare class BackupPlan extends Construct {
13
+ readonly plan: Plan;
14
+ readonly selection: BackupSelection;
15
+ readonly planArn: CfnOutput;
16
+ constructor(scope: Construct, id: string, props: BackupPlanProps);
17
+ private createBackupRole;
18
+ static build(id: string, props: BackupPlanProps): (scope: Construct) => BackupPlan;
19
+ }
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BackupPlan = void 0;
4
+ const constructs_1 = require("constructs");
5
+ const aws_cdk_lib_1 = require("aws-cdk-lib");
6
+ const aws_backup_1 = require("aws-cdk-lib/aws-backup");
7
+ const iam = require("aws-cdk-lib/aws-iam");
8
+ class BackupPlan extends constructs_1.Construct {
9
+ constructor(scope, id, props) {
10
+ super(scope, id);
11
+ const tagKey = props.tagKey || "fjall:disasterRecovery:tier";
12
+ // Create backup plan with provided rules
13
+ this.plan = new aws_backup_1.BackupPlan(this, `${props.planName}Plan`, {
14
+ backupPlanName: props.planName,
15
+ backupVault: props.backupVault.vault,
16
+ backupPlanRules: props.rules
17
+ });
18
+ // Create tag-based selection
19
+ this.selection = new aws_backup_1.BackupSelection(this, `${props.planName}Selection`, {
20
+ backupPlan: this.plan,
21
+ resources: [aws_backup_1.BackupResource.fromTag(tagKey, props.tagValue)],
22
+ role: this.createBackupRole(props)
23
+ });
24
+ // Export plan ARN
25
+ const planNamePascal = props.planName.charAt(0).toUpperCase() + props.planName.slice(1);
26
+ this.planArn = new aws_cdk_lib_1.CfnOutput(this, `${props.planName}PlanArn`, {
27
+ key: `${props.planName}PlanArn`,
28
+ value: this.plan.backupPlanArn,
29
+ exportName: `${planNamePascal}BackupPlanArn`
30
+ });
31
+ }
32
+ createBackupRole(props) {
33
+ const role = new iam.Role(this, `${props.planName}BackupRole`, {
34
+ assumedBy: new iam.ServicePrincipal("backup.amazonaws.com"),
35
+ description: `Backup role for ${props.planName}`,
36
+ managedPolicies: [
37
+ // Core backup policies
38
+ iam.ManagedPolicy.fromAwsManagedPolicyName("service-role/AWSBackupServiceRolePolicyForBackup"),
39
+ iam.ManagedPolicy.fromAwsManagedPolicyName("service-role/AWSBackupServiceRolePolicyForRestores"),
40
+ // S3 backup support
41
+ iam.ManagedPolicy.fromAwsManagedPolicyName("AWSBackupServiceRolePolicyForS3Backup"),
42
+ iam.ManagedPolicy.fromAwsManagedPolicyName("AWSBackupServiceRolePolicyForS3Restore")
43
+ ]
44
+ });
45
+ role.addToPolicy(new iam.PolicyStatement({
46
+ effect: iam.Effect.ALLOW,
47
+ actions: [
48
+ "rds:ModifyDBInstance",
49
+ "rds:DescribeDBInstanceAutomatedBackups",
50
+ "rds:RestoreDBInstanceToPointInTime",
51
+ "rds:DescribeDBInstances",
52
+ "rds:DescribeDBClusters",
53
+ "rds:RestoreDBClusterToPointInTime"
54
+ ],
55
+ resources: ["*"]
56
+ }));
57
+ role.addToPolicy(new iam.PolicyStatement({
58
+ effect: iam.Effect.ALLOW,
59
+ actions: ["backup:CopyIntoBackupVault", "backup:CopyFromBackupVault"],
60
+ resources: ["*"] // TODO: Tighten up
61
+ }));
62
+ return role;
63
+ }
64
+ static build(id, props) {
65
+ return (scope) => {
66
+ return new BackupPlan(scope, id, props);
67
+ };
68
+ }
69
+ }
70
+ exports.BackupPlan = BackupPlan;
71
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFja3VwUGxhbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL2xpYi9yZXNvdXJjZXMvYXdzL2JhY2t1cC9iYWNrdXBQbGFuLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLDJDQUF1QztBQUN2Qyw2Q0FBd0M7QUFDeEMsdURBS2dDO0FBQ2hDLDJDQUEyQztBQVczQyxNQUFhLFVBQVcsU0FBUSxzQkFBUztJQUt2QyxZQUFZLEtBQWdCLEVBQUUsRUFBVSxFQUFFLEtBQXNCO1FBQzlELEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFFakIsTUFBTSxNQUFNLEdBQUcsS0FBSyxDQUFDLE1BQU0sSUFBSSw2QkFBNkIsQ0FBQztRQUU3RCx5Q0FBeUM7UUFDekMsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLHVCQUFJLENBQUMsSUFBSSxFQUFFLEdBQUcsS0FBSyxDQUFDLFFBQVEsTUFBTSxFQUFFO1lBQ2xELGNBQWMsRUFBRSxLQUFLLENBQUMsUUFBUTtZQUM5QixXQUFXLEVBQUUsS0FBSyxDQUFDLFdBQVcsQ0FBQyxLQUFLO1lBQ3BDLGVBQWUsRUFBRSxLQUFLLENBQUMsS0FBSztTQUM3QixDQUFDLENBQUM7UUFFSCw2QkFBNkI7UUFDN0IsSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLDRCQUFlLENBQUMsSUFBSSxFQUFFLEdBQUcsS0FBSyxDQUFDLFFBQVEsV0FBVyxFQUFFO1lBQ3ZFLFVBQVUsRUFBRSxJQUFJLENBQUMsSUFBSTtZQUNyQixTQUFTLEVBQUUsQ0FBQywyQkFBYyxDQUFDLE9BQU8sQ0FBQyxNQUFNLEVBQUUsS0FBSyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1lBQzNELElBQUksRUFBRSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsS0FBSyxDQUFDO1NBQ25DLENBQUMsQ0FBQztRQUVILGtCQUFrQjtRQUNsQixNQUFNLGNBQWMsR0FDbEIsS0FBSyxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsV0FBVyxFQUFFLEdBQUcsS0FBSyxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFFbkUsSUFBSSxDQUFDLE9BQU8sR0FBRyxJQUFJLHVCQUFTLENBQUMsSUFBSSxFQUFFLEdBQUcsS0FBSyxDQUFDLFFBQVEsU0FBUyxFQUFFO1lBQzdELEdBQUcsRUFBRSxHQUFHLEtBQUssQ0FBQyxRQUFRLFNBQVM7WUFDL0IsS0FBSyxFQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsYUFBYTtZQUM5QixVQUFVLEVBQUUsR0FBRyxjQUFjLGVBQWU7U0FDN0MsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVPLGdCQUFnQixDQUFDLEtBQXNCO1FBQzdDLE1BQU0sSUFBSSxHQUFHLElBQUksR0FBRyxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsR0FBRyxLQUFLLENBQUMsUUFBUSxZQUFZLEVBQUU7WUFDN0QsU0FBUyxFQUFFLElBQUksR0FBRyxDQUFDLGdCQUFnQixDQUFDLHNCQUFzQixDQUFDO1lBQzNELFdBQVcsRUFBRSxtQkFBbUIsS0FBSyxDQUFDLFFBQVEsRUFBRTtZQUNoRCxlQUFlLEVBQUU7Z0JBQ2YsdUJBQXVCO2dCQUN2QixHQUFHLENBQUMsYUFBYSxDQUFDLHdCQUF3QixDQUN4QyxrREFBa0QsQ0FDbkQ7Z0JBQ0QsR0FBRyxDQUFDLGFBQWEsQ0FBQyx3QkFBd0IsQ0FDeEMsb0RBQW9ELENBQ3JEO2dCQUNELG9CQUFvQjtnQkFDcEIsR0FBRyxDQUFDLGFBQWEsQ0FBQyx3QkFBd0IsQ0FDeEMsdUNBQXVDLENBQ3hDO2dCQUNELEdBQUcsQ0FBQyxhQUFhLENBQUMsd0JBQXdCLENBQ3hDLHdDQUF3QyxDQUN6QzthQUNGO1NBQ0YsQ0FBQyxDQUFDO1FBRUgsSUFBSSxDQUFDLFdBQVcsQ0FDZCxJQUFJLEdBQUcsQ0FBQyxlQUFlLENBQUM7WUFDdEIsTUFBTSxFQUFFLEdBQUcsQ0FBQyxNQUFNLENBQUMsS0FBSztZQUN4QixPQUFPLEVBQUU7Z0JBQ1Asc0JBQXNCO2dCQUN0Qix3Q0FBd0M7Z0JBQ3hDLG9DQUFvQztnQkFDcEMseUJBQXlCO2dCQUN6Qix3QkFBd0I7Z0JBQ3hCLG1DQUFtQzthQUNwQztZQUNELFNBQVMsRUFBRSxDQUFDLEdBQUcsQ0FBQztTQUNqQixDQUFDLENBQ0gsQ0FBQztRQUVGLElBQUksQ0FBQyxXQUFXLENBQ2QsSUFBSSxHQUFHLENBQUMsZUFBZSxDQUFDO1lBQ3RCLE1BQU0sRUFBRSxHQUFHLENBQUMsTUFBTSxDQUFDLEtBQUs7WUFDeEIsT0FBTyxFQUFFLENBQUMsNEJBQTRCLEVBQUUsNEJBQTRCLENBQUM7WUFDckUsU0FBUyxFQUFFLENBQUMsR0FBRyxDQUFDLENBQUMsbUJBQW1CO1NBQ3JDLENBQUMsQ0FDSCxDQUFDO1FBRUYsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBRUQsTUFBTSxDQUFDLEtBQUssQ0FBQyxFQUFVLEVBQUUsS0FBc0I7UUFDN0MsT0FBTyxDQUFDLEtBQWdCLEVBQUUsRUFBRTtZQUMxQixPQUFPLElBQUksVUFBVSxDQUFDLEtBQUssRUFBRSxFQUFFLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDMUMsQ0FBQyxDQUFDO0lBQ0osQ0FBQztDQUNGO0FBeEZELGdDQXdGQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbnN0cnVjdCB9IGZyb20gXCJjb25zdHJ1Y3RzXCI7XG5pbXBvcnQgeyBDZm5PdXRwdXQgfSBmcm9tIFwiYXdzLWNkay1saWJcIjtcbmltcG9ydCB7XG4gIEJhY2t1cFBsYW4gYXMgUGxhbixcbiAgQmFja3VwU2VsZWN0aW9uLFxuICBCYWNrdXBSZXNvdXJjZSxcbiAgQmFja3VwUGxhblJ1bGVcbn0gZnJvbSBcImF3cy1jZGstbGliL2F3cy1iYWNrdXBcIjtcbmltcG9ydCAqIGFzIGlhbSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWlhbVwiO1xuaW1wb3J0IHsgQmFja3VwVmF1bHQgfSBmcm9tIFwiLi9iYWNrdXBWYXVsdFwiO1xuXG5leHBvcnQgaW50ZXJmYWNlIEJhY2t1cFBsYW5Qcm9wcyB7XG4gIHBsYW5OYW1lOiBzdHJpbmc7XG4gIHJ1bGVzOiBCYWNrdXBQbGFuUnVsZVtdO1xuICBiYWNrdXBWYXVsdDogQmFja3VwVmF1bHQ7XG4gIHRhZ1ZhbHVlOiBzdHJpbmc7XG4gIHRhZ0tleT86IHN0cmluZztcbn1cblxuZXhwb3J0IGNsYXNzIEJhY2t1cFBsYW4gZXh0ZW5kcyBDb25zdHJ1Y3Qge1xuICBwdWJsaWMgcmVhZG9ubHkgcGxhbjogUGxhbjtcbiAgcHVibGljIHJlYWRvbmx5IHNlbGVjdGlvbjogQmFja3VwU2VsZWN0aW9uO1xuICBwdWJsaWMgcmVhZG9ubHkgcGxhbkFybjogQ2ZuT3V0cHV0O1xuXG4gIGNvbnN0cnVjdG9yKHNjb3BlOiBDb25zdHJ1Y3QsIGlkOiBzdHJpbmcsIHByb3BzOiBCYWNrdXBQbGFuUHJvcHMpIHtcbiAgICBzdXBlcihzY29wZSwgaWQpO1xuXG4gICAgY29uc3QgdGFnS2V5ID0gcHJvcHMudGFnS2V5IHx8IFwiZmphbGw6ZGlzYXN0ZXJSZWNvdmVyeTp0aWVyXCI7XG5cbiAgICAvLyBDcmVhdGUgYmFja3VwIHBsYW4gd2l0aCBwcm92aWRlZCBydWxlc1xuICAgIHRoaXMucGxhbiA9IG5ldyBQbGFuKHRoaXMsIGAke3Byb3BzLnBsYW5OYW1lfVBsYW5gLCB7XG4gICAgICBiYWNrdXBQbGFuTmFtZTogcHJvcHMucGxhbk5hbWUsXG4gICAgICBiYWNrdXBWYXVsdDogcHJvcHMuYmFja3VwVmF1bHQudmF1bHQsXG4gICAgICBiYWNrdXBQbGFuUnVsZXM6IHByb3BzLnJ1bGVzXG4gICAgfSk7XG5cbiAgICAvLyBDcmVhdGUgdGFnLWJhc2VkIHNlbGVjdGlvblxuICAgIHRoaXMuc2VsZWN0aW9uID0gbmV3IEJhY2t1cFNlbGVjdGlvbih0aGlzLCBgJHtwcm9wcy5wbGFuTmFtZX1TZWxlY3Rpb25gLCB7XG4gICAgICBiYWNrdXBQbGFuOiB0aGlzLnBsYW4sXG4gICAgICByZXNvdXJjZXM6IFtCYWNrdXBSZXNvdXJjZS5mcm9tVGFnKHRhZ0tleSwgcHJvcHMudGFnVmFsdWUpXSxcbiAgICAgIHJvbGU6IHRoaXMuY3JlYXRlQmFja3VwUm9sZShwcm9wcylcbiAgICB9KTtcblxuICAgIC8vIEV4cG9ydCBwbGFuIEFSTlxuICAgIGNvbnN0IHBsYW5OYW1lUGFzY2FsID1cbiAgICAgIHByb3BzLnBsYW5OYW1lLmNoYXJBdCgwKS50b1VwcGVyQ2FzZSgpICsgcHJvcHMucGxhbk5hbWUuc2xpY2UoMSk7XG5cbiAgICB0aGlzLnBsYW5Bcm4gPSBuZXcgQ2ZuT3V0cHV0KHRoaXMsIGAke3Byb3BzLnBsYW5OYW1lfVBsYW5Bcm5gLCB7XG4gICAgICBrZXk6IGAke3Byb3BzLnBsYW5OYW1lfVBsYW5Bcm5gLFxuICAgICAgdmFsdWU6IHRoaXMucGxhbi5iYWNrdXBQbGFuQXJuLFxuICAgICAgZXhwb3J0TmFtZTogYCR7cGxhbk5hbWVQYXNjYWx9QmFja3VwUGxhbkFybmBcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgY3JlYXRlQmFja3VwUm9sZShwcm9wczogQmFja3VwUGxhblByb3BzKTogaWFtLlJvbGUge1xuICAgIGNvbnN0IHJvbGUgPSBuZXcgaWFtLlJvbGUodGhpcywgYCR7cHJvcHMucGxhbk5hbWV9QmFja3VwUm9sZWAsIHtcbiAgICAgIGFzc3VtZWRCeTogbmV3IGlhbS5TZXJ2aWNlUHJpbmNpcGFsKFwiYmFja3VwLmFtYXpvbmF3cy5jb21cIiksXG4gICAgICBkZXNjcmlwdGlvbjogYEJhY2t1cCByb2xlIGZvciAke3Byb3BzLnBsYW5OYW1lfWAsXG4gICAgICBtYW5hZ2VkUG9saWNpZXM6IFtcbiAgICAgICAgLy8gQ29yZSBiYWNrdXAgcG9saWNpZXNcbiAgICAgICAgaWFtLk1hbmFnZWRQb2xpY3kuZnJvbUF3c01hbmFnZWRQb2xpY3lOYW1lKFxuICAgICAgICAgIFwic2VydmljZS1yb2xlL0FXU0JhY2t1cFNlcnZpY2VSb2xlUG9saWN5Rm9yQmFja3VwXCJcbiAgICAgICAgKSxcbiAgICAgICAgaWFtLk1hbmFnZWRQb2xpY3kuZnJvbUF3c01hbmFnZWRQb2xpY3lOYW1lKFxuICAgICAgICAgIFwic2VydmljZS1yb2xlL0FXU0JhY2t1cFNlcnZpY2VSb2xlUG9saWN5Rm9yUmVzdG9yZXNcIlxuICAgICAgICApLFxuICAgICAgICAvLyBTMyBiYWNrdXAgc3VwcG9ydFxuICAgICAgICBpYW0uTWFuYWdlZFBvbGljeS5mcm9tQXdzTWFuYWdlZFBvbGljeU5hbWUoXG4gICAgICAgICAgXCJBV1NCYWNrdXBTZXJ2aWNlUm9sZVBvbGljeUZvclMzQmFja3VwXCJcbiAgICAgICAgKSxcbiAgICAgICAgaWFtLk1hbmFnZWRQb2xpY3kuZnJvbUF3c01hbmFnZWRQb2xpY3lOYW1lKFxuICAgICAgICAgIFwiQVdTQmFja3VwU2VydmljZVJvbGVQb2xpY3lGb3JTM1Jlc3RvcmVcIlxuICAgICAgICApXG4gICAgICBdXG4gICAgfSk7XG5cbiAgICByb2xlLmFkZFRvUG9saWN5KFxuICAgICAgbmV3IGlhbS5Qb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgICBlZmZlY3Q6IGlhbS5FZmZlY3QuQUxMT1csXG4gICAgICAgIGFjdGlvbnM6IFtcbiAgICAgICAgICBcInJkczpNb2RpZnlEQkluc3RhbmNlXCIsXG4gICAgICAgICAgXCJyZHM6RGVzY3JpYmVEQkluc3RhbmNlQXV0b21hdGVkQmFja3Vwc1wiLFxuICAgICAgICAgIFwicmRzOlJlc3RvcmVEQkluc3RhbmNlVG9Qb2ludEluVGltZVwiLFxuICAgICAgICAgIFwicmRzOkRlc2NyaWJlREJJbnN0YW5jZXNcIixcbiAgICAgICAgICBcInJkczpEZXNjcmliZURCQ2x1c3RlcnNcIixcbiAgICAgICAgICBcInJkczpSZXN0b3JlREJDbHVzdGVyVG9Qb2ludEluVGltZVwiXG4gICAgICAgIF0sXG4gICAgICAgIHJlc291cmNlczogW1wiKlwiXVxuICAgICAgfSlcbiAgICApO1xuXG4gICAgcm9sZS5hZGRUb1BvbGljeShcbiAgICAgIG5ldyBpYW0uUG9saWN5U3RhdGVtZW50KHtcbiAgICAgICAgZWZmZWN0OiBpYW0uRWZmZWN0LkFMTE9XLFxuICAgICAgICBhY3Rpb25zOiBbXCJiYWNrdXA6Q29weUludG9CYWNrdXBWYXVsdFwiLCBcImJhY2t1cDpDb3B5RnJvbUJhY2t1cFZhdWx0XCJdLFxuICAgICAgICByZXNvdXJjZXM6IFtcIipcIl0gLy8gVE9ETzogVGlnaHRlbiB1cFxuICAgICAgfSlcbiAgICApO1xuXG4gICAgcmV0dXJuIHJvbGU7XG4gIH1cblxuICBzdGF0aWMgYnVpbGQoaWQ6IHN0cmluZywgcHJvcHM6IEJhY2t1cFBsYW5Qcm9wcykge1xuICAgIHJldHVybiAoc2NvcGU6IENvbnN0cnVjdCkgPT4ge1xuICAgICAgcmV0dXJuIG5ldyBCYWNrdXBQbGFuKHNjb3BlLCBpZCwgcHJvcHMpO1xuICAgIH07XG4gIH1cbn1cbiJdfQ==
@@ -0,0 +1,19 @@
1
+ import { Construct } from "constructs";
2
+ import { CfnOutput, RemovalPolicy } from "aws-cdk-lib";
3
+ import { BackupVault as Vault, LockConfiguration } from "aws-cdk-lib/aws-backup";
4
+ import { PolicyDocument } from "aws-cdk-lib/aws-iam";
5
+ import { CustomerManagedKey } from "../secrets/kms";
6
+ export interface BackupVaultProps {
7
+ vaultName: string;
8
+ encryptionKey?: CustomerManagedKey;
9
+ accessPolicy?: PolicyDocument;
10
+ lockConfiguration?: LockConfiguration;
11
+ removalPolicy?: RemovalPolicy;
12
+ }
13
+ export declare class BackupVault extends Construct {
14
+ readonly vault: Vault;
15
+ readonly vaultArn: CfnOutput;
16
+ readonly vaultName: CfnOutput;
17
+ constructor(scope: Construct, id: string, props: BackupVaultProps);
18
+ static build(id: string, props: BackupVaultProps): (scope: Construct) => BackupVault;
19
+ }
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BackupVault = void 0;
4
+ const constructs_1 = require("constructs");
5
+ const aws_cdk_lib_1 = require("aws-cdk-lib");
6
+ const aws_backup_1 = require("aws-cdk-lib/aws-backup");
7
+ const kms_1 = require("../secrets/kms");
8
+ class BackupVault extends constructs_1.Construct {
9
+ constructor(scope, id, props) {
10
+ super(scope, id);
11
+ const encryptionKey = props.encryptionKey ||
12
+ new kms_1.CustomerManagedKey(this, `${props.vaultName}Key`, {
13
+ description: `Encryption key for backup vault ${props.vaultName}`,
14
+ aliasName: `cmk/backupVault/${props.vaultName}`
15
+ });
16
+ this.vault = new aws_backup_1.BackupVault(this, `${props.vaultName}Vault`, {
17
+ backupVaultName: props.vaultName,
18
+ encryptionKey: encryptionKey.key,
19
+ accessPolicy: props.accessPolicy,
20
+ lockConfiguration: props.lockConfiguration,
21
+ removalPolicy: props.removalPolicy || aws_cdk_lib_1.RemovalPolicy.RETAIN
22
+ });
23
+ const vaultNamePascal = props.vaultName.charAt(0).toUpperCase() + props.vaultName.slice(1);
24
+ this.vaultArn = new aws_cdk_lib_1.CfnOutput(this, `${props.vaultName}VaultArn`, {
25
+ key: `${props.vaultName}VaultArn`,
26
+ value: this.vault.backupVaultArn,
27
+ exportName: `${vaultNamePascal}Arn`
28
+ });
29
+ this.vaultName = new aws_cdk_lib_1.CfnOutput(this, `${props.vaultName}VaultName`, {
30
+ key: `${props.vaultName}VaultName`,
31
+ value: this.vault.backupVaultName,
32
+ exportName: `${vaultNamePascal}Name`
33
+ });
34
+ }
35
+ // Factory method following existing patterns
36
+ static build(id, props) {
37
+ return (scope) => {
38
+ return new BackupVault(scope, id, props);
39
+ };
40
+ }
41
+ }
42
+ exports.BackupVault = BackupVault;
43
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFja3VwVmF1bHQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9saWIvcmVzb3VyY2VzL2F3cy9iYWNrdXAvYmFja3VwVmF1bHQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsMkNBQXVDO0FBQ3ZDLDZDQUF1RDtBQUN2RCx1REFHZ0M7QUFFaEMsd0NBQW9EO0FBVXBELE1BQWEsV0FBWSxTQUFRLHNCQUFTO0lBS3hDLFlBQVksS0FBZ0IsRUFBRSxFQUFVLEVBQUUsS0FBdUI7UUFDL0QsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQztRQUVqQixNQUFNLGFBQWEsR0FDakIsS0FBSyxDQUFDLGFBQWE7WUFDbkIsSUFBSSx3QkFBa0IsQ0FBQyxJQUFJLEVBQUUsR0FBRyxLQUFLLENBQUMsU0FBUyxLQUFLLEVBQUU7Z0JBQ3BELFdBQVcsRUFBRSxtQ0FBbUMsS0FBSyxDQUFDLFNBQVMsRUFBRTtnQkFDakUsU0FBUyxFQUFFLG1CQUFtQixLQUFLLENBQUMsU0FBUyxFQUFFO2FBQ2hELENBQUMsQ0FBQztRQUVMLElBQUksQ0FBQyxLQUFLLEdBQUcsSUFBSSx3QkFBSyxDQUFDLElBQUksRUFBRSxHQUFHLEtBQUssQ0FBQyxTQUFTLE9BQU8sRUFBRTtZQUN0RCxlQUFlLEVBQUUsS0FBSyxDQUFDLFNBQVM7WUFDaEMsYUFBYSxFQUFFLGFBQWEsQ0FBQyxHQUFHO1lBQ2hDLFlBQVksRUFBRSxLQUFLLENBQUMsWUFBWTtZQUNoQyxpQkFBaUIsRUFBRSxLQUFLLENBQUMsaUJBQWlCO1lBQzFDLGFBQWEsRUFBRSxLQUFLLENBQUMsYUFBYSxJQUFJLDJCQUFhLENBQUMsTUFBTTtTQUMzRCxDQUFDLENBQUM7UUFFSCxNQUFNLGVBQWUsR0FDbkIsS0FBSyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsV0FBVyxFQUFFLEdBQUcsS0FBSyxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFFckUsSUFBSSxDQUFDLFFBQVEsR0FBRyxJQUFJLHVCQUFTLENBQUMsSUFBSSxFQUFFLEdBQUcsS0FBSyxDQUFDLFNBQVMsVUFBVSxFQUFFO1lBQ2hFLEdBQUcsRUFBRSxHQUFHLEtBQUssQ0FBQyxTQUFTLFVBQVU7WUFDakMsS0FBSyxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsY0FBYztZQUNoQyxVQUFVLEVBQUUsR0FBRyxlQUFlLEtBQUs7U0FDcEMsQ0FBQyxDQUFDO1FBRUgsSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLHVCQUFTLENBQUMsSUFBSSxFQUFFLEdBQUcsS0FBSyxDQUFDLFNBQVMsV0FBVyxFQUFFO1lBQ2xFLEdBQUcsRUFBRSxHQUFHLEtBQUssQ0FBQyxTQUFTLFdBQVc7WUFDbEMsS0FBSyxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsZUFBZTtZQUNqQyxVQUFVLEVBQUUsR0FBRyxlQUFlLE1BQU07U0FDckMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVELDZDQUE2QztJQUM3QyxNQUFNLENBQUMsS0FBSyxDQUFDLEVBQVUsRUFBRSxLQUF1QjtRQUM5QyxPQUFPLENBQUMsS0FBZ0IsRUFBRSxFQUFFO1lBQzFCLE9BQU8sSUFBSSxXQUFXLENBQUMsS0FBSyxFQUFFLEVBQUUsRUFBRSxLQUFLLENBQUMsQ0FBQztRQUMzQyxDQUFDLENBQUM7SUFDSixDQUFDO0NBQ0Y7QUE3Q0Qsa0NBNkNDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29uc3RydWN0IH0gZnJvbSBcImNvbnN0cnVjdHNcIjtcbmltcG9ydCB7IENmbk91dHB1dCwgUmVtb3ZhbFBvbGljeSB9IGZyb20gXCJhd3MtY2RrLWxpYlwiO1xuaW1wb3J0IHtcbiAgQmFja3VwVmF1bHQgYXMgVmF1bHQsXG4gIExvY2tDb25maWd1cmF0aW9uXG59IGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtYmFja3VwXCI7XG5pbXBvcnQgeyBQb2xpY3lEb2N1bWVudCB9IGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtaWFtXCI7XG5pbXBvcnQgeyBDdXN0b21lck1hbmFnZWRLZXkgfSBmcm9tIFwiLi4vc2VjcmV0cy9rbXNcIjtcblxuZXhwb3J0IGludGVyZmFjZSBCYWNrdXBWYXVsdFByb3BzIHtcbiAgdmF1bHROYW1lOiBzdHJpbmc7XG4gIGVuY3J5cHRpb25LZXk/OiBDdXN0b21lck1hbmFnZWRLZXk7XG4gIGFjY2Vzc1BvbGljeT86IFBvbGljeURvY3VtZW50O1xuICBsb2NrQ29uZmlndXJhdGlvbj86IExvY2tDb25maWd1cmF0aW9uO1xuICByZW1vdmFsUG9saWN5PzogUmVtb3ZhbFBvbGljeTtcbn1cblxuZXhwb3J0IGNsYXNzIEJhY2t1cFZhdWx0IGV4dGVuZHMgQ29uc3RydWN0IHtcbiAgcHVibGljIHJlYWRvbmx5IHZhdWx0OiBWYXVsdDtcbiAgcHVibGljIHJlYWRvbmx5IHZhdWx0QXJuOiBDZm5PdXRwdXQ7XG4gIHB1YmxpYyByZWFkb25seSB2YXVsdE5hbWU6IENmbk91dHB1dDtcblxuICBjb25zdHJ1Y3RvcihzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBwcm9wczogQmFja3VwVmF1bHRQcm9wcykge1xuICAgIHN1cGVyKHNjb3BlLCBpZCk7XG5cbiAgICBjb25zdCBlbmNyeXB0aW9uS2V5ID1cbiAgICAgIHByb3BzLmVuY3J5cHRpb25LZXkgfHxcbiAgICAgIG5ldyBDdXN0b21lck1hbmFnZWRLZXkodGhpcywgYCR7cHJvcHMudmF1bHROYW1lfUtleWAsIHtcbiAgICAgICAgZGVzY3JpcHRpb246IGBFbmNyeXB0aW9uIGtleSBmb3IgYmFja3VwIHZhdWx0ICR7cHJvcHMudmF1bHROYW1lfWAsXG4gICAgICAgIGFsaWFzTmFtZTogYGNtay9iYWNrdXBWYXVsdC8ke3Byb3BzLnZhdWx0TmFtZX1gXG4gICAgICB9KTtcblxuICAgIHRoaXMudmF1bHQgPSBuZXcgVmF1bHQodGhpcywgYCR7cHJvcHMudmF1bHROYW1lfVZhdWx0YCwge1xuICAgICAgYmFja3VwVmF1bHROYW1lOiBwcm9wcy52YXVsdE5hbWUsXG4gICAgICBlbmNyeXB0aW9uS2V5OiBlbmNyeXB0aW9uS2V5LmtleSxcbiAgICAgIGFjY2Vzc1BvbGljeTogcHJvcHMuYWNjZXNzUG9saWN5LFxuICAgICAgbG9ja0NvbmZpZ3VyYXRpb246IHByb3BzLmxvY2tDb25maWd1cmF0aW9uLFxuICAgICAgcmVtb3ZhbFBvbGljeTogcHJvcHMucmVtb3ZhbFBvbGljeSB8fCBSZW1vdmFsUG9saWN5LlJFVEFJTlxuICAgIH0pO1xuXG4gICAgY29uc3QgdmF1bHROYW1lUGFzY2FsID1cbiAgICAgIHByb3BzLnZhdWx0TmFtZS5jaGFyQXQoMCkudG9VcHBlckNhc2UoKSArIHByb3BzLnZhdWx0TmFtZS5zbGljZSgxKTtcblxuICAgIHRoaXMudmF1bHRBcm4gPSBuZXcgQ2ZuT3V0cHV0KHRoaXMsIGAke3Byb3BzLnZhdWx0TmFtZX1WYXVsdEFybmAsIHtcbiAgICAgIGtleTogYCR7cHJvcHMudmF1bHROYW1lfVZhdWx0QXJuYCxcbiAgICAgIHZhbHVlOiB0aGlzLnZhdWx0LmJhY2t1cFZhdWx0QXJuLFxuICAgICAgZXhwb3J0TmFtZTogYCR7dmF1bHROYW1lUGFzY2FsfUFybmBcbiAgICB9KTtcblxuICAgIHRoaXMudmF1bHROYW1lID0gbmV3IENmbk91dHB1dCh0aGlzLCBgJHtwcm9wcy52YXVsdE5hbWV9VmF1bHROYW1lYCwge1xuICAgICAga2V5OiBgJHtwcm9wcy52YXVsdE5hbWV9VmF1bHROYW1lYCxcbiAgICAgIHZhbHVlOiB0aGlzLnZhdWx0LmJhY2t1cFZhdWx0TmFtZSxcbiAgICAgIGV4cG9ydE5hbWU6IGAke3ZhdWx0TmFtZVBhc2NhbH1OYW1lYFxuICAgIH0pO1xuICB9XG5cbiAgLy8gRmFjdG9yeSBtZXRob2QgZm9sbG93aW5nIGV4aXN0aW5nIHBhdHRlcm5zXG4gIHN0YXRpYyBidWlsZChpZDogc3RyaW5nLCBwcm9wczogQmFja3VwVmF1bHRQcm9wcykge1xuICAgIHJldHVybiAoc2NvcGU6IENvbnN0cnVjdCkgPT4ge1xuICAgICAgcmV0dXJuIG5ldyBCYWNrdXBWYXVsdChzY29wZSwgaWQsIHByb3BzKTtcbiAgICB9O1xuICB9XG59XG4iXX0=
@@ -0,0 +1,2 @@
1
+ export * from "./backupVault";
2
+ export * from "./backupPlan";
@@ -0,0 +1,19 @@
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 __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./backupVault"), exports);
18
+ __exportStar(require("./backupPlan"), exports);
19
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9saWIvcmVzb3VyY2VzL2F3cy9iYWNrdXAvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLGdEQUE4QjtBQUM5QiwrQ0FBNkIiLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgKiBmcm9tIFwiLi9iYWNrdXBWYXVsdFwiO1xuZXhwb3J0ICogZnJvbSBcIi4vYmFja3VwUGxhblwiO1xuIl19
@@ -1,3 +1,4 @@
1
1
  export * from "./networking";
2
2
  export * from "./storage";
3
3
  export * from "./base";
4
+ export * from "./backup";
@@ -17,4 +17,5 @@ Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./networking"), exports);
18
18
  __exportStar(require("./storage"), exports);
19
19
  __exportStar(require("./base"), exports);
20
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9saWIvcmVzb3VyY2VzL2F3cy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsK0NBQTZCO0FBQzdCLDRDQUEwQjtBQUMxQix5Q0FBdUIiLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgKiBmcm9tIFwiLi9uZXR3b3JraW5nXCI7XG5leHBvcnQgKiBmcm9tIFwiLi9zdG9yYWdlXCI7XG5leHBvcnQgKiBmcm9tIFwiLi9iYXNlXCI7XG4iXX0=
20
+ __exportStar(require("./backup"), exports);
21
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9saWIvcmVzb3VyY2VzL2F3cy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsK0NBQTZCO0FBQzdCLDRDQUEwQjtBQUMxQix5Q0FBdUI7QUFDdkIsMkNBQXlCIiwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0ICogZnJvbSBcIi4vbmV0d29ya2luZ1wiO1xuZXhwb3J0ICogZnJvbSBcIi4vc3RvcmFnZVwiO1xuZXhwb3J0ICogZnJvbSBcIi4vYmFzZVwiO1xuZXhwb3J0ICogZnJvbSBcIi4vYmFja3VwXCI7XG4iXX0=
@@ -0,0 +1,37 @@
1
+ import { Construct } from "constructs";
2
+ import { IAccount, IPolicy } from "./interfaces";
3
+ import { AccountProps } from "./types";
4
+ /**
5
+ * AWS Account construct for managing member accounts
6
+ */
7
+ export declare class Account extends Construct implements IAccount {
8
+ readonly accountId: string;
9
+ readonly accountArn: string;
10
+ readonly accountName: string;
11
+ readonly email: string;
12
+ constructor(scope: Construct, id: string, props: AccountProps);
13
+ /**
14
+ * Attach policy to this account
15
+ */
16
+ attachPolicy(policy: IPolicy): void;
17
+ /**
18
+ * Delegate administrator privileges for a service
19
+ */
20
+ delegateAdministrator(servicePrincipal: string): void;
21
+ /**
22
+ * Helper to normalize account names for construct IDs
23
+ */
24
+ private normalizeAccountName;
25
+ /**
26
+ * Helper to normalize policy names for construct IDs
27
+ */
28
+ private normalizePolicyName;
29
+ /**
30
+ * Helper to normalize service names for construct IDs
31
+ */
32
+ private normalizeServiceName;
33
+ /**
34
+ * Get the root ID (placeholder - would need custom logic to get this)
35
+ */
36
+ private getRootId;
37
+ }