From 3d2af308243dd6e79bf479141edbbff9c08a1982 Mon Sep 17 00:00:00 2001 From: maz Date: Tue, 9 Jul 2024 11:54:55 +0900 Subject: [PATCH 1/2] feat: support custom certificate --- packages/@aws-cdk/aws-amplify-alpha/README.md | 11 + .../@aws-cdk/aws-amplify-alpha/lib/domain.ts | 12 + .../rosetta/default.ts-fixture | 1 + .../aws-amplify-alpha/test/domain.test.ts | 73 +++ ...efaultTestDeployAssert5F8CD1EB.assets.json | 19 + ...aultTestDeployAssert5F8CD1EB.template.json | 36 ++ .../cdk-amplify-app-custom-domain.assets.json | 19 + ...dk-amplify-app-custom-domain.template.json | 210 +++++++++ .../cdk.out | 1 + .../integ.json | 14 + .../manifest.json | 158 +++++++ .../tree.json | 433 ++++++++++++++++++ .../test/integ.app-custom-domain.ts | 75 +++ 13 files changed, 1062 insertions(+) create mode 100644 packages/@aws-cdk/aws-amplify-alpha/test/integ.app-custom-domain.js.snapshot/amplifyappcustomdomainintegDefaultTestDeployAssert5F8CD1EB.assets.json create mode 100644 packages/@aws-cdk/aws-amplify-alpha/test/integ.app-custom-domain.js.snapshot/amplifyappcustomdomainintegDefaultTestDeployAssert5F8CD1EB.template.json create mode 100644 packages/@aws-cdk/aws-amplify-alpha/test/integ.app-custom-domain.js.snapshot/cdk-amplify-app-custom-domain.assets.json create mode 100644 packages/@aws-cdk/aws-amplify-alpha/test/integ.app-custom-domain.js.snapshot/cdk-amplify-app-custom-domain.template.json create mode 100644 packages/@aws-cdk/aws-amplify-alpha/test/integ.app-custom-domain.js.snapshot/cdk.out create mode 100644 packages/@aws-cdk/aws-amplify-alpha/test/integ.app-custom-domain.js.snapshot/integ.json create mode 100644 packages/@aws-cdk/aws-amplify-alpha/test/integ.app-custom-domain.js.snapshot/manifest.json create mode 100644 packages/@aws-cdk/aws-amplify-alpha/test/integ.app-custom-domain.js.snapshot/tree.json create mode 100644 packages/@aws-cdk/aws-amplify-alpha/test/integ.app-custom-domain.ts diff --git a/packages/@aws-cdk/aws-amplify-alpha/README.md b/packages/@aws-cdk/aws-amplify-alpha/README.md index 0aa1e72e37726..3b7f58db37433 100644 --- a/packages/@aws-cdk/aws-amplify-alpha/README.md +++ b/packages/@aws-cdk/aws-amplify-alpha/README.md @@ -138,6 +138,17 @@ domain.mapSubDomain(main, 'www'); domain.mapSubDomain(dev); // sub domain prefix defaults to branch name ``` +If you want to use your custom domain, set your custom certificate to `customCertificate`: + +```ts +declare const customCertificate: acm.Certificate; +declare const amplifyApp: amplify.App; + +const domain = amplifyApp.addDomain('example.com', { + customCertificate, // set your custom certificate +}); +``` + ## Restricting access Password protect the app with basic auth by specifying the `basicAuth` prop. diff --git a/packages/@aws-cdk/aws-amplify-alpha/lib/domain.ts b/packages/@aws-cdk/aws-amplify-alpha/lib/domain.ts index 6075d2b2a1a52..c90d2ed78a46b 100644 --- a/packages/@aws-cdk/aws-amplify-alpha/lib/domain.ts +++ b/packages/@aws-cdk/aws-amplify-alpha/lib/domain.ts @@ -1,3 +1,4 @@ +import * as acm from 'aws-cdk-lib/aws-certificatemanager'; import * as iam from 'aws-cdk-lib/aws-iam'; import { Lazy, Resource, IResolvable } from 'aws-cdk-lib/core'; import { Construct } from 'constructs'; @@ -36,6 +37,13 @@ export interface DomainOptions { * @default - all repository branches ['*', 'pr*'] */ readonly autoSubdomainCreationPatterns?: string[]; + + /** + * The type of SSL/TLS certificate to use for your custom domain + * + * @default - Amplify uses the default certificate that it provisions and manages for you + */ + readonly customCertificate?: acm.ICertificate; } /** @@ -130,6 +138,10 @@ export class Domain extends Resource { enableAutoSubDomain: !!props.enableAutoSubdomain, autoSubDomainCreationPatterns: props.autoSubdomainCreationPatterns || ['*', 'pr*'], autoSubDomainIamRole: props.autoSubDomainIamRole?.roleArn, + certificateSettings: props.customCertificate ? { + certificateType: 'CUSTOM', + customCertificateArn: props.customCertificate.certificateArn, + } : undefined, }); this.arn = domain.attrArn; diff --git a/packages/@aws-cdk/aws-amplify-alpha/rosetta/default.ts-fixture b/packages/@aws-cdk/aws-amplify-alpha/rosetta/default.ts-fixture index dd27e406b3985..85e3aab9ce9f6 100644 --- a/packages/@aws-cdk/aws-amplify-alpha/rosetta/default.ts-fixture +++ b/packages/@aws-cdk/aws-amplify-alpha/rosetta/default.ts-fixture @@ -2,6 +2,7 @@ import { SecretValue, Stack } from 'aws-cdk-lib'; import { Construct } from 'constructs'; import * as amplify from '@aws-cdk/aws-amplify-alpha'; +import * as acm from 'aws-cdk-lib/aws-certificatemanager'; class Fixture extends Stack { constructor(scope: Construct, id: string) { diff --git a/packages/@aws-cdk/aws-amplify-alpha/test/domain.test.ts b/packages/@aws-cdk/aws-amplify-alpha/test/domain.test.ts index 4ed31051277e6..cbf8d9d9a42d2 100644 --- a/packages/@aws-cdk/aws-amplify-alpha/test/domain.test.ts +++ b/packages/@aws-cdk/aws-amplify-alpha/test/domain.test.ts @@ -1,4 +1,5 @@ import { Template } from 'aws-cdk-lib/assertions'; +import * as acm from 'aws-cdk-lib/aws-certificatemanager'; import * as iam from 'aws-cdk-lib/aws-iam'; import { App, SecretValue, Stack } from 'aws-cdk-lib'; import * as amplify from '../lib'; @@ -64,6 +65,78 @@ test('create a domain', () => { }); }); +test('create a domain with custom certificate', () => { + // GIVEN + const stack = new Stack(); + const app = new amplify.App(stack, 'App', { + sourceCodeProvider: new amplify.GitHubSourceCodeProvider({ + owner: 'aws', + repository: 'aws-cdk', + oauthToken: SecretValue.unsafePlainText('secret'), + }), + }); + const prodBranch = app.addBranch('main'); + const devBranch = app.addBranch('dev'); + + const customCertificate = new acm.Certificate(stack, 'Cert', { + domainName: '*.example.com', + }); + + // WHEN + const domain = app.addDomain('example.com', { + subDomains: [ + { + branch: prodBranch, + prefix: 'prod', + }, + ], + customCertificate, + }); + domain.mapSubDomain(devBranch); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::Amplify::Domain', { + AppId: { + 'Fn::GetAtt': [ + 'AppF1B96344', + 'AppId', + ], + }, + DomainName: 'example.com', + CertificateSettings: { + CertificateType: 'CUSTOM', + CustomCertificateArn: { + Ref: 'Cert5C9FAEC1', + }, + }, + SubDomainSettings: [ + { + BranchName: { + 'Fn::GetAtt': [ + 'AppmainF505BAED', + 'BranchName', + ], + }, + Prefix: 'prod', + }, + { + BranchName: { + 'Fn::GetAtt': [ + 'AppdevB328DAFC', + 'BranchName', + ], + }, + Prefix: { + 'Fn::GetAtt': [ + 'AppdevB328DAFC', + 'BranchName', + ], + }, + }, + ], + }); +}); + test('map a branch to the domain root', () => { // GIVEN const stack = new Stack(); diff --git a/packages/@aws-cdk/aws-amplify-alpha/test/integ.app-custom-domain.js.snapshot/amplifyappcustomdomainintegDefaultTestDeployAssert5F8CD1EB.assets.json b/packages/@aws-cdk/aws-amplify-alpha/test/integ.app-custom-domain.js.snapshot/amplifyappcustomdomainintegDefaultTestDeployAssert5F8CD1EB.assets.json new file mode 100644 index 0000000000000..f02a474074771 --- /dev/null +++ b/packages/@aws-cdk/aws-amplify-alpha/test/integ.app-custom-domain.js.snapshot/amplifyappcustomdomainintegDefaultTestDeployAssert5F8CD1EB.assets.json @@ -0,0 +1,19 @@ +{ + "version": "36.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "amplifyappcustomdomainintegDefaultTestDeployAssert5F8CD1EB.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-amplify-alpha/test/integ.app-custom-domain.js.snapshot/amplifyappcustomdomainintegDefaultTestDeployAssert5F8CD1EB.template.json b/packages/@aws-cdk/aws-amplify-alpha/test/integ.app-custom-domain.js.snapshot/amplifyappcustomdomainintegDefaultTestDeployAssert5F8CD1EB.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk/aws-amplify-alpha/test/integ.app-custom-domain.js.snapshot/amplifyappcustomdomainintegDefaultTestDeployAssert5F8CD1EB.template.json @@ -0,0 +1,36 @@ +{ + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-amplify-alpha/test/integ.app-custom-domain.js.snapshot/cdk-amplify-app-custom-domain.assets.json b/packages/@aws-cdk/aws-amplify-alpha/test/integ.app-custom-domain.js.snapshot/cdk-amplify-app-custom-domain.assets.json new file mode 100644 index 0000000000000..f1c3c1e152115 --- /dev/null +++ b/packages/@aws-cdk/aws-amplify-alpha/test/integ.app-custom-domain.js.snapshot/cdk-amplify-app-custom-domain.assets.json @@ -0,0 +1,19 @@ +{ + "version": "36.0.0", + "files": { + "5314d52dac3409b06902f1cf40df3d58dceb16146ad8cf66843edee0096d1d87": { + "source": { + "path": "cdk-amplify-app-custom-domain.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "5314d52dac3409b06902f1cf40df3d58dceb16146ad8cf66843edee0096d1d87.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-amplify-alpha/test/integ.app-custom-domain.js.snapshot/cdk-amplify-app-custom-domain.template.json b/packages/@aws-cdk/aws-amplify-alpha/test/integ.app-custom-domain.js.snapshot/cdk-amplify-app-custom-domain.template.json new file mode 100644 index 0000000000000..5909af114f54a --- /dev/null +++ b/packages/@aws-cdk/aws-amplify-alpha/test/integ.app-custom-domain.js.snapshot/cdk-amplify-app-custom-domain.template.json @@ -0,0 +1,210 @@ +{ + "Resources": { + "Repo02AC86CF": { + "Type": "AWS::CodeCommit::Repository", + "Properties": { + "RepositoryName": "integ-amplify-app" + } + }, + "AppRole1AF9B530": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "amplify.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "AppRoleDefaultPolicy9CADBAA1": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": "codecommit:GitPull", + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "Repo02AC86CF", + "Arn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "AppRoleDefaultPolicy9CADBAA1", + "Roles": [ + { + "Ref": "AppRole1AF9B530" + } + ] + } + }, + "AppF1B96344": { + "Type": "AWS::Amplify::App", + "Properties": { + "BasicAuthConfig": { + "EnableBasicAuth": false + }, + "IAMServiceRole": { + "Fn::GetAtt": [ + "AppRole1AF9B530", + "Arn" + ] + }, + "Name": "App", + "Platform": "WEB", + "Repository": { + "Fn::GetAtt": [ + "Repo02AC86CF", + "CloneUrlHttp" + ] + } + } + }, + "AppmainF505BAED": { + "Type": "AWS::Amplify::Branch", + "Properties": { + "AppId": { + "Fn::GetAtt": [ + "AppF1B96344", + "AppId" + ] + }, + "BranchName": "main", + "EnableAutoBuild": true, + "EnablePullRequestPreview": true + } + }, + "AppdevB328DAFC": { + "Type": "AWS::Amplify::Branch", + "Properties": { + "AppId": { + "Fn::GetAtt": [ + "AppF1B96344", + "AppId" + ] + }, + "BranchName": "dev", + "EnableAutoBuild": true, + "EnablePullRequestPreview": true + } + }, + "Appexamplecom6AF1A3AD": { + "Type": "AWS::Amplify::Domain", + "Properties": { + "AppId": { + "Fn::GetAtt": [ + "AppF1B96344", + "AppId" + ] + }, + "AutoSubDomainCreationPatterns": [ + "*", + "pr*" + ], + "AutoSubDomainIAMRole": { + "Fn::GetAtt": [ + "AppRole1AF9B530", + "Arn" + ] + }, + "CertificateSettings": { + "CertificateType": "CUSTOM", + "CustomCertificateArn": { + "Ref": "Certificate4E7ABB08" + } + }, + "DomainName": "*.example.com", + "EnableAutoSubDomain": false, + "SubDomainSettings": [ + { + "BranchName": { + "Fn::GetAtt": [ + "AppmainF505BAED", + "BranchName" + ] + }, + "Prefix": "prod" + }, + { + "BranchName": { + "Fn::GetAtt": [ + "AppdevB328DAFC", + "BranchName" + ] + }, + "Prefix": { + "Fn::GetAtt": [ + "AppdevB328DAFC", + "BranchName" + ] + } + } + ] + } + }, + "Certificate4E7ABB08": { + "Type": "AWS::CertificateManager::Certificate", + "Properties": { + "DomainName": "*.*.example.com", + "DomainValidationOptions": [ + { + "DomainName": "*.*.example.com", + "HostedZoneId": "Z23ABC4XYZL05B" + } + ], + "Tags": [ + { + "Key": "Name", + "Value": "cdk-amplify-app-custom-domain/Certificate" + } + ], + "ValidationMethod": "DNS" + } + } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-amplify-alpha/test/integ.app-custom-domain.js.snapshot/cdk.out b/packages/@aws-cdk/aws-amplify-alpha/test/integ.app-custom-domain.js.snapshot/cdk.out new file mode 100644 index 0000000000000..1f0068d32659a --- /dev/null +++ b/packages/@aws-cdk/aws-amplify-alpha/test/integ.app-custom-domain.js.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"36.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-amplify-alpha/test/integ.app-custom-domain.js.snapshot/integ.json b/packages/@aws-cdk/aws-amplify-alpha/test/integ.app-custom-domain.js.snapshot/integ.json new file mode 100644 index 0000000000000..b8c953f413ca9 --- /dev/null +++ b/packages/@aws-cdk/aws-amplify-alpha/test/integ.app-custom-domain.js.snapshot/integ.json @@ -0,0 +1,14 @@ +{ + "enableLookups": true, + "version": "36.0.0", + "testCases": { + "amplify-app-custom-domain-integ/DefaultTest": { + "stacks": [ + "cdk-amplify-app-custom-domain" + ], + "stackUpdateWorkflow": false, + "assertionStack": "amplify-app-custom-domain-integ/DefaultTest/DeployAssert", + "assertionStackName": "amplifyappcustomdomainintegDefaultTestDeployAssert5F8CD1EB" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-amplify-alpha/test/integ.app-custom-domain.js.snapshot/manifest.json b/packages/@aws-cdk/aws-amplify-alpha/test/integ.app-custom-domain.js.snapshot/manifest.json new file mode 100644 index 0000000000000..1586bbb9fed72 --- /dev/null +++ b/packages/@aws-cdk/aws-amplify-alpha/test/integ.app-custom-domain.js.snapshot/manifest.json @@ -0,0 +1,158 @@ +{ + "version": "36.0.0", + "artifacts": { + "cdk-amplify-app-custom-domain.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "cdk-amplify-app-custom-domain.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "cdk-amplify-app-custom-domain": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "cdk-amplify-app-custom-domain.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/5314d52dac3409b06902f1cf40df3d58dceb16146ad8cf66843edee0096d1d87.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "cdk-amplify-app-custom-domain.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "cdk-amplify-app-custom-domain.assets" + ], + "metadata": { + "/cdk-amplify-app-custom-domain/Repo/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "Repo02AC86CF" + } + ], + "/cdk-amplify-app-custom-domain/App/Role/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "AppRole1AF9B530" + } + ], + "/cdk-amplify-app-custom-domain/App/Role/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "AppRoleDefaultPolicy9CADBAA1" + } + ], + "/cdk-amplify-app-custom-domain/App/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "AppF1B96344" + } + ], + "/cdk-amplify-app-custom-domain/App/main/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "AppmainF505BAED" + } + ], + "/cdk-amplify-app-custom-domain/App/dev/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "AppdevB328DAFC" + } + ], + "/cdk-amplify-app-custom-domain/App/*.example.com/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "Appexamplecom6AF1A3AD" + } + ], + "/cdk-amplify-app-custom-domain/Certificate/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "Certificate4E7ABB08", + "trace": [ + "!!DESTRUCTIVE_CHANGES: WILL_REPLACE" + ] + } + ], + "/cdk-amplify-app-custom-domain/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/cdk-amplify-app-custom-domain/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "cdk-amplify-app-custom-domain" + }, + "amplifyappcustomdomainintegDefaultTestDeployAssert5F8CD1EB.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "amplifyappcustomdomainintegDefaultTestDeployAssert5F8CD1EB.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "amplifyappcustomdomainintegDefaultTestDeployAssert5F8CD1EB": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "amplifyappcustomdomainintegDefaultTestDeployAssert5F8CD1EB.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "amplifyappcustomdomainintegDefaultTestDeployAssert5F8CD1EB.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "amplifyappcustomdomainintegDefaultTestDeployAssert5F8CD1EB.assets" + ], + "metadata": { + "/amplify-app-custom-domain-integ/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/amplify-app-custom-domain-integ/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "amplify-app-custom-domain-integ/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-amplify-alpha/test/integ.app-custom-domain.js.snapshot/tree.json b/packages/@aws-cdk/aws-amplify-alpha/test/integ.app-custom-domain.js.snapshot/tree.json new file mode 100644 index 0000000000000..d91f03344d460 --- /dev/null +++ b/packages/@aws-cdk/aws-amplify-alpha/test/integ.app-custom-domain.js.snapshot/tree.json @@ -0,0 +1,433 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "cdk-amplify-app-custom-domain": { + "id": "cdk-amplify-app-custom-domain", + "path": "cdk-amplify-app-custom-domain", + "children": { + "Repo": { + "id": "Repo", + "path": "cdk-amplify-app-custom-domain/Repo", + "children": { + "Resource": { + "id": "Resource", + "path": "cdk-amplify-app-custom-domain/Repo/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::CodeCommit::Repository", + "aws:cdk:cloudformation:props": { + "repositoryName": "integ-amplify-app" + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_codecommit.CfnRepository", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_codecommit.Repository", + "version": "0.0.0" + } + }, + "App": { + "id": "App", + "path": "cdk-amplify-app-custom-domain/App", + "children": { + "Role": { + "id": "Role", + "path": "cdk-amplify-app-custom-domain/App/Role", + "children": { + "ImportRole": { + "id": "ImportRole", + "path": "cdk-amplify-app-custom-domain/App/Role/ImportRole", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "cdk-amplify-app-custom-domain/App/Role/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "amplify.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnRole", + "version": "0.0.0" + } + }, + "DefaultPolicy": { + "id": "DefaultPolicy", + "path": "cdk-amplify-app-custom-domain/App/Role/DefaultPolicy", + "children": { + "Resource": { + "id": "Resource", + "path": "cdk-amplify-app-custom-domain/App/Role/DefaultPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Policy", + "aws:cdk:cloudformation:props": { + "policyDocument": { + "Statement": [ + { + "Action": "codecommit:GitPull", + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "Repo02AC86CF", + "Arn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "policyName": "AppRoleDefaultPolicy9CADBAA1", + "roles": [ + { + "Ref": "AppRole1AF9B530" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnPolicy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Policy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Role", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "cdk-amplify-app-custom-domain/App/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Amplify::App", + "aws:cdk:cloudformation:props": { + "basicAuthConfig": { + "enableBasicAuth": false + }, + "iamServiceRole": { + "Fn::GetAtt": [ + "AppRole1AF9B530", + "Arn" + ] + }, + "name": "App", + "platform": "WEB", + "repository": { + "Fn::GetAtt": [ + "Repo02AC86CF", + "CloneUrlHttp" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_amplify.CfnApp", + "version": "0.0.0" + } + }, + "main": { + "id": "main", + "path": "cdk-amplify-app-custom-domain/App/main", + "children": { + "Resource": { + "id": "Resource", + "path": "cdk-amplify-app-custom-domain/App/main/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Amplify::Branch", + "aws:cdk:cloudformation:props": { + "appId": { + "Fn::GetAtt": [ + "AppF1B96344", + "AppId" + ] + }, + "branchName": "main", + "enableAutoBuild": true, + "enablePullRequestPreview": true + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_amplify.CfnBranch", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "dev": { + "id": "dev", + "path": "cdk-amplify-app-custom-domain/App/dev", + "children": { + "Resource": { + "id": "Resource", + "path": "cdk-amplify-app-custom-domain/App/dev/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Amplify::Branch", + "aws:cdk:cloudformation:props": { + "appId": { + "Fn::GetAtt": [ + "AppF1B96344", + "AppId" + ] + }, + "branchName": "dev", + "enableAutoBuild": true, + "enablePullRequestPreview": true + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_amplify.CfnBranch", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "*.example.com": { + "id": "*.example.com", + "path": "cdk-amplify-app-custom-domain/App/*.example.com", + "children": { + "Resource": { + "id": "Resource", + "path": "cdk-amplify-app-custom-domain/App/*.example.com/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Amplify::Domain", + "aws:cdk:cloudformation:props": { + "appId": { + "Fn::GetAtt": [ + "AppF1B96344", + "AppId" + ] + }, + "autoSubDomainCreationPatterns": [ + "*", + "pr*" + ], + "autoSubDomainIamRole": { + "Fn::GetAtt": [ + "AppRole1AF9B530", + "Arn" + ] + }, + "certificateSettings": { + "certificateType": "CUSTOM", + "customCertificateArn": { + "Ref": "Certificate4E7ABB08" + } + }, + "domainName": "*.example.com", + "enableAutoSubDomain": false, + "subDomainSettings": [ + { + "branchName": { + "Fn::GetAtt": [ + "AppmainF505BAED", + "BranchName" + ] + }, + "prefix": "prod" + }, + { + "branchName": { + "Fn::GetAtt": [ + "AppdevB328DAFC", + "BranchName" + ] + }, + "prefix": { + "Fn::GetAtt": [ + "AppdevB328DAFC", + "BranchName" + ] + } + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_amplify.CfnDomain", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "HostedZone": { + "id": "HostedZone", + "path": "cdk-amplify-app-custom-domain/HostedZone", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "Certificate": { + "id": "Certificate", + "path": "cdk-amplify-app-custom-domain/Certificate", + "children": { + "Resource": { + "id": "Resource", + "path": "cdk-amplify-app-custom-domain/Certificate/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::CertificateManager::Certificate", + "aws:cdk:cloudformation:props": { + "domainName": "*.*.example.com", + "domainValidationOptions": [ + { + "domainName": "*.*.example.com", + "hostedZoneId": "Z23ABC4XYZL05B" + } + ], + "tags": [ + { + "key": "Name", + "value": "cdk-amplify-app-custom-domain/Certificate" + } + ], + "validationMethod": "DNS" + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_certificatemanager.CfnCertificate", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_certificatemanager.Certificate", + "version": "0.0.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "cdk-amplify-app-custom-domain/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "cdk-amplify-app-custom-domain/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + }, + "amplify-app-custom-domain-integ": { + "id": "amplify-app-custom-domain-integ", + "path": "amplify-app-custom-domain-integ", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "amplify-app-custom-domain-integ/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "amplify-app-custom-domain-integ/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "amplify-app-custom-domain-integ/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "amplify-app-custom-domain-integ/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "amplify-app-custom-domain-integ/DefaultTest/DeployAssert/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests-alpha.IntegTestCase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests-alpha.IntegTest", + "version": "0.0.0" + } + }, + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.App", + "version": "0.0.0" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-amplify-alpha/test/integ.app-custom-domain.ts b/packages/@aws-cdk/aws-amplify-alpha/test/integ.app-custom-domain.ts new file mode 100644 index 0000000000000..2d38147cb0475 --- /dev/null +++ b/packages/@aws-cdk/aws-amplify-alpha/test/integ.app-custom-domain.ts @@ -0,0 +1,75 @@ +import * as acm from 'aws-cdk-lib/aws-certificatemanager'; +import * as codecommit from 'aws-cdk-lib/aws-codecommit'; +import * as route53 from 'aws-cdk-lib/aws-route53'; +import { App, Stack, StackProps } from 'aws-cdk-lib'; +import { Construct } from 'constructs'; +import * as amplify from '../lib'; +import { IntegTest } from '@aws-cdk/integ-tests-alpha'; + +interface TestStackProps extends StackProps { + hostedZoneId: string; + hostedZoneName: string; + domainName: string; +} + +class TestStack extends Stack { + constructor(scope: Construct, id: string, props: TestStackProps) { + super(scope, id, props); + + const repository = new codecommit.Repository(this, 'Repo', { + repositoryName: 'integ-amplify-app', + }); + + const app = new amplify.App(this, 'App', { + sourceCodeProvider: new amplify.CodeCommitSourceCodeProvider({ repository }), + }); + + const prodBranch = app.addBranch('main'); + const devBranch = app.addBranch('dev'); + + const hostedZone = route53.PublicHostedZone.fromHostedZoneAttributes(this, 'HostedZone', { + hostedZoneId: props.hostedZoneId, + zoneName: props.hostedZoneName, + }); + + const customCertificate = new acm.Certificate(this, 'Certificate', { + domainName: `*.${props.domainName}`, + validation: acm.CertificateValidation.fromDns(hostedZone), + }); + + const domain = app.addDomain(props.domainName, { + subDomains: [ + { + branch: prodBranch, + prefix: 'prod', + }, + ], + customCertificate, + }); + domain.mapSubDomain(devBranch); + } +} + +/** + * In order to test this you need to have a valid public hosted zone that you can use + * to request certificates for. +*/ +const hostedZoneId = process.env.CDK_INTEG_HOSTED_ZONE_ID ?? process.env.HOSTED_ZONE_ID; +if (!hostedZoneId) throw new Error('For this test you must provide your own HostedZoneId as an env var "HOSTED_ZONE_ID". See framework-integ/README.md for details.'); +const hostedZoneName = process.env.CDK_INTEG_HOSTED_ZONE_NAME ?? process.env.HOSTED_ZONE_NAME; +if (!hostedZoneName) throw new Error('For this test you must provide your own HostedZoneName as an env var "HOSTED_ZONE_NAME". See framework-integ/README.md for details.'); +const domainName = process.env.CDK_INTEG_DOMAIN_NAME ?? process.env.DOMAIN_NAME; +if (!domainName) throw new Error('For this test you must provide your own DomainName as an env var "DOMAIN_NAME". See framework-integ/README.md for details.'); + +const app = new App(); +const stack = new TestStack(app, 'cdk-amplify-app-custom-domain', { + hostedZoneId, + hostedZoneName, + domainName, +}); + +new IntegTest(app, 'amplify-app-custom-domain-integ', { + testCases: [stack], + enableLookups: true, + stackUpdateWorkflow: false, +}); From 653d74a1d735f446c9c7cfa528862e2e345a1f68 Mon Sep 17 00:00:00 2001 From: mazyu36 Date: Tue, 30 Jul 2024 22:47:53 +0900 Subject: [PATCH 2/2] Update packages/@aws-cdk/aws-amplify-alpha/README.md Co-authored-by: Luca Pizzini --- packages/@aws-cdk/aws-amplify-alpha/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@aws-cdk/aws-amplify-alpha/README.md b/packages/@aws-cdk/aws-amplify-alpha/README.md index 3b7f58db37433..d543b4090faff 100644 --- a/packages/@aws-cdk/aws-amplify-alpha/README.md +++ b/packages/@aws-cdk/aws-amplify-alpha/README.md @@ -138,7 +138,7 @@ domain.mapSubDomain(main, 'www'); domain.mapSubDomain(dev); // sub domain prefix defaults to branch name ``` -If you want to use your custom domain, set your custom certificate to `customCertificate`: +To specify a custom certificate for your custom domain use the `customCertificate` property: ```ts declare const customCertificate: acm.Certificate;