TECH
BLOG

Create a CloudFront distribution for MediaPackage using the AWS SDK

2020
12

beginning

For some reason, I had the opportunity to create a CloudFront distribution for the MediaPackage endpoint using the AWS SDK. I will leave the knowledge I gained at that time in an article as a memorandum with the source code.

The source code introduced in this article Gist It has also been uploaded with the same content.

By the way, if you want to build infrastructure with a MediaLive + MediaPackage + CloudFront configuration,CloudFormation now supports MediaPackageTherefore, I recommend using CloudFormation.

The content of this article is just due to some circumstances,It is likely to be helpful in cases where you want to link a CloudFront distribution to a MediaPackage endpoint later.

Implementation details

The content of the created source code is as follows.
The createDistributionForMediaPackage at the bottom is the function corresponding to the title of this article.

cloudfrontclientformediapackage.ts

import {CloudFront} from “aws-SDK”;
import * as url from “url”;
import {
createDistributionWithTagsResult,
getDistributionResult,
updateDistributionResult
} from “aws-sdk/clients/cloudfront”;
export class CloudFrontClientForMediaPackage {
private CloudFront: CloudFront;
constructor () {
this.cloudfront = new CloudFront ({
region: “ap-northeast-1",
apiVersion: '2020-5-31',
});
}
/**
* Used to obtain information about CloudFront distributions
* @param id The ID of your CloudFront distribution
* @return Get distribution information
*/
<GetDistributionResult>async getDistribution (id: string): Promise {
const distribution = await this.cloudFront.getDistribution ({
Id: id
}) .promise ()
return distribution;
}
/**
* Used to retrieve CloudFront distribution settings
* @param id The ID of your CloudFront distribution
* @return Get distribution settings
*/
<CloudFront.DistributionConfig>async getDistributionConfig (id: string): Promise {
const config = await this.cloudfront.getDistributionConfig ({
Id: id
}) .promise ()
return config.distributionConfig;
}
/**
* Delete a CloudFront distribution
* @param id The ID of the CloudFront distribution you want to delete
*/
async deleteDistribution (id: string) {
const distribution = await this.getDistribution (id);
await this.cloudfront.deleteDistribution ({
Id: id, ifMatch: distribution.ETag
}) .promise ()
}
/**
* Disable CloudFront distributions
* @param id The ID of the CloudFront distribution you want to disable
* @return Information about the disabled CloudFront distribution
*/
<UpdateDistributionResult>async disableDistribution (id: string): Promise {
const distribution = await this.getDistribution (id);
const config = distribution.distribution.distributionConfig;
config.enabled = false;
return await this.cloudfront.updateDistribution ({
Id: id,
ifMatch: distribution.etag,
distributionConfig: config
}) .promise ();
}
/**
* Create a CloudFront distribution for the MediaPackage endpoint
* @param id The ID to determine the CloudFront distribution
* @param MediaPackagEarn The ARN of the MediaPackage channel
* @param mediaPackageUrl URL of the mediaPackage endpoint
*/
async createDistributionForMediaPackage (
id: string,
mediaPackagEarn: string,
mediaPackageUrl: string
): Promise <CreateDistributionWithTagsResult>{
//1. Parse URL strings using the url module
const mediaPackageEndpoint = url.parse (mediaPackageUrl);
/**
2. Retrieve the FQDN from the MediaPackage endpoint URL.
Also used as the origin domain name for the CloudFront distribution described later
*/
const mediaPackageHostname = mediaPackageEndpoint.hostname;
/**
3. What is the format of the MediaPackage endpoint URL
https://<AccountID>.mediapackage. Since it <Region>is.amazonaws.com/****,
You can obtain an account ID by extracting the first part of the FQDN by splitting the string
*/
const accountId = mediaPackageHostName.split ('.') [0];
//4. Use an account ID as the origin ID for the CloudFront distribution described later
const targetOriginId = `MP-$ {accountId} `
/**
5. Instead of createDistribution, use the createDistributionWithTags function,
Create a CloudFront distribution. To use tags to link to MediaPackage.
*/
return await this.cloudfront.createDistributionWithTags ({
distributionConfigWithTags: {
Tags: {
Items: [
/**
!!!! IMPORTANT!!!!
6. I want to link to a CloudFront distribution
The channel ARN of the MediaPackage endpoint
mediapackage: defined by cloudfront_assoc.
By defining mediapackage:cloudfront_assoc,
CloudFront distributions and
MediaPackage channels can be linked.
*/
{
Key: 'mediapackage:cloudfront_assoc',
Value: MediaPackagEarn
},
{
Key: 'Id',
Value: id
},
{
Key: 'Product',
Value: 'product'
},
{
Key: 'Stage',
Value: 'dev'
}
]
},
distributionConfig: {
callerReference: new Date () .toIsoString (),
Comment: `Managed by MediaPackage - $ {id} `,
Enabled: true,
/**
7. Set up two origins for your CloudFront distribution.
One is for the MediaPackage endpoint, and
The other one is for the MediaPacakge service.
Basically, we use the origin for the MediaPackage endpoint.
The origin directed at the time of exception is for the MediaPacakge service.
*/
Origins: {
Quantity: 2,
Items: [
{
domainName: mediaPackageHostName,
Id: targetOriginId,
customOriginConfig: {
HttpPort: 80,
HttpsPort: 443,
originProtocolPolicy: 'match-viewer'
}
},
{
domainName: 'mediapackage.amazonaws.com',
Id: “temp_origin_id/channel”,
customOriginConfig: {
HttpPort: 80,
HttpsPort: 443,
originProtocolPolicy: 'match-viewer'
}
}
]
},
/**
8. When none of the CacheBehaviors apply
Defines cache behavior.
MediaPackage uses start, m, and end as query strings when using the time shift display function, etc.
Therefore, these strings are included in whiteListedNames and true is specified as queryString.
Since behavior caught in defaultCacheBehavior is treated as an exception,
Set the origin to be used from the MediaPackage service.
*/
defaultCacheBehavior: {
forwardedValues: {
cookies: {
Forward: 'whitelist',
whiteListedNames: {
Quantity: 3,
Items: [
'end', 'm', 'start'
]
}
},
queryString: true,
headers: {
Quantity: 0
},
queryStringCacheKeys: {
Quantity: 0
}
},
minTTL: 6,
targetOriginId: “temp_origin_id/channel”,
trustedSigners: {
Enabled: false,
Quantity: 0
},
viewerProtocolPolicy: 'redirect-to-https',
allowedMethods: {
Items: [
'GET', 'HEAD'
],
Quantity: 2,
},
maxTTL: 60
},
/**
9. Set the TTL to 1sec for all CloudFront error codes.
If the MediaPackage error cache persists for a long time,
During that time, even if it was successfully distributed on MediaPackage,
This is because it will be in an unrecoverable state.
*/
customErrorResponses: {
Quantity: 10,
Items: [
{
errorCode: 400,
errorCachingMinttl: 1
}, {
errorCode: 403,
errorCachingMinttl: 1
}, {
errorCode: 404,
errorCachingMinttl: 1
}, {
errorCode: 405,
errorCachingMinttl: 1
}, {
errorCode: 414,
errorCachingMinttl: 1
}, {
errorCode: 416,
errorCachingMinttl: 1
}, {
errorCode: 500,
errorCachingMinttl: 1
}, {
errorCode: 501,
errorCachingMinttl: 1
}, {
errorCode: 502,
errorCachingMinttl: 1
}, {
errorCode: 503,
errorCachingMinttl: 1
}
]
},
/**
10. We define two cache behaviors for CloudFront distributions.
The details of each setting are basically similar to those defined in defaultCacheBehavior.
However, the origin to be used uses the one aimed at the MediaPackage endpoint.
One is used when streaming on Microsoft Smooth Streaming
Smooth Streaming is set to true for index.ism.
The other one other than Microsoft Smooth Streaming above
It applies to streaming, which applies to everything.
*/
cacheBehaviors: {
Quantity: 2,
Items: [{
minTTL: 6,
pathPattern: 'index.ism/*',
targetOriginId: targetOriginId,
viewerProtocolPolicy: 'redirect-to-https',
allowedMethods: {
Items: [
'GET', 'HEAD'
],
Quantity: 2,
},
forwardedValues: {
cookies: {
Forward: 'whitelist',
whiteListedNames: {
Quantity: 3,
Items: [
'end', 'm', 'start'
]
}
},
queryString: true,
headers: {
Quantity: 0
},
queryStringCacheKeys: {
Quantity: 0
},
},
SmoothStreaming: true
}, {
minTTL: 6,
pathPattern: '*',
targetOriginId: targetOriginId,
viewerProtocolPolicy: 'redirect-to-https',
allowedMethods: {
Items: [
'GET', 'HEAD'
],
Quantity: 2,
},
forwardedValues: {
cookies: {
Forward: 'whitelist',
whiteListedNames: {
Quantity: 3,
Items: [
'end', 'm', 'start'
]
}
},
queryString: true,
headers: {
Quantity: 0
},
queryStringCacheKeys: {
Quantity: 0
},
}
}]
},
priceClass: 'priceClass_all'
}
}
}) .promise ()
}
}

