UNPKG

@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
"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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRmlyZXdhbGxEaXN0cmlidXRlZFZwY0NvbnN0cnVjdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIkZpcmV3YWxsRGlzdHJpYnV0ZWRWcGNDb25zdHJ1Y3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsbUNBQW1DO0FBRW5DLDJDQUF1QztBQUN2Qyx5QkFBeUI7QUFDekIsNkJBQTZCO0FBUTdCLE1BQWEsc0JBQXVCLFNBQVEsc0JBQVM7SUFJbkQsWUFBWSxLQUFnQixFQUFFLEVBQVUsRUFBRSxLQUFrQztRQUMxRSxLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBRWpCLElBQUksQ0FBQyxHQUFHLEdBQUcsS0FBSyxDQUFDLEdBQUcsQ0FBQztRQUVyQixNQUFNLFlBQVksR0FBRyxJQUFJLEdBQUcsQ0FBQyxtQkFBbUIsQ0FBQyxZQUFZLENBQUMsSUFBSSxFQUFFLGVBQWUsRUFBRTtZQUNuRixRQUFRLEVBQUUsSUFBSTtZQUNkLGFBQWEsRUFBRSxlQUFlO1lBQzlCLElBQUksRUFBRSxXQUFXO1lBQ2pCLFNBQVMsRUFBRTtnQkFDVCxXQUFXLEVBQUU7b0JBQ1gsOEJBQThCLEVBQUU7d0JBQzlCLGNBQWMsRUFBRTs0QkFDZDtnQ0FDRSxRQUFRLEVBQUUsQ0FBQztnQ0FDWCxjQUFjLEVBQUU7b0NBQ2QsT0FBTyxFQUFFLENBQUMsb0JBQW9CLENBQUM7b0NBQy9CLGVBQWUsRUFBRTt3Q0FDZixZQUFZLEVBQUUsQ0FBQztnREFDYixpQkFBaUIsRUFBRSxXQUFXOzZDQUMvQixDQUFDO3dDQUNGLE9BQU8sRUFBRSxDQUFDO2dEQUNSLGlCQUFpQixFQUFFLFdBQVc7NkNBQy9CLENBQUM7d0NBQ0YsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDO3dDQUNkLGdCQUFnQixFQUFFOzRDQUNoQjtnREFDRSxRQUFRLEVBQUUsRUFBRTtnREFDWixNQUFNLEVBQUUsRUFBRTs2Q0FDWDs0Q0FDRDtnREFDRSxRQUFRLEVBQUUsR0FBRztnREFD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QUFXLENBQUM7SUFDckIsQ0FBQztDQUVGO0FBek5ELHdEQXlOQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIGNkayBmcm9tICdhd3MtY2RrLWxpYic7XG5pbXBvcnQgeyBDZm5GaXJld2FsbCwgQ2ZuUnVsZUdyb3VwIH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLW5ldHdvcmtmaXJld2FsbCc7XG5pbXBvcnQgeyBDb25zdHJ1Y3QgfSBmcm9tICdjb25zdHJ1Y3RzJztcbmltcG9ydCAqIGFzIGZzIGZyb20gJ2ZzJztcbmltcG9ydCAqIGFzIHBhdGggZnJvbSAncGF0aCc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgRmlyZXdhbGxEaXN0cmlidXRlZFZwY1Byb3BzIHtcbiAgdnBjOiBjZGsuYXdzX2VjMi5JVnBjO1xuICBzdWJuZXRMaXN0OiBBcnJheTxjZGsuYXdzX2VjMi5JU3VibmV0PjtcbiAgcnVsZXNGaWxlPzogQXJyYXk8ZnMuUGF0aE9yRmlsZURlc2NyaXB0b3I+O1xufVxuXG5leHBvcnQgY2xhc3MgRmlyZXdhbGxEaXN0cmlidXRlZFZwYyBleHRlbmRzIENvbnN0cnVjdCB7XG5cbiAgcHJpdmF0ZSB2cGM6IGNkay5hd3NfZWMyLklWcGM7XG5cbiAgY29uc3RydWN0b3Ioc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgcHJvcHM6IEZpcmV3YWxsRGlzdHJpYnV0ZWRWcGNQcm9wcykge1xuICAgIHN1cGVyKHNjb3BlLCBpZCk7XG5cbiAgICB0aGlzLnZwYyA9IHByb3BzLnZwYztcblxuICAgIGNvbnN0IGFsbG93ZWRwb3J0cyA9IG5ldyBjZGsuYXdzX25ldHdvcmtmaXJld2FsbC5DZm5SdWxlR3JvdXAodGhpcywgJ2FsbG93ZWQtcG9ydHMnLCB7XG4gICAgICBjYXBhY2l0eTogMTAwMCxcbiAgICAgIHJ1bGVHcm91cE5hbWU6ICdhbGxvd2VkLXBvcnRzJyxcbiAgICAgIHR5cGU6ICdTVEFURUxFU1MnLFxuICAgICAgcnVsZUdyb3VwOiB7XG4gICAgICAgIHJ1bGVzU291cmNlOiB7XG4gICAgICAgICAgc3RhdGVsZXNzUnVsZXNBbmRDdXN0b21BY3Rpb25zOiB7XG4gICAgICAgICAgICBzdGF0ZWxlc3NSdWxlczogW1xuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgcHJpb3JpdHk6IDEsXG4gICAgICAgICAgICAgICAgcnVsZURlZmluaXRpb246IHtcbiAgICAgICAgICAgICAgICAgIGFjdGlvbnM6IFsnYXdzOmZvcndhcmRfdG9fc2ZlJ10sXG4gICAgICAgICAgICAgICAgICBtYXRjaEF0dHJpYnV0ZXM6IHtcbiAgICAgICAgICAgICAgICAgICAgZGVzdGluYXRpb25zOiBbe1xuICAgICAgICAgICAgICAgICAgICAgIGFkZHJlc3NEZWZpbml0aW9uOiAnMC4wLjAuMC8wJyxcbiAgICAgICAgICAgICAgICAgICAgfV0sXG4gICAgICAgICAgICAgICAgICAgIHNvdXJjZXM6IFt7XG4gICAgICAgICAgICAgICAgICAgICAgYWRkcmVzc0RlZmluaXRpb246ICcwLjAuMC4wLzAnLFxuICAgICAgICAgICAgICAgICAgICB9XSxcbiAgICAgICAgICAgICAgICAgICAgcHJvdG9jb2xzOiBbNl0sXG4gICAgICAgICAgICAgICAgICAgIGRlc3RpbmF0aW9uUG9ydHM6IFtcbiAgICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICBmcm9tUG9ydDogODAsXG4gICAgICAgICAgICAgICAgICAgICAgICB0b1BvcnQ6IDgwLFxuICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgZnJvbVBvcnQ6IDQ0MyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHRvUG9ydDogNDQzLFxuICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBwcmlvcml0eTogMixcbiAgICAgICAgICAgICAgICBydWxlRGVmaW5pdGlvbjoge1xuICAgICAgICAgICAgICAgICAgYWN0aW9uczogWydhd3M6Zm9yd2FyZF90b19zZmUnXSxcbiAgICAgICAgICAgICAgICAgIG1hdGNoQXR0cmlidXRlczoge1xuICAgICAgICAgICAgICAgICAgICBkZXN0aW5hdGlvbnM6IFt7XG4gICAgICAgICAgICAgICAgICAgICAgYWRkcmVzc0RlZmluaXRpb246ICcwLjAuMC4wLzAnLFxuICAgICAgICAgICAgICAgICAgICB9XSxcbiAgICAgICAgICAgICAgICAgICAgc291cmNlczogW3tcbiAgICAgICAgICAgICAgICAgICAgICBhZGRyZXNzRGVmaW5pdGlvbjogJzAuMC4wLjAvMCcsXG4gICAgICAgICAgICAgICAgICAgIH1dLFxuICAgICAgICAgICAgICAgICAgICBwcm90b2NvbHM6IFs2XSxcbiAgICAgICAgICAgICAgICAgICAgc291cmNlUG9ydHM6IFtcbiAgICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICBmcm9tUG9ydDogODAsXG4gICAgICAgICAgICAgICAgICAgICAgICB0b1BvcnQ6IDgwLFxuICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgZnJvbVBvcnQ6IDQ0MyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHRvUG9ydDogNDQzLFxuICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgfSxcbiAgICAgICAgfSwgICAgICAgIFxuICAgICAgfSxcbiAgICB9KTsgICAgXG5cbiAgICBsZXQgbGlzdGRvbWFpbnM6IHN0cmluZ1tdID0gW1xuICAgICAgJy5kb2NrZXIuY29tJyxcbiAgICAgICcuYXdzLmFtYXpvbi5jb20nLFxuICAgICAgJy5hbWF6b25hd3MuY29tJyxcbiAgICAgICdkb3dubG9hZHMubmVzc3VzLm9yZycsXG4gICAgICAncGx1Z2lucy5uZXNzdXMub3JnJyxcbiAgICAgICcuZmVkb3JhcHJvamVjdC5vcmcnLFxuICAgICAgJy5kdW9zZWN1cml0eS5jb20nLFxuICAgICAgJ2NybDMuZGlnaWNlcnQuY29tJyxcbiAgICAgICdjcmwuZ29kYWRkeS5jb20nLFxuICAgICAgJ2NlcnRpZmljYXRlLmdvZGFkZHkuY29tJyxcbiAgICAgICdvY3NwLmdvZGFkZHkuY29tJyxcbiAgICAgICdjcmw0LmRpZ2ljZXJ0LmNvbScsXG4gICAgICAnLmRpZ2ljZXJ0LmNvbScsXG4gICAgICAnLnJvb3RjYTEuYW1hem9udHJ1c3QuY29tJyxcbiAgICAgICcucm9vdGcyLmFtYXpvbnRydXN0LmNvbScsXG4gICAgICAnLmFtYXpvbnRydXN0LmNvbScsXG4gICAgICAnLnNjYTFhLmFtYXpvbnRydXN0LmNvbScsXG4gICAgICAnLnNjYTFiLmFtYXpvbnRydXN0LmNvbScsXG4gICAgXTtcblxuICAgIGNvbnN0IHN0YXRlZnVsUnVsZUdyb3VwczpBcnJheTxjZGsuYXdzX25ldHdvcmtmaXJld2FsbC5DZm5GaXJld2FsbFBvbGljeS5TdGF0ZWZ1bFJ1bGVHcm91cFJlZmVyZW5jZVByb3BlcnR5PiA9IFtdO1xuXG4gICAgc3RhdGVmdWxSdWxlR3JvdXBzLnB1c2goeyAgICBcbiAgICAgIHJlc291cmNlQXJuOlxuICAgICAgICBuZXcgY2RrLmF3c19uZXR3b3JrZmlyZXdhbGwuQ2ZuUnVsZUdyb3VwKHRoaXMsICdkb21haW4tYWxsb3dsaXN0Jywge1xuICAgICAgICAgIGNhcGFjaXR5OiAxMDAwLFxuICAgICAgICAgIHJ1bGVHcm91cE5hbWU6ICdkb21haW4tYWxsb3dsaXN0JyxcbiAgICAgICAgICB0eXBlOiAnU1RBVEVGVUwnLFxuICAgICAgICAgIHJ1bGVHcm91cDoge1xuICAgICAgICAgICAgcnVsZXNTb3VyY2U6IHtcbiAgICAgICAgICAgICAgcnVsZXNTb3VyY2VMaXN0OiB7XG4gICAgICAgICAgICAgICAgZ2VuZXJhdGVkUnVsZXNUeXBlOiAnQUxMT1dMSVNUJyxcbiAgICAgICAgICAgICAgICB0YXJnZXRzOiBsaXN0ZG9tYWlucyxcbiAgICAgICAgICAgICAgICB0YXJnZXRUeXBlczogWydUTFNfU05JJywgJ0hUVFBfSE9TVCddLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9LFxuICAgICAgICB9KS5yZWZcbiAgICAgIH1cbiAgICApO1xuXG4gICAgY29uc3QgcnVsZXNWYXJpYWJsZTogQ2ZuUnVsZUdyb3VwLlJ1bGVWYXJpYWJsZXNQcm9wZXJ0eSA9IHtcbiAgICAgIGlwU2V0czoge1xuICAgICAgICBIT01FX05FVDoge1xuICAgICAgICAgIGRlZmluaXRpb246IFt0aGlzLmdldEhvbWVOZXQoKV0sXG4gICAgICAgIH0sXG4gICAgICAgIEVYVEVSTkFMX05FVDoge1xuICAgICAgICAgIGRlZmluaXRpb246IFsnMC4wLjAuMC8wJ10sXG4gICAgICAgIH1cbiAgICAgIH0sICAgICAgXG4gICAgfVxuXG4gICAgaWYocHJvcHMucnVsZXNGaWxlKXtcbiAgICAgIGNvbnN0IHJ1bGVzRnJvbUZpbGU6QXJyYXk8Q2ZuUnVsZUdyb3VwPiA9IHRoaXMuZ2V0UnVsZXNTb3VyY2VQcm9wZXJ0eUZyb21GaWxlKHByb3BzLnJ1bGVzRmlsZSwgcnVsZXNWYXJpYWJsZSk7XG4gICAgICBmb3IobGV0IGluZGV4PTA7IGluZGV4PHJ1bGVzRnJvbUZpbGUubGVuZ3RoOyBpbmRleCsrKXtcbiAgICAgICAgc3RhdGVmdWxSdWxlR3JvdXBzLnB1c2goeyAgICBcbiAgICAgICAgICByZXNvdXJjZUFybjogICAgICAgXG4gICAgICAgICAgICBydWxlc0Zyb21GaWxlW2luZGV4XS5yZWZcbiAgICAgICAgICB9XG4gICAgICAgIClcbiAgICAgIH0gICAgXG4gICAgfTtcblxuICAgIGNvbnN0IHJ1bGVzRnJvbUZpbGVHcm91cFJlZmVyZW5jZSA9IG5ldyBjZGsuYXdzX25ldHdvcmtmaXJld2FsbC5DZm5SdWxlR3JvdXAodGhpcywgJ3J1bGVzRnJvbUZpbGUnLCB7XG4gICAgICBjYXBhY2l0eTogMTAwMCxcbiAgICAgIHJ1bGVHcm91cE5hbWU6ICdydWxlc0Zyb21GaWxlJyxcbiAgICAgIHR5cGU6ICdTVEFURUZVTCcsXG4gICAgICBydWxlR3JvdXA6IHtcbiAgICAgICAgcnVsZXNTb3VyY2U6IHtcbiAgICAgICAgICBydWxlc1NvdXJjZUxpc3Q6IHtcbiAgICAgICAgICAgIGdlbmVyYXRlZFJ1bGVzVHlwZTogJ0FMTE9XTElTVCcsXG4gICAgICAgICAgICB0YXJnZXRzOiBsaXN0ZG9tYWlucyxcbiAgICAgICAgICAgIHRhcmdldFR5cGVzOiBbJ1RMU19TTkknLCAnSFRUUF9IT1NUJ10sXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgfSk7ICAgICAgICAgIFxuXG4gICAgY29uc3QgZndfcG9saWN5ID0gbmV3IGNkay5hd3NfbmV0d29ya2ZpcmV3YWxsLkNmbkZpcmV3YWxsUG9saWN5KHRoaXMsICdmd19wb2xpY3knLCB7XG4gICAgICBmaXJld2FsbFBvbGljeU5hbWU6ICduZXR3b3JrLWZpcmV3YWxsLXBvbGljeScsXG4gICAgICBmaXJld2FsbFBvbGljeToge1xuICAgICAgICBzdGF0ZWxlc3NEZWZhdWx0QWN0aW9uczogWydhd3M6ZHJvcCddLFxuICAgICAgICBzdGF0ZWxlc3NGcmFnbWVudERlZmF1bHRBY3Rpb25zOiBbJ2F3czpkcm9wJ10sXG4gICAgICAgIHN0YXRlbGVzc1J1bGVHcm91cFJlZmVyZW5jZXM6IFt7XG4gICAgICAgICAgcHJpb3JpdHk6IDEwMCxcbiAgICAgICAgICByZXNvdXJjZUFybjogYWxsb3dlZHBvcnRzLnJlZixcbiAgICAgICAgfV0sXG4gICAgICAgIHN0YXRlZnVsUnVsZUdyb3VwUmVmZXJlbmNlczogc3RhdGVmdWxSdWxlR3JvdXBzXG4gICAgICB9LFxuICAgIH0pOyBcbiAgICBcbiAgICBjb25zdCBzdWJuZXRMaXN0OkFycmF5PENmbkZpcmV3YWxsLlN1Ym5ldE1hcHBpbmdQcm9wZXJ0eT4gPSBbXTtcbiAgICBwcm9wcy5zdWJuZXRMaXN0LmZvckVhY2goXG4gICAgICAoc3VibmV0KT0+e1xuICAgICAgICBzdWJuZXRMaXN0LnB1c2goe3N1Ym5ldElkOiBzdWJuZXQuc3VibmV0SWR9KVxuICAgICAgfVxuICAgIClcblxuICAgIGNvbnN0IGZpcmV3YWxsID0gbmV3IGNkay5hd3NfbmV0d29ya2ZpcmV3YWxsLkNmbkZpcmV3YWxsKHRoaXMsICduZXR3b3JrLWZpcmV3YWxsJywge1xuICAgICAgZmlyZXdhbGxOYW1lOiAnbmV0d29yay1maXJld2FsbCcsXG4gICAgICBmaXJld2FsbFBvbGljeUFybjogZndfcG9saWN5LmF0dHJGaXJld2FsbFBvbGljeUFybixcbiAgICAgIHN1Ym5ldE1hcHBpbmdzOiBzdWJuZXRMaXN0LFxuICAgICAgdnBjSWQ6IHByb3BzLnZwYy52cGNJZCxcbiAgICAgIGRlbGV0ZVByb3RlY3Rpb246IGZhbHNlLFxuICAgICAgZGVzY3JpcHRpb246ICdBV1MgTmV0d29yayBGaXJld2FsbCB0byBjZW50cmFsbHkgY29udHJvbCBlZ3Jlc3MgdHJhZmZpYycsXG4gICAgICBmaXJld2FsbFBvbGljeUNoYW5nZVByb3RlY3Rpb246IGZhbHNlLFxuICAgICAgc3VibmV0Q2hhbmdlUHJvdGVjdGlvbjogdHJ1ZSxcbiAgICB9KTtcblxuICB9XG5cbiAgZ2V0SG9tZU5ldCgpOiBzdHJpbmd7XG4gICAgY29uc3QgaG9tZU5ldCA9IHRoaXMudnBjLnZwY0NpZHJCbG9jaztcbiAgICBjb25zb2xlLmxvZyhcImhvbWVOZXRcIiwgaG9tZU5ldCk7XG4gICAgcmV0dXJuIGhvbWVOZXQ7XG4gIH1cblxuICBnZXRSdWxlc1NvdXJjZVByb3BlcnR5RnJvbUZpbGUoZmlsZW5hbWVMaXN0OkFycmF5PGZzLlBhdGhPckZpbGVEZXNjcmlwdG9yPiwgcnVsZXNWYXJpYWJsZTpDZm5SdWxlR3JvdXAuUnVsZVZhcmlhYmxlc1Byb3BlcnR5KTpBcnJheTxDZm5SdWxlR3JvdXA+e1xuXG4gICAgY29uc3QgcnVsZXNTb3VyY2U6QXJyYXk8Q2ZuUnVsZUdyb3VwPiA9IFtdO1xuXG4gICAgZmlsZW5hbWVMaXN0LmZvckVhY2goXG4gICAgICAoZmlsZW5hbWUpPT57XG4gICAgICAgIGNvbnN0IGNvbnRlbnRzID0gZnMucmVhZEZpbGVTeW5jKGZpbGVuYW1lLCB7IGVuY29kaW5nOiAndXRmOCcsIGZsYWc6ICdyJyB9KTtcbiAgICAgICAgcnVsZXNTb3VyY2UucHVzaCggXG4gICAgICAgICAgbmV3IGNkay5hd3NfbmV0d29ya2ZpcmV3YWxsLkNmblJ1bGVHcm91cCh0aGlzLCBwYXRoLnBhcnNlKGZpbGVuYW1lLnRvU3RyaW5nKCkpLm5hbWUsXG4gICAgICAgICAge1xuICAgICAgICAgICAgY2FwYWNpdHk6IDEwMDAsXG4gICAgICAgICAgICBydWxlR3JvdXBOYW1lOiBwYXRoLnBhcnNlKGZpbGVuYW1lLnRvU3RyaW5nKCkpLm5hbWUsXG4gICAgICAgICAgICB0eXBlOiAnU1RBVEVGVUwnLFxuICAgICAgICAgICAgcnVsZUdyb3VwOiB7XG4gICAgICAgICAgICAgIHJ1bGVWYXJpYWJsZXM6IHJ1bGVzVmFyaWFibGUsXG4gICAgICAgICAgICAgIHJ1bGVzU291cmNlOiB7XG4gICAgICAgICAgICAgICAgcnVsZXNTdHJpbmc6IGNvbnRlbnRzLnNwbGl0KC9cXHI/XFxuLykuZmlsdGVyKChsaW5lKSA9PiBsaW5lLm1hdGNoKFwiXihbXiNdKVwiKSkuam9pbihcIlxcblwiKVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0pICAgICAgICAgIFxuICAgICAgICApXG4gICAgICB9XG4gICAgKVxuICAgIHJldHVybiBydWxlc1NvdXJjZTtcbiAgfVxuXG59XG4iXX0=