open-next-cdk
Version:
Deploy a NextJS app using OpenNext packaging to serverless AWS using CDK
131 lines • 22.1 kB
JavaScript
;
// Copyright 2018-2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
Object.defineProperty(exports, "__esModule", { value: true });
exports.HttpsRedirectPatched = void 0;
const aws_certificatemanager_1 = require("aws-cdk-lib/aws-certificatemanager");
const aws_cloudfront_1 = require("aws-cdk-lib/aws-cloudfront");
const aws_route53_1 = require("aws-cdk-lib/aws-route53");
const aws_route53_targets_1 = require("aws-cdk-lib/aws-route53-targets");
const aws_s3_1 = require("aws-cdk-lib/aws-s3");
const core_1 = require("aws-cdk-lib/core");
const helpers_internal_1 = require("aws-cdk-lib/core/lib/helpers-internal");
const cx_api_1 = require("aws-cdk-lib/cx-api");
const constructs_1 = require("constructs");
const utils_1 = require("./utils");
/**
* Allows creating a domainA -> domainB redirect using CloudFront and S3.
* You can specify multiple domains to be redirected.
*/
class HttpsRedirectPatched extends constructs_1.Construct {
constructor(scope, id, props) {
super(scope, id);
const domainNames = props.recordNames ?? [props.zone.zoneName];
if (props.certificate) {
const certificateRegion = core_1.Stack.of(this).splitArn(props.certificate.certificateArn, core_1.ArnFormat.SLASH_RESOURCE_NAME).region;
if (!core_1.Token.isUnresolved(certificateRegion) && certificateRegion !== 'us-east-1') {
throw new Error(`The certificate must be in the us-east-1 region and the certificate you provided is in ${certificateRegion}.`);
}
}
const redirectCert = props.certificate ?? this.createCertificate(domainNames, props.zone);
const redirectBucket = new aws_s3_1.Bucket(this, 'RedirectBucket', {
websiteRedirect: {
hostName: props.targetDomain,
protocol: aws_s3_1.RedirectProtocol.HTTPS,
},
removalPolicy: core_1.RemovalPolicy.DESTROY,
blockPublicAccess: aws_s3_1.BlockPublicAccess.BLOCK_ALL,
});
const redirectDist = new aws_cloudfront_1.CloudFrontWebDistribution(this, 'RedirectDistribution', {
defaultRootObject: '',
originConfigs: [
{
behaviors: [{ isDefaultBehavior: true }],
customOriginSource: {
domainName: redirectBucket.bucketWebsiteDomainName,
originProtocolPolicy: aws_cloudfront_1.OriginProtocolPolicy.HTTP_ONLY,
},
},
],
viewerCertificate: aws_cloudfront_1.ViewerCertificate.fromAcmCertificate(redirectCert, {
aliases: domainNames,
}),
comment: `Redirect to ${props.targetDomain} from ${domainNames.join(', ')}`,
priceClass: aws_cloudfront_1.PriceClass.PRICE_CLASS_ALL,
viewerProtocolPolicy: aws_cloudfront_1.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
});
domainNames.forEach((domainName) => {
const hash = helpers_internal_1.md5hash(domainName).slice(0, 6);
// domainAddTrailingDot fixes ability to use CfnParameters as domain name
domainName = utils_1.domainAddTrailingDot(domainName);
const aliasProps = {
recordName: domainName,
zone: props.zone,
target: aws_route53_1.RecordTarget.fromAlias(new aws_route53_targets_1.CloudFrontTarget(redirectDist)),
};
new aws_route53_1.ARecord(this, `RedirectAliasRecord${hash}`, aliasProps);
new aws_route53_1.AaaaRecord(this, `RedirectAliasRecordSix${hash}`, aliasProps);
});
}
/**
* Gets the stack to use for creating the Certificate
* If the current stack is not in `us-east-1` then this
* will create a new `us-east-1` stack.
*
* CloudFront is a global resource which you can create (via CloudFormation) from
* _any_ region. So I could create a CloudFront distribution in `us-east-2` if I wanted
* to (maybe the rest of my application lives there). The problem is that some supporting resources
* that CloudFront uses (i.e. ACM Certificates) are required to exist in `us-east-1`. This means
* that if I want to create a CloudFront distribution in `us-east-2` I still need to create a ACM certificate in
* `us-east-1`.
*
* In order to do this correctly we need to know which region the CloudFront distribution is being created in.
* We have two options, either require the user to specify the region or make an assumption if they do not.
* This implementation requires the user specify the region.
*/
certificateScope() {
const stack = core_1.Stack.of(this);
const parent = stack.node.scope;
if (!parent) {
throw new Error(`Stack ${stack.stackId} must be created in the scope of an App or Stage`);
}
if (core_1.Token.isUnresolved(stack.region)) {
throw new Error(`When ${cx_api_1.ROUTE53_PATTERNS_USE_CERTIFICATE} is enabled, a region must be defined on the Stack`);
}
if (stack.region !== 'us-east-1') {
const stackId = `certificate-redirect-stack-${stack.node.addr}`;
const certStack = parent.node.tryFindChild(stackId);
return (certStack ??
new core_1.Stack(parent, stackId, {
env: { region: 'us-east-1', account: stack.account },
}));
}
return this;
}
/**
* Creates a certificate.
*/
createCertificate(domainNames, zone) {
// this preserves backwards compatibility. Previously the certificate was always created in `this` scope
// so we need to keep the name the same
const id = this.certificateScope() === this ? 'RedirectCertificate' : 'RedirectCertificate' + this.node.addr;
return new aws_certificatemanager_1.Certificate(this.certificateScope(), id, {
domainName: domainNames[0],
subjectAlternativeNames: domainNames,
validation: aws_certificatemanager_1.CertificateValidation.fromDns(zone),
});
}
}
exports.HttpsRedirectPatched = HttpsRedirectPatched;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2Vic2l0ZS1yZWRpcmVjdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy93ZWJzaXRlLXJlZGlyZWN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSwrRUFBK0U7QUFDL0UsRUFBRTtBQUNGLGtFQUFrRTtBQUNsRSxtRUFBbUU7QUFDbkUsMENBQTBDO0FBQzFDLEVBQUU7QUFDRixpREFBaUQ7QUFDakQsRUFBRTtBQUNGLHNFQUFzRTtBQUN0RSxvRUFBb0U7QUFDcEUsMkVBQTJFO0FBQzNFLHNFQUFzRTtBQUN0RSxpQ0FBaUM7OztBQUVqQywrRUFBc0c7QUFDdEcsK0RBTW9DO0FBQ3BDLHlEQUF5RjtBQUN6Rix5RUFBbUU7QUFDbkUsK0NBQWlGO0FBQ2pGLDJDQUEwRTtBQUMxRSw0RUFBZ0U7QUFDaEUsK0NBQXNFO0FBQ3RFLDJDQUF1QztBQUN2QyxtQ0FBK0M7QUE4Qy9DOzs7R0FHRztBQUNILE1BQWEsb0JBQXFCLFNBQVEsc0JBQVM7SUFDakQsWUFBWSxLQUFnQixFQUFFLEVBQVUsRUFBRSxLQUF5QjtRQUNqRSxLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBRWpCLE1BQU0sV0FBVyxHQUFHLEtBQUssQ0FBQyxXQUFXLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBRS9ELElBQUksS0FBSyxDQUFDLFdBQVcsRUFBRTtZQUNyQixNQUFNLGlCQUFpQixHQUFHLFlBQUssQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsUUFBUSxDQUMvQyxLQUFLLENBQUMsV0FBVyxDQUFDLGNBQWMsRUFDaEMsZ0JBQVMsQ0FBQyxtQkFBbUIsQ0FDOUIsQ0FBQyxNQUFNLENBQUM7WUFDVCxJQUFJLENBQUMsWUFBSyxDQUFDLFlBQVksQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLGlCQUFpQixLQUFLLFdBQVcsRUFBRTtnQkFDL0UsTUFBTSxJQUFJLEtBQUssQ0FDYiwwRkFBMEYsaUJBQWlCLEdBQUcsQ0FDL0csQ0FBQzthQUNIO1NBQ0Y7UUFDRCxNQUFNLFlBQVksR0FBRyxLQUFLLENBQUMsV0FBVyxJQUFJLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxXQUFXLEVBQUUsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBRTFGLE1BQU0sY0FBYyxHQUFHLElBQUksZUFBTSxDQUFDLElBQUksRUFBRSxnQkFBZ0IsRUFBRTtZQUN4RCxlQUFlLEVBQUU7Z0JBQ2YsUUFBUSxFQUFFLEtBQUssQ0FBQyxZQUFZO2dCQUM1QixRQUFRLEVBQUUseUJBQWdCLENBQUMsS0FBSzthQUNqQztZQUNELGFBQWEsRUFBRSxvQkFBYSxDQUFDLE9BQU87WUFDcEMsaUJBQWlCLEVBQUUsMEJBQWlCLENBQUMsU0FBUztTQUMvQyxDQUFDLENBQUM7UUFDSCxNQUFNLFlBQVksR0FBRyxJQUFJLDBDQUF5QixDQUFDLElBQUksRUFBRSxzQkFBc0IsRUFBRTtZQUMvRSxpQkFBaUIsRUFBRSxFQUFFO1lBQ3JCLGFBQWEsRUFBRTtnQkFDYjtvQkFDRSxTQUFTLEVBQUUsQ0FBQyxFQUFFLGlCQUFpQixFQUFFLElBQUksRUFBRSxDQUFDO29CQUN4QyxrQkFBa0IsRUFBRTt3QkFDbEIsVUFBVSxFQUFFLGNBQWMsQ0FBQyx1QkFBdUI7d0JBQ2xELG9CQUFvQixFQUFFLHFDQUFvQixDQUFDLFNBQVM7cUJBQ3JEO2lCQUNGO2FBQ0Y7WUFDRCxpQkFBaUIsRUFBRSxrQ0FBaUIsQ0FBQyxrQkFBa0IsQ0FBQyxZQUFZLEVBQUU7Z0JBQ3BFLE9BQU8sRUFBRSxXQUFXO2FBQ3JCLENBQUM7WUFDRixPQUFPLEVBQUUsZUFBZSxLQUFLLENBQUMsWUFBWSxTQUFTLFdBQVcsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUU7WUFDM0UsVUFBVSxFQUFFLDJCQUFVLENBQUMsZUFBZTtZQUN0QyxvQkFBb0IsRUFBRSxxQ0FBb0IsQ0FBQyxpQkFBaUI7U0FDN0QsQ0FBQyxDQUFDO1FBRUgsV0FBVyxDQUFDLE9BQU8sQ0FBQyxDQUFDLFVBQVUsRUFBRSxFQUFFO1lBQ2pDLE1BQU0sSUFBSSxHQUFHLDBCQUFPLENBQUMsVUFBVSxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztZQUM3Qyx5RUFBeUU7WUFDekUsVUFBVSxHQUFHLDRCQUFvQixDQUFDLFVBQVUsQ0FBQyxDQUFDO1lBQzlDLE1BQU0sVUFBVSxHQUFHO2dCQUNqQixVQUFVLEVBQUUsVUFBVTtnQkFDdEIsSUFBSSxFQUFFLEtBQUssQ0FBQyxJQUFJO2dCQUNoQixNQUFNLEVBQUUsMEJBQVksQ0FBQyxTQUFTLENBQUMsSUFBSSxzQ0FBZ0IsQ0FBQyxZQUFZLENBQUMsQ0FBQzthQUNuRSxDQUFDO1lBQ0YsSUFBSSxxQkFBTyxDQUFDLElBQUksRUFBRSxzQkFBc0IsSUFBSSxFQUFFLEVBQUUsVUFBVSxDQUFDLENBQUM7WUFDNUQsSUFBSSx3QkFBVSxDQUFDLElBQUksRUFBRSx5QkFBeUIsSUFBSSxFQUFFLEVBQUUsVUFBVSxDQUFDLENBQUM7UUFDcEUsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQ7Ozs7Ozs7Ozs7Ozs7OztPQWVHO0lBQ0ssZ0JBQWdCO1FBQ3RCLE1BQU0sS0FBSyxHQUFHLFlBQUssQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDN0IsTUFBTSxNQUFNLEdBQUcsS0FBSyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUM7UUFDaEMsSUFBSSxDQUFDLE1BQU0sRUFBRTtZQUNYLE1BQU0sSUFBSSxLQUFLLENBQUMsU0FBUyxLQUFLLENBQUMsT0FBTyxrREFBa0QsQ0FBQyxDQUFDO1NBQzNGO1FBQ0QsSUFBSSxZQUFLLENBQUMsWUFBWSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsRUFBRTtZQUNwQyxNQUFNLElBQUksS0FBSyxDQUFDLFFBQVEseUNBQWdDLG9EQUFvRCxDQUFDLENBQUM7U0FDL0c7UUFDRCxJQUFJLEtBQUssQ0FBQyxNQUFNLEtBQUssV0FBVyxFQUFFO1lBQ2hDLE1BQU0sT0FBTyxHQUFHLDhCQUE4QixLQUFLLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO1lBQ2hFLE1BQU0sU0FBUyxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLE9BQU8sQ0FBVSxDQUFDO1lBQzdELE9BQU8sQ0FDTCxTQUFTO2dCQUNULElBQUksWUFBSyxDQUFDLE1BQU0sRUFBRSxPQUFPLEVBQUU7b0JBQ3pCLEdBQUcsRUFBRSxFQUFFLE1BQU0sRUFBRSxXQUFXLEVBQUUsT0FBTyxFQUFFLEtBQUssQ0FBQyxPQUFPLEVBQUU7aUJBQ3JELENBQUMsQ0FDSCxDQUFDO1NBQ0g7UUFDRCxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFRDs7T0FFRztJQUNLLGlCQUFpQixDQUFDLFdBQXFCLEVBQUUsSUFBaUI7UUFDaEUsd0dBQXdHO1FBQ3hHLHVDQUF1QztRQUN2QyxNQUFNLEVBQUUsR0FBRyxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsS0FBSyxJQUFJLENBQUMsQ0FBQyxDQUFDLHFCQUFxQixDQUFDLENBQUMsQ0FBQyxxQkFBcUIsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQztRQUM3RyxPQUFPLElBQUksb0NBQVcsQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsRUFBRSxFQUFFLEVBQUU7WUFDbEQsVUFBVSxFQUFFLFdBQVcsQ0FBQyxDQUFDLENBQUM7WUFDMUIsdUJBQXVCLEVBQUUsV0FBVztZQUNwQyxVQUFVLEVBQUUsOENBQXFCLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQztTQUNoRCxDQUFDLENBQUM7SUFDTCxDQUFDO0NBQ0Y7QUEvR0Qsb0RBK0dDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IDIwMTgtMjAyMyBBbWF6b24uY29tLCBJbmMuIG9yIGl0cyBhZmZpbGlhdGVzLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuLy9cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4vLyB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4vLyBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbi8vXG4vLyAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4vL1xuLy8gVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuLy8gZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuLy8gV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4vLyBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4vLyBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuaW1wb3J0IHsgSUNlcnRpZmljYXRlLCBDZXJ0aWZpY2F0ZSwgQ2VydGlmaWNhdGVWYWxpZGF0aW9uIH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWNlcnRpZmljYXRlbWFuYWdlcic7XG5pbXBvcnQge1xuICBDbG91ZEZyb250V2ViRGlzdHJpYnV0aW9uLFxuICBPcmlnaW5Qcm90b2NvbFBvbGljeSxcbiAgUHJpY2VDbGFzcyxcbiAgVmlld2VyQ2VydGlmaWNhdGUsXG4gIFZpZXdlclByb3RvY29sUG9saWN5LFxufSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtY2xvdWRmcm9udCc7XG5pbXBvcnQgeyBBUmVjb3JkLCBBYWFhUmVjb3JkLCBJSG9zdGVkWm9uZSwgUmVjb3JkVGFyZ2V0IH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLXJvdXRlNTMnO1xuaW1wb3J0IHsgQ2xvdWRGcm9udFRhcmdldCB9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1yb3V0ZTUzLXRhcmdldHMnO1xuaW1wb3J0IHsgQmxvY2tQdWJsaWNBY2Nlc3MsIEJ1Y2tldCwgUmVkaXJlY3RQcm90b2NvbCB9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1zMyc7XG5pbXBvcnQgeyBBcm5Gb3JtYXQsIFJlbW92YWxQb2xpY3ksIFN0YWNrLCBUb2tlbiB9IGZyb20gJ2F3cy1jZGstbGliL2NvcmUnO1xuaW1wb3J0IHsgbWQ1aGFzaCB9IGZyb20gJ2F3cy1jZGstbGliL2NvcmUvbGliL2hlbHBlcnMtaW50ZXJuYWwnO1xuaW1wb3J0IHsgUk9VVEU1M19QQVRURVJOU19VU0VfQ0VSVElGSUNBVEUgfSBmcm9tICdhd3MtY2RrLWxpYi9jeC1hcGknO1xuaW1wb3J0IHsgQ29uc3RydWN0IH0gZnJvbSAnY29uc3RydWN0cyc7XG5pbXBvcnQgeyBkb21haW5BZGRUcmFpbGluZ0RvdCB9IGZyb20gJy4vdXRpbHMnO1xuXG4vKipcbiAqIFByb3BlcnRpZXMgdG8gY29uZmlndXJlIGFuIEhUVFBTIFJlZGlyZWN0XG4gKlxuICogUGF0Y2hlZCB2ZXJzaW9uIG9mIGh0dHBzOi8vZ2l0aHViLmNvbS9hd3MvYXdzLWNkay9ibG9iL21haW4vcGFja2FnZXMvYXdzLWNkay1saWIvYXdzLXJvdXRlNTMtcGF0dGVybnMvbGliL3dlYnNpdGUtcmVkaXJlY3QudHNcbiAqIC0gV29ya2Fyb3VuZCBmb3IgaHR0cHM6Ly9naXRodWIuY29tL2F3cy9hd3MtY2RrL2lzc3Vlcy8yNjU3MiB2aWEgZG9tYWluQWRkVHJhaWxpbmdEb3QgcGF0Y2hcbiAqIC0gUmVtb3ZlZCBkZXByZWNhdGVkIERuc1ZhbGlkYXRlZENlcnRpZmljYXRlXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgSHR0cHNSZWRpcmVjdFByb3BzIHtcbiAgLyoqXG4gICAqIEhvc3RlZCB6b25lIG9mIHRoZSBkb21haW4gd2hpY2ggd2lsbCBiZSB1c2VkIHRvIGNyZWF0ZSBhbGlhcyByZWNvcmQocykgZnJvbVxuICAgKiBkb21haW4gbmFtZXMgaW4gdGhlIGhvc3RlZCB6b25lIHRvIHRoZSB0YXJnZXQgZG9tYWluLiBUaGUgaG9zdGVkIHpvbmUgbXVzdFxuICAgKiBjb250YWluIGVudHJpZXMgZm9yIHRoZSBkb21haW4gbmFtZShzKSBzdXBwbGllZCB0aHJvdWdoIGByZWNvcmROYW1lc2AgdGhhdFxuICAgKiB3aWxsIHJlZGlyZWN0IHRvIHRoZSB0YXJnZXQgZG9tYWluLlxuICAgKlxuICAgKiBEb21haW4gbmFtZXMgaW4gdGhlIGhvc3RlZCB6b25lIGNhbiBpbmNsdWRlIGEgc3BlY2lmaWMgZG9tYWluIChleGFtcGxlLmNvbSlcbiAgICogYW5kIGl0cyBzdWJkb21haW5zIChhY21lLmV4YW1wbGUuY29tLCB6ZW5pdGguZXhhbXBsZS5jb20pLlxuICAgKlxuICAgKi9cbiAgcmVhZG9ubHkgem9uZTogSUhvc3RlZFpvbmU7XG5cbiAgLyoqXG4gICAqIFRoZSByZWRpcmVjdCB0YXJnZXQgZnVsbHkgcXVhbGlmaWVkIGRvbWFpbiBuYW1lIChGUUROKS4gQW4gYWxpYXMgcmVjb3JkXG4gICAqIHdpbGwgYmUgY3JlYXRlZCB0aGF0IHBvaW50cyB0byB5b3VyIENsb3VkRnJvbnQgZGlzdHJpYnV0aW9uLiBSb290IGRvbWFpblxuICAgKiBvciBzdWItZG9tYWluIGNhbiBiZSBzdXBwbGllZC5cbiAgICovXG4gIHJlYWRvbmx5IHRhcmdldERvbWFpbjogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgZG9tYWluIG5hbWVzIHRoYXQgd2lsbCByZWRpcmVjdCB0byBgdGFyZ2V0RG9tYWluYFxuICAgKlxuICAgKiBAZGVmYXVsdCAtIHRoZSBkb21haW4gbmFtZSBvZiB0aGUgaG9zdGVkIHpvbmVcbiAgICovXG4gIHJlYWRvbmx5IHJlY29yZE5hbWVzPzogc3RyaW5nW107XG5cbiAgLyoqXG4gICAqIFRoZSBBV1MgQ2VydGlmaWNhdGUgTWFuYWdlciAoQUNNKSBjZXJ0aWZpY2F0ZSB0aGF0IHdpbGwgYmUgYXNzb2NpYXRlZCB3aXRoXG4gICAqIHRoZSBDbG91ZEZyb250IGRpc3RyaWJ1dGlvbiB0aGF0IHdpbGwgYmUgY3JlYXRlZC4gSWYgcHJvdmlkZWQsIHRoZSBjZXJ0aWZpY2F0ZSBtdXN0IGJlXG4gICAqIHN0b3JlZCBpbiB1cy1lYXN0LTEgKE4uIFZpcmdpbmlhKVxuICAgKlxuICAgKiBAZGVmYXVsdCAtIEEgbmV3IGNlcnRpZmljYXRlIGlzIGNyZWF0ZWQgaW4gdXMtZWFzdC0xIChOLiBWaXJnaW5pYSlcbiAgICovXG4gIHJlYWRvbmx5IGNlcnRpZmljYXRlPzogSUNlcnRpZmljYXRlO1xufVxuXG4vKipcbiAqIEFsbG93cyBjcmVhdGluZyBhIGRvbWFpbkEgLT4gZG9tYWluQiByZWRpcmVjdCB1c2luZyBDbG91ZEZyb250IGFuZCBTMy5cbiAqIFlvdSBjYW4gc3BlY2lmeSBtdWx0aXBsZSBkb21haW5zIHRvIGJlIHJlZGlyZWN0ZWQuXG4gKi9cbmV4cG9ydCBjbGFzcyBIdHRwc1JlZGlyZWN0UGF0Y2hlZCBleHRlbmRzIENvbnN0cnVjdCB7XG4gIGNvbnN0cnVjdG9yKHNjb3BlOiBDb25zdHJ1Y3QsIGlkOiBzdHJpbmcsIHByb3BzOiBIdHRwc1JlZGlyZWN0UHJvcHMpIHtcbiAgICBzdXBlcihzY29wZSwgaWQpO1xuXG4gICAgY29uc3QgZG9tYWluTmFtZXMgPSBwcm9wcy5yZWNvcmROYW1lcyA/PyBbcHJvcHMuem9uZS56b25lTmFtZV07XG5cbiAgICBpZiAocHJvcHMuY2VydGlmaWNhdGUpIHtcbiAgICAgIGNvbnN0IGNlcnRpZmljYXRlUmVnaW9uID0gU3RhY2sub2YodGhpcykuc3BsaXRBcm4oXG4gICAgICAgIHByb3BzLmNlcnRpZmljYXRlLmNlcnRpZmljYXRlQXJuLFxuICAgICAgICBBcm5Gb3JtYXQuU0xBU0hfUkVTT1VSQ0VfTkFNRVxuICAgICAgKS5yZWdpb247XG4gICAgICBpZiAoIVRva2VuLmlzVW5yZXNvbHZlZChjZXJ0aWZpY2F0ZVJlZ2lvbikgJiYgY2VydGlmaWNhdGVSZWdpb24gIT09ICd1cy1lYXN0LTEnKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICBgVGhlIGNlcnRpZmljYXRlIG11c3QgYmUgaW4gdGhlIHVzLWVhc3QtMSByZWdpb24gYW5kIHRoZSBjZXJ0aWZpY2F0ZSB5b3UgcHJvdmlkZWQgaXMgaW4gJHtjZXJ0aWZpY2F0ZVJlZ2lvbn0uYFxuICAgICAgICApO1xuICAgICAgfVxuICAgIH1cbiAgICBjb25zdCByZWRpcmVjdENlcnQgPSBwcm9wcy5jZXJ0aWZpY2F0ZSA/PyB0aGlzLmNyZWF0ZUNlcnRpZmljYXRlKGRvbWFpbk5hbWVzLCBwcm9wcy56b25lKTtcblxuICAgIGNvbnN0IHJlZGlyZWN0QnVja2V0ID0gbmV3IEJ1Y2tldCh0aGlzLCAnUmVkaXJlY3RCdWNrZXQnLCB7XG4gICAgICB3ZWJzaXRlUmVkaXJlY3Q6IHtcbiAgICAgICAgaG9zdE5hbWU6IHByb3BzLnRhcmdldERvbWFpbixcbiAgICAgICAgcHJvdG9jb2w6IFJlZGlyZWN0UHJvdG9jb2wuSFRUUFMsXG4gICAgICB9LFxuICAgICAgcmVtb3ZhbFBvbGljeTogUmVtb3ZhbFBvbGljeS5ERVNUUk9ZLFxuICAgICAgYmxvY2tQdWJsaWNBY2Nlc3M6IEJsb2NrUHVibGljQWNjZXNzLkJMT0NLX0FMTCxcbiAgICB9KTtcbiAgICBjb25zdCByZWRpcmVjdERpc3QgPSBuZXcgQ2xvdWRGcm9udFdlYkRpc3RyaWJ1dGlvbih0aGlzLCAnUmVkaXJlY3REaXN0cmlidXRpb24nLCB7XG4gICAgICBkZWZhdWx0Um9vdE9iamVjdDogJycsXG4gICAgICBvcmlnaW5Db25maWdzOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBiZWhhdmlvcnM6IFt7IGlzRGVmYXVsdEJlaGF2aW9yOiB0cnVlIH1dLFxuICAgICAgICAgIGN1c3RvbU9yaWdpblNvdXJjZToge1xuICAgICAgICAgICAgZG9tYWluTmFtZTogcmVkaXJlY3RCdWNrZXQuYnVja2V0V2Vic2l0ZURvbWFpbk5hbWUsXG4gICAgICAgICAgICBvcmlnaW5Qcm90b2NvbFBvbGljeTogT3JpZ2luUHJvdG9jb2xQb2xpY3kuSFRUUF9PTkxZLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgICAgdmlld2VyQ2VydGlmaWNhdGU6IFZpZXdlckNlcnRpZmljYXRlLmZyb21BY21DZXJ0aWZpY2F0ZShyZWRpcmVjdENlcnQsIHtcbiAgICAgICAgYWxpYXNlczogZG9tYWluTmFtZXMsXG4gICAgICB9KSxcbiAgICAgIGNvbW1lbnQ6IGBSZWRpcmVjdCB0byAke3Byb3BzLnRhcmdldERvbWFpbn0gZnJvbSAke2RvbWFpbk5hbWVzLmpvaW4oJywgJyl9YCxcbiAgICAgIHByaWNlQ2xhc3M6IFByaWNlQ2xhc3MuUFJJQ0VfQ0xBU1NfQUxMLFxuICAgICAgdmlld2VyUHJvdG9jb2xQb2xpY3k6IFZpZXdlclByb3RvY29sUG9saWN5LlJFRElSRUNUX1RPX0hUVFBTLFxuICAgIH0pO1xuXG4gICAgZG9tYWluTmFtZXMuZm9yRWFjaCgoZG9tYWluTmFtZSkgPT4ge1xuICAgICAgY29uc3QgaGFzaCA9IG1kNWhhc2goZG9tYWluTmFtZSkuc2xpY2UoMCwgNik7XG4gICAgICAvLyBkb21haW5BZGRUcmFpbGluZ0RvdCBmaXhlcyBhYmlsaXR5IHRvIHVzZSBDZm5QYXJhbWV0ZXJzIGFzIGRvbWFpbiBuYW1lXG4gICAgICBkb21haW5OYW1lID0gZG9tYWluQWRkVHJhaWxpbmdEb3QoZG9tYWluTmFtZSk7XG4gICAgICBjb25zdCBhbGlhc1Byb3BzID0ge1xuICAgICAgICByZWNvcmROYW1lOiBkb21haW5OYW1lLFxuICAgICAgICB6b25lOiBwcm9wcy56b25lLFxuICAgICAgICB0YXJnZXQ6IFJlY29yZFRhcmdldC5mcm9tQWxpYXMobmV3IENsb3VkRnJvbnRUYXJnZXQocmVkaXJlY3REaXN0KSksXG4gICAgICB9O1xuICAgICAgbmV3IEFSZWNvcmQodGhpcywgYFJlZGlyZWN0QWxpYXNSZWNvcmQke2hhc2h9YCwgYWxpYXNQcm9wcyk7XG4gICAgICBuZXcgQWFhYVJlY29yZCh0aGlzLCBgUmVkaXJlY3RBbGlhc1JlY29yZFNpeCR7aGFzaH1gLCBhbGlhc1Byb3BzKTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXRzIHRoZSBzdGFjayB0byB1c2UgZm9yIGNyZWF0aW5nIHRoZSBDZXJ0aWZpY2F0ZVxuICAgKiBJZiB0aGUgY3VycmVudCBzdGFjayBpcyBub3QgaW4gYHVzLWVhc3QtMWAgdGhlbiB0aGlzXG4gICAqIHdpbGwgY3JlYXRlIGEgbmV3IGB1cy1lYXN0LTFgIHN0YWNrLlxuICAgKlxuICAgKiBDbG91ZEZyb250IGlzIGEgZ2xvYmFsIHJlc291cmNlIHdoaWNoIHlvdSBjYW4gY3JlYXRlICh2aWEgQ2xvdWRGb3JtYXRpb24pIGZyb21cbiAgICogX2FueV8gcmVnaW9uLiBTbyBJIGNvdWxkIGNyZWF0ZSBhIENsb3VkRnJvbnQgZGlzdHJpYnV0aW9uIGluIGB1cy1lYXN0LTJgIGlmIEkgd2FudGVkXG4gICAqIHRvIChtYXliZSB0aGUgcmVzdCBvZiBteSBhcHBsaWNhdGlvbiBsaXZlcyB0aGVyZSkuIFRoZSBwcm9ibGVtIGlzIHRoYXQgc29tZSBzdXBwb3J0aW5nIHJlc291cmNlc1xuICAgKiB0aGF0IENsb3VkRnJvbnQgdXNlcyAoaS5lLiBBQ00gQ2VydGlmaWNhdGVzKSBhcmUgcmVxdWlyZWQgdG8gZXhpc3QgaW4gYHVzLWVhc3QtMWAuIFRoaXMgbWVhbnNcbiAgICogdGhhdCBpZiBJIHdhbnQgdG8gY3JlYXRlIGEgQ2xvdWRGcm9udCBkaXN0cmlidXRpb24gaW4gYHVzLWVhc3QtMmAgSSBzdGlsbCBuZWVkIHRvIGNyZWF0ZSBhIEFDTSBjZXJ0aWZpY2F0ZSBpblxuICAgKiBgdXMtZWFzdC0xYC5cbiAgICpcbiAgICogSW4gb3JkZXIgdG8gZG8gdGhpcyBjb3JyZWN0bHkgd2UgbmVlZCB0byBrbm93IHdoaWNoIHJlZ2lvbiB0aGUgQ2xvdWRGcm9udCBkaXN0cmlidXRpb24gaXMgYmVpbmcgY3JlYXRlZCBpbi5cbiAgICogV2UgaGF2ZSB0d28gb3B0aW9ucywgZWl0aGVyIHJlcXVpcmUgdGhlIHVzZXIgdG8gc3BlY2lmeSB0aGUgcmVnaW9uIG9yIG1ha2UgYW4gYXNzdW1wdGlvbiBpZiB0aGV5IGRvIG5vdC5cbiAgICogVGhpcyBpbXBsZW1lbnRhdGlvbiByZXF1aXJlcyB0aGUgdXNlciBzcGVjaWZ5IHRoZSByZWdpb24uXG4gICAqL1xuICBwcml2YXRlIGNlcnRpZmljYXRlU2NvcGUoKTogQ29uc3RydWN0IHtcbiAgICBjb25zdCBzdGFjayA9IFN0YWNrLm9mKHRoaXMpO1xuICAgIGNvbnN0IHBhcmVudCA9IHN0YWNrLm5vZGUuc2NvcGU7XG4gICAgaWYgKCFwYXJlbnQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgU3RhY2sgJHtzdGFjay5zdGFja0lkfSBtdXN0IGJlIGNyZWF0ZWQgaW4gdGhlIHNjb3BlIG9mIGFuIEFwcCBvciBTdGFnZWApO1xuICAgIH1cbiAgICBpZiAoVG9rZW4uaXNVbnJlc29sdmVkKHN0YWNrLnJlZ2lvbikpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgV2hlbiAke1JPVVRFNTNfUEFUVEVSTlNfVVNFX0NFUlRJRklDQVRFfSBpcyBlbmFibGVkLCBhIHJlZ2lvbiBtdXN0IGJlIGRlZmluZWQgb24gdGhlIFN0YWNrYCk7XG4gICAgfVxuICAgIGlmIChzdGFjay5yZWdpb24gIT09ICd1cy1lYXN0LTEnKSB7XG4gICAgICBjb25zdCBzdGFja0lkID0gYGNlcnRpZmljYXRlLXJlZGlyZWN0LXN0YWNrLSR7c3RhY2subm9kZS5hZGRyfWA7XG4gICAgICBjb25zdCBjZXJ0U3RhY2sgPSBwYXJlbnQubm9kZS50cnlGaW5kQ2hpbGQoc3RhY2tJZCkgYXMgU3RhY2s7XG4gICAgICByZXR1cm4gKFxuICAgICAgICBjZXJ0U3RhY2sgPz9cbiAgICAgICAgbmV3IFN0YWNrKHBhcmVudCwgc3RhY2tJZCwge1xuICAgICAgICAgIGVudjogeyByZWdpb246ICd1cy1lYXN0LTEnLCBhY2NvdW50OiBzdGFjay5hY2NvdW50IH0sXG4gICAgICAgIH0pXG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgY2VydGlmaWNhdGUuXG4gICAqL1xuICBwcml2YXRlIGNyZWF0ZUNlcnRpZmljYXRlKGRvbWFpbk5hbWVzOiBzdHJpbmdbXSwgem9uZTogSUhvc3RlZFpvbmUpOiBJQ2VydGlmaWNhdGUge1xuICAgIC8vIHRoaXMgcHJlc2VydmVzIGJhY2t3YXJkcyBjb21wYXRpYmlsaXR5LiBQcmV2aW91c2x5IHRoZSBjZXJ0aWZpY2F0ZSB3YXMgYWx3YXlzIGNyZWF0ZWQgaW4gYHRoaXNgIHNjb3BlXG4gICAgLy8gc28gd2UgbmVlZCB0byBrZWVwIHRoZSBuYW1lIHRoZSBzYW1lXG4gICAgY29uc3QgaWQgPSB0aGlzLmNlcnRpZmljYXRlU2NvcGUoKSA9PT0gdGhpcyA/ICdSZWRpcmVjdENlcnRpZmljYXRlJyA6ICdSZWRpcmVjdENlcnRpZmljYXRlJyArIHRoaXMubm9kZS5hZGRyO1xuICAgIHJldHVybiBuZXcgQ2VydGlmaWNhdGUodGhpcy5jZXJ0aWZpY2F0ZVNjb3BlKCksIGlkLCB7XG4gICAgICBkb21haW5OYW1lOiBkb21haW5OYW1lc1swXSxcbiAgICAgIHN1YmplY3RBbHRlcm5hdGl2ZU5hbWVzOiBkb21haW5OYW1lcyxcbiAgICAgIHZhbGlkYXRpb246IENlcnRpZmljYXRlVmFsaWRhdGlvbi5mcm9tRG5zKHpvbmUpLFxuICAgIH0pO1xuICB9XG59XG4iXX0=