UNPKG

@aws-cdk/aws-cloudfront

Version:

The CDK Construct Library for AWS::CloudFront

524 lines 99.2 kB
"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.157.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) { var _c, _d, _e, _f; 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, this.constructor); } 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; let distributionConfig = { comment: trimmedComment, enabled: (_c = props.enabled) !== null && _c !== void 0 ? _c : true, defaultRootObject: (_d = props.defaultRootObject) !== null && _d !== void 0 ? _d : 'index.html', httpVersion: props.httpVersion || distribution_1.HttpVersion.HTTP2, priceClass: props.priceClass || distribution_1.PriceClass.PRICE_CLASS_100, ipv6Enabled: (_e = props.enableIpV6) !== null && _e !== void 0 ? _e : true, // eslint-disable-next-line max-len customErrorResponses: props.errorConfigurations, webAclId: props.webACLId, }; 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 = (_f = originConfig.failoverCriteriaStatusCodes) !== null && _f !== void 0 ? _f : [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; distributionConfig = { ...distributionConfig, origins, originGroups: originGroupsDistConfig, }; 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 ].'); } distributionConfig = { ...distributionConfig, defaultCacheBehavior: this.toBehavior(defaultBehaviors[0], props.viewerProtocolPolicy) }; 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)); } distributionConfig = { ...distributionConfig, 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) { var _c; 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: (_c = input.trustedKeyGroups) === null || _c === void 0 ? void 0 : _c.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) { var _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s; 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, (_c = originConfig.s3OriginSource) === null || _c === void 0 ? void 0 : _c.originHeaders, (_d = originConfig.customOriginSource) === null || _d === void 0 ? void 0 : _d.originHeaders, ].filter(x => x).length > 1) { throw new Error('Only one originHeaders field allowed across origin and failover origins'); } if ([ originConfig.originPath, (_e = originConfig.s3OriginSource) === null || _e === void 0 ? void 0 : _e.originPath, (_f = originConfig.customOriginSource) === null || _f === void 0 ? void 0 : _f.originPath, ].filter(x => x).length > 1) { throw new Error('Only one originPath field allowed across origin and failover origins'); } if ([ originConfig.originShieldRegion, (_g = originConfig.s3OriginSource) === null || _g === void 0 ? void 0 : _g.originShieldRegion, (_h = originConfig.customOriginSource) === null || _h === void 0 ? void 0 : _h.originShieldRegion, ].filter(x => x).length > 1) { throw new Error('Only one originShieldRegion field allowed across origin and failover origins'); } const headers = (_l = (_j = originConfig.originHeaders) !== null && _j !== void 0 ? _j : (_k = originConfig.s3OriginSource) === null || _k === void 0 ? void 0 : _k.originHeaders) !== null && _l !== void 0 ? _l : (_m = originConfig.customOriginSource) === null || _m === void 0 ? void 0 : _m.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 = (_o = originConfig.connectionAttempts) !== null && _o !== void 0 ? _o : 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: (_r = (_p = originConfig.originPath) !== null && _p !== void 0 ? _p : (_q = originConfig.customOriginSource) === null || _q === void 0 ? void 0 : _q.originPath) !== null && _r !== void 0 ? _r : (_s = originConfig.s3OriginSource) === null || _s === void 0 ? void 0 : _s.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) { var _c, _d, _e, _f; const originShieldRegion = (_e = (_c = originConfig.originShieldRegion) !== null && _c !== void 0 ? _c : (_d = originConfig.customOriginSource) === null || _d === void 0 ? void 0 : _d.originShieldRegion) !== null && _e !== void 0 ? _e : (_f = originConfig.s3OriginSource) === null || _f === void 0 ? void 0 : _f.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.157.0" }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2ViLWRpc3RyaWJ1dGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIndlYi1kaXN0cmlidXRpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQUEsc0VBQXNFO0FBQ3RFLHdDQUF3QztBQUV4QyxzQ0FBc0M7QUFDdEMscUNBQXFDO0FBRXJDLGlFQUF5RDtBQUN6RCxpREFBNEs7QUFNNUs7O0dBRUc7QUFDSCxJQUFZLGtCQThCWDtBQTlCRCxXQUFZLGtCQUFrQjtJQUM1Qjs7T0FFRztJQUNILHVFQUFlLENBQUE7SUFFZjs7T0FFRztJQUNILHVFQUFlLENBQUE7SUFFZjs7T0FFRztJQUNILCtGQUEyQixDQUFBO0lBRTNCOztPQUVHO0lBQ0gsMkVBQWlCLENBQUE7SUFFakI7O09BRUc7SUFDSCwyRkFBeUIsQ0FBQTtJQUV6Qjs7T0FFRztJQUNILG1GQUFxQixDQUFBO0FBQ3ZCLENBQUMsRUE5Qlcsa0JBQWtCLEdBQWxCLDBCQUFrQixLQUFsQiwwQkFBa0IsUUE4QjdCO0FBbVBELElBQVksZUFLWDtBQUxELFdBQVksZUFBZTtJQUN6QixtQ0FBZ0IsQ0FBQTtJQUNoQixtQ0FBZ0IsQ0FBQTtJQUNoQix1Q0FBb0IsQ0FBQTtJQUNwQix1Q0FBb0IsQ0FBQTtBQUN0QixDQUFDLEVBTFcsZUFBZSxHQUFmLHVCQUFlLEtBQWYsdUJBQWUsUUFLMUI7QUF3Q0Q7O0dBRUc7QUFDSCxJQUFZLHdCQUlYO0FBSkQsV0FBWSx3QkFBd0I7SUFDbEMsMkNBQWUsQ0FBQTtJQUNmLG9EQUF3QixDQUFBO0lBQ3hCLHVDQUFXLENBQUE7QUFDYixDQUFDLEVBSlcsd0JBQXdCLEdBQXhCLGdDQUF3QixLQUF4QixnQ0FBd0IsUUFJbkM7QUFFRDs7R0FFRztBQUNILElBQVksOEJBR1g7QUFIRCxXQUFZLDhCQUE4QjtJQUN4QyxpREFBZSxDQUFBO0lBQ2YsMERBQXdCLENBQUE7QUFDMUIsQ0FBQyxFQUhXLDhCQUE4QixHQUE5QixzQ0FBOEIsS0FBOUIsc0NBQThC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UUFFRixPQUFPLGNBQWMsQ0FBQztLQUN2QjtJQUVEOztPQUVHO0lBQ0ssc0JBQXNCLENBQUMsWUFBc0M7O1FBQ25FLE1BQU0sa0JBQWtCLGVBQUcsWUFBWSxDQUFDLGtCQUFrQix5Q0FDMUQsWUFBWSxDQUFDLGtCQUFrQiwwQ0FBRSxrQkFBa0IseUNBQ25ELFlBQVksQ0FBQyxjQUFjLDBDQUFFLGtCQUFrQixDQUFDO1FBQ2hELE9BQU8sa0JBQWtCO1lBQ3ZCLENBQUMsQ0FBQyxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsa0JBQWtCLEVBQUU7WUFDdkMsQ0FBQyxDQUFDLFNBQVMsQ0FBQztLQUNmOztBQTdhSCw4REE4YUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBjZXJ0aWZpY2F0ZW1hbmFnZXIgZnJvbSAnQGF3cy1jZGsvYXdzLWNlcnRpZmljYXRlbWFuYWdlcic7XG5pbXBvcnQgKiBhcyBpYW0gZnJvbSAnQGF3cy1jZGsvYXdzLWlhbSc7XG5pbXBvcnQgKiBhcyBsYW1iZGEgZnJvbSAnQGF3cy1jZGsvYXdzLWxhbWJkYSc7XG5pbXBvcnQgKiBhcyBzMyBmcm9tICdAYXdzLWNkay9hd3MtczMnO1xuaW1wb3J0ICogYXMgY2RrIGZyb20gJ0Bhd3MtY2RrL2NvcmUnO1xuaW1wb3J0IHsgQ29uc3RydWN0IH0gZnJvbSAnY29uc3RydWN0cyc7XG5pbXBvcnQgeyBDZm5EaXN0cmlidXRpb24gfSBmcm9tICcuL2Nsb3VkZnJvbnQuZ2VuZXJhdGVkJztcbmltcG9ydCB7IEh0dHBWZXJzaW9uLCBJRGlzdHJpYnV0aW9uLCBMYW1iZGFFZGdlRXZlbnRUeXBlLCBPcmlnaW5Qcm90b2NvbFBvbGljeSwgUHJpY2VDbGFzcywgVmlld2VyUHJvdG9jb2xQb2xpY3ksIFNTTE1ldGhvZCwgU2VjdXJpdHlQb2xpY3lQcm90b2NvbCB9IGZyb20gJy4vZGlzdHJpYnV0aW9uJztcbmltcG9ydCB7IEZ1bmN0aW9uQXNzb2NpYXRpb24gfSBmcm9tICcuL2Z1bmN0aW9uJztcbmltcG9ydCB7IEdlb1Jlc3RyaWN0aW9uIH0gZnJvbSAnLi9nZW8tcmVzdHJpY3Rpb24nO1xuaW1wb3J0IHsgSUtleUdyb3VwIH0gZnJvbSAnLi9rZXktZ3JvdXAnO1xuaW1wb3J0IHsgSU9yaWdpbkFjY2Vzc0lkZW50aXR5IH0gZnJvbSAnLi9vcmlnaW4tYWNjZXNzLWlkZW50aXR5JztcblxuLyoqXG4gKiBIVFRQIHN0YXR1cyBjb2RlIHRvIGZhaWxvdmVyIHRvIHNlY29uZCBvcmlnaW5cbiAqL1xuZXhwb3J0IGVudW0gRmFpbG92ZXJTdGF0dXNDb2RlIHtcbiAgLyoqXG4gICAqIEZvcmJpZGRlbiAoNDAzKVxuICAgKi9cbiAgRk9SQklEREVOID0gNDAzLFxuXG4gIC8qKlxuICAgKiBOb3QgZm91bmQgKDQwNClcbiAgICovXG4gIE5PVF9GT1VORCA9IDQwNCxcblxuICAvKipcbiAgICogSW50ZXJuYWwgU2VydmVyIEVycm9yICg1MDApXG4gICAqL1xuICBJTlRFUk5BTF9TRVJWRVJfRVJST1IgPSA1MDAsXG5cbiAgLyoqXG4gICAqIEJhZCBHYXRld2F5ICg1MDIpXG4gICAqL1xuICBCQURfR0FURVdBWSA9IDUwMixcblxuICAvKipcbiAgICogU2VydmljZSBVbmF2YWlsYWJsZSAoNTAzKVxuICAgKi9cbiAgU0VSVklDRV9VTkFWQUlMQUJMRSA9IDUwMyxcblxuICAvKipcbiAgICogR2F0ZXdheSBUaW1lb3V0ICg1MDQpXG4gICAqL1xuICBHQVRFV0FZX1RJTUVPVVQgPSA1MDQsXG59XG5cbi8qKlxuICogQ29uZmlndXJhdGlvbiBmb3IgY3VzdG9tIGRvbWFpbiBuYW1lc1xuICpcbiAqIENsb3VkRnJvbnQgY2FuIHVzZSBhIGN1c3RvbSBkb21haW4gdGhhdCB5b3UgcHJvdmlkZSBpbnN0ZWFkIG9mIGFcbiAqIFwiY2xvdWRmcm9udC5uZXRcIiBkb21haW4uIFRvIHVzZSB0aGlzIGZlYXR1cmUgeW91IG11c3QgcHJvdmlkZSB0aGUgbGlzdCBvZlxuICogYWRkaXRpb25hbCBkb21haW5zLCBhbmQgdGhlIEFDTSBDZXJ0aWZpY2F0ZSB0aGF0IENsb3VkRnJvbnQgc2hvdWxkIHVzZSBmb3JcbiAqIHRoZXNlIGFkZGl0aW9uYWwgZG9tYWlucy5cbiAqIEBkZXByZWNhdGVkIHNlZSB7QGxpbmsgQ2xvdWRGcm9udFdlYkRpc3RyaWJ1dGlvblByb3BzI3ZpZXdlckNlcnRpZmljYXRlfSB3aXRoIHtAbGluayBWaWV3ZXJDZXJ0aWZpY2F0ZSNhY21DZXJ0aWZpY2F0ZX1cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBBbGlhc0NvbmZpZ3VyYXRpb24ge1xuICAvKipcbiAgICogQVJOIG9mIGFuIEFXUyBDZXJ0aWZpY2F0ZSBNYW5hZ2VyIChBQ00pIGNlcnRpZmljYXRlLlxuICAgKi9cbiAgcmVhZG9ubHkgYWNtQ2VydFJlZjogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBEb21haW4gbmFtZXMgb24gdGhlIGNlcnRpZmljYXRlXG4gICAqXG4gICAqIEJvdGggbWFpbiBkb21haW4gbmFtZSBhbmQgU3ViamVjdCBBbHRlcm5hdGl2ZSBOYW1lcy5cbiAgICovXG4gIHJlYWRvbmx5IG5hbWVzOiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogSG93IENsb3VkRnJvbnQgc2hvdWxkIHNlcnZlIEhUVFBTIHJlcXVlc3RzLlxuICAgKlxuICAgKiBTZWUgdGhlIG5vdGVzIG9uIFNTTE1ldGhvZCBpZiB5b3Ugd2lzaCB0byB1c2Ugb3RoZXIgU1NMIHRlcm1pbmF0aW9uIHR5cGVzLlxuICAgKlxuICAgKiBAZGVmYXVsdCBTU0xNZXRob2QuU05JXG4gICAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2Nsb3VkZnJvbnQvbGF0ZXN0L0FQSVJlZmVyZW5jZS9BUElfVmlld2VyQ2VydGlmaWNhdGUuaHRtbFxuICAgKi9cbiAgcmVhZG9ubHkgc3NsTWV0aG9kPzogU1NMTWV0aG9kO1xuXG4gIC8qKlxuICAgKiBUaGUgbWluaW11bSB2ZXJzaW9uIG9mIHRoZSBTU0wgcHJvdG9jb2wgdGhhdCB5b3Ugd2FudCBDbG91ZEZyb250IHRvIHVzZSBmb3IgSFRUUFMgY29ubmVjdGlvbnMuXG4gICAqXG4gICAqIENsb3VkRnJvbnQgc2VydmVzIHlvdXIgb2JqZWN0cyBvbmx5IHRvIGJyb3dzZXJzIG9yIGRldmljZXMgdGhhdCBzdXBwb3J0IGF0XG4gICAqIGxlYXN0IHRoZSBTU0wgdmVyc2lvbiB0aGF0IHlvdSBzcGVjaWZ5LlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIFNTTHYzIGlmIHNzbE1ldGhvZCBWSVAsIFRMU3YxIGlmIHNzbE1ldGhvZCBTTklcbiAgICovXG4gIHJlYWRvbmx5IHNlY3VyaXR5UG9saWN5PzogU2VjdXJpdHlQb2xpY3lQcm90b2NvbDtcbn1cblxuLyoqXG4gKiBMb2dnaW5nIGNvbmZpZ3VyYXRpb24gZm9yIGluY29taW5nIHJlcXVlc3RzXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgTG9nZ2luZ0NvbmZpZ3VyYXRpb24ge1xuICAvKipcbiAgICogQnVja2V0IHRvIGxvZyByZXF1ZXN0cyB0b1xuICAgKlxuICAgKiBAZGVmYXVsdCAtIEEgbG9nZ2luZyBidWNrZXQgaXMgYXV0b21hdGljYWxseSBjcmVhdGVkLlxuICAgKi9cbiAgcmVhZG9ubHkgYnVja2V0PzogczMuSUJ1Y2tldCxcblxuICAvKipcbiAgICogV2hldGhlciB0byBpbmNsdWRlIHRoZSBjb29raWVzIGluIHRoZSBsb2dzXG4gICAqXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICByZWFkb25seSBpbmNsdWRlQ29va2llcz86IGJvb2xlYW4sXG5cbiAgLyoqXG4gICAqIFdoZXJlIGluIHRoZSBidWNrZXQgdG8gc3RvcmUgbG9nc1xuICAgKlxuICAgKiBAZGVmYXVsdCAtIE5vIHByZWZpeC5cbiAgICovXG4gIHJlYWRvbmx5IHByZWZpeD86IHN0cmluZ1xufVxuXG4vLyBTdWJzZXQgb2YgU291cmNlQ29uZmlndXJhdGlvbiBmb3IgcmVuZGVyaW5nIHByb3BlcnRpZXMgaW50ZXJuYWxseVxuaW50ZXJmYWNlIFNvdXJjZUNvbmZpZ3VyYXRpb25SZW5kZXIge1xuICByZWFkb25seSBjb25uZWN0aW9uQXR0ZW1wdHM/OiBudW1iZXI7XG4gIHJlYWRvbmx5IGNvbm5lY3Rpb25UaW1lb3V0PzogY2RrLkR1cmF0aW9uO1xuICByZWFkb25seSBzM09yaWdpblNvdXJjZT86IFMzT3JpZ2luQ29uZmlnO1xuICByZWFkb25seSBjdXN0b21PcmlnaW5Tb3VyY2U/OiBDdXN0b21PcmlnaW5Db25maWc7XG4gIHJlYWRvbmx5IG9yaWdpblBhdGg/OiBzdHJpbmc7XG4gIHJlYWRvbmx5IG9yaWdpbkhlYWRlcnM/OiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9O1xuICByZWFkb25seSBvcmlnaW5TaGllbGRSZWdpb24/OiBzdHJpbmdcbn1cblxuLyoqXG4gKiBBIHNvdXJjZSBjb25maWd1cmF0aW9uIGlzIGEgd3JhcHBlciBmb3IgQ2xvdWRGcm9udCBvcmlnaW5zIGFuZCBiZWhhdmlvcnMuXG4gKiBBbiB