@fjall/components-infrastructure 2.30.0 → 2.30.3

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 (72) hide show
  1. package/dist/lib/__tests__/setup.d.ts +48 -0
  2. package/dist/lib/__tests__/setup.js +1 -0
  3. package/dist/lib/config/aws/accountId.d.ts +6 -0
  4. package/dist/lib/config/aws/accountId.js +33 -0
  5. package/dist/lib/config/aws/backupGlobalSettings.d.ts +29 -0
  6. package/dist/lib/config/aws/backupGlobalSettings.js +51 -0
  7. package/dist/lib/config/aws/costAllocationTags.d.ts +12 -0
  8. package/dist/lib/config/aws/costAllocationTags.js +48 -0
  9. package/dist/lib/config/aws/eventBus.d.ts +7 -0
  10. package/dist/lib/config/aws/eventBus.js +24 -0
  11. package/dist/lib/config/aws/identityCenterGroupMembership.d.ts +10 -0
  12. package/dist/lib/config/aws/identityCenterGroupMembership.js +115 -0
  13. package/dist/lib/config/aws/ipamDelegateAdmin.d.ts +8 -0
  14. package/dist/lib/config/aws/ipamDelegateAdmin.js +58 -0
  15. package/dist/lib/config/aws/ipamPoolId.d.ts +10 -0
  16. package/dist/lib/config/aws/ipamPoolId.js +39 -0
  17. package/dist/lib/config/aws/organisation.d.ts +30 -0
  18. package/dist/lib/config/aws/organisation.js +95 -0
  19. package/dist/lib/config/aws/organisationId.d.ts +7 -0
  20. package/dist/lib/config/aws/organisationId.js +46 -0
  21. package/dist/lib/config/aws/organisationsAccess.d.ts +10 -0
  22. package/dist/lib/config/aws/organisationsAccess.js +50 -0
  23. package/dist/lib/config/aws/ramSharing.d.ts +4 -0
  24. package/dist/lib/config/aws/ramSharing.js +35 -0
  25. package/dist/lib/config/monitoring.d.ts +18 -0
  26. package/dist/lib/config/monitoring.js +22 -0
  27. package/dist/lib/patterns/aws/cicdRole.d.ts +67 -0
  28. package/dist/lib/patterns/aws/cicdRole.js +68 -0
  29. package/dist/lib/patterns/aws/compute.js +9 -0
  30. package/dist/lib/patterns/aws/computeLambda.d.ts +38 -3
  31. package/dist/lib/patterns/aws/computeLambda.js +29 -2
  32. package/dist/lib/patterns/aws/hostedZone.d.ts +28 -0
  33. package/dist/lib/patterns/aws/hostedZone.js +150 -0
  34. package/dist/lib/patterns/aws/managedAccount.d.ts +9 -0
  35. package/dist/lib/patterns/aws/managedAccount.js +55 -0
  36. package/dist/lib/patterns/aws/managedIdentityCenter.d.ts +4 -0
  37. package/dist/lib/patterns/aws/managedIdentityCenter.js +24 -0
  38. package/dist/lib/patterns/aws/managedOrganisation.d.ts +36 -0
  39. package/dist/lib/patterns/aws/managedOrganisation.js +97 -0
  40. package/dist/lib/patterns/aws/managedPlatform.d.ts +12 -0
  41. package/dist/lib/patterns/aws/managedPlatform.js +29 -0
  42. package/dist/lib/patterns/aws/subdomainHostedZone.d.ts +9 -0
  43. package/dist/lib/patterns/aws/subdomainHostedZone.js +39 -0
  44. package/dist/lib/resources/aws/cicd/cicdRole.d.ts +65 -0
  45. package/dist/lib/resources/aws/cicd/cicdRole.js +191 -0
  46. package/dist/lib/resources/aws/compute/ecsFreeTier.d.ts +75 -0
  47. package/dist/lib/resources/aws/compute/ecsFreeTier.js +1 -0
  48. package/dist/lib/resources/aws/compute/ecsImages.js +3 -25
  49. package/dist/lib/resources/aws/compute/ecsSpot.d.ts +75 -0
  50. package/dist/lib/resources/aws/compute/ecsSpot.js +1 -0
  51. package/dist/lib/resources/aws/compute/imageTagParameter.d.ts +12 -0
  52. package/dist/lib/resources/aws/compute/imageTagParameter.js +32 -0
  53. package/dist/lib/resources/aws/compute/utilities/capacityProviderDrainWaiter.d.ts +20 -0
  54. package/dist/lib/resources/aws/compute/utilities/capacityProviderDrainWaiter.js +1 -0
  55. package/dist/lib/resources/aws/database/database.d.ts +14 -0
  56. package/dist/lib/resources/aws/database/database.js +28 -0
  57. package/dist/lib/resources/aws/database/databaseInstance.d.ts +15 -0
  58. package/dist/lib/resources/aws/database/databaseInstance.js +30 -0
  59. package/dist/lib/resources/aws/iam/identityCenter/attachManagedPolicy.d.ts +13 -0
  60. package/dist/lib/resources/aws/iam/identityCenter/attachManagedPolicy.js +52 -0
  61. package/dist/lib/resources/aws/iam/securityGroup.d.ts +5 -0
  62. package/dist/lib/resources/aws/iam/securityGroup.js +14 -0
  63. package/dist/lib/resources/aws/monitoring/monitoringRole.d.ts +28 -0
  64. package/dist/lib/resources/aws/monitoring/monitoringRole.js +125 -0
  65. package/dist/lib/resources/aws/utilities/cfnOutput.d.ts +5 -0
  66. package/dist/lib/resources/aws/utilities/cfnOutput.js +1 -0
  67. package/dist/lib/utils/addSuffixToEmail.js +5 -1
  68. package/dist/lib/utils/capitalizeString.d.ts +1 -0
  69. package/dist/lib/utils/capitalizeString.js +7 -0
  70. package/package.json +4 -4
  71. package/dist/lib/config/aws/identityCenterMembership.d.ts +0 -11
  72. package/dist/lib/config/aws/identityCenterMembership.js +0 -61
