@aws-solutions-constructs/aws-cloudfront-s3
Version:
CDK Constructs for AWS Cloudfront to AWS S3 integration.
126 lines • 25.6 kB
JavaScript
;
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
exports.CloudFrontToS3 = void 0;
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
/**
* Copyright 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. A copy of the License is located at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES
* OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions
* and limitations under the License.
*/
const aws_cdk_lib_1 = require("aws-cdk-lib");
const iam = require("aws-cdk-lib/aws-iam");
const defaults = require("@aws-solutions-constructs/core");
const resources = require("@aws-solutions-constructs/resources");
// Note: To ensure CDKv2 compatibility, keep the import statement for Construct separate
const constructs_1 = require("constructs");
class CloudFrontToS3 extends constructs_1.Construct {
/**
* @summary Constructs a new instance of the CloudFrontToS3 class.
* @param {Construct} scope - represents the scope for all the resources.
* @param {string} id - this is a a scope-unique id.
* @param {CloudFrontToS3Props} props - user provided props for the construct
* @since 0.8.0
* @access public
*/
constructor(scope, id, props) {
super(scope, id);
// All our tests are based upon this behavior being on, so we're setting
// context here rather than assuming the client will set it
this.node.setContext("@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy", true);
defaults.CheckS3Props(props);
defaults.CheckCloudFrontProps(props);
defaults.CheckCloudfrontS3Props(props);
let originBucket;
if (!props.existingBucketObj) {
const buildS3BucketResponse = defaults.buildS3Bucket(this, {
bucketProps: props.bucketProps,
loggingBucketProps: props.loggingBucketProps,
logS3AccessLogs: props.logS3AccessLogs
});
this.s3Bucket = buildS3BucketResponse.bucket;
this.s3LoggingBucket = buildS3BucketResponse.loggingBucket;
originBucket = this.s3Bucket;
}
else {
originBucket = props.existingBucketObj;
}
this.s3BucketInterface = originBucket;
// Define the CloudFront Distribution
const cloudFrontDistributionForS3Props = {
sourceBucket: this.s3BucketInterface,
cloudFrontDistributionProps: props.cloudFrontDistributionProps,
httpSecurityHeaders: props.insertHttpSecurityHeaders,
cloudFrontLoggingBucketProps: props.cloudFrontLoggingBucketProps,
responseHeadersPolicyProps: props.responseHeadersPolicyProps,
cloudFrontLoggingBucketS3AccessLogBucketProps: props.cloudFrontLoggingBucketAccessLogBucketProps,
logCloudFrontAccessLog: props.logCloudFrontAccessLog
};
const cloudFrontDistributionForS3Response = defaults.createCloudFrontDistributionForS3(this, id, cloudFrontDistributionForS3Props);
this.cloudFrontWebDistribution = cloudFrontDistributionForS3Response.distribution;
this.cloudFrontFunction = cloudFrontDistributionForS3Response.cloudfrontFunction;
this.cloudFrontLoggingBucket = cloudFrontDistributionForS3Response.loggingBucket;
this.originAccessControl = cloudFrontDistributionForS3Response.originAccessControl;
this.cloudFrontLoggingBucketAccessLogBucket = cloudFrontDistributionForS3Response.loggingBucketS3AccesssLogBucket;
// Attach the OriginAccessControl to the CloudFront Distribution, and remove the OriginAccessIdentity
const l1CloudFrontDistribution = this.cloudFrontWebDistribution.node.defaultChild;
l1CloudFrontDistribution.addPropertyOverride('DistributionConfig.Origins.0.OriginAccessControlId', this.originAccessControl?.attrId);
if (props.originPath) {
l1CloudFrontDistribution.addPropertyOverride('DistributionConfig.Origins.0.OriginPath', props.originPath);
}
// Grant CloudFront permission to get the objects from the s3 bucket origin
originBucket.addToResourcePolicy(new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
actions: ['s3:GetObject'],
principals: [new iam.ServicePrincipal('cloudfront.amazonaws.com')],
resources: [originBucket.arnForObjects('*')],
conditions: {
StringEquals: {
'AWS:SourceArn': `arn:${aws_cdk_lib_1.Aws.PARTITION}:cloudfront::${aws_cdk_lib_1.Aws.ACCOUNT_ID}:distribution/${this.cloudFrontWebDistribution.distributionId}`
}
}
}));
originBucket.addToResourcePolicy(new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
actions: ['s3:ListBucket'],
principals: [new iam.ServicePrincipal('cloudfront.amazonaws.com')],
resources: [originBucket.bucketArn],
conditions: {
StringEquals: {
'AWS:SourceArn': `arn:${aws_cdk_lib_1.Aws.PARTITION}:cloudfront::${aws_cdk_lib_1.Aws.ACCOUNT_ID}:distribution/${this.cloudFrontWebDistribution.distributionId}`
}
}
}));
// We need to create a custom resource to introduce the indirection necessary to avoid
// a circular dependency when granting the CloudFront distribution access to use the
// KMS key to decrypt objects. Without this indirection, it is not possible to reference
// the CloudFront distribution ID in the KMS key policy because -
// * The S3 bucket references the KMS key
// * The CloudFront distribution references the bucket
// * The KMS key references the CloudFront distribution
let encryptionKey;
if (props.bucketProps && props.bucketProps.encryptionKey) {
encryptionKey = props.bucketProps.encryptionKey;
}
else if (props.existingBucketObj && props.existingBucketObj.encryptionKey) {
encryptionKey = props.existingBucketObj.encryptionKey;
}
if (encryptionKey) {
resources.createKeyPolicyUpdaterCustomResource(this, id, {
distribution: this.cloudFrontWebDistribution,
encryptionKey
});
}
}
}
exports.CloudFrontToS3 = CloudFrontToS3;
_a = JSII_RTTI_SYMBOL_1;
CloudFrontToS3[_a] = { fqn: "@aws-solutions-constructs/aws-cloudfront-s3.CloudFrontToS3", version: "2.97.0" };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBOzs7Ozs7Ozs7OztHQVdHO0FBRUgsNkNBQWtDO0FBRWxDLDJDQUEyQztBQUczQywyREFBMkQ7QUFDM0QsaUVBQWlFO0FBQ2pFLHdGQUF3RjtBQUN4RiwyQ0FBdUM7QUF3R3ZDLE1BQWEsY0FBZSxTQUFRLHNCQUFTO0lBVTNDOzs7Ozs7O09BT0c7SUFDSCxZQUFZLEtBQWdCLEVBQUUsRUFBVSxFQUFFLEtBQTBCO1FBQ2xFLEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFFakIsd0VBQXdFO1FBQ3hFLDJEQUEyRDtRQUMzRCxJQUFJLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxpREFBaUQsRUFBRSxJQUFJLENBQUMsQ0FBQztRQUU5RSxRQUFRLENBQUMsWUFBWSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQzdCLFFBQVEsQ0FBQyxvQkFBb0IsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNyQyxRQUFRLENBQUMsc0JBQXNCLENBQUMsS0FBSyxDQUFDLENBQUM7UUFFdkMsSUFBSSxZQUF3QixDQUFDO1FBRTdCLElBQUksQ0FBQyxLQUFLLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztZQUM3QixNQUFNLHFCQUFxQixHQUFHLFFBQVEsQ0FBQyxhQUFhLENBQUMsSUFBSSxFQUFFO2dCQUN6RCxXQUFXLEVBQUUsS0FBSyxDQUFDLFdBQVc7Z0JBQzlCLGtCQUFrQixFQUFFLEtBQUssQ0FBQyxrQkFBa0I7Z0JBQzVDLGVBQWUsRUFBRSxLQUFLLENBQUMsZUFBZTthQUN2QyxDQUFDLENBQUM7WUFDSCxJQUFJLENBQUMsUUFBUSxHQUFHLHFCQUFxQixDQUFDLE1BQU0sQ0FBQztZQUM3QyxJQUFJLENBQUMsZUFBZSxHQUFHLHFCQUFxQixDQUFDLGFBQWEsQ0FBQztZQUMzRCxZQUFZLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQztR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O1NBQ0YsQ0FBQyxDQUNILENBQUM7UUFFRixzRkFBc0Y7UUFDdEYsb0ZBQW9GO1FBQ3BGLHdGQUF3RjtRQUN4RixpRUFBaUU7UUFDakUsMkNBQTJDO1FBQzNDLHdEQUF3RDtRQUN4RCx5REFBeUQ7UUFDekQsSUFBSSxhQUFtQyxDQUFDO1FBQ3hDLElBQUksS0FBSyxDQUFDLFdBQVcsSUFBSSxLQUFLLENBQUMsV0FBVyxDQUFDLGFBQWEsRUFBRSxDQUFDO1lBQ3pELGFBQWEsR0FBRyxLQUFLLENBQUMsV0FBVyxDQUFDLGFBQWEsQ0FBQztRQUNsRCxDQUFDO2FBQU0sSUFBSSxLQUFLLENBQUMsaUJBQWlCLElBQUksS0FBSyxDQUFDLGlCQUFpQixDQUFDLGFBQWEsRUFBRSxDQUFDO1lBQzVFLGFBQWEsR0FBRyxLQUFLLENBQUMsaUJBQWlCLENBQUMsYUFBYSxDQUFDO1FBQ3hELENBQUM7UUFFRCxJQUFJLGFBQWEsRUFBRSxDQUFDO1lBQ2xCLFNBQVMsQ0FBQyxvQ0FBb0MsQ0FBQyxJQUFJLEVBQUUsRUFBRSxFQUFHO2dCQUN4RCxZQUFZLEVBQUUsSUFBSSxDQUFDLHlCQUF5QjtnQkFDNUMsYUFBYTthQUNkLENBQUMsQ0FBQztRQUNMLENBQUM7SUFDSCxDQUFDOztBQXZISCx3Q0F3SEMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqICBDb3B5cmlnaHQgQW1hem9uLmNvbSwgSW5jLiBvciBpdHMgYWZmaWxpYXRlcy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqXG4gKiAgTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKS4gWW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZVxuICogIHdpdGggdGhlIExpY2Vuc2UuIEEgY29weSBvZiB0aGUgTGljZW5zZSBpcyBsb2NhdGVkIGF0XG4gKlxuICogICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiAgb3IgaW4gdGhlICdsaWNlbnNlJyBmaWxlIGFjY29tcGFueWluZyB0aGlzIGZpbGUuIFRoaXMgZmlsZSBpcyBkaXN0cmlidXRlZCBvbiBhbiAnQVMgSVMnIEJBU0lTLCBXSVRIT1VUIFdBUlJBTlRJRVNcbiAqICBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBleHByZXNzIG9yIGltcGxpZWQuIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9uc1xuICogIGFuZCBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBBd3MgfSBmcm9tICdhd3MtY2RrLWxpYic7XG5pbXBvcnQgKiBhcyBjbG91ZGZyb250IGZyb20gJ2F3cy1jZGstbGliL2F3cy1jbG91ZGZyb250JztcbmltcG9ydCAqIGFzIGlhbSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtaWFtJztcbmltcG9ydCAqIGFzIGttcyBmcm9tICdhd3MtY2RrLWxpYi9hd3Mta21zJztcbmltcG9ydCAqIGFzIHMzIGZyb20gJ2F3cy1jZGstbGliL2F3cy1zMyc7XG5pbXBvcnQgKiBhcyBkZWZhdWx0cyBmcm9tICdAYXdzLXNvbHV0aW9ucy1jb25zdHJ1Y3RzL2NvcmUnO1xuaW1wb3J0ICogYXMgcmVzb3VyY2VzIGZyb20gJ0Bhd3Mtc29sdXRpb25zLWNvbnN0cnVjdHMvcmVzb3VyY2VzJztcbi8vIE5vdGU6IFRvIGVuc3VyZSBDREt2MiBjb21wYXRpYmlsaXR5LCBrZWVwIHRoZSBpbXBvcnQgc3RhdGVtZW50IGZvciBDb25zdHJ1Y3Qgc2VwYXJhdGVcbmltcG9ydCB7IENvbnN0cnVjdCB9IGZyb20gJ2NvbnN0cnVjdHMnO1xuXG4vKipcbiAqIEBzdW1tYXJ5IFRoZSBwcm9wZXJ0aWVzIGZvciB0aGUgQ2xvdWRGcm9udFRvUzMgQ29uc3RydWN0XG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQ2xvdWRGcm9udFRvUzNQcm9wcyB7XG4gIC8qKlxuICAgKiBPcHRpb25hbCB1c2VyIHByb3ZpZGVkIHByb3BzIHRvIG92ZXJyaWRlIHRoZSBkZWZhdWx0IHByb3BzXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gRGVmYXVsdCBwcm9wcyBhcmUgdXNlZFxuICAgKi9cbiAgcmVhZG9ubHkgY2xvdWRGcm9udERpc3RyaWJ1dGlvblByb3BzPzogY2xvdWRmcm9udC5EaXN0cmlidXRpb25Qcm9wcyB8IGFueSxcbiAgLyoqXG4gICAqIE9wdGlvbmFsIHVzZXIgcHJvdmlkZWQgcHJvcHMgdG8gdHVybiBvbi9vZmYgdGhlIGF1dG9tYXRpYyBpbmplY3Rpb24gb2YgYmVzdCBwcmFjdGljZSBIVFRQXG4gICAqIHNlY3VyaXR5IGhlYWRlcnMgaW4gYWxsIHJlc3BvbnNlcyBmcm9tIGNsb3VkZnJvbnQuXG4gICAqIFR1cm5pbmcgdGhpcyBvbiB3aWxsIGluamVjdCBkZWZhdWx0IGhlYWRlcnMgYW5kIGlzIG11dHVhbGx5IGV4Y2x1c2l2ZSB3aXRoIHBhc3NpbmcgY3VzdG9tIHNlY3VyaXR5IGhlYWRlcnNcbiAgICogdmlhIHRoZSByZXNwb25zZUhlYWRlcnNQb2xpY3lQcm9wcyBwYXJhbWV0ZXIuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gdHJ1ZVxuICAgKi9cbiAgcmVhZG9ubHkgaW5zZXJ0SHR0cFNlY3VyaXR5SGVhZGVycz86IGJvb2xlYW47XG4gIC8qKlxuICAgKiBPcHRpb25hbCB1c2VyIHByb3ZpZGVkIGNvbmZpZ3VyYXRpb24gdGhhdCBjbG91ZGZyb250IGFwcGxpZXMgdG8gYWxsIGh0dHAgcmVzcG9uc2VzLlxuICAgKiBDYW4gYmUgdXNlZCB0byBwYXNzIGEgY3VzdG9tIFJlc3BvbnNlU2VjdXJpdHlIZWFkZXJzQmVoYXZpb3IsIFJlc3BvbnNlQ3VzdG9tSGVhZGVyc0JlaGF2aW9yIG9yXG4gICAqIFJlc3BvbnNlSGVhZGVyc0NvcnNCZWhhdmlvciB0byB0aGUgY2xvdWRmcm9udCBkaXN0cmlidXRpb24uXG4gICAqXG4gICAqIFBhc3NpbmcgYSBjdXN0b20gUmVzcG9uc2VTZWN1cml0eUhlYWRlcnNCZWhhdmlvciBpcyBtdXR1YWxseSBleGNsdXNpdmUgd2l0aCB0dXJuaW5nIG9uIHRoZSBkZWZhdWx0IHNlY3VyaXR5IGhlYWRlcnNcbiAgICogdmlhIGBpbnNlcnRIdHRwU2VjdXJpdHlIZWFkZXJzYCBwcm9wLiBXaWxsIHRocm93IGFuIGVycm9yIGlmIGJvdGggYGluc2VydEh0dHBTZWN1cml0eUhlYWRlcnNgIGlzIHNldCB0byBgdHJ1ZWBcbiAgICogYW5kIFJlc3BvbnNlU2VjdXJpdHlIZWFkZXJzQmVoYXZpb3IgaXMgcGFzc2VkLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIHVuZGVmaW5lZFxuICAgKi9cbiAgcmVhZG9ubHkgcmVzcG9uc2VIZWFkZXJzUG9saWN5UHJvcHM/OiBjbG91ZGZyb250LlJlc3BvbnNlSGVhZGVyc1BvbGljeVByb3BzXG4gIC8qKlxuICAgKiBPcHRpb25hbCB1c2VyIHByb3ZpZGVkIHByb3BzIHRvIHByb3ZpZGUgYW4gb3JpZ2luUGF0aCB0aGF0IENsb3VkRnJvbnQgYXBwZW5kcyB0byB0aGVcbiAgICogb3JpZ2luIGRvbWFpbiBuYW1lIHdoZW4gQ2xvdWRGcm9udCByZXF1ZXN0cyBjb250ZW50IGZyb20gdGhlIG9yaWdpbi5cbiAgICogVGhlIHN0cmluZyBzaG91bGQgc3RhcnQgd2l0aCBhIGAvYCwgZm9yIGV4YW1wbGUgYC9wcm9kdWN0aW9uYC5cbiAgICogQGRlZmF1bHQgPSAnLydcbiAgICovXG4gIHJlYWRvbmx5IG9yaWdpblBhdGg/OiBzdHJpbmcsXG5cbiAgLy8gPT09PT09PT09PT09PT09PT09PT09XG4gIC8vIFMzIENvbnRlbnQgQnVja2V0XG4gIC8vID09PT09PT09PT09PT09PT09PT09PVxuICAvKipcbiAgICogT3B0aW9uYWwgLSBleGlzdGluZyBpbnN0YW5jZSBvZiBTMyBCdWNrZXQuIElmIHRoaXMgaXMgcHJvdmlkZWQsIHRoZW4gYWxzbyBwcm92aWRpbmcgYnVja2V0UHJvcHMgaXMgYW4gZXJyb3IuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gTm9uZVxuICAgKi9cbiAgcmVhZG9ubHkgZXhpc3RpbmdCdWNrZXRPYmo/OiBzMy5JQnVja2V0LFxuICAvKipcbiAgICogT3B0aW9uYWwgdXNlciBwcm92aWRlZCBwcm9wcyB0byBvdmVycmlkZSB0aGUgZGVmYXVsdCBwcm9wcyBmb3IgdGhlIFMzIENvbnRlbnQgQnVja2V0LCBwcm92aWRpbmcgYm90aCB0aGlzIGFuZCBgZXhpc3RpbmdCdWNrZXRPYmpgXG4gICAqIHdpbGwgY2F1c2UgYW4gZXJyb3IuIE5vdGUgLSB0byBsb2cgUzMgYWNjZXNzIGZvciB0aGlzIGJ1Y2tldCB0byBhbiBleGlzdGluZyBTMyBidWNrZXQsIHB1dCB0aGUgZXhpc3RpbmcgbG9nIGJ1Y2tldCBpbiBidWNrZXRQcm9wczpcbiAgICogYHNlcnZlckFjY2Vzc0xvZ3NCdWNrZXRgXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gRGVmYXVsdCBwcm9wcyBhcmUgdXNlZFxuICAgKi9cbiAgcmVhZG9ubHkgYnVja2V0UHJvcHM/OiBzMy5CdWNrZXRQcm9wcyxcblxuICAvLyA9PT09PT09PT09PT09PT09PT09PT1cbiAgLy8gUzMgQ29udGVudCBCdWNrZXQgQWNjZXNzIExvZ3MgQnVja2V0XG4gIC8vID09PT09PT09PT09PT09PT09PT09PVxuICAvKipcbiAgICogT3B0aW9uYWwgLSBXaGV0aGVyIHRvIG1haW50YWluIGFjY2VzcyBsb2dzIGZvciB0aGUgUzMgQ29udGVudCBidWNrZXRcbiAgICpcbiAgICogQGRlZmF1bHQgLSB0cnVlXG4gICAqL1xuICByZWFkb25seSBsb2dTM0FjY2Vzc0xvZ3M/OiBib29sZWFuLFxuICAvKipcbiAgICogT3B0aW9uYWwgdXNlciBwcm92aWRlZCBwcm9wcyB0byBvdmVycmlkZSB0aGUgZGVmYXVsdCBwcm9wcyBmb3IgdGhlIFMzIENvbnRlbnQgQnVja2V0IEFjY2VzcyBMb2cgQnVja2V0LlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIERlZmF1bHQgcHJvcHMgYXJlIHVzZWRcbiAgICovXG4gIHJlYWRvbmx5IGxvZ2dpbmdCdWNrZXRQcm9wcz86IHMzLkJ1Y2tldFByb3BzLFxuXG4gIC8vID09PT09PT09PT09PT09PT09PT09PVxuICAvLyBDbG91ZEZyb250IExvZyBCdWNrZXRcbiAgLy8gPT09PT09PT09PT09PT09PT09PT09XG4gIC8qKlxuICAgKiBPcHRpb25hbCB1c2VyIHByb3ZpZGVkIHByb3BzIHRvIG92ZXJyaWRlIHRoZSBkZWZhdWx0IHByb3BzIGZvciB0aGUgQ2xvdWRGcm9udCBMb2cgQnVja2V0LlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIERlZmF1bHQgcHJvcHMgYXJlIHVzZWRcbiAgICovXG4gIHJlYWRvbmx5IGNsb3VkRnJvbnRMb2dnaW5nQnVja2V0UHJvcHM/OiBzMy5CdWNrZXRQcm9wcyxcblxuICAvLyA9PT09PT09PT09PT09PT09PT09PT1cbiAgLy8gQ2xvdWRGcm9udCBMb2dzIEJ1Y2tldCBBY2Nlc3MgTG9nIEJ1Y2tldFxuICAvLyA9PT09PT09PT09PT09PT09PT09PT1cbiAgLyoqXG4gICAqIE9wdGlvbmFsIC0gV2hldGhlciB0byBtYWludGFpbiBhY2Nlc3MgbG9ncyBmb3IgdGhlIENsb3VkRnJvbnQgTG9nZ2luZyBidWNrZXQuIFNwZWNpZnlpbmcgZmFsc2UgZm9yIHRoaXNcbiAgICogd2hpbGUgcHJvdmlkaW5nIGluZm8gYWJvdXQgdGhlIGxvZyBidWNrZXQgd2lsbCBjYXVzZSBhbiBlcnJvci5cbiAgICpcbiAgICogQGRlZmF1bHQgLSB0cnVlXG4gICAqL1xuICByZWFkb25seSBsb2dDbG91ZEZyb250QWNjZXNzTG9nPzogYm9vbGVhbixcbiAgLyoqXG4gICAqIE9wdGlvbmFsIHVzZXIgcHJvdmlkZWQgcHJvcHMgdG8gb3ZlcnJpZGUgdGhlIGRlZmF1bHQgcHJvcHMgZm9yIHRoZSBDbG91ZEZyb250IExvZyBCdWNrZXQgQWNjZXNzIExvZyBidWNrZXQuXG4gICAqIFByb3ZpZGluZyBib3RoIHRoaXMgYW5kIGBleGlzdGluZ2Nsb3VkRnJvbnRMb2dnaW5nQnVja2V0QWNjZXNzTG9nQnVja2V0YCB3aWxsIGNhdXNlIGFuIGVycm9yXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gRGVmYXVsdCBwcm9wcyBhcmUgdXNlZFxuICAgKi9cbiAgcmVhZG9ubHkgY2xvdWRGcm9udExvZ2dpbmdCdWNrZXRBY2Nlc3NMb2dCdWNrZXRQcm9wcz86IHMzLkJ1Y2tldFByb3BzLFxufVxuXG5leHBvcnQgY2xhc3MgQ2xvdWRGcm9udFRvUzMgZXh0ZW5kcyBDb25zdHJ1Y3Qge1xuICBwdWJsaWMgcmVhZG9ubHkgY2xvdWRGcm9udFdlYkRpc3RyaWJ1dGlvbjogY2xvdWRmcm9udC5EaXN0cmlidXRpb247XG4gIHB1YmxpYyByZWFkb25seSBjbG91ZEZyb250RnVuY3Rpb24/OiBjbG91ZGZyb250LkZ1bmN0aW9uO1xuICBwdWJsaWMgcmVhZG9ubHkgY2xvdWRGcm9udExvZ2dpbmdCdWNrZXQ/OiBzMy5CdWNrZXQ7XG4gIHB1YmxpYyByZWFkb25seSBjbG91ZEZyb250TG9nZ2luZ0J1Y2tldEFjY2Vzc0xvZ0J1Y2tldD86IHMzLkJ1Y2tldDtcbiAgcHVibGljIHJlYWRvbmx5IHMzQnVja2V0SW50ZXJmYWNlOiBzMy5JQnVja2V0O1xuICBwdWJsaWMgcmVhZG9ubHkgczNCdWNrZXQ/OiBzMy5CdWNrZXQ7XG4gIHB1YmxpYyByZWFkb25seSBzM0xvZ2dpbmdCdWNrZXQ/OiBzMy5CdWNrZXQ7XG4gIHB1YmxpYyByZWFkb25seSBvcmlnaW5BY2Nlc3NDb250cm9sPzogY2xvdWRmcm9udC5DZm5PcmlnaW5BY2Nlc3NDb250cm9sO1xuXG4gIC8qKlxuICAgKiBAc3VtbWFyeSBDb25zdHJ1Y3RzIGEgbmV3IGluc3RhbmNlIG9mIHRoZSBDbG91ZEZyb250VG9TMyBjbGFzcy5cbiAgICogQHBhcmFtIHtDb25zdHJ1Y3R9IHNjb3BlIC0gcmVwcmVzZW50cyB0aGUgc2NvcGUgZm9yIGFsbCB0aGUgcmVzb3VyY2VzLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gaWQgLSB0aGlzIGlzIGEgYSBzY29wZS11bmlxdWUgaWQuXG4gICAqIEBwYXJhbSB7Q2xvdWRGcm9udFRvUzNQcm9wc30gcHJvcHMgLSB1c2VyIHByb3ZpZGVkIHByb3BzIGZvciB0aGUgY29uc3RydWN0XG4gICAqIEBzaW5jZSAwLjguMFxuICAgKiBAYWNjZXNzIHB1YmxpY1xuICAgKi9cbiAgY29uc3RydWN0b3Ioc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgcHJvcHM6IENsb3VkRnJvbnRUb1MzUHJvcHMpIHtcbiAgICBzdXBlcihzY29wZSwgaWQpO1xuXG4gICAgLy8gQWxsIG91ciB0ZXN0cyBhcmUgYmFzZWQgdXBvbiB0aGlzIGJlaGF2aW9yIGJlaW5nIG9uLCBzbyB3ZSdyZSBzZXR0aW5nXG4gICAgLy8gY29udGV4dCBoZXJlIHJhdGhlciB0aGFuIGFzc3VtaW5nIHRoZSBjbGllbnQgd2lsbCBzZXQgaXRcbiAgICB0aGlzLm5vZGUuc2V0Q29udGV4dChcIkBhd3MtY2RrL2F3cy1zMzpzZXJ2ZXJBY2Nlc3NMb2dzVXNlQnVja2V0UG9saWN5XCIsIHRydWUpO1xuXG4gICAgZGVmYXVsdHMuQ2hlY2tTM1Byb3BzKHByb3BzKTtcbiAgICBkZWZhdWx0cy5DaGVja0Nsb3VkRnJvbnRQcm9wcyhwcm9wcyk7XG4gICAgZGVmYXVsdHMuQ2hlY2tDbG91ZGZyb250UzNQcm9wcyhwcm9wcyk7XG5cbiAgICBsZXQgb3JpZ2luQnVja2V0OiBzMy5JQnVja2V0O1xuXG4gICAgaWYgKCFwcm9wcy5leGlzdGluZ0J1Y2tldE9iaikge1xuICAgICAgY29uc3QgYnVpbGRTM0J1Y2tldFJlc3BvbnNlID0gZGVmYXVsdHMuYnVpbGRTM0J1Y2tldCh0aGlzLCB7XG4gICAgICAgIGJ1Y2tldFByb3BzOiBwcm9wcy5idWNrZXRQcm9wcyxcbiAgICAgICAgbG9nZ2luZ0J1Y2tldFByb3BzOiBwcm9wcy5sb2dnaW5nQnVja2V0UHJvcHMsXG4gICAgICAgIGxvZ1MzQWNjZXNzTG9nczogcHJvcHMubG9nUzNBY2Nlc3NMb2dzXG4gICAgICB9KTtcbiAgICAgIHRoaXMuczNCdWNrZXQgPSBidWlsZFMzQnVja2V0UmVzcG9uc2UuYnVja2V0O1xuICAgICAgdGhpcy5zM0xvZ2dpbmdCdWNrZXQgPSBidWlsZFMzQnVja2V0UmVzcG9uc2UubG9nZ2luZ0J1Y2tldDtcbiAgICAgIG9yaWdpbkJ1Y2tldCA9IHRoaXMuczNCdWNrZXQ7XG4gICAgfSBlbHNlIHtcbiAgICAgIG9yaWdpbkJ1Y2tldCA9IHByb3BzLmV4aXN0aW5nQnVja2V0T2JqO1xuICAgIH1cblxuICAgIHRoaXMuczNCdWNrZXRJbnRlcmZhY2UgPSBvcmlnaW5CdWNrZXQ7XG5cbiAgICAvLyBEZWZpbmUgdGhlIENsb3VkRnJvbnQgRGlzdHJpYnV0aW9uXG4gICAgY29uc3QgY2xvdWRGcm9udERpc3RyaWJ1dGlvbkZvclMzUHJvcHM6IGRlZmF1bHRzLkNyZWF0ZUNsb3VkRnJvbnREaXN0cmlidXRpb25Gb3JTM1Byb3BzID0ge1xuICAgICAgc291cmNlQnVja2V0OiB0aGlzLnMzQnVja2V0SW50ZXJmYWNlLFxuICAgICAgY2xvdWRGcm9udERpc3RyaWJ1dGlvblByb3BzOiBwcm9wcy5jbG91ZEZyb250RGlzdHJpYnV0aW9uUHJvcHMsXG4gICAgICBodHRwU2VjdXJpdHlIZWFkZXJzOiBwcm9wcy5pbnNlcnRIdHRwU2VjdXJpdHlIZWFkZXJzLFxuICAgICAgY2xvdWRGcm9udExvZ2dpbmdCdWNrZXRQcm9wczogcHJvcHMuY2xvdWRGcm9udExvZ2dpbmdCdWNrZXRQcm9wcyxcbiAgICAgIHJlc3BvbnNlSGVhZGVyc1BvbGljeVByb3BzOiBwcm9wcy5yZXNwb25zZUhlYWRlcnNQb2xpY3lQcm9wcyxcbiAgICAgIGNsb3VkRnJvbnRMb2dnaW5nQnVja2V0UzNBY2Nlc3NMb2dCdWNrZXRQcm9wczogcHJvcHMuY2xvdWRGcm9udExvZ2dpbmdCdWNrZXRBY2Nlc3NMb2dCdWNrZXRQcm9wcyxcbiAgICAgIGxvZ0Nsb3VkRnJvbnRBY2Nlc3NMb2c6IHByb3BzLmxvZ0Nsb3VkRnJvbnRBY2Nlc3NMb2dcbiAgICB9O1xuICAgIGNvbnN0IGNsb3VkRnJvbnREaXN0cmlidXRpb25Gb3JTM1Jlc3BvbnNlID0gZGVmYXVsdHMuY3JlYXRlQ2xvdWRGcm9udERpc3RyaWJ1dGlvbkZvclMzKHRoaXMsIGlkLCBjbG91ZEZyb250RGlzdHJpYnV0aW9uRm9yUzNQcm9wcyk7XG4gICAgdGhpcy5jbG91ZEZyb250V2ViRGlzdHJpYnV0aW9uID0gY2xvdWRGcm9udERpc3RyaWJ1dGlvbkZvclMzUmVzcG9uc2UuZGlzdHJpYnV0aW9uO1xuICAgIHRoaXMuY2xvdWRGcm9udEZ1bmN0aW9uID0gY2xvdWRGcm9udERpc3RyaWJ1dGlvbkZvclMzUmVzcG9uc2UuY2xvdWRmcm9udEZ1bmN0aW9uO1xuICAgIHRoaXMuY2xvdWRGcm9udExvZ2dpbmdCdWNrZXQgPSBjbG91ZEZyb250RGlzdHJpYnV0aW9uRm9yUzNSZXNwb25zZS5sb2dnaW5nQnVja2V0O1xuICAgIHRoaXMub3JpZ2luQWNjZXNzQ29udHJvbCA9IGNsb3VkRnJvbnREaXN0cmlidXRpb25Gb3JTM1Jlc3BvbnNlLm9yaWdpbkFjY2Vzc0NvbnRyb2w7XG4gICAgdGhpcy5jbG91ZEZyb250TG9nZ2luZ0J1Y2tldEFjY2Vzc0xvZ0J1Y2tldCA9IGNsb3VkRnJvbnREaXN0cmlidXRpb25Gb3JTM1Jlc3BvbnNlLmxvZ2dpbmdCdWNrZXRTM0FjY2Vzc3NMb2dCdWNrZXQ7XG5cbiAgICAvLyBBdHRhY2ggdGhlIE9yaWdpbkFjY2Vzc0NvbnRyb2wgdG8gdGhlIENsb3VkRnJvbnQgRGlzdHJpYnV0aW9uLCBhbmQgcmVtb3ZlIHRoZSBPcmlnaW5BY2Nlc3NJZGVudGl0eVxuICAgIGNvbnN0IGwxQ2xvdWRGcm9udERpc3RyaWJ1dGlvbiA9IHRoaXMuY2xvdWRGcm9udFdlYkRpc3RyaWJ1dGlvbi5ub2RlLmRlZmF1bHRDaGlsZCBhcyBjbG91ZGZyb250LkNmbkRpc3RyaWJ1dGlvbjtcbiAgICBsMUNsb3VkRnJvbnREaXN0cmlidXRpb24uYWRkUHJvcGVydHlPdmVycmlkZSgnRGlzdHJpYnV0aW9uQ29uZmlnLk9yaWdpbnMuMC5PcmlnaW5BY2Nlc3NDb250cm9sSWQnLCB0aGlzLm9yaWdpbkFjY2Vzc0NvbnRyb2w/LmF0dHJJZCk7XG4gICAgaWYgKHByb3BzLm9yaWdpblBhdGgpIHtcbiAgICAgIGwxQ2xvdWRGcm9udERpc3RyaWJ1dGlvbi5hZGRQcm9wZXJ0eU92ZXJyaWRlKCdEaXN0cmlidXRpb25Db25maWcuT3JpZ2lucy4wLk9yaWdpblBhdGgnLCBwcm9wcy5vcmlnaW5QYXRoKTtcbiAgICB9XG5cbiAgICAvLyBHcmFudCBDbG91ZEZyb250IHBlcm1pc3Npb24gdG8gZ2V0IHRoZSBvYmplY3RzIGZyb20gdGhlIHMzIGJ1Y2tldCBvcmlnaW5cbiAgICBvcmlnaW5CdWNrZXQuYWRkVG9SZXNvdXJjZVBvbGljeShcbiAgICAgIG5ldyBpYW0uUG9saWN5U3RhdGVtZW50KHtcbiAgICAgICAgZWZmZWN0OiBpYW0uRWZmZWN0LkFMTE9XLFxuICAgICAgICBhY3Rpb25zOiBbJ3MzOkdldE9iamVjdCddLFxuICAgICAgICBwcmluY2lwYWxzOiBbbmV3IGlhbS5TZXJ2aWNlUHJpbmNpcGFsKCdjbG91ZGZyb250LmFtYXpvbmF3cy5jb20nKV0sXG4gICAgICAgIHJlc291cmNlczogW29yaWdpbkJ1Y2tldC5hcm5Gb3JPYmplY3RzKCcqJyldLFxuICAgICAgICBjb25kaXRpb25zOiB7XG4gICAgICAgICAgU3RyaW5nRXF1YWxzOiB7XG4gICAgICAgICAgICAnQVdTOlNvdXJjZUFybic6IGBhcm46JHtBd3MuUEFSVElUSU9OfTpjbG91ZGZyb250Ojoke0F3cy5BQ0NPVU5UX0lEfTpkaXN0cmlidXRpb24vJHt0aGlzLmNsb3VkRnJvbnRXZWJEaXN0cmlidXRpb24uZGlzdHJpYnV0aW9uSWR9YFxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSlcbiAgICApO1xuXG4gICAgb3JpZ2luQnVja2V0LmFkZFRvUmVzb3VyY2VQb2xpY3koXG4gICAgICBuZXcgaWFtLlBvbGljeVN0YXRlbWVudCh7XG4gICAgICAgIGVmZmVjdDogaWFtLkVmZmVjdC5BTExPVyxcbiAgICAgICAgYWN0aW9uczogWydzMzpMaXN0QnVja2V0J10sXG4gICAgICAgIHByaW5jaXBhbHM6IFtuZXcgaWFtLlNlcnZpY2VQcmluY2lwYWwoJ2Nsb3VkZnJvbnQuYW1hem9uYXdzLmNvbScpXSxcbiAgICAgICAgcmVzb3VyY2VzOiBbb3JpZ2luQnVja2V0LmJ1Y2tldEFybl0sXG4gICAgICAgIGNvbmRpdGlvbnM6IHtcbiAgICAgICAgICBTdHJpbmdFcXVhbHM6IHtcbiAgICAgICAgICAgICdBV1M6U291cmNlQXJuJzogYGFybjoke0F3cy5QQVJUSVRJT059OmNsb3VkZnJvbnQ6OiR7QXdzLkFDQ09VTlRfSUR9OmRpc3RyaWJ1dGlvbi8ke3RoaXMuY2xvdWRGcm9udFdlYkRpc3RyaWJ1dGlvbi5kaXN0cmlidXRpb25JZH1gXG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9KVxuICAgICk7XG5cbiAgICAvLyBXZSBuZWVkIHRvIGNyZWF0ZSBhIGN1c3RvbSByZXNvdXJjZSB0byBpbnRyb2R1Y2UgdGhlIGluZGlyZWN0aW9uIG5lY2Vzc2FyeSB0byBhdm9pZFxuICAgIC8vIGEgY2lyY3VsYXIgZGVwZW5kZW5jeSB3aGVuIGdyYW50aW5nIHRoZSBDbG91ZEZyb250IGRpc3RyaWJ1dGlvbiBhY2Nlc3MgdG8gdXNlIHRoZVxuICAgIC8vIEtNUyBrZXkgdG8gZGVjcnlwdCBvYmplY3RzLiBXaXRob3V0IHRoaXMgaW5kaXJlY3Rpb24sIGl0IGlzIG5vdCBwb3NzaWJsZSB0byByZWZlcmVuY2VcbiAgICAvLyB0aGUgQ2xvdWRGcm9udCBkaXN0cmlidXRpb24gSUQgaW4gdGhlIEtNUyBrZXkgcG9saWN5IGJlY2F1c2UgLVxuICAgIC8vICAgKiBUaGUgUzMgYnVja2V0IHJlZmVyZW5jZXMgdGhlIEtNUyBrZXlcbiAgICAvLyAgICogVGhlIENsb3VkRnJvbnQgZGlzdHJpYnV0aW9uIHJlZmVyZW5jZXMgdGhlIGJ1Y2tldFxuICAgIC8vICAgKiBUaGUgS01TIGtleSByZWZlcmVuY2VzIHRoZSBDbG91ZEZyb250IGRpc3RyaWJ1dGlvblxuICAgIGxldCBlbmNyeXB0aW9uS2V5OiBrbXMuSUtleSB8IHVuZGVmaW5lZDtcbiAgICBpZiAocHJvcHMuYnVja2V0UHJvcHMgJiYgcHJvcHMuYnVja2V0UHJvcHMuZW5jcnlwdGlvbktleSkge1xuICAgICAgZW5jcnlwdGlvbktleSA9IHByb3BzLmJ1Y2tldFByb3BzLmVuY3J5cHRpb25LZXk7XG4gICAgfSBlbHNlIGlmIChwcm9wcy5leGlzdGluZ0J1Y2tldE9iaiAmJiBwcm9wcy5leGlzdGluZ0J1Y2tldE9iai5lbmNyeXB0aW9uS2V5KSB7XG4gICAgICBlbmNyeXB0aW9uS2V5ID0gcHJvcHMuZXhpc3RpbmdCdWNrZXRPYmouZW5jcnlwdGlvbktleTtcbiAgICB9XG5cbiAgICBpZiAoZW5jcnlwdGlvbktleSkge1xuICAgICAgcmVzb3VyY2VzLmNyZWF0ZUtleVBvbGljeVVwZGF0ZXJDdXN0b21SZXNvdXJjZSh0aGlzLCBpZCwgIHtcbiAgICAgICAgZGlzdHJpYnV0aW9uOiB0aGlzLmNsb3VkRnJvbnRXZWJEaXN0cmlidXRpb24sXG4gICAgICAgIGVuY3J5cHRpb25LZXlcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxufSJdfQ==