1 | ;
|
2 | var _a;
|
3 | Object.defineProperty(exports, "__esModule", { value: true });
|
4 | exports.VpcEndpointServiceDomainName = void 0;
|
5 | const jsiiDeprecationWarnings = require("../.warnings.jsii.js");
|
6 | const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
|
7 | const crypto = require("crypto");
|
8 | const core_1 = require("@aws-cdk/core");
|
9 | const custom_resources_1 = require("@aws-cdk/custom-resources");
|
10 | const lib_1 = require("../lib");
|
11 | // v2 - keep this import as a separate section to reduce merge conflict when forward merging with the v2 branch.
|
12 | // eslint-disable-next-line
|
13 | const core_2 = require("@aws-cdk/core");
|
14 | /**
|
15 | * A Private DNS configuration for a VPC endpoint service.
|
16 | */
|
17 | class VpcEndpointServiceDomainName extends core_2.Construct {
|
18 | // The way this class works is by using three custom resources and a TxtRecord in conjunction
|
19 | // The first custom resource tells the VPC endpoint service to use the given DNS name
|
20 | // The VPC endpoint service will then say:
|
21 | // "ok, create a TXT record using these two values to prove you own the domain"
|
22 | // The second custom resource retrieves these two values from the service
|
23 | // The TxtRecord is created from these two values
|
24 | // The third custom resource tells the VPC Endpoint Service to verify the domain ownership
|
25 | constructor(scope, id, props) {
|
26 | super(scope, id);
|
27 | try {
|
28 | jsiiDeprecationWarnings._aws_cdk_aws_route53_VpcEndpointServiceDomainNameProps(props);
|
29 | }
|
30 | catch (error) {
|
31 | if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
|
32 | Error.captureStackTrace(error, VpcEndpointServiceDomainName);
|
33 | }
|
34 | throw error;
|
35 | }
|
36 | const serviceUniqueId = core_1.Names.nodeUniqueId(props.endpointService.node);
|
37 | const serviceId = props.endpointService.vpcEndpointServiceId;
|
38 | this.domainName = props.domainName;
|
39 | // Make sure a user doesn't accidentally add multiple domains
|
40 | this.validateProps(props);
|
41 | VpcEndpointServiceDomainName.endpointServicesMap[serviceUniqueId] = this.domainName;
|
42 | VpcEndpointServiceDomainName.endpointServices.push(props.endpointService);
|
43 | // Enable Private DNS on the endpoint service and retrieve the AWS-generated configuration
|
44 | const privateDnsConfiguration = this.getPrivateDnsConfiguration(serviceUniqueId, serviceId, this.domainName);
|
45 | // Tell AWS to verify that this account owns the domain attached to the service
|
46 | this.verifyPrivateDnsConfiguration(privateDnsConfiguration, props.publicHostedZone);
|
47 | // Finally, don't do any of the above before the endpoint service is created
|
48 | this.node.addDependency(props.endpointService);
|
49 | }
|
50 | validateProps(props) {
|
51 | const serviceUniqueId = core_1.Names.nodeUniqueId(props.endpointService.node);
|
52 | if (serviceUniqueId in VpcEndpointServiceDomainName.endpointServicesMap) {
|
53 | const endpoint = VpcEndpointServiceDomainName.endpointServicesMap[serviceUniqueId];
|
54 | throw new Error(`Cannot create a VpcEndpointServiceDomainName for service ${serviceUniqueId}, another VpcEndpointServiceDomainName (${endpoint}) is already associated with it`);
|
55 | }
|
56 | }
|
57 | /**
|
58 | * Sets up Custom Resources to make AWS calls to set up Private DNS on an endpoint service,
|
59 | * returning the values to use in a TxtRecord, which AWS uses to verify domain ownership.
|
60 | */
|
61 | getPrivateDnsConfiguration(serviceUniqueId, serviceId, privateDnsName) {
|
62 | // The custom resource which tells AWS to enable Private DNS on the given service, using the given domain name
|
63 | // AWS will generate a name/value pair for use in a TxtRecord, which is used to verify domain ownership.
|
64 | const enablePrivateDnsAction = {
|
65 | service: 'EC2',
|
66 | action: 'modifyVpcEndpointServiceConfiguration',
|
67 | parameters: {
|
68 | ServiceId: serviceId,
|
69 | PrivateDnsName: privateDnsName,
|
70 | },
|
71 | physicalResourceId: custom_resources_1.PhysicalResourceId.of(serviceUniqueId),
|
72 | };
|
73 | const removePrivateDnsAction = {
|
74 | service: 'EC2',
|
75 | action: 'modifyVpcEndpointServiceConfiguration',
|
76 | parameters: {
|
77 | ServiceId: serviceId,
|
78 | RemovePrivateDnsName: true,
|
79 | },
|
80 | };
|
81 | const enable = new custom_resources_1.AwsCustomResource(this, 'EnableDns', {
|
82 | onCreate: enablePrivateDnsAction,
|
83 | onUpdate: enablePrivateDnsAction,
|
84 | onDelete: removePrivateDnsAction,
|
85 | policy: custom_resources_1.AwsCustomResourcePolicy.fromSdkCalls({
|
86 | resources: [
|
87 | core_1.Fn.join(':', [
|
88 | 'arn',
|
89 | core_1.Stack.of(this).partition,
|
90 | 'ec2',
|
91 | core_1.Stack.of(this).region,
|
92 | core_1.Stack.of(this).account,
|
93 | core_1.Fn.join('/', [
|
94 | 'vpc-endpoint-service',
|
95 | serviceId,
|
96 | ]),
|
97 | ]),
|
98 | ],
|
99 | }),
|
100 | });
|
101 | // Look up the name/value pair if the domain changes, or the service changes,
|
102 | // which would cause the values to be different. If the unique ID changes,
|
103 | // the resource may be entirely recreated, so we will need to look it up again.
|
104 | const lookup = hashcode(core_1.Names.uniqueId(this) + serviceUniqueId + privateDnsName);
|
105 | // Create the custom resource to look up the name/value pair generated by AWS
|
106 | // after the previous API call
|
107 | const retrieveNameValuePairAction = {
|
108 | service: 'EC2',
|
109 | action: 'describeVpcEndpointServiceConfigurations',
|
110 | parameters: {
|
111 | ServiceIds: [serviceId],
|
112 | },
|
113 | physicalResourceId: custom_resources_1.PhysicalResourceId.of(lookup),
|
114 | };
|
115 | const getNames = new custom_resources_1.AwsCustomResource(this, 'GetNames', {
|
116 | onCreate: retrieveNameValuePairAction,
|
117 | onUpdate: retrieveNameValuePairAction,
|
118 | // describeVpcEndpointServiceConfigurations can't take an ARN for granular permissions
|
119 | policy: custom_resources_1.AwsCustomResourcePolicy.fromSdkCalls({
|
120 | resources: custom_resources_1.AwsCustomResourcePolicy.ANY_RESOURCE,
|
121 | }),
|
122 | });
|
123 | // We only want to call and get the name/value pair after we've told AWS to enable Private DNS
|
124 | // If we call before then, we'll get an empty pair of values.
|
125 | getNames.node.addDependency(enable);
|
126 | // Get the references to the name/value pair associated with the endpoint service
|
127 | const name = getNames.getResponseField('ServiceConfigurations.0.PrivateDnsNameConfiguration.Name');
|
128 | const value = getNames.getResponseField('ServiceConfigurations.0.PrivateDnsNameConfiguration.Value');
|
129 | return { name, value, serviceId };
|
130 | }
|
131 | /**
|
132 | * Creates a Route53 entry and a Custom Resource which explicitly tells AWS to verify ownership
|
133 | * of the domain name attached to an endpoint service.
|
134 | */
|
135 | verifyPrivateDnsConfiguration(config, publicHostedZone) {
|
136 | // Create the TXT record in the provided hosted zone
|
137 | const verificationRecord = new lib_1.TxtRecord(this, 'DnsVerificationRecord', {
|
138 | recordName: config.name,
|
139 | values: [config.value],
|
140 | zone: publicHostedZone,
|
141 | });
|
142 | // Tell the endpoint service to verify the domain ownership
|
143 | const startVerificationAction = {
|
144 | service: 'EC2',
|
145 | action: 'startVpcEndpointServicePrivateDnsVerification',
|
146 | parameters: {
|
147 | ServiceId: config.serviceId,
|
148 | },
|
149 | physicalResourceId: custom_resources_1.PhysicalResourceId.of(core_1.Fn.join(':', [config.name, config.value])),
|
150 | };
|
151 | const startVerification = new custom_resources_1.AwsCustomResource(this, 'StartVerification', {
|
152 | onCreate: startVerificationAction,
|
153 | onUpdate: startVerificationAction,
|
154 | policy: custom_resources_1.AwsCustomResourcePolicy.fromSdkCalls({
|
155 | resources: [
|
156 | core_1.Fn.join(':', [
|
157 | 'arn',
|
158 | core_1.Stack.of(this).partition,
|
159 | 'ec2',
|
160 | core_1.Stack.of(this).region,
|
161 | core_1.Stack.of(this).account,
|
162 | core_1.Fn.join('/', [
|
163 | 'vpc-endpoint-service',
|
164 | config.serviceId,
|
165 | ]),
|
166 | ]),
|
167 | ],
|
168 | }),
|
169 | });
|
170 | // Only verify after the record has been created
|
171 | startVerification.node.addDependency(verificationRecord);
|
172 | }
|
173 | }
|
174 | exports.VpcEndpointServiceDomainName = VpcEndpointServiceDomainName;
|
175 | _a = JSII_RTTI_SYMBOL_1;
|
176 | VpcEndpointServiceDomainName[_a] = { fqn: "@aws-cdk/aws-route53.VpcEndpointServiceDomainName", version: "1.204.0" };
|
177 | // Track all domain names created, so someone doesn't accidentally associate two domains with a single service
|
178 | VpcEndpointServiceDomainName.endpointServices = [];
|
179 | // Track all domain names created, so someone doesn't accidentally associate two domains with a single service
|
180 | VpcEndpointServiceDomainName.endpointServicesMap = {};
|
181 | /**
|
182 | * Hash a string
|
183 | */
|
184 | function hashcode(s) {
|
185 | const hash = crypto.createHash('md5');
|
186 | hash.update(s);
|
187 | return hash.digest('hex');
|
188 | }
|
189 | ;
|
190 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidnBjLWVuZHBvaW50LXNlcnZpY2UtZG9tYWluLW5hbWUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJ2cGMtZW5kcG9pbnQtc2VydmljZS1kb21haW4tbmFtZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQSxpQ0FBaUM7QUFFakMsd0NBQWlEO0FBQ2pELGdFQUEyRztBQUUzRyxnQ0FBc0Q7QUFFdEQsZ0hBQWdIO0FBQ2hILDJCQUEyQjtBQUMzQix3Q0FBMkQ7QUE0QjNEOztHQUVHO0FBQ0gsTUFBYSw0QkFBNkIsU0FBUSxnQkFBYTtJQWE3RCw2RkFBNkY7SUFDN0YscUZBQXFGO0lBQ3JGLDBDQUEwQztJQUMxQywrRUFBK0U7SUFDL0UseUVBQXlFO0lBQ3pFLGlEQUFpRDtJQUNqRCwwRkFBMEY7SUFDMUYsWUFBWSxLQUFnQixFQUFFLEVBQVUsRUFBRSxLQUF3QztRQUNoRixLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDOzs7Ozs7K0NBckJSLDRCQUE0Qjs7OztRQXVCckMsTUFBTSxlQUFlLEdBQUcsWUFBSyxDQUFDLFlBQVksQ0FBQyxLQUFLLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3ZFLE1BQU0sU0FBUyxHQUFHLEtBQUssQ0FBQyxlQUFlLENBQUMsb0JBQW9CLENBQUM7UUFDN0QsSUFBSSxDQUFDLFVBQVUsR0FBRyxLQUFLLENBQUMsVUFBVSxDQUFDO1FBRW5DLDZEQUE2RDtRQUM3RCxJQUFJLENBQUMsYUFBYSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBRTFCLDRCQUE0QixDQUFDLG1CQUFtQixDQUFDLGVBQWUsQ0FBQyxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUM7UUFDcEYsNEJBQTRCLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxlQUFlLENBQUMsQ0FBQztRQUUxRSwwRkFBMEY7UUFDMUYsTUFBTSx1QkFBdUIsR0FBRyxJQUFJLENBQUMsMEJBQTBCLENBQUMsZUFBZSxFQUFFLFNBQVMsRUFBRSxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUM7UUFFN0csK0VBQStFO1FBQy9FLElBQUksQ0FBQyw2QkFBNkIsQ0FBQyx1QkFBdUIsRUFBRSxLQUFLLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztRQUVwRiw0RUFBNEU7UUFDNUUsSUFBSSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsS0FBSyxDQUFDLGVBQWUsQ0FBQyxDQUFDO0tBQ2hEO0lBRU8sYUFBYSxDQUFDLEtBQXdDO1FBQzVELE1BQU0sZUFBZSxHQUFHLFlBQUssQ0FBQyxZQUFZLENBQUMsS0FBSyxDQUFDLGVBQWUsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUN2RSxJQUFJLGVBQWUsSUFBSSw0QkFBNEIsQ0FBQyxtQkFBbUIsRUFBRTtZQUN2RSxNQUFNLFFBQVEsR0FBRyw0QkFBNEIsQ0FBQyxtQkFBbUIsQ0FBQyxlQUFlLENBQUMsQ0FBQztZQUNuRixNQUFNLElBQUksS0FBSyxDQUNiLDREQUE0RCxlQUFlLDJDQUEyQyxRQUFRLGlDQUFpQyxDQUFDLENBQUM7U0FDcEs7S0FDRjtJQUVEOzs7T0FHRztJQUNLLDBCQUEwQixDQUFDLGVBQXVCLEVBQUUsU0FBaUIsRUFBRSxjQUFzQjtRQUVuRyw4R0FBOEc7UUFDOUcsd0dBQXdHO1FBQ3hHLE1BQU0sc0JBQXNCLEdBQUc7WUFDN0IsT0FBTyxFQUFFLEtBQUs7WUFDZCxNQUFNLEVBQUUsdUNBQXVDO1lBQy9DLFVBQVUsRUFBRTtnQkFDVixTQUFTLEVBQUUsU0FBUztnQkFDcEIsY0FBYyxFQUFFLGNBQWM7YUFDL0I7WUFDRCxrQkFBa0IsRUFBRSxxQ0FBa0IsQ0FBQyxFQUFFLENBQUMsZUFBZSxDQUFDO1NBQzNELENBQUM7UUFDRixNQUFNLHNCQUFzQixHQUFHO1lBQzdCLE9BQU8sRUFBRSxLQUFLO1lBQ2QsTUFBTSxFQUFFLHVDQUF1QztZQUMvQyxVQUFVLEVBQUU7Z0JBQ1YsU0FBUyxFQUFFLFNBQVM7Z0JBQ3BCLG9CQUFvQixFQUFFLElBQUk7YUFDM0I7U0FDRixDQUFDO1FBQ0YsTUFBTSxNQUFNLEdBQUcsSUFBSSxvQ0FBaUIsQ0FBQyxJQUFJLEVBQUUsV0FBVyxFQUFFO1lBQ3RELFFBQVEsRUFBRSxzQkFBc0I7WUFDaEMsUUFBUSxFQUFFLHNCQUFzQjtZQUNoQyxRQUFRLEVBQUUsc0JBQXNCO1lBQ2hDLE1BQU0sRUFBRSwwQ0FBdUIsQ0FBQyxZQUFZLENBQUM7Z0JBQzNDLFNBQVMsRUFBRTtvQkFDVCxTQUFFLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRTt3QkFDWCxLQUFLO3dCQUNMLFlBQUssQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsU0FBUzt3QkFDeEIsS0FBSzt3QkFDTCxZQUFLLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLE1BQU07d0JBQ3JCLFlBQUssQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsT0FBTzt3QkFDdEIsU0FBRSxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUU7NEJBQ1gsc0JBQXNCOzRCQUN0QixTQUFTO3lCQUNWLENBQUM7cUJBQ0gsQ0FBQztpQkFDSDthQUNGLENBQUM7U0FDSCxDQUFDLENBQUM7UUFFSCw2RUFBNkU7UUFDN0UsMEVBQTBFO1FBQzFFLCtFQUErRTtRQUMvRSxNQUFNLE1BQU0sR0FBRyxRQUFRLENBQUMsWUFBSyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsR0FBRyxlQUFlLEdBQUcsY0FBYyxDQUFDLENBQUM7UUFFakYsNkVBQTZFO1FBQzdFLDhCQUE4QjtRQUM5QixNQUFNLDJCQUEyQixHQUFHO1lBQ2xDLE9BQU8sRUFBRSxLQUFLO1lBQ2QsTUFBTSxFQUFFLDBDQUEwQztZQUNsRCxVQUFVLEVBQUU7Z0JBQ1YsVUFBVSxFQUFFLENBQUMsU0FBUyxDQUFDO2FBQ3hCO1lBQ0Qsa0JBQWtCLEVBQUUscUNBQWtCLENBQUMsRUFBRSxDQUFDLE1BQU0sQ0FBQztTQUNsRCxDQUFDO1FBQ0YsTUFBTSxRQUFRLEdBQUcsSUFBSSxvQ0FBaUIsQ0FBQyxJQUFJLEVBQUUsVUFBVSxFQUFFO1lBQ3ZELFFBQVEsRUFBRSwyQkFBMkI7WUFDckMsUUFBUSxFQUFFLDJCQUEyQjtZQUNyQyxzRkFBc0Y7WUFDdEYsTUFBTSxFQUFFLDBDQUF1QixDQUFDLFlBQVksQ0FBQztnQkFDM0MsU0FBUyxFQUFFLDBDQUF1QixDQUFDLFlBQVk7YUFDaEQsQ0FBQztTQUNILENBQUMsQ0FBQztRQUVILDhGQUE4RjtRQUM5Riw2REFBNkQ7UUFDN0QsUUFBUSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsTUFBTSxDQUFDLENBQUM7UUFFcEMsaUZBQWlGO1FBQ2pGLE1BQU0sSUFBSSxHQUFHLFFBQVEsQ0FBQyxnQkFBZ0IsQ0FBQywwREFBMEQsQ0FBQyxDQUFDO1FBQ25HLE1BQU0sS0FBSyxHQUFHLFFBQVEsQ0FBQyxnQkFBZ0IsQ0FBQywyREFBMkQsQ0FBQyxDQUFDO1FBRXJHLE9BQU8sRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLFNBQVMsRUFBRSxDQUFDO0tBQ25DO0lBRUQ7OztPQUdHO0lBQ0ssNkJBQTZCLENBQUMsTUFBK0IsRUFBRSxnQkFBbUM7UUFDeEcsb0RBQW9EO1FBQ3BELE1BQU0sa0JBQWtCLEdBQUcsSUFBSSxlQUFTLENBQUMsSUFBSSxFQUFFLHVCQUF1QixFQUFFO1lBQ3RFLFVBQVUsRUFBRSxNQUFNLENBQUMsSUFBSTtZQUN2QixNQUFNLEVBQUUsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDO1lBQ3RCLElBQUksRUFBRSxnQkFBZ0I7U0FDdkIsQ0FBQyxDQUFDO1FBRUgsMkRBQTJEO1FBQzNELE1BQU0sdUJBQXVCLEdBQUc7WUFDOUIsT0FBTyxFQUFFLEtBQUs7WUFDZCxNQUFNLEVBQUUsK0NBQStDO1lBQ3ZELFVBQVUsRUFBRTtnQkFDVixTQUFTLEVBQUUsTUFBTSxDQUFDLFNBQVM7YUFDNUI7WUFDRCxrQkFBa0IsRUFBRSxxQ0FBa0IsQ0FBQyxFQUFFLENBQUMsU0FBRSxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO1NBQ3JGLENBQUM7UUFDRixNQUFNLGlCQUFpQixHQUFHLElBQUksb0NBQWlCLENBQUMsSUFBSSxFQUFFLG1CQUFtQixFQUFFO1lBQ3pFLFFBQVEsRUFBRSx1QkFBdUI7WUFDakMsUUFBUSxFQUFFLHVCQUF1QjtZQUNqQyxNQUFNLEVBQUUsMENBQXVCLENBQUMsWUFBWSxDQUFDO2dCQUMzQyxTQUFTLEVBQUU7b0JBQ1QsU0FBRSxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUU7d0JBQ1gsS0FBSzt3QkFDTCxZQUFLLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLFNBQVM7d0JBQ3hCLEtBQUs7d0JBQ0wsWUFBSyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxNQUFNO3dCQUNyQixZQUFLLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLE9BQU87d0JBQ3RCLFNBQUUsQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFOzRCQUNYLHNCQUFzQjs0QkFDdEIsTUFBTSxDQUFDLFNBQVM7eUJBQ2pCLENBQUM7cUJBQ0gsQ0FBQztpQkFDSDthQUNGLENBQUM7U0FDSCxDQUFDLENBQUM7UUFDSCxnREFBZ0Q7UUFDaEQsaUJBQWlCLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO0tBQzFEOztBQS9LSCxvRUFnTEM7OztBQTlLQyw4R0FBOEc7QUFDdEYsNkNBQWdCLEdBQTBCLEVBQUUsQ0FBQztBQUVyRSw4R0FBOEc7QUFDdEYsZ0RBQW1CLEdBQXlDLEVBQUUsQ0FBQztBQXFMekY7O0dBRUc7QUFDSCxTQUFTLFFBQVEsQ0FBQyxDQUFTO0lBQ3pCLE1BQU0sSUFBSSxHQUFHLE1BQU0sQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDdEMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNmLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztBQUM1QixDQUFDO0FBQUEsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIGNyeXB0byBmcm9tICdjcnlwdG8nO1xuaW1wb3J0IHsgSVZwY0VuZHBvaW50U2VydmljZSB9IGZyb20gJ0Bhd3MtY2RrL2F3cy1lYzInO1xuaW1wb3J0IHsgRm4sIE5hbWVzLCBTdGFjayB9IGZyb20gJ0Bhd3MtY2RrL2NvcmUnO1xuaW1wb3J0IHsgQXdzQ3VzdG9tUmVzb3VyY2UsIEF3c0N1c3RvbVJlc291cmNlUG9saWN5LCBQaHlzaWNhbFJlc291cmNlSWQgfSBmcm9tICdAYXdzLWNkay9jdXN0b20tcmVzb3VyY2VzJztcbmltcG9ydCB7IENvbnN0cnVjdCB9IGZyb20gJ2NvbnN0cnVjdHMnO1xuaW1wb3J0IHsgSVB1YmxpY0hvc3RlZFpvbmUsIFR4dFJlY29yZCB9IGZyb20gJy4uL2xpYic7XG5cbi8vIHYyIC0ga2VlcCB0aGlzIGltcG9ydCBhcyBhIHNlcGFyYXRlIHNlY3Rpb24gdG8gcmVkdWNlIG1lcmdlIGNvbmZsaWN0IHdoZW4gZm9yd2FyZCBtZXJnaW5nIHdpdGggdGhlIHYyIGJyYW5jaC5cbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZVxuaW1wb3J0IHsgQ29uc3RydWN0IGFzIENvcmVDb25zdHJ1Y3QgfSBmcm9tICdAYXdzLWNkay9jb3JlJztcblxuLyoqXG4gKiBQcm9wZXJ0aWVzIHRvIGNvbmZpZ3VyZSBhIFZQQyBFbmRwb2ludCBTZXJ2aWNlIGRvbWFpbiBuYW1lXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgVnBjRW5kcG9pbnRTZXJ2aWNlRG9tYWluTmFtZVByb3BzIHtcblxuICAvKipcbiAgICogVGhlIFZQQyBFbmRwb2ludCBTZXJ2aWNlIHRvIGNvbmZpZ3VyZSBQcml2YXRlIEROUyBmb3JcbiAgICovXG4gIHJlYWRvbmx5IGVuZHBvaW50U2VydmljZTogSVZwY0VuZHBvaW50U2VydmljZTtcblxuICAvKipcbiAgICogVGhlIGRvbWFpbiBuYW1lIHRvIHVzZS5cbiAgICpcbiAgICogVGhpcyBkb21haW4gbmFtZSBtdXN0IGJlIG93bmVkIGJ5IHRoaXMgYWNjb3VudCAocmVnaXN0ZXJlZCB0aHJvdWdoIFJvdXRlNTMpLFxuICAgKiBvciBkZWxlZ2F0ZWQgdG8gdGhpcyBhY2NvdW50LiBEb21haW4gb3duZXJzaGlwIHdpbGwgYmUgdmVyaWZpZWQgYnkgQVdTIGJlZm9yZVxuICAgKiBwcml2YXRlIEROUyBjYW4gYmUgdXNlZC5cbiAgICogQHNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vdnBjL2xhdGVzdC91c2VyZ3VpZGUvZW5kcG9pbnQtc2VydmljZXMtZG5zLXZhbGlkYXRpb24uaHRtbFxuICAgKi9cbiAgcmVhZG9ubHkgZG9tYWluTmFtZTogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgcHVibGljIGhvc3RlZCB6b25lIHRvIHVzZSBmb3IgdGhlIGRvbWFpbi5cbiAgICovXG4gIHJlYWRvbmx5IHB1YmxpY0hvc3RlZFpvbmU6IElQdWJsaWNIb3N0ZWRab25lO1xufVxuXG4vKipcbiAqIEEgUHJpdmF0ZSBETlMgY29uZmlndXJhdGlvbiBmb3IgYSBWUEMgZW5kcG9pbnQgc2VydmljZS5cbiAqL1xuZXhwb3J0IGNsYXNzIFZwY0VuZHBvaW50U2VydmljZURvbWFpbk5hbWUgZXh0ZW5kcyBDb3JlQ29uc3RydWN0IHtcblxuICAvLyBUcmFjayBhbGwgZG9tYWluIG5hbWVzIGNyZWF0ZWQsIHNvIHNvbWVvbmUgZG9lc24ndCBhY2NpZGVudGFsbHkgYXNzb2NpYXRlIHR3byBkb21haW5zIHdpdGggYSBzaW5nbGUgc2VydmljZVxuICBwcml2YXRlIHN0YXRpYyByZWFkb25seSBlbmRwb2ludFNlcnZpY2VzOiBJVnBjRW5kcG9pbnRTZXJ2aWNlW10gPSBbXTtcblxuICAvLyBUcmFjayBhbGwgZG9tYWluIG5hbWVzIGNyZWF0ZWQsIHNvIHNvbWVvbmUgZG9lc24ndCBhY2NpZGVudGFsbHkgYXNzb2NpYXRlIHR3byBkb21haW5zIHdpdGggYSBzaW5nbGUgc2VydmljZVxuICBwcml2YXRlIHN0YXRpYyByZWFkb25seSBlbmRwb2ludFNlcnZpY2VzTWFwOiB7IFtlbmRwb2ludFNlcnZpY2U6IHN0cmluZ106IHN0cmluZ30gPSB7fTtcblxuICAvKipcbiAgICogVGhlIGRvbWFpbiBuYW1lIGFzc29jaWF0ZWQgd2l0aCB0aGUgcHJpdmF0ZSBETlMgY29uZmlndXJhdGlvblxuICAgKi9cbiAgcHVibGljIGRvbWFpbk5hbWU6IHN0cmluZztcblxuICAvLyBUaGUgd2F5IHRoaXMgY2xhc3Mgd29ya3MgaXMgYnkgdXNpbmcgdGhyZWUgY3VzdG9tIHJlc291cmNlcyBhbmQgYSBUeHRSZWNvcmQgaW4gY29uanVuY3Rpb25cbiAgLy8gVGhlIGZpcnN0IGN1c3RvbSByZXNvdXJjZSB0ZWxscyB0aGUgVlBDIGVuZHBvaW50IHNlcnZpY2UgdG8gdXNlIHRoZSBnaXZlbiBETlMgbmFtZVxuICAvLyBUaGUgVlBDIGVuZHBvaW50IHNlcnZpY2Ugd2lsbCB0aGVuIHNheTpcbiAgLy8gXCJvaywgY3JlYXRlIGEgVFhUIHJlY29yZCB1c2luZyB0aGVzZSB0d28gdmFsdWVzIHRvIHByb3ZlIHlvdSBvd24gdGhlIGRvbWFpblwiXG4gIC8vIFRoZSBzZWNvbmQgY3VzdG9tIHJlc291cmNlIHJldHJpZXZlcyB0aGVzZSB0d28gdmFsdWVzIGZyb20gdGhlIHNlcnZpY2VcbiAgLy8gVGhlIFR4dFJlY29yZCBpcyBjcmVhdGVkIGZyb20gdGhlc2UgdHdvIHZhbHVlc1xuICAvLyBUaGUgdGhpcmQgY3VzdG9tIHJlc291cmNlIHRlbGxzIHRoZSBWUEMgRW5kcG9pbnQgU2VydmljZSB0byB2ZXJpZnkgdGhlIGRvbWFpbiBvd25lcnNoaXBcbiAgY29uc3RydWN0b3Ioc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgcHJvcHM6IFZwY0VuZHBvaW50U2VydmljZURvbWFpbk5hbWVQcm9wcykge1xuICAgIHN1cGVyKHNjb3BlLCBpZCk7XG5cbiAgICBjb25zdCBzZXJ2aWNlVW5pcXVlSWQgPSBOYW1lcy5ub2RlVW5pcXVlSWQocHJvcHMuZW5kcG9pbnRTZXJ2aWNlLm5vZGUpO1xuICAgIGNvbnN0IHNlcnZpY2VJZCA9IHByb3BzLmVuZHBvaW50U2VydmljZS52cGNFbmRwb2ludFNlcnZpY2VJZDtcbiAgICB0aGlzLmRvbWFpbk5hbWUgPSBwcm9wcy5kb21haW5OYW1lO1xuXG4gICAgLy8gTWFrZSBzdXJlIGEgdXNlciBkb2Vzbid0IGFjY2lkZW50YWxseSBhZGQgbXVsdGlwbGUgZG9tYWluc1xuICAgIHRoaXMudmFsaWRhdGVQcm9wcyhwcm9wcyk7XG5cbiAgICBWcGNFbmRwb2ludFNlcnZpY2VEb21haW5OYW1lLmVuZHBvaW50U2VydmljZXNNYXBbc2VydmljZVVuaXF1ZUlkXSA9IHRoaXMuZG9tYWluTmFtZTtcbiAgICBWcGNFbmRwb2ludFNlcnZpY2VEb21haW5OYW1lLmVuZHBvaW50U2VydmljZXMucHVzaChwcm9wcy5lbmRwb2ludFNlcnZpY2UpO1xuXG4gICAgLy8gRW5hYmxlIFByaXZhdGUgRE5TIG9uIHRoZSBlbmRwb2ludCBzZXJ2aWNlIGFuZCByZXRyaWV2ZSB0aGUgQVdTLWdlbmVyYXRlZCBjb25maWd1cmF0aW9uXG4gICAgY29uc3QgcHJpdmF0ZURuc0NvbmZpZ3VyYXRpb24gPSB0aGlzLmdldFByaXZhdGVEbnNDb25maWd1cmF0aW9uKHNlcnZpY2VVbmlxdWVJZCwgc2VydmljZUlkLCB0aGlzLmRvbWFpbk5hbWUpO1xuXG4gICAgLy8gVGVsbCBBV1MgdG8gdmVyaWZ5IHRoYXQgdGhpcyBhY2NvdW50IG93bnMgdGhlIGRvbWFpbiBhdHRhY2hlZCB0byB0aGUgc2VydmljZVxuICAgIHRoaXMudmVyaWZ5UHJpdmF0ZURuc0NvbmZpZ3VyYXRpb24ocHJpdmF0ZURuc0NvbmZpZ3VyYXRpb24sIHByb3BzLnB1YmxpY0hvc3RlZFpvbmUpO1xuXG4gICAgLy8gRmluYWxseSwgZG9uJ3QgZG8gYW55IG9mIHRoZSBhYm92ZSBiZWZvcmUgdGhlIGVuZHBvaW50IHNlcnZpY2UgaXMgY3JlYXRlZFxuICAgIHRoaXMubm9kZS5hZGREZXBlbmRlbmN5KHByb3BzLmVuZHBvaW50U2VydmljZSk7XG4gIH1cblxuICBwcml2YXRlIHZhbGlkYXRlUHJvcHMocHJvcHM6IFZwY0VuZHBvaW50U2VydmljZURvbWFpbk5hbWVQcm9wcyk6IHZvaWQge1xuICAgIGNvbnN0IHNlcnZpY2VVbmlxdWVJZCA9IE5hbWVzLm5vZGVVbmlxdWVJZChwcm9wcy5lbmRwb2ludFNlcnZpY2Uubm9kZSk7XG4gICAgaWYgKHNlcnZpY2VVbmlxdWVJZCBpbiBWcGNFbmRwb2ludFNlcnZpY2VEb21haW5OYW1lLmVuZHBvaW50U2VydmljZXNNYXApIHtcbiAgICAgIGNvbnN0IGVuZHBvaW50ID0gVnBjRW5kcG9pbnRTZXJ2aWNlRG9tYWluTmFtZS5lbmRwb2ludFNlcnZpY2VzTWFwW3NlcnZpY2VVbmlxdWVJZF07XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBDYW5ub3QgY3JlYXRlIGEgVnBjRW5kcG9pbnRTZXJ2aWNlRG9tYWluTmFtZSBmb3Igc2VydmljZSAke3NlcnZpY2VVbmlxdWVJZH0sIGFub3RoZXIgVnBjRW5kcG9pbnRTZXJ2aWNlRG9tYWluTmFtZSAoJHtlbmRwb2ludH0pIGlzIGFscmVhZHkgYXNzb2NpYXRlZCB3aXRoIGl0YCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgdXAgQ3VzdG9tIFJlc291cmNlcyB0byBtYWtlIEFXUyBjYWxscyB0byBzZXQgdXAgUHJpdmF0ZSBETlMgb24gYW4gZW5kcG9pbnQgc2VydmljZSxcbiAgICogcmV0dXJuaW5nIHRoZSB2YWx1ZXMgdG8gdXNlIGluIGEgVHh0UmVjb3JkLCB3aGljaCBBV1MgdXNlcyB0byB2ZXJpZnkgZG9tYWluIG93bmVyc2hpcC5cbiAgICovXG4gIHByaXZhdGUgZ2V0UHJpdmF0ZURuc0NvbmZpZ3VyYXRpb24oc2VydmljZVVuaXF1ZUlkOiBzdHJpbmcsIHNlcnZpY2VJZDogc3RyaW5nLCBwcml2YXRlRG5zTmFtZTogc3RyaW5nKTogUHJpdmF0ZURuc0NvbmZpZ3VyYXRpb24ge1xuXG4gICAgLy8gVGhlIGN1c3RvbSByZXNvdXJjZSB3aGljaCB0ZWxscyBBV1MgdG8gZW5hYmxlIFByaXZhdGUgRE5TIG9uIHRoZSBnaXZlbiBzZXJ2aWNlLCB1c2luZyB0aGUgZ2l2ZW4gZG9tYWluIG5hbWVcbiAgICAvLyBBV1Mgd2lsbCBnZW5lcmF0ZSBhIG5hbWUvdmFsdWUgcGFpciBmb3IgdXNlIGluIGEgVHh0UmVjb3JkLCB3aGljaCBpcyB1c2VkIHRvIHZlcmlmeSBkb21haW4gb3duZXJzaGlwLlxuICAgIGNvbnN0IGVuYWJsZVByaXZhdGVEbnNBY3Rpb24gPSB7XG4gICAgICBzZXJ2aWNlOiAnRUMyJyxcbiAgICAgIGFjdGlvbjogJ21vZGlmeVZwY0VuZHBvaW50U2VydmljZUNvbmZpZ3VyYXRpb24nLFxuICAgICAgcGFyYW1ldGVyczoge1xuICAgICAgICBTZXJ2aWNlSWQ6IHNlcnZpY2VJZCxcbiAgICAgICAgUHJpdmF0ZURuc05hbWU6IHByaXZhdGVEbnNOYW1lLFxuICAgICAgfSxcbiAgICAgIHBoeXNpY2FsUmVzb3VyY2VJZDogUGh5c2ljYWxSZXNvdXJjZUlkLm9mKHNlcnZpY2VVbmlxdWVJZCksXG4gICAgfTtcbiAgICBjb25zdCByZW1vdmVQcml2YXRlRG5zQWN0aW9uID0ge1xuICAgICAgc2VydmljZTogJ0VDMicsXG4gICAgICBhY3Rpb246ICdtb2RpZnlWcGNFbmRwb2ludFNlcnZpY2VDb25maWd1cmF0aW9uJyxcbiAgICAgIHBhcmFtZXRlcnM6IHtcbiAgICAgICAgU2VydmljZUlkOiBzZXJ2aWNlSWQsXG4gICAgICAgIFJlbW92ZVByaXZhdGVEbnNOYW1lOiB0cnVlLFxuICAgICAgfSxcbiAgICB9O1xuICAgIGNvbnN0IGVuYWJsZSA9IG5ldyBBd3NDdXN0b21SZXNvdXJjZSh0aGlzLCAnRW5hYmxlRG5zJywge1xuICAgICAgb25DcmVhdGU6IGVuYWJsZVByaXZhdGVEbnNBY3Rpb24sXG4gICAgICBvblVwZGF0ZTogZW5hYmxlUHJpdmF0ZURuc0FjdGlvbixcbiAgICAgIG9uRGVsZXRlOiByZW1vdmVQcml2YXRlRG5zQWN0aW9uLFxuICAgICAgcG9saWN5OiBBd3NDdXN0b21SZXNvdXJjZVBvbGljeS5mcm9tU2RrQ2FsbHMoe1xuICAgICAgICByZXNvdXJjZXM6IFtcbiAgICAgICAgICBGbi5qb2luKCc6JywgW1xuICAgICAgICAgICAgJ2FybicsXG4gICAgICAgICAgICBTdGFjay5vZih0aGlzKS5wYXJ0aXRpb24sXG4gICAgICAgICAgICAnZWMyJyxcbiAgICAgICAgICAgIFN0YWNrLm9mKHRoaXMpLnJlZ2lvbixcbiAgICAgICAgICAgIFN0YWNrLm9mKHRoaXMpLmFjY291bnQsXG4gICAgICAgICAgICBGbi5qb2luKCcvJywgW1xuICAgICAgICAgICAgICAndnBjLWVuZHBvaW50LXNlcnZpY2UnLFxuICAgICAgICAgICAgICBzZXJ2aWNlSWQsXG4gICAgICAgICAgICBdKSxcbiAgICAgICAgICBdKSxcbiAgICAgICAgXSxcbiAgICAgIH0pLFxuICAgIH0pO1xuXG4gICAgLy8gTG9vayB1cCB0aGUgbmFtZS92YWx1ZSBwYWlyIGlmIHRoZSBkb21haW4gY2hhbmdlcywgb3IgdGhlIHNlcnZpY2UgY2hhbmdlcyxcbiAgICAvLyB3aGljaCB3b3VsZCBjYXVzZSB0aGUgdmFsdWVzIHRvIGJlIGRpZmZlcmVudC4gSWYgdGhlIHVuaXF1ZSBJRCBjaGFuZ2VzLFxuICAgIC8vIHRoZSByZXNvdXJjZSBtYXkgYmUgZW50aXJlbHkgcmVjcmVhdGVkLCBzbyB3ZSB3aWxsIG5lZWQgdG8gbG9vayBpdCB1cCBhZ2Fpbi5cbiAgICBjb25zdCBsb29rdXAgPSBoYXNoY29kZShOYW1lcy51bmlxdWVJZCh0aGlzKSArIHNlcnZpY2VVbmlxdWVJZCArIHByaXZhdGVEbnNOYW1lKTtcblxuICAgIC8vIENyZWF0ZSB0aGUgY3VzdG9tIHJlc291cmNlIHRvIGxvb2sgdXAgdGhlIG5hbWUvdmFsdWUgcGFpciBnZW5lcmF0ZWQgYnkgQVdTXG4gICAgLy8gYWZ0ZXIgdGhlIHByZXZpb3VzIEFQSSBjYWxsXG4gICAgY29uc3QgcmV0cmlldmVOYW1lVmFsdWVQYWlyQWN0aW9uID0ge1xuICAgICAgc2VydmljZTogJ0VDMicsXG4gICAgICBhY3Rpb246ICdkZXNjcmliZVZwY0VuZHBvaW50U2VydmljZUNvbmZpZ3VyYXRpb25zJyxcbiAgICAgIHBhcmFtZXRlcnM6IHtcbiAgICAgICAgU2VydmljZUlkczogW3NlcnZpY2VJZF0sXG4gICAgICB9LFxuICAgICAgcGh5c2ljYWxSZXNvdXJjZUlkOiBQaHlzaWNhbFJlc291cmNlSWQub2YobG9va3VwKSxcbiAgICB9O1xuICAgIGNvbnN0IGdldE5hbWVzID0gbmV3IEF3c0N1c3RvbVJlc291cmNlKHRoaXMsICdHZXROYW1lcycsIHtcbiAgICAgIG9uQ3JlYXRlOiByZXRyaWV2ZU5hbWVWYWx1ZVBhaXJBY3Rpb24sXG4gICAgICBvblVwZGF0ZTogcmV0cmlldmVOYW1lVmFsdWVQYWlyQWN0aW9uLFxuICAgICAgLy8gZGVzY3JpYmVWcGNFbmRwb2ludFNlcnZpY2VDb25maWd1cmF0aW9ucyBjYW4ndCB0YWtlIGFuIEFSTiBmb3IgZ3JhbnVsYXIgcGVybWlzc2lvbnNcbiAgICAgIHBvbGljeTogQXdzQ3VzdG9tUmVzb3VyY2VQb2xpY3kuZnJvbVNka0NhbGxzKHtcbiAgICAgICAgcmVzb3VyY2VzOiBBd3NDdXN0b21SZXNvdXJjZVBvbGljeS5BTllfUkVTT1VSQ0UsXG4gICAgICB9KSxcbiAgICB9KTtcblxuICAgIC8vIFdlIG9ubHkgd2FudCB0byBjYWxsIGFuZCBnZXQgdGhlIG5hbWUvdmFsdWUgcGFpciBhZnRlciB3ZSd2ZSB0b2xkIEFXUyB0byBlbmFibGUgUHJpdmF0ZSBETlNcbiAgICAvLyBJZiB3ZSBjYWxsIGJlZm9yZSB0aGVuLCB3ZSdsbCBnZXQgYW4gZW1wdHkgcGFpciBvZiB2YWx1ZXMuXG4gICAgZ2V0TmFtZXMubm9kZS5hZGREZXBlbmRlbmN5KGVuYWJsZSk7XG5cbiAgICAvLyBHZXQgdGhlIHJlZmVyZW5jZXMgdG8gdGhlIG5hbWUvdmFsdWUgcGFpciBhc3NvY2lhdGVkIHdpdGggdGhlIGVuZHBvaW50IHNlcnZpY2VcbiAgICBjb25zdCBuYW1lID0gZ2V0TmFtZXMuZ2V0UmVzcG9uc2VGaWVsZCgnU2VydmljZUNvbmZpZ3VyYXRpb25zLjAuUHJpdmF0ZURuc05hbWVDb25maWd1cmF0aW9uLk5hbWUnKTtcbiAgICBjb25zdCB2YWx1ZSA9IGdldE5hbWVzLmdldFJlc3BvbnNlRmllbGQoJ1NlcnZpY2VDb25maWd1cmF0aW9ucy4wLlByaXZhdGVEbnNOYW1lQ29uZmlndXJhdGlvbi5WYWx1ZScpO1xuXG4gICAgcmV0dXJuIHsgbmFtZSwgdmFsdWUsIHNlcnZpY2VJZCB9O1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBSb3V0ZTUzIGVudHJ5IGFuZCBhIEN1c3RvbSBSZXNvdXJjZSB3aGljaCBleHBsaWNpdGx5IHRlbGxzIEFXUyB0byB2ZXJpZnkgb3duZXJzaGlwXG4gICAqIG9mIHRoZSBkb21haW4gbmFtZSBhdHRhY2hlZCB0byBhbiBlbmRwb2ludCBzZXJ2aWNlLlxuICAgKi9cbiAgcHJpdmF0ZSB2ZXJpZnlQcml2YXRlRG5zQ29uZmlndXJhdGlvbihjb25maWc6IFByaXZhdGVEbnNDb25maWd1cmF0aW9uLCBwdWJsaWNIb3N0ZWRab25lOiBJUHVibGljSG9zdGVkWm9uZSkge1xuICAgIC8vIENyZWF0ZSB0aGUgVFhUIHJlY29yZCBpbiB0aGUgcHJvdmlkZWQgaG9zdGVkIHpvbmVcbiAgICBjb25zdCB2ZXJpZmljYXRpb25SZWNvcmQgPSBuZXcgVHh0UmVjb3JkKHRoaXMsICdEbnNWZXJpZmljYXRpb25SZWNvcmQnLCB7XG4gICAgICByZWNvcmROYW1lOiBjb25maWcubmFtZSxcbiAgICAgIHZhbHVlczogW2NvbmZpZy52YWx1ZV0sXG4gICAgICB6b25lOiBwdWJsaWNIb3N0ZWRab25lLFxuICAgIH0pO1xuXG4gICAgLy8gVGVsbCB0aGUgZW5kcG9pbnQgc2VydmljZSB0byB2ZXJpZnkgdGhlIGRvbWFpbiBvd25lcnNoaXBcbiAgICBjb25zdCBzdGFydFZlcmlmaWNhdGlvbkFjdGlvbiA9IHtcbiAgICAgIHNlcnZpY2U6ICdFQzInLFxuICAgICAgYWN0aW9uOiAnc3RhcnRWcGNFbmRwb2ludFNlcnZpY2VQcml2YXRlRG5zVmVyaWZpY2F0aW9uJyxcbiAgICAgIHBhcmFtZXRlcnM6IHtcbiAgICAgICAgU2VydmljZUlkOiBjb25maWcuc2VydmljZUlkLFxuICAgICAgfSxcbiAgICAgIHBoeXNpY2FsUmVzb3VyY2VJZDogUGh5c2ljYWxSZXNvdXJjZUlkLm9mKEZuLmpvaW4oJzonLCBbY29uZmlnLm5hbWUsIGNvbmZpZy52YWx1ZV0pKSxcbiAgICB9O1xuICAgIGNvbnN0IHN0YXJ0VmVyaWZpY2F0aW9uID0gbmV3IEF3c0N1c3RvbVJlc291cmNlKHRoaXMsICdTdGFydFZlcmlmaWNhdGlvbicsIHtcbiAgICAgIG9uQ3JlYXRlOiBzdGFydFZlcmlmaWNhdGlvbkFjdGlvbixcbiAgICAgIG9uVXBkYXRlOiBzdGFydFZlcmlmaWNhdGlvbkFjdGlvbixcbiAgICAgIHBvbGljeTogQXdzQ3VzdG9tUmVzb3VyY2VQb2xpY3kuZnJvbVNka0NhbGxzKHtcbiAgICAgICAgcmVzb3VyY2VzOiBbXG4gICAgICAgICAgRm4uam9pbignOicsIFtcbiAgICAgICAgICAgICdhcm4nLFxuICAgICAgICAgICAgU3RhY2sub2YodGhpcykucGFydGl0aW9uLFxuICAgICAgICAgICAgJ2VjMicsXG4gICAgICAgICAgICBTdGFjay5vZih0aGlzKS5yZWdpb24sXG4gICAgICAgICAgICBTdGFjay5vZih0aGlzKS5hY2NvdW50LFxuICAgICAgICAgICAgRm4uam9pbignLycsIFtcbiAgICAgICAgICAgICAgJ3ZwYy1lbmRwb2ludC1zZXJ2aWNlJyxcbiAgICAgICAgICAgICAgY29uZmlnLnNlcnZpY2VJZCxcbiAgICAgICAgICAgIF0pLFxuICAgICAgICAgIF0pLFxuICAgICAgICBdLFxuICAgICAgfSksXG4gICAgfSk7XG4gICAgLy8gT25seSB2ZXJpZnkgYWZ0ZXIgdGhlIHJlY29yZCBoYXMgYmVlbiBjcmVhdGVkXG4gICAgc3RhcnRWZXJpZmljYXRpb24ubm9kZS5hZGREZXBlbmRlbmN5KHZlcmlmaWNhdGlvblJlY29yZCk7XG4gIH1cbn1cblxuLyoqXG4gKiBSZXByZXNlbnQgdGhlIG5hbWUvdmFsdWUgcGFpciBhc3NvY2lhdGVkIHdpdGggYSBQcml2YXRlIEROUyBlbmFibGVkIGVuZHBvaW50IHNlcnZpY2VcbiAqL1xuaW50ZXJmYWNlIFByaXZhdGVEbnNDb25maWd1cmF0aW9uIHtcbiAgcmVhZG9ubHkgbmFtZTogc3RyaW5nO1xuICByZWFkb25seSB2YWx1ZTogc3RyaW5nO1xuICByZWFkb25seSBzZXJ2aWNlSWQ6IHN0cmluZztcbn1cblxuLyoqXG4gKiBIYXNoIGEgc3RyaW5nXG4gKi9cbmZ1bmN0aW9uIGhhc2hjb2RlKHM6IHN0cmluZyk6IHN0cmluZyB7XG4gIGNvbnN0IGhhc2ggPSBjcnlwdG8uY3JlYXRlSGFzaCgnbWQ1Jyk7XG4gIGhhc2gudXBkYXRlKHMpO1xuICByZXR1cm4gaGFzaC5kaWdlc3QoJ2hleCcpO1xufTsiXX0= |
\ | No newline at end of file |