@@ -0,0 +1,95 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const aws_cdk_lib_1 = require("aws-cdk-lib");
4
+ const constructs_1 = require("constructs");
5
+ const stripAndCamelCase_1 = require("../../utils/stripAndCamelCase");
6
+ const cdk_organizations_1 = require("@pepperize/cdk-organizations");
7
+ const addSuffixToEmail_1 = require("../../utils/addSuffixToEmail");
8
+ /**
9
+ * A construct for creating multi environment organisations with a production, staging and development account.
10
+ */
11
+ class Organisation extends constructs_1.Construct {
12
+ constructor(scope, id, props) {
13
+ super(scope, id);
14
+ this.accounts = {};
15
+ this.organisationalUnits = [];
16
+ this.existingAccounts = props.existingAccounts;
17
+ this.addOrganisation(props.organisationName);
18
+ this.addOrganisationUnitsAndAccounts(props.accounts, props.orgEmail);
19
+ }
20
+ addOrganisation(organisationName) {
21
+ this.organisation = new cdk_organizations_1.Organization(this, organisationName, {
22
+ featureSet: cdk_organizations_1.FeatureSet.ALL
23
+ });
24
+ // TODO: Validate this enables trusted access
25
+ this.organisation.enableAwsServiceAccess("account.amazonaws.com");
26
+ const enforcedPolicyTypes = [
27
+ cdk_organizations_1.PolicyType.SERVICE_CONTROL_POLICY,
28
+ cdk_organizations_1.PolicyType.TAG_POLICY,
29
+ cdk_organizations_1.PolicyType.BACKUP_POLICY,
30
+ cdk_organizations_1.PolicyType.AISERVICES_OPT_OUT_POLICY
31
+ ];
32
+ for (const policyType of enforcedPolicyTypes) {
33
+ this.organisation.enablePolicyType(policyType);
34
+ }
35
+ }
36
+ addOrganisationUnitsAndAccounts(accounts, orgEmail) {
37
+ for (const [environmentType, accountList] of Object.entries(accounts)) {
38
+ // Create OU for each environment type
39
+ const ouName = environmentType.charAt(0).toUpperCase() + environmentType.slice(1);
40
+ const orgUnit = this.addOrganisationalUnit(`${ouName}OrganizationalUnit`, ouName);
41
+ // Convert single account to array for uniform processing
42
+ const accountsArray = Array.isArray(accountList)
43
+ ? accountList
44
+ : [accountList];
45
+ // Add accounts to this OU
46
+ for (const accountName of accountsArray) {
47
+ const accountNameId = (0, stripAndCamelCase_1.stripAndCamelCase)(accountName);
48
+ const importedAccount = this.existingAccounts?.find((account) => account.Name === accountName);
49
+ const accountEmail = importedAccount
50
+ ? importedAccount.Email
51
+ : (0, addSuffixToEmail_1.default)(orgEmail, accountNameId.toLowerCase());
52
+ if (accountEmail) {
53
+ this.addAccount(`${accountNameId}Account`, accountName, accountEmail, { env: environmentType }, orgUnit);
54
+ }
55
+ }
56
+ }
57
+ }
58
+ addOrganisationalUnit(id, name) {
59
+ const ou = new cdk_organizations_1.OrganizationalUnit(this, id, {
60
+ organizationalUnitName: name,
61
+ parent: this.organisation.root,
62
+ importOnDuplicate: true
63
+ });
64
+ this.organisationalUnits.push(ou);
65
+ return ou;
66
+ }
67
+ addAccount(id, name, email, tags, organisationalUnit) {
68
+ const acc = new cdk_organizations_1.Account(this, id, {
69
+ accountName: name,
70
+ email: email,
71
+ parent: organisationalUnit,
72
+ importOnDuplicate: true
73
+ });
74
+ for (const tag in tags) {
75
+ aws_cdk_lib_1.Tags.of(acc).add(tag, tags[tag]);
76
+ }
77
+ this.accounts[name] = acc.accountId;
78
+ new aws_cdk_lib_1.CfnOutput(this, `${id}Id`, {
79
+ key: `${id}Id`,
80
+ value: acc.accountId,
81
+ exportName: `${id}Id`
82
+ });
83
+ new aws_cdk_lib_1.CfnOutput(this, `${id}Arn`, {
84
+ key: `${id}Arn`,
85
+ value: acc.accountArn,
86
+ exportName: `${id}Arn`
87
+ });
88
+ return acc;
89
+ }
90
+ getAccounts() {
91
+ return this.accounts;
92
+ }
93
+ }
94
+ exports.default = Organisation;
95
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3JnYW5pc2F0aW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vbGliL2NvbmZpZy9hd3Mvb3JnYW5pc2F0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUEsNkNBQStEO0FBQy9ELDJDQUF1QztBQUN2QyxxRUFBa0U7QUFFbEUsb0VBTXNDO0FBQ3RDLG1FQUE0RDtBQWM1RDs7R0FFRztBQUVILE1BQXFCLFlBQWEsU0FBUSxzQkFBUztJQVFqRCxZQUFZLEtBQWdCLEVBQUUsRUFBVSxFQUFFLEtBQXdCO1FBQ2hFLEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFMWCxhQUFRLEdBQWEsRUFBRSxDQUFDO1FBRXhCLHdCQUFtQixHQUF5QixFQUFFLENBQUM7UUFLckQsSUFBSSxDQUFDLGdCQUFnQixHQUFHLEtBQUssQ0FBQyxnQkFBZ0IsQ0FBQztRQUMvQyxJQUFJLENBQUMsZUFBZSxDQUFDLEtBQUssQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO1FBQzdDLElBQUksQ0FBQywrQkFBK0IsQ0FBQyxLQUFLLENBQUMsUUFBUSxFQUFFLEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUN2RSxDQUFDO0lBRU8sZUFBZSxDQUFDLGdCQUF3QjtRQUM5QyxJQUFJLENBQUMsWUFBWSxHQUFHLElBQUksZ0NBQVksQ0FBQyxJQUFJLEVBQUUsZ0JBQWdCLEVBQUU7WUFDM0QsVUFBVSxFQUFFLDhCQUFVLENBQUMsR0FBRztTQUMzQixDQUFDLENBQUM7UUFFSCw2Q0FBNkM7UUFDN0MsSUFBSSxDQUFDLFlBQVksQ0FBQyxzQkFBc0IsQ0FBQyx1QkFBdUIsQ0FBQyxDQUFDO1FBRWxFLE1BQU0sbUJBQW1CLEdBQWlCO1lBQ3hDLDhCQUFVLENBQUMsc0JBQXNCO1lBQ2pDLDhCQUFVLENBQUMsVUFBVTtZQUNyQiw4QkFBVSxDQUFDLGFBQWE7WUFDeEIsOEJBQVUsQ0FBQyx5QkFBeUI7U0FDckMsQ0FBQztRQUVGLEtBQUssTUFB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dUJBQVMsQ0FBQyxJQUFJLEVBQUUsR0FBRyxFQUFFLElBQUksRUFBRTtZQUM3QixHQUFHLEVBQUUsR0FBRyxFQUFFLElBQUk7WUFDZCxLQUFLLEVBQUUsR0FBRyxDQUFDLFNBQVM7WUFDcEIsVUFBVSxFQUFFLEdBQUcsRUFBRSxJQUFJO1NBQ3RCLENBQUMsQ0FBQztRQUNILElBQUksdUJBQVMsQ0FBQyxJQUFJLEVBQUUsR0FBRyxFQUFFLEtBQUssRUFBRTtZQUM5QixHQUFHLEVBQUUsR0FBRyxFQUFFLEtBQUs7WUFDZixLQUFLLEVBQUUsR0FBRyxDQUFDLFVBQVU7WUFDckIsVUFBVSxFQUFFLEdBQUcsRUFBRSxLQUFLO1NBQ3ZCLENBQUMsQ0FBQztRQUVILE9BQU8sR0FBRyxDQUFDO0lBQ2IsQ0FBQztJQUVNLFdBQVc7UUFDaEIsT0FBTyxJQUFJLENBQUMsUUFBUSxDQUFDO0lBQ3ZCLENBQUM7Q0FDRjtBQTlIRCwrQkE4SEMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDZm5PdXRwdXQsIFRhZ3MsIHR5cGUgU3RhY2tQcm9wcyB9IGZyb20gXCJhd3MtY2RrLWxpYlwiO1xuaW1wb3J0IHsgQ29uc3RydWN0IH0gZnJvbSBcImNvbnN0cnVjdHNcIjtcbmltcG9ydCB7IHN0cmlwQW5kQ2FtZWxDYXNlIH0gZnJvbSBcIi4uLy4uL3V0aWxzL3N0cmlwQW5kQ2FtZWxDYXNlXCI7XG5pbXBvcnQgeyB0eXBlIEFjY291bnQgYXMgRXhpc3RpbmdBY2NvdW50cyB9IGZyb20gXCJAYXdzLXNkay9jbGllbnQtb3JnYW5pemF0aW9uc1wiO1xuaW1wb3J0IHtcbiAgQWNjb3VudCxcbiAgRmVhdHVyZVNldCxcbiAgT3JnYW5pemF0aW9uLFxuICBPcmdhbml6YXRpb25hbFVuaXQsXG4gIFBvbGljeVR5cGVcbn0gZnJvbSBcIkBwZXBwZXJpemUvY2RrLW9yZ2FuaXphdGlvbnNcIjtcbmltcG9ydCBhZGRTdWZmaXhUb0VtYWlsIGZyb20gXCIuLi8uLi91dGlscy9hZGRTdWZmaXhUb0VtYWlsXCI7XG5pbXBvcnQgeyB0eXBlIEtleVZhbHVlIH0gZnJvbSBcIi4uLy4uL3R5cGVzXCI7XG5cbmludGVyZmFjZSBPcmdhbmlzYXRpb25Qcm9wcyBleHRlbmRzIFN0YWNrUHJvcHMge1xuICBvcmdhbmlzYXRpb25OYW1lOiBzdHJpbmc7XG4gIGFjY291bnRzOiBBY2NvdW50c0NvbmZpZztcbiAgb3JnRW1haWw6IHN0cmluZztcbiAgZXhpc3RpbmdBY2NvdW50cz86IEV4aXN0aW5nQWNjb3VudHNbXTtcbn1cblxudHlwZSBBY2NvdW50c0NvbmZpZyA9IHtcbiAgcmVhZG9ubHkgW2tleTogc3RyaW5nXTogcmVhZG9ubHkgc3RyaW5nW10gfCBzdHJpbmc7XG59O1xuXG4vKipcbiAqIEEgY29uc3RydWN0IGZvciBjcmVhdGluZyBtdWx0aSBlbnZpcm9ubWVudCBvcmdhbmlzYXRpb25zIHdpdGggYSBwcm9kdWN0aW9uLCBzdGFnaW5nIGFuZCBkZXZlbG9wbWVudCBhY2NvdW50LlxuICovXG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIE9yZ2FuaXNhdGlvbiBleHRlbmRzIENvbnN0cnVjdCB7XG4gIHB1YmxpYyBhY2NvdW50SWQ6IENmbk91dHB1dDtcblxuICBwcml2YXRlIGV4aXN0aW5nQWNjb3VudHM/OiBFeGlzdGluZ0FjY291bnRzW107XG4gIHByaXZhdGUgYWNjb3VudHM6IEtleVZhbHVlID0ge307XG4gIHByaXZhdGUgb3JnYW5pc2F0aW9uOiBPcmdhbml6YXRpb247XG4gIHByaXZhdGUgb3JnYW5pc2F0aW9uYWxVbml0czogT3JnYW5pemF0aW9uYWxVbml0W10gPSBbXTtcblxuICBjb25zdHJ1Y3RvcihzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBwcm9wczogT3JnYW5pc2F0aW9uUHJvcHMpIHtcbiAgICBzdXBlcihzY29wZSwgaWQpO1xuXG4gICAgdGhpcy5leGlzdGluZ0FjY291bnRzID0gcHJvcHMuZXhpc3RpbmdBY2NvdW50cztcbiAgICB0aGlzLmFkZE9yZ2FuaXNhdGlvbihwcm9wcy5vcmdhbmlzYXRpb25OYW1lKTtcbiAgICB0aGlzLmFkZE9yZ2FuaXNhdGlvblVuaXRzQW5kQWNjb3VudHMocHJvcHMuYWNjb3VudHMsIHByb3BzLm9yZ0VtYWlsKTtcbiAgfVxuXG4gIHByaXZhdGUgYWRkT3JnYW5pc2F0aW9uKG9yZ2FuaXNhdGlvbk5hbWU6IHN0cmluZykge1xuICAgIHRoaXMub3JnYW5pc2F0aW9uID0gbmV3IE9yZ2FuaXphdGlvbih0aGlzLCBvcmdhbmlzYXRpb25OYW1lLCB7XG4gICAgICBmZWF0dXJlU2V0OiBGZWF0dXJlU2V0LkFMTFxuICAgIH0pO1xuXG4gICAgLy8gVE9ETzogVmFsaWRhdGUgdGhpcyBlbmFibGVzIHRydXN0ZWQgYWNjZXNzXG4gICAgdGhpcy5vcmdhbmlzYXRpb24uZW5hYmxlQXdzU2VydmljZUFjY2VzcyhcImFjY291bnQuYW1hem9uYXdzLmNvbVwiKTtcblxuICAgIGNvbnN0IGVuZm9yY2VkUG9saWN5VHlwZXM6IFBvbGljeVR5cGVbXSA9IFtcbiAgICAgIFBvbGljeVR5cGUuU0VSVklDRV9DT05UUk9MX1BPTElDWSxcbiAgICAgIFBvbGljeVR5cGUuVEFHX1BPTElDWSxcbiAgICAgIFBvbGljeVR5cGUuQkFDS1VQX1BPTElDWSxcbiAgICAgIFBvbGljeVR5cGUuQUlTRVJWSUNFU19PUFRfT1VUX1BPTElDWVxuICAgIF07XG5cbiAgICBmb3IgKGNvbnN0IHBvbGljeVR5cGUgb2YgZW5mb3JjZWRQb2xpY3lUeXBlcykge1xuICAgICAgdGhpcy5vcmdhbmlzYXRpb24uZW5hYmxlUG9saWN5VHlwZShwb2xpY3lUeXBlKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFkZE9yZ2FuaXNhdGlvblVuaXRzQW5kQWNjb3VudHMoXG4gICAgYWNjb3VudHM6IEFjY291bnRzQ29uZmlnLFxuICAgIG9yZ0VtYWlsOiBzdHJpbmdcbiAgKSB7XG4gICAgZm9yIChjb25zdCBbZW52aXJvbm1lbnRUeXBlLCBhY2NvdW50TGlzdF0gb2YgT2JqZWN0LmVudHJpZXMoYWNjb3VudHMpKSB7XG4gICAgICAvLyBDcmVhdGUgT1UgZm9yIGVhY2ggZW52aXJvbm1lbnQgdHlwZVxuICAgICAgY29uc3Qgb3VOYW1lID1cbiAgICAgICAgZW52aXJvbm1lbnRUeXBlLmNoYXJBdCgwKS50b1VwcGVyQ2FzZSgpICsgZW52aXJvbm1lbnRUeXBlLnNsaWNlKDEpO1xuICAgICAgY29uc3Qgb3JnVW5pdCA9IHRoaXMuYWRkT3JnYW5pc2F0aW9uYWxVbml0KFxuICAgICAgICBgJHtvdU5hbWV9T3JnYW5pemF0aW9uYWxVbml0YCxcbiAgICAgICAgb3VOYW1lXG4gICAgICApO1xuXG4gICAgICAvLyBDb252ZXJ0IHNpbmdsZSBhY2NvdW50IHRvIGFycmF5IGZvciB1bmlmb3JtIHByb2Nlc3NpbmdcbiAgICAgIGNvbnN0IGFjY291bnRzQXJyYXkgPSBBcnJheS5pc0FycmF5KGFjY291bnRMaXN0KVxuICAgICAgICA/IGFjY291bnRMaXN0XG4gICAgICAgIDogW2FjY291bnRMaXN0XTtcblxuICAgICAgLy8gQWRkIGFjY291bnRzIHRvIHRoaXMgT1VcbiAgICAgIGZvciAoY29uc3QgYWNjb3VudE5hbWUgb2YgYWNjb3VudHNBcnJheSkge1xuICAgICAgICBjb25zdCBhY2NvdW50TmFtZUlkID0gc3RyaXBBbmRDYW1lbENhc2UoYWNjb3VudE5hbWUpO1xuXG4gICAgICAgIGNvbnN0IGltcG9ydGVkQWNjb3VudCA9IHRoaXMuZXhpc3RpbmdBY2NvdW50cz8uZmluZChcbiAgICAgICAgICAoYWNjb3VudCkgPT4gYWNjb3VudC5OYW1lID09PSBhY2NvdW50TmFtZVxuICAgICAgICApO1xuICAgICAgICBjb25zdCBhY2NvdW50RW1haWwgPSBpbXBvcnRlZEFjY291bnRcbiAgICAgICAgICA/IGltcG9ydGVkQWNjb3VudC5FbWFpbFxuICAgICAgICAgIDogYWRkU3VmZml4VG9FbWFpbChvcmdFbWFpbCwgYWNjb3VudE5hbWVJZC50b0xvd2VyQ2FzZSgpKTtcblxuICAgICAgICBpZiAoYWNjb3VudEVtYWlsKSB7XG4gICAgICAgICAgdGhpcy5hZGRBY2NvdW50KFxuICAgICAgICAgICAgYCR7YWNjb3VudE5hbWVJZH1BY2NvdW50YCxcbiAgICAgICAgICAgIGFjY291bnROYW1lLFxuICAgICAgICAgICAgYWNjb3VudEVtYWlsLFxuICAgICAgICAgICAgeyBlbnY6IGVudmlyb25tZW50VHlwZSB9LFxuICAgICAgICAgICAgb3JnVW5pdFxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFkZE9yZ2FuaXNhdGlvbmFsVW5pdChpZDogc3RyaW5nLCBuYW1lOiBzdHJpbmcpOiBPcmdhbml6YXRpb25hbFVuaXQge1xuICAgIGNvbnN0IG91ID0gbmV3IE9yZ2FuaXphdGlvbmFsVW5pdCh0aGlzLCBpZCwge1xuICAgICAgb3JnYW5pemF0aW9uYWxVbml0TmFtZTogbmFtZSxcbiAgICAgIHBhcmVudDogdGhpcy5vcmdhbmlzYXRpb24ucm9vdCxcbiAgICAgIGltcG9ydE9uRHVwbGljYXRlOiB0cnVlXG4gICAgfSk7XG5cbiAgICB0aGlzLm9yZ2FuaXNhdGlvbmFsVW5pdHMucHVzaChvdSk7XG4gICAgcmV0dXJuIG91O1xuICB9XG5cbiAgcHJpdmF0ZSBhZGRBY2NvdW50KFxuICAgIGlkOiBzdHJpbmcsXG4gICAgbmFtZTogc3RyaW5nLFxuICAgIGVtYWlsOiBzdHJpbmcsXG4gICAgdGFnczogeyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfSxcbiAgICBvcmdhbmlzYXRpb25hbFVuaXQ6IE9yZ2FuaXphdGlvbmFsVW5pdFxuICApOiBBY2NvdW50IHtcbiAgICBjb25zdCBhY2MgPSBuZXcgQWNjb3VudCh0aGlzLCBpZCwge1xuICAgICAgYWNjb3VudE5hbWU6IG5hbWUsXG4gICAgICBlbWFpbDogZW1haWwsXG4gICAgICBwYXJlbnQ6IG9yZ2FuaXNhdGlvbmFsVW5pdCxcbiAgICAgIGltcG9ydE9uRHVwbGljYXRlOiB0cnVlXG4gICAgfSk7XG5cbiAgICBmb3IgKGNvbnN0IHRhZyBpbiB0YWdzKSB7XG4gICAgICBUYWdzLm9mKGFjYykuYWRkKHRhZywgdGFnc1t0YWddKTtcbiAgICB9XG5cbiAgICB0aGlzLmFjY291bnRzW25hbWVdID0gYWNjLmFjY291bnRJZDtcblxuICAgIG5ldyBDZm5PdXRwdXQodGhpcywgYCR7aWR9SWRgLCB7XG4gICAgICBrZXk6IGAke2lkfUlkYCxcbiAgICAgIHZhbHVlOiBhY2MuYWNjb3VudElkLFxuICAgICAgZXhwb3J0TmFtZTogYCR7aWR9SWRgXG4gICAgfSk7XG4gICAgbmV3IENmbk91dHB1dCh0aGlzLCBgJHtpZH1Bcm5gLCB7XG4gICAgICBrZXk6IGAke2lkfUFybmAsXG4gICAgICB2YWx1ZTogYWNjLmFjY291bnRBcm4sXG4gICAgICBleHBvcnROYW1lOiBgJHtpZH1Bcm5gXG4gICAgfSk7XG5cbiAgICByZXR1cm4gYWNjO1xuICB9XG5cbiAgcHVibGljIGdldEFjY291bnRzKCkge1xuICAgIHJldHVybiB0aGlzLmFjY291bnRzO1xuICB9XG59XG4iXX0=
@@ -0,0 +1,7 @@
1
+ import { CfnOutput } from "aws-cdk-lib";
2
+ import { Construct } from "constructs";
3
+ export declare class OrganisationId extends Construct {
4
+ readonly organisationId: CfnOutput;
5
+ readonly organisationAccountArn: CfnOutput;
6
+ constructor(scope: Construct, id: string);
7
+ }
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.OrganisationId = void 0;
4
+ const aws_cdk_lib_1 = require("aws-cdk-lib");
5
+ const customResources = require("aws-cdk-lib/custom-resources");
6
+ const aws_iam_1 = require("aws-cdk-lib/aws-iam");
7
+ const constructs_1 = require("constructs");
8
+ const awsCustomResource_1 = require("../../resources/aws/utilities/awsCustomResource");
9
+ class OrganisationId extends constructs_1.Construct {
10
+ constructor(scope, id) {
11
+ super(scope, id);
12
+ const organisation = new awsCustomResource_1.AwsCustomResource(this, "OrganisationResource", {
13
+ functionName: "organisationId",
14
+ onCreate: {
15
+ service: "organizations",
16
+ action: "DescribeOrganizationCommand", // https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Organizations.html#describeOrganization-property
17
+ physicalResourceId: customResources.PhysicalResourceId.of("organisationId")
18
+ },
19
+ onUpdate: {
20
+ service: "organizations",
21
+ action: "DescribeOrganizationCommand", // https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Organizations.html#describeOrganization-property
22
+ physicalResourceId: customResources.PhysicalResourceId.of("organisationId")
23
+ },
24
+ resourceType: "Custom::DescribeOrganisation",
25
+ policy: customResources.AwsCustomResourcePolicy.fromStatements([
26
+ new aws_iam_1.PolicyStatement({
27
+ actions: ["organizations:DescribeOrganization"],
28
+ resources: ["*"],
29
+ effect: aws_iam_1.Effect.ALLOW
30
+ })
31
+ ])
32
+ });
33
+ this.organisationId = new aws_cdk_lib_1.CfnOutput(this, "OrganisationIdOutput", {
34
+ key: "OrganisationId",
35
+ value: organisation.getResponseField("Organization.Id"),
36
+ exportName: "OrganisationId"
37
+ });
38
+ this.organisationAccountArn = new aws_cdk_lib_1.CfnOutput(this, "OrganisationAccountArnOutput", {
39
+ key: "OrganisationAccountArn",
40
+ value: organisation.getResponseField("Organization.MasterAccountArn"),
41
+ exportName: "OrganisationAccountArn"
42
+ });
43
+ }
44
+ }
45
+ exports.OrganisationId = OrganisationId;
46
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3JnYW5pc2F0aW9uSWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9saWIvY29uZmlnL2F3cy9vcmdhbmlzYXRpb25JZC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSw2Q0FBd0M7QUFDeEMsZ0VBQWdFO0FBQ2hFLGlEQUE4RDtBQUM5RCwyQ0FBdUM7QUFFdkMsdUZBQW9GO0FBRXBGLE1BQWEsY0FBZSxTQUFRLHNCQUFTO0lBSTNDLFlBQVksS0FBZ0IsRUFBRSxFQUFVO1FBQ3RDLEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFFakIsTUFBTSxZQUFZLEdBQUcsSUFBSSxxQ0FBaUIsQ0FBQyxJQUFJLEVBQUUsc0JBQXNCLEVBQUU7WUFDdkUsWUFBWSxFQUFFLGdCQUFnQjtZQUM5QixRQUFRLEVBQUU7Z0JBQ1IsT0FBTyxFQUFFLGVBQWU7Z0JBQ3hCLE1BQU0sRUFBRSw2QkFBNkIsRUFBRSwyR0FBMkc7Z0JBQ2xKLGtCQUFrQixFQUNoQixlQUFlLENBQUMsa0JBQWtCLENBQUMsRUFBRSxDQUFDLGdCQUFnQixDQUFDO2FBQzFEO1lBQ0QsUUFBUSxFQUFFO2dCQUNSLE9BQU8sRUFBRSxlQUFlO2dCQUN4QixNQUFNLEVBQUUsNkJBQTZCLEVBQUUsMkdBQTJHO2dCQUNsSixrQkFBa0IsRUFDaEIsZUFBZSxDQUFDLGtCQUFrQixDQUFDLEVBQUUsQ0FBQyxnQkFBZ0IsQ0FBQzthQUMxRDtZQUNELFlBQVksRUFBRSw4QkFBOEI7WUFDNUMsTUFBTSxFQUFFLGVBQWUsQ0FBQyx1QkFBdUIsQ0FBQyxjQUFjLENBQUM7Z0JBQzdELElBQUkseUJBQWUsQ0FBQztvQkFDbEIsT0FBTyxFQUFFLENBQUMsb0NBQW9DLENBQUM7b0JBQy9DLFNBQVMsRUFBRSxDQUFDLEdBQUcsQ0FBQztvQkFDaEIsTUFBTSxFQUFFLGdCQUFNLENBQUMsS0FBSztpQkFDckIsQ0FBQzthQUNILENBQUM7U0FDSCxDQUFDLENBQUM7UUFFSCxJQUFJLENBQUMsY0FBYyxHQUFHLElBQUksdUJBQVMsQ0FBQyxJQUFJLEVBQUUsc0JBQXNCLEVBQUU7WUFDaEUsR0FBRyxFQUFFLGdCQUFnQjtZQUNyQixLQUFLLEVBQUUsWUFBWSxDQUFDLGdCQUFnQixDQUFDLGlCQUFpQixDQUFDO1lBQ3ZELFVBQVUsRUFBRSxnQkFBZ0I7U0FDN0IsQ0FBQyxDQUFDO1FBRUgsSUFBSSxDQUFDLHNCQUFzQixHQUFHLElBQUksdUJBQVMsQ0FDekMsSUFBSSxFQUNKLDhCQUE4QixFQUM5QjtZQUNFLEdBQUcsRUFBRSx3QkFBd0I7WUFDN0IsS0FBSyxFQUFFLFlBQVksQ0FBQyxnQkFBZ0IsQ0FBQywrQkFBK0IsQ0FBQztZQUNyRSxVQUFVLEVBQUUsd0JBQXdCO1NBQ3JDLENBQ0YsQ0FBQztJQUNKLENBQUM7Q0FDRjtBQS9DRCx3Q0ErQ0MiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDZm5PdXRwdXQgfSBmcm9tIFwiYXdzLWNkay1saWJcIjtcbmltcG9ydCAqIGFzIGN1c3RvbVJlc291cmNlcyBmcm9tIFwiYXdzLWNkay1saWIvY3VzdG9tLXJlc291cmNlc1wiO1xuaW1wb3J0IHsgRWZmZWN0LCBQb2xpY3lTdGF0ZW1lbnQgfSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWlhbVwiO1xuaW1wb3J0IHsgQ29uc3RydWN0IH0gZnJvbSBcImNvbnN0cnVjdHNcIjtcblxuaW1wb3J0IHsgQXdzQ3VzdG9tUmVzb3VyY2UgfSBmcm9tIFwiLi4vLi4vcmVzb3VyY2VzL2F3cy91dGlsaXRpZXMvYXdzQ3VzdG9tUmVzb3VyY2VcIjtcblxuZXhwb3J0IGNsYXNzIE9yZ2FuaXNhdGlvbklkIGV4dGVuZHMgQ29uc3RydWN0IHtcbiAgcHVibGljIHJlYWRvbmx5IG9yZ2FuaXNhdGlvbklkOiBDZm5PdXRwdXQ7XG4gIHB1YmxpYyByZWFkb25seSBvcmdhbmlzYXRpb25BY2NvdW50QXJuOiBDZm5PdXRwdXQ7XG5cbiAgY29uc3RydWN0b3Ioc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZykge1xuICAgIHN1cGVyKHNjb3BlLCBpZCk7XG5cbiAgICBjb25zdCBvcmdhbmlzYXRpb24gPSBuZXcgQXdzQ3VzdG9tUmVzb3VyY2UodGhpcywgXCJPcmdhbmlzYXRpb25SZXNvdXJjZVwiLCB7XG4gICAgICBmdW5jdGlvbk5hbWU6IFwib3JnYW5pc2F0aW9uSWRcIixcbiAgICAgIG9uQ3JlYXRlOiB7XG4gICAgICAgIHNlcnZpY2U6IFwib3JnYW5pemF0aW9uc1wiLFxuICAgICAgICBhY3Rpb246IFwiRGVzY3JpYmVPcmdhbml6YXRpb25Db21tYW5kXCIsIC8vIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9BV1NKYXZhU2NyaXB0U0RLL2xhdGVzdC9BV1MvT3JnYW5pemF0aW9ucy5odG1sI2Rlc2NyaWJlT3JnYW5pemF0aW9uLXByb3BlcnR5XG4gICAgICAgIHBoeXNpY2FsUmVzb3VyY2VJZDpcbiAgICAgICAgICBjdXN0b21SZXNvdXJjZXMuUGh5c2ljYWxSZXNvdXJjZUlkLm9mKFwib3JnYW5pc2F0aW9uSWRcIilcbiAgICAgIH0sXG4gICAgICBvblVwZGF0ZToge1xuICAgICAgICBzZXJ2aWNlOiBcIm9yZ2FuaXphdGlvbnNcIixcbiAgICAgICAgYWN0aW9uOiBcIkRlc2NyaWJlT3JnYW5pemF0aW9uQ29tbWFuZFwiLCAvLyBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTSmF2YVNjcmlwdFNESy9sYXRlc3QvQVdTL09yZ2FuaXphdGlvbnMuaHRtbCNkZXNjcmliZU9yZ2FuaXphdGlvbi1wcm9wZXJ0eVxuICAgICAgICBwaHlzaWNhbFJlc291cmNlSWQ6XG4gICAgICAgICAgY3VzdG9tUmVzb3VyY2VzLlBoeXNpY2FsUmVzb3VyY2VJZC5vZihcIm9yZ2FuaXNhdGlvbklkXCIpXG4gICAgICB9LFxuICAgICAgcmVzb3VyY2VUeXBlOiBcIkN1c3RvbTo6RGVzY3JpYmVPcmdhbmlzYXRpb25cIixcbiAgICAgIHBvbGljeTogY3VzdG9tUmVzb3VyY2VzLkF3c0N1c3RvbVJlc291cmNlUG9saWN5LmZyb21TdGF0ZW1lbnRzKFtcbiAgICAgICAgbmV3IFBvbGljeVN0YXRlbWVudCh7XG4gICAgICAgICAgYWN0aW9uczogW1wib3JnYW5pemF0aW9uczpEZXNjcmliZU9yZ2FuaXphdGlvblwiXSxcbiAgICAgICAgICByZXNvdXJjZXM6IFtcIipcIl0sXG4gICAgICAgICAgZWZmZWN0OiBFZmZlY3QuQUxMT1dcbiAgICAgICAgfSlcbiAgICAgIF0pXG4gICAgfSk7XG5cbiAgICB0aGlzLm9yZ2FuaXNhdGlvbklkID0gbmV3IENmbk91dHB1dCh0aGlzLCBcIk9yZ2FuaXNhdGlvbklkT3V0cHV0XCIsIHtcbiAgICAgIGtleTogXCJPcmdhbmlzYXRpb25JZFwiLFxuICAgICAgdmFsdWU6IG9yZ2FuaXNhdGlvbi5nZXRSZXNwb25zZUZpZWxkKFwiT3JnYW5pemF0aW9uLklkXCIpLFxuICAgICAgZXhwb3J0TmFtZTogXCJPcmdhbmlzYXRpb25JZFwiXG4gICAgfSk7XG5cbiAgICB0aGlzLm9yZ2FuaXNhdGlvbkFjY291bnRBcm4gPSBuZXcgQ2ZuT3V0cHV0KFxuICAgICAgdGhpcyxcbiAgICAgIFwiT3JnYW5pc2F0aW9uQWNjb3VudEFybk91dHB1dFwiLFxuICAgICAge1xuICAgICAgICBrZXk6IFwiT3JnYW5pc2F0aW9uQWNjb3VudEFyblwiLFxuICAgICAgICB2YWx1ZTogb3JnYW5pc2F0aW9uLmdldFJlc3BvbnNlRmllbGQoXCJPcmdhbml6YXRpb24uTWFzdGVyQWNjb3VudEFyblwiKSxcbiAgICAgICAgZXhwb3J0TmFtZTogXCJPcmdhbmlzYXRpb25BY2NvdW50QXJuXCJcbiAgICAgIH1cbiAgICApO1xuICB9XG59XG4iXX0=
@@ -0,0 +1,10 @@
1
+ import { Construct } from "constructs";
2
+ import { type StackProps } from "aws-cdk-lib";
3
+ interface ActivateOrganisationsAccessProps extends StackProps {
4
+ account: string;
5
+ region: string;
6
+ }
7
+ export declare class ActivateOrganisationsAccess extends Construct {
8
+ constructor(scope: Construct, id: string, props: ActivateOrganisationsAccessProps);
9
+ }
10
+ export {};
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ActivateOrganisationsAccess = void 0;
4
+ const customResources = require("aws-cdk-lib/custom-resources");
5
+ const constructs_1 = require("constructs");
6
+ const awsCustomResource_1 = require("../../resources/aws/utilities/awsCustomResource");
7
+ const aws_iam_1 = require("aws-cdk-lib/aws-iam");
8
+ class ActivateOrganisationsAccess extends constructs_1.Construct {
9
+ constructor(scope, id, props) {
10
+ super(scope, id);
11
+ new awsCustomResource_1.AwsCustomResource(this, "activateOrganisationsAccess", {
12
+ functionName: "activateOrganisationsAccess",
13
+ onCreate: {
14
+ service: "cloudformation",
15
+ action: "ActivateOrganizationsAccessCommand", // https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/cloudformation/command/ActivateOrganizationsAccessCommand/
16
+ parameters: {},
17
+ physicalResourceId: customResources.PhysicalResourceId.of("activateOrganisationsAccess")
18
+ },
19
+ resourceType: "Custom::ActivateOrganisationsAccess",
20
+ policy: customResources.AwsCustomResourcePolicy.fromStatements([
21
+ new aws_iam_1.PolicyStatement({
22
+ actions: [
23
+ "cloudformation:ActivateOrganizationsAccess",
24
+ "cloudformation:DescribeOrganizationsAccess",
25
+ "organizations:EnableAWSServiceAccess",
26
+ "organizations:DescribeOrganization",
27
+ "organizations:ListRoots",
28
+ "organizations:ListAWSServiceAccessForOrganization",
29
+ "organizations:DisableAWSServiceAccess",
30
+ "iam:CreateServiceLinkedRole",
31
+ "iam:GetRole"
32
+ ],
33
+ resources: [
34
+ "*" // TODO: Figure out what access is required here
35
+ ],
36
+ effect: aws_iam_1.Effect.ALLOW
37
+ }),
38
+ new aws_iam_1.PolicyStatement({
39
+ actions: ["cloudformation:ActivateOrganizationsAccess"],
40
+ resources: [
41
+ `arn:aws:cloudformation:${props.region}:${props.account}:stackset/*`
42
+ ],
43
+ effect: aws_iam_1.Effect.ALLOW
44
+ })
45
+ ])
46
+ });
47
+ }
48
+ }
49
+ exports.ActivateOrganisationsAccess = ActivateOrganisationsAccess;
50
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3JnYW5pc2F0aW9uc0FjY2Vzcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9jb25maWcvYXdzL29yZ2FuaXNhdGlvbnNBY2Nlc3MudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsZ0VBQWdFO0FBQ2hFLDJDQUF1QztBQUV2Qyx1RkFBb0Y7QUFDcEYsaURBQThEO0FBUTlELE1BQWEsMkJBQTRCLFNBQVEsc0JBQVM7SUFDeEQsWUFDRSxLQUFnQixFQUNoQixFQUFVLEVBQ1YsS0FBdUM7UUFFdkMsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQztRQUVqQixJQUFJLHFDQUFpQixDQUFDLElBQUksRUFBRSw2QkFBNkIsRUFBRTtZQUN6RCxZQUFZLEVBQUUsNkJBQTZCO1lBQzNDLFFBQVEsRUFBRTtnQkFDUixPQUFPLEVBQUUsZ0JBQWdCO2dCQUN6QixNQUFNLEVBQUUsb0NBQW9DLEVBQUUsMkhBQTJIO2dCQUN6SyxVQUFVLEVBQUUsRUFBRTtnQkFDZCxrQkFBa0IsRUFBRSxlQUFlLENBQUMsa0JBQWtCLENBQUMsRUFBRSxDQUN2RCw2QkFBNkIsQ0FDOUI7YUFDRjtZQUNELFlBQVksRUFBRSxxQ0FBcUM7WUFDbkQsTUFBTSxFQUFFLGVBQWUsQ0FBQyx1QkFBdUIsQ0FBQyxjQUFjLENBQUM7Z0JBQzdELElBQUkseUJBQWUsQ0FBQztvQkFDbEIsT0FBTyxFQUFFO3dCQUNQLDRDQUE0Qzt3QkFDNUMsNENBQTRDO3dCQUM1QyxzQ0FBc0M7d0JBQ3RDLG9DQUFvQzt3QkFDcEMseUJBQXlCO3dCQUN6QixtREFBbUQ7d0JBQ25ELHVDQUF1Qzt3QkFDdkMsNkJBQTZCO3dCQUM3QixhQUFhO3FCQUNkO29CQUNELFNBQVMsRUFBRTt3QkFDVCxHQUFHLENBQUMsZ0RBQWdEO3FCQUNyRDtvQkFDRCxNQUFNLEVBQUUsZ0JBQU0sQ0FBQyxLQUFLO2lCQUNyQixDQUFDO2dCQUNGLElBQUkseUJBQWUsQ0FBQztvQkFDbEIsT0FBTyxFQUFFLENBQUMsNENBQTRDLENBQUM7b0JBQ3ZELFNBQVMsRUFBRTt3QkFDVCwwQkFBMEIsS0FBSyxDQUFDLE1BQU0sSUFBSSxLQUFLLENBQUMsT0FBTyxhQUFhO3FCQUNyRTtvQkFDRCxNQUFNLEVBQUUsZ0JBQU0sQ0FBQyxLQUFLO2lCQUNyQixDQUFDO2FBQ0gsQ0FBQztTQUNILENBQUMsQ0FBQztJQUNMLENBQUM7Q0FDRjtBQS9DRCxrRUErQ0MiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBjdXN0b21SZXNvdXJjZXMgZnJvbSBcImF3cy1jZGstbGliL2N1c3RvbS1yZXNvdXJjZXNcIjtcbmltcG9ydCB7IENvbnN0cnVjdCB9IGZyb20gXCJjb25zdHJ1Y3RzXCI7XG5cbmltcG9ydCB7IEF3c0N1c3RvbVJlc291cmNlIH0gZnJvbSBcIi4uLy4uL3Jlc291cmNlcy9hd3MvdXRpbGl0aWVzL2F3c0N1c3RvbVJlc291cmNlXCI7XG5pbXBvcnQgeyBFZmZlY3QsIFBvbGljeVN0YXRlbWVudCB9IGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtaWFtXCI7XG5pbXBvcnQgeyB0eXBlIFN0YWNrUHJvcHMgfSBmcm9tIFwiYXdzLWNkay1saWJcIjtcblxuaW50ZXJmYWNlIEFjdGl2YXRlT3JnYW5pc2F0aW9uc0FjY2Vzc1Byb3BzIGV4dGVuZHMgU3RhY2tQcm9wcyB7XG4gIGFjY291bnQ6IHN0cmluZztcbiAgcmVnaW9uOiBzdHJpbmc7XG59XG5cbmV4cG9ydCBjbGFzcyBBY3RpdmF0ZU9yZ2FuaXNhdGlvbnNBY2Nlc3MgZXh0ZW5kcyBDb25zdHJ1Y3Qge1xuICBjb25zdHJ1Y3RvcihcbiAgICBzY29wZTogQ29uc3RydWN0LFxuICAgIGlkOiBzdHJpbmcsXG4gICAgcHJvcHM6IEFjdGl2YXRlT3JnYW5pc2F0aW9uc0FjY2Vzc1Byb3BzXG4gICkge1xuICAgIHN1cGVyKHNjb3BlLCBpZCk7XG5cbiAgICBuZXcgQXdzQ3VzdG9tUmVzb3VyY2UodGhpcywgXCJhY3RpdmF0ZU9yZ2FuaXNhdGlvbnNBY2Nlc3NcIiwge1xuICAgICAgZnVuY3Rpb25OYW1lOiBcImFjdGl2YXRlT3JnYW5pc2F0aW9uc0FjY2Vzc1wiLFxuICAgICAgb25DcmVhdGU6IHtcbiAgICAgICAgc2VydmljZTogXCJjbG91ZGZvcm1hdGlvblwiLFxuICAgICAgICBhY3Rpb246IFwiQWN0aXZhdGVPcmdhbml6YXRpb25zQWNjZXNzQ29tbWFuZFwiLCAvLyBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTSmF2YVNjcmlwdFNESy92My9sYXRlc3QvY2xpZW50L2Nsb3VkZm9ybWF0aW9uL2NvbW1hbmQvQWN0aXZhdGVPcmdhbml6YXRpb25zQWNjZXNzQ29tbWFuZC9cbiAgICAgICAgcGFyYW1ldGVyczoge30sXG4gICAgICAgIHBoeXNpY2FsUmVzb3VyY2VJZDogY3VzdG9tUmVzb3VyY2VzLlBoeXNpY2FsUmVzb3VyY2VJZC5vZihcbiAgICAgICAgICBcImFjdGl2YXRlT3JnYW5pc2F0aW9uc0FjY2Vzc1wiXG4gICAgICAgIClcbiAgICAgIH0sXG4gICAgICByZXNvdXJjZVR5cGU6IFwiQ3VzdG9tOjpBY3RpdmF0ZU9yZ2FuaXNhdGlvbnNBY2Nlc3NcIixcbiAgICAgIHBvbGljeTogY3VzdG9tUmVzb3VyY2VzLkF3c0N1c3RvbVJlc291cmNlUG9saWN5LmZyb21TdGF0ZW1lbnRzKFtcbiAgICAgICAgbmV3IFBvbGljeVN0YXRlbWVudCh7XG4gICAgICAgICAgYWN0aW9uczogW1xuICAgICAgICAgICAgXCJjbG91ZGZvcm1hdGlvbjpBY3RpdmF0ZU9yZ2FuaXphdGlvbnNBY2Nlc3NcIixcbiAgICAgICAgICAgIFwiY2xvdWRmb3JtYXRpb246RGVzY3JpYmVPcmdhbml6YXRpb25zQWNjZXNzXCIsXG4gICAgICAgICAgICBcIm9yZ2FuaXphdGlvbnM6RW5hYmxlQVdTU2VydmljZUFjY2Vzc1wiLFxuICAgICAgICAgICAgXCJvcmdhbml6YXRpb25zOkRlc2NyaWJlT3JnYW5pemF0aW9uXCIsXG4gICAgICAgICAgICBcIm9yZ2FuaXphdGlvbnM6TGlzdFJvb3RzXCIsXG4gICAgICAgICAgICBcIm9yZ2FuaXphdGlvbnM6TGlzdEFXU1NlcnZpY2VBY2Nlc3NGb3JPcmdhbml6YXRpb25cIixcbiAgICAgICAgICAgIFwib3JnYW5pemF0aW9uczpEaXNhYmxlQVdTU2VydmljZUFjY2Vzc1wiLFxuICAgICAgICAgICAgXCJpYW06Q3JlYXRlU2VydmljZUxpbmtlZFJvbGVcIixcbiAgICAgICAgICAgIFwiaWFtOkdldFJvbGVcIlxuICAgICAgICAgIF0sXG4gICAgICAgICAgcmVzb3VyY2VzOiBbXG4gICAgICAgICAgICBcIipcIiAvLyBUT0RPOiBGaWd1cmUgb3V0IHdoYXQgYWNjZXNzIGlzIHJlcXVpcmVkIGhlcmVcbiAgICAgICAgICBdLFxuICAgICAgICAgIGVmZmVjdDogRWZmZWN0LkFMTE9XXG4gICAgICAgIH0pLFxuICAgICAgICBuZXcgUG9saWN5U3RhdGVtZW50KHtcbiAgICAgICAgICBhY3Rpb25zOiBbXCJjbG91ZGZvcm1hdGlvbjpBY3RpdmF0ZU9yZ2FuaXphdGlvbnNBY2Nlc3NcIl0sXG4gICAgICAgICAgcmVzb3VyY2VzOiBbXG4gICAgICAgICAgICBgYXJuOmF3czpjbG91ZGZvcm1hdGlvbjoke3Byb3BzLnJlZ2lvbn06JHtwcm9wcy5hY2NvdW50fTpzdGFja3NldC8qYFxuICAgICAgICAgIF0sXG4gICAgICAgICAgZWZmZWN0OiBFZmZlY3QuQUxMT1dcbiAgICAgICAgfSlcbiAgICAgIF0pXG4gICAgfSk7XG4gIH1cbn1cbiJdfQ==
@@ -0,0 +1,4 @@
1
+ import { Construct } from "constructs";
2
+ export declare class RamSharing extends Construct {
3
+ constructor(scope: Construct, id: string);
4
+ }
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RamSharing = void 0;
4
+ const customResources = require("aws-cdk-lib/custom-resources");
5
+ const aws_iam_1 = require("aws-cdk-lib/aws-iam");
6
+ const constructs_1 = require("constructs");
7
+ const awsCustomResource_1 = require("../../resources/aws/utilities/awsCustomResource");
8
+ class RamSharing extends constructs_1.Construct {
9
+ constructor(scope, id) {
10
+ super(scope, id);
11
+ new awsCustomResource_1.AwsCustomResource(this, "enableRamSharing", {
12
+ functionName: "enableRamSharing",
13
+ onCreate: {
14
+ service: "RAM",
15
+ action: "enableSharingWithAwsOrganization", // https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/RAM.html#enableSharingWithAwsOrganization-property
16
+ parameters: {},
17
+ physicalResourceId: customResources.PhysicalResourceId.of("enableRamSharing")
18
+ },
19
+ resourceType: "Custom::ram",
20
+ policy: customResources.AwsCustomResourcePolicy.fromStatements([
21
+ new aws_iam_1.PolicyStatement({
22
+ actions: [
23
+ "ram:EnableSharingWithAwsOrganization",
24
+ "iam:CreateServiceLinkedRole",
25
+ "organizations:enableAWSServiceAccess",
26
+ "organizations:DescribeOrganization"
27
+ ],
28
+ resources: ["*"] // TODO: Find out the exact pricipal for this
29
+ })
30
+ ])
31
+ });
32
+ }
33
+ }
34
+ exports.RamSharing = RamSharing;
35
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmFtU2hhcmluZy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9jb25maWcvYXdzL3JhbVNoYXJpbmcudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsZ0VBQWdFO0FBQ2hFLGlEQUFzRDtBQUN0RCwyQ0FBdUM7QUFFdkMsdUZBQW9GO0FBRXBGLE1BQWEsVUFBVyxTQUFRLHNCQUFTO0lBQ3ZDLFlBQVksS0FBZ0IsRUFBRSxFQUFVO1FBQ3RDLEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFFakIsSUFBSSxxQ0FBaUIsQ0FBQyxJQUFJLEVBQUUsa0JBQWtCLEVBQUU7WUFDOUMsWUFBWSxFQUFFLGtCQUFrQjtZQUNoQyxRQUFRLEVBQUU7Z0JBQ1IsT0FBTyxFQUFFLEtBQUs7Z0JBQ2QsTUFBTSxFQUFFLGtDQUFrQyxFQUFFLDZHQUE2RztnQkFDekosVUFBVSxFQUFFLEVBQUU7Z0JBQ2Qsa0JBQWtCLEVBQ2hCLGVBQWUsQ0FBQyxrQkFBa0IsQ0FBQyxFQUFFLENBQUMsa0JBQWtCLENBQUM7YUFDNUQ7WUFDRCxZQUFZLEVBQUUsYUFBYTtZQUMzQixNQUFNLEVBQUUsZUFBZSxDQUFDLHVCQUF1QixDQUFDLGNBQWMsQ0FBQztnQkFDN0QsSUFBSSx5QkFBZSxDQUFDO29CQUNsQixPQUFPLEVBQUU7d0JBQ1Asc0NBQXNDO3dCQUN0Qyw2QkFBNkI7d0JBQzdCLHNDQUFzQzt3QkFDdEMsb0NBQW9DO3FCQUNyQztvQkFDRCxTQUFTLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyw2Q0FBNkM7aUJBQy9ELENBQUM7YUFDSCxDQUFDO1NBQ0gsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztDQUNGO0FBM0JELGdDQTJCQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIGN1c3RvbVJlc291cmNlcyBmcm9tIFwiYXdzLWNkay1saWIvY3VzdG9tLXJlc291cmNlc1wiO1xuaW1wb3J0IHsgUG9saWN5U3RhdGVtZW50IH0gZnJvbSBcImF3cy1jZGstbGliL2F3cy1pYW1cIjtcbmltcG9ydCB7IENvbnN0cnVjdCB9IGZyb20gXCJjb25zdHJ1Y3RzXCI7XG5cbmltcG9ydCB7IEF3c0N1c3RvbVJlc291cmNlIH0gZnJvbSBcIi4uLy4uL3Jlc291cmNlcy9hd3MvdXRpbGl0aWVzL2F3c0N1c3RvbVJlc291cmNlXCI7XG5cbmV4cG9ydCBjbGFzcyBSYW1TaGFyaW5nIGV4dGVuZHMgQ29uc3RydWN0IHtcbiAgY29uc3RydWN0b3Ioc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZykge1xuICAgIHN1cGVyKHNjb3BlLCBpZCk7XG5cbiAgICBuZXcgQXdzQ3VzdG9tUmVzb3VyY2UodGhpcywgXCJlbmFibGVSYW1TaGFyaW5nXCIsIHtcbiAgICAgIGZ1bmN0aW9uTmFtZTogXCJlbmFibGVSYW1TaGFyaW5nXCIsXG4gICAgICBvbkNyZWF0ZToge1xuICAgICAgICBzZXJ2aWNlOiBcIlJBTVwiLFxuICAgICAgICBhY3Rpb246IFwiZW5hYmxlU2hhcmluZ1dpdGhBd3NPcmdhbml6YXRpb25cIiwgLy8gaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FXU0phdmFTY3JpcHRTREsvbGF0ZXN0L0FXUy9SQU0uaHRtbCNlbmFibGVTaGFyaW5nV2l0aEF3c09yZ2FuaXphdGlvbi1wcm9wZXJ0eVxuICAgICAgICBwYXJhbWV0ZXJzOiB7fSxcbiAgICAgICAgcGh5c2ljYWxSZXNvdXJjZUlkOlxuICAgICAgICAgIGN1c3RvbVJlc291cmNlcy5QaHlzaWNhbFJlc291cmNlSWQub2YoXCJlbmFibGVSYW1TaGFyaW5nXCIpXG4gICAgICB9LFxuICAgICAgcmVzb3VyY2VUeXBlOiBcIkN1c3RvbTo6cmFtXCIsXG4gICAgICBwb2xpY3k6IGN1c3RvbVJlc291cmNlcy5Bd3NDdXN0b21SZXNvdXJjZVBvbGljeS5mcm9tU3RhdGVtZW50cyhbXG4gICAgICAgIG5ldyBQb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgICAgIGFjdGlvbnM6IFtcbiAgICAgICAgICAgIFwicmFtOkVuYWJsZVNoYXJpbmdXaXRoQXdzT3JnYW5pemF0aW9uXCIsXG4gICAgICAgICAgICBcImlhbTpDcmVhdGVTZXJ2aWNlTGlua2VkUm9sZVwiLFxuICAgICAgICAgICAgXCJvcmdhbml6YXRpb25zOmVuYWJsZUFXU1NlcnZpY2VBY2Nlc3NcIixcbiAgICAgICAgICAgIFwib3JnYW5pemF0aW9uczpEZXNjcmliZU9yZ2FuaXphdGlvblwiXG4gICAgICAgICAgXSxcbiAgICAgICAgICByZXNvdXJjZXM6IFtcIipcIl0gLy8gVE9ETzogRmluZCBvdXQgdGhlIGV4YWN0IHByaWNpcGFsIGZvciB0aGlzXG4gICAgICAgIH0pXG4gICAgICBdKVxuICAgIH0pO1xuICB9XG59XG4iXX0=
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Monitoring configuration for cross-account access
3
+ */
4
+ export declare const FJALL_MONITORING_CONFIG: {
5
+ /**
6
+ * Fjall webapp AWS account ID
7
+ * This account will be granted permission to assume monitoring roles
8
+ */
9
+ readonly webappAwsAccountId: "985539798308";
10
+ /**
11
+ * IAM role naming convention
12
+ */
13
+ readonly roleNamePrefix: "FjallMonitoring";
14
+ /**
15
+ * IAM role path (for organizational structure)
16
+ */
17
+ readonly rolePath: "/";
18
+ };
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FJALL_MONITORING_CONFIG = void 0;
4
+ /**
5
+ * Monitoring configuration for cross-account access
6
+ */
7
+ exports.FJALL_MONITORING_CONFIG = {
8
+ /**
9
+ * Fjall webapp AWS account ID
10
+ * This account will be granted permission to assume monitoring roles
11
+ */
12
+ webappAwsAccountId: "985539798308", // Fjall platform account
13
+ /**
14
+ * IAM role naming convention
15
+ */
16
+ roleNamePrefix: "FjallMonitoring",
17
+ /**
18
+ * IAM role path (for organizational structure)
19
+ */
20
+ rolePath: "/"
21
+ };
22
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibW9uaXRvcmluZy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL2xpYi9jb25maWcvbW9uaXRvcmluZy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQTs7R0FFRztBQUNVLFFBQUEsdUJBQXVCLEdBQUc7SUFDckM7OztPQUdHO0lBQ0gsa0JBQWtCLEVBQUUsY0FBYyxFQUFFLHlCQUF5QjtJQUU3RDs7T0FFRztJQUNILGNBQWMsRUFBRSxpQkFBaUI7SUFFakM7O09BRUc7SUFDSCxRQUFRLEVBQUUsR0FBRztDQUNMLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIE1vbml0b3JpbmcgY29uZmlndXJhdGlvbiBmb3IgY3Jvc3MtYWNjb3VudCBhY2Nlc3NcbiAqL1xuZXhwb3J0IGNvbnN0IEZKQUxMX01PTklUT1JJTkdfQ09ORklHID0ge1xuICAvKipcbiAgICogRmphbGwgd2ViYXBwIEFXUyBhY2NvdW50IElEXG4gICAqIFRoaXMgYWNjb3VudCB3aWxsIGJlIGdyYW50ZWQgcGVybWlzc2lvbiB0byBhc3N1bWUgbW9uaXRvcmluZyByb2xlc1xuICAgKi9cbiAgd2ViYXBwQXdzQWNjb3VudElkOiBcIjk4NTUzOTc5ODMwOFwiLCAvLyBGamFsbCBwbGF0Zm9ybSBhY2NvdW50XG5cbiAgLyoqXG4gICAqIElBTSByb2xlIG5hbWluZyBjb252ZW50aW9uXG4gICAqL1xuICByb2xlTmFtZVByZWZpeDogXCJGamFsbE1vbml0b3JpbmdcIixcblxuICAvKipcbiAgICogSUFNIHJvbGUgcGF0aCAoZm9yIG9yZ2FuaXphdGlvbmFsIHN0cnVjdHVyZSlcbiAgICovXG4gIHJvbGVQYXRoOiBcIi9cIlxufSBhcyBjb25zdDtcbiJdfQ==
@@ -0,0 +1,67 @@
1
+ import { Construct } from "constructs";
2
+ import { type Role } from "aws-cdk-lib/aws-iam";
3
+ import { type CICDProvider } from "../../resources/aws/cicd/cicdRole";
4
+ export interface CICDRoleProps {
5
+ /**
6
+ * The CI/CD provider (github-actions, buildkite, gitlab-ci)
7
+ */
8
+ provider: CICDProvider;
9
+ /**
10
+ * For GitHub Actions: repository in format "org/repo"
11
+ * For Buildkite: organization slug
12
+ * For GitLab CI: project path in format "group/project"
13
+ */
14
+ repositoryOrOrg: string;
15
+ /**
16
+ * Optional custom role name
17
+ * Defaults to "FjallDeploy-{provider}-{appName}"
18
+ */
19
+ roleName?: string;
20
+ /**
21
+ * Optional ARN of existing OIDC provider (skips creation)
22
+ * Useful when OIDC provider already exists in the account
23
+ */
24
+ existingProviderArn?: string;
25
+ }
26
+ /**
27
+ * High-level pattern for adding CI/CD OIDC authentication to an application.
28
+ *
29
+ * This creates an OIDC provider (if needed) and a deploy role that can be assumed
30
+ * by your CI/CD system without long-lived credentials.
31
+ *
32
+ * @example
33
+ * ```typescript
34
+ * import { App, CICDRole } from "@fjall/components-infrastructure";
35
+ *
36
+ * const app = App.getApp("MyApp");
37
+ *
38
+ * // Add GitHub Actions OIDC authentication
39
+ * const cicdRole = new CICDRole(app, "GitHubDeployRole", {
40
+ * provider: "github-actions",
41
+ * repositoryOrOrg: "myorg/myrepo"
42
+ * });
43
+ *
44
+ * // Continue with normal application setup
45
+ * app.addCompute(/* ... *\/);
46
+ * ```
47
+ *
48
+ * @example
49
+ * ```typescript
50
+ * // Use existing OIDC provider (created via fjall cicd setup)
51
+ * const cicdRole = new CICDRole(app, "GitHubDeployRole", {
52
+ * provider: "github-actions",
53
+ * repositoryOrOrg: "myorg/myrepo",
54
+ * existingProviderArn: "arn:aws:iam::123456789012:oidc-provider/token.actions.githubusercontent.com"
55
+ * });
56
+ * ```
57
+ */
58
+ export declare class CICDRole extends Construct {
59
+ readonly role: Role;
60
+ readonly provider: CICDProvider;
61
+ constructor(scope: Construct, id: string, props: CICDRoleProps);
62
+ /**
63
+ * Get the role ARN for use in CI/CD configuration
64
+ */
65
+ getRoleArn(): string;
66
+ }
67
+ export default CICDRole;
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CICDRole = void 0;
4
+ const constructs_1 = require("constructs");
5
+ const app_1 = require("../../app");
6
+ const cicdRole_1 = require("../../resources/aws/cicd/cicdRole");
7
+ /**
8
+ * High-level pattern for adding CI/CD OIDC authentication to an application.
9
+ *
10
+ * This creates an OIDC provider (if needed) and a deploy role that can be assumed
11
+ * by your CI/CD system without long-lived credentials.
12
+ *
13
+ * @example
14
+ * ```typescript
15
+ * import { App, CICDRole } from "@fjall/components-infrastructure";
16
+ *
17
+ * const app = App.getApp("MyApp");
18
+ *
19
+ * // Add GitHub Actions OIDC authentication
20
+ * const cicdRole = new CICDRole(app, "GitHubDeployRole", {
21
+ * provider: "github-actions",
22
+ * repositoryOrOrg: "myorg/myrepo"
23
+ * });
24
+ *
25
+ * // Continue with normal application setup
26
+ * app.addCompute(/* ... *\/);
27
+ * ```
28
+ *
29
+ * @example
30
+ * ```typescript
31
+ * // Use existing OIDC provider (created via fjall cicd setup)
32
+ * const cicdRole = new CICDRole(app, "GitHubDeployRole", {
33
+ * provider: "github-actions",
34
+ * repositoryOrOrg: "myorg/myrepo",
35
+ * existingProviderArn: "arn:aws:iam::123456789012:oidc-provider/token.actions.githubusercontent.com"
36
+ * });
37
+ * ```
38
+ */
39
+ class CICDRole extends constructs_1.Construct {
40
+ constructor(scope, id, props) {
41
+ super(scope, id);
42
+ // Get the App instance
43
+ const app = scope instanceof app_1.default ? scope : app_1.default.getInstance();
44
+ const networkStack = app.getDefaultNetworkStack();
45
+ this.provider = props.provider;
46
+ // Build the config for the factory
47
+ const config = {
48
+ provider: props.provider,
49
+ appName: app["name"],
50
+ repositoryOrOrg: props.repositoryOrOrg,
51
+ roleName: props.roleName,
52
+ existingProviderArn: props.existingProviderArn
53
+ };
54
+ // Create the CI/CD role using the factory
55
+ this.role = cicdRole_1.default.build(`${app["name"]}CICDRole`, config)(app, networkStack.getStack());
56
+ // Register the role with the network stack
57
+ networkStack.addConstruct(this.role);
58
+ }
59
+ /**
60
+ * Get the role ARN for use in CI/CD configuration
61
+ */
62
+ getRoleArn() {
63
+ return this.role.roleArn;
64
+ }
65
+ }
66
+ exports.CICDRole = CICDRole;
67
+ exports.default = CICDRole;
68
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2ljZFJvbGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9saWIvcGF0dGVybnMvYXdzL2NpY2RSb2xlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLDJDQUF1QztBQUV2QyxtQ0FBNEI7QUFDNUIsZ0VBRzJDO0FBNEIzQzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQStCRztBQUNILE1BQWEsUUFBUyxTQUFRLHNCQUFTO0lBSXJDLFlBQVksS0FBZ0IsRUFBRSxFQUFVLEVBQUUsS0FBb0I7UUFDNUQsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQztRQUVqQix1QkFBdUI7UUFDdkIsTUFBTSxHQUFHLEdBQUcsS0FBSyxZQUFZLGFBQUcsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxhQUFHLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDN0QsTUFBTSxZQUFZLEdBQUcsR0FBRyxDQUFDLHNCQUFzQixFQUFFLENBQUM7UUFFbEQsSUFBSSxDQUFDLFFBQVEsR0FBRyxLQUFLLENBQUMsUUFBUSxDQUFDO1FBRS9CLG1DQUFtQztRQUNuQyxNQUFNLE1BQU0sR0FBbUI7WUFDN0IsUUFBUSxFQUFFLEtBQUssQ0FBQyxRQUFRO1lBQ3hCLE9BQU8sRUFBRSxHQUFHLENBQUMsTUFBTSxDQUFDO1lBQ3BCLGVBQWUsRUFBRSxLQUFLLENBQUMsZUFBZTtZQUN0QyxRQUFRLEVBQUUsS0FBSyxDQUFDLFFBQVE7WUFDeEIsbUJBQW1CLEVBQUUsS0FBSyxDQUFDLG1CQUFtQjtTQUMvQyxDQUFDO1FBRUYsMENBQTBDO1FBQzFDLElBQUksQ0FBQyxJQUFJLEdBQUcsa0JBQWUsQ0FBQyxLQUFLLENBQUMsR0FBRyxHQUFHLENBQUMsTUFBTSxDQUFDLFVBQVUsRUFBRSxNQUFNLENBQUMsQ0FDakUsR0FBRyxFQUNILFlBQVksQ0FBQyxRQUFRLEVBQUUsQ0FDeEIsQ0FBQztRQUVGLDJDQUEyQztRQUMzQyxZQUFZLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUN2QyxDQUFDO0lBRUQ7O09BRUc7SUFDSSxVQUFVO1FBQ2YsT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQztJQUMzQixDQUFDO0NBQ0Y7QUF0Q0QsNEJBc0NDO0FBRUQsa0JBQWUsUUFBUSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29uc3RydWN0IH0gZnJvbSBcImNvbnN0cnVjdHNcIjtcbmltcG9ydCB7IHR5cGUgUm9sZSB9IGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtaWFtXCI7XG5pbXBvcnQgQXBwIGZyb20gXCIuLi8uLi9hcHBcIjtcbmltcG9ydCBDSUNEUm9sZUZhY3RvcnksIHtcbiAgdHlwZSBDSUNEUHJvdmlkZXIsXG4gIHR5cGUgQ0lDRFJvbGVDb25maWdcbn0gZnJvbSBcIi4uLy4uL3Jlc291cmNlcy9hd3MvY2ljZC9jaWNkUm9sZVwiO1xuXG5leHBvcnQgaW50ZXJmYWNlIENJQ0RSb2xlUHJvcHMge1xuICAvKipcbiAgICogVGhlIENJL0NEIHByb3ZpZGVyIChnaXRodWItYWN0aW9ucywgYnVpbGRraXRlLCBnaXRsYWItY2kpXG4gICAqL1xuICBwcm92aWRlcjogQ0lDRFByb3ZpZGVyO1xuXG4gIC8qKlxuICAgKiBGb3IgR2l0SHViIEFjdGlvbnM6IHJlcG9zaXRvcnkgaW4gZm9ybWF0IFwib3JnL3JlcG9cIlxuICAgKiBGb3IgQnVpbGRraXRlOiBvcmdhbml6YXRpb24gc2x1Z1xuICAgKiBGb3IgR2l0TGFiIENJOiBwcm9qZWN0IHBhdGggaW4gZm9ybWF0IFwiZ3JvdXAvcHJvamVjdFwiXG4gICAqL1xuICByZXBvc2l0b3J5T3JPcmc6IHN0cmluZztcblxuICAvKipcbiAgICogT3B0aW9uYWwgY3VzdG9tIHJvbGUgbmFtZVxuICAgKiBEZWZhdWx0cyB0byBcIkZqYWxsRGVwbG95LXtwcm92aWRlcn0te2FwcE5hbWV9XCJcbiAgICovXG4gIHJvbGVOYW1lPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBPcHRpb25hbCBBUk4gb2YgZXhpc3RpbmcgT0lEQyBwcm92aWRlciAoc2tpcHMgY3JlYXRpb24pXG4gICAqIFVzZWZ1bCB3aGVuIE9JREMgcHJvdmlkZXIgYWxyZWFkeSBleGlzdHMgaW4gdGhlIGFjY291bnRcbiAgICovXG4gIGV4aXN0aW5nUHJvdmlkZXJBcm4/OiBzdHJpbmc7XG59XG5cbi8qKlxuICogSGlnaC1sZXZlbCBwYXR0ZXJuIGZvciBhZGRpbmcgQ0kvQ0QgT0lEQyBhdXRoZW50aWNhdGlvbiB0byBhbiBhcHBsaWNhdGlvbi5cbiAqXG4gKiBUaGlzIGNyZWF0ZXMgYW4gT0lEQyBwcm92aWRlciAoaWYgbmVlZGVkKSBhbmQgYSBkZXBsb3kgcm9sZSB0aGF0IGNhbiBiZSBhc3N1bWVkXG4gKiBieSB5b3VyIENJL0NEIHN5c3RlbSB3aXRob3V0IGxvbmctbGl2ZWQgY3JlZGVudGlhbHMuXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGltcG9ydCB7IEFwcCwgQ0lDRFJvbGUgfSBmcm9tIFwiQGZqYWxsL2NvbXBvbmVudHMtaW5mcmFzdHJ1Y3R1cmVcIjtcbiAqXG4gKiBjb25zdCBhcHAgPSBBcHAuZ2V0QXBwKFwiTXlBcHBcIik7XG4gKlxuICogLy8gQWRkIEdpdEh1YiBBY3Rpb25zIE9JREMgYXV0aGVudGljYXRpb25cbiAqIGNvbnN0IGNpY2RSb2xlID0gbmV3IENJQ0RSb2xlKGFwcCwgXCJHaXRIdWJEZXBsb3lSb2xlXCIsIHtcbiAqICAgcHJvdmlkZXI6IFwiZ2l0aHViLWFjdGlvbnNcIixcbiAqICAgcmVwb3NpdG9yeU9yT3JnOiBcIm15b3JnL215cmVwb1wiXG4gKiB9KTtcbiAqXG4gKiAvLyBDb250aW51ZSB3aXRoIG5vcm1hbCBhcHBsaWNhdGlvbiBzZXR1cFxuICogYXBwLmFkZENvbXB1dGUoLyogLi4uICpcXC8pO1xuICogYGBgXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIC8vIFVzZSBleGlzdGluZyBPSURDIHByb3ZpZGVyIChjcmVhdGVkIHZpYSBmamFsbCBjaWNkIHNldHVwKVxuICogY29uc3QgY2ljZFJvbGUgPSBuZXcgQ0lDRFJvbGUoYXBwLCBcIkdpdEh1YkRlcGxveVJvbGVcIiwge1xuICogICBwcm92aWRlcjogXCJnaXRodWItYWN0aW9uc1wiLFxuICogICByZXBvc2l0b3J5T3JPcmc6IFwibXlvcmcvbXlyZXBvXCIsXG4gKiAgIGV4aXN0aW5nUHJvdmlkZXJBcm46IFwiYXJuOmF3czppYW06OjEyMzQ1Njc4OTAxMjpvaWRjLXByb3ZpZGVyL3Rva2VuLmFjdGlvbnMuZ2l0aHVidXNlcmNvbnRlbnQuY29tXCJcbiAqIH0pO1xuICogYGBgXG4gKi9cbmV4cG9ydCBjbGFzcyBDSUNEUm9sZSBleHRlbmRzIENvbnN0cnVjdCB7XG4gIHB1YmxpYyByZWFkb25seSByb2xlOiBSb2xlO1xuICBwdWJsaWMgcmVhZG9ubHkgcHJvdmlkZXI6IENJQ0RQcm92aWRlcjtcblxuICBjb25zdHJ1Y3RvcihzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBwcm9wczogQ0lDRFJvbGVQcm9wcykge1xuICAgIHN1cGVyKHNjb3BlLCBpZCk7XG5cbiAgICAvLyBHZXQgdGhlIEFwcCBpbnN0YW5jZVxuICAgIGNvbnN0IGFwcCA9IHNjb3BlIGluc3RhbmNlb2YgQXBwID8gc2NvcGUgOiBBcHAuZ2V0SW5zdGFuY2UoKTtcbiAgICBjb25zdCBuZXR3b3JrU3RhY2sgPSBhcHAuZ2V0RGVmYXVsdE5ldHdvcmtTdGFjaygpO1xuXG4gICAgdGhpcy5wcm92aWRlciA9IHByb3BzLnByb3ZpZGVyO1xuXG4gICAgLy8gQnVpbGQgdGhlIGNvbmZpZyBmb3IgdGhlIGZhY3RvcnlcbiAgICBjb25zdCBjb25maWc6IENJQ0RSb2xlQ29uZmlnID0ge1xuICAgICAgcHJvdmlkZXI6IHByb3BzLnByb3ZpZGVyLFxuICAgICAgYXBwTmFtZTogYXBwW1wibmFtZVwiXSxcbiAgICAgIHJlcG9zaXRvcnlPck9yZzogcHJvcHMucmVwb3NpdG9yeU9yT3JnLFxuICAgICAgcm9sZU5hbWU6IHByb3BzLnJvbGVOYW1lLFxuICAgICAgZXhpc3RpbmdQcm92aWRlckFybjogcHJvcHMuZXhpc3RpbmdQcm92aWRlckFyblxuICAgIH07XG5cbiAgICAvLyBDcmVhdGUgdGhlIENJL0NEIHJvbGUgdXNpbmcgdGhlIGZhY3RvcnlcbiAgICB0aGlzLnJvbGUgPSBDSUNEUm9sZUZhY3RvcnkuYnVpbGQoYCR7YXBwW1wibmFtZVwiXX1DSUNEUm9sZWAsIGNvbmZpZykoXG4gICAgICBhcHAsXG4gICAgICBuZXR3b3JrU3RhY2suZ2V0U3RhY2soKVxuICAgICk7XG5cbiAgICAvLyBSZWdpc3RlciB0aGUgcm9sZSB3aXRoIHRoZSBuZXR3b3JrIHN0YWNrXG4gICAgbmV0d29ya1N0YWNrLmFkZENvbnN0cnVjdCh0aGlzLnJvbGUpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCB0aGUgcm9sZSBBUk4gZm9yIHVzZSBpbiBDSS9DRCBjb25maWd1cmF0aW9uXG4gICAqL1xuICBwdWJsaWMgZ2V0Um9sZUFybigpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLnJvbGUucm9sZUFybjtcbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBDSUNEUm9sZTtcbiJdfQ==
@@ -221,6 +221,10 @@ export class ComputeFactory {
221
221
  ...computeProps,
222
222
  appName: app.getName()
223
223
  };
