@richkang/cdk-construct-network-firewall-textfile-rules
Version:
A simple AWS VPC Firewall with one stateless rule and one stateful rule to meet the AWS Config Network Firewall Conformance.
197 lines • 23.9 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.FirewallDistributedVpc = void 0;
const cdk = require("aws-cdk-lib");
const constructs_1 = require("constructs");
const fs = require("fs");
const path = require("path");
class FirewallDistributedVpc extends constructs_1.Construct {
constructor(scope, id, props) {
super(scope, id);
this.vpc = props.vpc;
const allowedports = new cdk.aws_networkfirewall.CfnRuleGroup(this, 'allowed-ports', {
capacity: 1000,
ruleGroupName: 'allowed-ports',
type: 'STATELESS',
ruleGroup: {
rulesSource: {
statelessRulesAndCustomActions: {
statelessRules: [
{
priority: 1,
ruleDefinition: {
actions: ['aws:forward_to_sfe'],
matchAttributes: {
destinations: [{
addressDefinition: '0.0.0.0/0',
}],
sources: [{
addressDefinition: '0.0.0.0/0',
}],
protocols: [6],
destinationPorts: [
{
fromPort: 80,
toPort: 80,
},
{
fromPort: 443,
toPort: 443,
},
],
},
},
},
{
priority: 2,
ruleDefinition: {
actions: ['aws:forward_to_sfe'],
matchAttributes: {
destinations: [{
addressDefinition: '0.0.0.0/0',
}],
sources: [{
addressDefinition: '0.0.0.0/0',
}],
protocols: [6],
sourcePorts: [
{
fromPort: 80,
toPort: 80,
},
{
fromPort: 443,
toPort: 443,
},
],
},
},
}
],
},
},
},
});
let listdomains = [
'.docker.com',
'.aws.amazon.com',
'.amazonaws.com',
'downloads.nessus.org',
'plugins.nessus.org',
'.fedoraproject.org',
'.duosecurity.com',
'crl3.digicert.com',
'crl.godaddy.com',
'certificate.godaddy.com',
'ocsp.godaddy.com',
'crl4.digicert.com',
'.digicert.com',
'.rootca1.amazontrust.com',
'.rootg2.amazontrust.com',
'.amazontrust.com',
'.sca1a.amazontrust.com',
'.sca1b.amazontrust.com',
];
const statefulRuleGroups = [];
statefulRuleGroups.push({
resourceArn: new cdk.aws_networkfirewall.CfnRuleGroup(this, 'domain-allowlist', {
capacity: 1000,
ruleGroupName: 'domain-allowlist',
type: 'STATEFUL',
ruleGroup: {
rulesSource: {
rulesSourceList: {
generatedRulesType: 'ALLOWLIST',
targets: listdomains,
targetTypes: ['TLS_SNI', 'HTTP_HOST'],
},
},
},
}).ref
});
const rulesVariable = {
ipSets: {
HOME_NET: {
definition: [this.getHomeNet()],
},
EXTERNAL_NET: {
definition: ['0.0.0.0/0'],
}
},
};
if (props.rulesFile) {
const rulesFromFile = this.getRulesSourcePropertyFromFile(props.rulesFile, rulesVariable);
for (let index = 0; index < rulesFromFile.length; index++) {
statefulRuleGroups.push({
resourceArn: rulesFromFile[index].ref
});
}
}
;
const rulesFromFileGroupReference = new cdk.aws_networkfirewall.CfnRuleGroup(this, 'rulesFromFile', {
capacity: 1000,
ruleGroupName: 'rulesFromFile',
type: 'STATEFUL',
ruleGroup: {
rulesSource: {
rulesSourceList: {
generatedRulesType: 'ALLOWLIST',
targets: listdomains,
targetTypes: ['TLS_SNI', 'HTTP_HOST'],
},
},
},
});
const fw_policy = new cdk.aws_networkfirewall.CfnFirewallPolicy(this, 'fw_policy', {
firewallPolicyName: 'network-firewall-policy',
firewallPolicy: {
statelessDefaultActions: ['aws:drop'],
statelessFragmentDefaultActions: ['aws:drop'],
statelessRuleGroupReferences: [{
priority: 100,
resourceArn: allowedports.ref,
}],
statefulRuleGroupReferences: statefulRuleGroups
},
});
const subnetList = [];
props.subnetList.forEach((subnet) => {
subnetList.push({ subnetId: subnet.subnetId });
});
const firewall = new cdk.aws_networkfirewall.CfnFirewall(this, 'network-firewall', {
firewallName: 'network-firewall',
firewallPolicyArn: fw_policy.attrFirewallPolicyArn,
subnetMappings: subnetList,
vpcId: props.vpc.vpcId,
deleteProtection: false,
description: 'AWS Network Firewall to centrally control egress traffic',
firewallPolicyChangeProtection: false,
subnetChangeProtection: true,
});
}
getHomeNet() {
const homeNet = this.vpc.vpcCidrBlock;
console.log("homeNet", homeNet);
return homeNet;
}
getRulesSourcePropertyFromFile(filenameList, rulesVariable) {
const rulesSource = [];
filenameList.forEach((filename) => {
const contents = fs.readFileSync(filename, { encoding: 'utf8', flag: 'r' });
rulesSource.push(new cdk.aws_networkfirewall.CfnRuleGroup(this, path.parse(filename.toString()).name, {
capacity: 1000,
ruleGroupName: path.parse(filename.toString()).name,
type: 'STATEFUL',
ruleGroup: {
ruleVariables: rulesVariable,
rulesSource: {
rulesString: contents.split(/\r?\n/).filter((line) => line.match("^([^#])")).join("\n")
}
},
}));
});
return rulesSource;
}
}
exports.FirewallDistributedVpc = FirewallDistributedVpc;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRmlyZXdhbGxEaXN0cmlidXRlZFZwY0NvbnN0cnVjdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIkZpcmV3YWxsRGlzdHJpYnV0ZWRWcGNDb25zdHJ1Y3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsbUNBQW1DO0FBRW5DLDJDQUF1QztBQUN2Qyx5QkFBeUI7QUFDekIsNkJBQTZCO0FBUTdCLE1BQWEsc0JBQXVCLFNBQVEsc0JBQVM7SUFJbkQsWUFBWSxLQUFnQixFQUFFLEVBQVUsRUFBRSxLQUFrQztRQUMxRSxLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBRWpCLElBQUksQ0FBQyxHQUFHLEdBQUcsS0FBSyxDQUFDLEdBQUcsQ0FBQztRQUVyQixNQUFNLFlBQVksR0FBRyxJQUFJLEdBQUcsQ0FBQyxtQkFBbUIsQ0FBQyxZQUFZLENBQUMsSUFBSSxFQUFFLGVBQWUsRUFBRTtZQUNuRixRQUFRLEVBQUUsSUFBSTtZQUNkLGFBQWEsRUFBRSxlQUFlO1lBQzlCLElBQUksRUFBRSxXQUFXO1lBQ2pCLFNBQVMsRUFBRTtnQkFDVCxXQUFXLEVBQUU7b0JBQ1gsOEJBQThCLEVBQUU7d0JBQzlCLGNBQWMsRUFBRTs0QkFDZDtnQ0FDRSxRQUFRLEVBQUUsQ0FBQztnQ0FDWCxjQUFjLEVBQUU7b0NBQ2QsT0FBTyxFQUFFLENBQUMsb0JBQW9CLENBQUM7b0NBQy9CLGVBQWUsRUFBRTt3Q0FDZixZQUFZLEVBQUUsQ0FBQztnREFDYixpQkFBaUIsRUFBRSxXQUFXOzZDQUMvQixDQUFDO3dDQUNGLE9BQU8sRUFBRSxDQUFDO2dEQUNSLGlCQUFpQixFQUFFLFdBQVc7NkNBQy9CLENBQUM7d0NBQ0YsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDO3dDQUNkLGdCQUFnQixFQUFFOzRDQUNoQjtnREFDRSxRQUFRLEVBQUUsRUFBRTtnREFDWixNQUFNLEVBQUUsRUFBRTs2Q0FDWDs0Q0FDRDtnREFDRSxRQUFRLEVBQUUsR0FBRztnREFDYixNQUFNLEVBQUUsR0FBRzs2Q0FDWjt5Q0FDRjtxQ0FDRjtpQ0FDRjs2QkFDRjs0QkFDRDtnQ0FDRSxRQUFRLEVBQUUsQ0FBQztnQ0FDWCxjQUFjLEVBQUU7b0NBQ2QsT0FBTyxFQUFFLENBQUMsb0JBQW9CLENBQUM7b0NBQy9CLGVBQWUsRUFBRTt3Q0FDZixZQUFZLEVBQUUsQ0FBQztnREFDYixpQkFBaUIsRUFBRSxXQUFXOzZDQUMvQixDQUFDO3dDQUNGLE9BQU8sRUFBRSxDQUFDO2dEQUNSLGlCQUFpQixFQUFFLFdBQVc7NkNBQy9CLENBQUM7d0NBQ0YsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDO3dDQUNkLFdBQVcsRUFBRTs0Q0FDWDtnREFDRSxRQUFRLEVBQUUsRUFBRTtnREFDWixNQUFNLEVBQUUsRUFBRTs2Q0FDWDs0Q0FDRDtnREFDRSxRQUFRLEVBQUUsR0FBRztnREFDYixNQUFNLEVBQUUsR0FBRzs2Q0FDWjt5Q0FDRjtxQ0FDRjtpQ0FDRjs2QkFDRjt5QkFDRjtxQkFDRjtpQkFDRjthQUNGO1NBQ0YsQ0FBQyxDQUFDO1FBRUgsSUFBSSxXQUFXLEdBQWE7WUFDMUIsYUFBYTtZQUNiLGlCQUFpQjtZQUNqQixnQkFBZ0I7WUFDaEIsc0JBQXNCO1lBQ3RCLG9CQUFvQjtZQUNwQixvQkFBb0I7WUFDcEIsa0JBQWtCO1lBQ2xCLG1CQUFtQjtZQUNuQixpQkFBaUI7WUFDakIseUJBQXlCO1lBQ3pCLGtCQUFrQjtZQUNsQixtQkFBbUI7WUFDbkIsZUFBZTtZQUNmLDBCQUEwQjtZQUMxQix5QkFBeUI7WUFDekIsa0JBQWtCO1lBQ2xCLHdCQUF3QjtZQUN4Qix3QkFBd0I7U0FDekIsQ0FBQztRQUVGLE1BQU0sa0JBQWtCLEdBQXVGLEVBQUUsQ0FBQztRQUVsSCxrQkFBa0IsQ0FBQyxJQUFJLENBQUM7WUFDdEIsV0FBVyxFQUNULElBQUksR0FBRyxDQUFDLG1CQUFtQixDQUFDLFlBQVksQ0FBQyxJQUFJLEVBQUUsa0JBQWtCLEVBQUU7Z0JBQ2pFLFFBQVEsRUFBRSxJQUFJO2dCQUNkLGFBQWEsRUFBRSxrQkFBa0I7Z0JBQ2pDLElBQUksRUFBRSxVQUFVO2dCQUNoQixTQUFTLEVBQUU7b0JBQ1QsV0FBVyxFQUFFO3dCQUNYLGVBQWUsRUFBRTs0QkFDZixrQkFBa0IsRUFBRSxXQUFXOzRCQUMvQixPQUFPLEVBQUUsV0FBVzs0QkFDcEIsV0FBVyxFQUFFLENBQUMsU0FBUyxFQUFFLFdBQVcsQ0FBQzt5QkFDdEM7cUJBQ0Y7aUJBQ0Y7YUFDRixDQUFDLENBQUMsR0FBRztTQUNQLENBQ0YsQ0FBQztRQUVGLE1BQU0sYUFBYSxHQUF1QztZQUN4RCxNQUFNLEVBQUU7Z0JBQ04sUUFBUSxFQUFFO29CQUNSLFVBQVUsRUFBRSxDQUFDLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztpQkFDaEM7Z0JBQ0QsWUFBWSxFQUFFO29CQUNaLFVBQVUsRUFBRSxDQUFDLFdBQVcsQ0FBQztpQkFDMUI7YUFDRjtTQUNGLENBQUE7UUFFRCxJQUFHLEtBQUssQ0FBQyxTQUFTLEVBQUM7WUFDakIsTUFBTSxhQUFhLEdBQXVCLElBQUksQ0FBQyw4QkFBOEIsQ0FBQyxLQUFLLENBQUMsU0FBUyxFQUFFLGFBQWEsQ0FBQyxDQUFDO1lBQzlHLEtBQUksSUFBSSxLQUFLLEdBQUMsQ0FBQyxFQUFFLEtBQUssR0FBQyxhQUFhLENBQUMsTUFBTSxFQUFFLEtBQUssRUFBRSxFQUFDO2dCQUNuRCxrQkFBa0IsQ0FBQyxJQUFJLENBQUM7b0JBQ3RCLFdBQVcsRUFDVCxhQUFhLENBQUMsS0FBSyxDQUFDLENBQUMsR0FBRztpQkFDekIsQ0FDRixDQUFBO2FBQ0Y7U0FDRjtRQUFBLENBQUM7UUFFRixNQUFNLDJCQUEyQixHQUFHLElBQUksR0FBRyxDQUFDLG1CQUFtQixDQUFDLFlBQVksQ0FBQyxJQUFJLEVBQUUsZUFBZSxFQUFFO1lBQ2xHLFFBQVEsRUFBRSxJQUFJO1lBQ2QsYUFBYSxFQUFFLGVBQWU7WUFDOUIsSUFBSSxFQUFFLFVBQVU7WUFDaEIsU0FBUyxFQUFFO2dCQUNULFdBQVcsRUFBRTtvQkFDWCxlQUFlLEVBQUU7d0JBQ2Ysa0JBQWtCLEVBQUUsV0FBVzt3QkFDL0IsT0FBTyxFQUFFLFdBQVc7d0JBQ3BCLFdBQVcsRUFBRSxDQUFDLFNBQVMsRUFBRSxXQUFXLENBQUM7cUJBQ3RDO2lCQUNGO2FBQ0Y7U0FDRixDQUFDLENBQUM7UUFFSCxNQUFNLFNBQVMsR0FBRyxJQUFJLEdBQUcsQ0FBQyxtQkFBbUIsQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLEVBQUUsV0FBVyxFQUFFO1lBQ2pGLGtCQUFrQixFQUFFLHlCQUF5QjtZQUM3QyxjQUFjLEVBQUU7Z0JBQ2QsdUJBQXVCLEVBQUUsQ0FBQyxVQUFVLENBQUM7Z0JBQ3JDLCtCQUErQixFQUFFLENBQUMsVUFBVSxDQUFDO2dCQUM3Qyw0QkFBNEIsRUFBRSxDQUFDO3dCQUM3QixRQUFRLEVBQUUsR0FBRzt3QkFDYixXQUFXLEVBQUUsWUFBWSxDQUFDLEdBQUc7cUJBQzlCLENBQUM7Z0JBQ0YsMkJBQTJCLEVBQUUsa0JBQWtCO2FBQ2hEO1NBQ0YsQ0FBQyxDQUFDO1FBRUgsTUFBTSxVQUFVLEdBQTRDLEVBQUUsQ0FBQztRQUMvRCxLQUFLLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FDdEIsQ0FBQyxNQUFNLEVBQUMsRUFBRTtZQUNSLFVBQVUsQ0FBQyxJQUFJLENBQUMsRUFBQyxRQUFRLEVBQUUsTUFBTSxDQUFDLFFBQVEsRUFBQyxDQUFDLENBQUE7UUFDOUMsQ0FBQyxDQUNGLENBQUE7UUFFRCxNQUFNLFFBQVEsR0FBRyxJQUFJLEdBQUcsQ0FBQyxtQkFBbUIsQ0FBQyxXQUFXLENBQUMsSUFBSSxFQUFFLGtCQUFrQixFQUFFO1lBQ2pGLFlBQVksRUFBRSxrQkFBa0I7WUFDaEMsaUJBQWlCLEVBQUUsU0FBUyxDQUFDLHFCQUFxQjtZQUNsRCxjQUFjLEVBQUUsVUFBVTtZQUMxQixLQUFLLEVBQUUsS0FBSyxDQUFDLEdBQUcsQ0FBQyxLQUFLO1lBQ3RCLGdCQUFnQixFQUFFLEtBQUs7WUFDdkIsV0FBVyxFQUFFLDBEQUEwRDtZQUN2RSw4QkFBOEIsRUFBRSxLQUFLO1lBQ3JDLHNCQUFzQixFQUFFLElBQUk7U0FDN0IsQ0FBQyxDQUFDO0lBRUwsQ0FBQztJQUVELFVBQVU7UUFDUixNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLFlBQVksQ0FBQztRQUN0QyxPQUFPLENBQUMsR0FBRyxDQUFDLFNBQVMsRUFBRSxPQUFPLENBQUMsQ0FBQztRQUNoQyxPQUFPLE9BQU8sQ0FBQztJQUNqQixDQUFDO0lBRUQsOEJBQThCLENBQUMsWUFBMkMsRUFBRSxhQUFnRDtRQUUxSCxNQUFNLFdBQVcsR0FBdUIsRUFBRSxDQUFDO1FBRTNDLFlBQVksQ0FBQyxPQUFPLENBQ2xCLENBQUMsUUFBUSxFQUFDLEVBQUU7WUFDVixNQUFNLFFBQVEsR0FBRyxFQUFFLENBQUMsWUFBWSxDQUFDLFFBQVEsRUFBRSxFQUFFLFFBQVEsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLEdBQUcsRUFBRSxDQUFDLENBQUM7WUFDNUUsV0FBVyxDQUFDLElBQUksQ0FDZCxJQUFJLEdBQUcsQ0FBQyxtQkFBbUIsQ0FBQyxZQUFZLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUMsSUFBSSxFQUNuRjtnQkFDRSxRQUFRLEVBQUUsSUFBSTtnQkFDZCxhQUFhLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQyxJQUFJO2dCQUNuRCxJQUFJLEVBQUUsVUFBVTtnQkFDaEIsU0FBUyxFQUFFO29CQUNULGFBQWEsRUFBRSxhQUFhO29CQUM1QixXQUFXLEVBQUU7d0JBQ1gsV0FBVyxFQUFFLFFBQVEsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQztxQkFDeEY7aUJBQ0Y7YUFDRixDQUFDLENBQ0gsQ0FBQTtRQUNILENBQUMsQ0FDRixDQUFBO1FBQ0QsT0FBTyxXQUFXLENBQUM7SUFDckIsQ0FBQztDQUVGO0FBek5ELHdEQXlOQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIGNkayBmcm9tICdhd3MtY2RrLWxpYic7XG5pbXBvcnQgeyBDZm5GaXJld2FsbCwgQ2ZuUnVsZUdyb3VwIH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLW5ldHdvcmtmaXJld2FsbCc7XG5pbXBvcnQgeyBDb25zdHJ1Y3QgfSBmcm9tICdjb25zdHJ1Y3RzJztcbmltcG9ydCAqIGFzIGZzIGZyb20gJ2ZzJztcbmltcG9ydCAqIGFzIHBhdGggZnJvbSAncGF0aCc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgRmlyZXdhbGxEaXN0cmlidXRlZFZwY1Byb3BzIHtcbiAgdnBjOiBjZGsuYXdzX2VjMi5JVnBjO1xuICBzdWJuZXRMaXN0OiBBcnJheTxjZGsuYXdzX2VjMi5JU3VibmV0PjtcbiAgcnVsZXNGaWxlPzogQXJyYXk8ZnMuUGF0aE9yRmlsZURlc2NyaXB0b3I+O1xufVxuXG5leHBvcnQgY2xhc3MgRmlyZXdhbGxEaXN0cmlidXRlZFZwYyBleHRlbmRzIENvbnN0cnVjdCB7XG5cbiAgcHJpdmF0ZSB2cGM6IGNkay5hd3NfZWMyLklWcGM7XG5cbiAgY29uc3RydWN0b3Ioc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgcHJvcHM6IEZpcmV3YWxsRGlzdHJpYnV0ZWRWcGNQcm9wcykge1xuICAgIHN1cGVyKHNjb3BlLCBpZCk7XG5cbiAgICB0aGlzLnZwYyA9IHByb3BzLnZwYztcblxuICAgIGNvbnN0IGFsbG93ZWRwb3J0cyA9IG5ldyBjZGsuYXdzX25ldHdvcmtmaXJld2FsbC5DZm5SdWxlR3JvdXAodGhpcywgJ2FsbG93ZWQtcG9ydHMnLCB7XG4gICAgICBjYXBhY2l0eTogMTAwMCxcbiAgICAgIHJ1bGVHcm91cE5hbWU6ICdhbGxvd2VkLXBvcnRzJyxcbiAgICAgIHR5cGU6ICdTVEFURUxFU1MnLFxuICAgICAgcnVsZUdyb3VwOiB7XG4gICAgICAgIHJ1bGVzU291cmNlOiB7XG4gICAgICAgICAgc3RhdGVsZXNzUnVsZXNBbmRDdXN0b21BY3Rpb25zOiB7XG4gICAgICAgICAgICBzdGF0ZWxlc3NSdWxlczogW1xuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgcHJpb3JpdHk6IDEsXG4gICAgICAgICAgICAgICAgcnVsZURlZmluaXRpb246IHtcbiAgICAgICAgICAgICAgICAgIGFjdGlvbnM6IFsnYXdzOmZvcndhcmRfdG9fc2ZlJ10sXG4gICAgICAgICAgICAgICAgICBtYXRjaEF0dHJpYnV0ZXM6IHtcbiAgICAgICAgICAgICAgICAgICAgZGVzdGluYXRpb25zOiBbe1xuICAgICAgICAgICAgICAgICAgICAgIGFkZHJlc3NEZWZpbml0aW9uOiAnMC4wLjAuMC8wJyxcbiAgICAgICAgICAgICAgICAgICAgfV0sXG4gICAgICAgICAgICAgICAgICAgIHNvdXJjZXM6IFt7XG4gICAgICAgICAgICAgICAgICAgICAgYWRkcmVzc0RlZmluaXRpb246ICcwLjAuMC4wLzAnLFxuICAgICAgICAgICAgICAgICAgICB9XSxcbiAgICAgICAgICAgICAgICAgICAgcHJvdG9jb2xzOiBbNl0sXG4gICAgICAgICAgICAgICAgICAgIGRlc3RpbmF0aW9uUG9ydHM6IFtcbiAgICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICBmcm9tUG9ydDogODAsXG4gICAgICAgICAgICAgICAgICAgICAgICB0b1BvcnQ6IDgwLFxuICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgZnJvbVBvcnQ6IDQ0MyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHRvUG9ydDogNDQzLFxuICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBwcmlvcml0eTogMixcbiAgICAgICAgICAgICAgICBydWxlRGVmaW5pdGlvbjoge1xuICAgICAgICAgICAgICAgICAgYWN0aW9uczogWydhd3M6Zm9yd2FyZF90b19zZmUnXSxcbiAgICAgICAgICAgICAgICAgIG1hdGNoQXR0cmlidXRlczoge1xuICAgICAgICAgICAgICAgICAgICBkZXN0aW5hdGlvbnM6IFt7XG4gICAgICAgICAgICAgICAgICAgICAgYWRkcmVzc0RlZmluaXRpb246ICcwLjAuMC4wLzAnLFxuICAgICAgICAgICAgICAgICAgICB9XSxcbiAgICAgICAgICAgICAgICAgICAgc291cmNlczogW3tcbiAgICAgICAgICAgICAgICAgICAgICBhZGRyZXNzRGVmaW5pdGlvbjogJzAuMC4wLjAvMCcsXG4gICAgICAgICAgICAgICAgICAgIH1dLFxuICAgICAgICAgICAgICAgICAgICBwcm90b2NvbHM6IFs2XSxcbiAgICAgICAgICAgICAgICAgICAgc291cmNlUG9ydHM6IFtcbiAgICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICBmcm9tUG9ydDogODAsXG4gICAgICAgICAgICAgICAgICAgICAgICB0b1BvcnQ6IDgwLFxuICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgZnJvbVBvcnQ6IDQ0MyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHRvUG9ydDogNDQzLFxuICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgfSxcbiAgICAgICAgfSwgICAgICAgIFxuICAgICAgfSxcbiAgICB9KTsgICAgXG5cbiAgICBsZXQgbGlzdGRvbWFpbnM6IHN0cmluZ1tdID0gW1xuICAgICAgJy5kb2NrZXIuY29tJyxcbiAgICAgICcuYXdzLmFtYXpvbi5jb20nLFxuICAgICAgJy5hbWF6b25hd3MuY29tJyxcbiAgICAgICdkb3dubG9hZHMubmVzc3VzLm9yZycsXG4gICAgICAncGx1Z2lucy5uZXNzdXMub3JnJyxcbiAgICAgICcuZmVkb3JhcHJvamVjdC5vcmcnLFxuICAgICAgJy5kdW9zZWN1cml0eS5jb20nLFxuICAgICAgJ2NybDMuZGlnaWNlcnQuY29tJyxcbiAgICAgICdjcmwuZ29kYWRkeS5jb20nLFxuICAgICAgJ2NlcnRpZmljYXRlLmdvZGFkZHkuY29tJyxcbiAgICAgICdvY3NwLmdvZGFkZHkuY29tJyxcbiAgICAgICdjcmw0LmRpZ2ljZXJ0LmNvbScsXG4gICAgICAnLmRpZ2ljZXJ0LmNvbScsXG4gICAgICAnLnJvb3RjYTEuYW1hem9udHJ1c3QuY29tJyxcbiAgICAgICcucm9vdGcyLmFtYXpvbnRydXN0LmNvbScsXG4gICAgICAnLmFtYXpvbnRydXN0LmNvbScsXG4gICAgICAnLnNjYTFhLmFtYXpvbnRydXN0LmNvbScsXG4gICAgICAnLnNjYTFiLmFtYXpvbnRydXN0LmNvbScsXG4gICAgXTtcblxuICAgIGNvbnN0IHN0YXRlZnVsUnVsZUdyb3VwczpBcnJheTxjZGsuYXdzX25ldHdvcmtmaXJld2FsbC5DZm5GaXJld2FsbFBvbGljeS5TdGF0ZWZ1bFJ1bGVHcm91cFJlZmVyZW5jZVByb3BlcnR5PiA9IFtdO1xuXG4gICAgc3RhdGVmdWxSdWxlR3JvdXBzLnB1c2goeyAgICBcbiAgICAgIHJlc291cmNlQXJuOlxuICAgICAgICBuZXcgY2RrLmF3c19uZXR3b3JrZmlyZXdhbGwuQ2ZuUnVsZUdyb3VwKHRoaXMsICdkb21haW4tYWxsb3dsaXN0Jywge1xuICAgICAgICAgIGNhcGFjaXR5OiAxMDAwLFxuICAgICAgICAgIHJ1bGVHcm91cE5hbWU6ICdkb21haW4tYWxsb3dsaXN0JyxcbiAgICAgICAgICB0eXBlOiAnU1RBVEVGVUwnLFxuICAgICAgICAgIHJ1bGVHcm91cDoge1xuICAgICAgICAgICAgcnVsZXNTb3VyY2U6IHtcbiAgICAgICAgICAgICAgcnVsZXNTb3VyY2VMaXN0OiB7XG4gICAgICAgICAgICAgICAgZ2VuZXJhdGVkUnVsZXNUeXBlOiAnQUxMT1dMSVNUJyxcbiAgICAgICAgICAgICAgICB0YXJnZXRzOiBsaXN0ZG9tYWlucyxcbiAgICAgICAgICAgICAgICB0YXJnZXRUeXBlczogWydUTFNfU05JJywgJ0hUVFBfSE9TVCddLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9LFxuICAgICAgICB9KS5yZWZcbiAgICAgIH1cbiAgICApO1xuXG4gICAgY29uc3QgcnVsZXNWYXJpYWJsZTogQ2ZuUnVsZUdyb3VwLlJ1bGVWYXJpYWJsZXNQcm9wZXJ0eSA9IHtcbiAgICAgIGlwU2V0czoge1xuICAgICAgICBIT01FX05FVDoge1xuICAgICAgICAgIGRlZmluaXRpb246IFt0aGlzLmdldEhvbWVOZXQoKV0sXG4gICAgICAgIH0sXG4gICAgICAgIEVYVEVSTkFMX05FVDoge1xuICAgICAgICAgIGRlZmluaXRpb246IFsnMC4wLjAuMC8wJ10sXG4gICAgICAgIH1cbiAgICAgIH0sICAgICAgXG4gICAgfVxuXG4gICAgaWYocHJvcHMucnVsZXNGaWxlKXtcbiAgICAgIGNvbnN0IHJ1bGVzRnJvbUZpbGU6QXJyYXk8Q2ZuUnVsZUdyb3VwPiA9IHRoaXMuZ2V0UnVsZXNTb3VyY2VQcm9wZXJ0eUZyb21GaWxlKHByb3BzLnJ1bGVzRmlsZSwgcnVsZXNWYXJpYWJsZSk7XG4gICAgICBmb3IobGV0IGluZGV4PTA7IGluZGV4PHJ1bGVzRnJvbUZpbGUubGVuZ3RoOyBpbmRleCsrKXtcbiAgICAgICAgc3RhdGVmdWxSdWxlR3JvdXBzLnB1c2goeyAgICBcbiAgICAgICAgICByZXNvdXJjZUFybjogICAgICAgXG4gICAgICAgICAgICBydWxlc0Zyb21GaWxlW2luZGV4XS5yZWZcbiAgICAgICAgICB9XG4gICAgICAgIClcbiAgICAgIH0gICAgXG4gICAgfTtcblxuICAgIGNvbnN0IHJ1bGVzRnJvbUZpbGVHcm91cFJlZmVyZW5jZSA9IG5ldyBjZGsuYXdzX25ldHdvcmtmaXJld2FsbC5DZm5SdWxlR3JvdXAodGhpcywgJ3J1bGVzRnJvbUZpbGUnLCB7XG4gICAgICBjYXBhY2l0eTogMTAwMCxcbiAgICAgIHJ1bGVHcm91cE5hbWU6ICdydWxlc0Zyb21GaWxlJyxcbiAgICAgIHR5cGU6ICdTVEFURUZVTCcsXG4gICAgICBydWxlR3JvdXA6IHtcbiAgICAgICAgcnVsZXNTb3VyY2U6IHtcbiAgICAgICAgICBydWxlc1NvdXJjZUxpc3Q6IHtcbiAgICAgICAgICAgIGdlbmVyYXRlZFJ1bGVzVHlwZTogJ0FMTE9XTElTVCcsXG4gICAgICAgICAgICB0YXJnZXRzOiBsaXN0ZG9tYWlucyxcbiAgICAgICAgICAgIHRhcmdldFR5cGVzOiBbJ1RMU19TTkknLCAnSFRUUF9IT1NUJ10sXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgfSk7ICAgICAgICAgIFxuXG4gICAgY29uc3QgZndfcG9saWN5ID0gbmV3IGNkay5hd3NfbmV0d29ya2ZpcmV3YWxsLkNmbkZpcmV3YWxsUG9saWN5KHRoaXMsICdmd19wb2xpY3knLCB7XG4gICAgICBmaXJld2FsbFBvbGljeU5hbWU6ICduZXR3b3JrLWZpcmV3YWxsLXBvbGljeScsXG4gICAgICBmaXJld2FsbFBvbGljeToge1xuICAgICAgICBzdGF0ZWxlc3NEZWZhdWx0QWN0aW9uczogWydhd3M6ZHJvcCddLFxuICAgICAgICBzdGF0ZWxlc3NGcmFnbWVudERlZmF1bHRBY3Rpb25zOiBbJ2F3czpkcm9wJ10sXG4gICAgICAgIHN0YXRlbGVzc1J1bGVHcm91cFJlZmVyZW5jZXM6IFt7XG4gICAgICAgICAgcHJpb3JpdHk6IDEwMCxcbiAgICAgICAgICByZXNvdXJjZUFybjogYWxsb3dlZHBvcnRzLnJlZixcbiAgICAgICAgfV0sXG4gICAgICAgIHN0YXRlZnVsUnVsZUdyb3VwUmVmZXJlbmNlczogc3RhdGVmdWxSdWxlR3JvdXBzXG4gICAgICB9LFxuICAgIH0pOyBcbiAgICBcbiAgICBjb25zdCBzdWJuZXRMaXN0OkFycmF5PENmbkZpcmV3YWxsLlN1Ym5ldE1hcHBpbmdQcm9wZXJ0eT4gPSBbXTtcbiAgICBwcm9wcy5zdWJuZXRMaXN0LmZvckVhY2goXG4gICAgICAoc3VibmV0KT0+e1xuICAgICAgICBzdWJuZXRMaXN0LnB1c2goe3N1Ym5ldElkOiBzdWJuZXQuc3VibmV0SWR9KVxuICAgICAgfVxuICAgIClcblxuICAgIGNvbnN0IGZpcmV3YWxsID0gbmV3IGNkay5hd3NfbmV0d29ya2ZpcmV3YWxsLkNmbkZpcmV3YWxsKHRoaXMsICduZXR3b3JrLWZpcmV3YWxsJywge1xuICAgICAgZmlyZXdhbGxOYW1lOiAnbmV0d29yay1maXJld2FsbCcsXG4gICAgICBmaXJld2FsbFBvbGljeUFybjogZndfcG9saWN5LmF0dHJGaXJld2FsbFBvbGljeUFybixcbiAgICAgIHN1Ym5ldE1hcHBpbmdzOiBzdWJuZXRMaXN0LFxuICAgICAgdnBjSWQ6IHByb3BzLnZwYy52cGNJZCxcbiAgICAgIGRlbGV0ZVByb3RlY3Rpb246IGZhbHNlLFxuICAgICAgZGVzY3JpcHRpb246ICdBV1MgTmV0d29yayBGaXJld2FsbCB0byBjZW50cmFsbHkgY29udHJvbCBlZ3Jlc3MgdHJhZmZpYycsXG4gICAgICBmaXJld2FsbFBvbGljeUNoYW5nZVByb3RlY3Rpb246IGZhbHNlLFxuICAgICAgc3VibmV0Q2hhbmdlUHJvdGVjdGlvbjogdHJ1ZSxcbiAgICB9KTtcblxuICB9XG5cbiAgZ2V0SG9tZU5ldCgpOiBzdHJpbmd7XG4gICAgY29uc3QgaG9tZU5ldCA9IHRoaXMudnBjLnZwY0NpZHJCbG9jaztcbiAgICBjb25zb2xlLmxvZyhcImhvbWVOZXRcIiwgaG9tZU5ldCk7XG4gICAgcmV0dXJuIGhvbWVOZXQ7XG4gIH1cblxuICBnZXRSdWxlc1NvdXJjZVByb3BlcnR5RnJvbUZpbGUoZmlsZW5hbWVMaXN0OkFycmF5PGZzLlBhdGhPckZpbGVEZXNjcmlwdG9yPiwgcnVsZXNWYXJpYWJsZTpDZm5SdWxlR3JvdXAuUnVsZVZhcmlhYmxlc1Byb3BlcnR5KTpBcnJheTxDZm5SdWxlR3JvdXA+e1xuXG4gICAgY29uc3QgcnVsZXNTb3VyY2U6QXJyYXk8Q2ZuUnVsZUdyb3VwPiA9IFtdO1xuXG4gICAgZmlsZW5hbWVMaXN0LmZvckVhY2goXG4gICAgICAoZmlsZW5hbWUpPT57XG4gICAgICAgIGNvbnN0IGNvbnRlbnRzID0gZnMucmVhZEZpbGVTeW5jKGZpbGVuYW1lLCB7IGVuY29kaW5nOiAndXRmOCcsIGZsYWc6ICdyJyB9KTtcbiAgICAgICAgcnVsZXNTb3VyY2UucHVzaCggXG4gICAgICAgICAgbmV3IGNkay5hd3NfbmV0d29ya2ZpcmV3YWxsLkNmblJ1bGVHcm91cCh0aGlzLCBwYXRoLnBhcnNlKGZpbGVuYW1lLnRvU3RyaW5nKCkpLm5hbWUsXG4gICAgICAgICAge1xuICAgICAgICAgICAgY2FwYWNpdHk6IDEwMDAsXG4gICAgICAgICAgICBydWxlR3JvdXBOYW1lOiBwYXRoLnBhcnNlKGZpbGVuYW1lLnRvU3RyaW5nKCkpLm5hbWUsXG4gICAgICAgICAgICB0eXBlOiAnU1RBVEVGVUwnLFxuICAgICAgICAgICAgcnVsZUdyb3VwOiB7XG4gICAgICAgICAgICAgIHJ1bGVWYXJpYWJsZXM6IHJ1bGVzVmFyaWFibGUsXG4gICAgICAgICAgICAgIHJ1bGVzU291cmNlOiB7XG4gICAgICAgICAgICAgICAgcnVsZXNTdHJpbmc6IGNvbnRlbnRzLnNwbGl0KC9cXHI/XFxuLykuZmlsdGVyKChsaW5lKSA9PiBsaW5lLm1hdGNoKFwiXihbXiNdKVwiKSkuam9pbihcIlxcblwiKVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0pICAgICAgICAgIFxuICAgICAgICApXG4gICAgICB9XG4gICAgKVxuICAgIHJldHVybiBydWxlc1NvdXJjZTtcbiAgfVxuXG59XG4iXX0=