Skip to content
Closed
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
290 changes: 290 additions & 0 deletions packages/aws-cdk-lib/aws-cloudfront/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,296 @@ new cloudfront.Distribution(this, 'myDist', {
defaultBehavior: { origin: new origins.HttpOrigin('www.example.com') },
});
```
### CloudFront SaaS Manager resources

#### Multi-tenant distribution and tenant providing ACM certificates
You can use Cloudfront to build multi-tenant distributions to house applications.

To create a multi-tenant distribution w/parameters, create a Distribution construct, and then update DistributionConfig in the CfnDistribution to use connectionMode: "tenant-only":
```ts
// Create the simple Origin
const myBucket = new s3.Bucket(this, 'myBucket');
const s3Origin = origins.S3BucketOrigin.withOriginAccessControl(myBucket, {
originAccessLevels: [cloudfront.AccessLevel.READ, cloudfront.AccessLevel.LIST],
});

// Create the Distribution construct
const myMultiTenantDistribution = new cloudfront.Distribution(this, 'distribution', {
defaultBehavior: {
origin: s3Origin,
},
defaultRootObject: 'index.html', // recommended to specify
});

// Access the underlying L1 CfnDistribution to configure SaaS Manager properties which are not yet available in the L2 Distribution construct
const cfnDistribution = myMultiTenantDistribution.node.defaultChild as cloudfront.CfnDistribution;

const defaultCacheBehavior: cloudfront.DefaultCacheBehaviorProperty = {
targetOriginId: myBucket.bucketArn,
viewerProtocolPolicy: 'allow-all',
compress: false,
allowedMethods: ['GET', 'HEAD'],
cachePolicyId: cloudfront.CachePolicy.CACHING_OPTIMIZED.cachePolicyId
};
// Create the updated distributionConfig
const distributionConfig: cloudfront.DistributionConfigProperty = {
defaultCacheBehavior: defaultCacheBehavior,
enabled: true,
// the properties below are optional
connectionMode: 'tenant-only',
origins: [
{
id: myBucket.bucketArn,
domainName: myBucket.bucketDomainName,
s3OriginConfig: {},
originPath: "/{{tenantName}}"
},
],
tenantConfig: {
parameterDefinitions: [
{
definition: {
stringSchema: {
required: false,
// the properties below are optional
comment: 'tenantName',
defaultValue: 'root',
},
},
name: 'tenantName',
},
],
},
};

// Override the distribution configuration to enable multi-tenancy.
cfnDistribution.distributionConfig = distributionConfig;
```

Create a distribution tenant using an existing ACM certificate
```ts
const cfnDistributionTenant = new cloudfront.CfnDistributionTenant(this, 'distribution-tenant', {
distributionId: myMultiTenantDistribution.distributionId,
domains: ['my-tenant.my.domain.com'],
name: 'my-tenant',
enabled: true,
parameters: [ // Override the default 'tenantName' parameter (root) defined in the multi-tenant distribution.
{
name: 'tenantName',
value: 'app',
},
],
customizations: {
certificate: {
arn: 'REPLACE_WITH_ARN', // Certificate must be in us-east-1 region and cover 'my-tenant.my.domain.com'
},
},
});
```

#### Multi-tenant distribution and tenant with CloudFront-hosted certificate
A distribution tenant with CloudFront-hosted domain validation is useful if you don't currently have traffic to the domain.

Start by creating a parent multi-tenant distribution
```ts
// Create the simple Origin
const myBucket = new s3.Bucket(this, 'myBucket');
const s3Origin = origins.S3BucketOrigin.withOriginAccessControl(myBucket, {
originAccessLevels: [cloudfront.AccessLevel.READ, cloudfront.AccessLevel.LIST],
});

// Create the Distribution construct
const myMultiTenantDistribution = new cloudfront.Distribution(this, 'cf-hosted-distribution', {
defaultBehavior: {
origin: s3Origin,
},
defaultRootObject: 'index.html', // recommended to specify
});

// Access the underlying L1 CfnDistribution to configure SaaS Manager properties which are not yet available in the L2 Distribution construct
const cfnDistribution = myMultiTenantDistribution.node.defaultChild as cloudfront.CfnDistribution;

const defaultCacheBehavior: cloudfront.DefaultCacheBehaviorProperty = {
targetOriginId: myBucket.bucketArn,
viewerProtocolPolicy: 'allow-all',
compress: false,
allowedMethods: ['GET', 'HEAD'],
cachePolicyId: cloudfront.CachePolicy.CACHING_OPTIMIZED.cachePolicyId
};
// Create the updated distributionConfig
const distributionConfig: cloudfront.DistributionConfigProperty = {
defaultCacheBehavior: defaultCacheBehavior,
enabled: true,
// the properties below are optional
connectionMode: 'tenant-only',
origins: [
{
id: myBucket.bucketArn,
domainName: myBucket.bucketDomainName,
s3OriginConfig: {},
originPath: "/{{tenantName}}"
},
],
tenantConfig: {
parameterDefinitions: [
{
definition: {
stringSchema: {
required: false,
// the properties below are optional
comment: 'tenantName',
defaultValue: 'root',
},
},
name: 'tenantName',
},
],
},
};

