@aws-cdk/aws-cloudfront
Version:
The CDK Construct Library for AWS::CloudFront
519 lines • 97.5 kB
JavaScript
"use strict";
var _a, _b;
Object.defineProperty(exports, "__esModule", { value: true });
exports.CloudFrontWebDistribution = exports.ViewerCertificate = exports.CloudFrontAllowedCachedMethods = exports.CloudFrontAllowedMethods = exports.OriginSslPolicy = exports.FailoverStatusCode = void 0;
const jsiiDeprecationWarnings = require("../.warnings.jsii.js");
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
const certificatemanager = require("@aws-cdk/aws-certificatemanager");
const iam = require("@aws-cdk/aws-iam");
const s3 = require("@aws-cdk/aws-s3");
const cdk = require("@aws-cdk/core");
const cloudfront_generated_1 = require("./cloudfront.generated");
const distribution_1 = require("./distribution");
/**
* HTTP status code to failover to second origin
*/
var FailoverStatusCode;
(function (FailoverStatusCode) {
/**
* Forbidden (403)
*/
FailoverStatusCode[FailoverStatusCode["FORBIDDEN"] = 403] = "FORBIDDEN";
/**
* Not found (404)
*/
FailoverStatusCode[FailoverStatusCode["NOT_FOUND"] = 404] = "NOT_FOUND";
/**
* Internal Server Error (500)
*/
FailoverStatusCode[FailoverStatusCode["INTERNAL_SERVER_ERROR"] = 500] = "INTERNAL_SERVER_ERROR";
/**
* Bad Gateway (502)
*/
FailoverStatusCode[FailoverStatusCode["BAD_GATEWAY"] = 502] = "BAD_GATEWAY";
/**
* Service Unavailable (503)
*/
FailoverStatusCode[FailoverStatusCode["SERVICE_UNAVAILABLE"] = 503] = "SERVICE_UNAVAILABLE";
/**
* Gateway Timeout (504)
*/
FailoverStatusCode[FailoverStatusCode["GATEWAY_TIMEOUT"] = 504] = "GATEWAY_TIMEOUT";
})(FailoverStatusCode = exports.FailoverStatusCode || (exports.FailoverStatusCode = {}));
var OriginSslPolicy;
(function (OriginSslPolicy) {
OriginSslPolicy["SSL_V3"] = "SSLv3";
OriginSslPolicy["TLS_V1"] = "TLSv1";
OriginSslPolicy["TLS_V1_1"] = "TLSv1.1";
OriginSslPolicy["TLS_V1_2"] = "TLSv1.2";
})(OriginSslPolicy = exports.OriginSslPolicy || (exports.OriginSslPolicy = {}));
/**
* An enum for the supported methods to a CloudFront distribution.
*/
var CloudFrontAllowedMethods;
(function (CloudFrontAllowedMethods) {
CloudFrontAllowedMethods["GET_HEAD"] = "GH";
CloudFrontAllowedMethods["GET_HEAD_OPTIONS"] = "GHO";
CloudFrontAllowedMethods["ALL"] = "ALL";
})(CloudFrontAllowedMethods = exports.CloudFrontAllowedMethods || (exports.CloudFrontAllowedMethods = {}));
/**
* Enums for the methods CloudFront can cache.
*/
var CloudFrontAllowedCachedMethods;
(function (CloudFrontAllowedCachedMethods) {
CloudFrontAllowedCachedMethods["GET_HEAD"] = "GH";
CloudFrontAllowedCachedMethods["GET_HEAD_OPTIONS"] = "GHO";
})(CloudFrontAllowedCachedMethods = exports.CloudFrontAllowedCachedMethods || (exports.CloudFrontAllowedCachedMethods = {}));
/**
* Viewer certificate configuration class
*/
class ViewerCertificate {
constructor(props, aliases = []) {
this.props = props;
this.aliases = aliases;
}
/**
* Generate an AWS Certificate Manager (ACM) viewer certificate configuration
*
* @param certificate AWS Certificate Manager (ACM) certificate.
* Your certificate must be located in the us-east-1 (US East (N. Virginia)) region to be accessed by CloudFront
* @param options certificate configuration options
*/
static fromAcmCertificate(certificate, options = {}) {
try {
jsiiDeprecationWarnings._aws_cdk_aws_cloudfront_ViewerCertificateOptions(options);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, this.fromAcmCertificate);
}
throw error;
}
const { sslMethod: sslSupportMethod = distribution_1.SSLMethod.SNI, securityPolicy: minimumProtocolVersion, aliases, } = options;
return new ViewerCertificate({
acmCertificateArn: certificate.certificateArn, sslSupportMethod, minimumProtocolVersion,
}, aliases);
}
/**
* Generate an IAM viewer certificate configuration
*
* @param iamCertificateId Identifier of the IAM certificate
* @param options certificate configuration options
*/
static fromIamCertificate(iamCertificateId, options = {}) {
try {
jsiiDeprecationWarnings._aws_cdk_aws_cloudfront_ViewerCertificateOptions(options);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, this.fromIamCertificate);
}
throw error;
}
const { sslMethod: sslSupportMethod = distribution_1.SSLMethod.SNI, securityPolicy: minimumProtocolVersion, aliases, } = options;
return new ViewerCertificate({
iamCertificateId, sslSupportMethod, minimumProtocolVersion,
}, aliases);
}
/**
* Generate a viewer certifcate configuration using
* the CloudFront default certificate (e.g. d111111abcdef8.cloudfront.net)
* and a {@link SecurityPolicyProtocol.TLS_V1} security policy.
*
* @param aliases Alternative CNAME aliases
* You also must create a CNAME record with your DNS service to route queries
*/
static fromCloudFrontDefaultCertificate(...aliases) {
return new ViewerCertificate({ cloudFrontDefaultCertificate: true }, aliases);
}
}
exports.ViewerCertificate = ViewerCertificate;
_a = JSII_RTTI_SYMBOL_1;
ViewerCertificate[_a] = { fqn: "@aws-cdk/aws-cloudfront.ViewerCertificate", version: "1.204.0" };
/**
* Amazon CloudFront is a global content delivery network (CDN) service that securely delivers data, videos,
* applications, and APIs to your viewers with low latency and high transfer speeds.
* CloudFront fronts user provided content and caches it at edge locations across the world.
*
* Here's how you can use this construct:
*
* ```ts
* const sourceBucket = new s3.Bucket(this, 'Bucket');
*
* const distribution = new cloudfront.CloudFrontWebDistribution(this, 'MyDistribution', {
* originConfigs: [
* {
* s3OriginSource: {
* s3BucketSource: sourceBucket,
* },
* behaviors : [ {isDefaultBehavior: true}],
* },
* ],
* });
* ```
*
* This will create a CloudFront distribution that uses your S3Bucket as it's origin.
*
* You can customize the distribution using additional properties from the CloudFrontWebDistributionProps interface.
*
* @resource AWS::CloudFront::Distribution
*/
class CloudFrontWebDistribution extends cdk.Resource {
constructor(scope, id, props) {
super(scope, id);
/**
* Maps our methods to the string arrays they are
*/
this.METHOD_LOOKUP_MAP = {
GH: ['GET', 'HEAD'],
GHO: ['GET', 'HEAD', 'OPTIONS'],
ALL: ['DELETE', 'GET', 'HEAD', 'OPTIONS', 'PATCH', 'POST', 'PUT'],
};
/**
* Maps for which SecurityPolicyProtocol are available to which SSLMethods
*/
this.VALID_SSL_PROTOCOLS = {
[distribution_1.SSLMethod.SNI]: [
distribution_1.SecurityPolicyProtocol.TLS_V1, distribution_1.SecurityPolicyProtocol.TLS_V1_1_2016,
distribution_1.SecurityPolicyProtocol.TLS_V1_2016, distribution_1.SecurityPolicyProtocol.TLS_V1_2_2018,
distribution_1.SecurityPolicyProtocol.TLS_V1_2_2019, distribution_1.SecurityPolicyProtocol.TLS_V1_2_2021,
],
[distribution_1.SSLMethod.VIP]: [distribution_1.SecurityPolicyProtocol.SSL_V3, distribution_1.SecurityPolicyProtocol.TLS_V1],
};
try {
jsiiDeprecationWarnings._aws_cdk_aws_cloudfront_CloudFrontWebDistributionProps(props);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, CloudFrontWebDistribution);
}
throw error;
}
// Comments have an undocumented limit of 128 characters
const trimmedComment = props.comment && props.comment.length > 128
? `${props.comment.slice(0, 128 - 3)}...`
: props.comment;
const behaviors = [];
const origins = [];
const originGroups = [];
let originIndex = 1;
for (const originConfig of props.originConfigs) {
let originId = `origin${originIndex}`;
const originProperty = this.toOriginProperty(originConfig, originId);
if (originConfig.failoverCustomOriginSource || originConfig.failoverS3OriginSource) {
const originSecondaryId = `originSecondary${originIndex}`;
const originSecondaryProperty = this.toOriginProperty({
s3OriginSource: originConfig.failoverS3OriginSource,
customOriginSource: originConfig.failoverCustomOriginSource,
originPath: originConfig.originPath,
originHeaders: originConfig.originHeaders,
originShieldRegion: originConfig.originShieldRegion,
}, originSecondaryId);
const originGroupsId = `OriginGroup${originIndex}`;
const failoverCodes = originConfig.failoverCriteriaStatusCodes ?? [500, 502, 503, 504];
originGroups.push({
id: originGroupsId,
members: {
items: [{ originId }, { originId: originSecondaryId }],
quantity: 2,
},
failoverCriteria: {
statusCodes: {
items: failoverCodes,
quantity: failoverCodes.length,
},
},
});
originId = originGroupsId;
origins.push(originSecondaryProperty);
}
for (const behavior of originConfig.behaviors) {
behaviors.push({ ...behavior, targetOriginId: originId });
}
origins.push(originProperty);
originIndex++;
}
origins.forEach(origin => {
if (!origin.s3OriginConfig && !origin.customOriginConfig) {
throw new Error(`Origin ${origin.domainName} is missing either S3OriginConfig or CustomOriginConfig. At least 1 must be specified.`);
}
});
const originGroupsDistConfig = originGroups.length > 0
? {
items: originGroups,
quantity: originGroups.length,
}
: undefined;
const defaultBehaviors = behaviors.filter(behavior => behavior.isDefaultBehavior);
if (defaultBehaviors.length !== 1) {
throw new Error('There can only be one default behavior across all sources. [ One default behavior per distribution ].');
}
const otherBehaviors = [];
for (const behavior of behaviors.filter(b => !b.isDefaultBehavior)) {
if (!behavior.pathPattern) {
throw new Error('pathPattern is required for all non-default behaviors');
}
otherBehaviors.push(this.toBehavior(behavior, props.viewerProtocolPolicy));
}
let distributionConfig = {
comment: trimmedComment,
enabled: props.enabled ?? true,
defaultRootObject: props.defaultRootObject ?? 'index.html',
httpVersion: props.httpVersion || distribution_1.HttpVersion.HTTP2,
priceClass: props.priceClass || distribution_1.PriceClass.PRICE_CLASS_100,
ipv6Enabled: props.enableIpV6 ?? true,
// eslint-disable-next-line max-len
customErrorResponses: props.errorConfigurations,
webAclId: props.webACLId,
origins,
originGroups: originGroupsDistConfig,
defaultCacheBehavior: this.toBehavior(defaultBehaviors[0], props.viewerProtocolPolicy),
cacheBehaviors: otherBehaviors.length > 0 ? otherBehaviors : undefined,
};
if (props.aliasConfiguration && props.viewerCertificate) {
throw new Error([
'You cannot set both aliasConfiguration and viewerCertificate properties.',
'Please only use viewerCertificate, as aliasConfiguration is deprecated.',
].join(' '));
}
let _viewerCertificate = props.viewerCertificate;
if (props.aliasConfiguration) {
const { acmCertRef, securityPolicy, sslMethod, names: aliases } = props.aliasConfiguration;
_viewerCertificate = ViewerCertificate.fromAcmCertificate(certificatemanager.Certificate.fromCertificateArn(this, 'AliasConfigurationCert', acmCertRef), { securityPolicy, sslMethod, aliases });
}
if (_viewerCertificate) {
const { props: viewerCertificate, aliases } = _viewerCertificate;
Object.assign(distributionConfig, { aliases, viewerCertificate });
const { minimumProtocolVersion, sslSupportMethod } = viewerCertificate;
if (minimumProtocolVersion != null && sslSupportMethod != null) {
const validProtocols = this.VALID_SSL_PROTOCOLS[sslSupportMethod];
if (validProtocols.indexOf(minimumProtocolVersion.toString()) === -1) {
// eslint-disable-next-line max-len
throw new Error(`${minimumProtocolVersion} is not compabtible with sslMethod ${sslSupportMethod}.\n\tValid Protocols are: ${validProtocols.join(', ')}`);
}
}
}
else {
distributionConfig = {
...distributionConfig,
viewerCertificate: { cloudFrontDefaultCertificate: true },
};
}
if (props.loggingConfig) {
this.loggingBucket = props.loggingConfig.bucket || new s3.Bucket(this, 'LoggingBucket', {
encryption: s3.BucketEncryption.S3_MANAGED,
});
distributionConfig = {
...distributionConfig,
logging: {
bucket: this.loggingBucket.bucketRegionalDomainName,
includeCookies: props.loggingConfig.includeCookies || false,
prefix: props.loggingConfig.prefix,
},
};
}
if (props.geoRestriction) {
distributionConfig = {
...distributionConfig,
restrictions: {
geoRestriction: {
restrictionType: props.geoRestriction.restrictionType,
locations: props.geoRestriction.locations,
},
},
};
}
const distribution = new cloudfront_generated_1.CfnDistribution(this, 'CFDistribution', { distributionConfig });
this.node.defaultChild = distribution;
this.domainName = distribution.attrDomainName;
this.distributionDomainName = distribution.attrDomainName;
this.distributionId = distribution.ref;
}
/**
* Creates a construct that represents an external (imported) distribution.
*/
static fromDistributionAttributes(scope, id, attrs) {
try {
jsiiDeprecationWarnings._aws_cdk_aws_cloudfront_CloudFrontWebDistributionAttributes(attrs);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, this.fromDistributionAttributes);
}
throw error;
}
return new class extends cdk.Resource {
constructor() {
super(scope, id);
this.domainName = attrs.domainName;
this.distributionDomainName = attrs.domainName;
this.distributionId = attrs.distributionId;
}
}();
}
toBehavior(input, protoPolicy) {
let toReturn = {
allowedMethods: this.METHOD_LOOKUP_MAP[input.allowedMethods || CloudFrontAllowedMethods.GET_HEAD],
cachedMethods: this.METHOD_LOOKUP_MAP[input.cachedMethods || CloudFrontAllowedCachedMethods.GET_HEAD],
compress: input.compress !== false,
defaultTtl: input.defaultTtl && input.defaultTtl.toSeconds(),
forwardedValues: input.forwardedValues || { queryString: false, cookies: { forward: 'none' } },
maxTtl: input.maxTtl && input.maxTtl.toSeconds(),
minTtl: input.minTtl && input.minTtl.toSeconds(),
trustedKeyGroups: input.trustedKeyGroups?.map(key => key.keyGroupId),
trustedSigners: input.trustedSigners,
targetOriginId: input.targetOriginId,
viewerProtocolPolicy: input.viewerProtocolPolicy || protoPolicy || distribution_1.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
};
if (!input.isDefaultBehavior) {
toReturn = Object.assign(toReturn, { pathPattern: input.pathPattern });
}
if (input.functionAssociations) {
toReturn = Object.assign(toReturn, {
functionAssociations: input.functionAssociations.map(association => ({
functionArn: association.function.functionArn,
eventType: association.eventType.toString(),
})),
});
}
if (input.lambdaFunctionAssociations) {
const includeBodyEventTypes = [distribution_1.LambdaEdgeEventType.ORIGIN_REQUEST, distribution_1.LambdaEdgeEventType.VIEWER_REQUEST];
if (input.lambdaFunctionAssociations.some(fna => fna.includeBody && !includeBodyEventTypes.includes(fna.eventType))) {
throw new Error('\'includeBody\' can only be true for ORIGIN_REQUEST or VIEWER_REQUEST event types.');
}
toReturn = Object.assign(toReturn, {
lambdaFunctionAssociations: input.lambdaFunctionAssociations
.map(fna => ({
eventType: fna.eventType,
lambdaFunctionArn: fna.lambdaFunction && fna.lambdaFunction.edgeArn,
includeBody: fna.includeBody,
})),
});
// allow edgelambda.amazonaws.com to assume the functions' execution role.
for (const a of input.lambdaFunctionAssociations) {
if (a.lambdaFunction.role && a.lambdaFunction.role instanceof iam.Role && a.lambdaFunction.role.assumeRolePolicy) {
a.lambdaFunction.role.assumeRolePolicy.addStatements(new iam.PolicyStatement({
actions: ['sts:AssumeRole'],
principals: [new iam.ServicePrincipal('edgelambda.amazonaws.com')],
}));
}
}
}
return toReturn;
}
toOriginProperty(originConfig, originId) {
if (!originConfig.s3OriginSource &&
!originConfig.customOriginSource) {
throw new Error('There must be at least one origin source - either an s3OriginSource, a customOriginSource');
}
if (originConfig.customOriginSource && originConfig.s3OriginSource) {
throw new Error('There cannot be both an s3OriginSource and a customOriginSource in the same SourceConfiguration.');
}
if ([
originConfig.originHeaders,
originConfig.s3OriginSource?.originHeaders,
originConfig.customOriginSource?.originHeaders,
].filter(x => x).length > 1) {
throw new Error('Only one originHeaders field allowed across origin and failover origins');
}
if ([
originConfig.originPath,
originConfig.s3OriginSource?.originPath,
originConfig.customOriginSource?.originPath,
].filter(x => x).length > 1) {
throw new Error('Only one originPath field allowed across origin and failover origins');
}
if ([
originConfig.originShieldRegion,
originConfig.s3OriginSource?.originShieldRegion,
originConfig.customOriginSource?.originShieldRegion,
].filter(x => x).length > 1) {
throw new Error('Only one originShieldRegion field allowed across origin and failover origins');
}
const headers = originConfig.originHeaders ?? originConfig.s3OriginSource?.originHeaders ?? originConfig.customOriginSource?.originHeaders;
const originHeaders = [];
if (headers) {
Object.keys(headers).forEach((key) => {
const oHeader = {
headerName: key,
headerValue: headers[key],
};
originHeaders.push(oHeader);
});
}
let s3OriginConfig;
if (originConfig.s3OriginSource) {
// first case for backwards compatibility
if (originConfig.s3OriginSource.originAccessIdentity) {
// grant CloudFront OriginAccessIdentity read access to S3 bucket
// Used rather than `grantRead` because `grantRead` will grant overly-permissive policies.
// Only GetObject is needed to retrieve objects for the distribution.
// This also excludes KMS permissions; currently, OAI only supports SSE-S3 for buckets.
// Source: https://aws.amazon.com/blogs/networking-and-content-delivery/serving-sse-kms-encrypted-content-from-s3-using-cloudfront/
originConfig.s3OriginSource.s3BucketSource.addToResourcePolicy(new iam.PolicyStatement({
resources: [originConfig.s3OriginSource.s3BucketSource.arnForObjects('*')],
actions: ['s3:GetObject'],
principals: [originConfig.s3OriginSource.originAccessIdentity.grantPrincipal],
}));
s3OriginConfig = {
originAccessIdentity: `origin-access-identity/cloudfront/${originConfig.s3OriginSource.originAccessIdentity.originAccessIdentityName}`,
};
}
else {
s3OriginConfig = {};
}
}
const connectionAttempts = originConfig.connectionAttempts ?? 3;
if (connectionAttempts < 1 || 3 < connectionAttempts || !Number.isInteger(connectionAttempts)) {
throw new Error('connectionAttempts: You can specify 1, 2, or 3 as the number of attempts.');
}
const connectionTimeout = (originConfig.connectionTimeout || cdk.Duration.seconds(10)).toSeconds();
if (connectionTimeout < 1 || 10 < connectionTimeout || !Number.isInteger(connectionTimeout)) {
throw new Error('connectionTimeout: You can specify a number of seconds between 1 and 10 (inclusive).');
}
const originProperty = {
id: originId,
domainName: originConfig.s3OriginSource
? originConfig.s3OriginSource.s3BucketSource.bucketRegionalDomainName
: originConfig.customOriginSource.domainName,
originPath: originConfig.originPath ?? originConfig.customOriginSource?.originPath ?? originConfig.s3OriginSource?.originPath,
originCustomHeaders: originHeaders.length > 0 ? originHeaders : undefined,
s3OriginConfig,
originShield: this.toOriginShieldProperty(originConfig),
customOriginConfig: originConfig.customOriginSource
? {
httpPort: originConfig.customOriginSource.httpPort || 80,
httpsPort: originConfig.customOriginSource.httpsPort || 443,
originKeepaliveTimeout: (originConfig.customOriginSource.originKeepaliveTimeout &&
originConfig.customOriginSource.originKeepaliveTimeout.toSeconds()) ||
5,
originReadTimeout: (originConfig.customOriginSource.originReadTimeout &&
originConfig.customOriginSource.originReadTimeout.toSeconds()) ||
30,
originProtocolPolicy: originConfig.customOriginSource.originProtocolPolicy ||
distribution_1.OriginProtocolPolicy.HTTPS_ONLY,
originSslProtocols: originConfig.customOriginSource
.allowedOriginSSLVersions || [OriginSslPolicy.TLS_V1_2],
}
: undefined,
connectionAttempts,
connectionTimeout,
};
return originProperty;
}
/**
* Takes origin shield region from props and converts to CfnDistribution.OriginShieldProperty
*/
toOriginShieldProperty(originConfig) {
const originShieldRegion = originConfig.originShieldRegion ??
originConfig.customOriginSource?.originShieldRegion ??
originConfig.s3OriginSource?.originShieldRegion;
return originShieldRegion
? { enabled: true, originShieldRegion }
: undefined;
}
}
exports.CloudFrontWebDistribution = CloudFrontWebDistribution;
_b = JSII_RTTI_SYMBOL_1;
CloudFrontWebDistribution[_b] = { fqn: "@aws-cdk/aws-cloudfront.CloudFrontWebDistribution", version: "1.204.0" };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2ViLWRpc3RyaWJ1dGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIndlYi1kaXN0cmlidXRpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQUEsc0VBQXNFO0FBQ3RFLHdDQUF3QztBQUV4QyxzQ0FBc0M7QUFDdEMscUNBQXFDO0FBRXJDLGlFQUF5RDtBQUN6RCxpREFBNEs7QUFNNUs7O0dBRUc7QUFDSCxJQUFZLGtCQThCWDtBQTlCRCxXQUFZLGtCQUFrQjtJQUM1Qjs7T0FFRztJQUNILHVFQUFlLENBQUE7SUFFZjs7T0FFRztJQUNILHVFQUFlLENBQUE7SUFFZjs7T0FFRztJQUNILCtGQUEyQixDQUFBO0lBRTNCOztPQUVHO0lBQ0gsMkVBQWlCLENBQUE7SUFFakI7O09BRUc7SUFDSCwyRkFBeUIsQ0FBQTtJQUV6Qjs7T0FFRztJQUNILG1GQUFxQixDQUFBO0FBQ3ZCLENBQUMsRUE5Qlcsa0JBQWtCLEdBQWxCLDBCQUFrQixLQUFsQiwwQkFBa0IsUUE4QjdCO0FBbVBELElBQVksZUFLWDtBQUxELFdBQVksZUFBZTtJQUN6QixtQ0FBZ0IsQ0FBQTtJQUNoQixtQ0FBZ0IsQ0FBQTtJQUNoQix1Q0FBb0IsQ0FBQTtJQUNwQix1Q0FBb0IsQ0FBQTtBQUN0QixDQUFDLEVBTFcsZUFBZSxHQUFmLHVCQUFlLEtBQWYsdUJBQWUsUUFLMUI7QUF3Q0Q7O0dBRUc7QUFDSCxJQUFZLHdCQUlYO0FBSkQsV0FBWSx3QkFBd0I7SUFDbEMsMkNBQWUsQ0FBQTtJQUNmLG9EQUF3QixDQUFBO0lBQ3hCLHVDQUFXLENBQUE7QUFDYixDQUFDLEVBSlcsd0JBQXdCLEdBQXhCLGdDQUF3QixLQUF4QixnQ0FBd0IsUUFJbkM7QUFFRDs7R0FFRztBQUNILElBQVksOEJBR1g7QUFIRCxXQUFZLDhCQUE4QjtJQUN4QyxpREFBZSxDQUFBO0lBQ2YsMERBQXdCLENBQUE7QUFDMUIsQ0FBQyxFQUhXLDhCQUE4QixHQUE5QixzQ0FBOEIsS0FBOUIsc0NBQThC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QUMsY0FBYyxFQUFFLGtCQUFrQixDQUFDO1FBQ2hELE9BQU8sa0JBQWtCO1lBQ3ZCLENBQUMsQ0FBQyxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsa0JBQWtCLEVBQUU7WUFDdkMsQ0FBQyxDQUFDLFNBQVMsQ0FBQztLQUNmOztBQTNhSCw4REE0YUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBjZXJ0aWZpY2F0ZW1hbmFnZXIgZnJvbSAnQGF3cy1jZGsvYXdzLWNlcnRpZmljYXRlbWFuYWdlcic7XG5pbXBvcnQgKiBhcyBpYW0gZnJvbSAnQGF3cy1jZGsvYXdzLWlhbSc7XG5pbXBvcnQgKiBhcyBsYW1iZGEgZnJvbSAnQGF3cy1jZGsvYXdzLWxhbWJkYSc7XG5pbXBvcnQgKiBhcyBzMyBmcm9tICdAYXdzLWNkay9hd3MtczMnO1xuaW1wb3J0ICogYXMgY2RrIGZyb20gJ0Bhd3MtY2RrL2NvcmUnO1xuaW1wb3J0IHsgQ29uc3RydWN0IH0gZnJvbSAnY29uc3RydWN0cyc7XG5pbXBvcnQgeyBDZm5EaXN0cmlidXRpb24gfSBmcm9tICcuL2Nsb3VkZnJvbnQuZ2VuZXJhdGVkJztcbmltcG9ydCB7IEh0dHBWZXJzaW9uLCBJRGlzdHJpYnV0aW9uLCBMYW1iZGFFZGdlRXZlbnRUeXBlLCBPcmlnaW5Qcm90b2NvbFBvbGljeSwgUHJpY2VDbGFzcywgVmlld2VyUHJvdG9jb2xQb2xpY3ksIFNTTE1ldGhvZCwgU2VjdXJpdHlQb2xpY3lQcm90b2NvbCB9IGZyb20gJy4vZGlzdHJpYnV0aW9uJztcbmltcG9ydCB7IEZ1bmN0aW9uQXNzb2NpYXRpb24gfSBmcm9tICcuL2Z1bmN0aW9uJztcbmltcG9ydCB7IEdlb1Jlc3RyaWN0aW9uIH0gZnJvbSAnLi9nZW8tcmVzdHJpY3Rpb24nO1xuaW1wb3J0IHsgSUtleUdyb3VwIH0gZnJvbSAnLi9rZXktZ3JvdXAnO1xuaW1wb3J0IHsgSU9yaWdpbkFjY2Vzc0lkZW50aXR5IH0gZnJvbSAnLi9vcmlnaW4tYWNjZXNzLWlkZW50aXR5JztcblxuLyoqXG4gKiBIVFRQIHN0YXR1cyBjb2RlIHRvIGZhaWxvdmVyIHRvIHNlY29uZCBvcmlnaW5cbiAqL1xuZXhwb3J0IGVudW0gRmFpbG92ZXJTdGF0dXNDb2RlIHtcbiAgLyoqXG4gICAqIEZvcmJpZGRlbiAoNDAzKVxuICAgKi9cbiAgRk9SQklEREVOID0gNDAzLFxuXG4gIC8qKlxuICAgKiBOb3QgZm91bmQgKDQwNClcbiAgICovXG4gIE5PVF9GT1VORCA9IDQwNCxcblxuICAvKipcbiAgICogSW50ZXJuYWwgU2VydmVyIEVycm9yICg1MDApXG4gICAqL1xuICBJTlRFUk5BTF9TRVJWRVJfRVJST1IgPSA1MDAsXG5cbiAgLyoqXG4gICAqIEJhZCBHYXRld2F5ICg1MDIpXG4gICAqL1xuICBCQURfR0FURVdBWSA9IDUwMixcblxuICAvKipcbiAgICogU2VydmljZSBVbmF2YWlsYWJsZSAoNTAzKVxuICAgKi9cbiAgU0VSVklDRV9VTkFWQUlMQUJMRSA9IDUwMyxcblxuICAvKipcbiAgICogR2F0ZXdheSBUaW1lb3V0ICg1MDQpXG4gICAqL1xuICBHQVRFV0FZX1RJTUVPVVQgPSA1MDQsXG59XG5cbi8qKlxuICogQ29uZmlndXJhdGlvbiBmb3IgY3VzdG9tIGRvbWFpbiBuYW1lc1xuICpcbiAqIENsb3VkRnJvbnQgY2FuIHVzZSBhIGN1c3RvbSBkb21haW4gdGhhdCB5b3UgcHJvdmlkZSBpbnN0ZWFkIG9mIGFcbiAqIFwiY2xvdWRmcm9udC5uZXRcIiBkb21haW4uIFRvIHVzZSB0aGlzIGZlYXR1cmUgeW91IG11c3QgcHJvdmlkZSB0aGUgbGlzdCBvZlxuICogYWRkaXRpb25hbCBkb21haW5zLCBhbmQgdGhlIEFDTSBDZXJ0aWZpY2F0ZSB0aGF0IENsb3VkRnJvbnQgc2hvdWxkIHVzZSBmb3JcbiAqIHRoZXNlIGFkZGl0aW9uYWwgZG9tYWlucy5cbiAqIEBkZXByZWNhdGVkIHNlZSB7QGxpbmsgQ2xvdWRGcm9udFdlYkRpc3RyaWJ1dGlvblByb3BzI3ZpZXdlckNlcnRpZmljYXRlfSB3aXRoIHtAbGluayBWaWV3ZXJDZXJ0aWZpY2F0ZSNhY21DZXJ0aWZpY2F0ZX1cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBBbGlhc0NvbmZpZ3VyYXRpb24ge1xuICAvKipcbiAgICogQVJOIG9mIGFuIEFXUyBDZXJ0aWZpY2F0ZSBNYW5hZ2VyIChBQ00pIGNlcnRpZmljYXRlLlxuICAgKi9cbiAgcmVhZG9ubHkgYWNtQ2VydFJlZjogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBEb21haW4gbmFtZXMgb24gdGhlIGNlcnRpZmljYXRlXG4gICAqXG4gICAqIEJvdGggbWFpbiBkb21haW4gbmFtZSBhbmQgU3ViamVjdCBBbHRlcm5hdGl2ZSBOYW1lcy5cbiAgICovXG4gIHJlYWRvbmx5IG5hbWVzOiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogSG93IENsb3VkRnJvbnQgc2hvdWxkIHNlcnZlIEhUVFBTIHJlcXVlc3RzLlxuICAgKlxuICAgKiBTZWUgdGhlIG5vdGVzIG9uIFNTTE1ldGhvZCBpZiB5b3Ugd2lzaCB0byB1c2Ugb3RoZXIgU1NMIHRlcm1pbmF0aW9uIHR5cGVzLlxuICAgKlxuICAgKiBAZGVmYXVsdCBTU0xNZXRob2QuU05JXG4gICAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2Nsb3VkZnJvbnQvbGF0ZXN0L0FQSVJlZmVyZW5jZS9BUElfVmlld2VyQ2VydGlmaWNhdGUuaHRtbFxuICAgKi9cbiAgcmVhZG9ubHkgc3NsTWV0aG9kPzogU1NMTWV0aG9kO1xuXG4gIC8qKlxuICAgKiBUaGUgbWluaW11bSB2ZXJzaW9uIG9mIHRoZSBTU0wgcHJvdG9jb2wgdGhhdCB5b3Ugd2FudCBDbG91ZEZyb250IHRvIHVzZSBmb3IgSFRUUFMgY29ubmVjdGlvbnMuXG4gICAqXG4gICAqIENsb3VkRnJvbnQgc2VydmVzIHlvdXIgb2JqZWN0cyBvbmx5IHRvIGJyb3dzZXJzIG9yIGRldmljZXMgdGhhdCBzdXBwb3J0IGF0XG4gICAqIGxlYXN0IHRoZSBTU0wgdmVyc2lvbiB0aGF0IHlvdSBzcGVjaWZ5LlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIFNTTHYzIGlmIHNzbE1ldGhvZCBWSVAsIFRMU3YxIGlmIHNzbE1ldGhvZCBTTklcbiAgICovXG4gIHJlYWRvbmx5IHNlY3VyaXR5UG9saWN5PzogU2VjdXJpdHlQb2xpY3lQcm90b2NvbDtcbn1cblxuLyoqXG4gKiBMb2dnaW5nIGNvbmZpZ3VyYXRpb24gZm9yIGluY29taW5nIHJlcXVlc3RzXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgTG9nZ2luZ0NvbmZpZ3VyYXRpb24ge1xuICAvKipcbiAgICogQnVja2V0IHRvIGxvZyByZXF1ZXN0cyB0b1xuICAgKlxuICAgKiBAZGVmYXVsdCAtIEEgbG9nZ2luZyBidWNrZXQgaXMgYXV0b21hdGljYWxseSBjcmVhdGVkLlxuICAgKi9cbiAgcmVhZG9ubHkgYnVja2V0PzogczMuSUJ1Y2tldCxcblxuICAvKipcbiAgICogV2hldGhlciB0byBpbmNsdWRlIHRoZSBjb29raWVzIGluIHRoZSBsb2dzXG4gICAqXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICByZWFkb25seSBpbmNsdWRlQ29va2llcz86IGJvb2xlYW4sXG5cbiAgLyoqXG4gICAqIFdoZXJlIGluIHRoZSBidWNrZXQgdG8gc3RvcmUgbG9nc1xuICAgKlxuICAgKiBAZGVmYXVsdCAtIE5vIHByZWZpeC5cbiAgICovXG4gIHJlYWRvbmx5IHByZWZpeD86IHN0cmluZ1xufVxuXG4vLyBTdWJzZXQgb2YgU291cmNlQ29uZmlndXJhdGlvbiBmb3IgcmVuZGVyaW5nIHByb3BlcnRpZXMgaW50ZXJuYWxseVxuaW50ZXJmYWNlIFNvdXJjZUNvbmZpZ3VyYXRpb25SZW5kZXIge1xuICByZWFkb25seSBjb25uZWN0aW9uQXR0ZW1wdHM/OiBudW1iZXI7XG4gIHJlYWRvbmx5IGNvbm5lY3Rpb25UaW1lb3V0PzogY2RrLkR1cmF0aW9uO1xuICByZWFkb25seSBzM09yaWdpblNvdXJjZT86IFMzT3JpZ2luQ29uZmlnO1xuICByZWFkb25seSBjdXN0b21PcmlnaW5Tb3VyY2U/OiBDdXN0b21PcmlnaW5Db25maWc7XG4gIHJlYWRvbmx5IG9yaWdpblBhdGg/OiBzdHJpbmc7XG4gIHJlYWRvbmx5IG9yaWdpbkhlYWRlcnM/OiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9O1xuICByZWFkb25seSBvcmlnaW5TaGllbGRSZWdpb24/OiBzdHJpbmdcbn1cblxuLyoqXG4gKiBBIHNvdXJjZSBjb25maWd1cmF0aW9uIGlzIGEgd3JhcHBlciBmb3IgQ2xvdWRGcm9udCBvcmlnaW5zIGFuZCBiZWhhdmlvcnMuXG4gKiBBbiBvcmlnaW4gaXMgd2hhdCBDbG91ZEZyb250IHdpbGwgXCJiZSBpbiBmcm9udCBvZlwiIC0gdGhhdCBpcywgQ2xvdWRGcm9udCB3aWxsIHB1bGwgaXQncyBhc3NldHMgZnJvbSBhbiBvcmlnaW4uXG4gKlxuICogSWYgeW91J3JlIHVzaW5nIHMzIGFzIGEgc291cmNlIC0gcGFzcyB0aGUgYHMzT3JpZ2luYCBwcm9wZXJ0eSwgb3RoZXJ3aXNlLCBwYXNzIHRoZSBgY3VzdG9tT3JpZ2luU291cmNlYCBwcm9wZXJ0eS5cbiAqXG4gKiBPbmUgb3IgdGhlIG90aGVyIG11c3QgYmUgcGFzc2VkLCBhbmQgaXQgaXMgaW52YWxpZCB0byBwYXNzIGJvdGggaW4gdGhlIHNhbWUgU291cmNlQ29uZmlndXJhdGlvbi5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBTb3VyY2VDb25maWd1cmF0aW9uIHtcbiAgLyoqXG4gICAqIFRoZSBudW1iZXIgb2YgdGltZXMgdGhhdCBDbG91ZEZyb250IGF0dGVtcHRzIHRvIGNvbm5lY3QgdG8gdGhlIG9yaWdpbi5cbiAgICogWW91IGNhbiBzcGVjaWZ5IDEsIDIsIG9yIDMgYXMgdGhlIG51bWJlciBvZiBhdHRlbXB0cy5cbiAgICpcbiAgICogQGRlZmF1bHQgM1xuICAgKi9cbiAgcmVhZG9ubHkgY29ubmVjdGlvbkF0dGVtcHRzPzogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBUaGUgbnVtYmVyIG9mIHNlY29uZHMgdGhhdCBDbG91ZEZyb250IHdhaXRzIHdoZW4gdHJ5aW5nIHRvIGVzdGFibGlzaCBhIGNvbm5lY3Rpb24gdG8gdGhlIG9yaWdpbi5cbiAgICogWW91IGNhbiBzcGVjaWZ5IGEgbnVtYmVyIG9mIHNlY29uZHMgYmV0d2VlbiAxIGFuZCAxMCAoaW5jbHVzaXZlKS5cbiAgICpcbiAgICogQGRlZmF1bHQgY2RrLkR1cmF0aW9uLnNlY29uZHMoMTApXG4gICAqL1xuICByZWFkb25seSBjb25uZWN0aW9uVGltZW91dD86IGNkay5EdXJhdGlvbjtcblxuICAvKipcbiAgICogQW4gczMgb3JpZ2luIHNvdXJjZSAtIGlmIHlvdSdyZSB1c2luZyBzMyBmb3IgeW91ciBhc3NldHNcbiAgICovXG4gIHJlYWRvbmx5IHMzT3JpZ2luU291cmNlPzogUzNPcmlnaW5Db25maWc7XG5cbiAgLyoqXG4gICAqIEEgY3VzdG9tIG9yaWdpbiBzb3VyY2UgLSBmb3IgYWxsIG5vbi1zMyBzb3VyY2VzLlxuICAgKi9cbiAgcmVhZG9ubHkgY3VzdG9tT3JpZ2luU291cmNlPzogQ3VzdG9t