Distributions created with createDistributionForMediaPackage areInstructions described on the official page It's equivalent to the CloudFront distribution you created in

I wrote a detailed explanation in an inline comment, but I'll add a few additional explanations for now.

About Quantity that comes up everywhere

Enter the number of items specified in Items for Quantity. For example, since Headers and queryStringCacheKeys don't specify anything in Items, specify 0 for Quantity.

However, 2 and 3, which are the number of items specified in Items, are entered into Quantity in allowedMethods and whiteListedNames.If the quantity does not match the number of items in Items, an error will occur, so be careful.

mediapackage: meaning of defining cloudfront_assoc

In the CloudFront distribution tag mediapackage:By specifying the MediaPackage channel ARN linked with cloudfront_assoc, you can view the linked CloudFront distribution information from the MediaPackage console.

When you move to the endpoint details page of the MediaPackage channel linked to the trial,
You should be able to see a screen like the one below.

mediapackage:cloudfront_assoc で紐付いた CloudFront ディストリビューションが確認できる


You can check CloudFront distributions linked to mediapackage: cloudfront_assoc

Note that other tags such as Id, Product, and Stage are defined in the source code in this article, but since they have nothing to do with MediaPackage, there is no problem deleting them.

Points to note when running UpdateDistribution

This isn't directly related to the content of this article, but I'm sobbly addicted to it, so I'll post it.

CloudFront requires more parameters for UpdateDistribution than for createDistribution. Comparison chart on the AWS official pageIt's as it is in.

Therefore, even though I just want to update some of the settings with updateDistribution, I need to specify so many parameters, which is very troublesome. For example, just enable/disable a CloudFront distribution would require you to specify close to 30 parameters.

How to eliminate the trouble of entering the above It was easy to create updateDistribution parameters by modifying existing distribution information obtained with getDistribution.

If you refer to the content of the current source code, DisableDistribution is applicable.

//1. Run getDistribution to get CloudFront distribution information
const distribution = await this.getDistribution (id);
//2. Retrieve the CloudFront distribution settings
const config = distribution.distribution.distributionConfig;
//3. Modify the Enabled/Disabled option for CloudFront distributions
config.enabled = false;
//4. 3. Update Distribution to reflect the changes made in the CloudFront distribution
return await this.cloudfront.updateDistribution ({
Id: id,
ifMatch: distribution.etag,
distributionConfig: config
}) .promise ();

concluding

The content is niche, so I don't know if I'll use the content of this article in the future, but I've left the knowledge I've gained as an article. I hope it will be helpful for those who have found it necessary to do something similar.

Reference links

RELATED PROJECT

No items found.