224
+ // `ecrRepository` is already defaulted to the app's shared default
225
+ // container registry above (line ~323) when omitted — the same
226
+ // repo ECS services push into — so a container Lambda always has
227
+ // one by this point, whether or not `docker` is set.
224
228
  // Always register Lambda with manifest collector for CLI discovery
225
229
  // This ensures all Lambdas are discoverable for secrets management,
226
230
  // even those that don't currently have secrets configured
@@ -242,6 +246,11 @@ export class ComputeFactory {
242
246
  if (lambdaImportedSecretNames.size > 0) {
243
247
  manifestLambda.importedSecretNames = Array.from(lambdaImportedSecretNames);
244
248
  }
249
+ if (lambdaComputeProps.deployment === "container" &&
250
+ lambdaComputeProps.docker !== undefined) {
251
+ manifestLambda.docker = lambdaComputeProps.docker;
252
+ manifestLambda.imageKey = lambdaComputeProps.image ?? id;
253
+ }
245
254
  collector.addLambda(manifestLambda);
246
255
  return new LambdaCompute(scope, id, lambdaComputeProps);
247
256
  }
@@ -8,6 +8,7 @@ import { type ILambdaCompute } from "./interfaces/compute.js";
8
8
  import { type ConnectionSpec } from "./interfaces/connector.js";
