@fjall/components-infrastructure 0.89.5 → 0.89.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +50 -21
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -18
- package/dist/lib/app.d.ts +12 -12
- package/dist/lib/app.js +61 -56
- package/dist/lib/aspects/index.d.ts +1 -1
- package/dist/lib/aspects/index.js +1 -6
- package/dist/lib/aspects/resourceInventory.js +6 -13
- package/dist/lib/config/audit.js +1 -5
- package/dist/lib/config/aws/accessAnalyser.d.ts +11 -0
- package/dist/lib/config/aws/accessAnalyser.js +17 -0
- package/dist/lib/config/aws/accountAuditRole.js +11 -15
- package/dist/lib/config/aws/accountMonitoringRole.js +25 -29
- package/dist/lib/config/aws/alarmTopic.d.ts +8 -0
- package/dist/lib/config/aws/alarmTopic.js +19 -0
- package/dist/lib/config/aws/cloudTrail.js +4 -9
- package/dist/lib/config/aws/configRecorder.d.ts +16 -0
- package/dist/lib/config/aws/configRecorder.js +51 -0
- package/dist/lib/config/aws/configRulePreset.d.ts +13 -0
- package/dist/lib/config/aws/configRulePreset.js +62 -0
- package/dist/lib/config/aws/disasterRecovery.d.ts +1 -1
- package/dist/lib/config/aws/disasterRecovery.js +56 -73
- package/dist/lib/config/aws/ebsDefaultEncryption.d.ts +8 -0
- package/dist/lib/config/aws/ebsDefaultEncryption.js +41 -0
- package/dist/lib/config/aws/ecrDefaultImage.js +25 -30
- package/dist/lib/config/aws/eventBus.js +8 -11
- package/dist/lib/config/aws/guardDutyDetector.d.ts +16 -0
- package/dist/lib/config/aws/guardDutyDetector.js +26 -0
- package/dist/lib/config/aws/identityCenter.d.ts +1 -1
- package/dist/lib/config/aws/identityCenter.js +23 -25
- package/dist/lib/config/aws/identityCenterGroupMembership.js +18 -22
- package/dist/lib/config/aws/index.d.ts +19 -8
- package/dist/lib/config/aws/index.js +19 -25
- package/dist/lib/config/aws/inspectorEnablement.d.ts +9 -0
- package/dist/lib/config/aws/inspectorEnablement.js +51 -0
- package/dist/lib/config/aws/ipam.js +9 -13
- package/dist/lib/config/aws/oidcConnector.js +8 -12
- package/dist/lib/config/aws/platform.js +1 -5
- package/dist/lib/config/aws/s3BlockPublicAccess.d.ts +9 -0
- package/dist/lib/config/aws/s3BlockPublicAccess.js +55 -0
- package/dist/lib/config/aws/scpPreset.d.ts +21 -0
- package/dist/lib/config/aws/scpPreset.js +311 -0
- package/dist/lib/config/aws/securityBaseline.d.ts +15 -0
- package/dist/lib/config/aws/securityBaseline.js +27 -0
- package/dist/lib/config/aws/securityHubHub.d.ts +15 -0
- package/dist/lib/config/aws/securityHubHub.js +28 -0
- package/dist/lib/config/aws/securityServicesAdmin.d.ts +20 -0
- package/dist/lib/config/aws/securityServicesAdmin.js +115 -0
- package/dist/lib/config/index.d.ts +2 -2
- package/dist/lib/config/index.js +2 -21
- package/dist/lib/index.d.ts +4 -4
- package/dist/lib/index.js +5 -26
- package/dist/lib/patterns/aws/account.d.ts +17 -1
- package/dist/lib/patterns/aws/account.js +60 -33
- package/dist/lib/patterns/aws/apexDomainPattern.d.ts +26 -0
- package/dist/lib/patterns/aws/apexDomainPattern.js +91 -0
- package/dist/lib/patterns/aws/auditRole.js +13 -16
- package/dist/lib/patterns/aws/buildkite.d.ts +1 -1
- package/dist/lib/patterns/aws/buildkite.js +70 -75
- package/dist/lib/patterns/aws/cdn.d.ts +5 -5
- package/dist/lib/patterns/aws/cdn.js +22 -28
- package/dist/lib/patterns/aws/compute.d.ts +1 -1
- package/dist/lib/patterns/aws/compute.js +31 -44
- package/dist/lib/patterns/aws/computeEc2.d.ts +1 -1
- package/dist/lib/patterns/aws/computeEc2.js +11 -14
- package/dist/lib/patterns/aws/computeEcs.d.ts +18 -2
- package/dist/lib/patterns/aws/computeEcs.js +41 -31
- package/dist/lib/patterns/aws/computeLambda.d.ts +2 -2
- package/dist/lib/patterns/aws/computeLambda.js +24 -31
- package/dist/lib/patterns/aws/database.d.ts +16 -7
- package/dist/lib/patterns/aws/database.js +81 -73
- package/dist/lib/patterns/aws/delegatedDomainPattern.d.ts +17 -0
- package/dist/lib/patterns/aws/delegatedDomainPattern.js +54 -0
- package/dist/lib/patterns/aws/dnsRecordComposer.d.ts +25 -0
- package/dist/lib/patterns/aws/dnsRecordComposer.js +225 -0
- package/dist/lib/patterns/aws/domain.d.ts +32 -0
- package/dist/lib/patterns/aws/domain.js +115 -0
- package/dist/lib/patterns/aws/domainDelegation.d.ts +3 -3
- package/dist/lib/patterns/aws/domainDelegation.js +28 -37
- package/dist/lib/patterns/aws/domainFactory.d.ts +20 -5
- package/dist/lib/patterns/aws/domainFactory.js +48 -10
- package/dist/lib/patterns/aws/domainValidation.d.ts +11 -0
- package/dist/lib/patterns/aws/domainValidation.js +145 -0
- package/dist/lib/patterns/aws/externalRecordsPattern.d.ts +18 -0
- package/dist/lib/patterns/aws/externalRecordsPattern.js +141 -0
- package/dist/lib/patterns/aws/fivetranProxy.d.ts +1 -1
- package/dist/lib/patterns/aws/fivetranProxy.js +6 -11
- package/dist/lib/patterns/aws/index.d.ts +21 -19
- package/dist/lib/patterns/aws/index.js +25 -36
- package/dist/lib/patterns/aws/interfaces/cdn.js +1 -5
- package/dist/lib/patterns/aws/interfaces/compute.js +4 -11
- package/dist/lib/patterns/aws/interfaces/connector.js +1 -15
- package/dist/lib/patterns/aws/interfaces/database.d.ts +1 -1
- package/dist/lib/patterns/aws/interfaces/database.js +6 -15
- package/dist/lib/patterns/aws/interfaces/domain.d.ts +80 -2
- package/dist/lib/patterns/aws/interfaces/domain.js +1 -6
- package/dist/lib/patterns/aws/interfaces/index.js +8 -41
- package/dist/lib/patterns/aws/interfaces/messaging.js +4 -11
- package/dist/lib/patterns/aws/interfaces/organisation.d.ts +1 -1
- package/dist/lib/patterns/aws/interfaces/organisation.js +4 -11
- package/dist/lib/patterns/aws/interfaces/pattern.js +2 -7
- package/dist/lib/patterns/aws/interfaces/storage.js +1 -5
- package/dist/lib/patterns/aws/managedIdentityCenter.js +7 -12
- package/dist/lib/patterns/aws/messaging.d.ts +7 -7
- package/dist/lib/patterns/aws/messaging.js +22 -33
- package/dist/lib/patterns/aws/network.d.ts +2 -2
- package/dist/lib/patterns/aws/network.js +9 -14
- package/dist/lib/patterns/aws/organisation.d.ts +6 -2
- package/dist/lib/patterns/aws/organisation.js +34 -35
- package/dist/lib/patterns/aws/organisationFactory.d.ts +3 -3
- package/dist/lib/patterns/aws/organisationFactory.js +7 -12
- package/dist/lib/patterns/aws/pattern.js +6 -12
- package/dist/lib/patterns/aws/payload.js +73 -63
- package/dist/lib/patterns/aws/platform.d.ts +6 -3
- package/dist/lib/patterns/aws/platform.js +15 -15
- package/dist/lib/patterns/aws/storage.d.ts +6 -4
- package/dist/lib/patterns/aws/storage.js +35 -40
- package/dist/lib/patterns/aws/subdomainHostedZone.js +11 -16
- package/dist/lib/patterns/aws/targets/fjallTargets.d.ts +37 -0
- package/dist/lib/patterns/aws/targets/fjallTargets.js +66 -0
- package/dist/lib/patterns/aws/targets/index.d.ts +2 -0
- package/dist/lib/patterns/aws/targets/index.js +2 -0
- package/dist/lib/patterns/aws/targets/targetResolution.d.ts +76 -0
- package/dist/lib/patterns/aws/targets/targetResolution.js +119 -0
- package/dist/lib/patterns/index.d.ts +1 -0
- package/dist/lib/patterns/index.js +1 -0
- package/dist/lib/resources/aws/analytics/clickhouse.d.ts +15 -0
- package/dist/lib/resources/aws/analytics/clickhouse.js +292 -0
- package/dist/lib/resources/aws/analytics/clickhouseConstants.d.ts +73 -0
- package/dist/lib/resources/aws/analytics/clickhouseConstants.js +87 -0
- package/dist/lib/resources/aws/analytics/clickhouseSecurityGroup.d.ts +13 -0
- package/dist/lib/resources/aws/analytics/clickhouseSecurityGroup.js +28 -0
- package/dist/lib/resources/aws/analytics/clickhouseTypes.d.ts +47 -0
- package/dist/lib/resources/aws/analytics/clickhouseTypes.js +1 -0
- package/dist/lib/resources/aws/analytics/clickhouseUserData.d.ts +5 -0
- package/dist/lib/resources/aws/analytics/clickhouseUserData.js +248 -0
- package/dist/lib/resources/aws/analytics/index.d.ts +2 -0
- package/dist/lib/resources/aws/analytics/index.js +1 -0
- package/dist/lib/resources/aws/audit/auditRole.js +10 -15
- package/dist/lib/resources/aws/audit/index.d.ts +1 -1
- package/dist/lib/resources/aws/audit/index.js +1 -6
- package/dist/lib/resources/aws/backup/backupPlan.d.ts +1 -1
- package/dist/lib/resources/aws/backup/backupPlan.js +14 -16
- package/dist/lib/resources/aws/backup/backupVault.d.ts +1 -1
- package/dist/lib/resources/aws/backup/backupVault.js +13 -15
- package/dist/lib/resources/aws/backup/index.d.ts +2 -2
- package/dist/lib/resources/aws/backup/index.js +2 -19
- package/dist/lib/resources/aws/base/awsStack.js +17 -19
- package/dist/lib/resources/aws/base/index.d.ts +1 -1
- package/dist/lib/resources/aws/base/index.js +1 -18
- package/dist/lib/resources/aws/cdn/cloudFront.js +40 -42
- package/dist/lib/resources/aws/cdn/index.d.ts +1 -1
- package/dist/lib/resources/aws/cdn/index.js +1 -18
- package/dist/lib/resources/aws/compute/ec2.js +39 -39
- package/dist/lib/resources/aws/compute/ecs.d.ts +18 -396
- package/dist/lib/resources/aws/compute/ecs.js +105 -976
- package/dist/lib/resources/aws/compute/ecsCapacityProviderAspect.d.ts +22 -0
- package/dist/lib/resources/aws/compute/ecsCapacityProviderAspect.js +35 -0
- package/dist/lib/resources/aws/compute/ecsConstants.d.ts +20 -0
- package/dist/lib/resources/aws/compute/ecsConstants.js +49 -0
- package/dist/lib/resources/aws/compute/ecsContext.d.ts +12 -0
- package/dist/lib/resources/aws/compute/ecsContext.js +1 -0
- package/dist/lib/resources/aws/compute/ecsImages.d.ts +4 -0
- package/dist/lib/resources/aws/compute/ecsImages.js +35 -0
- package/dist/lib/resources/aws/compute/ecsNetworking.d.ts +28 -0
- package/dist/lib/resources/aws/compute/ecsNetworking.js +290 -0
- package/dist/lib/resources/aws/compute/ecsRoles.d.ts +15 -0
- package/dist/lib/resources/aws/compute/ecsRoles.js +110 -0
- package/dist/lib/resources/aws/compute/ecsServiceFactory.d.ts +33 -0
- package/dist/lib/resources/aws/compute/ecsServiceFactory.js +183 -0
- package/dist/lib/resources/aws/compute/ecsTaskDefinition.d.ts +30 -0
- package/dist/lib/resources/aws/compute/ecsTaskDefinition.js +168 -0
- package/dist/lib/resources/aws/compute/ecsTypes.d.ts +337 -0
- package/dist/lib/resources/aws/compute/ecsTypes.js +10 -0
- package/dist/lib/resources/aws/compute/ecsValidation.d.ts +18 -0
- package/dist/lib/resources/aws/compute/ecsValidation.js +72 -0
- package/dist/lib/resources/aws/compute/index.d.ts +3 -3
- package/dist/lib/resources/aws/compute/index.js +3 -20
- package/dist/lib/resources/aws/compute/lambda.d.ts +10 -2
- package/dist/lib/resources/aws/compute/lambda.js +81 -71
- package/dist/lib/resources/aws/database/dynamodb.js +24 -27
- package/dist/lib/resources/aws/database/index.d.ts +7 -7
- package/dist/lib/resources/aws/database/index.js +14 -33
- package/dist/lib/resources/aws/database/rdsAurora.d.ts +10 -2
- package/dist/lib/resources/aws/database/rdsAurora.js +76 -61
- package/dist/lib/resources/aws/database/rdsAuroraGlobal.d.ts +2 -2
- package/dist/lib/resources/aws/database/rdsAuroraGlobal.js +24 -21
- package/dist/lib/resources/aws/database/rdsDefaults.js +3 -7
- package/dist/lib/resources/aws/database/rdsHelpers.d.ts +2 -2
- package/dist/lib/resources/aws/database/rdsHelpers.js +21 -29
- package/dist/lib/resources/aws/database/rdsInstance.d.ts +11 -3
- package/dist/lib/resources/aws/database/rdsInstance.js +101 -83
- package/dist/lib/resources/aws/database/rdsProxyOutput.js +5 -9
- package/dist/lib/resources/aws/iam/delegationRole.d.ts +18 -0
- package/dist/lib/resources/aws/iam/delegationRole.js +60 -0
- package/dist/lib/resources/aws/iam/identityCenter/assignment.js +4 -9
- package/dist/lib/resources/aws/iam/identityCenter/group.js +5 -9
- package/dist/lib/resources/aws/iam/identityCenter/index.d.ts +3 -3
- package/dist/lib/resources/aws/iam/identityCenter/index.js +3 -20
- package/dist/lib/resources/aws/iam/identityCenter/permissionSet.d.ts +1 -1
- package/dist/lib/resources/aws/iam/identityCenter/permissionSet.js +5 -9
- package/dist/lib/resources/aws/iam/index.d.ts +5 -4
- package/dist/lib/resources/aws/iam/index.js +5 -21
- package/dist/lib/resources/aws/iam/instanceProfile.js +2 -7
- package/dist/lib/resources/aws/iam/managedPolicy.js +2 -7
- package/dist/lib/resources/aws/iam/policy.js +2 -7
- package/dist/lib/resources/aws/iam/role.js +2 -7
- package/dist/lib/resources/aws/index.d.ts +7 -7
- package/dist/lib/resources/aws/index.js +7 -24
- package/dist/lib/resources/aws/logging/cloudTrail.d.ts +1 -1
- package/dist/lib/resources/aws/logging/cloudTrail.js +18 -22
- package/dist/lib/resources/aws/logging/index.d.ts +2 -2
- package/dist/lib/resources/aws/logging/index.js +2 -19
- package/dist/lib/resources/aws/logging/logGroup.js +4 -10
- package/dist/lib/resources/aws/messaging/eventbridge.js +11 -14
- package/dist/lib/resources/aws/messaging/index.d.ts +4 -4
- package/dist/lib/resources/aws/messaging/index.js +4 -21
- package/dist/lib/resources/aws/messaging/sns.js +11 -14
- package/dist/lib/resources/aws/messaging/sqs.js +32 -34
- package/dist/lib/resources/aws/messaging/utils.d.ts +1 -1
- package/dist/lib/resources/aws/messaging/utils.js +1 -6
- package/dist/lib/resources/aws/monitoring/alarmDefaults.d.ts +36 -0
- package/dist/lib/resources/aws/monitoring/alarmDefaults.js +34 -0
- package/dist/lib/resources/aws/monitoring/ecsAlarms.d.ts +21 -0
- package/dist/lib/resources/aws/monitoring/ecsAlarms.js +88 -0
- package/dist/lib/resources/aws/monitoring/index.d.ts +4 -0
- package/dist/lib/resources/aws/monitoring/index.js +4 -5
- package/dist/lib/resources/aws/monitoring/lambdaAlarms.d.ts +18 -0
- package/dist/lib/resources/aws/monitoring/lambdaAlarms.js +44 -0
- package/dist/lib/resources/aws/monitoring/rdsAlarms.d.ts +20 -0
- package/dist/lib/resources/aws/monitoring/rdsAlarms.js +52 -0
- package/dist/lib/resources/aws/networking/crossAccountDelegationRecord.d.ts +17 -0
- package/dist/lib/resources/aws/networking/crossAccountDelegationRecord.js +26 -0
- package/dist/lib/resources/aws/networking/dnsRecord/aRecord.d.ts +12 -0
- package/dist/lib/resources/aws/networking/dnsRecord/aRecord.js +21 -0
- package/dist/lib/resources/aws/networking/dnsRecord/aaaaRecord.d.ts +12 -0
- package/dist/lib/resources/aws/networking/dnsRecord/aaaaRecord.js +22 -0
- package/dist/lib/resources/aws/networking/dnsRecord/aliasRecord.d.ts +12 -0
- package/dist/lib/resources/aws/networking/dnsRecord/aliasRecord.js +23 -0
- package/dist/lib/resources/aws/networking/dnsRecord/caaRecord.d.ts +17 -0
- package/dist/lib/resources/aws/networking/dnsRecord/caaRecord.js +21 -0
- package/dist/lib/resources/aws/networking/dnsRecord/cnameRecord.d.ts +12 -0
- package/dist/lib/resources/aws/networking/dnsRecord/cnameRecord.js +22 -0
- package/dist/lib/resources/aws/networking/dnsRecord/dnsRecordBase.d.ts +17 -0
- package/dist/lib/resources/aws/networking/dnsRecord/dnsRecordBase.js +17 -0
- package/dist/lib/resources/aws/networking/dnsRecord/index.d.ts +10 -0
- package/dist/lib/resources/aws/networking/dnsRecord/index.js +10 -0
- package/dist/lib/resources/aws/networking/dnsRecord/mxRecord.d.ts +16 -0
- package/dist/lib/resources/aws/networking/dnsRecord/mxRecord.js +21 -0
- package/dist/lib/resources/aws/networking/dnsRecord/nsRecord.d.ts +12 -0
- package/dist/lib/resources/aws/networking/dnsRecord/nsRecord.js +21 -0
- package/dist/lib/resources/aws/networking/dnsRecord/srvRecord.d.ts +18 -0
- package/dist/lib/resources/aws/networking/dnsRecord/srvRecord.js +21 -0
- package/dist/lib/resources/aws/networking/dnsRecord/txtRecord.d.ts +12 -0
- package/dist/lib/resources/aws/networking/dnsRecord/txtRecord.js +21 -0
- package/dist/lib/resources/aws/networking/domain.d.ts +1 -1
- package/dist/lib/resources/aws/networking/domain.js +32 -34
- package/dist/lib/resources/aws/networking/domainCertificate.d.ts +8 -3
- package/dist/lib/resources/aws/networking/domainCertificate.js +22 -16
- package/dist/lib/resources/aws/networking/hostedZone.d.ts +23 -19
- package/dist/lib/resources/aws/networking/hostedZone.js +70 -134
- package/dist/lib/resources/aws/networking/index.d.ts +8 -7
- package/dist/lib/resources/aws/networking/index.js +8 -24
- package/dist/lib/resources/aws/networking/ipam.js +2 -7
- package/dist/lib/resources/aws/networking/ipamPool.d.ts +1 -1
- package/dist/lib/resources/aws/networking/ipamPool.js +45 -55
- package/dist/lib/resources/aws/networking/securityGroup.js +2 -7
- package/dist/lib/resources/aws/networking/vpc.d.ts +1 -1
- package/dist/lib/resources/aws/networking/vpc.js +17 -21
- package/dist/lib/resources/aws/organisation/costAllocationTagActivator.d.ts +1 -1
- package/dist/lib/resources/aws/organisation/costAllocationTagActivator.js +11 -15
- package/dist/lib/resources/aws/organisation/index.d.ts +5 -5
- package/dist/lib/resources/aws/organisation/index.js +4 -12
- package/dist/lib/resources/aws/organisation/organisation.js +5 -7
- package/dist/lib/resources/aws/organisation/organisationAccount.js +7 -10
- package/dist/lib/resources/aws/organisation/organisationPolicy.js +5 -9
- package/dist/lib/resources/aws/organisation/organisationalUnit.js +1 -3
- package/dist/lib/resources/aws/secrets/alias.js +2 -7
- package/dist/lib/resources/aws/secrets/index.d.ts +4 -4
- package/dist/lib/resources/aws/secrets/index.js +4 -21
- package/dist/lib/resources/aws/secrets/kms.js +15 -18
- package/dist/lib/resources/aws/secrets/parameter.d.ts +3 -3
- package/dist/lib/resources/aws/secrets/parameter.js +19 -22
- package/dist/lib/resources/aws/secrets/secret.d.ts +2 -2
- package/dist/lib/resources/aws/secrets/secret.js +12 -14
- package/dist/lib/resources/aws/storage/ecr.d.ts +2 -2
- package/dist/lib/resources/aws/storage/ecr.js +7 -13
- package/dist/lib/resources/aws/storage/index.d.ts +2 -2
- package/dist/lib/resources/aws/storage/index.js +2 -19
- package/dist/lib/resources/aws/storage/s3.d.ts +1 -1
- package/dist/lib/resources/aws/storage/s3.js +24 -12
- package/dist/lib/resources/aws/utilities/awsCustomResource.js +3 -7
- package/dist/lib/resources/aws/utilities/codeBuild.js +7 -12
- package/dist/lib/resources/aws/utilities/customResource.js +14 -17
- package/dist/lib/resources/aws/utilities/customResourceProvider.js +2 -7
- package/dist/lib/resources/aws/utilities/index.d.ts +5 -5
- package/dist/lib/resources/aws/utilities/index.js +5 -22
- package/dist/lib/resources/aws/utilities/resourceShare.js +2 -7
- package/dist/lib/resources/index.d.ts +1 -1
- package/dist/lib/resources/index.js +1 -18
- package/dist/lib/types.js +1 -3
- package/dist/lib/utils/accountsUtils.d.ts +5 -0
- package/dist/lib/utils/accountsUtils.js +18 -0
- package/dist/lib/utils/addSuffixToEmail.js +1 -5
- package/dist/lib/utils/backupTierMapping.js +2 -6
- package/dist/lib/utils/capitaliseString.js +1 -10
- package/dist/lib/utils/connections.js +9 -13
- package/dist/lib/utils/connector.js +10 -23
- package/dist/lib/utils/constructMap.d.ts +33 -0
- package/dist/lib/utils/constructMap.js +154 -0
- package/dist/lib/utils/databaseTypes.js +4 -10
- package/dist/lib/utils/dnsRecords.d.ts +1 -1
- package/dist/lib/utils/dnsRecords.js +23 -27
- package/dist/lib/utils/domainTypes.d.ts +0 -1
- package/dist/lib/utils/domainTypes.js +2 -10
- package/dist/lib/utils/env.js +14 -26
- package/dist/lib/utils/getAccountId.js +3 -7
- package/dist/lib/utils/getAsync.js +7 -10
- package/dist/lib/utils/getConfig.d.ts +0 -2
- package/dist/lib/utils/getConfig.js +29 -47
- package/dist/lib/utils/getStackOutput.js +4 -8
- package/dist/lib/utils/index.d.ts +12 -12
- package/dist/lib/utils/index.js +12 -29
- package/dist/lib/utils/manifestWriter.d.ts +14 -3
- package/dist/lib/utils/manifestWriter.js +60 -43
- package/dist/lib/utils/orgConfigParser.d.ts +14 -0
- package/dist/lib/utils/orgConfigParser.js +49 -0
- package/dist/lib/utils/removalPolicy.js +5 -9
- package/dist/lib/utils/resourceNaming.js +11 -16
- package/dist/lib/utils/standardTagsAspect.js +9 -16
- package/dist/lib/utils/stripAndCamelCase.js +1 -5
- package/dist/lib/utils/validationLogger.js +12 -18
- package/dist/lib/utils/vpcUtils.js +5 -10
- package/package.json +25 -8
- package/dist/lib/config/aws/accountId.d.ts +0 -6
- package/dist/lib/config/aws/accountId.js +0 -32
- package/dist/lib/config/aws/backupGlobalSettings.d.ts +0 -29
- package/dist/lib/config/aws/backupGlobalSettings.js +0 -49
- package/dist/lib/config/aws/costAllocationTags.d.ts +0 -12
- package/dist/lib/config/aws/costAllocationTags.js +0 -47
- package/dist/lib/config/aws/ipamDelegateAdmin.d.ts +0 -8
- package/dist/lib/config/aws/ipamDelegateAdmin.js +0 -57
- package/dist/lib/config/aws/ipamPoolId.d.ts +0 -16
- package/dist/lib/config/aws/ipamPoolId.js +0 -42
- package/dist/lib/config/aws/organisation.d.ts +0 -30
- package/dist/lib/config/aws/organisation.js +0 -92
- package/dist/lib/config/aws/organisationId.d.ts +0 -7
- package/dist/lib/config/aws/organisationId.js +0 -45
- package/dist/lib/config/aws/organisationsAccess.d.ts +0 -10
- package/dist/lib/config/aws/organisationsAccess.js +0 -49
- package/dist/lib/config/aws/ramSharing.d.ts +0 -4
- package/dist/lib/config/aws/ramSharing.js +0 -34
- package/dist/lib/config/monitoring.d.ts +0 -18
- package/dist/lib/config/monitoring.js +0 -22
- package/dist/lib/patterns/aws/connections.d.ts +0 -46
- package/dist/lib/patterns/aws/connections.js +0 -159
- package/dist/lib/patterns/aws/hostedZone.d.ts +0 -28
- package/dist/lib/patterns/aws/hostedZone.js +0 -150
- package/dist/lib/patterns/aws/managedAccount.d.ts +0 -9
- package/dist/lib/patterns/aws/managedAccount.js +0 -55
- package/dist/lib/patterns/aws/managedOrganisation.d.ts +0 -36
- package/dist/lib/patterns/aws/managedOrganisation.js +0 -97
- package/dist/lib/patterns/aws/managedPlatform.d.ts +0 -12
- package/dist/lib/patterns/aws/managedPlatform.js +0 -29
- package/dist/lib/resources/aws/database/database.d.ts +0 -14
- package/dist/lib/resources/aws/database/database.js +0 -28
- package/dist/lib/resources/aws/database/databaseInstance.d.ts +0 -15
- package/dist/lib/resources/aws/database/databaseInstance.js +0 -30
- package/dist/lib/resources/aws/database/migrationLambda.d.ts +0 -80
- package/dist/lib/resources/aws/database/migrationLambda.js +0 -119
- package/dist/lib/resources/aws/iam/identityCenter/attachManagedPolicy.d.ts +0 -13
- package/dist/lib/resources/aws/iam/identityCenter/attachManagedPolicy.js +0 -51
- package/dist/lib/resources/aws/iam/securityGroup.d.ts +0 -5
- package/dist/lib/resources/aws/iam/securityGroup.js +0 -14
- package/dist/lib/resources/aws/monitoring/monitoringRole.d.ts +0 -29
- package/dist/lib/resources/aws/monitoring/monitoringRole.js +0 -120
- package/dist/lib/utils/capitalizeString.d.ts +0 -12
- package/dist/lib/utils/capitalizeString.js +0 -30
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type Cluster as CdkCluster } from "aws-cdk-lib/aws-ecs";
|
|
2
|
+
import type { IAspect } from "aws-cdk-lib";
|
|
3
|
+
import type { IConstruct } from "constructs";
|
|
4
|
+
/**
|
|
5
|
+
* CDK Aspect that fixes capacity provider deletion dependencies.
|
|
6
|
+
*
|
|
7
|
+
* This is a workaround for CDK bug #15366 where ECS services don't properly
|
|
8
|
+
* depend on CfnClusterCapacityProviderAssociations, causing "capacity provider
|
|
9
|
+
* is in use" errors during stack deletion.
|
|
10
|
+
*
|
|
11
|
+
* The aspect runs at synth time (when associations exist) and adds:
|
|
12
|
+
* - Service depends on CfnClusterCapacityProviderAssociations
|
|
13
|
+
*
|
|
14
|
+
* DELETE order becomes: Services -> Associations -> Cluster
|
|
15
|
+
*
|
|
16
|
+
* @see https://github.com/aws/aws-cdk/issues/15366
|
|
17
|
+
*/
|
|
18
|
+
export declare class CapacityProviderDependencyAspect implements IAspect {
|
|
19
|
+
private readonly cluster;
|
|
20
|
+
constructor(cluster: CdkCluster);
|
|
21
|
+
visit(node: IConstruct): void;
|
|
22
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { FargateService, Ec2Service, CfnClusterCapacityProviderAssociations } from "aws-cdk-lib/aws-ecs";
|
|
2
|
+
/**
|
|
3
|
+
* CDK Aspect that fixes capacity provider deletion dependencies.
|
|
4
|
+
*
|
|
5
|
+
* This is a workaround for CDK bug #15366 where ECS services don't properly
|
|
6
|
+
* depend on CfnClusterCapacityProviderAssociations, causing "capacity provider
|
|
7
|
+
* is in use" errors during stack deletion.
|
|
8
|
+
*
|
|
9
|
+
* The aspect runs at synth time (when associations exist) and adds:
|
|
10
|
+
* - Service depends on CfnClusterCapacityProviderAssociations
|
|
11
|
+
*
|
|
12
|
+
* DELETE order becomes: Services -> Associations -> Cluster
|
|
13
|
+
*
|
|
14
|
+
* @see https://github.com/aws/aws-cdk/issues/15366
|
|
15
|
+
*/
|
|
16
|
+
export class CapacityProviderDependencyAspect {
|
|
17
|
+
cluster;
|
|
18
|
+
constructor(cluster) {
|
|
19
|
+
this.cluster = cluster;
|
|
20
|
+
}
|
|
21
|
+
visit(node) {
|
|
22
|
+
// Find ECS services that belong to this cluster
|
|
23
|
+
if (node instanceof FargateService || node instanceof Ec2Service) {
|
|
24
|
+
// Find CfnClusterCapacityProviderAssociations in the cluster's descendants
|
|
25
|
+
const associations = this.cluster.node
|
|
26
|
+
.findAll()
|
|
27
|
+
.find((child) => child instanceof CfnClusterCapacityProviderAssociations);
|
|
28
|
+
if (associations) {
|
|
29
|
+
// Add dependency: Service -> Associations
|
|
30
|
+
// DELETE order: Service deleted first, then Associations
|
|
31
|
+
node.node.addDependency(associations);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { AmiHardwareType } from "aws-cdk-lib/aws-ecs";
|
|
2
|
+
export declare const DEFAULT_EC2_INSTANCE_TYPE = "t4g.micro";
|
|
3
|
+
export declare const DEFAULT_WARM_POOL_MIN_SIZE = 1;
|
|
4
|
+
export declare const DEFAULT_WARM_POOL_REUSE_ON_SCALE_IN = true;
|
|
5
|
+
export declare const DEFAULT_LOG_RETENTION_DAYS = 14;
|
|
6
|
+
/**
|
|
7
|
+
* Instance type prefixes that use ARM64 architecture (Graviton processors).
|
|
8
|
+
* All other prefixes are assumed to be x86-64 (STANDARD).
|
|
9
|
+
*
|
|
10
|
+
* Keep in sync with @fjall/generator schemas/instanceTypeArchitecture.ts
|
|
11
|
+
*/
|
|
12
|
+
export declare const ARM_INSTANCE_PREFIXES: string[];
|
|
13
|
+
/**
|
|
14
|
+
* Infer the AMI hardware type from an EC2 instance type.
|
|
15
|
+
* Uses the instance type prefix to determine if it's ARM (Graviton) or x86-64.
|
|
16
|
+
*
|
|
17
|
+
* @param instanceType - EC2 instance type (e.g., "t4g.micro", "t3.small")
|
|
18
|
+
* @returns AmiHardwareType.ARM for Graviton instances, AmiHardwareType.STANDARD for Intel/AMD
|
|
19
|
+
*/
|
|
20
|
+
export declare function inferAmiHardwareType(instanceType: string): AmiHardwareType;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { AmiHardwareType } from "aws-cdk-lib/aws-ecs";
|
|
2
|
+
// Canonical source: @fjall/generator schemas/constants.ts — keep in sync
|
|
3
|
+
export const DEFAULT_EC2_INSTANCE_TYPE = "t4g.micro";
|
|
4
|
+
export const DEFAULT_WARM_POOL_MIN_SIZE = 1;
|
|
5
|
+
export const DEFAULT_WARM_POOL_REUSE_ON_SCALE_IN = true;
|
|
6
|
+
// 14 days balances cost against retaining enough history for post-mortem debugging
|
|
7
|
+
export const DEFAULT_LOG_RETENTION_DAYS = 14;
|
|
8
|
+
/**
|
|
9
|
+
* Instance type prefixes that use ARM64 architecture (Graviton processors).
|
|
10
|
+
* All other prefixes are assumed to be x86-64 (STANDARD).
|
|
11
|
+
*
|
|
12
|
+
* Keep in sync with @fjall/generator schemas/instanceTypeArchitecture.ts
|
|
13
|
+
*/
|
|
14
|
+
export const ARM_INSTANCE_PREFIXES = [
|
|
15
|
+
"t4g",
|
|
16
|
+
"c6g",
|
|
17
|
+
"c6gd",
|
|
18
|
+
"c6gn",
|
|
19
|
+
"c7g",
|
|
20
|
+
"c7gd",
|
|
21
|
+
"c7gn",
|
|
22
|
+
"r6g",
|
|
23
|
+
"r6gd",
|
|
24
|
+
"r7g",
|
|
25
|
+
"r7gd",
|
|
26
|
+
"m6g",
|
|
27
|
+
"m6gd",
|
|
28
|
+
"m7g",
|
|
29
|
+
"m7gd",
|
|
30
|
+
"a1",
|
|
31
|
+
"x2gd",
|
|
32
|
+
"im4gn",
|
|
33
|
+
"is4gen",
|
|
34
|
+
"i4g",
|
|
35
|
+
"hpc7g"
|
|
36
|
+
];
|
|
37
|
+
/**
|
|
38
|
+
* Infer the AMI hardware type from an EC2 instance type.
|
|
39
|
+
* Uses the instance type prefix to determine if it's ARM (Graviton) or x86-64.
|
|
40
|
+
*
|
|
41
|
+
* @param instanceType - EC2 instance type (e.g., "t4g.micro", "t3.small")
|
|
42
|
+
* @returns AmiHardwareType.ARM for Graviton instances, AmiHardwareType.STANDARD for Intel/AMD
|
|
43
|
+
*/
|
|
44
|
+
export function inferAmiHardwareType(instanceType) {
|
|
45
|
+
const prefix = instanceType.split(".")[0] ?? instanceType;
|
|
46
|
+
return ARM_INSTANCE_PREFIXES.includes(prefix)
|
|
47
|
+
? AmiHardwareType.ARM
|
|
48
|
+
: AmiHardwareType.STANDARD;
|
|
49
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Construct } from "constructs";
|
|
2
|
+
import type { Cluster as CdkCluster } from "aws-cdk-lib/aws-ecs";
|
|
3
|
+
import type { EcsClusterProps } from "./ecsTypes.js";
|
|
4
|
+
/** Shared state passed from EcsCluster to extracted helper functions. */
|
|
5
|
+
export interface EcsConstructContext {
|
|
6
|
+
scope: Construct;
|
|
7
|
+
props: EcsClusterProps;
|
|
8
|
+
cluster: CdkCluster;
|
|
9
|
+
outputName: string;
|
|
10
|
+
loadBalancerDisabled: boolean;
|
|
11
|
+
directAccessEnabled: boolean;
|
|
12
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { ContainerImage } from "aws-cdk-lib/aws-ecs";
|
|
2
|
+
import type { EcsConstructContext } from "./ecsContext.js";
|
|
3
|
+
import type { EcsClusterContainerConfig, EcsServiceProps } from "./ecsTypes.js";
|
|
4
|
+
export declare function getContainerImage(ctx: EcsConstructContext, serviceName: string, containerConfig: EcsClusterContainerConfig, serviceProps: EcsServiceProps): ContainerImage;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { ContainerImage } from "aws-cdk-lib/aws-ecs";
|
|
2
|
+
import { Repository } from "aws-cdk-lib/aws-ecr";
|
|
3
|
+
export function getContainerImage(ctx, serviceName, containerConfig, serviceProps) {
|
|
4
|
+
const imageSource = containerConfig.image || serviceProps.image || ctx.props.ecrRepository;
|
|
5
|
+
if (!imageSource) {
|
|
6
|
+
return ContainerImage.fromRegistry("amazon/amazon-ecs-sample");
|
|
7
|
+
}
|
|
8
|
+
// Build image tag with optional dockerTarget suffix
|
|
9
|
+
// Format: <service>-[<target>-]<version>
|
|
10
|
+
// imageVersion comes from CDK context (git SHA) to ensure CloudFormation
|
|
11
|
+
// detects template changes when new code is deployed. Falls back to 'latest'
|
|
12
|
+
// for apps without Dockerfiles (welcome image) or local dev.
|
|
13
|
+
const rawVersion = ctx.scope.node.tryGetContext("imageVersion");
|
|
14
|
+
const imageVersion = (typeof rawVersion === "string" ? rawVersion : undefined) || "latest";
|
|
15
|
+
const targetSuffix = serviceProps.dockerTarget
|
|
16
|
+
? `-${serviceProps.dockerTarget.toLowerCase()}`
|
|
17
|
+
: "";
|
|
18
|
+
const imageTag = `${serviceName.toLowerCase()}${targetSuffix}-${imageVersion}`;
|
|
19
|
+
if (typeof imageSource === "string") {
|
|
20
|
+
// Detect full registry URLs vs bare ECR repository names.
|
|
21
|
+
// Bare names (with or without namespace slashes) are treated as ECR repos.
|
|
22
|
+
// Docker Hub requires an explicit registry prefix (docker.io/).
|
|
23
|
+
const isFullRegistryUrl = /^(docker\.io|registry\.hub\.docker\.com|ghcr\.io)\//i.test(imageSource) || // Docker Hub / GHCR URLs
|
|
24
|
+
imageSource.startsWith("public.ecr.aws/") || // Public ECR: public.ecr.aws/fjall/welcome
|
|
25
|
+
imageSource.includes(".dkr.ecr."); // Private ECR full URL: 123456789012.dkr.ecr.us-east-2.amazonaws.com/repo:tag
|
|
26
|
+
if (isFullRegistryUrl) {
|
|
27
|
+
return ContainerImage.fromRegistry(imageSource);
|
|
28
|
+
}
|
|
29
|
+
return ContainerImage.fromEcrRepository(Repository.fromRepositoryName(ctx.scope, `${serviceName}${containerConfig.name}EcrRepo`, imageSource), imageTag);
|
|
30
|
+
}
|
|
31
|
+
if (imageSource instanceof Repository) {
|
|
32
|
+
return ContainerImage.fromEcrRepository(imageSource, imageTag);
|
|
33
|
+
}
|
|
34
|
+
return imageSource;
|
|
35
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { type ApplicationListener, ApplicationLoadBalancer, type IApplicationTargetGroup, ListenerCondition } from "aws-cdk-lib/aws-elasticloadbalancingv2";
|
|
2
|
+
import { type ICertificate } from "aws-cdk-lib/aws-certificatemanager";
|
|
3
|
+
import { ARecord, type IHostedZone } from "aws-cdk-lib/aws-route53";
|
|
4
|
+
import type { AutoScalingGroup } from "aws-cdk-lib/aws-autoscaling";
|
|
5
|
+
import type { ContainerDefinition, FargateService, Ec2Service } from "aws-cdk-lib/aws-ecs";
|
|
6
|
+
import { SecurityGroup } from "../networking/securityGroup.js";
|
|
7
|
+
import type { EcsConstructContext } from "./ecsContext.js";
|
|
8
|
+
import type { EcsRoutingConfig, EcsServiceProps } from "./ecsTypes.js";
|
|
9
|
+
/** Mutable priority state for ALB rule ordering. */
|
|
10
|
+
export interface PriorityState {
|
|
11
|
+
nextPriority: number;
|
|
12
|
+
usedPriorities: Set<number>;
|
|
13
|
+
}
|
|
14
|
+
/** Returns the next unused auto-incremented ALB priority, skipping any manually assigned values. */
|
|
15
|
+
export declare function getNextPriority(state: PriorityState): number;
|
|
16
|
+
export declare function buildRoutingConditions(rule: EcsRoutingConfig | undefined): ListenerCondition[];
|
|
17
|
+
export declare function addLoadBalancer(ctx: EcsConstructContext, anyServiceUsesEc2: boolean, asgSecurityGroup?: SecurityGroup): {
|
|
18
|
+
loadBalancer: ApplicationLoadBalancer;
|
|
19
|
+
loadBalancerSecurityGroup?: SecurityGroup;
|
|
20
|
+
};
|
|
21
|
+
export declare function addLoadBalancerListener(ctx: EcsConstructContext, loadBalancer: ApplicationLoadBalancer, certificate?: ICertificate): ApplicationListener;
|
|
22
|
+
export declare function addHostedZone(ctx: EcsConstructContext, loadBalancer?: ApplicationLoadBalancer): {
|
|
23
|
+
hostedZone?: IHostedZone;
|
|
24
|
+
certificate?: ICertificate;
|
|
25
|
+
aRecord?: ARecord;
|
|
26
|
+
};
|
|
27
|
+
export declare function addDirectAccessOutputs(ctx: EcsConstructContext, autoScalingGroup?: AutoScalingGroup): void;
|
|
28
|
+
export declare function registerServiceWithALB(ctx: EcsConstructContext, listener: ApplicationListener, serviceName: string, serviceProps: EcsServiceProps, service: FargateService | Ec2Service, primaryContainer: ContainerDefinition, priorityState: PriorityState): IApplicationTargetGroup;
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
import { ApplicationLoadBalancer, ApplicationProtocol, ListenerAction, ListenerCondition } from "aws-cdk-lib/aws-elasticloadbalancingv2";
|
|
2
|
+
import { Port, SubnetType } from "aws-cdk-lib/aws-ec2";
|
|
3
|
+
import { CfnOutput, Duration, Fn } from "aws-cdk-lib";
|
|
4
|
+
import { Certificate, CertificateValidation } from "aws-cdk-lib/aws-certificatemanager";
|
|
5
|
+
import { ARecord, HostedZone as AWSHostedZone, RecordTarget } from "aws-cdk-lib/aws-route53";
|
|
6
|
+
import { LoadBalancerTarget } from "aws-cdk-lib/aws-route53-targets";
|
|
7
|
+
import { HostedZone as FjallHostedZone } from "../networking/hostedZone.js";
|
|
8
|
+
import { SecurityGroup } from "../networking/securityGroup.js";
|
|
9
|
+
import { isServiceEc2 } from "./ecsTaskDefinition.js";
|
|
10
|
+
/** Returns the next unused auto-incremented ALB priority, skipping any manually assigned values. */
|
|
11
|
+
export function getNextPriority(state) {
|
|
12
|
+
while (state.usedPriorities.has(state.nextPriority)) {
|
|
13
|
+
state.nextPriority++;
|
|
14
|
+
}
|
|
15
|
+
const priority = state.nextPriority++;
|
|
16
|
+
state.usedPriorities.add(priority);
|
|
17
|
+
return priority;
|
|
18
|
+
}
|
|
19
|
+
export function buildRoutingConditions(rule) {
|
|
20
|
+
const conditions = [];
|
|
21
|
+
if (rule?.path) {
|
|
22
|
+
conditions.push(ListenerCondition.pathPatterns([rule.path]));
|
|
23
|
+
}
|
|
24
|
+
if (rule?.host) {
|
|
25
|
+
conditions.push(ListenerCondition.hostHeaders([rule.host]));
|
|
26
|
+
}
|
|
27
|
+
return conditions;
|
|
28
|
+
}
|
|
29
|
+
export function addLoadBalancer(ctx, anyServiceUsesEc2, asgSecurityGroup) {
|
|
30
|
+
const props = ctx.props;
|
|
31
|
+
const defaultLoadBalancerName = `${props.clusterName}LoadBalancer`;
|
|
32
|
+
const supportedNameLength = 32;
|
|
33
|
+
let truncatedLoadBalancerName = defaultLoadBalancerName.length > supportedNameLength
|
|
34
|
+
? defaultLoadBalancerName.substring(0, supportedNameLength)
|
|
35
|
+
: defaultLoadBalancerName;
|
|
36
|
+
truncatedLoadBalancerName = truncatedLoadBalancerName.replace(/-+$/, "");
|
|
37
|
+
const isInternal = props.cluster?.loadBalancer === "internal";
|
|
38
|
+
let loadBalancerSecurityGroup;
|
|
39
|
+
if (anyServiceUsesEc2) {
|
|
40
|
+
loadBalancerSecurityGroup = new SecurityGroup(ctx.scope, `${props.clusterName}LoadBalancerSecurityGroup`, {
|
|
41
|
+
vpc: ctx.cluster.vpc,
|
|
42
|
+
description: `Security group for the ${props.clusterName} load balancer`
|
|
43
|
+
});
|
|
44
|
+
if (asgSecurityGroup) {
|
|
45
|
+
loadBalancerSecurityGroup.connections.allowTo(asgSecurityGroup, Port.allTcp());
|
|
46
|
+
// ECS bridge-mode maps container ports to IANA ephemeral range (49152-65535).
|
|
47
|
+
// The ALB must reach these dynamic ports on the EC2 instances.
|
|
48
|
+
asgSecurityGroup.connections.allowFrom(loadBalancerSecurityGroup, Port.tcpRange(49152, 65535));
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
const loadBalancer = new ApplicationLoadBalancer(ctx.scope, `${props.clusterName}LoadBalancer`, {
|
|
52
|
+
vpc: ctx.cluster.vpc,
|
|
53
|
+
internetFacing: !isInternal,
|
|
54
|
+
...(loadBalancerSecurityGroup && {
|
|
55
|
+
securityGroup: loadBalancerSecurityGroup
|
|
56
|
+
}),
|
|
57
|
+
loadBalancerName: truncatedLoadBalancerName,
|
|
58
|
+
vpcSubnets: {
|
|
59
|
+
subnetType: isInternal
|
|
60
|
+
? SubnetType.PRIVATE_WITH_EGRESS
|
|
61
|
+
: SubnetType.PUBLIC
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
new CfnOutput(ctx.scope, `${ctx.outputName}LoadBalancerDnsName`, {
|
|
65
|
+
key: `${ctx.outputName}LoadBalancerDnsName`,
|
|
66
|
+
exportName: `${props.clusterName}LoadBalancerDnsName`,
|
|
67
|
+
value: loadBalancer.loadBalancerDnsName
|
|
68
|
+
});
|
|
69
|
+
// Cross-stack exports consumed by the Domain construct's `fjallApp(<name>)`
|
|
70
|
+
// alias target. Names mirror the consumer contract in `cross-system-parity`.
|
|
71
|
+
new CfnOutput(ctx.scope, `${ctx.outputName}AlbDnsName`, {
|
|
72
|
+
key: `${ctx.outputName}AlbDnsName`,
|
|
73
|
+
exportName: `${ctx.outputName}AlbDnsName`,
|
|
74
|
+
value: loadBalancer.loadBalancerDnsName,
|
|
75
|
+
description: `ALB DNS name for ${props.clusterName} (consumed by Domain alias targets)`
|
|
76
|
+
});
|
|
77
|
+
new CfnOutput(ctx.scope, `${ctx.outputName}AlbHostedZoneId`, {
|
|
78
|
+
key: `${ctx.outputName}AlbHostedZoneId`,
|
|
79
|
+
exportName: `${ctx.outputName}AlbHostedZoneId`,
|
|
80
|
+
value: loadBalancer.loadBalancerCanonicalHostedZoneId,
|
|
81
|
+
description: `ALB canonical hosted zone ID for ${props.clusterName}`
|
|
82
|
+
});
|
|
83
|
+
const customDomain = props.cluster?.domain || props.cluster?.domainConfig?.domainName;
|
|
84
|
+
new CfnOutput(ctx.scope, `${ctx.outputName}LoadBalancerUrl`, {
|
|
85
|
+
key: `${ctx.outputName}LoadBalancerUrl`,
|
|
86
|
+
exportName: `${props.clusterName}LoadBalancerUrl`,
|
|
87
|
+
value: customDomain
|
|
88
|
+
? `https://${customDomain}`
|
|
89
|
+
: `http://${loadBalancer.loadBalancerDnsName}`,
|
|
90
|
+
description: `Load Balancer URL for ${props.clusterName}`
|
|
91
|
+
});
|
|
92
|
+
// Export load balancer ARN for monitoring
|
|
93
|
+
new CfnOutput(ctx.scope, `${ctx.outputName}LoadBalancerArn`, {
|
|
94
|
+
key: `${ctx.outputName}LoadBalancerArn`,
|
|
95
|
+
exportName: `${props.clusterName}LoadBalancerArn`,
|
|
96
|
+
value: loadBalancer.loadBalancerArn,
|
|
97
|
+
description: `Load Balancer ARN for ${props.clusterName}`
|
|
98
|
+
});
|
|
99
|
+
return { loadBalancer, loadBalancerSecurityGroup };
|
|
100
|
+
}
|
|
101
|
+
export function addLoadBalancerListener(ctx, loadBalancer, certificate) {
|
|
102
|
+
const port = certificate ? 443 : 80;
|
|
103
|
+
const defaultAction = ListenerAction.fixedResponse(404, {
|
|
104
|
+
contentType: "text/plain",
|
|
105
|
+
messageBody: "Not Found"
|
|
106
|
+
});
|
|
107
|
+
if (certificate) {
|
|
108
|
+
return loadBalancer.addListener(`${ctx.props.clusterName}Listener`, {
|
|
109
|
+
port,
|
|
110
|
+
certificates: [certificate],
|
|
111
|
+
defaultAction
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
return loadBalancer.addListener(`${ctx.props.clusterName}Listener`, {
|
|
116
|
+
port,
|
|
117
|
+
defaultAction
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
export function addHostedZone(ctx, loadBalancer) {
|
|
122
|
+
const props = ctx.props;
|
|
123
|
+
const domainConfig = props.cluster?.domainConfig;
|
|
124
|
+
const simpleDomain = props.cluster?.domain;
|
|
125
|
+
const domainName = domainConfig?.domainName ?? simpleDomain;
|
|
126
|
+
if (!domainName)
|
|
127
|
+
return {};
|
|
128
|
+
let hostedZone;
|
|
129
|
+
let certificate;
|
|
130
|
+
let aRecord;
|
|
131
|
+
// Managed domain: import zone and cert from domain stack via Fn.importValue
|
|
132
|
+
if (domainConfig?.managedDomain) {
|
|
133
|
+
const managed = domainConfig.managedDomain;
|
|
134
|
+
hostedZone = AWSHostedZone.fromHostedZoneAttributes(ctx.scope, `${props.clusterName}ManagedHostedZone`, {
|
|
135
|
+
hostedZoneId: Fn.importValue(managed.hostedZoneIdExport),
|
|
136
|
+
zoneName: managed.zoneName
|
|
137
|
+
});
|
|
138
|
+
certificate = Certificate.fromCertificateArn(ctx.scope, `${props.clusterName}ManagedCertificate`, Fn.importValue(managed.certificateArnExport));
|
|
139
|
+
}
|
|
140
|
+
else if (!domainConfig?.hostedZone) {
|
|
141
|
+
const fjallHostedZone = new FjallHostedZone(ctx.scope, `${props.clusterName}HostedZone`, {
|
|
142
|
+
zoneName: domainName
|
|
143
|
+
});
|
|
144
|
+
hostedZone = fjallHostedZone.hostedZone;
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
hostedZone = domainConfig.hostedZone.hostedZone;
|
|
148
|
+
}
|
|
149
|
+
if (domainConfig?.certificate) {
|
|
150
|
+
certificate = domainConfig.certificate;
|
|
151
|
+
}
|
|
152
|
+
else if (!domainConfig?.managedDomain) {
|
|
153
|
+
certificate = new Certificate(ctx.scope, `${props.clusterName}Certificate`, {
|
|
154
|
+
domainName,
|
|
155
|
+
validation: CertificateValidation.fromDns(hostedZone)
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
if (domainConfig) {
|
|
159
|
+
const region = "region" in domainConfig ? domainConfig.region : undefined;
|
|
160
|
+
const weight = "weight" in domainConfig ? domainConfig.weight : undefined;
|
|
161
|
+
const geoLocation = "geoLocation" in domainConfig ? domainConfig.geoLocation : undefined;
|
|
162
|
+
const hasRoutingPolicy = !!region || weight !== undefined || !!geoLocation;
|
|
163
|
+
let setIdentifier = domainConfig.setIdentifier;
|
|
164
|
+
if (hasRoutingPolicy && !setIdentifier) {
|
|
165
|
+
if (region) {
|
|
166
|
+
setIdentifier = `${props.clusterName}${region}`;
|
|
167
|
+
}
|
|
168
|
+
else if (weight !== undefined) {
|
|
169
|
+
setIdentifier = `${props.clusterName}Weight${weight}`;
|
|
170
|
+
}
|
|
171
|
+
else if (geoLocation) {
|
|
172
|
+
setIdentifier = `${props.clusterName}Geo`;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
if (loadBalancer && hostedZone) {
|
|
176
|
+
aRecord = new ARecord(ctx.scope, `${props.clusterName}ARecord`, {
|
|
177
|
+
recordName: domainName,
|
|
178
|
+
zone: hostedZone,
|
|
179
|
+
target: RecordTarget.fromAlias(new LoadBalancerTarget(loadBalancer, {
|
|
180
|
+
evaluateTargetHealth: hasRoutingPolicy
|
|
181
|
+
})),
|
|
182
|
+
region,
|
|
183
|
+
weight,
|
|
184
|
+
geoLocation,
|
|
185
|
+
setIdentifier: setIdentifier
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
else if (simpleDomain && loadBalancer && hostedZone) {
|
|
190
|
+
aRecord = new ARecord(ctx.scope, `${props.clusterName}ARecord`, {
|
|
191
|
+
recordName: domainName,
|
|
192
|
+
zone: hostedZone,
|
|
193
|
+
target: RecordTarget.fromAlias(new LoadBalancerTarget(loadBalancer))
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
return { hostedZone, certificate, aRecord };
|
|
197
|
+
}
|
|
198
|
+
export function addDirectAccessOutputs(ctx, autoScalingGroup) {
|
|
199
|
+
if (!ctx.directAccessEnabled || !autoScalingGroup)
|
|
200
|
+
return;
|
|
201
|
+
const props = ctx.props;
|
|
202
|
+
const containerPort = props.services.flatMap((s) => s.containers).find((c) => c.port)?.port ||
|
|
203
|
+
3000;
|
|
204
|
+
new CfnOutput(ctx.scope, `${ctx.outputName}AutoScalingGroupName`, {
|
|
205
|
+
key: `${ctx.outputName}AutoScalingGroupName`,
|
|
206
|
+
exportName: `${props.clusterName}AutoScalingGroupName`,
|
|
207
|
+
value: autoScalingGroup.autoScalingGroupName,
|
|
208
|
+
description: `Run: aws autoscaling describe-auto-scaling-groups --auto-scaling-group-names <name> to find instance IP`
|
|
209
|
+
});
|
|
210
|
+
new CfnOutput(ctx.scope, `${ctx.outputName}DirectAccessPort`, {
|
|
211
|
+
key: `${ctx.outputName}DirectAccessPort`,
|
|
212
|
+
exportName: `${props.clusterName}DirectAccessPort`,
|
|
213
|
+
value: String(containerPort),
|
|
214
|
+
description: `Access your app at http://<EC2-PUBLIC-IP>:${containerPort}`
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
export function registerServiceWithALB(ctx, listener, serviceName, serviceProps, service, primaryContainer, priorityState) {
|
|
218
|
+
const containerPort = primaryContainer.containerPort;
|
|
219
|
+
// Normalise routing to array
|
|
220
|
+
const routingRules = Array.isArray(serviceProps.routing)
|
|
221
|
+
? serviceProps.routing
|
|
222
|
+
: serviceProps.routing
|
|
223
|
+
? [serviceProps.routing]
|
|
224
|
+
: [];
|
|
225
|
+
const healthCheckPath = routingRules.find((r) => r.healthCheckPath)?.healthCheckPath ?? "/";
|
|
226
|
+
const servicesWithPorts = ctx.props.services.filter((s) => s.containers.some((c) => c.port !== undefined));
|
|
227
|
+
const isSingleService = servicesWithPorts.length === 1;
|
|
228
|
+
const healthCheckConfig = isServiceEc2(serviceProps)
|
|
229
|
+
? {
|
|
230
|
+
interval: Duration.seconds(30),
|
|
231
|
+
healthyThresholdCount: 3,
|
|
232
|
+
unhealthyThresholdCount: 3,
|
|
233
|
+
path: healthCheckPath,
|
|
234
|
+
port: "traffic-port",
|
|
235
|
+
timeout: Duration.seconds(15)
|
|
236
|
+
}
|
|
237
|
+
: {
|
|
238
|
+
interval: Duration.seconds(120),
|
|
239
|
+
path: healthCheckPath,
|
|
240
|
+
port: `${containerPort}`,
|
|
241
|
+
timeout: Duration.seconds(10)
|
|
242
|
+
};
|
|
243
|
+
if (isSingleService && routingRules.length <= 1) {
|
|
244
|
+
return listener.addTargets(`${serviceName}TargetGroup`, {
|
|
245
|
+
targets: [
|
|
246
|
+
service.loadBalancerTarget({
|
|
247
|
+
containerName: primaryContainer.containerName,
|
|
248
|
+
containerPort
|
|
249
|
+
})
|
|
250
|
+
],
|
|
251
|
+
port: containerPort,
|
|
252
|
+
protocol: ApplicationProtocol.HTTP,
|
|
253
|
+
healthCheck: healthCheckConfig
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
else {
|
|
257
|
+
const firstRule = routingRules[0];
|
|
258
|
+
const firstPriority = firstRule?.priority ?? getNextPriority(priorityState);
|
|
259
|
+
if (firstRule?.priority)
|
|
260
|
+
priorityState.usedPriorities.add(firstRule.priority);
|
|
261
|
+
const targetGroup = listener.addTargets(`${serviceName}Targets`, {
|
|
262
|
+
targets: [
|
|
263
|
+
service.loadBalancerTarget({
|
|
264
|
+
containerName: primaryContainer.containerName,
|
|
265
|
+
containerPort
|
|
266
|
+
})
|
|
267
|
+
],
|
|
268
|
+
port: containerPort,
|
|
269
|
+
protocol: ApplicationProtocol.HTTP,
|
|
270
|
+
healthCheck: healthCheckConfig,
|
|
271
|
+
conditions: buildRoutingConditions(firstRule),
|
|
272
|
+
priority: firstPriority
|
|
273
|
+
});
|
|
274
|
+
// Additional rules reuse the same target group
|
|
275
|
+
for (let i = 1; i < routingRules.length; i++) {
|
|
276
|
+
const rule = routingRules[i];
|
|
277
|
+
if (!rule)
|
|
278
|
+
continue;
|
|
279
|
+
const priority = rule.priority ?? getNextPriority(priorityState);
|
|
280
|
+
if (rule.priority)
|
|
281
|
+
priorityState.usedPriorities.add(rule.priority);
|
|
282
|
+
listener.addAction(`${serviceName}Route${i}`, {
|
|
283
|
+
conditions: buildRoutingConditions(rule),
|
|
284
|
+
priority,
|
|
285
|
+
action: ListenerAction.forward([targetGroup])
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
return targetGroup;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Role } from "aws-cdk-lib/aws-iam";
|
|
2
|
+
import type { EcsConstructContext } from "./ecsContext.js";
|
|
3
|
+
import type { EcsServiceProps } from "./ecsTypes.js";
|
|
4
|
+
/**
|
|
5
|
+
* Creates the execution role for ECS infrastructure operations.
|
|
6
|
+
* Used by the ECS agent to pull images, write logs, and inject secrets.
|
|
7
|
+
* NOT used by application code — that's the task role.
|
|
8
|
+
*/
|
|
9
|
+
export declare function createExecutionRole(ctx: EcsConstructContext, serviceName: string): Role;
|
|
10
|
+
/**
|
|
11
|
+
* Creates the task role for application code running in the container.
|
|
12
|
+
* This role is assumed by the application, not the ECS agent.
|
|
13
|
+
* Includes default ECS Exec permissions plus any service-specific policies.
|
|
14
|
+
*/
|
|
15
|
+
export declare function createTaskRole(ctx: EcsConstructContext, serviceName: string, serviceProps: EcsServiceProps): Role;
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { Stack } from "aws-cdk-lib";
|
|
2
|
+
import { Effect, Policy, PolicyStatement, Role, ServicePrincipal } from "aws-cdk-lib/aws-iam";
|
|
3
|
+
import { collectSecretsManagerSecretNames, deriveSsmSecretsPath } from "./ecsTaskDefinition.js";
|
|
4
|
+
/**
|
|
5
|
+
* Creates the execution role for ECS infrastructure operations.
|
|
6
|
+
* Used by the ECS agent to pull images, write logs, and inject secrets.
|
|
7
|
+
* NOT used by application code — that's the task role.
|
|
8
|
+
*/
|
|
9
|
+
export function createExecutionRole(ctx, serviceName) {
|
|
10
|
+
const executionRole = new Role(ctx.scope, `${serviceName}ExecutionRole`, {
|
|
11
|
+
assumedBy: new ServicePrincipal("ecs-tasks.amazonaws.com")
|
|
12
|
+
});
|
|
13
|
+
// GetAuthorizationToken is an account-level API that requires resources: ["*"].
|
|
14
|
+
// The image-pull actions also use "*" because ecrRepository can be a string URI
|
|
15
|
+
// (cross-account or public ECR), not always a Repository construct with an ARN.
|
|
16
|
+
executionRole.addToPolicy(new PolicyStatement({
|
|
17
|
+
effect: Effect.ALLOW,
|
|
18
|
+
actions: [
|
|
19
|
+
"ecr:GetAuthorizationToken",
|
|
20
|
+
"ecr:BatchCheckLayerAvailability",
|
|
21
|
+
"ecr:GetDownloadUrlForLayer",
|
|
22
|
+
"ecr:BatchGetImage"
|
|
23
|
+
],
|
|
24
|
+
resources: ["*"]
|
|
25
|
+
}));
|
|
26
|
+
const { partition, region, account } = Stack.of(ctx.scope);
|
|
27
|
+
const logGroupArn = `arn:${partition}:logs:${region}:${account}:log-group:/ecs/${ctx.props.clusterName}*`;
|
|
28
|
+
executionRole.addToPolicy(new PolicyStatement({
|
|
29
|
+
effect: Effect.ALLOW,
|
|
30
|
+
actions: [
|
|
31
|
+
"logs:CreateLogStream",
|
|
32
|
+
"logs:PutLogEvents",
|
|
33
|
+
"logs:CreateLogGroup"
|
|
34
|
+
],
|
|
35
|
+
resources: [logGroupArn, `${logGroupArn}:*`]
|
|
36
|
+
}));
|
|
37
|
+
const secretNames = collectSecretsManagerSecretNames(ctx.props, serviceName);
|
|
38
|
+
if (secretNames.length > 0) {
|
|
39
|
+
const secretArns = secretNames.map((secretName) => `arn:${partition}:secretsmanager:${region}:${account}:secret:${secretName}-*`);
|
|
40
|
+
executionRole.addToPolicy(new PolicyStatement({
|
|
41
|
+
effect: Effect.ALLOW,
|
|
42
|
+
actions: [
|
|
43
|
+
"secretsmanager:GetSecretValue",
|
|
44
|
+
"secretsmanager:DescribeSecret"
|
|
45
|
+
],
|
|
46
|
+
resources: secretArns
|
|
47
|
+
}));
|
|
48
|
+
}
|
|
49
|
+
const serviceProps = ctx.props.services.find((s) => s.name === serviceName);
|
|
50
|
+
const hasSsmSecrets = serviceProps?.containers.some((container) => container.secrets && container.secrets.length > 0) ?? false;
|
|
51
|
+
if (hasSsmSecrets && serviceProps) {
|
|
52
|
+
const ssmPath = deriveSsmSecretsPath(ctx.props, serviceName, serviceProps.ssmSecretsPath);
|
|
53
|
+
executionRole.addToPolicy(new PolicyStatement({
|
|
54
|
+
effect: Effect.ALLOW,
|
|
55
|
+
actions: ["ssm:GetParameters", "ssm:GetParameter"],
|
|
56
|
+
resources: [
|
|
57
|
+
`arn:${partition}:ssm:${region}:${account}:parameter${ssmPath}/*`
|
|
58
|
+
]
|
|
59
|
+
}));
|
|
60
|
+
}
|
|
61
|
+
// KMS decrypt for SSM SecureString and Secrets Manager with customer-managed keys (CMKs)
|
|
62
|
+
executionRole.addToPolicy(new PolicyStatement({
|
|
63
|
+
effect: Effect.ALLOW,
|
|
64
|
+
actions: ["kms:Decrypt"],
|
|
65
|
+
resources: ["*"],
|
|
66
|
+
conditions: {
|
|
67
|
+
StringEquals: {
|
|
68
|
+
"kms:ViaService": [
|
|
69
|
+
`ssm.${region}.amazonaws.com`,
|
|
70
|
+
`secretsmanager.${region}.amazonaws.com`
|
|
71
|
+
]
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}));
|
|
75
|
+
return executionRole;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Creates the task role for application code running in the container.
|
|
79
|
+
* This role is assumed by the application, not the ECS agent.
|
|
80
|
+
* Includes default ECS Exec permissions plus any service-specific policies.
|
|
81
|
+
*/
|
|
82
|
+
export function createTaskRole(ctx, serviceName, serviceProps) {
|
|
83
|
+
const taskRole = new Role(ctx.scope, `${serviceName}TaskRole`, {
|
|
84
|
+
assumedBy: new ServicePrincipal("ecs-tasks.amazonaws.com")
|
|
85
|
+
});
|
|
86
|
+
// SSM permissions for ECS Exec (ecs execute-command)
|
|
87
|
+
taskRole.addToPolicy(new PolicyStatement({
|
|
88
|
+
effect: Effect.ALLOW,
|
|
89
|
+
actions: [
|
|
90
|
+
"ssmmessages:CreateControlChannel",
|
|
91
|
+
"ssmmessages:CreateDataChannel",
|
|
92
|
+
"ssmmessages:OpenControlChannel",
|
|
93
|
+
"ssmmessages:OpenDataChannel"
|
|
94
|
+
],
|
|
95
|
+
resources: ["*"]
|
|
96
|
+
}));
|
|
97
|
+
if (serviceProps.taskRoleInlinePolicies) {
|
|
98
|
+
for (const [policyName, policyDocument] of Object.entries(serviceProps.taskRoleInlinePolicies)) {
|
|
99
|
+
taskRole.attachInlinePolicy(new Policy(ctx.scope, `${serviceName}${policyName}`, {
|
|
100
|
+
document: policyDocument
|
|
101
|
+
}));
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
if (serviceProps.taskRoleManagedPolicies) {
|
|
105
|
+
for (const policy of serviceProps.taskRoleManagedPolicies) {
|
|
106
|
+
taskRole.addManagedPolicy(policy);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return taskRole;
|
|
110
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { FargateService, Ec2Service, AsgCapacityProvider } from "aws-cdk-lib/aws-ecs";
|
|
2
|
+
import type { FargateTaskDefinition, Ec2TaskDefinition } from "aws-cdk-lib/aws-ecs";
|
|
3
|
+
import { TargetTrackingScalingPolicy } from "aws-cdk-lib/aws-applicationautoscaling";
|
|
4
|
+
import { AutoScalingGroup } from "aws-cdk-lib/aws-autoscaling";
|
|
5
|
+
import { SecurityGroup } from "../networking/securityGroup.js";
|
|
6
|
+
import { type EcsServiceProps, type Ec2CapacityConfig } from "./ecsTypes.js";
|
|
7
|
+
import type { EcsConstructContext } from "./ecsContext.js";
|
|
8
|
+
/** Mutable state for ASG capacity provider deduplication. */
|
|
9
|
+
export interface AsgCapacityState {
|
|
10
|
+
providers: Map<string, AsgCapacityProvider>;
|
|
11
|
+
autoScalingGroup?: AutoScalingGroup;
|
|
12
|
+
asgSecurityGroup?: SecurityGroup;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Generates a unique key for EC2 config so services with matching
|
|
16
|
+
* configurations share an ASG.
|
|
17
|
+
*/
|
|
18
|
+
export declare function getEc2ConfigKey(ec2Config: Ec2CapacityConfig): string;
|
|
19
|
+
/**
|
|
20
|
+
* Gets or creates an ASG capacity provider for an EC2-backed service.
|
|
21
|
+
* Services with matching EC2 configs share the same ASG.
|
|
22
|
+
*
|
|
23
|
+
* Mutates `state` to track the provider and first ASG/security group.
|
|
24
|
+
*/
|
|
25
|
+
export declare function getOrCreateAsgCapacityProvider(ctx: EcsConstructContext, serviceProps: EcsServiceProps, state: AsgCapacityState): AsgCapacityProvider;
|
|
26
|
+
/**
|
|
27
|
+
* Creates a Fargate or EC2 service and emits a CfnOutput for its ARN.
|
|
28
|
+
*/
|
|
29
|
+
export declare function createService(ctx: EcsConstructContext, serviceName: string, serviceProps: EcsServiceProps, taskDefinition: FargateTaskDefinition | Ec2TaskDefinition, asgState: AsgCapacityState): FargateService | Ec2Service;
|
|
30
|
+
/**
|
|
31
|
+
* Adds auto-scaling to an ECS service based on CPU or memory utilisation.
|
|
32
|
+
*/
|
|
33
|
+
export declare function addServiceScaling(ctx: EcsConstructContext, serviceName: string, serviceProps: EcsServiceProps, service: FargateService | Ec2Service): TargetTrackingScalingPolicy;
|