UNPKG

aws-cdk

Version:

CDK Toolkit, the command line tool for CDK apps

348 lines 38.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const AWS = require("aws-sdk-mock"); const security_groups_1 = require("../../lib/context-providers/security-groups"); const mock_sdk_1 = require("../util/mock-sdk"); AWS.setSDK(require.resolve('aws-sdk')); const mockSDK = new mock_sdk_1.MockSdkProvider(); afterEach(done => { AWS.restore(); done(); }); describe('security group context provider plugin', () => { test('errors when no matches are found', async () => { // GIVEN const provider = new security_groups_1.SecurityGroupContextProviderPlugin(mockSDK); AWS.mock('EC2', 'describeSecurityGroups', (_params, cb) => { cb(null, { SecurityGroups: [] }); }); // WHEN await expect(provider.getValue({ account: '1234', region: 'us-east-1', securityGroupId: 'sg-1234', })).rejects.toThrow(/No security groups found/i); }); test('looks up by security group id', async () => { // GIVEN const provider = new security_groups_1.SecurityGroupContextProviderPlugin(mockSDK); AWS.mock('EC2', 'describeSecurityGroups', (_params, cb) => { expect(_params).toEqual({ GroupIds: ['sg-1234'] }); cb(null, { SecurityGroups: [ { GroupId: 'sg-1234', IpPermissionsEgress: [ { IpProtocol: '-1', IpRanges: [ { CidrIp: '0.0.0.0/0' }, ], }, { IpProtocol: '-1', Ipv6Ranges: [ { CidrIpv6: '::/0' }, ], }, ], }, ], }); }); // WHEN const res = await provider.getValue({ account: '1234', region: 'us-east-1', securityGroupId: 'sg-1234', }); // THEN expect(res.securityGroupId).toEqual('sg-1234'); expect(res.allowAllOutbound).toEqual(true); }); test('looks up by security group id and vpc id', async () => { // GIVEN const provider = new security_groups_1.SecurityGroupContextProviderPlugin(mockSDK); AWS.mock('EC2', 'describeSecurityGroups', (_params, cb) => { expect(_params).toEqual({ GroupIds: ['sg-1234'], Filters: [ { Name: 'vpc-id', Values: ['vpc-1234567'], }, ], }); cb(null, { SecurityGroups: [ { GroupId: 'sg-1234', IpPermissionsEgress: [ { IpProtocol: '-1', IpRanges: [ { CidrIp: '0.0.0.0/0' }, ], }, { IpProtocol: '-1', Ipv6Ranges: [ { CidrIpv6: '::/0' }, ], }, ], }, ], }); }); // WHEN const res = await provider.getValue({ account: '1234', region: 'us-east-1', securityGroupId: 'sg-1234', vpcId: 'vpc-1234567', }); // THEN expect(res.securityGroupId).toEqual('sg-1234'); expect(res.allowAllOutbound).toEqual(true); }); test('looks up by security group name', async () => { // GIVEN const provider = new security_groups_1.SecurityGroupContextProviderPlugin(mockSDK); AWS.mock('EC2', 'describeSecurityGroups', (_params, cb) => { expect(_params).toEqual({ Filters: [ { Name: 'group-name', Values: ['my-security-group'], }, ], }); cb(null, { SecurityGroups: [ { GroupId: 'sg-1234', IpPermissionsEgress: [ { IpProtocol: '-1', IpRanges: [ { CidrIp: '0.0.0.0/0' }, ], }, { IpProtocol: '-1', Ipv6Ranges: [ { CidrIpv6: '::/0' }, ], }, ], }, ], }); }); // WHEN const res = await provider.getValue({ account: '1234', region: 'us-east-1', securityGroupName: 'my-security-group', }); // THEN expect(res.securityGroupId).toEqual('sg-1234'); expect(res.allowAllOutbound).toEqual(true); }); test('looks up by security group name and vpc id', async () => { // GIVEN const provider = new security_groups_1.SecurityGroupContextProviderPlugin(mockSDK); AWS.mock('EC2', 'describeSecurityGroups', (_params, cb) => { expect(_params).toEqual({ Filters: [ { Name: 'vpc-id', Values: ['vpc-1234567'], }, { Name: 'group-name', Values: ['my-security-group'], }, ], }); cb(null, { SecurityGroups: [ { GroupId: 'sg-1234', IpPermissionsEgress: [ { IpProtocol: '-1', IpRanges: [ { CidrIp: '0.0.0.0/0' }, ], }, { IpProtocol: '-1', Ipv6Ranges: [ { CidrIpv6: '::/0' }, ], }, ], }, ], }); }); // WHEN const res = await provider.getValue({ account: '1234', region: 'us-east-1', securityGroupName: 'my-security-group', vpcId: 'vpc-1234567', }); // THEN expect(res.securityGroupId).toEqual('sg-1234'); expect(res.allowAllOutbound).toEqual(true); }); test('detects non all-outbound egress', async () => { // GIVEN const provider = new security_groups_1.SecurityGroupContextProviderPlugin(mockSDK); AWS.mock('EC2', 'describeSecurityGroups', (_params, cb) => { expect(_params).toEqual({ GroupIds: ['sg-1234'] }); cb(null, { SecurityGroups: [ { GroupId: 'sg-1234', IpPermissionsEgress: [ { IpProtocol: '-1', IpRanges: [ { CidrIp: '10.0.0.0/16' }, ], }, ], }, ], }); }); // WHEN const res = await provider.getValue({ account: '1234', region: 'us-east-1', securityGroupId: 'sg-1234', }); // THEN expect(res.securityGroupId).toEqual('sg-1234'); expect(res.allowAllOutbound).toEqual(false); }); test('errors when more than one security group is found', async () => { // GIVEN const provider = new security_groups_1.SecurityGroupContextProviderPlugin(mockSDK); AWS.mock('EC2', 'describeSecurityGroups', (_params, cb) => { expect(_params).toEqual({ GroupIds: ['sg-1234'] }); cb(null, { SecurityGroups: [ { GroupId: 'sg-1234', IpPermissionsEgress: [ { IpProtocol: '-1', IpRanges: [ { CidrIp: '10.0.0.0/16' }, ], }, ], }, { GroupId: 'sg-1234', IpPermissionsEgress: [ { IpProtocol: '-1', IpRanges: [ { CidrIp: '10.0.0.0/16' }, ], }, ], }, ], }); }); // WHEN await expect(provider.getValue({ account: '1234', region: 'us-east-1', securityGroupId: 'sg-1234', })).rejects.toThrow(/\More than one security groups found matching/i); }); test('errors when securityGroupId and securityGroupName are specified both', async () => { // GIVEN const provider = new security_groups_1.SecurityGroupContextProviderPlugin(mockSDK); // WHEN await expect(provider.getValue({ account: '1234', region: 'us-east-1', securityGroupId: 'sg-1234', securityGroupName: 'my-security-group', })).rejects.toThrow(/\'securityGroupId\' and \'securityGroupName\' can not be specified both when looking up a security group/i); }); test('errors when neither securityGroupId nor securityGroupName are specified', async () => { // GIVEN const provider = new security_groups_1.SecurityGroupContextProviderPlugin(mockSDK); // WHEN await expect(provider.getValue({ account: '1234', region: 'us-east-1', })).rejects.toThrow(/\'securityGroupId\' or \'securityGroupName\' must be specified to look up a security group/i); }); test('identifies allTrafficEgress from SecurityGroup permissions', () => { expect((0, security_groups_1.hasAllTrafficEgress)({ IpPermissionsEgress: [ { IpProtocol: '-1', IpRanges: [ { CidrIp: '0.0.0.0/0' }, ], }, { IpProtocol: '-1', Ipv6Ranges: [ { CidrIpv6: '::/0' }, ], }, ], })).toBe(true); }); test('identifies allTrafficEgress from SecurityGroup permissions when combined', () => { expect((0, security_groups_1.hasAllTrafficEgress)({ IpPermissionsEgress: [ { IpProtocol: '-1', IpRanges: [ { CidrIp: '0.0.0.0/0' }, ], Ipv6Ranges: [ { CidrIpv6: '::/0' }, ], }, ], })).toBe(true); }); test('identifies lacking allTrafficEgress from SecurityGroup permissions', () => { expect((0, security_groups_1.hasAllTrafficEgress)({ IpPermissionsEgress: [ { IpProtocol: '-1', IpRanges: [ { CidrIp: '10.0.0.0/16' }, ], }, ], })).toBe(false); expect((0, security_groups_1.hasAllTrafficEgress)({ IpPermissions: [ { IpProtocol: 'TCP', IpRanges: [ { CidrIp: '0.0.0.0/0' }, ], }, ], })).toBe(false); }); }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VjdXJpdHktZ3JvdXBzLnRlc3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJzZWN1cml0eS1ncm91cHMudGVzdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUVBLG9DQUFvQztBQUNwQyxpRkFBc0g7QUFDdEgsK0NBQW1EO0FBRW5ELEdBQUcsQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDO0FBRXZDLE1BQU0sT0FBTyxHQUFHLElBQUksMEJBQWUsRUFBRSxDQUFDO0FBSXRDLFNBQVMsQ0FBQyxJQUFJLENBQUMsRUFBRTtJQUNmLEdBQUcsQ0FBQyxPQUFPLEVBQUUsQ0FBQztJQUNkLElBQUksRUFBRSxDQUFDO0FBQ1QsQ0FBQyxDQUFDLENBQUM7QUFFSCxRQUFRLENBQUMsd0NBQXdDLEVBQUUsR0FBRyxFQUFFO0lBQ3RELElBQUksQ0FBQyxrQ0FBa0MsRUFBRSxLQUFLLElBQUksRUFBRTtRQUNsRCxRQUFRO1FBQ1IsTUFBTSxRQUFRLEdBQUcsSUFBSSxvREFBa0MsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUVqRSxHQUFHLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSx3QkFBd0IsRUFBRSxDQUFDLE9BQThDLEVBQUUsRUFBcUQsRUFBRSxFQUFFO1lBQ2xKLEVBQUUsQ0FBQyxJQUFJLEVBQUUsRUFBRSxjQUFjLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQztRQUNuQyxDQUFDLENBQUMsQ0FBQztRQUVILE9BQU87UUFDUCxNQUFNLE1BQU0sQ0FDVixRQUFRLENBQUMsUUFBUSxDQUFDO1lBQ2hCLE9BQU8sRUFBRSxNQUFNO1lBQ2YsTUFBTSxFQUFFLFdBQVc7WUFDbkIsZUFBZSxFQUFFLFNBQVM7U0FDM0IsQ0FBQyxDQUNILENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQywyQkFBMkIsQ0FBQyxDQUFDO0lBQ2pELENBQUMsQ0FBQyxDQUFDO0lBRUgsSUFBSSxDQUFDLCtCQUErQixFQUFFLEtBQUss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bXBvcnQvb3JkZXIgKi9cbmltcG9ydCAqIGFzIGF3cyBmcm9tICdhd3Mtc2RrJztcbmltcG9ydCAqIGFzIEFXUyBmcm9tICdhd3Mtc2RrLW1vY2snO1xuaW1wb3J0IHsgaGFzQWxsVHJhZmZpY0VncmVzcywgU2VjdXJpdHlHcm91cENvbnRleHRQcm92aWRlclBsdWdpbiB9IGZyb20gJy4uLy4uL2xpYi9jb250ZXh0LXByb3ZpZGVycy9zZWN1cml0eS1ncm91cHMnO1xuaW1wb3J0IHsgTW9ja1Nka1Byb3ZpZGVyIH0gZnJvbSAnLi4vdXRpbC9tb2NrLXNkayc7XG5cbkFXUy5zZXRTREsocmVxdWlyZS5yZXNvbHZlKCdhd3Mtc2RrJykpO1xuXG5jb25zdCBtb2NrU0RLID0gbmV3IE1vY2tTZGtQcm92aWRlcigpO1xuXG50eXBlIEF3c0NhbGxiYWNrPFQ+ID0gKGVycjogRXJyb3IgfCBudWxsLCB2YWw6IFQpID0+IHZvaWQ7XG5cbmFmdGVyRWFjaChkb25lID0+IHtcbiAgQVdTLnJlc3RvcmUoKTtcbiAgZG9uZSgpO1xufSk7XG5cbmRlc2NyaWJlKCdzZWN1cml0eSBncm91cCBjb250ZXh0IHByb3ZpZGVyIHBsdWdpbicsICgpID0+IHtcbiAgdGVzdCgnZXJyb3JzIHdoZW4gbm8gbWF0Y2hlcyBhcmUgZm91bmQnLCBhc3luYyAoKSA9PiB7XG4gICAgLy8gR0lWRU5cbiAgICBjb25zdCBwcm92aWRlciA9IG5ldyBTZWN1cml0eUdyb3VwQ29udGV4dFByb3ZpZGVyUGx1Z2luKG1vY2tTREspO1xuXG4gICAgQVdTLm1vY2soJ0VDMicsICdkZXNjcmliZVNlY3VyaXR5R3JvdXBzJywgKF9wYXJhbXM6IGF3cy5FQzIuRGVzY3JpYmVTZWN1cml0eUdyb3Vwc1JlcXVlc3QsIGNiOiBBd3NDYWxsYmFjazxhd3MuRUMyLkRlc2NyaWJlU2VjdXJpdHlHcm91cHNSZXN1bHQ+KSA9PiB7XG4gICAgICBjYihudWxsLCB7IFNlY3VyaXR5R3JvdXBzOiBbXSB9KTtcbiAgICB9KTtcblxuICAgIC8vIFdIRU5cbiAgICBhd2FpdCBleHBlY3QoXG4gICAgICBwcm92aWRlci5nZXRWYWx1ZSh7XG4gICAgICAgIGFjY291bnQ6ICcxMjM0JyxcbiAgICAgICAgcmVnaW9uOiAndXMtZWFzdC0xJyxcbiAgICAgICAgc2VjdXJpdHlHcm91cElkOiAnc2ctMTIzNCcsXG4gICAgICB9KSxcbiAgICApLnJlamVjdHMudG9UaHJvdygvTm8gc2VjdXJpdHkgZ3JvdXBzIGZvdW5kL2kpO1xuICB9KTtcblxuICB0ZXN0KCdsb29rcyB1cCBieSBzZWN1cml0eSBncm91cCBpZCcsIGFzeW5jICgpID0+IHtcbiAgICAvLyBHSVZFTlxuICAgIGNvbnN0IHByb3ZpZGVyID0gbmV3IFNlY3VyaXR5R3JvdXBDb250ZXh0UHJvdmlkZXJQbHVnaW4obW9ja1NESyk7XG5cbiAgICBBV1MubW9jaygnRUMyJywgJ2Rlc2NyaWJlU2VjdXJpdHlHcm91cHMnLCAoX3BhcmFtczogYXdzLkVDMi5EZXNjcmliZVNlY3VyaXR5R3JvdXBzUmVxdWVzdCwgY2I6IEF3c0NhbGxiYWNrPGF3cy5FQzIuRGVzY3JpYmVTZWN1cml0eUdyb3Vwc1Jlc3VsdD4pID0+IHtcbiAgICAgIGV4cGVjdChfcGFyYW1zKS50b0VxdWFsKHsgR3JvdXBJZHM6IFsnc2ctMTIzNCddIH0pO1xuICAgICAgY2IobnVsbCwge1xuICAgICAgICBTZWN1cml0eUdyb3VwczogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIEdyb3VwSWQ6ICdzZy0xMjM0JyxcbiAgICAgICAgICAgIElwUGVybWlzc2lvbnNFZ3Jlc3M6IFtcbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIElwUHJvdG9jb2w6ICctMScsXG4gICAgICAgICAgICAgICAgSXBSYW5nZXM6IFtcbiAgICAgICAgICAgICAgICAgIHsgQ2lkcklwOiAnMC4wLjAuMC8wJyB9LFxuICAgICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBJcFByb3RvY29sOiAnLTEnLFxuICAgICAgICAgICAgICAgIElwdjZSYW5nZXM6IFtcbiAgICAgICAgICAgICAgICAgIHsgQ2lkcklwdjY6ICc6Oi8wJyB9LFxuICAgICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBdLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIC8vIFdIRU5cbiAgICBjb25zdCByZXMgPSBhd2FpdCBwcm92aWRlci5nZXRWYWx1ZSh7XG4gICAgICBhY2NvdW50OiAnMTIzNCcsXG4gICAgICByZWdpb246ICd1cy1lYXN0LTEnLFxuICAgICAgc2VjdXJpdHlHcm91cElkOiAnc2ctMTIzNCcsXG4gICAgfSk7XG5cbiAgICAvLyBUSEVOXG4gICAgZXhwZWN0KHJlcy5zZWN1cml0eUdyb3VwSWQpLnRvRXF1YWwoJ3NnLTEyMzQnKTtcbiAgICBleHBlY3QocmVzLmFsbG93QWxsT3V0Ym91bmQpLnRvRXF1YWwodHJ1ZSk7XG4gIH0pO1xuXG4gIHRlc3QoJ2xvb2tzIHVwIGJ5IHNlY3VyaXR5IGdyb3VwIGlkIGFuZCB2cGMgaWQnLCBhc3luYyAoKSA9PiB7XG4gICAgLy8gR0lWRU5cbiAgICBjb25zdCBwcm92aWRlciA9IG5ldyBTZWN1cml0eUdyb3VwQ29udGV4dFByb3ZpZGVyUGx1Z2luKG1vY2tTREspO1xuXG4gICAgQVdTLm1vY2soJ0VDMicsICdkZXNjcmliZVNlY3VyaXR5R3JvdXBzJywgKF9wYXJhbXM6IGF3cy5FQzIuRGVzY3JpYmVTZWN1cml0eUdyb3Vwc1JlcXVlc3QsIGNiOiBBd3NDYWxsYmFjazxhd3MuRUMyLkRlc2NyaWJlU2VjdXJpdHlHcm91cHNSZXN1bHQ+KSA9PiB7XG4gICAgICBleHBlY3QoX3BhcmFtcykudG9FcXVhbCh7XG4gICAgICAgIEdyb3VwSWRzOiBbJ3NnLTEyMzQnXSxcbiAgICAgICAgRmlsdGVyczogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIE5hbWU6ICd2cGMtaWQnLFxuICAgICAgICAgICAgVmFsdWVzOiBbJ3ZwYy0xMjM0NTY3J10sXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgIH0pO1xuICAgICAgY2IobnVsbCwge1xuICAgICAgICBTZWN1cml0eUdyb3VwczogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIEdyb3VwSWQ6ICdzZy0xMjM0JyxcbiAgICAgICAgICAgIElwUGVybWlzc2lvbnNFZ3Jlc3M6IFtcbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIElwUHJvdG9jb2w6ICctMScsXG4gICAgICAgICAgICAgICAgSXBSYW5nZXM6IFtcbiAgICAgICAgICAgICAgICAgIHsgQ2lkcklwOiAnMC4wLjAuMC8wJyB9LFxuICAgICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBJcFByb3RvY29sOiAnLTEnLFxuICAgICAgICAgICAgICAgIElwdjZSYW5nZXM6IFtcbiAgICAgICAgICAgICAgICAgIHsgQ2lkcklwdjY6ICc6Oi8wJyB9LFxuICAgICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBdLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIC8vIFdIRU5cbiAgICBjb25zdCByZXMgPSBhd2FpdCBwcm92aWRlci5nZXRWYWx1ZSh7XG4gICAgICBhY2NvdW50OiAnMTIzNCcsXG4gICAgICByZWdpb246ICd1cy1lYXN0LTEnLFxuICAgICAgc2VjdXJpdHlHcm91cElkOiAnc2ctMTIzNCcsXG4gICAgICB2cGNJZDogJ3ZwYy0xMjM0NTY3JyxcbiAgICB9KTtcblxuICAgIC8vIFRIRU5cbiAgICBleHBlY3QocmVzLnNlY3VyaXR5R3JvdXBJZCkudG9FcXVhbCgnc2ctMTIzNCcpO1xuICAgIGV4cGVjdChyZXMuYWxsb3dBbGxPdXRib3VuZCkudG9FcXVhbCh0cnVlKTtcbiAgfSk7XG5cbiAgdGVzdCgnbG9va3MgdXAgYnkgc2VjdXJpdHkgZ3JvdXAgbmFtZScsIGFzeW5jICgpID0+IHtcbiAgICAvLyBHSVZFTlxuICAgIGNvbnN0IHByb3ZpZGVyID0gbmV3IFNlY3VyaXR5R3JvdXBDb250ZXh0UHJvdmlkZXJQbHVnaW4obW9ja1NESyk7XG5cbiAgICBBV1MubW9jaygnRUMyJywgJ2Rlc2NyaWJlU2VjdXJpdHlHcm91cHMnLCAoX3BhcmFtczogYXdzLkVDMi5EZXNjcmliZVNlY3VyaXR5R3JvdXBzUmVxdWVzdCwgY2I6IEF3c0NhbGxiYWNrPGF3cy5FQzIuRGVzY3JpYmVTZWN1cml0eUdyb3Vwc1Jlc3VsdD4pID0+IHtcbiAgICAgIGV4cGVjdChfcGFyYW1zKS50b0VxdWFsKHtcbiAgICAgICAgRmlsdGVyczogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIE5hbWU6ICdncm91cC1uYW1lJyxcbiAgICAgICAgICAgIFZhbHVlczogWydteS1zZWN1cml0eS1ncm91cCddLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICB9KTtcbiAgICAgIGNiKG51bGwsIHtcbiAgICAgICAgU2VjdXJpdHlHcm91cHM6IFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICBHcm91cElkOiAnc2ctMTIzNCcsXG4gICAgICAgICAgICBJcFBlcm1pc3Npb25zRWdyZXNzOiBbXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBJcFByb3RvY29sOiAnLTEnLFxuICAgICAgICAgICAgICAgIElwUmFuZ2VzOiBbXG4gICAgICAgICAgICAgICAgICB7IENpZHJJcDogJzAuMC4wLjAvMCcgfSxcbiAgICAgICAgICAgICAgICBdLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgSXBQcm90b2NvbDogJy0xJyxcbiAgICAgICAgICAgICAgICBJcHY2UmFuZ2VzOiBbXG4gICAgICAgICAgICAgICAgICB7IENpZHJJcHY2OiAnOjovMCcgfSxcbiAgICAgICAgICAgICAgICBdLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgXSxcbiAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICAvLyBXSEVOXG4gICAgY29uc3QgcmVzID0gYXdhaXQgcHJvdmlkZXIuZ2V0VmFsdWUoe1xuICAgICAgYWNjb3VudDogJzEyMzQnLFxuICAgICAgcmVnaW9uOiAndXMtZWFzdC0xJyxcbiAgICAgIHNlY3VyaXR5R3JvdXBOYW1lOiAnbXktc2VjdXJpdHktZ3JvdXAnLFxuICAgIH0pO1xuXG4gICAgLy8gVEhFTlxuICAgIGV4cGVjdChyZXMuc2VjdXJpdHlHcm91cElkKS50b0VxdWFsKCdzZy0xMjM0Jyk7XG4gICAgZXhwZWN0KHJlcy5hbGxvd0FsbE91dGJvdW5kKS50b0VxdWFsKHRydWUpO1xuICB9KTtcblxuICB0ZXN0KCdsb29rcyB1cCBieSBzZWN1cml0eSBncm91cCBuYW1lIGFuZCB2cGMgaWQnLCBhc3luYyAoKSA9PiB7XG4gICAgLy8gR0lWRU5cbiAgICBjb25zdCBwcm92aWRlciA9IG5ldyBTZWN1cml0eUdyb3VwQ29udGV4dFByb3ZpZGVyUGx1Z2luKG1vY2tTREspO1xuXG4gICAgQVdTLm1vY2soJ0VDMicsICdkZXNjcmliZVNlY3VyaXR5R3JvdXBzJywgKF9wYXJhbXM6IGF3cy5FQzIuRGVzY3JpYmVTZWN1cml0eUdyb3Vwc1JlcXVlc3QsIGNiOiBBd3NDYWxsYmFjazxhd3MuRUMyLkRlc2NyaWJlU2VjdXJpdHlHcm91cHNSZXN1bHQ+KSA9PiB7XG4gICAgICBleHBlY3QoX3BhcmFtcykudG9FcXVhbCh7XG4gICAgICAgIEZpbHRlcnM6IFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICBOYW1lOiAndnBjLWlkJyxcbiAgICAgICAgICAgIFZhbHVlczogWyd2cGMtMTIzNDU2NyddLFxuICAgICAgICAgIH0sXG4gICAgICAgICAge1xuICAgICAgICAgICAgTmFtZTogJ2dyb3VwLW5hbWUnLFxuICAgICAgICAgICAgVmFsdWVzOiBbJ215LXNlY3VyaXR5LWdyb3VwJ10sXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgIH0pO1xuICAgICAgY2IobnVsbCwge1xuICAgICAgICBTZWN1cml0eUdyb3VwczogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIEdyb3VwSWQ6ICdzZy0xMjM0JyxcbiAgICAgICAgICAgIElwUGVybWlzc2lvbnNFZ3Jlc3M6IFtcbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIElwUHJvdG9jb2w6ICctMScsXG4gICAgICAgICAgICAgICAgSXBSYW5nZXM6IFtcbiAgICAgICAgICAgICAgICAgIHsgQ2lkcklwOiAnMC4wLjAuMC8wJyB9LFxuICAgICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBJcFByb3RvY29sOiAnLTEnLFxuICAgICAgICAgICAgICAgIElwdjZSYW5nZXM6IFtcbiAgICAgICAgICAgICAgICAgIHsgQ2lkcklwdjY6ICc6Oi8wJyB9LFxuICAgICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBdLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIC8vIFdIRU5cbiAgICBjb25zdCByZXMgPSBhd2FpdCBwcm92aWRlci5nZXRWYWx1ZSh7XG4gICAgICBhY2NvdW50OiAnMTIzNCcsXG4gICAgICByZWdpb246ICd1cy1lYXN0LTEnLFxuICAgICAgc2VjdXJpdHlHcm91cE5hbWU6ICdteS1zZWN1cml0eS1ncm91cCcsXG4gICAgICB2cGNJZDogJ3ZwYy0xMjM0NTY3JyxcbiAgICB9KTtcblxuICAgIC8vIFRIRU5cbiAgICBleHBlY3QocmVzLnNlY3VyaXR5R3JvdXBJZCkudG9FcXVhbCgnc2ctMTIzNCcpO1xuICAgIGV4cGVjdChyZXMuYWxsb3dBbGxPdXRib3VuZCkudG9FcXVhbCh0cnVlKTtcbiAgfSk7XG5cbiAgdGVzdCgnZGV0ZWN0cyBub24gYWxsLW91dGJvdW5kIGVncmVzcycsIGFzeW5jICgpID0+IHtcbiAgICAvLyBHSVZFTlxuICAgIGNvbnN0IHByb3ZpZGVyID0gbmV3IFNlY3VyaXR5R3JvdXBDb250ZXh0UHJvdmlkZXJQbHVnaW4obW9ja1NESyk7XG5cbiAgICBBV1MubW9jaygnRUMyJywgJ2Rlc2NyaWJlU2VjdXJpdHlHcm91cHMnLCAoX3BhcmFtczogYXdzLkVDMi5EZXNjcmliZVNlY3VyaXR5R3JvdXBzUmVxdWVzdCwgY2I6IEF3c0NhbGxiYWNrPGF3cy5FQzIuRGVzY3JpYmVTZWN1cml0eUdyb3Vwc1Jlc3VsdD4pID0+IHtcbiAgICAgIGV4cGVjdChfcGFyYW1zKS50b0VxdWFsKHsgR3JvdXBJZHM6IFsnc2ctMTIzNCddIH0pO1xuICAgICAgY2IobnVsbCwge1xuICAgICAgICBTZWN1cml0eUdyb3VwczogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIEdyb3VwSWQ6ICdzZy0xMjM0JyxcbiAgICAgICAgICAgIElwUGVybWlzc2lvbnNFZ3Jlc3M6IFtcbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIElwUHJvdG9jb2w6ICctMScsXG4gICAgICAgICAgICAgICAgSXBSYW5nZXM6IFtcbiAgICAgICAgICAgICAgICAgIHsgQ2lkcklwOiAnMTAuMC4wLjAvMTYnIH0sXG4gICAgICAgICAgICAgICAgXSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgLy8gV0hFTlxuICAgIGNvbnN0IHJlcyA9IGF3YWl0IHByb3ZpZGVyLmdldFZhbHVlKHtcbiAgICAgIGFjY291bnQ6ICcxMjM0JyxcbiAgICAgIHJlZ2lvbjogJ3VzLWVhc3QtMScsXG4gICAgICBzZWN1cml0eUdyb3VwSWQ6ICdzZy0xMjM0JyxcbiAgICB9KTtcblxuICAgIC8vIFRIRU5cbiAgICBleHBlY3QocmVzLnNlY3VyaXR5R3JvdXBJZCkudG9FcXVhbCgnc2ctMTIzNCcpO1xuICAgIGV4cGVjdChyZXMuYWxsb3dBbGxPdXRib3VuZCkudG9FcXVhbChmYWxzZSk7XG4gIH0pO1xuXG4gIHRlc3QoJ2Vycm9ycyB3aGVuIG1vcmUgdGhhbiBvbmUgc2VjdXJpdHkgZ3JvdXAgaXMgZm91bmQnLCBhc3luYyAoKSA9PiB7XG4gICAgLy8gR0lWRU5cbiAgICBjb25zdCBwcm92aWRlciA9IG5ldyBTZWN1cml0eUdyb3VwQ29udGV4dFByb3ZpZGVyUGx1Z2luKG1vY2tTREspO1xuXG4gICAgQVdTLm1vY2soJ0VDMicsICdkZXNjcmliZVNlY3VyaXR5R3JvdXBzJywgKF9wYXJhbXM6IGF3cy5FQzIuRGVzY3JpYmVTZWN1cml0eUdyb3Vwc1JlcXVlc3QsIGNiOiBBd3NDYWxsYmFjazxhd3MuRUMyLkRlc2NyaWJlU2VjdXJpdHlHcm91cHNSZXN1bHQ+KSA9PiB7XG4gICAgICBleHBlY3QoX3BhcmFtcykudG9FcXVhbCh7IEdyb3VwSWRzOiBbJ3NnLTEyMzQnXSB9KTtcbiAgICAgIGNiKG51bGwsIHtcbiAgICAgICAgU2VjdXJpdHlHcm91cHM6IFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICBHcm91cElkOiAnc2ctMTIzNCcsXG4gICAgICAgICAgICBJcFBlcm1pc3Npb25zRWdyZXNzOiBbXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBJcFByb3RvY29sOiAnLTEnLFxuICAgICAgICAgICAgICAgIElwUmFuZ2VzOiBbXG4gICAgICAgICAgICAgICAgICB7IENpZHJJcDogJzEwLjAuMC4wLzE2JyB9LFxuICAgICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBdLFxuICAgICAgICAgIH0sXG4gICAgICAgICAge1xuICAgICAgICAgICAgR3JvdXBJZDogJ3NnLTEyMzQnLFxuICAgICAgICAgICAgSXBQZXJtaXNzaW9uc0VncmVzczogW1xuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgSXBQcm90b2NvbDogJy0xJyxcbiAgICAgICAgICAgICAgICBJcFJhbmdlczogW1xuICAgICAgICAgICAgICAgICAgeyBDaWRySXA6ICcxMC4wLjAuMC8xNicgfSxcbiAgICAgICAgICAgICAgICBdLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgXSxcbiAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgfSk7XG4gICAgfSk7XG4gICAgLy8gV0hFTlxuICAgIGF3YWl0IGV4cGVjdChcbiAgICAgIHByb3ZpZGVyLmdldFZhbHVlKHtcbiAgICAgICAgYWNjb3VudDogJzEyMzQnLFxuICAgICAgICByZWdpb246ICd1cy1lYXN0LTEnLFxuICAgICAgICBzZWN1cml0eUdyb3VwSWQ6ICdzZy0xMjM0JyxcbiAgICAgIH0pLFxuICAgICkucmVqZWN0cy50b1Rocm93KC9cXE1vcmUgdGhhbiBvbmUgc2VjdXJpdHkgZ3JvdXBzIGZvdW5kIG1hdGNoaW5nL2kpO1xuICB9KTtcblxuICB0ZXN0KCdlcnJvcnMgd2hlbiBzZWN1cml0eUdyb3VwSWQgYW5kIHNlY3VyaXR5R3JvdXBOYW1lIGFyZSBzcGVjaWZpZWQgYm90aCcsIGFzeW5jICgpID0+IHtcbiAgICAvLyBHSVZFTlxuICAgIGNvbnN0IHByb3ZpZGVyID0gbmV3IFNlY3VyaXR5R3JvdXBDb250ZXh0UHJvdmlkZXJQbHVnaW4obW9ja1NESyk7XG5cbiAgICAvLyBXSEVOXG4gICAgYXdhaXQgZXhwZWN0KFxuICAgICAgcHJvdmlkZXIuZ2V0VmFsdWUoe1xuICAgICAgICBhY2NvdW50OiAnMTIzNCcsXG4gICAgICAgIHJlZ2lvbjogJ3VzLWVhc3QtMScsXG4gICAgICAgIHNlY3VyaXR5R3JvdXBJZDogJ3NnLTEyMzQnLFxuICAgICAgICBzZWN1cml0eUdyb3VwTmFtZTogJ215LXNlY3VyaXR5LWdyb3VwJyxcbiAgICAgIH0pLFxuICAgICkucmVqZWN0cy50b1Rocm93KC9cXCdzZWN1cml0eUdyb3VwSWRcXCcgYW5kIFxcJ3NlY3VyaXR5R3JvdXBOYW1lXFwnIGNhbiBub3QgYmUgc3BlY2lmaWVkIGJvdGggd2hlbiBsb29raW5nIHVwIGEgc2VjdXJpdHkgZ3JvdXAvaSk7XG4gIH0pO1xuXG4gIHRlc3QoJ2Vycm9ycyB3aGVuIG5laXRoZXIgc2VjdXJpdHlHcm91cElkIG5vciBzZWN1cml0eUdyb3VwTmFtZSBhcmUgc3BlY2lmaWVkJywgYXN5bmMgKCkgPT4ge1xuICAgIC8vIEdJVkVOXG4gICAgY29uc3QgcHJvdmlkZXIgPSBuZXcgU2VjdXJpdHlHcm91cENvbnRleHRQcm92aWRlclBsdWdpbihtb2NrU0RLKTtcblxuICAgIC8vIFdIRU5cbiAgICBhd2FpdCBleHBlY3QoXG4gICAgICBwcm92aWRlci5nZXRWYWx1ZSh7XG4gICAgICAgIGFjY291bnQ6ICcxMjM0JyxcbiAgICAgICAgcmVnaW9uOiAndXMtZWFzdC0xJyxcbiAgICAgIH0pLFxuICAgICkucmVqZWN0cy50b1Rocm93KC9cXCdzZWN1cml0eUdyb3VwSWRcXCcgb3IgXFwnc2VjdXJpdHlHcm91cE5hbWVcXCcgbXVzdCBiZSBzcGVjaWZpZWQgdG8gbG9vayB1cCBhIHNlY3VyaXR5IGdyb3VwL2kpO1xuICB9KTtcblxuICB0ZXN0KCdpZGVudGlmaWVzIGFsbFRyYWZmaWNFZ3Jlc3MgZnJvbSBTZWN1cml0eUdyb3VwIHBlcm1pc3Npb25zJywgKCkgPT4ge1xuICAgIGV4cGVjdChcbiAgICAgIGhhc0FsbFRyYWZmaWNFZ3Jlc3Moe1xuICAgICAgICBJcFBlcm1pc3Npb25zRWdyZXNzOiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgSXBQcm90b2NvbDogJy0xJyxcbiAgICAgICAgICAgIElwUmFuZ2VzOiBbXG4gICAgICAgICAgICAgIHsgQ2lkcklwOiAnMC4wLjAuMC8wJyB9LFxuICAgICAgICAgICAgXSxcbiAgICAgICAgICB9LFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIElwUHJvdG9jb2w6ICctMScsXG4gICAgICAgICAgICBJcHY2UmFuZ2VzOiBbXG4gICAgICAgICAgICAgIHsgQ2lkcklwdjY6ICc6Oi8wJyB9LFxuICAgICAgICAgICAgXSxcbiAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgfSksXG4gICAgKS50b0JlKHRydWUpO1xuICB9KTtcblxuICB0ZXN0KCdpZGVudGlmaWVzIGFsbFRyYWZmaWNFZ3Jlc3MgZnJvbSBTZWN1cml0eUdyb3VwIHBlcm1pc3Npb25zIHdoZW4gY29tYmluZWQnLCAoKSA9PiB7XG4gICAgZXhwZWN0KFxuICAgICAgaGFzQWxsVHJhZmZpY0VncmVzcyh7XG4gICAgICAgIElwUGVybWlzc2lvbnNFZ3Jlc3M6IFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICBJcFByb3RvY29sOiAnLTEnLFxuICAgICAgICAgICAgSXBSYW5nZXM6IFtcbiAgICAgICAgICAgICAgeyBDaWRySXA6ICcwLjAuMC4wLzAnIH0sXG4gICAgICAgICAgICBdLFxuICAgICAgICAgICAgSXB2NlJhbmdlczogW1xuICAgICAgICAgICAgICB7IENpZHJJcHY2OiAnOjovMCcgfSxcbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgIH0pLFxuICAgICkudG9CZSh0cnVlKTtcbiAgfSk7XG5cbiAgdGVzdCgnaWRlbnRpZmllcyBsYWNraW5nIGFsbFRyYWZmaWNFZ3Jlc3MgZnJvbSBTZWN1cml0eUdyb3VwIHBlcm1pc3Npb25zJywgKCkgPT4ge1xuICAgIGV4cGVjdChcbiAgICAgIGhhc0FsbFRyYWZmaWNFZ3Jlc3Moe1xuICAgICAgICBJcFBlcm1pc3Npb25zRWdyZXNzOiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgSXBQcm90b2NvbDogJy0xJyxcbiAgICAgICAgICAgIElwUmFuZ2VzOiBbXG4gICAgICAgICAgICAgIHsgQ2lkcklwOiAnMTAuMC4wLjAvMTYnIH0sXG4gICAgICAgICAgICBdLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICB9KSxcbiAgICApLnRvQmUoZmFsc2UpO1xuXG4gICAgZXhwZWN0KFxuICAgICAgaGFzQWxsVHJhZmZpY0VncmVzcyh7XG4gICAgICAgIElwUGVybWlzc2lvbnM6IFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICBJcFByb3RvY29sOiAnVENQJyxcbiAgICAgICAgICAgIElwUmFuZ2VzOiBbXG4gICAgICAgICAgICAgIHsgQ2lkcklwOiAnMC4wLjAuMC8wJyB9LFxuICAgICAgICAgICAgXSxcbiAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgfSksXG4gICAgKS50b0JlKGZhbHNlKTtcbiAgfSk7XG59KTtcbiJdfQ==