9
9
  import { LambdaFunction } from "../../resources/aws/compute/lambda.js";
10
10
  import { type SecretImport } from "../../resources/aws/secrets/index.js";
11
+ import { type DockerBuild } from "@fjall/util/manifest/schemas";
11
12
  export { Architecture, HttpMethod, InvokeMode, type FunctionUrlCorsOptions } from "aws-cdk-lib/aws-lambda";
12
13
  /**
13
14
  * Lambda function URL configuration.
@@ -114,17 +115,47 @@ interface BaseLambdaProps {
114
115
  * automatically set to FROM_IMAGE.
115
116
  *
116
117
  * @example
118
+ * // Bring your own image (built/pushed out of band)
117
119
  * app.addCompute(ComputeFactory.build("ImageLambda", {
118
120
  * type: "lambda",
119
121
  * deployment: "container",
120
122
  * ecrRepository: app.getDefaultContainerRegistry()
121
123
  * }));
124
+ *
125
+ * @example
126
+ * // fjall builds and pushes the image on every `fjall deploy`
127
+ * app.addCompute(ComputeFactory.build("ImageLambda", {
128
+ * type: "lambda",
129
+ * deployment: "container",
130
+ * docker: { path: "lambda.Dockerfile" }
131
+ * }));
122
132
  */
