@gammarers/aws-transfer-custom-lambda-identity-provider 1.0.2 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.jsii CHANGED
@@ -3471,7 +3471,7 @@
3471
3471
  },
3472
3472
  "name": "@gammarers/aws-transfer-custom-lambda-identity-provider",
3473
3473
  "readme": {
3474
- "markdown": "# AWS Transfer Custom Lambda Identity Provider\n\n[![GitHub](https://img.shields.io/github/license/gammarers/aws-transfer-custom-lambda-identity-provider?style=flat-square)](https://github.com/gammarers/aws-transfer-custom-lambda-identity-provider/blob/main/LICENSE)\n[![npm (scoped)](https://img.shields.io/npm/v/@gammarers/aws-transfer-custom-lambda-identity-provider?style=flat-square)](https://www.npmjs.com/package/@gammarers/aws-transfer-custom-lambda-identity-provider)\n[![GitHub Workflow Status (branch)](https://img.shields.io/github/actions/workflow/status/gammarers/aws-transfer-custom-lambda-identity-provider/release.yml?branch=main&label=release&style=flat-square)](https://github.com/gammarers/aws-transfer-custom-lambda-identity-provider/actions/workflows/release.yml)\n[![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/gammarers/aws-transfer-custom-lambda-identity-provider?sort=semver&style=flat-square)](https://github.com/gammarers/aws-transfer-custom-lambda-identity-provider/releases)\n\nThis is a Simple Transfer AWS CDK Construct\n\n## Features\n\n- [x] SFTP User password login (inclued ip restrict)\n - [x] testing implementetion\n - [ ] ested in an actual AWS environment\n- [x] SFTP User password login (none ip restrict)\n - [ ] testing implementetion\n - [ ] ested in an actual AWS environment\n- [x] SFTP User public key authentication login (inclued ip restrict)\n - [x] testing implementetion\n - [ ] ested in an actual AWS environment\n- [x] SFTP User public key authentication login (none ip restrict)\n - [ ] testing implementetion\n - [ ] ested in an actual AWS environment\n- [x] SFTP User's info from AWS SecretManager\n - [x] SecureString\n - [x] testing implementetion\n - [ ] ested in an actual AWS environment\n - [x] SecureBinary\n - [ ] testing implementetion\n - [ ] ested in an actual AWS environment\n- [x] FTP/S User's password login (inclued ip restrict)\n - [x] testing implementetion\n - [ ] ested in an actual AWS environment\n- [ ] HomeDirectoryDetails\n\n### Other\n\n- [ ] SecretManager layer\n- [ ] Logging to JSON\n- [ ] disable output log in projen test\n\n## Architecture\n\ndiagram\n\n## Install\n\n### TypeScript\n\n```shell\nnpm install @gammarers/transfer-custom-lambda-identity-provider\n```\nor\n```shell\nyarn add @gammarers/transfer-custom-lambda-identity-provider\n```\n\n## Example\n\n```shell\nnpm install @gammarers/transfer-custom-lambda-identity-provider\n```\n\n```typescript\nimport { TransferCustomLambdaIdentityProvider } from '@gammarers/aws-transfer-custom-lambda-identity-provider';\n\nnew TransferCustomLambdaIdentityProvider(stack, 'TransferCustomLambdaIdentityProvider');\n\n```\n"
3474
+ "markdown": "# AWS Transfer Custom Lambda Identity Provider\n\n[![GitHub](https://img.shields.io/github/license/gammarers/aws-transfer-custom-lambda-identity-provider?style=flat-square)](https://github.com/gammarers/aws-transfer-custom-lambda-identity-provider/blob/main/LICENSE)\n[![npm (scoped)](https://img.shields.io/npm/v/@gammarers/aws-transfer-custom-lambda-identity-provider?style=flat-square)](https://www.npmjs.com/package/@gammarers/aws-transfer-custom-lambda-identity-provider)\n[![GitHub Workflow Status (branch)](https://img.shields.io/github/actions/workflow/status/gammarers/aws-transfer-custom-lambda-identity-provider/release.yml?branch=main&label=release&style=flat-square)](https://github.com/gammarers/aws-transfer-custom-lambda-identity-provider/actions/workflows/release.yml)\n[![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/gammarers/aws-transfer-custom-lambda-identity-provider?sort=semver&style=flat-square)](https://github.com/gammarers/aws-transfer-custom-lambda-identity-provider/releases)\n\nThis is a Simple Transfer AWS CDK Construct\n\n## Features\n\n- [x] SFTP User password login (inclued ip restrict(ipv4,ipv6))\n - [x] testing implementetion\n - [ ] ested in an actual AWS environment\n- [x] SFTP User password login (none ip restrict)\n - [x] testing implementetion\n - [ ] ested in an actual AWS environment\n- [x] SFTP User public key authentication login (inclued ip restrict)\n - [x] testing implementetion\n - [ ] ested in an actual AWS environment\n- [x] SFTP User public key authentication login (none ip restrict)\n - [x] testing implementetion\n - [ ] ested in an actual AWS environment\n- [x] SFTP User's info from AWS SecretManager\n - [x] SecureString\n - [x] testing implementetion\n - [ ] ested in an actual AWS environment\n - [x] SecureBinary\n - [x] testing implementetion\n - [ ] ested in an actual AWS environment\n- [x] FTP/S User's password login (inclued ip restrict)\n - [x] testing implementetion\n - [ ] ested in an actual AWS environment\n- [x] HomeDirectoryDetails\n - [x] Logical home directory\n - [x] testing implementetion\n - [ ] ested in an actual AWS environment\n\n### Other\n\n- [ ] SecretManager layer\n- [ ] Logging to JSON\n- [x] disable output log in projen test\n\n## Architecture\n\ndiagram\n\n## Install\n\n### TypeScript\n\n```shell\nnpm install @gammarers/transfer-custom-lambda-identity-provider\n```\nor\n```shell\nyarn add @gammarers/transfer-custom-lambda-identity-provider\n```\n\n## Example\n\n```shell\nnpm install @gammarers/transfer-custom-lambda-identity-provider\n```\n\n```typescript\nimport { TransferCustomLambdaIdentityProvider } from '@gammarers/aws-transfer-custom-lambda-identity-provider';\n\nnew TransferCustomLambdaIdentityProvider(stack, 'TransferCustomLambdaIdentityProvider');\n\n```\n"
3475
3475
  },
3476
3476
  "repository": {
3477
3477
  "type": "git",
@@ -3523,6 +3523,6 @@
3523
3523
  "symbolId": "src/index:TransferCustomLambdaIdentityProvider"
3524
3524
  }
3525
3525
  },
3526
- "version": "1.0.2",
3527
- "fingerprint": "PjHiQb3gPLoaj4MMbLmP7xOurh9Ynyd/222vWwfcJ4c="
3526
+ "version": "1.1.0",
3527
+ "fingerprint": "dkJh+4S7+QLYViEH+w/35BfANkf6Oi8lxAjVBiUhLVE="
3528
3528
  }
package/README.md CHANGED
@@ -9,35 +9,38 @@ This is a Simple Transfer AWS CDK Construct
9
9
 
10
10
  ## Features
11
11
 
12
- - [x] SFTP User password login (inclued ip restrict)
12
+ - [x] SFTP User password login (inclued ip restrict(ipv4,ipv6))
13
13
  - [x] testing implementetion
14
14
  - [ ] ested in an actual AWS environment
15
15
  - [x] SFTP User password login (none ip restrict)
16
- - [ ] testing implementetion
16
+ - [x] testing implementetion
17
17
  - [ ] ested in an actual AWS environment
18
18
  - [x] SFTP User public key authentication login (inclued ip restrict)
19
19
  - [x] testing implementetion
20
20
  - [ ] ested in an actual AWS environment
21
21
  - [x] SFTP User public key authentication login (none ip restrict)
22
- - [ ] testing implementetion
22
+ - [x] testing implementetion
23
23
  - [ ] ested in an actual AWS environment
24
24
  - [x] SFTP User's info from AWS SecretManager
25
25
  - [x] SecureString
26
26
  - [x] testing implementetion
27
27
  - [ ] ested in an actual AWS environment
28
28
  - [x] SecureBinary
29
- - [ ] testing implementetion
29
+ - [x] testing implementetion
30
30
  - [ ] ested in an actual AWS environment
31
31
  - [x] FTP/S User's password login (inclued ip restrict)
32
32
  - [x] testing implementetion
33
33
  - [ ] ested in an actual AWS environment
34
- - [ ] HomeDirectoryDetails
34
+ - [x] HomeDirectoryDetails
35
+ - [x] Logical home directory
36
+ - [x] testing implementetion
37
+ - [ ] ested in an actual AWS environment
35
38
 
36
39
  ### Other
37
40
 
38
41
  - [ ] SecretManager layer
39
42
  - [ ] Logging to JSON
40
- - [ ] disable output log in projen test
43
+ - [x] disable output log in projen test
41
44
 
42
45
  ## Architecture
43
46
 
@@ -20,10 +20,17 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/funcs/transfer-user-authentication.lambda.ts
21
21
  var transfer_user_authentication_lambda_exports = {};
22
22
  __export(transfer_user_authentication_lambda_exports, {
23
+ EmptySecretValueError: () => EmptySecretValueError,
23
24
  handler: () => handler
24
25
  });
25
26
  module.exports = __toCommonJS(transfer_user_authentication_lambda_exports);
26
27
  var import_client_secrets_manager = require("@aws-sdk/client-secrets-manager");
