Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

既存の ACM 証明書を指定してカスタムドメインを利用可能にする #627

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 24 additions & 2 deletions docs/DEPLOY_OPTION.md
Original file line number Diff line number Diff line change
Expand Up @@ -678,8 +678,6 @@ PDF や Excel などのファイルをアップロードしてテキストを抽

Web サイトの URL としてカスタムドメインを使用することができます。同一 AWS アカウントの Route53 にパブリックホストゾーンが作成済みであることが必要です。パブリックホストゾーンについてはこちらをご参照ください: [パブリックホストゾーンの使用 - Amazon Route 53](https://docs.aws.amazon.com/ja_jp/Route53/latest/DeveloperGuide/AboutHZWorkingWith.html)

同一 AWS アカウントにパブリックホストゾーンを持っていない場合は、AWS ACM による SSL 証明書の検証時に手動で DNS レコードを追加する方法や、Eメール検証を行う方法もあります。これらの方法を利用する場合は、CDK のドキュメントを参照してカスタマイズしてください: [aws-cdk-lib.aws_certificatemanager module · AWS CDK](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_certificatemanager-readme.html)

cdk.json には以下の値を設定します。

- `hostName` ... Web サイトのホスト名です。A レコードは CDK によって作成されます。事前に作成する必要はありません
Expand All @@ -698,6 +696,30 @@ cdk.json には以下の値を設定します。
}
```

パブリックホストゾーンを別アカウントで管理している等の環境では、作成済みの AWS ACM 証明書を使用することもできます。

cdk.json には以下の値を設定します。

- `hostName` ... Web サイトのホスト名です。**A レコードは CDK によって自動で追加されません。** 別アカウントのパブリックホステッドゾーンに手動で追加してください
- `domainName` ... 別アカウントに作成されたパブリックホストゾーンのドメイン名です
- `certificateArn` ... 事前に作成したバージニア北部リージョンの AWS ACM 証明書 ARN です

**[packages/cdk/cdk.json](/packages/cdk/cdk.json) を編集**

```json
{
"context": {
"hostName": "genai",
"domainName": "example.com",
"certificateArn": "arn:aws:acm:us-east-1:123456789012:certificate/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}
}
```

`hostedZoneId` と `certificateArn` は同時に指定できません。

その他、AWS ACM による SSL 証明書の検証時に手動で DNS レコードを追加する方法や、Eメール検証を行う方法もあります。これらの方法を利用する場合は、CDK のドキュメントを参照してカスタマイズしてください: [aws-cdk-lib.aws_certificatemanager module · AWS CDK](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_certificatemanager-readme.html)

## 別 AWS アカウントの Bedrock を利用したい場合

別 AWS アカウントの Bedrock を利用することができます。前提条件として、GenU の初回デプロイは完了済みとします。
Expand Down
36 changes: 27 additions & 9 deletions packages/cdk/bin/generative-ai-use-cases.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,17 +56,34 @@ if (
) {
throw new Error('hostedZoneId must be a string');
}

// check hostName, domainName hostedZoneId are all set or none of them
const certificateArn = app.node.tryGetContext('certificateArn');
if (
!(
(hostName && domainName && hostedZoneId) ||
(!hostName && !domainName && !hostedZoneId)
)
typeof certificateArn != 'undefined' &&
typeof certificateArn != 'string' &&
certificateArn != null
) {
throw new Error(
'hostName, domainName and hostedZoneId must be set or none of them'
);
throw new Error('certificateArn must be a string');
}

// check custom domain settings
if (certificateArn) {
// When certificateArn is provided, hostName and domainName must be set, but hostedZoneId must not be set
if (!hostName || !domainName) {
throw new Error('When certificateArn is provided, both hostName and domainName must be set');
}
if (hostedZoneId) {
throw new Error('When certificateArn is provided, hostedZoneId must not be set');
}
} else {
// When certificateArn is not provided, either all of hostName, domainName, and hostedZoneId must be set, or none of them
if (
!(
(hostName && domainName && hostedZoneId) ||
(!hostName && !domainName && !hostedZoneId)
)
) {
throw new Error('When certificateArn is not provided, either all of hostName, domainName, and hostedZoneId must be set, or none of them');
}
}

let cloudFrontWafStack: CloudFrontWafStack | undefined;
Expand All @@ -90,6 +107,7 @@ if (
hostName,
domainName,
hostedZoneId,
certificateArn,
crossRegionReferences: true,
});
}
Expand Down
1 change: 1 addition & 0 deletions packages/cdk/cdk.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
"hostName": null,
"domainName": null,
"hostedZoneId": null,
"certificateArn": null,
"dashboard": false,
"anonymousUsageTracking": true,
"recognizeFileEnabled": false,
Expand Down
10 changes: 7 additions & 3 deletions packages/cdk/lib/cloud-front-waf-stack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ interface CloudFrontWafStackProps extends StackProps {
hostName?: string;
domainName?: string;
hostedZoneId?: string;
certificateArn?: string;
}

export class CloudFrontWafStack extends Stack {
Expand Down Expand Up @@ -44,7 +45,11 @@ export class CloudFrontWafStack extends Stack {
this.webAcl = webAcl;
}

if (props.hostName && props.domainName && props.hostedZoneId) {
if (props.certificateArn) {
// 既存の証明書を使用
this.cert = Certificate.fromCertificateArn(this, 'ExistingCert', props.certificateArn);
} else if (props.hostName && props.domainName && props.hostedZoneId) {
// ホスト名、ドメイン名、ホストゾーンIDがすべて提供された場合のみ、新しい証明書を作成
const hostedZone = HostedZone.fromHostedZoneAttributes(
this,
'HostedZone',
Expand All @@ -53,11 +58,10 @@ export class CloudFrontWafStack extends Stack {
zoneName: props.domainName,
}
);
const cert = new Certificate(this, 'Cert', {
this.cert = new Certificate(this, 'Cert', {
domainName: `${props.hostName}.${props.domainName}`,
validation: CertificateValidation.fromDns(hostedZone),
});
this.cert = cert;
}
}
}
47 changes: 23 additions & 24 deletions packages/cdk/lib/construct/web.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,7 @@ export class Web extends Construct {
if (
props.cert &&
props.hostName &&
props.domainName &&
props.hostedZoneId
props.domainName
) {
cloudFrontToS3Props.cloudFrontDistributionProps.certificate = props.cert;
cloudFrontToS3Props.cloudFrontDistributionProps.domainNames = [
Expand All @@ -93,28 +92,28 @@ export class Web extends Construct {
cloudFrontToS3Props
);

if (
props.cert &&
props.hostName &&
props.domainName &&
props.hostedZoneId
) {
// DNS record for custom domain
const hostedZone = HostedZone.fromHostedZoneAttributes(
this,
'HostedZone',
{
hostedZoneId: props.hostedZoneId,
zoneName: props.domainName,
}
);
new ARecord(this, 'ARecord', {
zone: hostedZone,
recordName: props.hostName,
target: RecordTarget.fromAlias(
new CloudFrontTarget(cloudFrontWebDistribution)
),
});
if (props.hostName && props.domainName) {
// DNS records will be created only if hostedZoneId is provided.
if (props.hostedZoneId) {
// DNS record for custom domain
const hostedZone = HostedZone.fromHostedZoneAttributes(
this,
'HostedZone',
{
hostedZoneId: props.hostedZoneId,
zoneName: props.domainName,
}
);
new ARecord(this, 'ARecord', {
zone: hostedZone,
recordName: props.hostName,
target: RecordTarget.fromAlias(
new CloudFrontTarget(cloudFrontWebDistribution)
),
});
} else {
console.warn('hostedZoneId not provided. DNS record will not be created or deleted automatically.');
}
}

if (props.webAclId) {
Expand Down