@aws-cdk/aws-ec2
Version:
The CDK Construct Library for AWS::EC2
275 lines • 37.9 kB
JavaScript
;
var _a, _b;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ClientVpnEndpoint = exports.ClientVpnUserBasedAuthentication = exports.ClientVpnSessionTimeout = void 0;
const jsiiDeprecationWarnings = require("../.warnings.jsii.js");
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
const logs = require("@aws-cdk/aws-logs");
const core_1 = require("@aws-cdk/core");
const client_vpn_authorization_rule_1 = require("./client-vpn-authorization-rule");
const client_vpn_route_1 = require("./client-vpn-route");
const connections_1 = require("./connections");
const ec2_generated_1 = require("./ec2.generated");
const network_util_1 = require("./network-util");
const security_group_1 = require("./security-group");
/**
* Maximum VPN session duration time
*/
var ClientVpnSessionTimeout;
(function (ClientVpnSessionTimeout) {
/** 8 hours */
ClientVpnSessionTimeout[ClientVpnSessionTimeout["EIGHT_HOURS"] = 8] = "EIGHT_HOURS";
/** 10 hours */
ClientVpnSessionTimeout[ClientVpnSessionTimeout["TEN_HOURS"] = 10] = "TEN_HOURS";
/** 12 hours */
ClientVpnSessionTimeout[ClientVpnSessionTimeout["TWELVE_HOURS"] = 12] = "TWELVE_HOURS";
/** 24 hours */
ClientVpnSessionTimeout[ClientVpnSessionTimeout["TWENTY_FOUR_HOURS"] = 24] = "TWENTY_FOUR_HOURS";
})(ClientVpnSessionTimeout = exports.ClientVpnSessionTimeout || (exports.ClientVpnSessionTimeout = {}));
/**
* User-based authentication for a client VPN endpoint
*/
class ClientVpnUserBasedAuthentication {
/**
* Active Directory authentication
*/
static activeDirectory(directoryId) {
return new ActiveDirectoryAuthentication(directoryId);
}
/** Federated authentication */
static federated(samlProvider, selfServiceSamlProvider) {
return new FederatedAuthentication(samlProvider, selfServiceSamlProvider);
}
}
exports.ClientVpnUserBasedAuthentication = ClientVpnUserBasedAuthentication;
_a = JSII_RTTI_SYMBOL_1;
ClientVpnUserBasedAuthentication[_a] = { fqn: "@aws-cdk/aws-ec2.ClientVpnUserBasedAuthentication", version: "1.204.0" };
/**
* Active Directory authentication
*/
class ActiveDirectoryAuthentication extends ClientVpnUserBasedAuthentication {
constructor(directoryId) {
super();
this.directoryId = directoryId;
}
render() {
return {
type: 'directory-service-authentication',
activeDirectory: { directoryId: this.directoryId },
};
}
}
/**
* Federated authentication
*/
class FederatedAuthentication extends ClientVpnUserBasedAuthentication {
constructor(samlProvider, selfServiceSamlProvider) {
super();
this.samlProvider = samlProvider;
this.selfServiceSamlProvider = selfServiceSamlProvider;
}
render() {
return {
type: 'federated-authentication',
federatedAuthentication: {
samlProviderArn: this.samlProvider.samlProviderArn,
selfServiceSamlProviderArn: this.selfServiceSamlProvider?.samlProviderArn,
},
};
}
}
/**
* A client VPN connnection
*/
class ClientVpnEndpoint extends core_1.Resource {
constructor(scope, id, props) {
super(scope, id);
this._targetNetworksAssociated = new core_1.ConcreteDependable();
try {
jsiiDeprecationWarnings._aws_cdk_aws_ec2_ClientVpnEndpointProps(props);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, ClientVpnEndpoint);
}
throw error;
}
if (!core_1.Token.isUnresolved(props.vpc.vpcCidrBlock)) {
const clientCidr = new network_util_1.CidrBlock(props.cidr);
const vpcCidr = new network_util_1.CidrBlock(props.vpc.vpcCidrBlock);
if (vpcCidr.containsCidr(clientCidr)) {
throw new Error('The client CIDR cannot overlap with the local CIDR of the VPC');
}
}
if (props.dnsServers && props.dnsServers.length > 2) {
throw new Error('A client VPN endpoint can have up to two DNS servers');
}
if (props.logging == false && (props.logGroup || props.logStream)) {
throw new Error('Cannot specify `logGroup` or `logStream` when logging is disabled');
}
if (props.clientConnectionHandler
&& !core_1.Token.isUnresolved(props.clientConnectionHandler.functionName)
&& !props.clientConnectionHandler.functionName.startsWith('AWSClientVPN-')) {
throw new Error('The name of the Lambda function must begin with the `AWSClientVPN-` prefix');
}
if (props.clientLoginBanner
&& !core_1.Token.isUnresolved(props.clientLoginBanner)
&& props.clientLoginBanner.length > 1400) {
throw new Error(`The maximum length for the client login banner is 1400, got ${props.clientLoginBanner.length}`);
}
const logging = props.logging ?? true;
const logGroup = logging
? props.logGroup ?? new logs.LogGroup(this, 'LogGroup')
: undefined;
const securityGroups = props.securityGroups ?? [new security_group_1.SecurityGroup(this, 'SecurityGroup', {
vpc: props.vpc,
})];
this.connections = new connections_1.Connections({ securityGroups });
const endpoint = new ec2_generated_1.CfnClientVpnEndpoint(this, 'Resource', {
authenticationOptions: renderAuthenticationOptions(props.clientCertificateArn, props.userBasedAuthentication),
clientCidrBlock: props.cidr,
clientConnectOptions: props.clientConnectionHandler
? {
enabled: true,
lambdaFunctionArn: props.clientConnectionHandler.functionArn,
}
: undefined,
connectionLogOptions: {
enabled: logging,
cloudwatchLogGroup: logGroup?.logGroupName,
cloudwatchLogStream: props.logStream?.logStreamName,
},
description: props.description,
dnsServers: props.dnsServers,
securityGroupIds: securityGroups.map(s => s.securityGroupId),
selfServicePortal: booleanToEnabledDisabled(props.selfServicePortal),
serverCertificateArn: props.serverCertificateArn,
splitTunnel: props.splitTunnel,
transportProtocol: props.transportProtocol,
vpcId: props.vpc.vpcId,
vpnPort: props.port,
sessionTimeoutHours: props.sessionTimeout,
clientLoginBannerOptions: props.clientLoginBanner
? {
enabled: true,
bannerText: props.clientLoginBanner,
}
: undefined,
});
this.endpointId = endpoint.ref;
if (props.userBasedAuthentication && (props.selfServicePortal ?? true)) {
// Output self-service portal URL
new core_1.CfnOutput(this, 'SelfServicePortalUrl', {
value: `https://self-service.clientvpn.amazonaws.com/endpoints/${this.endpointId}`,
});
}
// Associate subnets
const subnetIds = props.vpc.selectSubnets(props.vpcSubnets).subnetIds;
if (core_1.Token.isUnresolved(subnetIds)) {
throw new Error('Cannot associate subnets when VPC are imported from parameters or exports containing lists of subnet IDs.');
}
for (const [idx, subnetId] of Object.entries(subnetIds)) {
this._targetNetworksAssociated.add(new ec2_generated_1.CfnClientVpnTargetNetworkAssociation(this, `Association${idx}`, {
clientVpnEndpointId: this.endpointId,
subnetId,
}));
}
this.targetNetworksAssociated = this._targetNetworksAssociated;
if (props.authorizeAllUsersToVpcCidr ?? true) {
this.addAuthorizationRule('AuthorizeAll', {
cidr: props.vpc.vpcCidrBlock,
});
}
}
/**
* Import an existing client VPN endpoint
*/
static fromEndpointAttributes(scope, id, attrs) {
try {
jsiiDeprecationWarnings._aws_cdk_aws_ec2_ClientVpnEndpointAttributes(attrs);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, this.fromEndpointAttributes);
}
throw error;
}
class Import extends core_1.Resource {
constructor() {
super(...arguments);
this.endpointId = attrs.endpointId;
this.connections = new connections_1.Connections({ securityGroups: attrs.securityGroups });
this.targetNetworksAssociated = new core_1.ConcreteDependable();
}
}
return new Import(scope, id);
}
/**
* Adds an authorization rule to this endpoint
*/
addAuthorizationRule(id, props) {
try {
jsiiDeprecationWarnings._aws_cdk_aws_ec2_ClientVpnAuthorizationRuleOptions(props);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, this.addAuthorizationRule);
}
throw error;
}
return new client_vpn_authorization_rule_1.ClientVpnAuthorizationRule(this, id, {
...props,
clientVpnEndpoint: this,
});
}
/**
* Adds a route to this endpoint
*/
addRoute(id, props) {
try {
jsiiDeprecationWarnings._aws_cdk_aws_ec2_ClientVpnRouteOptions(props);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, this.addRoute);
}
throw error;
}
return new client_vpn_route_1.ClientVpnRoute(this, id, {
...props,
clientVpnEndpoint: this,
});
}
}
exports.ClientVpnEndpoint = ClientVpnEndpoint;
_b = JSII_RTTI_SYMBOL_1;
ClientVpnEndpoint[_b] = { fqn: "@aws-cdk/aws-ec2.ClientVpnEndpoint", version: "1.204.0" };
function renderAuthenticationOptions(clientCertificateArn, userBasedAuthentication) {
const authenticationOptions = [];
if (clientCertificateArn) {
authenticationOptions.push({
type: 'certificate-authentication',
mutualAuthentication: {
clientRootCertificateChainArn: clientCertificateArn,
},
});
}
if (userBasedAuthentication) {
authenticationOptions.push(userBasedAuthentication.render());
}
if (authenticationOptions.length === 0) {
throw new Error('A client VPN endpoint must use at least one authentication option');
}
return authenticationOptions;
}
function booleanToEnabledDisabled(val) {
switch (val) {
case undefined:
return undefined;
case true:
return 'enabled';
case false:
return 'disabled';
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xpZW50LXZwbi1lbmRwb2ludC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImNsaWVudC12cG4tZW5kcG9pbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQ0EsMENBQTBDO0FBQzFDLHdDQUE0RjtBQUU1RixtRkFBZ0g7QUFFaEgseURBQTJFO0FBQzNFLCtDQUE0QztBQUM1QyxtREFBNkY7QUFDN0YsaURBQTJDO0FBQzNDLHFEQUFpRTtBQWlLakU7O0dBRUc7QUFDSCxJQUFZLHVCQVNYO0FBVEQsV0FBWSx1QkFBdUI7SUFDakMsY0FBYztJQUNkLG1GQUFlLENBQUE7SUFDZixlQUFlO0lBQ2YsZ0ZBQWMsQ0FBQTtJQUNkLGVBQWU7SUFDZixzRkFBaUIsQ0FBQTtJQUNqQixlQUFlO0lBQ2YsZ0dBQXNCLENBQUE7QUFDeEIsQ0FBQyxFQVRXLHVCQUF1QixHQUF2QiwrQkFBdUIsS0FBdkIsK0JBQXVCLFFBU2xDO0FBRUQ7O0dBRUc7QUFDSCxNQUFzQixnQ0FBZ0M7SUFDcEQ7O09BRUc7SUFDSSxNQUFNLENBQUMsZUFBZSxDQUFDLFdBQW1CO1FBQy9DLE9BQU8sSUFBSSw2QkFBNkIsQ0FBQyxXQUFXLENBQUMsQ0FBQztLQUN2RDtJQUVELCtCQUErQjtJQUN4QixNQUFNLENBQUMsU0FBUyxDQUFDLFlBQTJCLEVBQUUsdUJBQXVDO1FBQzFGLE9BQU8sSUFBSSx1QkFBdUIsQ0FBQyxZQUFZLEVBQUUsdUJBQXVCLENBQUMsQ0FBQztLQUMzRTs7QUFYSCw0RUFlQzs7O0FBRUQ7O0dBRUc7QUFDSCxNQUFNLDZCQUE4QixTQUFRLGdDQUFnQztJQUMxRSxZQUE2QixXQUFtQjtRQUM5QyxLQUFLLEVBQUUsQ0FBQztRQURtQixnQkFBVyxHQUFYLFdBQVcsQ0FBUTtLQUUvQztJQUVELE1BQU07UUFDSixPQUFPO1lBQ0wsSUFBSSxFQUFFLGtDQUFrQztZQUN4QyxlQUFlLEVBQUUsRUFBRSxXQUFXLEVBQUUsSUFBSSxDQUFDLFdBQVcsRUFBRTtTQUNu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QkFBb0IsRUFBRTtRQUN4QixxQkFBcUIsQ0FBQyxJQUFJLENBQUM7WUFDekIsSUFBSSxFQUFFLDRCQUE0QjtZQUNsQyxvQkFBb0IsRUFBRTtnQkFDcEIsNkJBQTZCLEVBQUUsb0JBQW9CO2FBQ3BEO1NBQ0YsQ0FBQyxDQUFDO0tBQ0o7SUFFRCxJQUFJLHVCQUF1QixFQUFFO1FBQzNCLHFCQUFxQixDQUFDLElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO0tBQzlEO0lBRUQsSUFBSSxxQkFBcUIsQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFO1FBQ3RDLE1BQU0sSUFBSSxLQUFLLENBQUMsbUVBQW1FLENBQUMsQ0FBQztLQUN0RjtJQUNELE9BQU8scUJBQXFCLENBQUM7QUFDL0IsQ0FBQztBQUVELFNBQVMsd0JBQXdCLENBQUMsR0FBYTtJQUM3QyxRQUFRLEdBQUcsRUFBRTtRQUNYLEtBQUssU0FBUztZQUNaLE9BQU8sU0FBUyxDQUFDO1FBQ25CLEtBQUssSUFBSTtZQUNQLE9BQU8sU0FBUyxDQUFDO1FBQ25CLEtBQUssS0FBSztZQUNSLE9BQU8sVUFBVSxDQUFDO0tBQ3JCO0FBQ0gsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IElTYW1sUHJvdmlkZXIgfSBmcm9tICdAYXdzLWNkay9hd3MtaWFtJztcbmltcG9ydCAqIGFzIGxvZ3MgZnJvbSAnQGF3cy1jZGsvYXdzLWxvZ3MnO1xuaW1wb3J0IHsgQ2ZuT3V0cHV0LCBDb25jcmV0ZURlcGVuZGFibGUsIElEZXBlbmRhYmxlLCBSZXNvdXJjZSwgVG9rZW4gfSBmcm9tICdAYXdzLWNkay9jb3JlJztcbmltcG9ydCB7IENvbnN0cnVjdCB9IGZyb20gJ2NvbnN0cnVjdHMnO1xuaW1wb3J0IHsgQ2xpZW50VnBuQXV0aG9yaXphdGlvblJ1bGUsIENsaWVudFZwbkF1dGhvcml6YXRpb25SdWxlT3B0aW9ucyB9IGZyb20gJy4vY2xpZW50LXZwbi1hdXRob3JpemF0aW9uLXJ1bGUnO1xuaW1wb3J0IHsgSUNsaWVudFZwbkNvbm5lY3Rpb25IYW5kbGVyLCBJQ2xpZW50VnBuRW5kcG9pbnQsIFRyYW5zcG9ydFByb3RvY29sLCBWcG5Qb3J0IH0gZnJvbSAnLi9jbGllbnQtdnBuLWVuZHBvaW50LXR5cGVzJztcbmltcG9ydCB7IENsaWVudFZwblJvdXRlLCBDbGllbnRWcG5Sb3V0ZU9wdGlvbnMgfSBmcm9tICcuL2NsaWVudC12cG4tcm91dGUnO1xuaW1wb3J0IHsgQ29ubmVjdGlvbnMgfSBmcm9tICcuL2Nvbm5lY3Rpb25zJztcbmltcG9ydCB7IENmbkNsaWVudFZwbkVuZHBvaW50LCBDZm5DbGllbnRWcG5UYXJnZXROZXR3b3JrQXNzb2NpYXRpb24gfSBmcm9tICcuL2VjMi5nZW5lcmF0ZWQnO1xuaW1wb3J0IHsgQ2lkckJsb2NrIH0gZnJvbSAnLi9uZXR3b3JrLXV0aWwnO1xuaW1wb3J0IHsgSVNlY3VyaXR5R3JvdXAsIFNlY3VyaXR5R3JvdXAgfSBmcm9tICcuL3NlY3VyaXR5LWdyb3VwJztcbmltcG9ydCB7IElWcGMsIFN1Ym5ldFNlbGVjdGlvbiB9IGZyb20gJy4vdnBjJztcblxuLyoqXG4gKiBPcHRpb25zIGZvciBhIGNsaWVudCBWUE4gZW5kcG9pbnRcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBDbGllbnRWcG5FbmRwb2ludE9wdGlvbnMge1xuICAvKipcbiAgICogVGhlIElQdjQgYWRkcmVzcyByYW5nZSwgaW4gQ0lEUiBub3RhdGlvbiwgZnJvbSB3aGljaCB0byBhc3NpZ24gY2xpZW50IElQXG4gICAqIGFkZHJlc3Nlcy4gVGhlIGFkZHJlc3MgcmFuZ2UgY2Fubm90IG92ZXJsYXAgd2l0aCB0aGUgbG9jYWwgQ0lEUiBvZiB0aGUgVlBDXG4gICAqIGluIHdoaWNoIHRoZSBhc3NvY2lhdGVkIHN1Ym5ldCBpcyBsb2NhdGVkLCBvciB0aGUgcm91dGVzIHRoYXQgeW91IGFkZCBtYW51YWxseS5cbiAgICpcbiAgICogQ2hhbmdpbmcgdGhlIGFkZHJlc3MgcmFuZ2Ugd2lsbCByZXBsYWNlIHRoZSBDbGllbnQgVlBOIGVuZHBvaW50LlxuICAgKlxuICAgKiBUaGUgQ0lEUiBibG9jayBzaG91bGQgYmUgLzIyIG9yIGdyZWF0ZXIuXG4gICAqL1xuICByZWFkb25seSBjaWRyOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBBUk4gb2YgdGhlIGNsaWVudCBjZXJ0aWZpY2F0ZSBmb3IgbXV0dWFsIGF1dGhlbnRpY2F0aW9uLlxuICAgKlxuICAgKiBUaGUgY2VydGlmaWNhdGUgbXVzdCBiZSBzaWduZWQgYnkgYSBjZXJ0aWZpY2F0ZSBhdXRob3JpdHkgKENBKSBhbmQgaXQgbXVzdFxuICAgKiBiZSBwcm92aXNpb25lZCBpbiBBV1MgQ2VydGlmaWNhdGUgTWFuYWdlciAoQUNNKS5cbiAgICpcbiAgICogQGRlZmF1bHQgLSB1c2UgdXNlci1iYXNlZCBhdXRoZW50aWNhdGlvblxuICAgKi9cbiAgcmVhZG9ubHkgY2xpZW50Q2VydGlmaWNhdGVBcm4/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSB0eXBlIG9mIHVzZXItYmFzZWQgYXV0aGVudGljYXRpb24gdG8gdXNlLlxuICAgKlxuICAgKiBAc2VlIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS92cG4vbGF0ZXN0L2NsaWVudHZwbi1hZG1pbi9jbGllbnQtYXV0aGVudGljYXRpb24uaHRtbFxuICAgKlxuICAgKiBAZGVmYXVsdCAtIHVzZSBtdXR1YWwgYXV0aGVudGljYXRpb25cbiAgICovXG4gIHJlYWRvbmx5IHVzZXJCYXNlZEF1dGhlbnRpY2F0aW9uPzogQ2xpZW50VnBuVXNlckJhc2VkQXV0aGVudGljYXRpb247XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdG8gZW5hYmxlIGNvbm5lY3Rpb25zIGxvZ2dpbmdcbiAgICpcbiAgICogQGRlZmF1bHQgdHJ1ZVxuICAgKi9cbiAgcmVhZG9ubHkgbG9nZ2luZz86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIEEgQ2xvdWRXYXRjaCBMb2dzIGxvZyBncm91cCBmb3IgY29ubmVjdGlvbiBsb2dnaW5nXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gYSBuZXcgZ3JvdXAgaXMgY3JlYXRlZFxuICAgKi9cbiAgcmVhZG9ubHkgbG9nR3JvdXA/OiBsb2dzLklMb2dHcm91cDtcblxuICAvKipcbiAgICogQSBDbG91ZFdhdGNoIExvZ3MgbG9nIHN0cmVhbSBmb3IgY29ubmVjdGlvbiBsb2dnaW5nXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gYSBuZXcgc3RyZWFtIGlzIGNyZWF0ZWRcbiAgICovXG4gIHJlYWRvbmx5IGxvZ1N0cmVhbT86IGxvZ3MuSUxvZ1N0cmVhbTtcblxuICAvKipcbiAgICogVGhlIEFXUyBMYW1iZGEgZnVuY3Rpb24gdXNlZCBmb3IgY29ubmVjdGlvbiBhdXRob3JpemF0aW9uXG4gICAqXG4gICAqIFRoZSBuYW1lIG9mIHRoZSBMYW1iZGEgZnVuY3Rpb24gbXVzdCBiZWdpbiB3aXRoIHRoZSBgQVdTQ2xpZW50VlBOLWAgcHJlZml4XG4gICAqXG4gICAqIEBkZWZhdWx0IC0gbm8gY29ubmVjdGlvbiBoYW5kbGVyXG4gICAqL1xuICByZWFkb25seSBjbGllbnRDb25uZWN0aW9uSGFuZGxlcj86IElDbGllbnRWcG5Db25uZWN0aW9uSGFuZGxlcjtcblxuICAvKipcbiAgICogQSBicmllZiBkZXNjcmlwdGlvbiBvZiB0aGUgQ2xpZW50IFZQTiBlbmRwb2ludC5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBubyBkZXNjcmlwdGlvblxuICAgKi9cbiAgcmVhZG9ubHkgZGVzY3JpcHRpb24/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBzZWN1cml0eSBncm91cHMgdG8gYXBwbHkgdG8gdGhlIHRhcmdldCBuZXR3b3JrLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIGEgbmV3IHNlY3VyaXR5IGdyb3VwIGlzIGNyZWF0ZWRcbiAgICovXG4gIHJlYWRvbmx5IHNlY3VyaXR5R3JvdXBzPzogSVNlY3VyaXR5R3JvdXBbXTtcblxuICAvKipcbiAgICogU3BlY2lmeSB3aGV0aGVyIHRvIGVuYWJsZSB0aGUgc2VsZi1zZXJ2aWNlIHBvcnRhbCBmb3IgdGhlIENsaWVudCBWUE4gZW5kcG9pbnQuXG4gICAqXG4gICAqIEBkZWZhdWx0IHRydWVcbiAgICovXG4gIHJlYWRvbmx5IHNlbGZTZXJ2aWNlUG9ydGFsPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogVGhlIEFSTiBvZiB0aGUgc2VydmVyIGNlcnRpZmljYXRlXG4gICAqL1xuICByZWFkb25seSBzZXJ2ZXJDZXJ0aWZpY2F0ZUFybjogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBJbmRpY2F0ZXMgd2hldGhlciBzcGxpdC10dW5uZWwgaXMgZW5hYmxlZCBvbiB0aGUgQVdTIENsaWVudCBWUE4gZW5kcG9pbnQuXG4gICAqXG4gICAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL3Zwbi9sYXRlc3QvY2xpZW50dnBuLWFkbWluL3NwbGl0LXR1bm5lbC12cG4uaHRtbFxuICAgKlxuICAgKiBAZGVmYXVsdCBmYWxzZVxuICAgKi9cbiAgcmVhZG9ubHkgc3BsaXRUdW5uZWw/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBUaGUgdHJhbnNwb3J0IHByb3RvY29sIHRvIGJlIHVzZWQgYnkgdGhlIFZQTiBzZXNzaW9uLlxuICAgKlxuICAgKiBAZGVmYXVsdCBUcmFuc3BvcnRQcm90b2NvbC5VRFBcbiAgICovXG4gIHJlYWRvbmx5IHRyYW5zcG9ydFByb3RvY29sPzogVHJhbnNwb3J0UHJvdG9jb2w7XG5cbiAgLyoqXG4gICAqIFRoZSBwb3J0IG51bWJlciB0byBhc3NpZ24gdG8gdGhlIENsaWVudCBWUE4gZW5kcG9pbnQgZm9yIFRDUCBhbmQgVURQXG4gICAqIHRyYWZmaWMuXG4gICAqXG4gICAqIEBkZWZhdWx0IFZwblBvcnQuSFRUUFNcbiAgICovXG4gIHJlYWRvbmx5IHBvcnQ/OiBWcG5Qb3J0O1xuXG4gIC8qKlxuICAgKiBJbmZvcm1hdGlvbiBhYm91dCB0aGUgRE5TIHNlcnZlcnMgdG8gYmUgdXNlZCBmb3IgRE5TIHJlc29sdXRpb24uXG4gICAqXG4gICAqIEEgQ2xpZW50IFZQTiBlbmRwb2ludCBjYW4gaGF2ZSB1cCB0byB0d28gRE5TIHNlcnZlcnMuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gdXNlIHRoZSBETlMgYWRkcmVzcyBjb25maWd1cmVkIG9uIHRoZSBkZXZpY2VcbiAgICovXG4gIHJlYWRvbmx5IGRuc1NlcnZlcnM/OiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogU3VibmV0cyB0byBhc3NvY2lhdGUgdG8gdGhlIGNsaWVudCBWUE4gZW5kcG9pbnQuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gdGhlIFZQQyBkZWZhdWx0IHN0cmF0ZWd5XG4gICAqL1xuICByZWFkb25seSB2cGNTdWJuZXRzPzogU3VibmV0U2VsZWN0aW9uO1xuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRvIGF1dGhvcml6ZSBhbGwgdXNlcnMgdG8gdGhlIFZQQyBDSURSXG4gICAqXG4gICAqIFRoaXMgYXV0b21hdGljYWxseSBjcmVhdGVzIGFuIGF1dGhvcml6YXRpb24gcnVsZS4gU2V0IHRoaXMgdG8gYGZhbHNlYCBhbmRcbiAgICogdXNlIGBhZGRBdXRob3JpemF0aW9uUnVsZSgpYCB0byBjcmVhdGUgeW91ciBvd24gcnVsZXMgaW5zdGVhZC5cbiAgICpcbiAgICogQGRlZmF1bHQgdHJ1ZVxuICAgKi9cbiAgcmVhZG9ubHkgYXV0aG9yaXplQWxsVXNlcnNUb1ZwY0NpZHI/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBUaGUgbWF4aW11bSBWUE4gc2Vzc2lvbiBkdXJhdGlvbiB0aW1lLlxuICAgKlxuICAgKiBAZGVmYXVsdCBDbGllbnRWcG5TZXNzaW9uVGltZW91dC5UV0VOVFlfRk9VUl9IT1VSU1xuICAgKi9cbiAgcmVhZG9ubHkgc2Vzc2lvblRpbWVvdXQ/OiBDbGllbnRWcG5TZXNzaW9uVGltZW91dDtcblxuICAvKipcbiAgICogQ3VzdG9taXphYmxlIHRleHQgdGhhdCB3aWxsIGJlIGRpc3BsYXllZCBpbiBhIGJhbm5lciBvbiBBV1MgcHJvdmlkZWQgY2xpZW50c1xuICAgKiB3aGVuIGEgVlBOIHNlc3Npb24gaXMgZXN0YWJsaXNoZWQuXG4gICAqXG4gICAqIFVURi04IGVuY29kZWQgY2hhcmFjdGVycyBvbmx5LiBNYXhpbXVtIG9mIDE0MDAgY2hhcmFjdGVycy5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBubyBiYW5uZXIgaXMgcHJlc2VudGVkIHRvIHRoZSBjbGllbnRcbiAgICovXG4gIHJlYWRvbmx5IGNsaWVudExvZ2luQmFubmVyPzogc3RyaW5nO1xufVxuXG4vKipcbiAqIE1heGltdW0gVlBOIHNlc3Npb24gZHVyYXRpb24gdGltZVxuICovXG5leHBvcnQgZW51bSBDbGllbnRWcG5TZXNzaW9uVGltZW91dCB7XG4gIC8qKiA4IGhvdXJzICovXG4gIEVJR0hUX0hPVVJTID0gOCxcbiAgLyoqIDEwIGhvdXJzICovXG4gIFRFTl9IT1VSUyA9IDEwLFxuICAvKiogMTIgaG91cnMgKi9cbiAgVFdFTFZFX0hPVVJTID0gMTIsXG4gIC8qKiAyNCBob3VycyAqL1xuICBUV0VOVFlfRk9VUl9IT1VSUyA9IDI0LFxufVxuXG4vKipcbiAqIFVzZXItYmFzZWQgYXV0aGVudGljYXRpb24gZm9yIGEgY2xpZW50IFZQTiBlbmRwb2ludFxuICovXG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgQ2xpZW50VnBuVXNlckJhc2VkQXV0aGVudGljYXRpb24ge1xuICAvKipcbiAgICogQWN0aXZlIERpcmVjdG9yeSBhdXRoZW50aWNhdGlvblxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBhY3RpdmVEaXJlY3RvcnkoZGlyZWN0b3J5SWQ6IHN0cmluZyk6IENsaWVudFZwblVzZXJCYXNlZEF1dGhlbnRpY2F0aW9uIHtcbiAgICByZXR1cm4gbmV3IEFjdGl2ZURpcmVjdG9yeUF1dGhlbnRpY2F0aW9uKGRpcmVjdG9yeUlkKTtcbiAgfVxuXG4gIC8qKiBGZWRlcmF0ZWQgYXV0aGVudGljYXRpb24gKi9cbiAgcHVibGljIHN0YXRpYyBmZWRlcmF0ZWQoc2FtbFByb3ZpZGVyOiBJU2FtbFByb3ZpZGVyLCBzZWxmU2VydmljZVNhbWxQcm92aWRlcj86IElTYW1sUHJvdmlkZXIpOiBDbGllbnRWcG5Vc2VyQmFzZWRBdXRoZW50aWNhdGlvbiB7XG4gICAgcmV0dXJuIG5ldyBGZWRlcmF0ZWRBdXRoZW50aWNhdGlvbihzYW1sUHJvdmlkZXIsIHNlbGZTZXJ2aWNlU2FtbFByb3ZpZGVyKTtcbiAgfVxuXG4gIC8qKiBSZW5kZXJzIHRoZSB1c2VyIGJhc2VkIGF1dGhlbnRpY2F0aW9uICovXG4gIHB1YmxpYyBhYnN0cmFjdCByZW5kZXIoKTogYW55O1xufVxuXG4vKipcbiAqIEFjdGl2ZSBEaXJlY3RvcnkgYXV0aGVudGljYXRpb25cbiAqL1xuY2xhc3MgQWN0aXZlRGlyZWN0b3J5QXV0aGVudGljYXRpb24gZXh0ZW5kcyBDbGllbnRWcG5Vc2VyQmFzZWRBdXRoZW50aWNhdGlvbiB7XG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgcmVhZG9ubHkgZGlyZWN0b3J5SWQ6IHN0cmluZykge1xuICAgIHN1cGVyKCk7XG4gIH1cblxuICByZW5kZXIoKTogYW55IHtcbiAgICByZXR1cm4ge1xuICAgICAgdHlwZTogJ2RpcmVjdG9yeS1zZXJ2aWNlLWF1dGhlbnRpY2F0aW9uJyxcbiAgICAgIGFjdGl2ZURpcmVjdG9yeTogeyBkaXJlY3RvcnlJZDogdGhpcy5kaXJlY3RvcnlJZCB9LFxuICAgIH07XG4gIH1cbn1cblxuLyoqXG4gKiBGZWRlcmF0ZWQgYXV0aGVudGljYXRpb25cbiAqL1xuY2xhc3MgRmVkZXJhdGVkQXV0aGVudGljYXRpb24gZXh0ZW5kcyBDbGllbnRWcG5Vc2VyQmFzZWRBdXRoZW50aWNhdGlvbiB7XG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgcmVhZG9ubHkgc2FtbFByb3ZpZGVyOiBJU2FtbFByb3ZpZGVyLCBwcml2YXRlIHJlYWRvbmx5IHNlbGZTZXJ2aWNlU2FtbFByb3ZpZGVyPzogSVNhbWxQcm92aWRlcikge1xuICAgIHN1cGVyKCk7XG4gIH1cblxuICByZW5kZXIoKTogYW55IHtcbiAgICByZXR1cm4ge1xuICAgICAgdHlwZTogJ2ZlZGVyYXRlZC1hdXRoZW50aWNhdGlvbicsXG4gICAgICBmZWRlcmF0ZWRBdXRoZW50aWNhdGlvbjoge1xuICAgICAgICBzYW1sUHJvdmlkZXJBcm46IHRoaXMuc2FtbFByb3ZpZGVyLnNhbWxQcm92aWRlckFybixcbiAgICAgICAgc2VsZlNlcnZpY2VTYW1sUHJvdmlkZXJBcm46IHRoaXMuc2VsZlNlcnZpY2VTYW1sUHJvdmlkZXI/LnNhbWxQcm92aWRlckFybixcbiAgICAgIH0sXG4gICAgfTtcbiAgfVxufVxuXG4vKipcbiAqIFByb3BlcnRpZXMgZm9yIGEgY2xpZW50IFZQTiBlbmRwb2ludFxuICovXG5leHBvcnQgaW50ZXJmYWNlIENsaWVudFZwbkVuZHBvaW50UHJvcHMgZXh0ZW5kcyBDbGllbnRWcG5FbmRwb2ludE9wdGlvbnMge1xuICAvKipcbiAgICogVGhlIFZQQyB0byBjb25uZWN0IHRvLlxuICAgKi9cbiAgcmVhZG9ubHkgdnBjOiBJVnBjO1xufVxuXG4vKipcbiAqIEF0dHJpYnV0ZXMgd2hlbiBpbXBvcnRpbmcgYW4gZXhpc3RpbmcgY2xpZW50IFZQTiBlbmRwb2ludFxuICovXG5leHBvcnQgaW50ZXJmYWNlIENsaWVudFZwbkVuZHBvaW50QXR0cmlidXRlcyB7XG4gIC8qKlxuICAgKiBUaGUgZW5kcG9pbnQgSURcbiAgICovXG4gIHJlYWRvbmx5IGVuZHBvaW50SWQ6IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIHNlY3VyaXR5IGdyb3VwcyBhc3NvY2lhdGVkIHdpdGggdGhlIGVuZHBvaW50XG4gICAqL1xuICByZWFkb25seSBzZWN1cml0eUdyb3VwczogSVNlY3VyaXR5R3JvdXBbXTtcbn1cblxuLyoqXG4gKiBBIGNsaWVudCBWUE4gY29ubm5lY3Rpb25cbiAqL1xuZXhwb3J0IGNsYXNzIENsaWVudFZwbkVuZHBvaW50IGV4dGVuZHMgUmVzb3VyY2UgaW1wbGVtZW50cyBJQ2xpZW50VnBuRW5kcG9pbnQge1xuICAvKipcbiAgICogSW1wb3J0IGFuIGV4aXN0aW5nIGNsaWVudCBWUE4gZW5kcG9pbnRcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgZnJvbUVuZHBvaW50QXR0cmlidXRlcyhzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBhdHRyczogQ2xpZW50VnBuRW5kcG9pbnRBdHRyaWJ1dGVzKTogSUNsaWVudFZwbkVuZHBvaW50IHtcbiAgICBjbGFzcyBJbXBvcnQgZXh0ZW5kcyBSZXNvdXJjZSBpbXBsZW1lbnRzIElDbGllbnRWcG5FbmRwb2ludCB7XG4gICAgICBwdWJsaWMgcmVhZG9ubHkgZW5kcG9pbnRJZCA9IGF0dHJzLmVuZHBvaW50SWQ7XG4gICAgICBwdWJsaWMgcmVhZG9ubHkgY29ubmVjdGlvbnMgPSBuZXcgQ29ubmVjdGlvbnMoeyBzZWN1cml0eUdyb3VwczogYXR0cnMuc2VjdXJpdHlHcm91cHMgfSk7XG4gICAgICBwdWJsaWMgcmVhZG9ubHkgdGFyZ2V0TmV0d29ya3NBc3NvY2lhdGVkOiBJRGVwZW5kYWJsZSA9IG5ldyBDb25jcmV0ZURlcGVuZGFibGUoKTtcbiAgICB9XG4gICAgcmV0dXJuIG5ldyBJbXBvcnQoc2NvcGUsIGlkKTtcbiAgfVxuXG4gIHB1YmxpYyByZWFkb25seSBlbmRwb2ludElkOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEFsbG93cyBzcGVjaWZ5IHNlY3VyaXR5IGdyb3VwIGNvbm5lY3Rpb25zIGZvciB0aGUgZW5kcG9pbnQuXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgY29ubmVjdGlvbnM6IENvbm5lY3Rpb25zO1xuXG4gIHB1YmxpYyByZWFkb25seSB0YXJnZXROZXR3b3Jrc0Fzc29jaWF0ZWQ6IElEZXBlbmRhYmxlO1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgX3RhcmdldE5ldHdvcmtzQXNzb2NpYXRlZCA9IG5ldyBDb25jcmV0ZURlcGVuZGFibGUoKTtcblxuICBjb25zdHJ1Y3RvcihzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBwcm9wczogQ2xpZW50VnBuRW5kcG9pbnRQcm9wcykge1xuICAgIHN1cGVyKHNjb3BlLCBpZCk7XG5cbiAgICBpZiAoIVRva2VuLmlzVW5yZXNvbHZlZChwcm9wcy52cGMudnBjQ2lkckJsb2NrKSkge1xuICAgICAgY29uc3QgY2xpZW50Q2lkciA9IG5ldyBDaWRyQmxvY2socHJvcHMuY2lkcik7XG4gICAgICBjb25zdCB2cGNDaWRyID0gbmV3IENpZHJCbG9jayhwcm9wcy52cGMudnBjQ2lkckJsb2NrKTtcbiAgICAgIGlmICh2cGNDaWRyLmNvbnRhaW5zQ2lkcihjbGllbnRDaWRyKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoZSBjbGllbnQgQ0lEUiBjYW5ub3Qgb3ZlcmxhcCB3aXRoIHRoZSBsb2NhbCBDSURSIG9mIHRoZSBWUEMnKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAocHJvcHMuZG5zU2VydmVycyAmJiBwcm9wcy5kbnNTZXJ2ZXJzLmxlbmd0aCA+IDIpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQSBjbGllbnQgVlBOIGVuZHBvaW50IGNhbiBoYXZlIHVwIHRvIHR3byBETlMgc2VydmVycycpO1xuICAgIH1cblxuICAgIGlmIChwcm9wcy5sb2dnaW5nID09IGZhbHNlICYmIChwcm9wcy5sb2dHcm91cCB8fCBwcm9wcy5sb2dTdHJlYW0pKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCBzcGVjaWZ5IGBsb2dHcm91cGAgb3IgYGxvZ1N0cmVhbWAgd2hlbiBsb2dnaW5nIGlzIGRpc2FibGVkJyk7XG4gICAgfVxuXG4gICAgaWYgKHByb3BzLmNsaWVudENvbm5lY3Rpb25IYW5kbGVyXG4gICAgICAmJiAhVG9rZW4uaXNVbnJlc29sdmVkKHByb3BzLmNsaWVudENvbm5lY3Rpb25IYW5kbGVyLmZ1bmN0aW9uTmFtZSlcbiAgICAgICYmICFwcm9wcy5jbGllbnRDb25uZWN0aW9uSGFuZGxlci5mdW5jdGlvbk5hbWUuc3RhcnRzV2l0aCgnQVdTQ2xpZW50VlBOLScpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoZSBuYW1lIG9mIHRoZSBMYW1iZGEgZnVuY3Rpb24gbXVzdCBiZWdpbiB3aXRoIHRoZSBgQVdTQ2xpZW50VlBOLWAgcHJlZml4Jyk7XG4gICAgfVxuXG4gICAgaWYgKHByb3BzLmNsaWVudExvZ2luQmFubmVyXG4gICAgICAmJiAhVG9rZW4uaXNVbnJlc29sdmVkKHByb3BzLmNsaWVudExvZ2luQmFubmVyKVxuICAgICAgJiYgcHJvcHMuY2xpZW50TG9naW5CYW5uZXIubGVuZ3RoID4gMTQwMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBUaGUgbWF4aW11bSBsZW5ndGggZm9yIHRoZSBjbGllbnQgbG9naW4gYmFubmVyIGlzIDE0MDAsIGdvdCAke3Byb3BzLmNsaWVudExvZ2luQmFubmVyLmxlbmd0aH1gKTtcbiAgICB9XG5cbiAgICBjb25zdCBsb2dnaW5nID0gcHJvcHMubG9nZ2luZyA/PyB0cnVlO1xuICAgIGNvbnN0IGxvZ0dyb3VwID0gbG9nZ2luZ1xuICAgICAgPyBwcm9wcy5sb2dHcm91cCA/PyBuZXcgbG9ncy5Mb2dHcm91cCh0aGlzLCAnTG9nR3JvdXAnKVxuICAgICAgOiB1bmRlZmluZWQ7XG5cbiAgICBjb25zdCBzZWN1cml0eUdyb3VwcyA9IHByb3BzLnNlY3VyaXR5R3JvdXBzID8/IFtuZXcgU2VjdXJpdHlHcm91cCh0aGlzLCAnU2VjdXJpdHlHcm91cCcsIHtcbiAgICAgIHZwYzogcHJvcHMudnBjLFxuICAgIH0pXTtcbiAgICB0aGlzLmNvbm5lY3Rpb25zID0gbmV3IENvbm5lY3Rpb25zKHsgc2VjdXJpdHlHcm91cHMgfSk7XG5cbiAgICBjb25zdCBlbmRwb2ludCA9IG5ldyBDZm5DbGllbnRWcG5FbmRwb2ludCh0aGlzLCAnUmVzb3VyY2UnLCB7XG4gICAgICBhdXRoZW50aWNhdGlvbk9wdGlvbnM6IHJlbmRlckF1dGhlbnRpY2F0aW9uT3B0aW9ucyhwcm9wcy5jbGllbnRDZXJ0aWZpY2F0ZUFybiwgcHJvcHMudXNlckJhc2VkQXV0aGVudGljYXRpb24pLFxuICAgICAgY2xpZW50Q2lkckJsb2NrOiBwcm9wcy5jaWRyLFxuICAgICAgY2xpZW50Q29ubmVjdE9wdGlvbnM6IHByb3BzLmNsaWVudENvbm5lY3Rpb25IYW5kbGVyXG4gICAgICAgID8ge1xuICAgICAgICAgIGVuYWJsZWQ6IHRydWUsXG4gICAgICAgICAgbGFtYmRhRnVuY3Rpb25Bcm46IHByb3BzLmNsaWVudENvbm5lY3Rpb25IYW5kbGVyLmZ1bmN0aW9uQXJuLFxuICAgICAgICB9XG4gICAgICAgIDogdW5kZWZpbmVkLFxuICAgICAgY29ubmVjdGlvbkxvZ09wdGlvbnM6IHtcbiAgICAgICAgZW5hYmxlZDogbG9nZ2luZyxcbiAgICAgICAgY2xvdWR3YXRjaExvZ0dyb3VwOiBsb2dHcm91cD8ubG9nR3JvdXBOYW1lLFxuICAgICAgICBjbG91ZHdhdGNoTG9nU3RyZWFtOiBwcm9wcy5sb2dTdHJlYW0/LmxvZ1N0cmVhbU5hbWUsXG4gICAgICB9LFxuICAgICAgZGVzY3JpcHRpb246IHByb3BzLmRlc2NyaXB0aW9uLFxuICAgICAgZG5zU2VydmVyczogcHJvcHMuZG5zU2VydmVycyxcbiAgICAgIHNlY3VyaXR5R3JvdXBJZHM6IHNlY3VyaXR5R3JvdXBzLm1hcChzID0+IHMuc2VjdXJpdHlHcm91cElkKSxcbiAgICAgIHNlbGZTZXJ2aWNlUG9ydGFsOiBib29sZWFuVG9FbmFibGVkRGlzYWJsZWQocHJvcHMuc2VsZlNlcnZpY2VQb3J0YWwpLFxuICAgICAgc2VydmVyQ2VydGlmaWNhdGVBcm46IHByb3BzLnNlcnZlckNlcnRpZmljYXRlQXJuLFxuICAgICAgc3BsaXRUdW5uZWw6IHByb3BzLnNwbGl0VHVubmVsLFxuICAgICAgdHJhbnNwb3J0UHJvdG9jb2w6IHByb3BzLnRyYW5zcG9ydFByb3RvY29sLFxuICAgICAgdnBjSWQ6IHByb3BzLnZwYy52cGNJZCxcbiAgICAgIHZwblBvcnQ6IHByb3BzLnBvcnQsXG4gICAgICBzZXNzaW9uVGltZW91dEhvdXJzOiBwcm9wcy5zZXNzaW9uVGltZW91dCxcbiAgICAgIGNsaWVudExvZ2luQmFubmVyT3B0aW9uczogcHJvcHMuY2xpZW50TG9naW5CYW5uZXJcbiAgICAgICAgPyB7XG4gICAgICAgICAgZW5hYmxlZDogdHJ1ZSxcbiAgICAgICAgICBiYW5uZXJUZXh0OiBwcm9wcy5jbGllbnRMb2dpbkJhbm5lcixcbiAgICAgICAgfVxuICAgICAgICA6IHVuZGVmaW5lZCxcbiAgICB9KTtcblxuICAgIHRoaXMuZW5kcG9pbnRJZCA9IGVuZHBvaW50LnJlZjtcblxuICAgIGlmIChwcm9wcy51c2VyQmFzZWRBdXRoZW50aWNhdGlvbiAmJiAocHJvcHMuc2VsZlNlcnZpY2VQb3J0YWwgPz8gdHJ1ZSkpIHtcbiAgICAgIC8vIE91dHB1dCBzZWxmLXNlcnZpY2UgcG9ydGFsIFVSTFxuICAgICAgbmV3IENmbk91dHB1dCh0aGlzLCAnU2VsZlNlcnZpY2VQb3J0YWxVcmwnLCB7XG4gICAgICAgIHZhbHVlOiBgaHR0cHM6Ly9zZWxmLXNlcnZpY2UuY2xpZW50dnBuLmFtYXpvbmF3cy5jb20vZW5kcG9pbnRzLyR7dGhpcy5lbmRwb2ludElkfWAsXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvLyBBc3NvY2lhdGUgc3VibmV0c1xuICAgIGNvbnN0IHN1Ym5ldElkcyA9IHByb3BzLnZwYy5zZWxlY3RTdWJuZXRzKHByb3BzLnZwY1N1Ym5ldHMpLnN1Ym5ldElkcztcblxuICAgIGlmIChUb2tlbi5pc1VucmVzb2x2ZWQoc3VibmV0SWRzKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgYXNzb2NpYXRlIHN1Ym5ldHMgd2hlbiBWUEMgYXJlIGltcG9ydGVkIGZyb20gcGFyYW1ldGVycyBvciBleHBvcnRzIGNvbnRhaW5pbmcgbGlzdHMgb2Ygc3VibmV0IElEcy4nKTtcbiAgICB9XG5cbiAgICBmb3IgKGNvbnN0IFtpZHgsIHN1Ym5ldElkXSBvZiBPYmplY3QuZW50cmllcyhzdWJuZXRJZHMpKSB7XG4gICAgICB0aGlzLl90YXJnZXROZXR3b3Jrc0Fzc29jaWF0ZWQuYWRkKG5ldyBDZm5DbGllbnRWcG5UYXJnZXROZXR3b3JrQXNzb2NpYXRpb24odGhpcywgYEFzc29jaWF0aW9uJHtpZHh9YCwge1xuICAgICAgICBjbGllbnRWcG5FbmRwb2ludElkOiB0aGlzLmVuZHBvaW50SWQsXG4gICAgICAgIHN1Ym5ldElkLFxuICAgICAgfSkpO1xuICAgIH1cbiAgICB0aGlzLnRhcmdldE5ldHdvcmtzQXNzb2NpYXRlZCA9IHRoaXMuX3RhcmdldE5ldHdvcmtzQXNzb2NpYXRlZDtcblxuICAgIGlmIChwcm9wcy5hdXRob3JpemVBbGxVc2Vyc1RvVnBjQ2lkciA/PyB0cnVlKSB7XG4gICAgICB0aGlzLmFkZEF1dGhvcml6YXRpb25SdWxlKCdBdXRob3JpemVBbGwnLCB7XG4gICAgICAgIGNpZHI6IHByb3BzLnZwYy52cGNDaWRyQmxvY2ssXG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQWRkcyBhbiBhdXRob3JpemF0aW9uIHJ1bGUgdG8gdGhpcyBlbmRwb2ludFxuICAgKi9cbiAgcHVibGljIGFkZEF1dGhvcml6YXRpb25SdWxlKGlkOiBzdHJpbmcsIHByb3BzOiBDbGllbnRWcG5BdXRob3JpemF0aW9uUnVsZU9wdGlvbnMpOiBDbGllbnRWcG5BdXRob3JpemF0aW9uUnVsZSB7XG4gICAgcmV0dXJuIG5ldyBDbGllbnRWcG5BdXRob3JpemF0aW9uUnVsZSh0aGlzLCBpZCwge1xuICAgICAgLi4ucHJvcHMsXG4gICAgICBjbGllbnRWcG5FbmRwb2ludDogdGhpcyxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGRzIGEgcm91dGUgdG8gdGhpcyBlbmRwb2ludFxuICAgKi9cbiAgcHVibGljIGFkZFJvdXRlKGlkOiBzdHJpbmcsIHByb3BzOiBDbGllbnRWcG5Sb3V0ZU9wdGlvbnMpOiBDbGllbnRWcG5Sb3V0ZSB7XG4gICAgcmV0dXJuIG5ldyBDbGllbnRWcG5Sb3V0ZSh0aGlzLCBpZCwge1xuICAgICAgLi4ucHJvcHMsXG4gICAgICBjbGllbnRWcG5FbmRwb2ludDogdGhpcyxcbiAgICB9KTtcbiAgfVxufVxuXG5mdW5jdGlvbiByZW5kZXJBdXRoZW50aWNhdGlvbk9wdGlvbnMoXG4gIGNsaWVudENlcnRpZmljYXRlQXJuPzogc3RyaW5nLFxuICB1c2VyQmFzZWRBdXRoZW50aWNhdGlvbj86IENsaWVudFZwblVzZXJCYXNlZEF1dGhlbnRpY2F0aW9uKTogQ2ZuQ2xpZW50VnBuRW5kcG9pbnQuQ2xpZW50QXV0aGVudGljYXRpb25SZXF1ZXN0UHJvcGVydHlbXSB7XG4gIGNvbnN0IGF1dGhlbnRpY2F0aW9uT3B0aW9uczogQ2ZuQ2xpZW50VnBuRW5kcG9pbnQuQ2xpZW50QXV0aGVudGljYXRpb25SZXF1ZXN0UHJvcGVydHlbXSA9IFtdO1xuXG4gIGlmIChjbGllbnRDZXJ0aWZpY2F0ZUFybikge1xuICAgIGF1dGhlbnRpY2F0aW9uT3B0aW9ucy5wdXNoKHtcbiAgICAgIHR5cGU6ICdjZXJ0aWZpY2F0ZS1hdXRoZW50aWNhdGlvbicsXG4gICAgICBtdXR1YWxBdXRoZW50aWNhdGlvbjoge1xuICAgICAgICBjbGllbnRSb290Q2VydGlmaWNhdGVDaGFpbkFybjogY2xpZW50Q2VydGlmaWNhdGVBcm4sXG4gICAgICB9LFxuICAgIH0pO1xuICB9XG5cbiAgaWYgKHVzZXJCYXNlZEF1dGhlbnRpY2F0aW9uKSB7XG4gICAgYXV0aGVudGljYXRpb25PcHRpb25zLnB1c2godXNlckJhc2VkQXV0aGVudGljYXRpb24ucmVuZGVyKCkpO1xuICB9XG5cbiAgaWYgKGF1dGhlbnRpY2F0aW9uT3B0aW9ucy5sZW5ndGggPT09IDApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0EgY2xpZW50IFZQTiBlbmRwb2ludCBtdXN0IHVzZSBhdCBsZWFzdCBvbmUgYXV0aGVudGljYXRpb24gb3B0aW9uJyk7XG4gIH1cbiAgcmV0dXJuIGF1dGhlbnRpY2F0aW9uT3B0aW9ucztcbn1cblxuZnVuY3Rpb24gYm9vbGVhblRvRW5hYmxlZERpc2FibGVkKHZhbD86IGJvb2xlYW4pOiAnZW5hYmxlZCcgfCAnZGlzYWJsZWQnIHwgdW5kZWZpbmVkIHtcbiAgc3dpdGNoICh2YWwpIHtcbiAgICBjYXNlIHVuZGVmaW5lZDpcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgY2FzZSB0cnVlOlxuICAgICAgcmV0dXJuICdlbmFibGVkJztcbiAgICBjYXNlIGZhbHNlOlxuICAgICAgcmV0dXJuICdkaXNhYmxlZCc7XG4gIH1cbn1cbiJdfQ==