123
133
  export interface ContainerLambdaProps extends BaseLambdaProps {
124
134
  /** Container-based deployment using ECR image */
125
135
  deployment: "container";
126
- /** ECR repository containing the Lambda container image */
127
- ecrRepository: Repository | RepositoryImage;
136
+ /**
137
+ * ECR repository containing the Lambda container image. Optional when
138
+ * `docker` is set — defaults to the app's shared default container
139
+ * registry (the same repo ECS services push into).
140
+ */
141
+ ecrRepository?: Repository | RepositoryImage;
142
+ /**
143
+ * When set, `fjall deploy` builds and pushes this Dockerfile into the app's
144
+ * shared default container registry, then wires the function to the
145
+ * resulting content-hash-tagged image — the same mechanism ECS services
146
+ * already use. Omit to keep managing the image out of band (the previous
147
+ * behaviour: the function tracks a moving `:latest` tag in `ecrRepository`).
148
+ */
149
+ docker?: DockerBuild;
150
+ /**
151
+ * Shared build/tag key for Lambda functions that intentionally run the
152
+ * same container image (e.g. several handlers packaged from one
153
+ * Dockerfile). Functions sharing one `image` value build once and share
154
+ * one content-hash tag. Defaults to this Lambda's own construct id, so
155
+ * omitting it is safe when no sharing is intended. Only meaningful when
156
+ * `docker` is set.
157
+ */
158
+ image?: string;
128
159
  }
