UNPKG

raindancers-network

Version:
260 lines 37.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.SuricataRuleGroup = exports.PrefixList = exports.IPAddressFamily = exports.FQDNStatefulRule = exports.Direction = exports.FWProtocol = exports.StatefulAction = void 0; const path = require("path"); const aws_cdk_lib_1 = require("aws-cdk-lib"); const cdk = require("aws-cdk-lib"); const constructs = require("constructs"); const resourceGroups_1 = require("./resourceGroups"); var StatefulAction; (function (StatefulAction) { /** * Traffic will pass */ StatefulAction["PASS"] = "pass"; /** * Traffic will be droped silently. Note, When will cause a timeout for TCP, Consider using REJECT */ StatefulAction["DROP"] = "drop"; /** * Traffic will be dropped, and a TCP reset sent to the source */ StatefulAction["REJECT"] = "reject"; /** * Raises an alert according to the firewalls logging/alert */ StatefulAction["ALERT"] = "alert"; })(StatefulAction = exports.StatefulAction || (exports.StatefulAction = {})); var FWProtocol; (function (FWProtocol) { FWProtocol["TCP"] = "tcp"; FWProtocol["UPD"] = "udp"; FWProtocol["ICMP"] = "icmp"; FWProtocol["IP"] = "ip"; FWProtocol["HTTP"] = "http"; FWProtocol["TLS"] = "tls"; })(FWProtocol = exports.FWProtocol || (exports.FWProtocol = {})); var Direction; (function (Direction) { /** * Traffic allowed from Src to destination only */ Direction["OUTBOUND"] = "->"; /** * Traffic allowed in both directions */ Direction["BOTH"] = "<>"; })(Direction = exports.Direction || (exports.Direction = {})); class FQDNStatefulRule extends constructs.Construct { constructor(scope, id, props) { super(scope, id); this.prefixListSet = []; this.resourceGroupSets = []; if (!([FWProtocol.HTTP, FWProtocol.TLS].includes(props.protocol))) { throw new Error('The protocol for FQDN Rules must be HTTP or TLS'); } let priority = 1; if (props.priority) { priority = props.priority; } let matchingMessage = 'matching denyed FQDNs'; if (props.action == StatefulAction.PASS) { matchingMessage = 'matching allowed FQDNs'; } var options = ''; if (props.protocol === FWProtocol.HTTP) { options = `(http.host; content:"${props.fqdn}"; startswith; endswith; msg:"${matchingMessage}"; priority:${priority}; flow:to_server, established;`; //sid:${getSid()}; rev:1;)` } if (props.protocol === FWProtocol.TLS) { options = `(tls.sni; content:"${props.fqdn}"; startswith; endswith; msg:"${matchingMessage}"; priority:${priority}; flow:to_server, established;`; //sid:${getSid()}; rev:1;)` } let source = ''; if (props.source instanceof PrefixList) { source = '@' + props.source.prefixlist.prefixListName; this.prefixListSet.push(props.source.prefixListSet); } else if (props.source instanceof resourceGroups_1.DynamicTagResourceGroup) { source = '@' + props.source.name; this.resourceGroupSets.push({ name: props.source.name, arn: props.source.groupArn }); } else { source = props.source; } let destination = ''; if (props.destination instanceof PrefixList) { destination = '@' + props.destination.prefixlist.prefixListName; this.prefixListSet.push(props.destination.prefixListSet); } else if (props.destination instanceof resourceGroups_1.DynamicTagResourceGroup) { source = '@' + props.destination; this.resourceGroupSets.push({ name: props.destination.name, arn: props.destination.groupArn }); } else { destination = props.destination; } var rule = ''.concat(props.action, ' ', //drop props.protocol, ' ', // protocol source, ' ', // @example props.srcPort, ' ', // any props.direction, ' ', // -> destination, ' ', // $EXTERNAL_NET props.destPort, ' ', // any options); const suricataRule = new cdk.CustomResource(this, `${id}customresource`, { serviceToken: props.rulesDatabase?.crudServiceToken, properties: { Rule: rule, }, }); this.uuid = suricataRule.getAttString('UUID'); } } exports.FQDNStatefulRule = FQDNStatefulRule; var IPAddressFamily; (function (IPAddressFamily) { IPAddressFamily["IPV4"] = "IPv4"; IPAddressFamily["IPV6"] = "IPv6"; })(IPAddressFamily = exports.IPAddressFamily || (exports.IPAddressFamily = {})); class PrefixList extends constructs.Construct { constructor(scope, id, props) { super(scope, id); this.entries = []; this.prefixlist = new aws_cdk_lib_1.aws_ec2.CfnPrefixList(this, `prefix-list${id}`, { addressFamily: props.addressFamily, prefixListName: props.prefixListName, maxEntries: props.maxEntries, entries: this.entries, }); this.prefixlistArn = this.prefixlist.attrArn; this.prefixListSet = { arn: this.prefixlist.attrArn, name: props.prefixListName }; } addEC2Instance(props) { this.entries.push({ cidr: props.instancePrivateIp + '/32', description: props.instancePrivateDnsName, }); } } exports.PrefixList = PrefixList; class SuricataRuleGroup extends constructs.Construct { constructor(scope, id, props) { super(scope, id); this.ruleGroupArn = ''; this.ruleReferenceSets = []; this.ruleuuidlist = []; this.rulesDatabase = props.networkFirewallEngine.rulesDatabase; const suricataRuleGroupLambda = new aws_cdk_lib_1.aws_lambda.Function(this, 'fqdnLambda', { timeout: cdk.Duration.seconds(300), runtime: aws_cdk_lib_1.aws_lambda.Runtime.PYTHON_3_9, handler: 'suricata_rule.on_event', code: aws_cdk_lib_1.aws_lambda.Code.fromAsset(path.join(__dirname, '../../lambda/firewall'), { bundling: { image: aws_cdk_lib_1.aws_lambda.Runtime.PYTHON_3_9.bundlingImage, command: [ 'bash', '-c', 'pip install -r requirements.txt -t /asset-output && cp -au . /asset-output', ], }, }), environment: { TableName: props.networkFirewallEngine.rulesDatabase.policyTable.tableName, }, }); this.crLambda = suricataRuleGroupLambda; suricataRuleGroupLambda.addToRolePolicy(new aws_cdk_lib_1.aws_iam.PolicyStatement({ effect: aws_cdk_lib_1.aws_iam.Effect.ALLOW, resources: ['*'], actions: [ 'network-firewall:DescribeRuleGroup', 'network-firewall:DeleteRuleGroup', 'network-firewall:CreateRuleGroup', 'network-firewall:UpdateRuleGroup', 'iam:CreateServiceLinkedRole', 'ec2:GetManagedPrefixListEntries', 'resource-groups:Get*', 'resource-groups:List*', ], })); props.networkFirewallEngine.rulesDatabase.policyTable.grantReadData(suricataRuleGroupLambda); // this is not permitted by default in 'read?' suricataRuleGroupLambda.addToRolePolicy(new aws_cdk_lib_1.aws_iam.PolicyStatement({ effect: aws_cdk_lib_1.aws_iam.Effect.ALLOW, resources: [props.networkFirewallEngine.rulesDatabase.policyTable.tableArn], actions: [ 'dynamodb:PartiQLSelect', ], })); const suricataRuleCr = new cdk.CustomResource(this, `${props.ruleGroupName}customresource`, { serviceToken: new aws_cdk_lib_1.custom_resources.Provider(this, `${props.ruleGroupName}serviceprovider`, { onEventHandler: this.crLambda, }).serviceToken, properties: { Capacity: props.capacity, RuleGroupName: props.ruleGroupName, Description: props.description, Rules: this.ruleuuidlist, ReferenceSets: this.ruleReferenceSets, }, }); this.ruleGroupArn = suricataRuleCr.getAttString('RuleGroupArn'); new aws_cdk_lib_1.aws_ram.CfnResourceShare(this, 'shareRuleGroup', { name: props.ruleGroupName, allowExternalPrincipals: false, principals: [props.networkFirewallEngine.firewallAccount], resourceArns: [this.ruleGroupArn], }); } addRule(props) { let priority = 1; if (props.priority) { priority = props.priority; } let rulesDatabase = this.rulesDatabase; // create a new rule, and insert it in the table. const ruleToAdd = new FQDNStatefulRule(this, props.name + 'FQDNRule', { name: props.name, action: props.action, protocol: props.protocol, source: props.source, destination: props.destination, srcPort: props.srcPort, destPort: props.destPort, direction: props.direction, fqdn: props.fqdn, priority: priority, rulesDatabase: rulesDatabase, }); this.ruleuuidlist.push(ruleToAdd.uuid); // add prefixlists to the RulereferenceSets ruleToAdd.prefixListSet.forEach((plset) => { // need to check if adding this to to the ruleprefix list is bad. const checklist = this.ruleReferenceSets; checklist.push(plset); const errorCheck = checkForDuplicateNamedPL(checklist); // this will raise an error if there is one if (errorCheck.length > this.ruleReferenceSets.length) { // we had a new unique one, so we can add it this.ruleReferenceSets.push(plset); } }); // add TagGroups: TODO. THis needs some validation. ruleToAdd.resourceGroupSets.forEach((resourceGroup) => { this.ruleReferenceSets.push(resourceGroup); }); } } exports.SuricataRuleGroup = SuricataRuleGroup; function checkForDuplicateNamedPL(prefixlistSet) { const unique = [...new Set(prefixlistSet.map(item => item.name))]; unique.forEach((setname) => { const filtered = prefixlistSet.filter((obj) => { return obj.name === setname; }); if (filtered.length > 1) { const uniqueArn = [...new Set(filtered.map(item => item.arn))]; if (uniqueArn.length > 1) { throw Error(`Reference Set names must be unique. Set name ${setname} has been used more than once`); } } }); return [...new Map(prefixlistSet.map((item) => [item.arn, item])).values()]; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3VyaWNhdGFSdWxlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL253ZmlyZXdhbGwvc3VyaWNhdGFSdWxlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLDZCQUE2QjtBQUM3Qiw2Q0FPcUI7QUFDckIsbUNBQW1DO0FBQ25DLHlDQUF5QztBQUN6QyxxREFBdUY7QUFFdkYsSUFBWSxjQWlCWDtBQWpCRCxXQUFZLGNBQWM7SUFDeEI7O09BRUc7SUFDSCwrQkFBYSxDQUFBO0lBQ2I7O09BRUc7SUFDSCwrQkFBYSxDQUFBO0lBQ2I7O09BRUc7SUFDSCxtQ0FBaUIsQ0FBQTtJQUNqQjs7T0FFRztJQUNILGlDQUFlLENBQUE7QUFDakIsQ0FBQyxFQWpCVyxjQUFjLEdBQWQsc0JBQWMsS0FBZCxzQkFBYyxRQWlCekI7QUFFRCxJQUFZLFVBT1g7QUFQRCxXQUFZLFVBQVU7SUFDcEIseUJBQVcsQ0FBQTtJQUNYLHlCQUFXLENBQUE7SUFDWCwyQkFBYSxDQUFBO0lBQ2IsdUJBQVMsQ0FBQTtJQUNULDJCQUFhLENBQUE7SUFDYix5QkFBVyxDQUFBO0FBQ2IsQ0FBQyxFQVBXLFVBQVUsR0FBVixrQkFBVSxLQUFWLGtCQUFVLFFBT3JCO0FBRUQsSUFBWSxTQVNYO0FBVEQsV0FBWSxTQUFTO0lBQ25COztPQUVHO0lBQ0gsNEJBQWUsQ0FBQTtJQUNmOztPQUVHO0lBQ0gsd0JBQVcsQ0FBQTtBQUNiLENBQUMsRUFUVyxTQUFTLEdBQVQsaUJBQVMsS0FBVCxpQkFBUyxRQVNwQjtBQW9DRCxNQUFhLGdCQUFpQixTQUFRLFVBQVUsQ0FBQyxTQUFTO0lBT3hELFlBQVksS0FBMkIsRUFBRSxFQUFVLEVBQUUsS0FBNEI7UUFDL0UsS0FBSyxDQUFFLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQztRQUxiLGtCQUFhLEdBQW9CLEVBQUUsQ0FBQztRQUNwQyxzQkFBaUIsR0FBaUMsRUFBRSxDQUFDO1FBTTFELElBQUksQ0FBQyxDQUFDLENBQUMsVUFB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aCc7XG5pbXBvcnQge1xuICBjdXN0b21fcmVzb3VyY2VzIGFzIGNyLFxuICBhd3NfbGFtYmRhLFxuICBhd3NfaWFtIGFzIGlhbSxcbiAgYXdzX2VjMiBhcyBlYzIsXG4gIGF3c19yYW0gYXMgcmFtLFxufVxuICBmcm9tICdhd3MtY2RrLWxpYic7XG5pbXBvcnQgKiBhcyBjZGsgZnJvbSAnYXdzLWNkay1saWInO1xuaW1wb3J0ICogYXMgY29uc3RydWN0cyBmcm9tICdjb25zdHJ1Y3RzJztcbmltcG9ydCB7IER5bmFtaWNUYWdSZXNvdXJjZUdyb3VwLCBEeW5hbWljVGFnUmVzb3VyY2VHcm91cFNldCB9IGZyb20gJy4vcmVzb3VyY2VHcm91cHMnO1xuaW1wb3J0IHsgU3RhdGVmdWxSdWxlRGF0YWJhc2UgfSBmcm9tICcuL3N0YXRlZnVsZGF0YWJhc2UnO1xuZXhwb3J0IGVudW0gU3RhdGVmdWxBY3Rpb24ge1xuICAvKipcbiAgICogVHJhZmZpYyB3aWxsIHBhc3NcbiAgICovXG4gIFBBU1MgPSAncGFzcycsXG4gIC8qKlxuICAgKiBUcmFmZmljIHdpbGwgYmUgZHJvcGVkIHNpbGVudGx5LiBOb3RlLCBXaGVuIHdpbGwgY2F1c2UgYSB0aW1lb3V0IGZvciBUQ1AsIENvbnNpZGVyIHVzaW5nIFJFSkVDVFxuICAgKi9cbiAgRFJPUCA9ICdkcm9wJyxcbiAgLyoqXG4gICAqIFRyYWZmaWMgd2lsbCBiZSBkcm9wcGVkLCBhbmQgYSBUQ1AgcmVzZXQgc2VudCB0byB0aGUgc291cmNlXG4gICAqL1xuICBSRUpFQ1QgPSAncmVqZWN0JyxcbiAgLyoqXG4gICAqIFJhaXNlcyBhbiBhbGVydCBhY2NvcmRpbmcgdG8gdGhlIGZpcmV3YWxscyBsb2dnaW5nL2FsZXJ0XG4gICAqL1xuICBBTEVSVCA9ICdhbGVydCcsXG59XG5cbmV4cG9ydCBlbnVtIEZXUHJvdG9jb2wge1xuICBUQ1AgPSAndGNwJyxcbiAgVVBEID0gJ3VkcCcsXG4gIElDTVAgPSAnaWNtcCcsXG4gIElQID0gJ2lwJyxcbiAgSFRUUCA9ICdodHRwJyxcbiAgVExTID0gJ3Rscydcbn1cblxuZXhwb3J0IGVudW0gRGlyZWN0aW9uIHtcbiAgLyoqXG4gICAqIFRyYWZmaWMgYWxsb3dlZCBmcm9tIFNyYyB0byBkZXN0aW5hdGlvbiBvbmx5XG4gICAqL1xuICBPVVRCT1VORCA9ICctPicsXG4gIC8qKlxuICAgKiBUcmFmZmljIGFsbG93ZWQgaW4gYm90aCBkaXJlY3Rpb25zXG4gICAqL1xuICBCT1RIID0gJzw+J1xufVxuXG5leHBvcnQgdHlwZSBTcmNEc3RBZGRyID0gc3RyaW5nIHwgUHJlZml4TGlzdCB8IER5bmFtaWNUYWdSZXNvdXJjZUdyb3VwO1xuZXhwb3J0IHR5cGUgU3JjRHN0UG9ydCA9IHN0cmluZztcblxuXG5leHBvcnQgaW50ZXJmYWNlIFN1cmljYXRhUnVsZVByb3Bze1xuICByZWFkb25seSBuYW1lOiBzdHJpbmc7XG4gIHJlYWRvbmx5IGFjdGlvbjogU3RhdGVmdWxBY3Rpb247XG4gIHJlYWRvbmx5IHByb3RvY29sOiBGV1Byb3RvY29sO1xuICByZWFkb25seSBzb3VyY2U6IFNyY0RzdEFkZHI7XG4gIHJlYWRvbmx5IGRlc3RpbmF0aW9uOiBTcmNEc3RBZGRyO1xuICByZWFkb25seSBzcmNQb3J0OiBTcmNEc3RQb3J0O1xuICByZWFkb25seSBkZXN0UG9ydDogU3JjRHN0UG9ydDtcbiAgcmVhZG9ubHkgZGlyZWN0aW9uOiBEaXJlY3Rpb247XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgRlFETlN0YXRlZnVsUnVsZVByb3BzIGV4dGVuZHMgU3VyaWNhdGFSdWxlUHJvcHMge1xuICByZWFkb25seSBmcWRuOiBzdHJpbmc7XG4gIHJlYWRvbmx5IHByaW9yaXR5PzogbnVtYmVyIHwgdW5kZWZpbmVkO1xuICByZWFkb25seSBydWxlc0RhdGFiYXNlPzogU3RhdGVmdWxSdWxlRGF0YWJhc2UgfCB1bmRlZmluZWQ7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUHJlZml4TGlzdFNldEludGVyZmFjZSB7XG4gIHJlYWRvbmx5IGFybjogc3RyaW5nO1xuICByZWFkb25seSBuYW1lOiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUmVmZXJlbmNlU2V0IHtcbiAgcmVhZG9ubHkgYXJuOiBzdHJpbmc7XG4gIHJlYWRvbmx5IG5hbWU6IHN0cmluZztcbn1cblxudHlwZSBQcmVmaXhMaXN0U2V0ID0gUHJlZml4TGlzdFNldEludGVyZmFjZVxuXG5cbmV4cG9ydCBjbGFzcyBGUUROU3RhdGVmdWxSdWxlIGV4dGVuZHMgY29uc3RydWN0cy5Db25zdHJ1Y3Qge1xuXG4gIHB1YmxpYyB1dWlkOiBzdHJpbmc7XG4gIHB1YmxpYyBwcmVmaXhMaXN0U2V0OiBQcmVmaXhMaXN0U2V0W10gPSBbXTtcbiAgcHVibGljIHJlc291cmNlR3JvdXBTZXRzOiBEeW5hbWljVGFnUmVzb3VyY2VHcm91cFNldFtdID0gW107XG5cblxuICBjb25zdHJ1Y3RvcihzY29wZTogY29uc3RydWN0cy5Db25zdHJ1Y3QsIGlkOiBzdHJpbmcsIHByb3BzOiBGUUROU3RhdGVmdWxSdWxlUHJvcHMpIHtcbiAgICBzdXBlciggc2NvcGUsIGlkKTtcblxuICAgIGlmICghKFtGV1Byb3RvY29sLkhUVFAsIEZXUHJvdG9jb2wuVExTXS5pbmNsdWRlcyhwcm9wcy5wcm90b2NvbCkpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoZSBwcm90b2NvbCBmb3IgRlFETiBSdWxlcyBtdXN0IGJlIEhUVFAgb3IgVExTJyk7XG4gICAgfVxuXG4gICAgbGV0IHByaW9yaXR5ID0gMTtcbiAgICBpZiAocHJvcHMucHJpb3JpdHkpIHtcbiAgICAgIHByaW9yaXR5ID0gcHJvcHMucHJpb3JpdHk7XG4gICAgfVxuICAgIGxldCBtYXRjaGluZ01lc3NhZ2UgPSAnbWF0Y2hpbmcgZGVueWVkIEZRRE5zJztcbiAgICBpZiAocHJvcHMuYWN0aW9uID09IFN0YXRlZnVsQWN0aW9uLlBBU1MpIHtcbiAgICAgIG1hdGNoaW5nTWVzc2FnZSA9ICdtYXRjaGluZyBhbGxvd2VkIEZRRE5zJztcbiAgICB9XG5cbiAgICB2YXIgb3B0aW9uczogc3RyaW5nID0gJyc7XG4gICAgaWYgKHByb3BzLnByb3RvY29sID09PSBGV1Byb3RvY29sLkhUVFApIHtcbiAgICAgIG9wdGlvbnMgPSBgKGh0dHAuaG9zdDsgY29udGVudDpcIiR7cHJvcHMuZnFkbn1cIjsgc3RhcnRzd2l0aDsgZW5kc3dpdGg7IG1zZzpcIiR7bWF0Y2hpbmdNZXNzYWdlfVwiOyBwcmlvcml0eToke3ByaW9yaXR5fTsgZmxvdzp0b19zZXJ2ZXIsIGVzdGFibGlzaGVkO2A7IC8vc2lkOiR7Z2V0U2lkKCl9OyByZXY6MTspYFxuICAgIH1cblxuICAgIGlmIChwcm9wcy5wcm90b2NvbCA9PT0gRldQcm90b2NvbC5UTFMpIHtcbiAgICAgIG9wdGlvbnMgPSBgKHRscy5zbmk7IGNvbnRlbnQ6XCIke3Byb3BzLmZxZG59XCI7IHN0YXJ0c3dpdGg7IGVuZHN3aXRoOyBtc2c6XCIke21hdGNoaW5nTWVzc2FnZX1cIjsgcHJpb3JpdHk6JHtwcmlvcml0eX07IGZsb3c6dG9fc2VydmVyLCBlc3RhYmxpc2hlZDtgOyAvL3NpZDoke2dldFNpZCgpfTsgcmV2OjE7KWBcbiAgICB9XG5cbiAgICBsZXQgc291cmNlID0gJyc7XG5cbiAgICBpZiAocHJvcHMuc291cmNlIGluc3RhbmNlb2YgUHJlZml4TGlzdCkge1xuICAgICAgc291cmNlID0gJ0AnICsgcHJvcHMuc291cmNlLnByZWZpeGxpc3QucHJlZml4TGlzdE5hbWU7XG4gICAgICB0aGlzLnByZWZpeExpc3RTZXQucHVzaChwcm9wcy5zb3VyY2UucHJlZml4TGlzdFNldCk7XG4gICAgfSBlbHNlIGlmIChwcm9wcy5zb3VyY2UgaW5zdGFuY2VvZiBEeW5hbWljVGFnUmVzb3VyY2VHcm91cCkge1xuICAgICAgc291cmNlID0gJ0AnICsgcHJvcHMuc291cmNlLm5hbWU7XG4gICAgICB0aGlzLnJlc291cmNlR3JvdXBTZXRzLnB1c2goeyBuYW1lOiBwcm9wcy5zb3VyY2UubmFtZSwgYXJuOiBwcm9wcy5zb3VyY2UuZ3JvdXBBcm4gfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHNvdXJjZSA9IHByb3BzLnNvdXJjZSBhcyBzdHJpbmc7XG4gICAgfVxuXG4gICAgbGV0IGRlc3RpbmF0aW9uID0gJyc7XG4gICAgaWYgKHByb3BzLmRlc3RpbmF0aW9uIGluc3RhbmNlb2YgUHJlZml4TGlzdCkge1xuICAgICAgZGVzdGluYXRpb24gPSAnQCcgKyBwcm9wcy5kZXN0aW5hdGlvbi5wcmVmaXhsaXN0LnByZWZpeExpc3ROYW1lO1xuICAgICAgdGhpcy5wcmVmaXhMaXN0U2V0LnB1c2gocHJvcHMuZGVzdGluYXRpb24ucHJlZml4TGlzdFNldCk7XG4gICAgfSBlbHNlIGlmIChwcm9wcy5kZXN0aW5hdGlvbiBpbnN0YW5jZW9mIER5bmFtaWNUYWdSZXNvdXJjZUdyb3VwKSB7XG4gICAgICBzb3VyY2UgPSAnQCcgKyBwcm9wcy5kZXN0aW5hdGlvbjtcbiAgICAgIHRoaXMucmVzb3VyY2VHcm91cFNldHMucHVzaCh7IG5hbWU6IHByb3BzLmRlc3RpbmF0aW9uLm5hbWUsIGFybjogcHJvcHMuZGVzdGluYXRpb24uZ3JvdXBBcm4gfSk7XG5cbiAgICB9IGVsc2Uge1xuICAgICAgZGVzdGluYXRpb24gPSBwcm9wcy5kZXN0aW5hdGlvbiBhcyBzdHJpbmc7XG4gICAgfVxuXG4gICAgdmFyIHJ1bGUgPSAnJy5jb25jYXQoXG4gICAgICBwcm9wcy5hY3Rpb24sICcgJywgLy9kcm9wXG4gICAgICBwcm9wcy5wcm90b2NvbCwgJyAnLCAvLyBwcm90b2NvbFxuICAgICAgc291cmNlLCAnICcsIC8vIEBleGFtcGxlXG4gICAgICBwcm9wcy5zcmNQb3J0LCAnICcsIC8vIGFueVxuICAgICAgcHJvcHMuZGlyZWN0aW9uLCAnICcsIC8vIC0+XG4gICAgICBkZXN0aW5hdGlvbiwgJyAnLCAvLyAkRVhURVJOQUxfTkVUXG4gICAgICBwcm9wcy5kZXN0UG9ydCwgJyAnLCAvLyBhbnlcbiAgICAgIG9wdGlvbnMsXG4gICAgKTtcblxuICAgIGNvbnN0IHN1cmljYXRhUnVsZSA9IG5ldyBjZGsuQ3VzdG9tUmVzb3VyY2UodGhpcywgYCR7aWR9Y3VzdG9tcmVzb3VyY2VgLCB7XG4gICAgICBzZXJ2aWNlVG9rZW46IHByb3BzLnJ1bGVzRGF0YWJhc2U/LmNydWRTZXJ2aWNlVG9rZW4gYXMgc3RyaW5nLFxuICAgICAgcHJvcGVydGllczoge1xuICAgICAgICBSdWxlOiBydWxlLFxuICAgICAgfSxcbiAgICB9KTtcblxuICAgIHRoaXMudXVpZCA9IHN1cmljYXRhUnVsZS5nZXRBdHRTdHJpbmcoJ1VVSUQnKTtcblxuXG4gIH1cbn1cblxuXG5leHBvcnQgZW51bSBJUEFkZHJlc3NGYW1pbHkge1xuICBJUFY0ID0gJ0lQdjQnLFxuICBJUFY2ID0gJ0lQdjYnXG59XG5cblxuZXhwb3J0IGludGVyZmFjZSBQcmVmaXhMaXN0UHJvcHMge1xuICByZWFkb25seSBhZGRyZXNzRmFtaWx5OiBJUEFkZHJlc3NGYW1pbHk7XG4gIHJlYWRvbmx5IHByZWZpeExpc3ROYW1lOiBzdHJpbmc7XG4gIHJlYWRvbmx5IG1heEVudHJpZXM6IG51bWJlcjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBQcmVmaXhMaXN0RW50cnkge1xuICByZWFkb25seSBjaWRyOiBzdHJpbmc7XG4gIHJlYWRvbmx5IGRlc2NyaXB0aW9uOiBzdHJpbmc7XG59XG5cblxuZXhwb3J0IGNsYXNzIFByZWZpeExpc3QgZXh0ZW5kcyBjb25zdHJ1Y3RzLkNvbnN0cnVjdCB7XG5cbiAgcHVibGljIHJlYWRvbmx5IHByZWZpeGxpc3Q6IGVjMi5DZm5QcmVmaXhMaXN0O1xuICBwdWJsaWMgcmVhZG9ubHkgcHJlZml4bGlzdEFybjogc3RyaW5nO1xuICBwdWJsaWMgcmVhZG9ubHkgcHJlZml4TGlzdFNldDogUHJlZml4TGlzdFNldDtcblxuICBwcml2YXRlIGVudHJpZXM6IFByZWZpeExpc3RFbnRyeVtdID0gW107XG5cbiAgY29uc3RydWN0b3Ioc2NvcGU6IGNvbnN0cnVjdHMuQ29uc3RydWN0LCBpZDogc3RyaW5nLCBwcm9wczogUHJlZml4TGlzdFByb3BzKSB7XG4gICAgc3VwZXIoIHNjb3BlLCBpZCk7XG5cbiAgICB0aGlzLnByZWZpeGxpc3QgPSBuZXcgZWMyLkNmblByZWZpeExpc3QodGhpcywgYHByZWZpeC1saXN0JHtpZH1gLCB7XG4gICAgICBhZGRyZXNzRmFtaWx5OiBwcm9wcy5hZGRyZXNzRmFtaWx5LFxuICAgICAgcHJlZml4TGlzdE5hbWU6IHByb3BzLnByZWZpeExpc3ROYW1lLFxuICAgICAgbWF4RW50cmllczogcHJvcHMubWF4RW50cmllcyxcbiAgICAgIGVudHJpZXM6IHRoaXMuZW50cmllcyxcbiAgICB9KTtcblxuICAgIHRoaXMucHJlZml4bGlzdEFybiA9IHRoaXMucHJlZml4bGlzdC5hdHRyQXJuO1xuICAgIHRoaXMucHJlZml4TGlzdFNldCA9IHsgYXJuOiB0aGlzLnByZWZpeGxpc3QuYXR0ckFybiwgbmFtZTogcHJvcHMucHJlZml4TGlzdE5hbWUgfTtcblxuICB9XG5cbiAgcHVibGljIGFkZEVDMkluc3RhbmNlKHByb3BzOiBlYzIuSW5zdGFuY2UpOiB2b2lkIHtcblxuICAgIHRoaXMuZW50cmllcy5wdXNoKFxuICAgICAge1xuICAgICAgICBjaWRyOiBwcm9wcy5pbnN0YW5jZVByaXZhdGVJcCArICcvMzInLFxuICAgICAgICBkZXNjcmlwdGlvbjogcHJvcHMuaW5zdGFuY2VQcml2YXRlRG5zTmFtZSxcbiAgICAgIH0sXG4gICAgKTtcbiAgfVxufVxuXG5leHBvcnQgaW50ZXJmYWNlIE5XRldSdWxlc0VuZ2luZSB7XG4gIHJlYWRvbmx5IGZpcmV3YWxsQWNjb3VudDogc3RyaW5nO1xuICByZWFkb25seSBydWxlc0RhdGFiYXNlOiBTdGF0ZWZ1bFJ1bGVEYXRhYmFzZTtcbn1cblxuXG5leHBvcnQgaW50ZXJmYWNlIFN1cmljYXRhUnVsZUdyb3VwUHJvcHN7XG4gIHJlYWRvbmx5IHJ1bGVHcm91cE5hbWU6IHN0cmluZztcbiAgcmVhZG9ubHkgZGVzY3JpcHRpb24/OiBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gIHJlYWRvbmx5IHN1cmljYXRhUnVsZXM/OiBGUUROU3RhdGVmdWxSdWxlW107IC8vIGFkZCBvaHRlciBraW5kcyBvZiBydWxlcyBpbiBoZXJlLlxuICByZWFkb25seSBjYXBhY2l0eTogbnVtYmVyO1xuICByZWFkb25seSBuZXR3b3JrRmlyZXdhbGxFbmdpbmU6IE5XRldSdWxlc0VuZ2luZTtcbiAgLy9yZWFkb25seSBydWxlc0RhdGFiYXNlOiBTdGF0ZWZ1bFJ1bGVEYXRhYmFzZTtcbn1cblxuZXhwb3J0IGNsYXNzIFN1cmljYXRhUnVsZUdyb3VwIGV4dGVuZHMgY29uc3RydWN0cy5Db25zdHJ1Y3Qge1xuXG4gIHB1YmxpYyBydWxlR3JvdXBBcm46IHN0cmluZyA9ICcnO1xuXG4gIHByaXZhdGUgcnVsZVJlZmVyZW5jZVNldHM6IFJlZmVyZW5jZVNldFtdID1bXTtcbiAgcHJpdmF0ZSBydWxldXVpZGxpc3Q6IHN0cmluZ1tdID0gW107XG4gIHByaXZhdGUgcnVsZXNEYXRhYmFzZTogU3RhdGVmdWxSdWxlRGF0YWJhc2U7XG4gIHByaXZhdGUgY3JMYW1iZGE6IGF3c19sYW1iZGEuRnVuY3Rpb247XG5cbiAgY29uc3RydWN0b3Ioc2NvcGU6IGNvbnN0cnVjdHMuQ29uc3RydWN0LCBpZDogc3RyaW5nLCBwcm9wczogU3VyaWNhdGFSdWxlR3JvdXBQcm9wcykge1xuICAgIHN1cGVyKCBzY29wZSwgaWQpO1xuXG4gICAgdGhpcy5ydWxlc0RhdGFiYXNlID0gcHJvcHMubmV0d29ya0ZpcmV3YWxsRW5naW5lLnJ1bGVzRGF0YWJhc2U7XG5cbiAgICBjb25zdCBzdXJpY2F0YVJ1bGVHcm91cExhbWJkYSA9IG5ldyBhd3NfbGFtYmRhLkZ1bmN0aW9uKHRoaXMsICdmcWRuTGFtYmRhJywge1xuICAgICAgdGltZW91dDogY2RrLkR1cmF0aW9uLnNlY29uZHMoMzAwKSxcbiAgICAgIHJ1bnRpbWU6IGF3c19sYW1iZGEuUnVudGltZS5QWVRIT05fM185LFxuICAgICAgaGFuZGxlcjogJ3N1cmljYXRhX3J1bGUub25fZXZlbnQnLFxuICAgICAgY29kZTogYXdzX2xhbWJkYS5Db2RlLmZyb21Bc3NldChwYXRoLmpvaW4oX19kaXJuYW1lLCAnLi4vLi4vbGFtYmRhL2ZpcmV3YWxsJyksIHtcbiAgICAgICAgYnVuZGxpbmc6IHtcbiAgICAgICAgICBpbWFnZTogYXdzX2xhbWJkYS5SdW50aW1lLlBZVEhPTl8zXzkuYnVuZGxpbmdJbWFnZSxcbiAgICAgICAgICBjb21tYW5kOiBbXG4gICAgICAgICAgICAnYmFzaCcsICctYycsXG4gICAgICAgICAgICAncGlwIGluc3RhbGwgLXIgcmVxdWlyZW1lbnRzLnR4dCAtdCAvYXNzZXQtb3V0cHV0ICYmIGNwIC1hdSAuIC9hc3NldC1vdXRwdXQnLFxuICAgICAgICAgIF0sXG4gICAgICAgIH0sXG4gICAgICB9KSxcbiAgICAgIGVudmlyb25tZW50OiB7XG4gICAgICAgIFRhYmxlTmFtZTogcHJvcHMubmV0d29ya0ZpcmV3YWxsRW5naW5lLnJ1bGVzRGF0YWJhc2UucG9saWN5VGFibGUudGFibGVOYW1lLFxuICAgICAgfSxcbiAgICB9KTtcblxuICAgIHRoaXMuY3JMYW1iZGEgPSBzdXJpY2F0YVJ1bGVHcm91cExhbWJkYTtcblxuICAgIHN1cmljYXRhUnVsZUdyb3VwTGFtYmRhLmFkZFRvUm9sZVBvbGljeShcbiAgICAgIG5ldyBpYW0uUG9saWN5U3RhdGVtZW50KHtcbiAgICAgICAgZWZmZWN0OiBpYW0uRWZmZWN0LkFMTE9XLFxuICAgICAgICByZXNvdXJjZXM6IFsnKiddLFxuICAgICAgICBhY3Rpb25zOiBbXG4gICAgICAgICAgJ25ldHdvcmstZmlyZXdhbGw6RGVzY3JpYmVSdWxlR3JvdXAnLFxuICAgICAgICAgICduZXR3b3JrLWZpcmV3YWxsOkRlbGV0ZVJ1bGVHcm91cCcsXG4gICAgICAgICAgJ25ldHdvcmstZmlyZXdhbGw6Q3JlYXRlUnVsZUdyb3VwJyxcbiAgICAgICAgICAnbmV0d29yay1maXJld2FsbDpVcGRhdGVSdWxlR3JvdXAnLFxuICAgICAgICAgICdpYW06Q3JlYXRlU2VydmljZUxpbmtlZFJvbGUnLFxuICAgICAgICAgICdlYzI6R2V0TWFuYWdlZFByZWZpeExpc3RFbnRyaWVzJyxcbiAgICAgICAgICAncmVzb3VyY2UtZ3JvdXBzOkdldConLFxuICAgICAgICAgICdyZXNvdXJjZS1ncm91cHM6TGlzdConLFxuICAgICAgICBdLFxuICAgICAgfSksXG4gICAgKTtcblxuXG4gICAgcHJvcHMubmV0d29ya0ZpcmV3YWxsRW5naW5lLnJ1bGVzRGF0YWJhc2UucG9saWN5VGFibGUuZ3JhbnRSZWFkRGF0YShzdXJpY2F0YVJ1bGVHcm91cExhbWJkYSk7XG5cbiAgICAvLyB0aGlzIGlzIG5vdCBwZXJtaXR0ZWQgYnkgZGVmYXVsdCBpbiAncmVhZD8nXG4gICAgc3VyaWNhdGFSdWxlR3JvdXBMYW1iZGEuYWRkVG9Sb2xlUG9saWN5KFxuICAgICAgbmV3IGlhbS5Qb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgICBlZmZlY3Q6IGlhbS5FZmZlY3QuQUxMT1csXG4gICAgICAgIHJlc291cmNlczogW3Byb3BzLm5ldHdvcmtGaXJld2FsbEVuZ2luZS5ydWxlc0RhdGFiYXNlLnBvbGljeVRhYmxlLnRhYmxlQXJuXSxcbiAgICAgICAgYWN0aW9uczogW1xuICAgICAgICAgICdkeW5hbW9kYjpQYXJ0aVFMU2VsZWN0JyxcbiAgICAgICAgXSxcbiAgICAgIH0pLFxuICAgICk7XG5cblxuICAgIGNvbnN0IHN1cmljYXRhUnVsZUNyID0gbmV3IGNkay5DdXN0b21SZXNvdXJjZSh0aGlzLCBgJHtwcm9wcy5ydWxlR3JvdXBOYW1lfWN1c3RvbXJlc291cmNlYCwge1xuICAgICAgc2VydmljZVRva2VuOiBuZXcgY3IuUHJvdmlkZXIodGhpcywgYCR7cHJvcHMucnVsZUdyb3VwTmFtZX1zZXJ2aWNlcHJvdmlkZXJgLCB7XG4gICAgICAgIG9uRXZlbnRIYW5kbGVyOiB0aGlzLmNyTGFtYmRhLFxuICAgICAgfSkuc2VydmljZVRva2VuLFxuICAgICAgcHJvcGVydGllczoge1xuICAgICAgICBDYXBhY2l0eTogcHJvcHMuY2FwYWNpdHksXG4gICAgICAgIFJ1bGVHcm91cE5hbWU6IHByb3BzLnJ1bGVHcm91cE5hbWUsXG4gICAgICAgIERlc2NyaXB0aW9uOiBwcm9wcy5kZXNjcmlwdGlvbixcbiAgICAgICAgUnVsZXM6IHRoaXMucnVsZXV1aWRsaXN0LFxuICAgICAgICBSZWZlcmVuY2VTZXRzOiB0aGlzLnJ1bGVSZWZlcmVuY2VTZXRzLFxuICAgICAgfSxcbiAgICB9KTtcblxuXG4gICAgdGhpcy5ydWxlR3JvdXBBcm4gPSBzdXJpY2F0YVJ1bGVDci5nZXRBdHRTdHJpbmcoJ1J1bGVHcm91cEFybicpO1xuXG4gICAgbmV3IHJhbS5DZm5SZXNvdXJjZVNoYXJlKHRoaXMsICdzaGFyZVJ1bGVHcm91cCcsIHtcbiAgICAgIG5hbWU6IHByb3BzLnJ1bGVHcm91cE5hbWUsXG4gICAgICBhbGxvd0V4dGVybmFsUHJpbmNpcGFsczogZmFsc2UsXG4gICAgICBwcmluY2lwYWxzOiBbcHJvcHMubmV0d29ya0ZpcmV3YWxsRW5naW5lLmZpcmV3YWxsQWNjb3VudF0sXG4gICAgICByZXNvdXJjZUFybnM6IFt0aGlzLnJ1bGVHcm91cEFybl0sXG4gICAgfSk7XG5cblxuICB9XG5cblxuICBwdWJsaWMgYWRkUnVsZShwcm9wczogRlFETlN0YXRlZnVsUnVsZVByb3BzKTogdm9pZCB7XG5cbiAgICBsZXQgcHJpb3JpdHkgPSAxO1xuICAgIGlmIChwcm9wcy5wcmlvcml0eSkge1xuICAgICAgcHJpb3JpdHkgPSBwcm9wcy5wcmlvcml0eTtcbiAgICB9XG5cbiAgICBsZXQgcnVsZXNEYXRhYmFzZTogU3RhdGVmdWxSdWxlRGF0YWJhc2UgPSB0aGlzLnJ1bGVzRGF0YWJhc2U7XG5cbiAgICAvLyBjcmVhdGUgYSBuZXcgcnVsZSwgYW5kIGluc2VydCBpdCBpbiB0aGUgdGFibGUuXG4gICAgY29uc3QgcnVsZVRvQWRkID0gbmV3IEZRRE5TdGF0ZWZ1bFJ1bGUodGhpcywgcHJvcHMubmFtZSArICdGUUROUnVsZScsIHtcbiAgICAgIG5hbWU6IHByb3BzLm5hbWUsXG4gICAgICBhY3Rpb246IHByb3BzLmFjdGlvbixcbiAgICAgIHByb3RvY29sOiBwcm9wcy5wcm90b2NvbCxcbiAgICAgIHNvdXJjZTogcHJvcHMuc291cmNlLFxuICAgICAgZGVzdGluYXRpb246IHByb3BzLmRlc3RpbmF0aW9uLFxuICAgICAgc3JjUG9ydDogcHJvcHMuc3JjUG9ydCxcbiAgICAgIGRlc3RQb3J0OiBwcm9wcy5kZXN0UG9ydCxcbiAgICAgIGRpcmVjdGlvbjogcHJvcHMuZGlyZWN0aW9uLFxuICAgICAgZnFkbjogcHJvcHMuZnFkbixcbiAgICAgIHByaW9yaXR5OiBwcmlvcml0eSxcbiAgICAgIHJ1bGVzRGF0YWJhc2U6IHJ1bGVzRGF0YWJhc2UsXG5cbiAgICB9KTtcblxuXG4gICAgdGhpcy5ydWxldXVpZGxpc3QucHVzaChydWxlVG9BZGQudXVpZCk7XG5cblxuICAgIC8vIGFkZCBwcmVmaXhsaXN0cyB0byB0aGUgUnVsZXJlZmVyZW5jZVNldHNcbiAgICBydWxlVG9BZGQucHJlZml4TGlzdFNldC5mb3JFYWNoKChwbHNldCkgPT4ge1xuXG4gICAgICAvLyBuZWVkIHRvIGNoZWNrIGlmIGFkZGluZyB0aGlzIHRvIHRvIHRoZSBydWxlcHJlZml4IGxpc3QgaXMgYmFkLlxuICAgICAgY29uc3QgY2hlY2tsaXN0ID0gdGhpcy5ydWxlUmVmZXJlbmNlU2V0cztcbiAgICAgIGNoZWNrbGlzdC5wdXNoKHBsc2V0KTtcbiAgICAgIGNvbnN0IGVycm9yQ2hlY2sgPSBjaGVja0ZvckR1cGxpY2F0ZU5hbWVkUEwoY2hlY2tsaXN0KTsgLy8gdGhpcyB3aWxsIHJhaXNlIGFuIGVycm9yIGlmIHRoZXJlIGlzIG9uZVxuICAgICAgaWYgKGVycm9yQ2hlY2subGVuZ3RoID4gdGhpcy5ydWxlUmVmZXJlbmNlU2V0cy5sZW5ndGgpIHsgLy8gd2UgaGFkIGEgbmV3IHVuaXF1ZSBvbmUsIHNvIHdlIGNhbiBhZGQgaXRcbiAgICAgICAgdGhpcy5ydWxlUmVmZXJlbmNlU2V0cy5wdXNoKHBsc2V0KTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIC8vIGFkZCBUYWdHcm91cHM6IFRPRE8uIFRIaXMgbmVlZHMgc29tZSB2YWxpZGF0aW9uLlxuICAgIHJ1bGVUb0FkZC5yZXNvdXJjZUdyb3VwU2V0cy5mb3JFYWNoKChyZXNvdXJjZUdyb3VwKSA9PiB7XG4gICAgICB0aGlzLnJ1bGVSZWZlcmVuY2VTZXRzLnB1c2gocmVzb3VyY2VHcm91cCk7XG4gICAgfSk7XG5cbiAgfVxufVxuXG5mdW5jdGlvbiBjaGVja0ZvckR1cGxpY2F0ZU5hbWVkUEwocHJlZml4bGlzdFNldDpQcmVmaXhMaXN0U2V0SW50ZXJmYWNlW10pOiBQcmVmaXhMaXN0U2V0SW50ZXJmYWNlW10ge1xuXG4gIGNvbnN0IHVuaXF1ZSA9IFsuLi5uZXcgU2V0KHByZWZpeGxpc3RTZXQubWFwKGl0ZW0gPT4gaXRlbS5uYW1lKSldO1xuICB1bmlxdWUuZm9yRWFjaCgoc2V0bmFtZSkgPT4ge1xuICAgIGNvbnN0IGZpbHRlcmVkID0gcHJlZml4bGlzdFNldC5maWx0ZXIoKG9iaikgPT4ge1xuICAgICAgcmV0dXJuIG9iai5uYW1lID09PSBzZXRuYW1lO1xuICAgIH0pO1xuICAgIGlmIChmaWx0ZXJlZC5sZW5ndGggPiAxKSB7XG4gICAgICBjb25zdCB1bmlxdWVBcm4gPSBbLi4ubmV3IFNldChmaWx0ZXJlZC5tYXAoaXRlbSA9PiBpdGVtLmFybikpXTtcbiAgICAgIGlmICh1bmlxdWVBcm4ubGVuZ3RoID4gMSkge1xuICAgICAgICB0aHJvdyBFcnJvcihgUmVmZXJlbmNlIFNldCBuYW1lcyBtdXN0IGJlIHVuaXF1ZS4gU2V0IG5hbWUgJHtzZXRuYW1lfSBoYXMgYmVlbiB1c2VkIG1vcmUgdGhhbiBvbmNlYCk7XG4gICAgICB9XG4gICAgfVxuICB9KTtcbiAgcmV0dXJuIFsuLi5uZXcgTWFwKHByZWZpeGxpc3RTZXQubWFwKChpdGVtKSA9PiBbaXRlbS5hcm4sIGl0ZW1dKSkudmFsdWVzKCldO1xufSJdfQ==