// Override the distribution configuration to enable multi-tenancy.
cfnDistribution.distributionConfig = distributionConfig;
```

Create a connection group and a cname record in an existing hosted zone to validate domain ownership
```ts
const connectionGroup = new cloudfront.CfnConnectionGroup(this, 'cf-hosted-connection-group', {
enabled: true,
ipv6Enabled: true,
name: 'my-connection-group',
});

// Import the existing hosted zone info, replacing with your hostedZoneId and zoneName
const hostedZoneId = 'YOUR_HOSTED_ZONE_ID';
const zoneName = 'my.domain.com';
const hostedZone = HostedZone.fromHostedZoneAttributes(this, 'hosted-zone', {
hostedZoneId,
zoneName,
});

const record = new CnameRecord(this, 'cname-record', {
domainName: connectionGroup.attrRoutingEndpoint,
zone: hostedZone,
recordName: 'cf-hosted-tenant.my.domain.com',
});
```

Create the cloudfront-hosted tenant, passing in the previously created connection group
```ts
const cloudfrontHostedTenant = new cloudfront.CfnDistributionTenant(this, 'cf-hosted-tenant', {
distributionId: myMultiTenantDistribution.distributionId,
name: 'cf-hosted-tenant',
domains: ['cf-hosted-tenant.my.domain.com'],
connectionGroupId: connectionGroup.attrId,
enabled: true,
managedCertificateRequest: {
validationTokenHost: 'cloudfront'
},
});
```

#### Multi-tenant distribution and tenant with self-hosted certificate
A tenant with self-hosted domain validation is useful if you already have traffic to the domain and can't tolerate downtime during migration to multi-tenant architecture.

The tenant will be created, and the managed certificate will be awaiting validation of domain ownership. You can then validate domain ownership via http redirect or token file upload. [More details here](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/managed-cloudfront-certificates.html#complete-domain-ownership)

Traffic won't be migrated until you update your hosted zone to point the tenant domain to the CloudFront RoutingEndpoint.

Start by creating a parent multi-tenant distribution
```ts
// Create the simple Origin
const myBucket = new s3.Bucket(this, 'myBucket');
const s3Origin = origins.S3BucketOrigin.withOriginAccessControl(myBucket, {
originAccessLevels: [cloudfront.AccessLevel.READ, cloudfront.AccessLevel.LIST],
});

// Create the Distribution construct
const myMultiTenantDistribution = new cloudfront.Distribution(this, 'cf-hosted-distribution', {
defaultBehavior: {
origin: s3Origin,
},
defaultRootObject: 'index.html', // recommended to specify
});

// Access the underlying L1 CfnDistribution to configure SaaS Manager properties which are not yet available in the L2 Distribution construct
const cfnDistribution = myMultiTenantDistribution.node.defaultChild as cloudfront.CfnDistribution;

const defaultCacheBehavior: cloudfront.DefaultCacheBehaviorProperty = {
targetOriginId: myBucket.bucketArn,
viewerProtocolPolicy: 'allow-all',
compress: false,
allowedMethods: ['GET', 'HEAD'],
cachePolicyId: cloudfront.CachePolicy.CACHING_OPTIMIZED.cachePolicyId
};
// Create the updated distributionConfig
const distributionConfig: cloudfront.DistributionConfigProperty = {
defaultCacheBehavior: defaultCacheBehavior,
enabled: true,
// the properties below are optional
connectionMode: 'tenant-only',
origins: [
{
id: myBucket.bucketArn,
domainName: myBucket.bucketDomainName,
s3OriginConfig: {},
originPath: "/{{tenantName}}"
},
],
tenantConfig: {
parameterDefinitions: [
{
definition: {
stringSchema: {
required: false,
// the properties below are optional
comment: 'tenantName',
defaultValue: 'root',
},
},
name: 'tenantName',
},
],
},
};

// Override the distribution configuration to enable multi-tenancy.
cfnDistribution.distributionConfig = distributionConfig;
```

Create a connection group so we have access to the RoutingEndpoint associated with the tenant we are about to create
```ts
const connectionGroup = new cloudfront.CfnConnectionGroup(this, 'self-hosted-connection-group', {
enabled: true,
ipv6Enabled: true,
name: 'self-hosted-connection-group',
});
```

Create a distribution tenant with a self-hosted domain.
```ts
const selfHostedTenant = new cloudfront.CfnDistributionTenant(this, 'self-hosted-tenant', {
distributionId: myMultiTenantDistribution.distributionId,
connectionGroupId: connectionGroup.attrId,
name: 'self-hosted-tenant',
domains: ['self-hosted-tenant.my.domain.com'],
enabled: true,
managedCertificateRequest: {
primaryDomainName: 'self-hosted-tenant.my.domain.com',
validationTokenHost: 'self-hosted',
},
});

// Export the RoutingEndpoint, skip this step if you'd prefer to fetch it from the CloudFront console or via Cloudfront.ListConnectionGroups API
new cdk.CfnOutput(this, 'RoutingEndpoint', {
value: connectionGroup.attrRoutingEndpoint,
description: 'CloudFront Routing Endpoint to be added to my hosted zone CNAME records',
});
```
After this self-hosted tenant is created, [follow the steps here](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/managed-cloudfront-certificates.html#complete-domain-ownership) to complete domain setup.

Validate domain ownership using the section "I have existing traffic"

Then, when you are ready to accept traffic, follow the steps [here](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/managed-cloudfront-certificates.html#point-domains-to-cloudfront) using the RoutingEndpoint from above

### VPC origins

Expand Down
Loading