129
160
  /**
130
161
  * Code-based Lambda using inline code or S3.
@@ -177,8 +208,12 @@ export interface ResolvedLambdaDeployment {
177
208
  /**
178
209
  * Resolve Lambda deployment configuration from props.
179
210
  * Handles container vs code deployment types.
211
+ *
212
+ * `scope`/`id` are only used on the container-with-`docker` path, to create
213
+ * (or reuse) the per-key `CfnParameter` that `fjall deploy` overrides with
214
+ * the content-hash tag after building and pushing the image.
180
215
  */
181
- export declare function resolveLambdaDeployment(props: LambdaComputeProps): ResolvedLambdaDeployment;
216
+ export declare function resolveLambdaDeployment(scope: Construct, id: string, props: LambdaComputeProps): ResolvedLambdaDeployment;
182
217
  /**
183
218
  * Lambda compute wrapper implementing ILambdaCompute.
184
219
  * Provides type-safe access to Lambda-specific resources.
@@ -4,18 +4,45 @@ import { Repository } from "aws-cdk-lib/aws-ecr";
4
4
  import { Construct } from "constructs";
5
5
  import { processConnections } from "../../utils/connections.js";
6
6
  import { LambdaFunction } from "../../resources/aws/compute/lambda.js";
7
+ import { getOrCreateImageTagParameter } from "../../resources/aws/compute/imageTagParameter.js";
7
8
  import { COMPUTE_DEFAULTS } from "./compute.js";
9
+ import { evaluateBakeGuard } from "@fjall/util/docker";
10
+ import { toKebab } from "@fjall/util";
8
11
  // Re-export Lambda types from CDK for user convenience
9
12
  export { Architecture, HttpMethod, InvokeMode } from "aws-cdk-lib/aws-lambda";
10
13
  /**
11
14
  * Resolve Lambda deployment configuration from props.
12
15
  * Handles container vs code deployment types.
16
+ *
17
+ * `scope`/`id` are only used on the container-with-`docker` path, to create
18
+ * (or reuse) the per-key `CfnParameter` that `fjall deploy` overrides with
19
+ * the content-hash tag after building and pushing the image.
13
20
  */
