@scloud/cdk-patterns
Version:
Serverless CDK patterns for common infrastructure needs
80 lines • 14.3 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.WebApi = void 0;
const aws_cdk_lib_1 = require("aws-cdk-lib");
const aws_certificatemanager_1 = require("aws-cdk-lib/aws-certificatemanager");
const aws_route53_targets_1 = require("aws-cdk-lib/aws-route53-targets");
const aws_cloudfront_origins_1 = require("aws-cdk-lib/aws-cloudfront-origins");
const aws_cloudfront_1 = require("aws-cdk-lib/aws-cloudfront");
const aws_apigateway_1 = require("aws-cdk-lib/aws-apigateway");
const constructs_1 = require("constructs");
const aws_route53_1 = require("aws-cdk-lib/aws-route53");
const GithubActions_1 = require("./GithubActions");
const PrivateBucket_1 = require("./PrivateBucket");
/**
* Builds a web API, backed by a single Lambda function - a kind of "Lambda-lith" (https://github.com/cdk-patterns/serverless/blob/main/the-lambda-trilogy/README.md)
*
* This construct sends requests that don't have a file extension to the Lambda. Static content is handled by routing requests that match *.* (eg *.js. *.css) to an S3 bucket.
* Dumping requests with file expensions means the majority of spam requests will not invoke your Lambda.
* Typically spam requests are probing for wordpress *.xml files, *.php files, .env files etc.
*/
class WebApi extends constructs_1.Construct {
constructor(scope, id, props) {
super(scope, `${id}WebApi`);
const domainName = props.domainName || `${props.zone.zoneName}`;
// Static content
this.bucket = PrivateBucket_1.PrivateBucket.expendable(scope, `${id}Static`);
(0, GithubActions_1.githubActions)(scope).addGhaBucket(id, this.bucket);
// Web app handler - default values can be overridden using lambdaProps
this.lambda = props.lambda;
this.api = new aws_apigateway_1.LambdaRestApi(scope, `${id}ApiGateway`, {
handler: this.lambda,
proxy: true,
description: `${aws_cdk_lib_1.Stack.of(scope).stackName} ${id}`,
binaryMediaTypes: ['multipart/form-data'],
});
this.certificate = new aws_certificatemanager_1.DnsValidatedCertificate(scope, `${id}Certificate`, {
domainName,
hostedZone: props.zone,
region: 'us-east-1',
});
// This enables us to separate out the defaultBehavior props (if any) from the distributionProps (if provided)
// See https://stackoverflow.com/a/34710102/723506 for an explanation of this destructuring
const { defaultBehavior, additionalBehaviors, ...distributionProps } = props.distributionProps || {};
this.distribution = new aws_cloudfront_1.Distribution(scope, `${id}Distribution`, {
domainNames: [domainName],
comment: domainName,
defaultBehavior: {
origin: new aws_cloudfront_origins_1.RestApiOrigin(this.api),
allowedMethods: aws_cloudfront_1.AllowedMethods.ALLOW_ALL,
viewerProtocolPolicy: aws_cloudfront_1.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
cachePolicy: aws_cloudfront_1.CachePolicy.CACHING_DISABLED, // Assume dynamic content
originRequestPolicy: aws_cloudfront_1.OriginRequestPolicy.ALL_VIEWER_EXCEPT_HOST_HEADER,
...defaultBehavior,
},
// All requests for something with a file extension go to s3 (actually, any path that contains a period).
// The aim is to route *.css, *.js, *.jpeg, etc)
additionalBehaviors: {
'*.*': {
origin: aws_cloudfront_origins_1.S3BucketOrigin.withOriginAccessControl(this.bucket),
allowedMethods: aws_cloudfront_1.AllowedMethods.ALLOW_GET_HEAD_OPTIONS,
viewerProtocolPolicy: aws_cloudfront_1.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
compress: true,
},
...additionalBehaviors,
},
certificate: this.certificate,
errorResponses: props.errorResponses,
...distributionProps,
});
(0, GithubActions_1.githubActions)(scope).addGhaDistribution(id, this.distribution);
// DNS record for the Cloudfront distribution
new aws_route53_1.ARecord(scope, `${id}ARecord`, {
recordName: domainName,
target: aws_route53_1.RecordTarget.fromAlias(new aws_route53_targets_1.CloudFrontTarget(this.distribution)),
zone: props.zone,
});
}
}
exports.WebApi = WebApi;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiV2ViQXBpLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL1dlYkFwaS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSw2Q0FFcUI7QUFDckIsK0VBQTZFO0FBQzdFLHlFQUFtRTtBQUVuRSwrRUFBbUY7QUFDbkYsK0RBTW9DO0FBQ3BDLCtEQUVvQztBQUVwQywyQ0FBdUM7QUFDdkMseURBQTZFO0FBQzdFLG1EQUFnRDtBQUNoRCxtREFBZ0Q7QUFpQmhEOzs7Ozs7R0FNRztBQUNILE1BQWEsTUFBTyxTQUFRLHNCQUFTO0lBV25DLFlBQ0UsS0FBZ0IsRUFDaEIsRUFBVSxFQUNWLEtBQWtCO1FBRWxCLEtBQUssQ0FBQyxLQUFLLEVBQUUsR0FBRyxFQUFFLFFBQVEsQ0FBQyxDQUFDO1FBRTVCLE1BQU0sVUFBVSxHQUFHLEtBQUssQ0FBQyxVQUFVLElBQUksR0FBRyxLQUFLLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO1FBRWhFLGlCQUFpQjtRQUNqQixJQUFJLENBQUMsTUFBTSxHQUFHLDZCQUFhLENBQUMsVUFBVSxDQUFDLEtBQUssRUFBRSxHQUFHLEVBQUUsUUFBUSxDQUFDLENBQUM7UUFDN0QsSUFBQSw2QkFBYSxFQUFDLEtBQUssQ0FBQyxDQUFDLFlBQVksQ0FBQyxFQUFFLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBRW5ELHVFQUF1RTtRQUN2RSxJQUFJLENBQUMsTUFBTSxHQUFHLEtBQUssQ0FBQyxNQUFNLENBQUM7UUFFM0IsSUFBSSxDQUFDLEdBQUcsR0FBRyxJQUFJLDhCQUFhLENBQUMsS0FBSyxFQUFFLEdBQUcsRUFBRSxZQUFZLEVBQUU7WUFDckQsT0FBTyxFQUFFLElBQUksQ0FBQyxNQUFNO1lBQ3BCLEtBQUssRUFBRSxJQUFJO1lBQ1gsV0FBVyxFQUFFLEdBQUcsbUJBQUssQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLENBQUMsU0FBUyxJQUFJLEVBQUUsRUFBRTtZQUNqRCxnQkFBZ0IsRUFBRSxDQUFDLHFCQUFxQixDQUFDO1NBQzFDLENBQUMsQ0FBQztRQUVILElBQUksQ0FBQyxXQUFXLEdBQUcsSUFBSSxnREFBdUIsQ0FBQyxLQUFLLEVBQUUsR0FBRyxFQUFFLGFBQWEsRUFBRTtZQUN4RSxVQUFVO1lBQ1YsVUFBVSxFQUFFLEtBQUssQ0FBQyxJQUFJO1lBQ3RCLE1BQU0sRUFBRSxXQUFXO1NBQ3BCLENBQUMsQ0FBQztRQUVILDhHQUE4RztRQUM5RywyRkFBMkY7UUFDM0YsTUFBTSxFQUFFLGVBQWUsRUFBRSxtQkFBbUIsRUFBRSxHQUFHLGlCQUFpQixFQUFFLEdBQUcsS0FBSyxDQUFDLGlCQUFpQixJQUFLLEVBQWlDLENBQUM7UUFDckksSUFBSSxDQUFDLFlBQVksR0FBRyxJQUFJLDZCQUFZLENBQUMsS0FBSyxFQUFFLEdBQUcsRUFBRSxjQUFjLEVBQUU7WUFDL0QsV0FBVyxFQUFFLENBQUMsVUFBVSxDQUFDO1lBQ3pCLE9BQU8sRUFBRSxVQUFVO1lBQ25CLGVBQWUsRUFBRTtnQkFDZixNQUFNLEVBQUUsSUFBSSxzQ0FBYSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUM7Z0JBQ25DLGNBQWMsRUFBRSwrQkFBYyxDQUFDLFNBQVM7Z0JBQ3hDLG9CQUFvQixFQUFFLHFDQUFvQixDQUFDLGlCQUFpQjtnQkFDNUQsV0FBVyxFQUFFLDRCQUFXLENBQUMsZ0JBQWdCLEVBQUUseUJBQXlCO2dCQUNwRSxtQkFBbUIsRUFBRSxvQ0FBbUIsQ0FBQyw2QkFBNkI7Z0JBQ3RFLEdBQUcsZUFBZTthQUNuQjtZQUNELHlHQUF5RztZQUN6RyxnREFBZ0Q7WUFDaEQsbUJBQW1CLEVBQUU7Z0JBQ25CLEtBQUssRUFBRTtvQkFDTCxNQUFNLEVBQUUsdUNBQWMsQ0FBQyx1QkFBdUIsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDO29CQUMzRCxjQUFjLEVBQUUsK0JBQWMsQ0FBQyxzQkFBc0I7b0JBQ3JELG9CQUFvQixFQUFFLHFDQUFvQixDQUFDLGlCQUFpQjtvQkFDNUQsUUFBUSxFQUFFLElBQUk7aUJBQ2Y7Z0JBQ0QsR0FBRyxtQkFBbUI7YUFDdkI7WUFDRCxXQUFXLEVBQUUsSUFBSSxDQUFDLFdBQVc7WUFDN0IsY0FBYyxFQUFFLEtBQUssQ0FBQyxjQUFjO1lBQ3BDLEdBQUcsaUJBQWlCO1NBQ3JCLENBQUMsQ0FBQztRQUNILElBQUEsNkJBQWEsRUFBQyxLQUFLLENBQUMsQ0FBQyxrQkFBa0IsQ0FBQyxFQUFFLEVBQUUsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO1FBRS9ELDZDQUE2QztRQUM3QyxJQUFJLHFCQUFPLENBQUMsS0FBSyxFQUFFLEdBQUcsRUFBRSxTQUFTLEVBQUU7WUFDakMsVUFBVSxFQUFFLFVBQVU7WUFDdEIsTUFBTSxFQUFFLDBCQUFZLENBQUMsU0FBUyxDQUFDLElBQUksc0NBQWdCLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO1lBQ3ZFLElBQUksRUFBRSxLQUFLLENBQUMsSUFBSTtTQUNqQixDQUFDLENBQUM7SUFDTCxDQUFDO0NBQ0Y7QUE5RUQsd0JBOEVDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgU3RhY2ssXG59IGZyb20gJ2F3cy1jZGstbGliJztcbmltcG9ydCB7IERuc1ZhbGlkYXRlZENlcnRpZmljYXRlIH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWNlcnRpZmljYXRlbWFuYWdlcic7XG5pbXBvcnQgeyBDbG91ZEZyb250VGFyZ2V0IH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLXJvdXRlNTMtdGFyZ2V0cyc7XG5pbXBvcnQgeyBCdWNrZXQgfSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtczMnO1xuaW1wb3J0IHsgUmVzdEFwaU9yaWdpbiwgUzNCdWNrZXRPcmlnaW4gfSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtY2xvdWRmcm9udC1vcmlnaW5zJztcbmltcG9ydCB7XG4gIEFsbG93ZWRNZXRob2RzLCBDYWNoZVBvbGljeSwgRGlzdHJpYnV0aW9uLFxuICBEaXN0cmlidXRpb25Qcm9wcyxcbiAgRXJyb3JSZXNwb25zZSxcbiAgT3JpZ2luUmVxdWVzdFBvbGljeSxcbiAgVmlld2VyUHJvdG9jb2xQb2xpY3ksXG59IGZyb20gJ2F3cy1jZGstbGliL2F3cy1jbG91ZGZyb250JztcbmltcG9ydCB7XG4gIExhbWJkYVJlc3RBcGksXG59IGZyb20gJ2F3cy1jZGstbGliL2F3cy1hcGlnYXRld2F5JztcbmltcG9ydCB7IEZ1bmN0aW9uIH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWxhbWJkYSc7XG5pbXBvcnQgeyBDb25zdHJ1Y3QgfSBmcm9tICdjb25zdHJ1Y3RzJztcbmltcG9ydCB7IEFSZWNvcmQsIElIb3N0ZWRab25lLCBSZWNvcmRUYXJnZXQgfSBmcm9tICdhd3MtY2RrLWxpYi9hd3Mtcm91dGU1Myc7XG5pbXBvcnQgeyBnaXRodWJBY3Rpb25zIH0gZnJvbSAnLi9HaXRodWJBY3Rpb25zJztcbmltcG9ydCB7IFByaXZhdGVCdWNrZXQgfSBmcm9tICcuL1ByaXZhdGVCdWNrZXQnO1xuXG4vKipcbiAqIEBwYXJhbSBsYW1iZGEgVGhlIGZ1bmN0aW9uIHdoaWNoIHdpbGwgcmVzcG9uZCB0byBpbmNvbWluZyByZXF1ZXN0IGV2ZW50cy5cbiAqIEBwYXJhbSB6b25lIFRoZSBETlMgem9uZSBmb3IgdGhpcyB3ZWIgYXBwLlxuICogQHBhcmFtIGRvbWFpbk5hbWUgT3B0aW9uYWw6IGJ5IGRlZmF1bHQgdGhlIHpvbmUgbmFtZSB3aWxsIGJlIHVzZWQgKGUuZy4gJ2V4YW1wbGUuY29tJykgYSBkaWZmZXJlbnQgZG9tYWluIGhlcmUgKGUuZy4gJ3N1YmRvbWFpbi5leGFtcGxlLmNvbScpLlxuICogQHBhcmFtIGRpc3RyaWJ1dGlvblByb3BzIE9wdGlvbmFsOiBJZiB5b3Ugd2FudCB0byBhZGQgYWRkaXRpb25hbCBwcm9wZXJ0aWVzIHRvIHRoZSBDbG91ZGZyb250IGRpc3RyaWJ1dGlvbiwgeW91IGNhbiBwYXNzIHRoZW0gaGVyZS5cbiAqIEBwYXJhbSBlcnJvclJlc3BvbnNlcyBPcHRpb25hbDogSWYgeW91IHdhbnQgdG8gYWRkIGN1c3RvbSBlcnJvciByZXNwb25zZXMgdG8gdGhlIENsb3VkZnJvbnQgZGlzdHJpYnV0aW9uLCB5b3UgY2FuIHBhc3MgdGhlbSBoZXJlLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFdlYkFwaVByb3BzIHtcbiAgbGFtYmRhOiBGdW5jdGlvbixcbiAgem9uZTogSUhvc3RlZFpvbmUsXG4gIGRvbWFpbk5hbWU/OiBzdHJpbmcsXG4gIGRpc3RyaWJ1dGlvblByb3BzPzogUGFydGlhbDxEaXN0cmlidXRpb25Qcm9wcz4sXG4gIGVycm9yUmVzcG9uc2VzPzogRXJyb3JSZXNwb25zZVtdLFxufVxuXG4vKipcbiAqIEJ1aWxkcyBhIHdlYiBBUEksIGJhY2tlZCBieSBhIHNpbmdsZSBMYW1iZGEgZnVuY3Rpb24gLSBhIGtpbmQgb2YgXCJMYW1iZGEtbGl0aFwiIChodHRwczovL2dpdGh1Yi5jb20vY2RrLXBhdHRlcm5zL3NlcnZlcmxlc3MvYmxvYi9tYWluL3RoZS1sYW1iZGEtdHJpbG9neS9SRUFETUUubWQpXG4gKlxuICogVGhpcyBjb25zdHJ1Y3Qgc2VuZHMgcmVxdWVzdHMgdGhhdCBkb24ndCBoYXZlIGEgZmlsZSBleHRlbnNpb24gdG8gdGhlIExhbWJkYS4gU3RhdGljIGNvbnRlbnQgaXMgaGFuZGxlZCBieSByb3V0aW5nIHJlcXVlc3RzIHRoYXQgbWF0Y2ggKi4qIChlZyAqLmpzLiAqLmNzcykgdG8gYW4gUzMgYnVja2V0LlxuICogRHVtcGluZyByZXF1ZXN0cyB3aXRoIGZpbGUgZXhwZW5zaW9ucyBtZWFucyB0aGUgbWFqb3JpdHkgb2Ygc3BhbSByZXF1ZXN0cyB3aWxsIG5vdCBpbnZva2UgeW91ciBMYW1iZGEuXG4gKiBUeXBpY2FsbHkgc3BhbSByZXF1ZXN0cyBhcmUgcHJvYmluZyBmb3Igd29yZHByZXNzICoueG1sIGZpbGVzLCAqLnBocCBmaWxlcywgLmVudiBmaWxlcyBldGMuXG4gKi9cbmV4cG9ydCBjbGFzcyBXZWJBcGkgZXh0ZW5kcyBDb25zdHJ1Y3Qge1xuICBsYW1iZGE6IEZ1bmN0aW9uO1xuXG4gIGJ1Y2tldDogQnVja2V0O1xuXG4gIGRpc3RyaWJ1dGlvbjogRGlzdHJpYnV0aW9uO1xuXG4gIGFwaTogTGFtYmRhUmVzdEFwaTtcblxuICBjZXJ0aWZpY2F0ZTogRG5zVmFsaWRhdGVkQ2VydGlmaWNhdGU7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgc2NvcGU6IENvbnN0cnVjdCxcbiAgICBpZDogc3RyaW5nLFxuICAgIHByb3BzOiBXZWJBcGlQcm9wcyxcbiAgKSB7XG4gICAgc3VwZXIoc2NvcGUsIGAke2lkfVdlYkFwaWApO1xuXG4gICAgY29uc3QgZG9tYWluTmFtZSA9IHByb3BzLmRvbWFpbk5hbWUgfHwgYCR7cHJvcHMuem9uZS56b25lTmFtZX1gO1xuXG4gICAgLy8gU3RhdGljIGNvbnRlbnRcbiAgICB0aGlzLmJ1Y2tldCA9IFByaXZhdGVCdWNrZXQuZXhwZW5kYWJsZShzY29wZSwgYCR7aWR9U3RhdGljYCk7XG4gICAgZ2l0aHViQWN0aW9ucyhzY29wZSkuYWRkR2hhQnVja2V0KGlkLCB0aGlzLmJ1Y2tldCk7XG5cbiAgICAvLyBXZWIgYXBwIGhhbmRsZXIgLSBkZWZhdWx0IHZhbHVlcyBjYW4gYmUgb3ZlcnJpZGRlbiB1c2luZyBsYW1iZGFQcm9wc1xuICAgIHRoaXMubGFtYmRhID0gcHJvcHMubGFtYmRhO1xuXG4gICAgdGhpcy5hcGkgPSBuZXcgTGFtYmRhUmVzdEFwaShzY29wZSwgYCR7aWR9QXBpR2F0ZXdheWAsIHtcbiAgICAgIGhhbmRsZXI6IHRoaXMubGFtYmRhLFxuICAgICAgcHJveHk6IHRydWUsXG4gICAgICBkZXNjcmlwdGlvbjogYCR7U3RhY2sub2Yoc2NvcGUpLnN0YWNrTmFtZX0gJHtpZH1gLFxuICAgICAgYmluYXJ5TWVkaWFUeXBlczogWydtdWx0aXBhcnQvZm9ybS1kYXRhJ10sXG4gICAgfSk7XG5cbiAgICB0aGlzLmNlcnRpZmljYXRlID0gbmV3IERuc1ZhbGlkYXRlZENlcnRpZmljYXRlKHNjb3BlLCBgJHtpZH1DZXJ0aWZpY2F0ZWAsIHtcbiAgICAgIGRvbWFpbk5hbWUsXG4gICAgICBob3N0ZWRab25lOiBwcm9wcy56b25lLFxuICAgICAgcmVnaW9uOiAndXMtZWFzdC0xJyxcbiAgICB9KTtcblxuICAgIC8vIFRoaXMgZW5hYmxlcyB1cyB0byBzZXBhcmF0ZSBvdXQgdGhlIGRlZmF1bHRCZWhhdmlvciBwcm9wcyAoaWYgYW55KSBmcm9tIHRoZSBkaXN0cmlidXRpb25Qcm9wcyAoaWYgcHJvdmlkZWQpXG4gICAgLy8gU2VlIGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vYS8zNDcxMDEwMi83MjM1MDYgZm9yIGFuIGV4cGxhbmF0aW9uIG9mIHRoaXMgZGVzdHJ1Y3R1cmluZ1xuICAgIGNvbnN0IHsgZGVmYXVsdEJlaGF2aW9yLCBhZGRpdGlvbmFsQmVoYXZpb3JzLCAuLi5kaXN0cmlidXRpb25Qcm9wcyB9ID0gcHJvcHMuZGlzdHJpYnV0aW9uUHJvcHMgfHwgKHt9IGFzIFBhcnRpYWw8RGlzdHJpYnV0aW9uUHJvcHM+KTtcbiAgICB0aGlzLmRpc3RyaWJ1dGlvbiA9IG5ldyBEaXN0cmlidXRpb24oc2NvcGUsIGAke2lkfURpc3RyaWJ1dGlvbmAsIHtcbiAgICAgIGRvbWFpbk5hbWVzOiBbZG9tYWluTmFtZV0sXG4gICAgICBjb21tZW50OiBkb21haW5OYW1lLFxuICAgICAgZGVmYXVsdEJlaGF2aW9yOiB7XG4gICAgICAgIG9yaWdpbjogbmV3IFJlc3RBcGlPcmlnaW4odGhpcy5hcGkpLFxuICAgICAgICBhbGxvd2VkTWV0aG9kczogQWxsb3dlZE1ldGhvZHMuQUxMT1dfQUxMLFxuICAgICAgICB2aWV3ZXJQcm90b2NvbFBvbGljeTogVmlld2VyUHJvdG9jb2xQb2xpY3kuUkVESVJFQ1RfVE9fSFRUUFMsXG4gICAgICAgIGNhY2hlUG9saWN5OiBDYWNoZVBvbGljeS5DQUNISU5HX0RJU0FCTEVELCAvLyBBc3N1bWUgZHluYW1pYyBjb250ZW50XG4gICAgICAgIG9yaWdpblJlcXVlc3RQb2xpY3k6IE9yaWdpblJlcXVlc3RQb2xpY3kuQUxMX1ZJRVdFUl9FWENFUFRfSE9TVF9IRUFERVIsXG4gICAgICAgIC4uLmRlZmF1bHRCZWhhdmlvcixcbiAgICAgIH0sXG4gICAgICAvLyBBbGwgcmVxdWVzdHMgZm9yIHNvbWV0aGluZyB3aXRoIGEgZmlsZSBleHRlbnNpb24gZ28gdG8gczMgKGFjdHVhbGx5LCBhbnkgcGF0aCB0aGF0IGNvbnRhaW5zIGEgcGVyaW9kKS5cbiAgICAgIC8vIFRoZSBhaW0gaXMgdG8gcm91dGUgKi5jc3MsICouanMsICouanBlZywgZXRjKVxuICAgICAgYWRkaXRpb25hbEJlaGF2aW9yczoge1xuICAgICAgICAnKi4qJzoge1xuICAgICAgICAgIG9yaWdpbjogUzNCdWNrZXRPcmlnaW4ud2l0aE9yaWdpbkFjY2Vzc0NvbnRyb2wodGhpcy5idWNrZXQpLFxuICAgICAgICAgIGFsbG93ZWRNZXRob2RzOiBBbGxvd2VkTWV0aG9kcy5BTExPV19HRVRfSEVBRF9PUFRJT05TLFxuICAgICAgICAgIHZpZXdlclByb3RvY29sUG9saWN5OiBWaWV3ZXJQcm90b2NvbFBvbGljeS5SRURJUkVDVF9UT19IVFRQUyxcbiAgICAgICAgICBjb21wcmVzczogdHJ1ZSxcbiAgICAgICAgfSxcbiAgICAgICAgLi4uYWRkaXRpb25hbEJlaGF2aW9ycyxcbiAgICAgIH0sXG4gICAgICBjZXJ0aWZpY2F0ZTogdGhpcy5jZXJ0aWZpY2F0ZSxcbiAgICAgIGVycm9yUmVzcG9uc2VzOiBwcm9wcy5lcnJvclJlc3BvbnNlcyxcbiAgICAgIC4uLmRpc3RyaWJ1dGlvblByb3BzLFxuICAgIH0pO1xuICAgIGdpdGh1YkFjdGlvbnMoc2NvcGUpLmFkZEdoYURpc3RyaWJ1dGlvbihpZCwgdGhpcy5kaXN0cmlidXRpb24pO1xuXG4gICAgLy8gRE5TIHJlY29yZCBmb3IgdGhlIENsb3VkZnJvbnQgZGlzdHJpYnV0aW9uXG4gICAgbmV3IEFSZWNvcmQoc2NvcGUsIGAke2lkfUFSZWNvcmRgLCB7XG4gICAgICByZWNvcmROYW1lOiBkb21haW5OYW1lLFxuICAgICAgdGFyZ2V0OiBSZWNvcmRUYXJnZXQuZnJvbUFsaWFzKG5ldyBDbG91ZEZyb250VGFyZ2V0KHRoaXMuZGlzdHJpYnV0aW9uKSksXG4gICAgICB6b25lOiBwcm9wcy56b25lLFxuICAgIH0pO1xuICB9XG59XG4iXX0=