28
+ var EmptySecretValueError = class extends Error {
29
+ constructor() {
30
+ super("Got a secret value is empty.");
31
+ this.name = "EmptySecretValueError";
32
+ }
33
+ };
27
34
  var handler = async (event) => {
28
35
  const requiredParamList = ["serverId", "username", "protocol", "sourceIp"];
29
36
  for (const parameter of requiredParamList) {
@@ -49,12 +56,18 @@ var handler = async (event) => {
49
56
  return {};
50
57
  }
51
58
  console.log("Using SSH authentication");
52
- authenticationType = "SSH";
59
+ authenticationType = "SSHPubKey";
53
60
  }
54
61
  const secret = await getSecret(`transfer-user/${inputServerId}/${inputUsername}`);
55
62
  if (secret) {
56
63
  const secretDict = JSON.parse(secret);
57
- const userAuthenticated = authenticateUser(authenticationType, secretDict, inputPassword, inputProtocol);
64
+ const userAuthenticated = (() => {
65
+ if (authenticationType === "SSHPubKey") {
66
+ console.log("Skip password check as SSH login request");
67
+ return true;
68
+ }
69
+ return authenticatePasswordUser(secretDict, inputPassword, inputProtocol);
70
+ })();
58
71
  const ipMatch = checkIpAddress(secretDict, inputSourceIp, inputProtocol);
59
72
  if (userAuthenticated && ipMatch) {
60
73
  console.log(`User authenticated, calling buildResponse with: ${authenticationType}`);
@@ -77,13 +90,14 @@ var lookup = (secretDict, key, inputProtocol) => {
77
90
  }
78
91
  };
79
92
  var checkIpAddress = (secretDict, inputSourceIp, inputProtocol) => {
80
- const acceptedIpNetworkList = lookup(secretDict, "AcceptedIpNetworkList", inputProtocol);
81
- if (!acceptedIpNetworkList) {
82
- console.log("No IP range provided - Skip IP check");
83
- return true;
84
- }
85
- for (const acceptedIpNetwork of acceptedIpNetworkList.split(",")) {
86
- if (isIpInCidr(inputSourceIp, acceptedIpNetwork)) {
93
+ const acceptedIpNetworks = lookup(secretDict, "AcceptedIpNetworks", inputProtocol);
94
+ console.log(`AcceptedIpNetworks: ${acceptedIpNetworks}`);
95
+ if (!acceptedIpNetworks) {
96
+ console.log("Unable to authenticate user - No filed match in Secret for AcceptedIpNetworks(CIDR format, comma-separated)");
97
+ return false;
98
+ }
99
+ for (const cidr of acceptedIpNetworks.split(",")) {
100
+ if (isIpInCidr(inputSourceIp, cidr)) {
87
101
  console.log("Source IP address match");
88
102
  return true;
89
103
  }
@@ -91,22 +105,17 @@ var checkIpAddress = (secretDict, inputSourceIp, inputProtocol) => {
91
105
  console.log("Source IP address not in range");
92
106
  return false;
93
107
  };
94
- var authenticateUser = (authType, secretDict, inputPassword, inputProtocol) => {
95
- if (authType === "SSH") {
96
- console.log("Skip password check as SSH login request");
108
+ var authenticatePasswordUser = (secretDict, inputPassword, inputProtocol) => {
109
+ const password = lookup(secretDict, "Password", inputProtocol);
110
+ if (!password) {
111
+ console.log("Unable to authenticate user - No field match in Secret for password");
112
+ return false;
113
+ }
114
+ if (inputPassword === password) {
97
115
  return true;
98
116
  } else {
99
- const password = lookup(secretDict, "Password", inputProtocol);
100
- if (!password) {
101
- console.log("Unable to authenticate user - No field match in Secret for password");
102
- return false;
103
- }
104
- if (inputPassword === password) {
105
- return true;
106
- } else {
107
- console.log("Unable to authenticate user - Incoming password does not match stored");
108
- return false;
109
- }
117
+ console.log("Unable to authenticate user - Incoming password does not match stored");
118
+ return false;
110
119
  }
111
120
  };
112
121
  var buildResponse = (secretDict, authType, inputProtocol) => {
@@ -134,7 +143,7 @@ var buildResponse = (secretDict, authType, inputProtocol) => {
134
143
  console.log("HomeDirectory found - Note: Cannot be used in conjunction with key: HomeDirectoryDetails");
135
144
  responseData.HomeDirectory = homeDirectory;
136
145
  }
137
- if (authType === "SSH") {
146
+ if (authType === "SSHPubKey") {
138
147
  const publicKey = lookup(secretDict, "PublicKey", inputProtocol);
139
148
  if (publicKey) {
140
149
  responseData.PublicKeys = [publicKey];
@@ -150,22 +159,20 @@ var getSecret = async (id) => {
150
159
  const client = new import_client_secrets_manager.SecretsManagerClient({
151
160
  region: "ap-northeast-1"
152
161
  });
153
- const command = new import_client_secrets_manager.GetSecretValueCommand({ SecretId: id });
154
- try {
155
- const data = await client.send(command);
156
- console.log(data);
162
+ return client.send(new import_client_secrets_manager.GetSecretValueCommand({ SecretId: id })).then((data) => {
163
+ if (data.SecretBinary) {
164
+ console.log("Got SecretBinary value");
165
+ return Buffer.from(data.SecretBinary).toString("utf-8");
166
+ }
157
167
  if (data.SecretString) {
168
+ console.log("Got SecretString value");
158
169
  return data.SecretString;
159
170
  }
160
- if (data.SecretBinary) {
161
- return new TextDecoder().decode(data.SecretBinary);
162
- }
163
- return null;
164
- } catch (error) {
165
- console.log("Not found Secret");
166
- console.log(`Error: ${JSON.stringify(error)}`);
171
+ throw new EmptySecretValueError();
172
+ }).catch((error) => {
173
+ console.warn(error.message);
167
174
  return null;
168
- }
175
+ });
169
176
  };
170
177
  var ipToBigInt = (address) => {
171
178
  if (address.includes(":")) {
@@ -184,29 +191,25 @@ var ipToBigInt = (address) => {
184
191
  return bigInt;
185
192
  }
186
193
  };
187
- var getSubnetMask = (bits, isIPv6 = false) => {
188
- let mask = BigInt(0);
189
- const totalBits = isIPv6 ? 128 : 32;
190
- for (let i = 0; i < bits; i++) {
191
- mask = mask * BigInt(2) + BigInt(1);
192
- }
193
- for (let i = bits; i < totalBits; i++) {
194
- mask = mask * BigInt(2);
195
- }
196
- return mask;
197
- };
198
- var isIpInCidr = (address, cidr) => {
194
+ var getSubnetRange = (cidr) => {
199
195
  const [network, bits] = cidr.split("/");
200
196
  const isIPv6 = network.includes(":");
201
- const ipBigInt = ipToBigInt(address);
197
+ const totalBits = isIPv6 ? 128 : 32;
202
198
  const networkBigInt = ipToBigInt(network);
203
- const mask = getSubnetMask(parseInt(bits), isIPv6);
204
- const maskedIp = ipBigInt - ipBigInt % (mask + BigInt(1));
205
- const maskedNetwork = networkBigInt - networkBigInt % (mask + BigInt(1));
206
- return maskedIp === maskedNetwork;
199
+ const hostBits = totalBits - parseInt(bits, 10);
200
+ const subnetSize = BigInt(2) ** BigInt(hostBits);
201
+ const start = networkBigInt - networkBigInt % subnetSize;
202
+ const end = start + subnetSize - BigInt(1);
203
+ return { start, end };
204
+ };
205
+ var isIpInCidr = (ipAddr, cidr) => {
206
+ const ipBigInt = ipToBigInt(ipAddr);
207
+ const { start, end } = getSubnetRange(cidr);
208
+ return ipBigInt >= start && ipBigInt <= end;
207
209
  };
208
210
  // Annotate the CommonJS export names for ESM import in node:
209
211
  0 && (module.exports = {
212
+ EmptySecretValueError,
210
213
  handler
211
214
  });
212
215
  //# sourceMappingURL=index.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/funcs/transfer-user-authentication.lambda.ts"],
4
- "sourcesContent": ["import { SecretsManagerClient, GetSecretValueCommand, GetSecretValueCommandOutput } from '@aws-sdk/client-secrets-manager';\nimport { TransferFamilyAuthorizerEvent, TransferFamilyAuthorizerResult } from 'aws-lambda';\n\ninterface SecretDict {\n [key: string]: string;\n}\n\nexport const handler = async (event: TransferFamilyAuthorizerEvent): Promise<TransferFamilyAuthorizerResult> => {\n const requiredParamList = ['serverId', 'username', 'protocol', 'sourceIp'];\n for (const parameter of requiredParamList) {\n if (!event.hasOwnProperty(parameter)) {\n console.log(`Incoming ${parameter} missing - Unexpected`);\n return {};\n }\n }\n\n const inputServerId = event.serverId;\n const inputUsername = event.username;\n const inputProtocol = event.protocol;\n const inputSourceIp = event.sourceIp;\n const inputPassword = event.password || '';\n\n console.log(`ServerId: ${inputServerId}, Username: ${inputUsername}, Protocol: ${inputProtocol}, SourceIp: ${inputSourceIp}`);\n\n console.log('Start User Authentication Flow');\n let authenticationType = '';\n if (inputPassword !== '') {\n console.log('Using PASSWORD authentication');\n authenticationType = 'PASSWORD';\n } else {\n if (inputProtocol === 'FTP' || inputProtocol === 'FTPS') {\n console.log('Empty password not allowed for FTP/S');\n return {};\n }\n console.log('Using SSH authentication');\n authenticationType = 'SSH';\n }\n\n const secret = await getSecret(`transfer-user/${inputServerId}/${inputUsername}`);\n\n if (secret) {\n const secretDict = JSON.parse(secret) as SecretDict;\n const userAuthenticated = authenticateUser(authenticationType, secretDict, inputPassword, inputProtocol);\n const ipMatch = checkIpAddress(secretDict, inputSourceIp, inputProtocol);\n\n if (userAuthenticated && ipMatch) {\n console.log(`User authenticated, calling buildResponse with: ${authenticationType}`);\n return buildResponse(secretDict, authenticationType, inputProtocol);\n } else {\n console.log('User failed authentication return empty response');\n return {};\n }\n } else {\n console.log('Secrets Manager exception thrown - Returning empty response');\n return {};\n }\n};\n\nconst lookup = (secretDict: SecretDict, key: string, inputProtocol: string): string | null => {\n if (secretDict[`${inputProtocol}${key}`]) {\n console.log(`Found protocol-specified ${key}`);\n return secretDict[`${inputProtocol}${key}`];\n } else {\n return secretDict[key] || null;\n }\n};\n\nconst checkIpAddress = (secretDict: SecretDict, inputSourceIp: string, inputProtocol: string): boolean => {\n const acceptedIpNetworkList = lookup(secretDict, 'AcceptedIpNetworkList', inputProtocol);\n if (!acceptedIpNetworkList) {\n console.log('No IP range provided - Skip IP check');\n return true;\n }\n\n for (const acceptedIpNetwork of acceptedIpNetworkList.split(',')) {\n if (isIpInCidr(inputSourceIp, acceptedIpNetwork)) {\n console.log('Source IP address match');\n return true;\n }\n }\n // if (new CIDRMatcher(acceptedIpNetworkList.split(',')).contains(inputSourceIp)) {\n // console.log('Source IP address match');\n // return true;\n // }\n\n console.log('Source IP address not in range');\n return false;\n};\n\nconst authenticateUser = (authType: string, secretDict: SecretDict, inputPassword: string, inputProtocol: string): boolean => {\n if (authType === 'SSH') {\n console.log('Skip password check as SSH login request');\n return true;\n } else {\n const password = lookup(secretDict, 'Password', inputProtocol);\n if (!password) {\n console.log('Unable to authenticate user - No field match in Secret for password');\n return false;\n }\n\n if (inputPassword === password) {\n return true;\n } else {\n console.log('Unable to authenticate user - Incoming password does not match stored');\n return false;\n }\n }\n};\n\nconst buildResponse = (secretDict: SecretDict, authType: string, inputProtocol: string): TransferFamilyAuthorizerResult => {\n const responseData: TransferFamilyAuthorizerResult = {};\n\n const role = lookup(secretDict, 'Role', inputProtocol);\n if (role) {\n responseData.Role = role;\n } else {\n console.log('No field match for role - Set empty string in response');\n responseData.Role = '';\n }\n\n const policy = lookup(secretDict, 'Policy', inputProtocol);\n if (policy) {\n responseData.Policy = policy;\n }\n\n const homeDirectoryDetails = lookup(secretDict, 'HomeDirectoryDetails', inputProtocol);\n if (homeDirectoryDetails) {\n console.log('HomeDirectoryDetails found - Applying setting for virtual folders - Note: Cannot be used in conjunction with key: HomeDirectory');\n responseData.HomeDirectoryDetails = homeDirectoryDetails;\n console.log('Setting HomeDirectoryType to LOGICAL');\n responseData.HomeDirectoryType = 'LOGICAL';\n }\n\n const homeDirectory = lookup(secretDict, 'HomeDirectory', inputProtocol);\n if (homeDirectory) {\n console.log('HomeDirectory found - Note: Cannot be used in conjunction with key: HomeDirectoryDetails');\n responseData.HomeDirectory = homeDirectory;\n }\n\n if (authType === 'SSH') {\n const publicKey = lookup(secretDict, 'PublicKey', inputProtocol);\n if (publicKey) {\n responseData.PublicKeys = [publicKey];\n } else {\n console.log('Unable to authenticate user - No public keys found');\n return {};\n }\n }\n\n return responseData;\n};\n\nconst getSecret = async (id: string): Promise<string | null> => {\n console.log(`Secret Name: ${id}`);\n\n const client = new SecretsManagerClient({\n region: 'ap-northeast-1',\n });\n const command = new GetSecretValueCommand({ SecretId: id });\n\n try {\n const data: GetSecretValueCommandOutput = await client.send(command);\n console.log(data);\n if (data.SecretString) {\n return data.SecretString;\n }\n if (data.SecretBinary) {\n return new TextDecoder().decode(data.SecretBinary);\n }\n return null;\n } catch (error) {\n console.log('Not found Secret');\n console.log(`Error: ${JSON.stringify(error)}`);\n return null;\n }\n //const resp = await client.send(command);\n// return client.send(command)\n// .then((data: GetSecretValueCommandOutput) => {\n// if (data?.SecretString) {\n// return data.SecretString;\n// }\n// if (data?.SecretBinary) {\n// return new TextDecoder().decode(data.SecretBinary);\n// }\n// return null;\n// })\n// .catch((error: Error) => {\n// console.log('Not found Secret');\n// console.log(`Error:${JSON.stringify(error)}`);\n// return null;\n// });\n// console.log(resp);\n// if (resp.SecretString) {\n// console.log('Found Secret String');\n// return resp.SecretString;\n// } else {\n// if (resp.SecretBinary) {\n// console.log('Found Binary Secret');\n// //return Buffer.from(resp.SecretBinary as string, 'base64').toString('ascii');\n// return new TextDecoder().decode(resp.SecretBinary);\n// }\n// }\n//\n// console.log('Not found Secret');\n// return null;\n};\n\nconst ipToBigInt = (address: string) => {\n if (address.includes(':')) {\n // IPv6\n let parts = address.split(':').map(part => part === '' ? '0' : part);\n let bigInt = BigInt(0);\n for (let i = 0; i < parts.length; i++) {\n bigInt = bigInt * BigInt(0x10000) + BigInt(parseInt(parts[i], 16));\n }\n return bigInt;\n } else {\n // IPv4\n let parts = address.split('.').map(part => parseInt(part, 10));\n let bigInt = BigInt(0);\n for (let i = 0; i < parts.length; i++) {\n bigInt = bigInt * BigInt(256) + BigInt(parts[i]);\n }\n return bigInt;\n }\n};\n\nconst getSubnetMask = (bits: number, isIPv6 = false) => {\n let mask = BigInt(0);\n const totalBits = isIPv6 ? 128 : 32;\n for (let i = 0; i < bits; i++) {\n mask = mask * BigInt(2) + BigInt(1);\n }\n for (let i = bits; i < totalBits; i++) {\n mask = mask * BigInt(2);\n }\n return mask;\n};\n\nconst isIpInCidr = (address: string, cidr: string) => {\n const [network, bits] = cidr.split('/');\n const isIPv6 = network.includes(':');\n const ipBigInt = ipToBigInt(address);\n const networkBigInt = ipToBigInt(network);\n const mask = getSubnetMask(parseInt(bits), isIPv6);\n\n const maskedIp = ipBigInt - (ipBigInt % (mask + BigInt(1)));\n const maskedNetwork = networkBigInt - (networkBigInt % (mask + BigInt(1)));\n\n return maskedIp === maskedNetwork;\n};"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { SecretsManagerClient, GetSecretValueCommand, GetSecretValueCommandOutput } from '@aws-sdk/client-secrets-manager';\nimport { TransferFamilyAuthorizerEvent, TransferFamilyAuthorizerResult } from 'aws-lambda';\n\nexport class EmptySecretValueError extends Error {\n constructor() {\n super('Got a secret value is empty.');\n this.name = 'EmptySecretValueError';\n }\n}\n\ninterface SecretDict {\n [key: string]: string;\n}\n\nexport const handler = async (event: TransferFamilyAuthorizerEvent): Promise<TransferFamilyAuthorizerResult> => {\n const requiredParamList = ['serverId', 'username', 'protocol', 'sourceIp'];\n for (const parameter of requiredParamList) {\n if (!event.hasOwnProperty(parameter)) {\n console.log(`Incoming ${parameter} missing - Unexpected`);\n return {};\n }\n }\n\n const inputServerId = event.serverId;\n const inputUsername = event.username;\n const inputProtocol = event.protocol;\n const inputSourceIp = event.sourceIp;\n const inputPassword = event.password || '';\n\n console.log(`ServerId: ${inputServerId}, Username: ${inputUsername}, Protocol: ${inputProtocol}, SourceIp: ${inputSourceIp}`);\n\n console.log('Start User Authentication Flow');\n let authenticationType = '';\n if (inputPassword !== '') {\n console.log('Using PASSWORD authentication');\n authenticationType = 'PASSWORD';\n } else {\n if (inputProtocol === 'FTP' || inputProtocol === 'FTPS') {\n console.log('Empty password not allowed for FTP/S');\n return {};\n }\n console.log('Using SSH authentication');\n authenticationType = 'SSHPubKey';\n }\n\n const secret = await getSecret(`transfer-user/${inputServerId}/${inputUsername}`);\n\n if (secret) {\n const secretDict = JSON.parse(secret) as SecretDict;\n const userAuthenticated = (() => {\n if (authenticationType === 'SSHPubKey') {\n console.log('Skip password check as SSH login request');\n return true;\n }\n return authenticatePasswordUser(secretDict, inputPassword, inputProtocol);\n })();\n const ipMatch = checkIpAddress(secretDict, inputSourceIp, inputProtocol);\n\n if (userAuthenticated && ipMatch) {\n console.log(`User authenticated, calling buildResponse with: ${authenticationType}`);\n return buildResponse(secretDict, authenticationType, inputProtocol);\n } else {\n console.log('User failed authentication return empty response');\n return {};\n }\n } else {\n console.log('Secrets Manager exception thrown - Returning empty response');\n return {};\n }\n};\n\nconst lookup = (secretDict: SecretDict, key: string, inputProtocol: string): string | null => {\n if (secretDict[`${inputProtocol}${key}`]) {\n console.log(`Found protocol-specified ${key}`);\n return secretDict[`${inputProtocol}${key}`];\n } else {\n return secretDict[key] || null;\n }\n};\n\nconst checkIpAddress = (secretDict: SecretDict, inputSourceIp: string, inputProtocol: string): boolean => {\n const acceptedIpNetworks = lookup(secretDict, 'AcceptedIpNetworks', inputProtocol);\n console.log(`AcceptedIpNetworks: ${acceptedIpNetworks}`);\n if (!acceptedIpNetworks) {\n console.log('Unable to authenticate user - No filed match in Secret for AcceptedIpNetworks(CIDR format, comma-separated)');\n return false;\n }\n\n for (const cidr of acceptedIpNetworks.split(',')) {\n if (isIpInCidr(inputSourceIp, cidr)) {\n console.log('Source IP address match');\n return true;\n }\n }\n\n console.log('Source IP address not in range');\n return false;\n};\n\nconst authenticatePasswordUser = (secretDict: SecretDict, inputPassword: string, inputProtocol: string): boolean => {\n const password = lookup(secretDict, 'Password', inputProtocol);\n if (!password) {\n console.log('Unable to authenticate user - No field match in Secret for password');\n return false;\n }\n\n if (inputPassword === password) {\n return true;\n } else {\n console.log('Unable to authenticate user - Incoming password does not match stored');\n return false;\n }\n};\n\nconst buildResponse = (secretDict: SecretDict, authType: string, inputProtocol: string): TransferFamilyAuthorizerResult => {\n const responseData: TransferFamilyAuthorizerResult = {};\n\n const role = lookup(secretDict, 'Role', inputProtocol);\n if (role) {\n responseData.Role = role;\n } else {\n console.log('No field match for role - Set empty string in response');\n responseData.Role = '';\n }\n\n const policy = lookup(secretDict, 'Policy', inputProtocol);\n if (policy) {\n responseData.Policy = policy;\n }\n\n const homeDirectoryDetails = lookup(secretDict, 'HomeDirectoryDetails', inputProtocol);\n if (homeDirectoryDetails) {\n console.log('HomeDirectoryDetails found - Applying setting for virtual folders - Note: Cannot be used in conjunction with key: HomeDirectory');\n responseData.HomeDirectoryDetails = homeDirectoryDetails;\n console.log('Setting HomeDirectoryType to LOGICAL');\n responseData.HomeDirectoryType = 'LOGICAL';\n }\n\n const homeDirectory = lookup(secretDict, 'HomeDirectory', inputProtocol);\n if (homeDirectory) {\n console.log('HomeDirectory found - Note: Cannot be used in conjunction with key: HomeDirectoryDetails');\n responseData.HomeDirectory = homeDirectory;\n }\n\n if (authType === 'SSHPubKey') {\n const publicKey = lookup(secretDict, 'PublicKey', inputProtocol);\n if (publicKey) {\n responseData.PublicKeys = [publicKey];\n } else {\n console.log('Unable to authenticate user - No public keys found');\n return {};\n }\n }\n\n return responseData;\n};\n\nconst getSecret = async (id: string): Promise<string | null> => {\n console.log(`Secret Name: ${id}`);\n\n const client = new SecretsManagerClient({\n region: 'ap-northeast-1',\n });\n\n return client.send(new GetSecretValueCommand({ SecretId: id }))\n .then((data: GetSecretValueCommandOutput) => {\n if (data.SecretBinary) {\n console.log('Got SecretBinary value');\n return Buffer.from(data.SecretBinary).toString('utf-8');\n }\n if (data.SecretString) {\n console.log('Got SecretString value');\n return data.SecretString;\n }\n throw new EmptySecretValueError();\n })\n .catch((error: Error) => {\n console.warn(error.message);\n return null;\n });\n};\n\nconst ipToBigInt = (address: string) => {\n if (address.includes(':')) {\n // IPv6\n let parts = address.split(':').map(part => part === '' ? '0' : part);\n let bigInt = BigInt(0);\n for (let i = 0; i < parts.length; i++) {\n bigInt = bigInt * BigInt(0x10000) + BigInt(parseInt(parts[i], 16));\n }\n return bigInt;\n } else {\n // IPv4\n let parts = address.split('.').map(part => parseInt(part, 10));\n let bigInt = BigInt(0);\n for (let i = 0; i < parts.length; i++) {\n bigInt = bigInt * BigInt(256) + BigInt(parts[i]);\n }\n return bigInt;\n }\n};\n\nconst getSubnetRange = (cidr: string): { start: bigint; end: bigint } => {\n const [network, bits] = cidr.split('/');\n const isIPv6 = network.includes(':');\n const totalBits = isIPv6 ? 128 : 32;\n const networkBigInt = ipToBigInt(network);\n const hostBits = totalBits - parseInt(bits, 10);\n const subnetSize = BigInt(2) ** BigInt(hostBits);\n\n const start = networkBigInt - (networkBigInt % subnetSize);\n const end = start + subnetSize - BigInt(1);\n\n return { start, end };\n};\n\nconst isIpInCidr = (ipAddr: string, cidr: string) => {\n const ipBigInt = ipToBigInt(ipAddr);\n const { start, end } = getSubnetRange(cidr);\n return ipBigInt >= start && ipBigInt <= end;\n};"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,2 +1,5 @@
1
1
  import { TransferFamilyAuthorizerEvent, TransferFamilyAuthorizerResult } from 'aws-lambda';
2
+ export declare class EmptySecretValueError extends Error {
3
+ constructor();
4
+ }
2
5
  export declare const handler: (event: TransferFamilyAuthorizerEvent) => Promise<TransferFamilyAuthorizerResult>;
@@ -1,7 +1,14 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.handler = void 0;
3
+ exports.handler = exports.EmptySecretValueError = void 0;
4
4
  const client_secrets_manager_1 = require("@aws-sdk/client-secrets-manager");
5
+ class EmptySecretValueError extends Error {
6
+ constructor() {
7
+ super('Got a secret value is empty.');
8
+ this.name = 'EmptySecretValueError';
9
+ }
10
+ }
11
+ exports.EmptySecretValueError = EmptySecretValueError;
5
12
  const handler = async (event) => {
6
13
  const requiredParamList = ['serverId', 'username', 'protocol', 'sourceIp'];
7
14
  for (const parameter of requiredParamList) {
@@ -28,12 +35,18 @@ const handler = async (event) => {
28
35
  return {};
29
36
  }
30
37
  console.log('Using SSH authentication');
31
- authenticationType = 'SSH';
38
+ authenticationType = 'SSHPubKey';
32
39
  }
33
40
  const secret = await getSecret(`transfer-user/${inputServerId}/${inputUsername}`);
34
41
  if (secret) {
35
42
  const secretDict = JSON.parse(secret);
36
- const userAuthenticated = authenticateUser(authenticationType, secretDict, inputPassword, inputProtocol);
43
+ const userAuthenticated = (() => {
44
+ if (authenticationType === 'SSHPubKey') {
45
+ console.log('Skip password check as SSH login request');
46
+ return true;
47
+ }
48
+ return authenticatePasswordUser(secretDict, inputPassword, inputProtocol);
49
+ })();
37
50
  const ipMatch = checkIpAddress(secretDict, inputSourceIp, inputProtocol);
38
51
  if (userAuthenticated && ipMatch) {
39
52
  console.log(`User authenticated, calling buildResponse with: ${authenticationType}`);
@@ -60,42 +73,33 @@ const lookup = (secretDict, key, inputProtocol) => {
60
73
  }
61
74
  };
62
75
  const checkIpAddress = (secretDict, inputSourceIp, inputProtocol) => {
63
- const acceptedIpNetworkList = lookup(secretDict, 'AcceptedIpNetworkList', inputProtocol);
64
- if (!acceptedIpNetworkList) {
65
- console.log('No IP range provided - Skip IP check');
66
- return true;
67
- }
68
- for (const acceptedIpNetwork of acceptedIpNetworkList.split(',')) {
69
- if (isIpInCidr(inputSourceIp, acceptedIpNetwork)) {
76
+ const acceptedIpNetworks = lookup(secretDict, 'AcceptedIpNetworks', inputProtocol);
77
+ console.log(`AcceptedIpNetworks: ${acceptedIpNetworks}`);
78
+ if (!acceptedIpNetworks) {
79
+ console.log('Unable to authenticate user - No filed match in Secret for AcceptedIpNetworks(CIDR format, comma-separated)');
80
+ return false;
81
+ }
82
+ for (const cidr of acceptedIpNetworks.split(',')) {
83
+ if (isIpInCidr(inputSourceIp, cidr)) {
70
84
  console.log('Source IP address match');
71
85
  return true;
72
86
  }
73
87
  }
74
- // if (new CIDRMatcher(acceptedIpNetworkList.split(',')).contains(inputSourceIp)) {
75
- // console.log('Source IP address match');
76
- // return true;
77
- // }
78
88
  console.log('Source IP address not in range');
79
89
  return false;
80
90
  };
81
- const authenticateUser = (authType, secretDict, inputPassword, inputProtocol) => {
82
- if (authType === 'SSH') {
83
- console.log('Skip password check as SSH login request');
91
+ const authenticatePasswordUser = (secretDict, inputPassword, inputProtocol) => {
92
+ const password = lookup(secretDict, 'Password', inputProtocol);
93
+ if (!password) {
94
+ console.log('Unable to authenticate user - No field match in Secret for password');
95
+ return false;
96
+ }
97
+ if (inputPassword === password) {
84
98
  return true;
85
99
  }
86
100
  else {
87
- const password = lookup(secretDict, 'Password', inputProtocol);
88
- if (!password) {
89
- console.log('Unable to authenticate user - No field match in Secret for password');
90
- return false;
91
- }
92
- if (inputPassword === password) {
93
- return true;
94
- }
95
- else {
96
- console.log('Unable to authenticate user - Incoming password does not match stored');
97
- return false;
98
- }
101
+ console.log('Unable to authenticate user - Incoming password does not match stored');
102
+ return false;
99
103
  }
100
104
  };
101
105
  const buildResponse = (secretDict, authType, inputProtocol) => {
@@ -124,7 +128,7 @@ const buildResponse = (secretDict, authType, inputProtocol) => {
124
128
  console.log('HomeDirectory found - Note: Cannot be used in conjunction with key: HomeDirectoryDetails');
125
129
  responseData.HomeDirectory = homeDirectory;
126
130
  }
127
- if (authType === 'SSH') {
131
+ if (authType === 'SSHPubKey') {
128
132
  const publicKey = lookup(secretDict, 'PublicKey', inputProtocol);
129
133
  if (publicKey) {
130
134
  responseData.PublicKeys = [publicKey];
@@ -141,53 +145,22 @@ const getSecret = async (id) => {
141
145
  const client = new client_secrets_manager_1.SecretsManagerClient({
142
146
  region: 'ap-northeast-1',
143
147
  });
144
- const command = new client_secrets_manager_1.GetSecretValueCommand({ SecretId: id });
145
- try {
146
- const data = await client.send(command);
147
- console.log(data);
148
+ return client.send(new client_secrets_manager_1.GetSecretValueCommand({ SecretId: id }))
149
+ .then((data) => {
150
+ if (data.SecretBinary) {
151
+ console.log('Got SecretBinary value');
152
+ return Buffer.from(data.SecretBinary).toString('utf-8');
153
+ }
148
154
  if (data.SecretString) {
155
+ console.log('Got SecretString value');
149
156
  return data.SecretString;
150
157
  }
151
- if (data.SecretBinary) {
152
- return new TextDecoder().decode(data.SecretBinary);
153
- }
154
- return null;
155
- }
156
- catch (error) {
157
- console.log('Not found Secret');
158
- console.log(`Error: ${JSON.stringify(error)}`);
158
+ throw new EmptySecretValueError();
159
+ })
160
+ .catch((error) => {
161
+ console.warn(error.message);
159
162
  return null;
160
- }
161
- //const resp = await client.send(command);
162
- // return client.send(command)
163
- // .then((data: GetSecretValueCommandOutput) => {
164
- // if (data?.SecretString) {
165
- // return data.SecretString;
166
- // }
167
- // if (data?.SecretBinary) {
168
- // return new TextDecoder().decode(data.SecretBinary);
169
- // }
170
- // return null;
171
- // })
172
- // .catch((error: Error) => {
173
- // console.log('Not found Secret');
174
- // console.log(`Error:${JSON.stringify(error)}`);
175
- // return null;
176
- // });
177
- // console.log(resp);
178
- // if (resp.SecretString) {
179
- // console.log('Found Secret String');
180
- // return resp.SecretString;
181
- // } else {
182
- // if (resp.SecretBinary) {
183
- // console.log('Found Binary Secret');
184
- // //return Buffer.from(resp.SecretBinary as string, 'base64').toString('ascii');
185
- // return new TextDecoder().decode(resp.SecretBinary);
186
- // }
187
- // }
188
- //
189
- // console.log('Not found Secret');
190
- // return null;
163
+ });
191
164
  };
192
165
  const ipToBigInt = (address) => {
193
166
  if (address.includes(':')) {
@@ -209,25 +182,20 @@ const ipToBigInt = (address) => {
209
182
  return bigInt;
210
183
  }
211
184
  };
212
- const getSubnetMask = (bits, isIPv6 = false) => {
213
- let mask = BigInt(0);
214
- const totalBits = isIPv6 ? 128 : 32;
215
- for (let i = 0; i < bits; i++) {
216
- mask = mask * BigInt(2) + BigInt(1);
217
- }
218
- for (let i = bits; i < totalBits; i++) {
219
- mask = mask * BigInt(2);
220
- }
221
- return mask;
222
- };
223
- const isIpInCidr = (address, cidr) => {
185
+ const getSubnetRange = (cidr) => {
224
186
  const [network, bits] = cidr.split('/');
225
187
  const isIPv6 = network.includes(':');
226
- const ipBigInt = ipToBigInt(address);
188
+ const totalBits = isIPv6 ? 128 : 32;
227
189
  const networkBigInt = ipToBigInt(network);
228
- const mask = getSubnetMask(parseInt(bits), isIPv6);
229
- const maskedIp = ipBigInt - (ipBigInt % (mask + BigInt(1)));
230
- const maskedNetwork = networkBigInt - (networkBigInt % (mask + BigInt(1)));
231
- return maskedIp === maskedNetwork;
190
+ const hostBits = totalBits - parseInt(bits, 10);
191
+ const subnetSize = BigInt(2) ** BigInt(hostBits);
192
+ const start = networkBigInt - (networkBigInt % subnetSize);
193
+ const end = start + subnetSize - BigInt(1);
194
+ return { start, end };
195
+ };
196
+ const isIpInCidr = (ipAddr, cidr) => {
197
+ const ipBigInt = ipToBigInt(ipAddr);
198
+ const { start, end } = getSubnetRange(cidr);
199
+ return ipBigInt >= start && ipBigInt <= end;
232
200
  };
233
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNmZXItdXNlci1hdXRoZW50aWNhdGlvbi5sYW1iZGEuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvZnVuY3MvdHJhbnNmZXItdXNlci1hdXRoZW50aWNhdGlvbi5sYW1iZGEudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsNEVBQTJIO0FBT3BILE1BQU0sT0FBTyxHQUFHLEtBQUssRUFBRSxLQUFvQyxFQUEyQyxFQUFFO0lBQzdHLE1BQU0saUJBQWlCLEdBQUcsQ0FBQyxVQUFVLEVBQUUsVUFBVSxFQUFFLFVBQVUsRUFBRSxVQUFVLENBQUMsQ0FBQztJQUMzRSxLQUFLLE1BQU0sU0FBUyxJQUFJLGlCQUFpQixFQUFFLENBQUM7UUFDMUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxjQUFjLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQztZQUNyQyxPQUFPLENBQUMsR0FBRyxDQUFDLFlBQVksU0FBUyx1QkFBdUIsQ0FBQyxDQUFDO1lBQzFELE9BQU8sRUFBRSxDQUFDO1FBQ1osQ0FBQztJQUNILENBQUM7SUFFRCxNQUFNLGFBQWEsR0FBRyxLQUFLLENBQUMsUUFBUSxDQUFDO0lBQ3JDLE1BQU0sYUFBYSxHQUFHLEtBQUssQ0FBQyxRQUFRLENBQUM7SUFDckMsTUFBTSxhQUFhLEdBQUcsS0FBSyxDQUFDLFFBQVEsQ0FBQztJQUNyQyxNQUFNLGFBQWEsR0FBRyxLQUFLLENBQUMsUUFBUSxDQUFDO0lBQ3JDLE1BQU0sYUFBYSxHQUFHLEtBQUssQ0FBQyxRQUFRLElBQUksRUFBRSxDQUFDO0lBRTNDLE9BQU8sQ0FBQyxHQUFHLENBQUMsYUFBYSxhQUFhLGVBQWUsYUFBYSxlQUFlLGFBQWEsZUFBZSxhQUFhLEVBQUUsQ0FBQyxDQUFDO0lBRTlILE9BQU8sQ0FBQyxHQUFHLENBQUMsZ0NBQWdDLENBQUMsQ0FBQztJQUM5QyxJQUFJLGtCQUFrQixHQUFHLEVBQUUsQ0FBQztJQUM1QixJQUFJLGFBQWEsS0FBSyxFQUFFLEVBQUUs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LE9BQWUsRUFBRSxJQUFZLEVBQUUsRUFBRTtJQUNuRCxNQUFNLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDeEMsTUFBTSxNQUFNLEdBQUcsT0FBTyxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNyQyxNQUFNLFFBQVEsR0FBRyxVQUFVLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDckMsTUFBTSxhQUFhLEdBQUcsVUFBVSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQzFDLE1BQU0sSUFBSSxHQUFHLGFBQWEsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLEVBQUUsTUFBTSxDQUFDLENBQUM7SUFFbkQsTUFBTSxRQUFRLEdBQUcsUUFBUSxHQUFHLENBQUMsUUFBUSxHQUFHLENBQUMsSUFBSSxHQUFHLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDNUQsTUFBTSxhQUFhLEdBQUcsYUFBYSxHQUFHLENBQUMsYUFBYSxHQUFHLENBQUMsSUFBSSxHQUFHLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFFM0UsT0FBTyxRQUFRLEtBQUssYUFBYSxDQUFDO0FBQ3BDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFNlY3JldHNNYW5hZ2VyQ2xpZW50LCBHZXRTZWNyZXRWYWx1ZUNvbW1hbmQsIEdldFNlY3JldFZhbHVlQ29tbWFuZE91dHB1dCB9IGZyb20gJ0Bhd3Mtc2RrL2NsaWVudC1zZWNyZXRzLW1hbmFnZXInO1xuaW1wb3J0IHsgVHJhbnNmZXJGYW1pbHlBdXRob3JpemVyRXZlbnQsIFRyYW5zZmVyRmFtaWx5QXV0aG9yaXplclJlc3VsdCB9IGZyb20gJ2F3cy1sYW1iZGEnO1xuXG5pbnRlcmZhY2UgU2VjcmV0RGljdCB7XG4gIFtrZXk6IHN0cmluZ106IHN0cmluZztcbn1cblxuZXhwb3J0IGNvbnN0IGhhbmRsZXIgPSBhc3luYyAoZXZlbnQ6IFRyYW5zZmVyRmFtaWx5QXV0aG9yaXplckV2ZW50KTogUHJvbWlzZTxUcmFuc2ZlckZhbWlseUF1dGhvcml6ZXJSZXN1bHQ+ID0+IHtcbiAgY29uc3QgcmVxdWlyZWRQYXJhbUxpc3QgPSBbJ3NlcnZlcklkJywgJ3VzZXJuYW1lJywgJ3Byb3RvY29sJywgJ3NvdXJjZUlwJ107XG4gIGZvciAoY29uc3QgcGFyYW1ldGVyIG9mIHJlcXVpcmVkUGFyYW1MaXN0KSB7XG4gICAgaWYgKCFldmVudC5oYXNPd25Qcm9wZXJ0eShwYXJhbWV0ZXIpKSB7XG4gICAgICBjb25zb2xlLmxvZyhgSW5jb21pbmcgJHtwYXJhbWV0ZXJ9IG1pc3NpbmcgLSBVbmV4cGVjdGVkYCk7XG4gICAgICByZXR1cm4ge307XG4gICAgfVxuICB9XG5cbiAgY29uc3QgaW5wdXRTZXJ2ZXJJZCA9IGV2ZW50LnNlcnZlcklkO1xuICBjb25zdCBpbnB1dFVzZXJuYW1lID0gZXZlbnQudXNlcm5hbWU7XG4gIGNvbnN0IGlucHV0UHJvdG9jb2wgPSBldmVudC5wcm90b2NvbDtcbiAgY29uc3QgaW5wdXRTb3VyY2VJcCA9IGV2ZW50LnNvdXJjZUlwO1xuICBjb25zdCBpbnB1dFBhc3N3b3JkID0gZXZlbnQucGFzc3dvcmQgfHwgJyc7XG5cbiAgY29uc29sZS5sb2coYFNlcnZlcklkOiAke2lucHV0U2VydmVySWR9LCBVc2VybmFtZTogJHtpbnB1dFVzZXJuYW1lfSwgUHJvdG9jb2w6ICR7aW5wdXRQcm90b2NvbH0sIFNvdXJjZUlwOiAke2lucHV0U291cmNlSXB9YCk7XG5cbiAgY29uc29sZS5sb2coJ1N0YXJ0IFVzZXIgQXV0aGVudGljYXRpb24gRmxvdycpO1xuICBsZXQgYXV0aGVudGljYXRpb25UeXBlID0gJyc7XG4gIGlmIChpbnB1dFBhc3N3b3JkICE9PSAnJykge1xuICAgIGNvbnNvbGUubG9nKCdVc2luZyBQQVNTV09SRCBhdXRoZW50aWNhdGlvbicpO1xuICAgIGF1dGhlbnRpY2F0aW9uVHlwZSA9ICdQQVNTV09SRCc7XG4gIH0gZWxzZSB7XG4gICAgaWYgKGlucHV0UHJvdG9jb2wgPT09ICdGVFAnIHx8IGlucHV0UHJvdG9jb2wgPT09ICdGVFBTJykge1xuICAgICAgY29uc29sZS5sb2coJ0VtcHR5IHBhc3N3b3JkIG5vdCBhbGxvd2VkIGZvciBGVFAvUycpO1xuICAgICAgcmV0dXJuIHt9O1xuICAgIH1cbiAgICBjb25zb2xlLmxvZygnVXNpbmcgU1NIIGF1dGhlbnRpY2F0aW9uJyk7XG4gICAgYXV0aGVudGljYXRpb25UeXBlID0gJ1NTSCc7XG4gIH1cblxuICBjb25zdCBzZWNyZXQgPSBhd2FpdCBnZXRTZWNyZXQoYHRyYW5zZmVyLXVzZXIvJHtpbnB1dFNlcnZlcklkfS8ke2lucHV0VXNlcm5hbWV9YCk7XG5cbiAgaWYgKHNlY3JldCkge1xuICAgIGNvbnN0IHNlY3JldERpY3QgPSBKU09OLnBhcnNlKHNlY3JldCkgYXMgU2VjcmV0RGljdDtcbiAgICBjb25zdCB1c2VyQXV0aGVudGljYXRlZCA9IGF1dGhlbnRpY2F0ZVVzZXIoYXV0aGVudGljYXRpb25UeXBlLCBzZWNyZXREaWN0LCBpbnB1dFBhc3N3b3JkLCBpbnB1dFByb3RvY29sKTtcbiAgICBjb25zdCBpcE1hdGNoID0gY2hlY2tJcEFkZHJlc3Moc2VjcmV0RGljdCwgaW5wdXRTb3VyY2VJcCwgaW5wdXRQcm90b2NvbCk7XG5cbiAgICBpZiAodXNlckF1dGhlbnRpY2F0ZWQgJiYgaXBNYXRjaCkge1xuICAgICAgY29uc29sZS5sb2coYFVzZXIgYXV0aGVudGljYXRlZCwgY2FsbGluZyBidWlsZFJlc3BvbnNlIHdpdGg6ICR7YXV0aGVudGljYXRpb25UeXBlfWApO1xuICAgICAgcmV0dXJuIGJ1aWxkUmVzcG9uc2Uoc2VjcmV0RGljdCwgYXV0aGVudGljYXRpb25UeXBlLCBpbnB1dFByb3RvY29sKTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc29sZS5sb2coJ1VzZXIgZmFpbGVkIGF1dGhlbnRpY2F0aW9uIHJldHVybiBlbXB0eSByZXNwb25zZScpO1xuICAgICAgcmV0dXJuIHt9O1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBjb25zb2xlLmxvZygnU2VjcmV0cyBNYW5hZ2VyIGV4Y2VwdGlvbiB0aHJvd24gLSBSZXR1cm5pbmcgZW1wdHkgcmVzcG9uc2UnKTtcbiAgICByZXR1cm4ge307XG4gIH1cbn07XG5cbmNvbnN0IGxvb2t1cCA9IChzZWNyZXREaWN0OiBTZWNyZXREaWN0LCBrZXk6IHN0cmluZywgaW5wdXRQcm90b2NvbDogc3RyaW5nKTogc3RyaW5nIHwgbnVsbCA9PiB7XG4gIGlmIChzZWNyZXREaWN0W2Ake2lucHV0UHJvdG9jb2x9JHtrZXl9YF0pIHtcbiAgICBjb25zb2xlLmxvZyhgRm91bmQgcHJvdG9jb2wtc3BlY2lmaWVkICR7a2V5fWApO1xuICAgIHJldHVybiBzZWNyZXREaWN0W2Ake2lucHV0UHJvdG9jb2x9JHtrZXl9YF07XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIHNlY3JldERpY3Rba2V5XSB8fCBudWxsO1xuICB9XG59O1xuXG5jb25zdCBjaGVja0lwQWRkcmVzcyA9IChzZWNyZXREaWN0OiBTZWNyZXREaWN0LCBpbnB1dFNvdXJjZUlwOiBzdHJpbmcsIGlucHV0UHJvdG9jb2w6IHN0cmluZyk6IGJvb2xlYW4gPT4ge1xuICBjb25zdCBhY2NlcHRlZElwTmV0d29ya0xpc3QgPSBsb29rdXAoc2VjcmV0RGljdCwgJ0FjY2VwdGVkSXBOZXR3b3JrTGlzdCcsIGlucHV0UHJvdG9jb2wpO1xuICBpZiAoIWFjY2VwdGVkSXBOZXR3b3JrTGlzdCkge1xuICAgIGNvbnNvbGUubG9nKCdObyBJUCByYW5nZSBwcm92aWRlZCAtIFNraXAgSVAgY2hlY2snKTtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIGZvciAoY29uc3QgYWNjZXB0ZWRJcE5ldHdvcmsgb2YgYWNjZXB0ZWRJcE5ldHdvcmtMaXN0LnNwbGl0KCcsJykpIHtcbiAgICBpZiAoaXNJcEluQ2lkcihpbnB1dFNvdXJjZUlwLCBhY2NlcHRlZElwTmV0d29yaykpIHtcbiAgICAgIGNvbnNvbGUubG9nKCdTb3VyY2UgSVAgYWRkcmVzcyBtYXRjaCcpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG4gIC8vICBpZiAobmV3IENJRFJNYXRjaGVyKGFjY2VwdGVkSXBOZXR3b3JrTGlzdC5zcGxpdCgnLCcpKS5jb250YWlucyhpbnB1dFNvdXJjZUlwKSkge1xuICAvLyAgICBjb25zb2xlLmxvZygnU291cmNlIElQIGFkZHJlc3MgbWF0Y2gnKTtcbiAgLy8gICAgcmV0dXJuIHRydWU7XG4gIC8vICB9XG5cbiAgY29uc29sZS5sb2coJ1NvdXJjZSBJUCBhZGRyZXNzIG5vdCBpbiByYW5nZScpO1xuICByZXR1cm4gZmFsc2U7XG59O1xuXG5jb25zdCBhdXRoZW50aWNhdGVVc2VyID0gKGF1dGhUeXBlOiBzdHJpbmcsIHNlY3JldERpY3Q6IFNlY3JldERpY3QsIGlucHV0UGFzc3dvcmQ6IHN0cmluZywgaW5wdXRQcm90b2NvbDogc3RyaW5nKTogYm9vbGVhbiA9PiB7XG4gIGlmIChhdXRoVHlwZSA9PT0gJ1NTSCcpIHtcbiAgICBjb25zb2xlLmxvZygnU2tpcCBwYXNzd29yZCBjaGVjayBhcyBTU0ggbG9naW4gcmVxdWVzdCcpO1xuICAgIHJldHVybiB0cnVlO1xuICB9IGVsc2Uge1xuICAgIGNvbnN0IHBhc3N3b3JkID0gbG9va3VwKHNlY3JldERpY3QsICdQYXNzd29yZCcsIGlucHV0UHJvdG9jb2wpO1xuICAgIGlmICghcGFzc3dvcmQpIHtcbiAgICAgIGNvbnNvbGUubG9nKCdVbmFibGUgdG8gYXV0aGVudGljYXRlIHVzZXIgLSBObyBmaWVsZCBtYXRjaCBpbiBTZWNyZXQgZm9yIHBhc3N3b3JkJyk7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgaWYgKGlucHV0UGFzc3dvcmQgPT09IHBhc3N3b3JkKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc29sZS5sb2coJ1VuYWJsZSB0byBhdXRoZW50aWNhdGUgdXNlciAtIEluY29taW5nIHBhc3N3b3JkIGRvZXMgbm90IG1hdGNoIHN0b3JlZCcpO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxufTtcblxuY29uc3QgYnVpbGRSZXNwb25zZSA9IChzZWNyZXREaWN0OiBTZWNyZXREaWN0LCBhdXRoVHlwZTogc3RyaW5nLCBpbnB1dFByb3RvY29sOiBzdHJpbmcpOiBUcmFuc2ZlckZhbWlseUF1dGhvcml6ZXJSZXN1bHQgPT4ge1xuICBjb25zdCByZXNwb25zZURhdGE6IFRyYW5zZmVyRmFtaWx5QXV0aG9yaXplclJlc3VsdCA9IHt9O1xuXG4gIGNvbnN0IHJvbGUgPSBsb29rdXAoc2VjcmV0RGljdCwgJ1JvbGUnLCBpbnB1dFByb3RvY29sKTtcbiAgaWYgKHJvbGUpIHtcbiAgICByZXNwb25zZURhdGEuUm9sZSA9IHJvbGU7XG4gIH0gZWxzZSB7XG4gICAgY29uc29sZS5sb2coJ05vIGZpZWxkIG1hdGNoIGZvciByb2xlIC0gU2V0IGVtcHR5IHN0cmluZyBpbiByZXNwb25zZScpO1xuICAgIHJlc3BvbnNlRGF0YS5Sb2xlID0gJyc7XG4gIH1cblxuICBjb25zdCBwb2xpY3kgPSBsb29rdXAoc2VjcmV0RGljdCwgJ1BvbGljeScsIGlucHV0UHJvdG9jb2wpO1xuICBpZiAocG9saWN5KSB7XG4gICAgcmVzcG9uc2VEYXRhLlBvbGljeSA9IHBvbGljeTtcbiAgfVxuXG4gIGNvbnN0IGhvbWVEaXJlY3RvcnlEZXRhaWxzID0gbG9va3VwKHNlY3JldERpY3QsICdIb21lRGlyZWN0b3J5RGV0YWlscycsIGlucHV0UHJvdG9jb2wpO1xuICBpZiAoaG9tZURpcmVjdG9yeURldGFpbHMpIHtcbiAgICBjb25zb2xlLmxvZygnSG9tZURpcmVjdG9yeURldGFpbHMgZm91bmQgLSBBcHBseWluZyBzZXR0aW5nIGZvciB2aXJ0dWFsIGZvbGRlcnMgLSBOb3RlOiBDYW5ub3QgYmUgdXNlZCBpbiBjb25qdW5jdGlvbiB3aXRoIGtleTogSG9tZURpcmVjdG9yeScpO1xuICAgIHJlc3BvbnNlRGF0YS5Ib21lRGlyZWN0b3J5RGV0YWlscyA9IGhvbWVEaXJlY3RvcnlEZXRhaWxzO1xuICAgIGNvbnNvbGUubG9nKCdTZXR0aW5nIEhvbWVEaXJlY3RvcnlUeXBlIHRvIExPR0lDQUwnKTtcbiAgICByZXNwb25zZURhdGEuSG9tZURpcmVjdG9yeVR5cGUgPSAnTE9HSUNBTCc7XG4gIH1cblxuICBjb25zdCBob21lRGlyZWN0b3J5ID0gbG9va3VwKHNlY3JldERpY3QsICdIb21lRGlyZWN0b3J5JywgaW5wdXRQcm90b2NvbCk7XG4gIGlmIChob21lRGlyZWN0b3J5KSB7XG4gICAgY29uc29sZS5sb2coJ0hvbWVEaXJlY3RvcnkgZm91bmQgLSBOb3RlOiBDYW5ub3QgYmUgdXNlZCBpbiBjb25qdW5jdGlvbiB3aXRoIGtleTogSG9tZURpcmVjdG9yeURldGFpbHMnKTtcbiAgICByZXNwb25zZURhdGEuSG9tZURpcmVjdG9yeSA9IGhvbWVEaXJlY3Rvcnk7XG4gIH1cblxuICBpZiAoYXV0aFR5cGUgPT09ICdTU0gnKSB7XG4gICAgY29uc3QgcHVibGljS2V5ID0gbG9va3VwKHNlY3JldERpY3QsICdQdWJsaWNLZXknLCBpbnB1dFByb3RvY29sKTtcbiAgICBpZiAocHVibGljS2V5KSB7XG4gICAgICByZXNwb25zZURhdGEuUHVibGljS2V5cyA9IFtwdWJsaWNLZXldO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zb2xlLmxvZygnVW5hYmxlIHRvIGF1dGhlbnRpY2F0ZSB1c2VyIC0gTm8gcHVibGljIGtleXMgZm91bmQnKTtcbiAgICAgIHJldHVybiB7fTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gcmVzcG9uc2VEYXRhO1xufTtcblxuY29uc3QgZ2V0U2VjcmV0ID0gYXN5bmMgKGlkOiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZyB8IG51bGw+ID0+IHtcbiAgY29uc29sZS5sb2coYFNlY3JldCBOYW1lOiAke2lkfWApO1xuXG4gIGNvbnN0IGNsaWVudCA9IG5ldyBTZWNyZXRzTWFuYWdlckNsaWVudCh7XG4gICAgcmVnaW9uOiAnYXAtbm9ydGhlYXN0LTEnLFxuICB9KTtcbiAgY29uc3QgY29tbWFuZCA9IG5ldyBHZXRTZWNyZXRWYWx1ZUNvbW1hbmQoeyBTZWNyZXRJZDogaWQgfSk7XG5cbiAgdHJ5IHtcbiAgICBjb25zdCBkYXRhOiBHZXRTZWNyZXRWYWx1ZUNvbW1hbmRPdXRwdXQgPSBhd2FpdCBjbGllbnQuc2VuZChjb21tYW5kKTtcbiAgICBjb25zb2xlLmxvZyhkYXRhKTtcbiAgICBpZiAoZGF0YS5TZWNyZXRTdHJpbmcpIHtcbiAgICAgIHJldHVybiBkYXRhLlNlY3JldFN0cmluZztcbiAgICB9XG4gICAgaWYgKGRhdGEuU2VjcmV0QmluYXJ5KSB7XG4gICAgICByZXR1cm4gbmV3IFRleHREZWNvZGVyKCkuZGVjb2RlKGRhdGEuU2VjcmV0QmluYXJ5KTtcbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgY29uc29sZS5sb2coJ05vdCBmb3VuZCBTZWNyZXQnKTtcbiAgICBjb25zb2xlLmxvZyhgRXJyb3I6ICR7SlNPTi5zdHJpbmdpZnkoZXJyb3IpfWApO1xuICAgIHJldHVybiBudWxsO1xuICB9XG4gIC8vY29uc3QgcmVzcCA9IGF3YWl0IGNsaWVudC5zZW5kKGNvbW1hbmQpO1xuLy8gIHJldHVybiBjbGllbnQuc2VuZChjb21tYW5kKVxuLy8gICAgLnRoZW4oKGRhdGE6IEdldFNlY3JldFZhbHVlQ29tbWFuZE91dHB1dCkgPT4ge1xuLy8gICAgICBpZiAoZGF0YT8uU2VjcmV0U3RyaW5nKSB7XG4vLyAgICAgICAgcmV0dXJuIGRhdGEuU2VjcmV0U3RyaW5nO1xuLy8gICAgICB9XG4vLyAgICAgIGlmIChkYXRhPy5TZWNyZXRCaW5hcnkpIHtcbi8vICAgICAgICByZXR1cm4gbmV3IFRleHREZWNvZGVyKCkuZGVjb2RlKGRhdGEuU2VjcmV0QmluYXJ5KTtcbi8vICAgICAgfVxuLy8gICAgICByZXR1cm4gbnVsbDtcbi8vICAgIH0pXG4vLyAgICAuY2F0Y2goKGVycm9yOiBFcnJvcikgPT4ge1xuLy8gICAgICBjb25zb2xlLmxvZygnTm90IGZvdW5kIFNlY3JldCcpO1xuLy8gICAgICBjb25zb2xlLmxvZyhgRXJyb3I6JHtKU09OLnN0cmluZ2lmeShlcnJvcil9YCk7XG4vLyAgICAgIHJldHVybiBudWxsO1xuLy8gICAgfSk7XG4vLyAgY29uc29sZS5sb2cocmVzcCk7XG4vLyAgaWYgKHJlc3AuU2VjcmV0U3RyaW5nKSB7XG4vLyAgICBjb25zb2xlLmxvZygnRm91bmQgU2VjcmV0IFN0cmluZycpO1xuLy8gICAgcmV0dXJuIHJlc3AuU2VjcmV0U3RyaW5nO1xuLy8gIH0gZWxzZSB7XG4vLyAgICBpZiAocmVzcC5TZWNyZXRCaW5hcnkpIHtcbi8vICAgICAgY29uc29sZS5sb2coJ0ZvdW5kIEJpbmFyeSBTZWNyZXQnKTtcbi8vICAgICAgLy9yZXR1cm4gQnVmZmVyLmZyb20ocmVzcC5TZWNyZXRCaW5hcnkgYXMgc3RyaW5nLCAnYmFzZTY0JykudG9TdHJpbmcoJ2FzY2lpJyk7XG4vLyAgICAgIHJldHVybiBuZXcgVGV4dERlY29kZXIoKS5kZWNvZGUocmVzcC5TZWNyZXRCaW5hcnkpO1xuLy8gICAgfVxuLy8gIH1cbi8vXG4vLyAgY29uc29sZS5sb2coJ05vdCBmb3VuZCBTZWNyZXQnKTtcbi8vICByZXR1cm4gbnVsbDtcbn07XG5cbmNvbnN0IGlwVG9CaWdJbnQgPSAoYWRkcmVzczogc3RyaW5nKSA9PiB7XG4gIGlmIChhZGRyZXNzLmluY2x1ZGVzKCc6JykpIHtcbiAgICAvLyBJUHY2XG4gICAgbGV0IHBhcnRzID0gYWRkcmVzcy5zcGxpdCgnOicpLm1hcChwYXJ0ID0+IHBhcnQgPT09ICcnID8gJzAnIDogcGFydCk7XG4gICAgbGV0IGJpZ0ludCA9IEJpZ0ludCgwKTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHBhcnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBiaWdJbnQgPSBiaWdJbnQgKiBCaWdJbnQoMHgxMDAwMCkgKyBCaWdJbnQocGFyc2VJbnQocGFydHNbaV0sIDE2KSk7XG4gICAgfVxuICAgIHJldHVybiBiaWdJbnQ7XG4gIH0gZWxzZSB7XG4gICAgLy8gSVB2NFxuICAgIGxldCBwYXJ0cyA9IGFkZHJlc3Muc3BsaXQoJy4nKS5tYXAocGFydCA9PiBwYXJzZUludChwYXJ0LCAxMCkpO1xuICAgIGxldCBiaWdJbnQgPSBCaWdJbnQoMCk7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBwYXJ0cy5sZW5ndGg7IGkrKykge1xuICAgICAgYmlnSW50ID0gYmlnSW50ICogQmlnSW50KDI1NikgKyBCaWdJbnQocGFydHNbaV0pO1xuICAgIH1cbiAgICByZXR1cm4gYmlnSW50O1xuICB9XG59O1xuXG5jb25zdCBnZXRTdWJuZXRNYXNrID0gKGJpdHM6IG51bWJlciwgaXNJUHY2ID0gZmFsc2UpID0+IHtcbiAgbGV0IG1hc2sgPSBCaWdJbnQoMCk7XG4gIGNvbnN0IHRvdGFsQml0cyA9IGlzSVB2NiA/IDEyOCA6IDMyO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IGJpdHM7IGkrKykge1xuICAgIG1hc2sgPSBtYXNrICogQmlnSW50KDIpICsgQmlnSW50KDEpO1xuICB9XG4gIGZvciAobGV0IGkgPSBiaXRzOyBpIDwgdG90YWxCaXRzOyBpKyspIHtcbiAgICBtYXNrID0gbWFzayAqIEJpZ0ludCgyKTtcbiAgfVxuICByZXR1cm4gbWFzaztcbn07XG5cbmNvbnN0IGlzSXBJbkNpZHIgPSAoYWRkcmVzczogc3RyaW5nLCBjaWRyOiBzdHJpbmcpID0+IHtcbiAgY29uc3QgW25ldHdvcmssIGJpdHNdID0gY2lkci5zcGxpdCgnLycpO1xuICBjb25zdCBpc0lQdjYgPSBuZXR3b3JrLmluY2x1ZGVzKCc6Jyk7XG4gIGNvbnN0IGlwQmlnSW50ID0gaXBUb0JpZ0ludChhZGRyZXNzKTtcbiAgY29uc3QgbmV0d29ya0JpZ0ludCA9IGlwVG9CaWdJbnQobmV0d29yayk7XG4gIGNvbnN0IG1hc2sgPSBnZXRTdWJuZXRNYXNrKHBhcnNlSW50KGJpdHMpLCBpc0lQdjYpO1xuXG4gIGNvbnN0IG1hc2tlZElwID0gaXBCaWdJbnQgLSAoaXBCaWdJbnQgJSAobWFzayArIEJpZ0ludCgxKSkpO1xuICBjb25zdCBtYXNrZWROZXR3b3JrID0gbmV0d29ya0JpZ0ludCAtIChuZXR3b3JrQmlnSW50ICUgKG1hc2sgKyBCaWdJbnQoMSkpKTtcblxuICByZXR1cm4gbWFza2VkSXAgPT09IG1hc2tlZE5ldHdvcms7XG59OyJdfQ==
201
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNmZXItdXNlci1hdXRoZW50aWNhdGlvbi5sYW1iZGEuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvZnVuY3MvdHJhbnNmZXItdXNlci1hdXRoZW50aWNhdGlvbi5sYW1iZGEudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsNEVBQTJIO0FBRzNILE1BQWEscUJBQXNCLFNBQVEsS0FBSztJQUM5QztRQUNFLEtBQUssQ0FBQyw4QkFBOEIsQ0FBQyxDQUFDO1FBQ3RDLElBQUksQ0FBQyxJQUFJLEdBQUcsdUJBQXVCLENBQUM7SUFDdEMsQ0FBQztDQUNGO0FBTEQsc0RBS0M7QUFNTSxNQUFNLE9BQU8sR0FBRyxLQUFLLEVBQUUsS0FBb0MsRUFBMkMsRUFBRTtJQUM3RyxNQUFNLGlCQUFpQixHQUFHLENBQUMsVUFBVSxFQUFFLFVBQVUsRUFBRSxVQUFVLEVBQUUsVUFBVSxDQUFDLENBQUM7SUFDM0UsS0FBSyxNQUFNLFNBQVMsSUFBSSxpQkFBaUIsRUFBRSxDQUFDO1FBQzFDLElBQUksQ0FBQyxLQUFLLENBQUMsY0FBYyxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUM7WUFDckMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxZQUFZLFNBQVMsdUJBQXVCLENBQUMsQ0FBQztZQUMxRCxPQUFPLEVBQUUsQ0FBQztRQUNaLENBQUM7SUFDSCxDQUFDO0lBRUQsTUFBTSxhQUFhLEdBQUcsS0FBSyxDQUFDLFFBQVEsQ0FBQztJQUNyQyxNQUFNLGFBQWEsR0FBRyxLQUFLLENBQUMsUUFBUSxDQUFDO0lBQ3JDLE1BQU0sYUFBYSxHQUFHLEtBQUssQ0FBQyxRQUFRLENBQUM7SUFDckMsTUFBTSxhQUFhLEdBQUcsS0FBSyxDQUFDLFFBQVEsQ0FBQztJQUNyQyxNQUFNLGFBQWEsR0FBRyxLQUFLLENBQUMsUUFBUSxJQUFJLEVBQUUsQ0FBQztJQUUzQyxPQUFPLENBQUMsR0FBRyxDQUFDLGFBQWEsYUFBYSxlQUFlLGFBQWEsZUFBZSxhQUFhLGVB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Q0FBQyxPQUFPLENBQUMsQ0FBQztRQUM1QixPQUFPLElBQUksQ0FBQztJQUNkLENBQUMsQ0FBQyxDQUFDO0FBQ1AsQ0FBQyxDQUFDO0FBRUYsTUFBTSxVQUFVLEdBQUcsQ0FBQyxPQUFlLEVBQUUsRUFBRTtJQUNyQyxJQUFJLE9BQU8sQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztRQUMxQixPQUFPO1FBQ1AsSUFBSSxLQUFLLEdBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxJQUFJLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3JFLElBQUksTUFBTSxHQUFHLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUN2QixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsS0FBSyxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO1lBQ3RDLE1BQU0sR0FBRyxNQUFNLEdBQUcsTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLE1BQU0sQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDckUsQ0FBQztRQUNELE9BQU8sTUFBTSxDQUFDO0lBQ2hCLENBQUM7U0FBTSxDQUFDO1FBQ04sT0FBTztRQUNQLElBQUksS0FBSyxHQUFHLE9BQU8sQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsUUFBUSxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQy9ELElBQUksTUFBTSxHQUFHLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUN2QixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsS0FBSyxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO1lBQ3RDLE1BQU0sR0FBRyxNQUFNLEdBQUcsTUFBTSxDQUFDLEdBQUcsQ0FBQyxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNuRCxDQUFDO1FBQ0QsT0FBTyxNQUFNLENBQUM7SUFDaEIsQ0FBQztBQUNILENBQUMsQ0FBQztBQUVGLE1BQU0sY0FBYyxHQUFHLENBQUMsSUFBWSxFQUFrQyxFQUFFO0lBQ3RFLE1BQU0sQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUN4QyxNQUFNLE1BQU0sR0FBRyxPQUFPLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ3JDLE1BQU0sU0FBUyxHQUFHLE1BQU0sQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7SUFDcEMsTUFBTSxhQUFhLEdBQUcsVUFBVSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQzFDLE1BQU0sUUFBUSxHQUFHLFNBQVMsR0FBRyxRQUFRLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQ2hELE1BQU0sVUFBVSxHQUFHLE1BQU0sQ0FBQyxDQUFDLENBQUMsSUFBSSxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUM7SUFFakQsTUFBTSxLQUFLLEdBQUcsYUFBYSxHQUFHLENBQUMsYUFBYSxHQUFHLFVBQVUsQ0FBQyxDQUFDO0lBQzNELE1BQU0sR0FBRyxHQUFHLEtBQUssR0FBRyxVQUFVLEdBQUcsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBRTNDLE9BQU8sRUFBRSxLQUFLLEVBQUUsR0FBRyxFQUFFLENBQUM7QUFDeEIsQ0FBQyxDQUFDO0FBRUYsTUFBTSxVQUFVLEdBQUcsQ0FBQyxNQUFjLEVBQUUsSUFBWSxFQUFFLEVBQUU7SUFDbEQsTUFBTSxRQUFRLEdBQUcsVUFBVSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQ3BDLE1BQU0sRUFBRSxLQUFLLEVBQUUsR0FBRyxFQUFFLEdBQUcsY0FBYyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzVDLE9BQU8sUUFBUSxJQUFJLEtBQUssSUFBSSxRQUFRLElBQUksR0FBRyxDQUFDO0FBQzlDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFNlY3JldHNNYW5hZ2VyQ2xpZW50LCBHZXRTZWNyZXRWYWx1ZUNvbW1hbmQsIEdldFNlY3JldFZhbHVlQ29tbWFuZE91dHB1dCB9IGZyb20gJ0Bhd3Mtc2RrL2NsaWVudC1zZWNyZXRzLW1hbmFnZXInO1xuaW1wb3J0IHsgVHJhbnNmZXJGYW1pbHlBdXRob3JpemVyRXZlbnQsIFRyYW5zZmVyRmFtaWx5QXV0aG9yaXplclJlc3VsdCB9IGZyb20gJ2F3cy1sYW1iZGEnO1xuXG5leHBvcnQgY2xhc3MgRW1wdHlTZWNyZXRWYWx1ZUVycm9yIGV4dGVuZHMgRXJyb3Ige1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBzdXBlcignR290IGEgc2VjcmV0IHZhbHVlIGlzIGVtcHR5LicpO1xuICAgIHRoaXMubmFtZSA9ICdFbXB0eVNlY3JldFZhbHVlRXJyb3InO1xuICB9XG59XG5cbmludGVyZmFjZSBTZWNyZXREaWN0IHtcbiAgW2tleTogc3RyaW5nXTogc3RyaW5nO1xufVxuXG5leHBvcnQgY29uc3QgaGFuZGxlciA9IGFzeW5jIChldmVudDogVHJhbnNmZXJGYW1pbHlBdXRob3JpemVyRXZlbnQpOiBQcm9taXNlPFRyYW5zZmVyRmFtaWx5QXV0aG9yaXplclJlc3VsdD4gPT4ge1xuICBjb25zdCByZXF1aXJlZFBhcmFtTGlzdCA9IFsnc2VydmVySWQnLCAndXNlcm5hbWUnLCAncHJvdG9jb2wnLCAnc291cmNlSXAnXTtcbiAgZm9yIChjb25zdCBwYXJhbWV0ZXIgb2YgcmVxdWlyZWRQYXJhbUxpc3QpIHtcbiAgICBpZiAoIWV2ZW50Lmhhc093blByb3BlcnR5KHBhcmFtZXRlcikpIHtcbiAgICAgIGNvbnNvbGUubG9nKGBJbmNvbWluZyAke3BhcmFtZXRlcn0gbWlzc2luZyAtIFVuZXhwZWN0ZWRgKTtcbiAgICAgIHJldHVybiB7fTtcbiAgICB9XG4gIH1cblxuICBjb25zdCBpbnB1dFNlcnZlcklkID0gZXZlbnQuc2VydmVySWQ7XG4gIGNvbnN0IGlucHV0VXNlcm5hbWUgPSBldmVudC51c2VybmFtZTtcbiAgY29uc3QgaW5wdXRQcm90b2NvbCA9IGV2ZW50LnByb3RvY29sO1xuICBjb25zdCBpbnB1dFNvdXJjZUlwID0gZXZlbnQuc291cmNlSXA7XG4gIGNvbnN0IGlucHV0UGFzc3dvcmQgPSBldmVudC5wYXNzd29yZCB8fCAnJztcblxuICBjb25zb2xlLmxvZyhgU2VydmVySWQ6ICR7aW5wdXRTZXJ2ZXJJZH0sIFVzZXJuYW1lOiAke2lucHV0VXNlcm5hbWV9LCBQcm90b2NvbDogJHtpbnB1dFByb3RvY29sfSwgU291cmNlSXA6ICR7aW5wdXRTb3VyY2VJcH1gKTtcblxuICBjb25zb2xlLmxvZygnU3RhcnQgVXNlciBBdXRoZW50aWNhdGlvbiBGbG93Jyk7XG4gIGxldCBhdXRoZW50aWNhdGlvblR5cGUgPSAnJztcbiAgaWYgKGlucHV0UGFzc3dvcmQgIT09ICcnKSB7XG4gICAgY29uc29sZS5sb2coJ1VzaW5nIFBBU1NXT1JEIGF1dGhlbnRpY2F0aW9uJyk7XG4gICAgYXV0aGVudGljYXRpb25UeXBlID0gJ1BBU1NXT1JEJztcbiAgfSBlbHNlIHtcbiAgICBpZiAoaW5wdXRQcm90b2NvbCA9PT0gJ0ZUUCcgfHwgaW5wdXRQcm90b2NvbCA9PT0gJ0ZUUFMnKSB7XG4gICAgICBjb25zb2xlLmxvZygnRW1wdHkgcGFzc3dvcmQgbm90IGFsbG93ZWQgZm9yIEZUUC9TJyk7XG4gICAgICByZXR1cm4ge307XG4gICAgfVxuICAgIGNvbnNvbGUubG9nKCdVc2luZyBTU0ggYXV0aGVudGljYXRpb24nKTtcbiAgICBhdXRoZW50aWNhdGlvblR5cGUgPSAnU1NIUHViS2V5JztcbiAgfVxuXG4gIGNvbnN0IHNlY3JldCA9IGF3YWl0IGdldFNlY3JldChgdHJhbnNmZXItdXNlci8ke2lucHV0U2VydmVySWR9LyR7aW5wdXRVc2VybmFtZX1gKTtcblxuICBpZiAoc2VjcmV0KSB7XG4gICAgY29uc3Qgc2VjcmV0RGljdCA9IEpTT04ucGFyc2Uoc2VjcmV0KSBhcyBTZWNyZXREaWN0O1xuICAgIGNvbnN0IHVzZXJBdXRoZW50aWNhdGVkID0gKCgpID0+IHtcbiAgICAgIGlmIChhdXRoZW50aWNhdGlvblR5cGUgPT09ICdTU0hQdWJLZXknKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKCdTa2lwIHBhc3N3b3JkIGNoZWNrIGFzIFNTSCBsb2dpbiByZXF1ZXN0Jyk7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGF1dGhlbnRpY2F0ZVBhc3N3b3JkVXNlcihzZWNyZXREaWN0LCBpbnB1dFBhc3N3b3JkLCBpbnB1dFByb3RvY29sKTtcbiAgICB9KSgpO1xuICAgIGNvbnN0IGlwTWF0Y2ggPSBjaGVja0lwQWRkcmVzcyhzZWNyZXREaWN0LCBpbnB1dFNvdXJjZUlwLCBpbnB1dFByb3RvY29sKTtcblxuICAgIGlmICh1c2VyQXV0aGVudGljYXRlZCAmJiBpcE1hdGNoKSB7XG4gICAgICBjb25zb2xlLmxvZyhgVXNlciBhdXRoZW50aWNhdGVkLCBjYWxsaW5nIGJ1aWxkUmVzcG9uc2Ugd2l0aDogJHthdXRoZW50aWNhdGlvblR5cGV9YCk7XG4gICAgICByZXR1cm4gYnVpbGRSZXNwb25zZShzZWNyZXREaWN0LCBhdXRoZW50aWNhdGlvblR5cGUsIGlucHV0UHJvdG9jb2wpO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zb2xlLmxvZygnVXNlciBmYWlsZWQgYXV0aGVudGljYXRpb24gcmV0dXJuIGVtcHR5IHJlc3BvbnNlJyk7XG4gICAgICByZXR1cm4ge307XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIGNvbnNvbGUubG9nKCdTZWNyZXRzIE1hbmFnZXIgZXhjZXB0aW9uIHRocm93biAtIFJldHVybmluZyBlbXB0eSByZXNwb25zZScpO1xuICAgIHJldHVybiB7fTtcbiAgfVxufTtcblxuY29uc3QgbG9va3VwID0gKHNlY3JldERpY3Q6IFNlY3JldERpY3QsIGtleTogc3RyaW5nLCBpbnB1dFByb3RvY29sOiBzdHJpbmcpOiBzdHJpbmcgfCBudWxsID0+IHtcbiAgaWYgKHNlY3JldERpY3RbYCR7aW5wdXRQcm90b2NvbH0ke2tleX1gXSkge1xuICAgIGNvbnNvbGUubG9nKGBGb3VuZCBwcm90b2NvbC1zcGVjaWZpZWQgJHtrZXl9YCk7XG4gICAgcmV0dXJuIHNlY3JldERpY3RbYCR7aW5wdXRQcm90b2NvbH0ke2tleX1gXTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gc2VjcmV0RGljdFtrZXldIHx8IG51bGw7XG4gIH1cbn07XG5cbmNvbnN0IGNoZWNrSXBBZGRyZXNzID0gKHNlY3JldERpY3Q6IFNlY3JldERpY3QsIGlucHV0U291cmNlSXA6IHN0cmluZywgaW5wdXRQcm90b2NvbDogc3RyaW5nKTogYm9vbGVhbiA9PiB7XG4gIGNvbnN0IGFjY2VwdGVkSXBOZXR3b3JrcyA9IGxvb2t1cChzZWNyZXREaWN0LCAnQWNjZXB0ZWRJcE5ldHdvcmtzJywgaW5wdXRQcm90b2NvbCk7XG4gIGNvbnNvbGUubG9nKGBBY2NlcHRlZElwTmV0d29ya3M6ICR7YWNjZXB0ZWRJcE5ldHdvcmtzfWApO1xuICBpZiAoIWFjY2VwdGVkSXBOZXR3b3Jrcykge1xuICAgIGNvbnNvbGUubG9nKCdVbmFibGUgdG8gYXV0aGVudGljYXRlIHVzZXIgLSBObyBmaWxlZCBtYXRjaCBpbiBTZWNyZXQgZm9yIEFjY2VwdGVkSXBOZXR3b3JrcyhDSURSIGZvcm1hdCwgY29tbWEtc2VwYXJhdGVkKScpO1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGZvciAoY29uc3QgY2lkciBvZiBhY2NlcHRlZElwTmV0d29ya3Muc3BsaXQoJywnKSkge1xuICAgIGlmIChpc0lwSW5DaWRyKGlucHV0U291cmNlSXAsIGNpZHIpKSB7XG4gICAgICBjb25zb2xlLmxvZygnU291cmNlIElQIGFkZHJlc3MgbWF0Y2gnKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIGNvbnNvbGUubG9nKCdTb3VyY2UgSVAgYWRkcmVzcyBub3QgaW4gcmFuZ2UnKTtcbiAgcmV0dXJuIGZhbHNlO1xufTtcblxuY29uc3QgYXV0aGVudGljYXRlUGFzc3dvcmRVc2VyID0gKHNlY3JldERpY3Q6IFNlY3JldERpY3QsIGlucHV0UGFzc3dvcmQ6IHN0cmluZywgaW5wdXRQcm90b2NvbDogc3RyaW5nKTogYm9vbGVhbiA9PiB7XG4gIGNvbnN0IHBhc3N3b3JkID0gbG9va3VwKHNlY3JldERpY3QsICdQYXNzd29yZCcsIGlucHV0UHJvdG9jb2wpO1xuICBpZiAoIXBhc3N3b3JkKSB7XG4gICAgY29uc29sZS5sb2coJ1VuYWJsZSB0byBhdXRoZW50aWNhdGUgdXNlciAtIE5vIGZpZWxkIG1hdGNoIGluIFNlY3JldCBmb3IgcGFzc3dvcmQnKTtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBpZiAoaW5wdXRQYXNzd29yZCA9PT0gcGFzc3dvcmQpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfSBlbHNlIHtcbiAgICBjb25zb2xlLmxvZygnVW5hYmxlIHRvIGF1dGhlbnRpY2F0ZSB1c2VyIC0gSW5jb21pbmcgcGFzc3dvcmQgZG9lcyBub3QgbWF0Y2ggc3RvcmVkJyk7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG59O1xuXG5jb25zdCBidWlsZFJlc3BvbnNlID0gKHNlY3JldERpY3Q6IFNlY3JldERpY3QsIGF1dGhUeXBlOiBzdHJpbmcsIGlucHV0UHJvdG9jb2w6IHN0cmluZyk6IFRyYW5zZmVyRmFtaWx5QXV0aG9yaXplclJlc3VsdCA9PiB7XG4gIGNvbnN0IHJlc3BvbnNlRGF0YTogVHJhbnNmZXJGYW1pbHlBdXRob3JpemVyUmVzdWx0ID0ge307XG5cbiAgY29uc3Qgcm9sZSA9IGxvb2t1cChzZWNyZXREaWN0LCAnUm9sZScsIGlucHV0UHJvdG9jb2wpO1xuICBpZiAocm9sZSkge1xuICAgIHJlc3BvbnNlRGF0YS5Sb2xlID0gcm9sZTtcbiAgfSBlbHNlIHtcbiAgICBjb25zb2xlLmxvZygnTm8gZmllbGQgbWF0Y2ggZm9yIHJvbGUgLSBTZXQgZW1wdHkgc3RyaW5nIGluIHJlc3BvbnNlJyk7XG4gICAgcmVzcG9uc2VEYXRhLlJvbGUgPSAnJztcbiAgfVxuXG4gIGNvbnN0IHBvbGljeSA9IGxvb2t1cChzZWNyZXREaWN0LCAnUG9saWN5JywgaW5wdXRQcm90b2NvbCk7XG4gIGlmIChwb2xpY3kpIHtcbiAgICByZXNwb25zZURhdGEuUG9saWN5ID0gcG9saWN5O1xuICB9XG5cbiAgY29uc3QgaG9tZURpcmVjdG9yeURldGFpbHMgPSBsb29rdXAoc2VjcmV0RGljdCwgJ0hvbWVEaXJlY3RvcnlEZXRhaWxzJywgaW5wdXRQcm90b2NvbCk7XG4gIGlmIChob21lRGlyZWN0b3J5RGV0YWlscykge1xuICAgIGNvbnNvbGUubG9nKCdIb21lRGlyZWN0b3J5RGV0YWlscyBmb3VuZCAtIEFwcGx5aW5nIHNldHRpbmcgZm9yIHZpcnR1YWwgZm9sZGVycyAtIE5vdGU6IENhbm5vdCBiZSB1c2VkIGluIGNvbmp1bmN0aW9uIHdpdGgga2V5OiBIb21lRGlyZWN0b3J5Jyk7XG4gICAgcmVzcG9uc2VEYXRhLkhvbWVEaXJlY3RvcnlEZXRhaWxzID0gaG9tZURpcmVjdG9yeURldGFpbHM7XG4gICAgY29uc29sZS5sb2coJ1NldHRpbmcgSG9tZURpcmVjdG9yeVR5cGUgdG8gTE9HSUNBTCcpO1xuICAgIHJlc3BvbnNlRGF0YS5Ib21lRGlyZWN0b3J5VHlwZSA9ICdMT0dJQ0FMJztcbiAgfVxuXG4gIGNvbnN0IGhvbWVEaXJlY3RvcnkgPSBsb29rdXAoc2VjcmV0RGljdCwgJ0hvbWVEaXJlY3RvcnknLCBpbnB1dFByb3RvY29sKTtcbiAgaWYgKGhvbWVEaXJlY3RvcnkpIHtcbiAgICBjb25zb2xlLmxvZygnSG9tZURpcmVjdG9yeSBmb3VuZCAtIE5vdGU6IENhbm5vdCBiZSB1c2VkIGluIGNvbmp1bmN0aW9uIHdpdGgga2V5OiBIb21lRGlyZWN0b3J5RGV0YWlscycpO1xuICAgIHJlc3BvbnNlRGF0YS5Ib21lRGlyZWN0b3J5ID0gaG9tZURpcmVjdG9yeTtcbiAgfVxuXG4gIGlmIChhdXRoVHlwZSA9PT0gJ1NTSFB1YktleScpIHtcbiAgICBjb25zdCBwdWJsaWNLZXkgPSBsb29rdXAoc2VjcmV0RGljdCwgJ1B1YmxpY0tleScsIGlucHV0UHJvdG9jb2wpO1xuICAgIGlmIChwdWJsaWNLZXkpIHtcbiAgICAgIHJlc3BvbnNlRGF0YS5QdWJsaWNLZXlzID0gW3B1YmxpY0tleV07XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnNvbGUubG9nKCdVbmFibGUgdG8gYXV0aGVudGljYXRlIHVzZXIgLSBObyBwdWJsaWMga2V5cyBmb3VuZCcpO1xuICAgICAgcmV0dXJuIHt9O1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiByZXNwb25zZURhdGE7XG59O1xuXG5jb25zdCBnZXRTZWNyZXQgPSBhc3luYyAoaWQ6IHN0cmluZyk6IFByb21pc2U8c3RyaW5nIHwgbnVsbD4gPT4ge1xuICBjb25zb2xlLmxvZyhgU2VjcmV0IE5hbWU6ICR7aWR9YCk7XG5cbiAgY29uc3QgY2xpZW50ID0gbmV3IFNlY3JldHNNYW5hZ2VyQ2xpZW50KHtcbiAgICByZWdpb246ICdhcC1ub3J0aGVhc3QtMScsXG4gIH0pO1xuXG4gIHJldHVybiBjbGllbnQuc2VuZChuZXcgR2V0U2VjcmV0VmFsdWVDb21tYW5kKHsgU2VjcmV0SWQ6IGlkIH0pKVxuICAgIC50aGVuKChkYXRhOiBHZXRTZWNyZXRWYWx1ZUNvbW1hbmRPdXRwdXQpID0+IHtcbiAgICAgIGlmIChkYXRhLlNlY3JldEJpbmFyeSkge1xuICAgICAgICBjb25zb2xlLmxvZygnR290IFNlY3JldEJpbmFyeSB2YWx1ZScpO1xuICAgICAgICByZXR1cm4gQnVmZmVyLmZyb20oZGF0YS5TZWNyZXRCaW5hcnkpLnRvU3RyaW5nKCd1dGYtOCcpO1xuICAgICAgfVxuICAgICAgaWYgKGRhdGEuU2VjcmV0U3RyaW5nKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKCdHb3QgU2VjcmV0U3RyaW5nIHZhbHVlJyk7XG4gICAgICAgIHJldHVybiBkYXRhLlNlY3JldFN0cmluZztcbiAgICAgIH1cbiAgICAgIHRocm93IG5ldyBFbXB0eVNlY3JldFZhbHVlRXJyb3IoKTtcbiAgICB9KVxuICAgIC5jYXRjaCgoZXJyb3I6IEVycm9yKSA9PiB7XG4gICAgICBjb25zb2xlLndhcm4oZXJyb3IubWVzc2FnZSk7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9KTtcbn07XG5cbmNvbnN0IGlwVG9CaWdJbnQgPSAoYWRkcmVzczogc3RyaW5nKSA9PiB7XG4gIGlmIChhZGRyZXNzLmluY2x1ZGVzKCc6JykpIHtcbiAgICAvLyBJUHY2XG4gICAgbGV0IHBhcnRzID0gYWRkcmVzcy5zcGxpdCgnOicpLm1hcChwYXJ0ID0+IHBhcnQgPT09ICcnID8gJzAnIDogcGFydCk7XG4gICAgbGV0IGJpZ0ludCA9IEJpZ0ludCgwKTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHBhcnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBiaWdJbnQgPSBiaWdJbnQgKiBCaWdJbnQoMHgxMDAwMCkgKyBCaWdJbnQocGFyc2VJbnQocGFydHNbaV0sIDE2KSk7XG4gICAgfVxuICAgIHJldHVybiBiaWdJbnQ7XG4gIH0gZWxzZSB7XG4gICAgLy8gSVB2NFxuICAgIGxldCBwYXJ0cyA9IGFkZHJlc3Muc3BsaXQoJy4nKS5tYXAocGFydCA9PiBwYXJzZUludChwYXJ0LCAxMCkpO1xuICAgIGxldCBiaWdJbnQgPSBCaWdJbnQoMCk7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBwYXJ0cy5sZW5ndGg7IGkrKykge1xuICAgICAgYmlnSW50ID0gYmlnSW50ICogQmlnSW50KDI1NikgKyBCaWdJbnQocGFydHNbaV0pO1xuICAgIH1cbiAgICByZXR1cm4gYmlnSW50O1xuICB9XG59O1xuXG5jb25zdCBnZXRTdWJuZXRSYW5nZSA9IChjaWRyOiBzdHJpbmcpOiB7IHN0YXJ0OiBiaWdpbnQ7IGVuZDogYmlnaW50IH0gPT4ge1xuICBjb25zdCBbbmV0d29yaywgYml0c10gPSBjaWRyLnNwbGl0KCcvJyk7XG4gIGNvbnN0IGlzSVB2NiA9IG5ldHdvcmsuaW5jbHVkZXMoJzonKTtcbiAgY29uc3QgdG90YWxCaXRzID0gaXNJUHY2ID8gMTI4IDogMzI7XG4gIGNvbnN0IG5ldHdvcmtCaWdJbnQgPSBpcFRvQmlnSW50KG5ldHdvcmspO1xuICBjb25zdCBob3N0Qml0cyA9IHRvdGFsQml0cyAtIHBhcnNlSW50KGJpdHMsIDEwKTtcbiAgY29uc3Qgc3VibmV0U2l6ZSA9IEJpZ0ludCgyKSAqKiBCaWdJbnQoaG9zdEJpdHMpO1xuXG4gIGNvbnN0IHN0YXJ0ID0gbmV0d29ya0JpZ0ludCAtIChuZXR3b3JrQmlnSW50ICUgc3VibmV0U2l6ZSk7XG4gIGNvbnN0IGVuZCA9IHN0YXJ0ICsgc3VibmV0U2l6ZSAtIEJpZ0ludCgxKTtcblxuICByZXR1cm4geyBzdGFydCwgZW5kIH07XG59O1xuXG5jb25zdCBpc0lwSW5DaWRyID0gKGlwQWRkcjogc3RyaW5nLCBjaWRyOiBzdHJpbmcpID0+IHtcbiAgY29uc3QgaXBCaWdJbnQgPSBpcFRvQmlnSW50KGlwQWRkcik7XG4gIGNvbnN0IHsgc3RhcnQsIGVuZCB9ID0gZ2V0U3VibmV0UmFuZ2UoY2lkcik7XG4gIHJldHVybiBpcEJpZ0ludCA+PSBzdGFydCAmJiBpcEJpZ0ludCA8PSBlbmQ7XG59OyJdfQ==
package/lib/index.js CHANGED
@@ -45,5 +45,5 @@ class TransferCustomLambdaIdentityProvider extends constructs_1.Construct {
45
45
  }
46
46
  exports.TransferCustomLambdaIdentityProvider = TransferCustomLambdaIdentityProvider;
47
47
  _a = JSII_RTTI_SYMBOL_1;
48
- TransferCustomLambdaIdentityProvider[_a] = { fqn: "@gammarers/aws-transfer-custom-lambda-identity-provider.TransferCustomLambdaIdentityProvider", version: "1.0.2" };
48
+ TransferCustomLambdaIdentityProvider[_a] = { fqn: "@gammarers/aws-transfer-custom-lambda-identity-provider.TransferCustomLambdaIdentityProvider", version: "1.1.0" };
49
49
  //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSw2Q0FBb0M7QUFDcEMsMkNBQTJDO0FBQzNDLDJDQUF1QztBQUN2Qyx5R0FBbUc7QUFFbkcsK0RBQStEO0FBRS9ELE1BQWEsb0NBQXFDLFNBQVEsc0JBQVM7SUFFakUsZ0dBQWdHO0lBQ2hHLFlBQVksS0FBZ0IsRUFBRSxFQUFVO1FBQ3RDLE1BQU0sT0FBTyxHQUFHLG1CQUFLLENBQUMsRUFBRSxDQUFDLEtBQUssQ0FBQyxDQUFDLE9BQU8sQ0FBQztRQUN4QyxNQUFNLE1BQU0sR0FBRyxtQkFBSyxDQUFDLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxNQUFNLENBQUM7UUFDdEMsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQztRQUVqQixNQUFNLElBQUksR0FBRyxJQUFJLDBFQUFrQyxDQUFDLElBQUksRUFBRSxvQ0FBb0MsRUFBRTtZQUM5RixXQUFXLEVBQUUscUVBQXFFO1lBQ2xGLElBQUksRUFBRSxJQUFJLEdBQUcsQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLGtEQUFrRCxFQUFFO2dCQUM1RSxTQUFTLEVBQUUsSUFBSSxHQUFHLENBQUMsZ0JBQWdCLENBQUMsc0JBQXNCLENBQUM7Z0JBQzNELGVBQWUsRUFBRTtvQkFDZixHQUFHLENBQUMsYUFBYSxDQUFDLHdCQUF3QixDQUFDLDBDQUEwQyxDQUFDO2lCQUN2RjtnQkFDRCxjQUFjLEVBQUU7b0JBQ2QsQ0FBQyxtQkFBbUIsQ0FBQyxFQUFFLElBQUksR0FBRyxDQUFDLGNBQWMsQ0FBQzt3QkFDNUMsVUFBVSxFQUFFOzRCQUNWLElBQUksR0FBRyxDQUFDLGVBQWUsQ0FBQztnQ0FDdEIsTUFBTSxFQUFFLEdBQUcsQ0FBQyxNQUFNLENBQUMsS0FBSztnQ0FDeEIsT0FBTyxFQUFFO29DQUNQLCtCQUErQjtpQ0FDaEM7Z0NBQ0QsU0FBUyxFQUFFO29DQUNULDBCQUEwQixNQUFNLElBQUksT0FBTyxzQkFBc0I7aUNBQ2xFOzZCQUNGLENBQUM7eUJBQ0g7cUJBQ0YsQ0FBQztpQkFDSDthQUNGLENBQUM7U0FDSCxDQUFDLENBQUM7UUFDSCxJQUFJLENBQUMsYUFBYSxDQUFDLHdCQUF3QixFQUFFO1lBQzNDLFNBQVMsRUFBRSxJQUFJLEdBQUcsQ0FBQyxnQkFBZ0IsQ0FBQyx3QkFBd0IsQ0FBQztTQUM5RCxDQUFDLENBQUM7SUFDTCxDQUFDOztBQW5DSCxvRkFvQ0MiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBTdGFjayB9IGZyb20gJ2F3cy1jZGstbGliJztcbmltcG9ydCAqIGFzIGlhbSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtaWFtJztcbmltcG9ydCB7IENvbnN0cnVjdCB9IGZyb20gJ2NvbnN0cnVjdHMnO1xuaW1wb3J0IHsgVHJhbnNmZXJVc2VyQXV0aGVudGljYXRpb25GdW5jdGlvbiB9IGZyb20gJy4vZnVuY3MvdHJhbnNmZXItdXNlci1hdXRoZW50aWNhdGlvbi1mdW5jdGlvbic7XG5cbi8vZXhwb3J0IGludGVyZmFjZSBUcmFuc2ZlckN1c3RvbUxhbWJkYUlkZW50aXR5UHJvdmlkZXJQcm9wcyB7fVxuXG5leHBvcnQgY2xhc3MgVHJhbnNmZXJDdXN0b21MYW1iZGFJZGVudGl0eVByb3ZpZGVyIGV4dGVuZHMgQ29uc3RydWN0IHtcblxuICAvL2NvbnN0cnVjdG9yKHNjb3BlOiBDb25zdHJ1Y3QsIGlkOiBzdHJpbmcsIHByb3BzPzogVHJhbnNmZXJDdXN0b21MYW1iZGFJZGVudGl0eVByb3ZpZGVyUHJvcHMpIHtcbiAgY29uc3RydWN0b3Ioc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZykge1xuICAgIGNvbnN0IGFjY291bnQgPSBTdGFjay5vZihzY29wZSkuYWNjb3VudDtcbiAgICBjb25zdCByZWdpb24gPSBTdGFjay5vZihzY29wZSkucmVnaW9uO1xuICAgIHN1cGVyKHNjb3BlLCBpZCk7XG5cbiAgICBjb25zdCBmdW5jID0gbmV3IFRyYW5zZmVyVXNlckF1dGhlbnRpY2F0aW9uRnVuY3Rpb24odGhpcywgJ1RyYW5zZmVyVXNlckF1dGhlbnRpY2F0aW9uRnVuY3Rpb24nLCB7XG4gICAgICBkZXNjcmlwdGlvbjogJ0EgZnVuY3Rpb24gdG8gbG9va3VwIGFuZCByZXR1cm4gdXNlciBkYXRhIGZyb20gQVdTIFNlY3JldHMgTWFuYWdlci4nLFxuICAgICAgcm9sZTogbmV3IGlhbS5Sb2xlKHNjb3BlLCAnVHJhbnNmZXJDdXN0b21MYW1iZGFJZGVudGl0eVByb3ZpZGVyRnVuY3Rpb25Sb2xlJywge1xuICAgICAgICBhc3N1bWVkQnk6IG5ldyBpYW0uU2VydmljZVByaW5jaXBhbCgnbGFtYmRhLmFtYXpvbmF3cy5jb20nKSxcbiAgICAgICAgbWFuYWdlZFBvbGljaWVzOiBbXG4gICAgICAgICAgaWFtLk1hbmFnZWRQb2xpY3kuZnJvbUF3c01hbmFnZWRQb2xpY3lOYW1lKCdzZXJ2aWNlLXJvbGUvQVdTTGFtYmRhQmFzaWNFeGVjdXRpb25Sb2xlJyksXG4gICAgICAgIF0sXG4gICAgICAgIGlubGluZVBvbGljaWVzOiB7XG4gICAgICAgICAgWydnZXQtc2VjcmV0LXBvbGljeSddOiBuZXcgaWFtLlBvbGljeURvY3VtZW50KHtcbiAgICAgICAgICAgIHN0YXRlbWVudHM6IFtcbiAgICAgICAgICAgICAgbmV3IGlhbS5Qb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgICAgICAgICAgIGVmZmVjdDogaWFtLkVmZmVjdC5BTExPVyxcbiAgICAgICAgICAgICAgICBhY3Rpb25zOiBbXG4gICAgICAgICAgICAgICAgICAnc2VjcmV0c21hbmFnZXI6R2V0U2VjcmV0VmFsdWUnLFxuICAgICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICAgICAgcmVzb3VyY2VzOiBbXG4gICAgICAgICAgICAgICAgICBgYXJuOmF3czpzZWNyZXRzbWFuYWdlcjoke3JlZ2lvbn06JHthY2NvdW50fTpzZWNyZXQ6dHJhbnNmZXIvcy0qYCxcbiAgICAgICAgICAgICAgICBdLFxuICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgfSksXG4gICAgICAgIH0sXG4gICAgICB9KSxcbiAgICB9KTtcbiAgICBmdW5jLmFkZFBlcm1pc3Npb24oJ0xhbWJkYUFjY2Vzc1Blcm1pc3Npb24nLCB7XG4gICAgICBwcmluY2lwYWw6IG5ldyBpYW0uU2VydmljZVByaW5jaXBhbCgndHJhbnNmZXIuYW1hem9uYXdzLmNvbScpLFxuICAgIH0pO1xuICB9XG59XG4iXX0=
package/package.json CHANGED
@@ -85,7 +85,7 @@
85
85
  "publishConfig": {
86
86
  "access": "public"
87
87
  },
88
- "version": "1.0.2",
88
+ "version": "1.1.0",
89
89
  "jest": {
90
90
  "coverageProvider": "v8",
91
91
  "snapshotSerializers": [