14
- export function resolveLambdaDeployment(props) {
21
+ export function resolveLambdaDeployment(scope, id, props) {
15
22
  if (props.deployment === "container") {
23
+ if (!props.ecrRepository) {
24
+ throw new Error(`Lambda '${id}': ecrRepository is required unless \`docker\` is set ` +
25
+ "(ComputeFactory fills it in automatically from the app's default container registry when docker is present).");
26
+ }
16
27
  if (!(props.ecrRepository instanceof Repository)) {
17
28
  throw new Error("ecrRepository must be a Repository instance for Lambda compute type");
18
29
  }
30
+ if (props.docker !== undefined) {
31
+ const appPrefix = props.appName !== undefined ? toKebab(props.appName) : "";
32
+ const findings = evaluateBakeGuard(props.docker.buildArgs, appPrefix).findings;
33
+ if (findings.length > 0) {
34
+ throw new Error(`Lambda '${id}': ${findings.map((f) => f.message).join(" ")}`);
35
+ }
36
+ const tagKey = props.image ?? id;
37
+ const param = getOrCreateImageTagParameter(scope, tagKey);
38
+ return {
39
+ code: Code.fromEcrImage(props.ecrRepository, {
40
+ tagOrDigest: param.valueAsString
41
+ }),
42
+ handler: Handler.FROM_IMAGE,
43
+ runtime: Runtime.FROM_IMAGE
44
+ };
45
+ }
19
46
  return {
20
47
  code: Code.fromEcrImage(props.ecrRepository, {
21
48
  tagOrDigest: COMPUTE_DEFAULTS.ECS.IMAGE_TAG
@@ -40,7 +67,7 @@ export class LambdaCompute extends Construct {
40
67
  lambdaFunction;
41
68
  constructor(scope, id, props) {
42
69
  super(scope, id);
43
- const { code, handler, runtime } = resolveLambdaDeployment(props);
70
+ const { code, handler, runtime } = resolveLambdaDeployment(scope, id, props);
44
71
  // Convert presence-based functionUrl config to legacy boolean format
45
72
  const functionUrlConfig = props.functionUrl;
46
73
  const enableFunctionUrl = functionUrlConfig !== undefined && functionUrlConfig !== false;