@pipeline-builder/pipeline-manager 4.1.3 → 4.1.5

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.
Files changed (52) hide show
  1. package/README.md +2 -1
  2. package/dist/agent/env-file.d.ts +1 -1
  3. package/dist/agent/env-file.js +2 -2
  4. package/dist/agent/post-steps.d.ts.map +1 -1
  5. package/dist/agent/post-steps.js +38 -18
  6. package/dist/cli.d.ts.map +1 -1
  7. package/dist/cli.js +19 -9
  8. package/dist/commands/audit-tokens.d.ts.map +1 -1
  9. package/dist/commands/audit-tokens.js +32 -21
  10. package/dist/commands/create-pat.d.ts +20 -13
  11. package/dist/commands/create-pat.d.ts.map +1 -1
  12. package/dist/commands/create-pat.js +93 -98
  13. package/dist/commands/login.d.ts +14 -8
  14. package/dist/commands/login.d.ts.map +1 -1
  15. package/dist/commands/login.js +89 -124
  16. package/dist/commands/setup-events.d.ts.map +1 -1
  17. package/dist/commands/setup-events.js +6 -5
  18. package/dist/commands/status.d.ts.map +1 -1
  19. package/dist/commands/status.js +9 -3
  20. package/dist/commands/store-token.d.ts +16 -11
  21. package/dist/commands/store-token.d.ts.map +1 -1
  22. package/dist/commands/store-token.js +213 -131
  23. package/dist/lambda/token-renew-handler.d.ts.map +1 -1
  24. package/dist/lambda/token-renew-handler.js +134 -97
  25. package/dist/templates/events-stack.json +1 -1
  26. package/dist/templates/token-renew-stack.json +9 -10
  27. package/dist/utils/auth-utils.d.ts +21 -38
  28. package/dist/utils/auth-utils.d.ts.map +1 -1
  29. package/dist/utils/auth-utils.js +20 -33
  30. package/dist/utils/command-utils.d.ts +8 -6
  31. package/dist/utils/command-utils.d.ts.map +1 -1
  32. package/dist/utils/command-utils.js +71 -15
  33. package/dist/utils/config-loader.d.ts +2 -1
  34. package/dist/utils/config-loader.d.ts.map +1 -1
  35. package/dist/utils/config-loader.js +18 -8
  36. package/dist/utils/credential-store.d.ts +23 -0
  37. package/dist/utils/credential-store.d.ts.map +1 -0
  38. package/dist/utils/credential-store.js +92 -0
  39. package/dist/utils/device-auth.d.ts +59 -0
  40. package/dist/utils/device-auth.d.ts.map +1 -0
  41. package/dist/utils/device-auth.js +139 -0
  42. package/dist/utils/pipeline-config.js +2 -2
  43. package/dist/utils/platform-secret.d.ts +19 -1
  44. package/dist/utils/platform-secret.d.ts.map +1 -1
  45. package/dist/utils/platform-secret.js +26 -4
  46. package/dist/utils/service-account.d.ts +73 -0
  47. package/dist/utils/service-account.d.ts.map +1 -0
  48. package/dist/utils/service-account.js +158 -0
  49. package/package.json +4 -4
  50. package/dist/utils/rate-limiter.d.ts +0 -15
  51. package/dist/utils/rate-limiter.d.ts.map +0 -1
  52. package/dist/utils/rate-limiter.js +0 -164
@@ -9,14 +9,14 @@ import { LambdaClient, UpdateFunctionCodeCommand } from '@aws-sdk/client-lambda'
9
9
  import { Command } from 'commander';
10
10
  import { APP_VERSION, validateNumber } from '../config/cli.constants.js';
11
11
  import { auditLog } from '../utils/audit-log.js';
12
- import { decodeTokenPayload } from '../utils/auth-guard.js';
13
12
  import { resolveAwsRegion } from '../utils/aws-env.js';
14
- import { upsertSecret, getSecretArn } from '../utils/aws-secrets.js';
13
+ import { upsertSecret, getSecretArn, getSecretValue } from '../utils/aws-secrets.js';
15
14
  import { createAuthenticatedClientAsync, printCommandHeader, printSslWarning, withProfileOption, withRegionOption, withSslOptions } from '../utils/command-utils.js';
16
15
  import { toEventBridgeCron } from '../utils/cron.js';
17
16
  import { ERROR_CODES, handleError } from '../utils/error-handler.js';
18
- import { printInfo, printKeyValue, printSection, printSuccess } from '../utils/output-utils.js';
19
- import { ensurePlatformToken, resolveSecretName } from '../utils/platform-secret.js';
17
+ import { printInfo, printKeyValue, printSection, printSuccess, printWarning } from '../utils/output-utils.js';
18
+ import { ensurePlatformToken, scopeSecretLeaf, secretNameForOrg } from '../utils/platform-secret.js';
19
+ import { provisionServiceAccountKey, revokeServiceAccountKey } from '../utils/service-account.js';
20
20
  // ESM has no __dirname; derive it from this module's URL.
21
21
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
22
22
  const RENEW_STACK_NAME = 'pipeline-builder-token-renew';
@@ -25,18 +25,41 @@ const RENEW_LAMBDA_NAME = 'pipeline-builder-token-renew';
25
25
  // Default 5-field cron (daily at midnight) when neither --cron nor TOKEN_RENEW_SCHEDULE is set.
26
26
  const DEFAULT_RENEW_CRON = '0 0 * * *';
27
27
  /**
28
- * Deploy (or update) the once-a-day token-renewal stack: a scheduled Lambda that
29
- * re-mints the platform JWT in this same secret before it expires. Mirrors
28
+ * Capability scopes a stored credential may carry, and what each one is FOR.
29
+ *
30
+ * A scoped key exchanges to a token with no permissions and no admin flags at
31
+ * all — only the one capability — so it is the shape every automation that does
32
+ * exactly one thing should hold (#12). The unscoped `platform` credential is the
33
+ * remaining full-privilege one: synth/deploy callbacks and the plugin-lookup
34
+ * Lambda call the ordinary API surface, which no single scope covers.
35
+ */
36
+ const SCOPE_CATALOG = {
37
+ 'reporting:ingest': {
38
+ account: 'reporting-ingest',
39
+ description: 'AWS pipeline-event ingestion (the events Lambda POSTs /reports/events)',
40
+ },
41
+ 'registry:push': {
42
+ account: 'registry-push',
43
+ description: 'CI image pushes into this org’s registry namespace (CodeBuild → /token)',
44
+ },
45
+ };
46
+ /** The account that holds the unscoped, full-privilege stored credential. */
47
+ const PLATFORM_ACCOUNT = {
48
+ account: 'platform-automation',
49
+ description: 'Stored platform credential for CDK synth/deploy, plugin lookup and image pushes',
50
+ };
51
+ /**
52
+ * Deploy (or update) the once-a-day KEY ROTATION stack: a scheduled Lambda that
53
+ * replaces the service-account key in this secret before it expires. Mirrors
30
54
  * setup-events — `aws cloudformation deploy` for the infra, then a direct
31
- * UpdateFunctionCode with the thin orchestrator handler compiled alongside this
32
- * CLI (the handler npm-installs pipeline-manager at runtime and re-runs
33
- * store-token; see src/lambda/token-renew-handler.ts).
55
+ * UpdateFunctionCode with the rotator handler compiled alongside this CLI (see
56
+ * src/lambda/token-renew-handler.ts).
34
57
  */
35
58
  async function deployRenewSchedule(opts) {
36
59
  const scheduleExpression = toEventBridgeCron(opts.fiveFieldCron); // validates + 15-min guard
37
- // Name renewal resources per-secret so a scoped-token stack (e.g. the
38
- // reporting-ingest credential the event Lambda reads) coexists with the
39
- // platform-token stack instead of colliding on the (account-global) IAM
60
+ // Name renewal resources per-secret so a scoped-credential stack (e.g. the
61
+ // reporting-ingest key the event Lambda reads) coexists with the
62
+ // platform-credential stack instead of colliding on the (account-global) IAM
40
63
  // role / Lambda / rule names. The platform secret keeps the bare name
41
64
  // (suffix '') so existing deployments' stack is updated in place, not
42
65
  // duplicated; any other secret appends its trailing path segment.
@@ -44,7 +67,7 @@ async function deployRenewSchedule(opts) {
44
67
  const nameSuffix = secretLeaf === 'platform' ? '' : `-${secretLeaf.replace(/[^a-z0-9]+/gi, '-')}`;
45
68
  const stackName = `${RENEW_STACK_NAME}${nameSuffix}`;
46
69
  const lambdaName = `${RENEW_LAMBDA_NAME}${nameSuffix}`;
47
- printSection('Schedule Renewal');
70
+ printSection('Schedule Rotation');
48
71
  printInfo('Parameters', {
49
72
  stack: stackName,
50
73
  schedule: opts.fiveFieldCron,
@@ -63,8 +86,9 @@ async function deployRenewSchedule(opts) {
63
86
  `RenewDays=${opts.days}`,
64
87
  `ScheduleExpression=${scheduleExpression}`,
65
88
  `NameSuffix=${nameSuffix}`,
66
- // Pin the handler's runtime npm install to THIS CLI's version (reproducible
67
- // renewals instead of a floating "latest").
89
+ // Recorded for provenance only — the rotator no longer installs the CLI at
90
+ // runtime (it speaks to the platform directly), but knowing which CLI
91
+ // deployed a stack is worth keeping.
68
92
  `PipelineManagerVersion=${APP_VERSION}`,
69
93
  '--capabilities', 'CAPABILITY_NAMED_IAM',
70
94
  '--no-fail-on-empty-changeset',
@@ -93,153 +117,204 @@ async function deployRenewSchedule(opts) {
93
117
  finally {
94
118
  fs.rmSync(tmpDir, { recursive: true, force: true });
95
119
  }
96
- printSuccess(`Renewal scheduled (${scheduleExpression})`);
120
+ printSuccess(`Rotation scheduled (${scheduleExpression})`);
97
121
  return scheduleExpression;
98
122
  }
123
+ /** Read the key id a previous run stored, so this run can retire it. */
124
+ async function previousKeyId(secretName, aws) {
125
+ try {
126
+ const raw = await getSecretValue(secretName, aws);
127
+ const parsed = JSON.parse(raw);
128
+ return { keyId: parsed.keyId, serviceAccountId: parsed.serviceAccountId };
129
+ }
130
+ catch {
131
+ // No secret yet (first run), or one written before the service-account
132
+ // cutover (no keyId). Either way there is nothing this run can retire.
133
+ return {};
134
+ }
135
+ }
99
136
  /**
100
137
  * Registers the `store-token` command with the CLI program.
101
138
  *
102
- * Generates a long-lived JWT token via the platform API and stores it
103
- * in AWS Secrets Manager for use by the synth/deploy --store-tokens flag.
139
+ * Provisions the org's machine identity — a SERVICE ACCOUNT and one `pb_sa_…`
140
+ * key — and stores the key in AWS Secrets Manager for CDK deployments,
141
+ * CodeBuild's registry credentials, the plugin-lookup Lambda and the event
142
+ * ingestion Lambda (#12 / #N2). Nothing stored is tied to a person's session any
143
+ * more: the account outlives its creator, takes no seat, and every audit row it
144
+ * produces names the account.
104
145
  *
105
- * Requires PLATFORM_TOKEN to be set, or use --email/--password to login inline.
146
+ * Because creating an account and issuing its key are step-up gated, this needs
147
+ * the operator's password — `--password`, or the `PLATFORM_PASSWORD` env var
148
+ * (preferred: it keeps the password out of shell history and plan output).
106
149
  *
107
150
  * By default it ONLY writes the secret. Pass --schedule to also deploy the daily
108
- * token-renewal stack (a Lambda that auto-renews this token before it expires).
151
+ * KEY ROTATION stack (a Lambda that replaces the key before it expires).
109
152
  *
110
153
  * @example
111
154
  * ```bash
112
- * pipeline-manager infra store-token --region us-east-1
113
- * pipeline-manager infra store-token --days 90 --region us-east-1
114
- * pipeline-manager infra store-token --schedule --region us-east-1 # + daily auto-renewal
115
- * pipeline-manager infra store-token --schedule --cron '0 3 * * *' # custom renewal time
116
- * pipeline-manager infra store-token --days 7 --no-verify-ssl
117
- * PLATFORM_SECRET_NAME=my-custom-secret pipeline-manager infra store-token # override the derived name
155
+ * PLATFORM_PASSWORD=*** pipeline-manager infra store-token --region us-east-1
156
+ * PLATFORM_PASSWORD=*** pipeline-manager infra store-token --days 90 --region us-east-1
157
+ * PLATFORM_PASSWORD=*** pipeline-manager infra store-token --schedule --region us-east-1 # + daily rotation
158
+ * PLATFORM_PASSWORD=*** pipeline-manager infra store-token --scope reporting:ingest --schedule
159
+ * PLATFORM_PASSWORD=*** pipeline-manager infra store-token --scope registry:push --schedule
118
160
  * pipeline-manager infra store-token --dry-run
119
- * pipeline-manager infra store-token -e admin -p '***' --region us-east-1
161
+ * pipeline-manager infra store-token -u admin -p '***' --region us-east-1
120
162
  * ```
121
163
  */
122
164
  export function storeToken(program) {
123
165
  withSslOptions(withProfileOption(withRegionOption(program
124
166
  .command('store-token')
125
- .description('Generate JWT token and store in AWS Secrets Manager for CDK deployments')
167
+ .description('Provision an org service-account key (its own machine identity) and store it in AWS Secrets Manager for CDK deployments')
126
168
  .option('-u, --identifier <identifier>', 'Username or email (skips PLATFORM_TOKEN requirement)')
127
- .option('-p, --password <password>', 'Login password (used with --identifier)')
128
- .option('--days <days>', 'Token lifetime in days', '30')
129
- .option('--scope <scope>', 'Mint a narrow-scope machine token (e.g. "reporting:ingest") and store it at a scope-specific secret path instead of the shared platform secret')
130
- .option('--dry-run', 'Show what would be stored without writing to Secrets Manager', false)))
131
- .option('--schedule', 'Also deploy the daily token-renewal stack that auto-renews this token (off by default)', false)
132
- .option('--cron <expr>', 'Renewal schedule as a 5-field cron, used with --schedule (default: TOKEN_RENEW_SCHEDULE env or "0 0 * * *"; min every 15 minutes)')
169
+ .option('-p, --password <password>', 'Login password — also used for the step-up every key write requires (prefer PLATFORM_PASSWORD)')
170
+ .option('--days <days>', 'Key lifetime in days (max 365)', '30')
171
+ .option('--scope <scope>', `Provision a least-privilege scoped key instead of the full-privilege platform one. One of: ${Object.keys(SCOPE_CATALOG).join(', ')}`)
172
+ .option('--account <name>', 'Override the service-account name this key is issued on (default: derived from --scope)')
173
+ .option('--dry-run', 'Show what would be provisioned without calling the platform or writing to Secrets Manager', false)))
174
+ .option('--schedule', 'Also deploy the daily key-rotation stack that replaces this key before it expires (off by default)', false)
175
+ .option('--cron <expr>', 'Rotation schedule as a 5-field cron, used with --schedule (default: TOKEN_RENEW_SCHEDULE env or "0 0 * * *"; min every 15 minutes)')
133
176
  .option('--json', 'Output result as JSON', false))
134
177
  .action(async (options) => {
135
178
  const executionId = printCommandHeader('Store Token', undefined, { quiet: options.json });
136
179
  try {
137
180
  printSslWarning(options.verifySsl);
138
181
  const region = resolveAwsRegion(options.region);
182
+ const aws = { region, profile: options.profile };
139
183
  const days = validateNumber(options.days, 'days', 1, 365);
140
184
  const expiresInSeconds = days * 24 * 60 * 60;
141
- // Step 0: log in first when creds are available and no PLATFORM_TOKEN is set
142
- // (shared with setup-events). Creds come from --email/--password OR the env
143
- // vars PLATFORM_IDENTIFIER/PLATFORM_PASSWORD — the env path lets callers like
144
- // `provision --with-events` pass them without putting the password on the
145
- // command line (where it would show in plans/logs).
185
+ const scope = options.scope;
186
+ const catalogued = scope ? SCOPE_CATALOG[scope] : undefined;
187
+ if (scope && !catalogued) {
188
+ throw new Error(`Unknown --scope "${scope}". Supported: ${Object.keys(SCOPE_CATALOG).join(', ')}`);
189
+ }
190
+ // Which machine identity this credential belongs to: the scope's own
191
+ // account, or the org's single full-privilege automation account.
192
+ const identity = catalogued ?? PLATFORM_ACCOUNT;
193
+ const accountName = options.account ?? identity.account;
194
+ // Step 0: log in first when creds are available and no PLATFORM_TOKEN is
195
+ // set (shared with setup-events). Creds come from --identifier/--password
196
+ // OR the env vars PLATFORM_IDENTIFIER/PLATFORM_PASSWORD — the env path
197
+ // lets callers like `provision --with-events` pass them without putting
198
+ // the password on the command line (where it would show in plans/logs).
146
199
  await ensurePlatformToken(options);
147
- // Step 1: Authenticate and generate long-lived token
148
- printSection('Generate Token');
200
+ // The password is ALSO the step-up factor for both writes below, so it is
201
+ // required even when PLATFORM_TOKEN is already set. Say that plainly
202
+ // rather than failing three calls later with a 403.
203
+ const password = options.password || process.env.PLATFORM_PASSWORD;
204
+ if (!password && !options.dryRun) {
205
+ throw new Error('A password is required: creating a service account and issuing its key are both step-up gated. '
206
+ + 'Set PLATFORM_PASSWORD (preferred) or pass --password.');
207
+ }
208
+ printSection('Provision Service-Account Key');
149
209
  const client = await createAuthenticatedClientAsync(options);
150
- // Resolve secret name from the token's organizationId. An explicit
151
- // PLATFORM_SECRET_NAME env wins (escape hatch for system/no-org tokens and
152
- // the renewal Lambda); otherwise derive `{prefix}/{orgId}/platform`.
153
- // A `--scope` token is a distinct machine credential — store it at a
154
- // scope-specific path (`.../reporting-ingest`) so it never clobbers the
155
- // full-privilege platform token used by synth/deploy callbacks.
156
- const scope = options.scope;
157
- const baseSecretName = process.env.PLATFORM_SECRET_NAME || resolveSecretName(process.env.PLATFORM_TOKEN);
158
- const secretName = scope && !process.env.PLATFORM_SECRET_NAME
159
- ? baseSecretName.replace(/\/platform$/, `/${scope.replace(/[^a-z0-9]+/gi, '-')}`)
160
- : baseSecretName;
161
- auditLog('store-token', { executionId, secretName, days, dryRun: options.dryRun });
210
+ if (options.dryRun) {
211
+ // Dry run stays entirely OFFLINE — it must not create an account or
212
+ // burn a key just to show what it would do.
213
+ const plan = {
214
+ serviceAccount: accountName,
215
+ roles: scope ? 'none (scoped, least privilege)' : 'org admin',
216
+ scope: scope ?? '(none — full platform credential)',
217
+ secretName: process.env.PLATFORM_SECRET_NAME || `${secretNameForOrg('<orgId>', scope ? scopeSecretLeaf(scope) : 'platform')}`,
218
+ region,
219
+ expiresInDays: days,
220
+ };
221
+ if (options.json) {
222
+ console.log(JSON.stringify({ success: true, dryRun: true, ...plan }, null, 2));
223
+ }
224
+ else {
225
+ console.log('');
226
+ printSection('Dry Run — No Changes Made');
227
+ printKeyValue({
228
+ 'Service Account': plan.serviceAccount,
229
+ 'Roles': plan.roles,
230
+ 'Key Scope': plan.scope,
231
+ 'Secret Name': plan.secretName,
232
+ 'Region': plan.region,
233
+ 'Expires In': `${days} days`,
234
+ });
235
+ printSuccess('Dry run complete — no account, key or secret was created');
236
+ }
237
+ return;
238
+ }
239
+ const keyName = `${accountName}-${new Date().toISOString().slice(0, 10)}`;
240
+ const provisioned = await provisionServiceAccountKey({
241
+ client,
242
+ password: password,
243
+ accountName,
244
+ description: identity.description,
245
+ roles: scope ? 'none' : 'admin',
246
+ ...(scope ? { scope } : {}),
247
+ expiresInSeconds,
248
+ keyName,
249
+ });
250
+ printSuccess(`Key issued on service account '${accountName}' (expires ${provisioned.expiresAt})`);
251
+ // An explicit PLATFORM_SECRET_NAME still wins (the escape hatch for
252
+ // hand-managed paths); otherwise derive it from the org the platform
253
+ // reported, which works with an opaque access key as PLATFORM_TOKEN —
254
+ // a key carries no org claim to decode.
255
+ const secretName = process.env.PLATFORM_SECRET_NAME
256
+ || secretNameForOrg(provisioned.organizationId, scope ? scopeSecretLeaf(scope) : 'platform');
257
+ auditLog('store-token', {
258
+ executionId,
259
+ secretName,
260
+ days,
261
+ serviceAccount: accountName,
262
+ scope: scope ?? null,
263
+ keyId: provisioned.keyId,
264
+ });
162
265
  printInfo('Parameters', {
163
266
  secretName,
164
267
  region,
268
+ serviceAccount: accountName,
269
+ scope: scope ?? '(none)',
165
270
  days,
166
271
  expiresIn: `${expiresInSeconds}s`,
167
- dryRun: options.dryRun,
168
272
  });
169
- printInfo('Requesting token', { expiresIn: `${expiresInSeconds}s (${days} days)` });
170
- const tokenResponse = await client.post('/api/user/generate-token', { expiresIn: expiresInSeconds, ...(scope ? { scope } : {}) });
171
- const tokenData = tokenResponse?.data ?? tokenResponse;
172
- const accessToken = tokenData?.accessToken;
173
- const refreshToken = tokenData?.refreshToken;
174
- const actualExpiresIn = tokenData?.expiresIn ?? expiresInSeconds;
175
- if (!accessToken) {
176
- throw new Error('Token generation failed — no access token in response');
177
- }
178
- printSuccess(`Token generated (expires in ${actualExpiresIn}s)`);
179
- const expiresAt = new Date(Date.now() + actualExpiresIn * 1000).toISOString();
180
- // Schema: { username: orgId, password: JWT, ...metadata }
181
- // - username/password fields satisfy CodeBuild's `secretsManagerCredentials`
182
- // (HTTP Basic, sent to pipeline-image-registry's /token endpoint)
183
- // - The same JWT is consumed by the plugin-lookup Lambda by reading
184
- // the `password` field
185
- // - One Secret per customer account replaces the previous two-secret model
186
- // Decode JWT for orgId — it's a stable identifier for the username field;
187
- // the actual auth uses the password (JWT) which the token service verifies.
188
- // `||` (not `??`): an EMPTY-string organizationId must also fall back. A
189
- // sysadmin/system token often carries organizationId="", and CodeBuild
190
- // rejects a registry credential whose `username` field is empty with
191
- // "AuthorizationData is malformed, empty field" — so username must always
192
- // be a non-empty value.
193
- const payload = decodeTokenPayload(accessToken);
194
- const orgId = payload?.organizationId?.trim() || 'unknown-org';
273
+ // What this run is REPLACING, read before the write so the old key can be
274
+ // retired after the new one is safely stored.
275
+ const previous = await previousKeyId(secretName, aws);
276
+ // Schema: { username: orgId, password: <pb_sa_ key>, ...metadata }
277
+ // - username/password satisfy CodeBuild's `secretsManagerCredentials`
278
+ // (HTTP Basic, sent to pipeline-image-registry's /token endpoint, which
279
+ // exchanges the opaque key like every other service does)
280
+ // - `password` stays the canonical field: the plugin-lookup Lambda, the
281
+ // events Lambda and `--store-tokens` all read it. Only its VALUE changed,
282
+ // from a machine-session JWT to an opaque service-account key.
283
+ // - keyId / serviceAccountId are what the rotation Lambda needs to retire
284
+ // the key it replaces.
195
285
  const secretValue = JSON.stringify({
196
- username: orgId,
197
- // `password` is the canonical JWT field — read by CodeBuild creds,
198
- // plugin-lookup, token-renew, and the event-ingestion Lambda.
199
- password: accessToken,
200
- ...(refreshToken && { refreshToken }),
286
+ username: provisioned.organizationId,
287
+ password: provisioned.key,
201
288
  platformUrl: client.getBaseUrl(),
202
- expiresIn: actualExpiresIn,
203
- expiresAt,
289
+ organizationId: provisioned.organizationId,
290
+ serviceAccountId: provisioned.serviceAccountId,
291
+ serviceAccountName: provisioned.serviceAccountName,
292
+ keyId: provisioned.keyId,
293
+ scope: provisioned.scope,
294
+ expiresIn: expiresInSeconds,
295
+ expiresAt: provisioned.expiresAt,
204
296
  createdAt: new Date().toISOString(),
205
297
  });
206
- // Dry-run: show what would be stored
207
- if (options.dryRun) {
208
- if (options.json) {
209
- console.log(JSON.stringify({
210
- success: true,
211
- dryRun: true,
212
- secretName,
213
- region,
214
- expiresInDays: days,
215
- expiresAt,
216
- tokenLength: accessToken.length,
217
- hasRefreshToken: !!refreshToken,
218
- }, null, 2));
298
+ printSection('Store Key');
299
+ const description = `Pipeline Builder service-account key (${accountName}; renew by ${provisioned.expiresAt})`;
300
+ await upsertSecret(secretName, secretValue, description, aws);
301
+ const arn = await getSecretArn(secretName, aws);
302
+ // Retire the credential this run replaced — AFTER the new one is stored,
303
+ // never before. A failure here leaves a superfluous key that expires on
304
+ // its own; doing it in the other order would leave the secret naming a
305
+ // revoked key if the write failed.
306
+ if (previous.keyId && previous.serviceAccountId === provisioned.serviceAccountId) {
307
+ try {
308
+ await revokeServiceAccountKey(client, password, provisioned.organizationId, provisioned.serviceAccountId, previous.keyId);
309
+ printSuccess(`Retired the previous key (${previous.keyId})`);
219
310
  }
220
- else {
221
- console.log('');
222
- printSection('Dry Run — No Changes Made');
223
- printKeyValue({
224
- 'Secret Name': secretName,
225
- 'Region': region,
226
- 'Expires In': `${days} days`,
227
- 'Renew By': expiresAt,
228
- 'Token Length': `${accessToken.length} chars`,
229
- 'Has Refresh Token': refreshToken ? 'Yes' : 'No',
230
- });
231
- printSuccess('Dry run complete — no secret was created or updated');
311
+ catch (err) {
312
+ printWarning(`Stored the new key, but could not revoke the previous one (${previous.keyId}): `
313
+ + `${err instanceof Error ? err.message : String(err)}. It expires on its own; revoke it from `
314
+ + 'Settings → Service accounts if you want it gone now.');
232
315
  }
233
- return;
234
316
  }
235
- // Step 2: Store token in Secrets Manager
236
- printSection('Store Token');
237
- const description = `Platform JWT token (renew by ${expiresAt})`;
238
- await upsertSecret(secretName, secretValue, description, { region, profile: options.profile });
239
- const arn = await getSecretArn(secretName, { region, profile: options.profile });
240
- // Optionally install the once-a-day renewal stack so this token never lapses.
241
- // Off by default — opt in with --schedule (e.g. for the AWS event-ingestion
242
- // bundle whose Lambda needs a non-expiring token).
317
+ // Optionally install the once-a-day rotation stack so this key never lapses.
243
318
  let scheduleExpression;
244
319
  if (options.schedule) {
245
320
  const fiveFieldCron = options.cron || process.env.TOKEN_RENEW_SCHEDULE || DEFAULT_RENEW_CRON;
@@ -258,34 +333,41 @@ export function storeToken(program) {
258
333
  secretName,
259
334
  secretArn: arn,
260
335
  region,
336
+ serviceAccount: accountName,
337
+ serviceAccountId: provisioned.serviceAccountId,
338
+ keyId: provisioned.keyId,
339
+ scope: provisioned.scope,
261
340
  expiresInDays: days,
262
- expiresAt,
341
+ expiresAt: provisioned.expiresAt,
263
342
  schedule: scheduleExpression ?? null,
264
343
  }, null, 2));
265
344
  }
266
345
  else {
267
346
  console.log('');
268
- printSection('Token Stored');
347
+ printSection('Key Stored');
269
348
  printKeyValue({
270
349
  'Secret Name': secretName,
271
350
  'Secret ARN': arn,
272
351
  'Region': region,
352
+ 'Service Account': accountName,
353
+ 'Key Scope': provisioned.scope ?? '(none — full platform credential)',
354
+ 'Key Id': provisioned.keyId,
273
355
  'Expires In': `${days} days`,
274
- 'Renew By': expiresAt,
275
- 'Auto-Renew': scheduleExpression ? `✓ ${scheduleExpression}` : 'off (pass --schedule to enable)',
356
+ 'Renew By': provisioned.expiresAt,
357
+ 'Auto-Rotate': scheduleExpression ? `✓ ${scheduleExpression}` : 'off (pass --schedule to enable)',
276
358
  'Status': '✓ Stored',
277
359
  });
278
360
  console.log('');
279
- printSuccess('Token stored. To use with synth/deploy:');
361
+ printSuccess('Key stored. To use with synth/deploy:');
280
362
  printInfo(` export PLATFORM_SECRET_NAME=${secretName}`);
281
363
  printInfo(' pipeline-manager pipeline synth --id <pipeline-id> --store-tokens');
282
364
  console.log('');
283
365
  if (scheduleExpression) {
284
- printInfo(`Auto-renewal is active (${scheduleExpression}); the secret refreshes before ${expiresAt}.`);
366
+ printInfo(`Auto-rotation is active (${scheduleExpression}); the secret is replaced before ${provisioned.expiresAt}.`);
285
367
  }
286
368
  else {
287
- printInfo(`Renew before ${expiresAt} with: pipeline-manager infra store-token --days ${days}`);
288
- printInfo(' (or pass --schedule to install a daily auto-renewal stack)');
369
+ printInfo(`Rotate before ${provisioned.expiresAt} with: pipeline-manager infra store-token --days ${days}`);
370
+ printInfo(' (or pass --schedule to install a daily auto-rotation stack)');
289
371
  }
290
372
  }
291
373
  }
@@ -296,10 +378,10 @@ export function storeToken(program) {
296
378
  context: {
297
379
  command: 'store-token',
298
380
  executionId,
299
- secretName: process.env.PLATFORM_SECRET_NAME || '(derived from token)',
381
+ secretName: process.env.PLATFORM_SECRET_NAME || '(derived from the org)',
300
382
  },
301
383
  });
302
384
  }
303
385
  });
304
386
  }
305
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RvcmUtdG9rZW4uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY29tbWFuZHMvc3RvcmUtdG9rZW4udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsK0NBQStDO0FBQy9DLHNDQUFzQztBQUV0QyxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzdDLE9BQU8sS0FBSyxFQUFFLE1BQU0sSUFBSSxDQUFDO0FBQ3pCLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFDekMsT0FBTyxLQUFLLEVBQUUsTUFBTSxJQUFJLENBQUM7QUFDekIsT0FBTyxJQUFJLE1BQU0sTUFBTSxDQUFDO0FBQ3hCLE9BQU8sRUFBRSxZQUFZLEVBQUUseUJBQXlCLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUNqRixPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQ3BDLE9BQU8sRUFBRSxXQUFXLEVBQUUsY0FBYyxFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFDekUsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQ2pELE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQzVELE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ3ZELE9BQU8sRUFBRSxZQUFZLEVBQUUsWUFBWSxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDckUsT0FBTyxFQUFFLDhCQUE4QixFQUFFLGtCQUFrQixFQUFFLGVBQWUsRUFBRSxpQkFBaUIsRUFBRSxnQkFBZ0IsRUFBRSxjQUFjLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUNySyxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUNyRCxPQUFPLEVBQUUsV0FBVyxFQUFFLFdBQVcsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQ3JFLE9BQU8sRUFBRSxTQUFTLEVBQUUsYUFBYSxFQUFFLFlBQVksRUFBRSxZQUFZLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUNoRyxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUVyRiwwREFBMEQ7QUFDMUQsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxhQUFhLENBQUMsT0FBTyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztBQUUvRCxNQUFNLGdCQUFnQixHQUFHLDhCQUE4QixDQUFDO0FBQ3hELCtFQUErRTtBQUMvRSxNQUFNLGlCQUFpQixHQUFHLDhCQUE4QixDQUFDO0FBQ3pELGdHQUFnRztBQUNoRyxNQUFNLGtCQUFrQixHQUFHLFdBQVcsQ0FBQztBQUV2Qzs7Ozs7OztHQU9HO0FBQ0gsS0FBSyxVQUFVLG1CQUFtQixDQUFDLElBT2xDO0lBQ0MsTUFBTSxrQkFBa0IsR0FBRyxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQywyQkFBMkI7SUFFN0Ysc0VBQXNFO0lBQ3RFLHdFQUF3RTtJQUN4RSx3RUFBd0U7SUFDeEUsc0VBQXNFO0lBQ3RFLHNFQUFzRTtJQUN0RSxrRUFBa0U7SUFDbEUsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsc0NBQXNDO0lBQzlGLE1BQU0sVUFBVSxHQUFHLFVBQVUsS0FBSyxVQUFVLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxVQUFVLENBQUMsT0FBTyxDQUFDLGNBQWMsRUFBRSxHQUFHLENBQUMsRUFBRSxDQUFDO0lBQ2xHLE1BQU0sU0FBUyxHQUFHLEdBQUcsZ0JBQWdCLEdBQUcsVUFBVSxFQUFFLENBQUM7SUFDckQsTUFBTSxVQUFVLEdBQUcsR0FBRyxpQkFBaUIsR0FBRyxVQUFVLEVBQUUsQ0FBQztJQUV2RCxZQUFZLENBQUMsa0JBQWtCLENBQUMsQ0FBQztJQUNqQyxTQUFTLENBQUMsWUFBWSxFQUFFO1FBQ3RCLEtBQUssRUFBRSxTQUFTO1FBQ2hCLFFBQVEsRUFBRSxJQUFJLENBQUMsYUFBYTtRQUM1QixXQUFXLEVBQUUsa0JBQWtCO1FBQy9CLFNBQVMsRUFBRSxJQUFJLENBQUMsSUFBSTtLQUNyQixDQUFDLENBQUM7SUFFSCxnRUFBZ0U7SUFDaEUsTUFBTSxZQUFZLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUscUNBQXFDLENBQUMsQ0FBQztJQUNqRixNQUFNLE9BQU8sR0FBRztRQUNkLGdCQUFnQixFQUFFLFFBQVE7UUFDMUIsY0FBYyxFQUFFLFNBQVM7UUFDekIsaUJBQWlCLEVBQUUsWUFBWTtRQUMvQix1QkFBdUI7UUFDdkIsbUJBQW1CLElBQUksQ0FBQyxXQUFXLEVBQUU7UUFDckMsc0JBQXNCLElBQUksQ0FBQyxVQUFVLEVBQUU7UUFDdkMsYUFBYSxJQUFJLENBQUMsSUFBSSxFQUFFO1FBQ3hCLHNCQUFzQixrQkFBa0IsRUFBRTtRQUMxQyxjQUFjLFVBQVUsRUFBRTtRQUMxQiw0RUFBNEU7UUFDNUUsNENBQTRDO1FBQzVDLDBCQUEwQixXQUFXLEVBQUU7UUFDdkMsZ0JBQWdCLEVBQUUsc0JBQXNCO1FBQ3hDLDhCQUE4QjtRQUM5QixVQUFVLEVBQUUsSUFBSSxDQUFDLE1BQU07S0FDeEIsQ0FBQztJQUNGLElBQUksSUFBSSxDQUFDLE9BQU87UUFBRSxPQUFPLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDMUQsWUFBWSxDQUFDLEtBQUssRUFBRSxPQUFPLEVBQUUsRUFBRSxLQUFLLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQztJQUVuRCxnRkFBZ0Y7SUFDaEYsMEVBQTBFO0lBQzFFLE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLGtDQUFrQyxDQUFDLENBQUM7SUFDNUUsSUFBSSxDQUFDLEVBQUUsQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQztRQUMvQixNQUFNLElBQUksS0FBSyxDQUFDLG9DQUFvQyxVQUFVLDJCQUEyQixDQUFDLENBQUM7SUFDN0YsQ0FBQztJQUNELE1BQU0sTUFBTSxHQUFHLEVBQUUsQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsTUFBTSxFQUFFLEVBQUUsY0FBYyxDQUFDLENBQUMsQ0FBQztJQUN0RSxJQUFJLENBQUM7UUFDSCxFQUFFLENBQUMsWUFBWSxDQUFDLFVBQVUsRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxXQUFXLENBQUMsQ0FBQyxDQUFDO1FBQzVELE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLFdBQVcsQ0FBQyxDQUFDO1FBQy9DLFlBQVksQ0FBQyxLQUFLLEVBQUUsQ0FBQyxJQUFJLEVBQUUsT0FBTyxFQUFFLFdBQVcsQ0FBQyxFQUFFLEVBQUUsR0FBRyxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLENBQUMsQ0FBQztRQUVsRixNQUFNLFlBQVksR0FBRyxJQUFJLFlBQVksQ0FBQyxFQUFFLE1BQU0sRUFBRSxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQztRQUMvRCxNQUFNLFlBQVksQ0FBQyxJQUFJLENBQUMsSUFBSSx5QkFBeUIsQ0FBQztZQUNwRCxZQUFZLEVBQUUsVUFBVTtZQUN4QixPQUFPLEVBQUUsRUFBRSxDQUFDLFlBQVksQ0FBQyxPQUFPLENBQUM7U0FDbEMsQ0FBQyxDQUFDLENBQUM7SUFDTixDQUFDO1lBQVMsQ0FBQztRQUNULEVBQUUsQ0FBQyxNQUFNLENBQUMsTUFBTSxFQUFFLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUN0RCxDQUFDO0lBRUQsWUFBWSxDQUFDLHNCQUFzQixrQkFBa0IsR0FBRyxDQUFDLENBQUM7SUFDMUQsT0FBTyxrQkFBa0IsQ0FBQztBQUM1QixDQUFDO0FBRUQ7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FzQkc7QUFDSCxNQUFNLFVBQVUsVUFBVSxDQUFDLE9BQWdCO0lBQ3pDLGNBQWMsQ0FDWixpQkFBaUIsQ0FDZixnQkFBZ0IsQ0FBQyxPQUFPO1NBQ3JCLE9BQU8sQ0FBQyxhQUFhLENBQUM7U0FDdEIsV0FBVyxDQUFDLHlFQUF5RSxDQUFDO1NBQ3RGLE1BQU0sQ0FBQywrQkFBK0IsRUFBRSxzREFBc0QsQ0FBQztTQUMvRixNQUFNLENBQUMsMkJBQTJCLEVBQUUseUNBQXlDLENBQUM7U0FDOUUsTUFBTSxDQUFDLGVBQWUsRUFBRSx3QkFBd0IsRUFBRSxJQUFJLENBQUM7U0FDdkQsTUFBTSxDQUFDLGlCQUFpQixFQUFFLGdKQUFnSixDQUFDO1NBQzNLLE1BQU0sQ0FBQyxXQUFXLEVBQUUsOERBQThELEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FDL0Y7U0FDRSxNQUFNLENBQUMsWUFBWSxFQUFFLHdGQUF3RixFQUFFLEtBQUssQ0FBQztTQUNySCxNQUFNLENBQUMsZUFBZSxFQUFFLG1JQUFtSSxDQUFDO1NBQzVKLE1BQU0sQ0FBQyxRQUFRLEVBQUUsdUJBQXVCLEVBQUUsS0FBSyxDQUFDLENBQ3BEO1NBQ0UsTUFBTSxDQUFDLEtBQUssRUFBRSxPQUFPLEVBQUUsRUFBRTtRQUN4QixNQUFNLFdBQVcsR0FBRyxrQkFBa0IsQ0FBQyxhQUFhLEVBQUUsU0FBUyxFQUFFLEVBQUUsS0FBSyxFQUFFLE9BQU8sQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBRTFGLElBQUksQ0FBQztZQUNILGVBQWUsQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUM7WUFFbkMsTUFBTSxNQUFNLEdBQUcsZ0JBQWdCLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBRWhELE1BQU0sSUFBSSxHQUFHLGNBQWMsQ0FBQyxPQUFPLENBQUMsSUFBSSxFQUFFLE1BQU0sRUFBRSxDQUFDLEVBQUUsR0FBRyxDQUFDLENBQUM7WUFDMUQsTUFBTSxnQkFBZ0IsR0FBRyxJQUFJLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLENBQUM7WUFFN0MsNkVBQTZFO1lBQzdFLDRFQUE0RTtZQUM1RSw4RUFBOEU7WUFDOUUsMEVBQTBFO1lBQzFFLG9EQUFvRDtZQUNwRCxNQUFNLG1CQUFtQixDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBRW5DLHFEQUFxRDtZQUNyRCxZQUFZLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztZQUUvQixNQUFNLE1BQU0sR0FBRyxNQUFNLDhCQUE4QixDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBRTdELG1FQUFtRTtZQUNuRSwyRUFBMkU7WUFDM0UscUVBQXFFO1lBQ3JFLHFFQUFxRTtZQUNyRSx3RUFBd0U7WUFDeEUsZ0VBQWdFO1lBQ2hFLE1BQU0sS0FBSyxHQUFHLE9BQU8sQ0FBQyxLQUEyQixDQUFDO1lBQ2xELE1BQU0sY0FBYyxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsb0JBQW9CLElBQUksaUJBQWlCLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxjQUFlLENBQUMsQ0FBQztZQUMxRyxNQUFNLFVBQVUsR0FBRyxLQUFLLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLG9CQUFvQjtnQkFDM0QsQ0FBQyxDQUFDLGNBQWMsQ0FBQyxPQUFPLENBQUMsYUFBYSxFQUFFLElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxjQUFjLEVBQUUsR0FBRyxDQUFDLEVBQUUsQ0FBQztnQkFDakYsQ0FBQyxDQUFDLGNBQWMsQ0FBQztZQUVuQixRQUFRLENBQUMsYUFBYSxFQUFFLEVBQUUsV0FBVyxFQUFFLFVBQVUsRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLE9BQU8sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO1lBRW5GLFNBQVMsQ0FBQyxZQUFZLEVBQUU7Z0JBQ3RCLFVBQVU7Z0JBQ1YsTUFBTTtnQkFDTixJQUFJO2dCQUNKLFNBQVMsRUFBRSxHQUFHLGdCQUFnQixHQUFHO2dCQUNqQyxNQUFNLEVBQUUsT0FBTyxDQUFDLE1BQU07YUFDdkIsQ0FBQyxDQUFDO1lBRUgsU0FBUyxDQUFDLGtCQUFrQixFQUFFLEVBQUUsU0FBUyxFQUFFLEdBQUcsZ0JBQWdCLE1BQU0sSUFBSSxRQUFRLEVBQUUsQ0FBQyxDQUFDO1lBRXBGLE1BQU0sYUFBYSxHQUFHLE1BQU0sTUFBTSxDQUFDLElBQUksQ0FDckMsMEJBQTBCLEVBQzFCLEVBQUUsU0FBUyxFQUFFLGdCQUFnQixFQUFFLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQzdELENBQUM7WUFFRixNQUFNLFNBQVMsR0FBSSxhQUF5QyxFQUFFLElBQUksSUFBSSxhQUFhLENBQUM7WUFDcEYsTUFBTSxXQUFXLEdBQUksU0FBcUMsRUFBRSxXQUFpQyxDQUFDO1lBQzlGLE1BQU0sWUFBWSxHQUFJLFNBQXFDLEVBQUUsWUFBa0MsQ0FBQztZQUNoRyxNQUFNLGVBQWUsR0FBSyxTQUFxQyxFQUFFLFNBQW9CLElBQUksZ0JBQWdCLENBQUM7WUFFMUcsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO2dCQUNqQixNQUFNLElBQUksS0FBSyxDQUFDLHVEQUF1RCxDQUFDLENBQUM7WUFDM0UsQ0FBQztZQUVELFlBQVksQ0FBQywrQkFBK0IsZUFBZSxJQUFJLENBQUMsQ0FBQztZQUVqRSxNQUFNLFNBQVMsR0FBRyxJQUFJLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLEdBQUcsZUFBZSxHQUFHLElBQUksQ0FBQyxDQUFDLFdBQVcsRUFBRSxDQUFDO1lBRTlFLDBEQUEwRDtZQUMxRCw2RUFBNkU7WUFDN0Usb0VBQW9FO1lBQ3BFLG9FQUFvRTtZQUNwRSx5QkFBeUI7WUFDekIsMkVBQTJFO1lBQzNFLDBFQUEwRTtZQUMxRSw0RUFBNEU7WUFDNUUseUVBQXlFO1lBQ3pFLHVFQUF1RTtZQUN2RSxxRUFBcUU7WUFDckUsMEVBQTBFO1lBQzFFLHdCQUF3QjtZQUN4QixNQUFNLE9BQU8sR0FBRyxrQkFBa0IsQ0FBQyxXQUFXLENBQUMsQ0FBQztZQUNoRCxNQUFNLEtBQUssR0FBRyxPQUFPLEVBQUUsY0FBYyxFQUFFLElBQUksRUFBRSxJQUFJLGFBQWEsQ0FBQztZQUUvRCxNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDO2dCQUNqQyxRQUFRLEVBQUUsS0FBSztnQkFDZixtRUFBbUU7Z0JBQ25FLDhEQUE4RDtnQkFDOUQsUUFBUSxFQUFFLFdBQVc7Z0JBQ3JCLEdBQUcsQ0FBQyxZQUFZLElBQUksRUFBRSxZQUFZLEVBQUUsQ0FBQztnQkFDckMsV0FBVyxFQUFFLE1BQU0sQ0FBQyxVQUFVLEVBQUU7Z0JBQ2hDLFNBQVMsRUFBRSxlQUFlO2dCQUMxQixTQUFTO2dCQUNULFNBQVMsRUFBRSxJQUFJLElBQUksRUFBRSxDQUFDLFdBQVcsRUFBRTthQUNwQyxDQUFDLENBQUM7WUFFSCxxQ0FBcUM7WUFDckMsSUFBSSxPQUFPLENBQUMsTUFBTSxFQUFFLENBQUM7Z0JBQ25CLElBQUksT0FBTyxDQUFDLElBQUksRUFBRSxDQUFDO29CQUNqQixPQUFPLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUM7d0JBQ3pCLE9BQU8sRUFBRSxJQUFJO3dCQUNiLE1BQU0sRUFBRSxJQUFJO3dCQUNaLFVBQVU7d0JBQ1YsTUFBTTt3QkFDTixhQUFhLEVBQUUsSUFBSTt3QkFDbkIsU0FBUzt3QkFDVCxXQUFXLEVBQUUsV0FBVyxDQUFDLE1BQU07d0JBQy9CLGVBQWUsRUFBRSxDQUFDLENBQUMsWUFBWTtxQkFDaEMsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDZixDQUFDO3FCQUFNLENBQUM7b0JBQ04sT0FBTyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQztvQkFDaEIsWUFBWSxDQUFDLDJCQUEyQixDQUFDLENBQUM7b0JBQzFDLGFBQWEsQ0FBQzt3QkFDWixhQUFhLEVBQUUsVUFBVTt3QkFDekIsUUFBUSxFQUFFLE1BQU07d0JBQ2hCLFlBQVksRUFBRSxHQUFHLElBQUksT0FBTzt3QkFDNUIsVUFBVSxFQUFFLFNBQVM7d0JBQ3JCLGNBQWMsRUFBRSxHQUFHLFdBQVcsQ0FBQyxNQUFNLFFBQVE7d0JBQzdDLG1CQUFtQixFQUFFLFlBQVksQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxJQUFJO3FCQUNqRCxDQUFDLENBQUM7b0JBQ0gsWUFBWSxDQUFDLHFEQUFxRCxDQUFDLENBQUM7Z0JBQ3RFLENBQUM7Z0JBQ0QsT0FBTztZQUNULENBQUM7WUFFRCx5Q0FBeUM7WUFDekMsWUFBWSxDQUFDLGFBQWEsQ0FBQyxDQUFDO1lBRTVCLE1BQU0sV0FBVyxHQUFHLGdDQUFnQyxTQUFTLEdBQUcsQ0FBQztZQUNqRSxNQUFNLFlBQVksQ0FBQyxVQUFVLEVBQUUsV0FBVyxFQUFFLFdBQVcsRUFBRSxFQUFFLE1BQU0sRUFBRSxPQUFPLEVBQUUsT0FBTyxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUM7WUFFL0YsTUFBTSxHQUFHLEdBQUcsTUFBTSxZQUFZLENBQUMsVUFBVSxFQUFFLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRSxPQUFPLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQztZQUVqRiw4RUFBOEU7WUFDOUUsNEVBQTRFO1lBQzVFLG1EQUFtRDtZQUNuRCxJQUFJLGtCQUFzQyxDQUFDO1lBQzNDLElBQUksT0FBTyxDQUFDLFFBQVEsRUFBRSxDQUFDO2dCQUNyQixNQUFNLGFBQWEsR0FBRyxPQUFPLENBQUMsSUFBSSxJQUFJLE9BQU8sQ0FBQyxHQUFHLENBQUMsb0JBQW9CLElBQUksa0JBQWtCLENBQUM7Z0JBQzdGLGtCQUFrQixHQUFHLE1BQU0sbUJBQW1CLENBQUM7b0JBQzdDLFdBQVcsRUFBRSxNQUFNLENBQUMsVUFBVSxFQUFFO29CQUNoQyxVQUFVO29CQUNWLElBQUk7b0JBQ0osYUFBYTtvQkFDYixNQUFNO29CQUNOLE9BQU8sRUFBRSxPQUFPLENBQUMsT0FBTztpQkFDekIsQ0FBQyxDQUFDO1lBQ0wsQ0FBQztZQUVELElBQUksT0FBTyxDQUFDLElBQUksRUFBRSxDQUFDO2dCQUNqQixPQUFPLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUM7b0JBQ3pCLE9BQU8sRUFBRSxJQUFJO29CQUNiLFVBQVU7b0JBQ1YsU0FBUyxFQUFFLEdBQUc7b0JBQ2QsTUFBTTtvQkFDTixhQUFhLEVBQUUsSUFBSTtvQkFDbkIsU0FBUztvQkFDVCxRQUFRLEVBQUUsa0JBQWtCLElBQUksSUFBSTtpQkFDckMsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUNmLENBQUM7aUJBQU0sQ0FBQztnQkFDTixPQUFPLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDO2dCQUNoQixZQUFZLENBQUMsY0FBYyxDQUFDLENBQUM7Z0JBRTdCLGFBQWEsQ0FBQztvQkFDWixhQUFhLEVBQUUsVUFBVTtvQkFDekIsWUFBWSxFQUFFLEdBQUc7b0JBQ2pCLFFBQVEsRUFBRSxNQUFNO29CQUNoQixZQUFZLEVBQUUsR0FBRyxJQUFJLE9BQU87b0JBQzVCLFVBQVUsRUFBRSxTQUFTO29CQUNyQixZQUFZLEVBQUUsa0JBQWtCLENBQUMsQ0FBQyxDQUFDLEtBQUssa0JBQWtCLEVBQUUsQ0FBQyxDQUFDLENBQUMsaUNBQWlDO29CQUNoRyxRQUFRLEVBQUUsVUFBVTtpQkFDckIsQ0FBQyxDQUFDO2dCQUVILE9BQU8sQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUM7Z0JBQ2hCLFlBQVksQ0FBQyx5Q0FBeUMsQ0FBQyxDQUFDO2dCQUN4RCxTQUFTLENBQUMsaUNBQWlDLFVBQVUsRUFBRSxDQUFDLENBQUM7Z0JBQ3pELFNBQVMsQ0FBQyxxRUFBcUUsQ0FBQyxDQUFDO2dCQUNqRixPQUFPLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDO2dCQUNoQixJQUFJLGtCQUFrQixFQUFFLENBQUM7b0JBQ3ZCLFNBQVMsQ0FBQywyQkFBMkIsa0JBQWtCLGtDQUFrQyxTQUFTLEdBQUcsQ0FBQyxDQUFDO2dCQUN6RyxDQUFDO3FCQUFNLENBQUM7b0JBQ04sU0FBUyxDQUFDLGdCQUFnQixTQUFTLG9EQUFvRCxJQUFJLEVBQUUsQ0FBQyxDQUFDO29CQUMvRixTQUFTLENBQUMsOERBQThELENBQUMsQ0FBQztnQkFDNUUsQ0FBQztZQUNILENBQUM7UUFFSCxDQUFDO1FBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztZQUNmLFdBQVcsQ0FBQyxLQUFLLEVBQUUsV0FBVyxDQUFDLFdBQVcsRUFBRTtnQkFDMUMsS0FBSyxFQUFFLE9BQU8sQ0FBQyxJQUFJLEVBQUUsQ0FBQyxLQUFLO2dCQUMzQixJQUFJLEVBQUUsSUFBSTtnQkFDVixPQUFPLEVBQUU7b0JBQ1AsT0FBTyxFQUFFLGFBQWE7b0JBQ3RCLFdBQVc7b0JBQ1gsVUFBVSxFQUFFLE9BQU8sQ0FBQyxHQUFHLENBQUMsb0JBQW9CLElBQUksc0JBQXNCO2lCQUN2RTthQUNGLENBQUMsQ0FBQztRQUNMLENBQUM7SUFDSCxDQUFDLENBQUMsQ0FBQztBQUNQLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgMjAyNiBQaXBlbGluZSBCdWlsZGVyIENvbnRyaWJ1dG9yc1xuLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcblxuaW1wb3J0IHsgZXhlY0ZpbGVTeW5jIH0gZnJvbSAnY2hpbGRfcHJvY2Vzcyc7XG5pbXBvcnQgKiBhcyBmcyBmcm9tICdmcyc7XG5pbXBvcnQgeyBmaWxlVVJMVG9QYXRoIH0gZnJvbSAnbm9kZTp1cmwnO1xuaW1wb3J0ICogYXMgb3MgZnJvbSAnb3MnO1xuaW1wb3J0IHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQgeyBMYW1iZGFDbGllbnQsIFVwZGF0ZUZ1bmN0aW9uQ29kZUNvbW1hbmQgfSBmcm9tICdAYXdzLXNkay9jbGllbnQtbGFtYmRhJztcbmltcG9ydCB7IENvbW1hbmQgfSBmcm9tICdjb21tYW5kZXInO1xuaW1wb3J0IHsgQVBQX1ZFUlNJT04sIHZhbGlkYXRlTnVtYmVyIH0gZnJvbSAnLi4vY29uZmlnL2NsaS5jb25zdGFudHMuanMnO1xuaW1wb3J0IHsgYXVkaXRMb2cgfSBmcm9tICcuLi91dGlscy9hdWRpdC1sb2cuanMnO1xuaW1wb3J0IHsgZGVjb2RlVG9rZW5QYXlsb2FkIH0gZnJvbSAnLi4vdXRpbHMvYXV0aC1ndWFyZC5qcyc7XG5pbXBvcnQgeyByZXNvbHZlQXdzUmVnaW9uIH0gZnJvbSAnLi4vdXRpbHMvYXdzLWVudi5qcyc7XG5pbXBvcnQgeyB1cHNlcnRTZWNyZXQsIGdldFNlY3JldEFybiB9IGZyb20gJy4uL3V0aWxzL2F3cy1zZWNyZXRzLmpzJztcbmltcG9ydCB7IGNyZWF0ZUF1dGhlbnRpY2F0ZWRDbGllbnRBc3luYywgcHJpbnRDb21tYW5kSGVhZGVyLCBwcmludFNzbFdhcm5pbmcsIHdpdGhQcm9maWxlT3B0aW9uLCB3aXRoUmVnaW9uT3B0aW9uLCB3aXRoU3NsT3B0aW9ucyB9IGZyb20gJy4uL3V0aWxzL2NvbW1hbmQtdXRpbHMuanMnO1xuaW1wb3J0IHsgdG9FdmVudEJyaWRnZUNyb24gfSBmcm9tICcuLi91dGlscy9jcm9uLmpzJztcbmltcG9ydCB7IEVSUk9SX0NPREVTLCBoYW5kbGVFcnJvciB9IGZyb20gJy4uL3V0aWxzL2Vycm9yLWhhbmRsZXIuanMnO1xuaW1wb3J0IHsgcHJpbnRJbmZvLCBwcmludEtleVZhbHVlLCBwcmludFNlY3Rpb24sIHByaW50U3VjY2VzcyB9IGZyb20gJy4uL3V0aWxzL291dHB1dC11dGlscy5qcyc7XG5pbXBvcnQgeyBlbnN1cmVQbGF0Zm9ybVRva2VuLCByZXNvbHZlU2VjcmV0TmFtZSB9IGZyb20gJy4uL3V0aWxzL3BsYXRmb3JtLXNlY3JldC5qcyc7XG5cbi8vIEVTTSBoYXMgbm8gX19kaXJuYW1lOyBkZXJpdmUgaXQgZnJvbSB0aGlzIG1vZHVsZSdzIFVSTC5cbmNvbnN0IF9fZGlybmFtZSA9IHBhdGguZGlybmFtZShmaWxlVVJMVG9QYXRoKGltcG9ydC5tZXRhLnVybCkpO1xuXG5jb25zdCBSRU5FV19TVEFDS19OQU1FID0gJ3BpcGVsaW5lLWJ1aWxkZXItdG9rZW4tcmVuZXcnO1xuLy8gQ0ZOLW1hbmFnZWQgTGFtYmRhIGZ1bmN0aW9uIG5hbWUg4oCUIGtlZXAgaW4gc3luYyB3aXRoIHRva2VuLXJlbmV3LXN0YWNrLmpzb24uXG5jb25zdCBSRU5FV19MQU1CREFfTkFNRSA9ICdwaXBlbGluZS1idWlsZGVyLXRva2VuLXJlbmV3Jztcbi8vIERlZmF1bHQgNS1maWVsZCBjcm9uIChkYWlseSBhdCBtaWRuaWdodCkgd2hlbiBuZWl0aGVyIC0tY3JvbiBub3IgVE9LRU5fUkVORVdfU0NIRURVTEUgaXMgc2V0LlxuY29uc3QgREVGQVVMVF9SRU5FV19DUk9OID0gJzAgMCAqICogKic7XG5cbi8qKlxuICogRGVwbG95IChvciB1cGRhdGUpIHRoZSBvbmNlLWEtZGF5IHRva2VuLXJlbmV3YWwgc3RhY2s6IGEgc2NoZWR1bGVkIExhbWJkYSB0aGF0XG4gKiByZS1taW50cyB0aGUgcGxhdGZvcm0gSldUIGluIHRoaXMgc2FtZSBzZWNyZXQgYmVmb3JlIGl0IGV4cGlyZXMuIE1pcnJvcnNcbiAqIHNldHVwLWV2ZW50cyDigJQgYGF3cyBjbG91ZGZvcm1hdGlvbiBkZXBsb3lgIGZvciB0aGUgaW5mcmEsIHRoZW4gYSBkaXJlY3RcbiAqIFVwZGF0ZUZ1bmN0aW9uQ29kZSB3aXRoIHRoZSB0aGluIG9yY2hlc3RyYXRvciBoYW5kbGVyIGNvbXBpbGVkIGFsb25nc2lkZSB0aGlzXG4gKiBDTEkgKHRoZSBoYW5kbGVyIG5wbS1pbnN0YWxscyBwaXBlbGluZS1tYW5hZ2VyIGF0IHJ1bnRpbWUgYW5kIHJlLXJ1bnNcbiAqIHN0b3JlLXRva2VuOyBzZWUgc3JjL2xhbWJkYS90b2tlbi1yZW5ldy1oYW5kbGVyLnRzKS5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gZGVwbG95UmVuZXdTY2hlZHVsZShvcHRzOiB7XG4gIHBsYXRmb3JtVXJsOiBzdHJpbmc7XG4gIHNlY3JldE5hbWU6IHN0cmluZztcbiAgZGF5czogbnVtYmVyO1xuICBmaXZlRmllbGRDcm9uOiBzdHJpbmc7XG4gIHJlZ2lvbjogc3RyaW5nO1xuICBwcm9maWxlPzogc3RyaW5nO1xufSk6IFByb21pc2U8c3RyaW5nPiB7XG4gIGNvbnN0IHNjaGVkdWxlRXhwcmVzc2lvbiA9IHRvRXZlbnRCcmlkZ2VDcm9uKG9wdHMuZml2ZUZpZWxkQ3Jvbik7IC8vIHZhbGlkYXRlcyArIDE1LW1pbiBndWFyZFxuXG4gIC8vIE5hbWUgcmVuZXdhbCByZXNvdXJjZXMgcGVyLXNlY3JldCBzbyBhIHNjb3BlZC10b2tlbiBzdGFjayAoZS5nLiB0aGVcbiAgLy8gcmVwb3J0aW5nLWluZ2VzdCBjcmVkZW50aWFsIHRoZSBldmVudCBMYW1iZGEgcmVhZHMpIGNvZXhpc3RzIHdpdGggdGhlXG4gIC8vIHBsYXRmb3JtLXRva2VuIHN0YWNrIGluc3RlYWQgb2YgY29sbGlkaW5nIG9uIHRoZSAoYWNjb3VudC1nbG9iYWwpIElBTVxuICAvLyByb2xlIC8gTGFtYmRhIC8gcnVsZSBuYW1lcy4gVGhlIHBsYXRmb3JtIHNlY3JldCBrZWVwcyB0aGUgYmFyZSBuYW1lXG4gIC8vIChzdWZmaXggJycpIHNvIGV4aXN0aW5nIGRlcGxveW1lbnRzJyBzdGFjayBpcyB1cGRhdGVkIGluIHBsYWNlLCBub3RcbiAgLy8gZHVwbGljYXRlZDsgYW55IG90aGVyIHNlY3JldCBhcHBlbmRzIGl0cyB0cmFpbGluZyBwYXRoIHNlZ21lbnQuXG4gIGNvbnN0IHNlY3JldExlYWYgPSBvcHRzLnNlY3JldE5hbWUucmVwbGFjZSgvLipcXC8vLCAnJyk7IC8vICdwbGF0Zm9ybScgfCAncmVwb3J0aW5nLWluZ2VzdCcgfCDigKZcbiAgY29uc3QgbmFtZVN1ZmZpeCA9IHNlY3JldExlYWYgPT09ICdwbGF0Zm9ybScgPyAnJyA6IGAtJHtzZWNyZXRMZWFmLnJlcGxhY2UoL1teYS16MC05XSsvZ2ksICctJyl9YDtcbiAgY29uc3Qgc3RhY2tOYW1lID0gYCR7UkVORVdfU1RBQ0tfTkFNRX0ke25hbWVTdWZmaXh9YDtcbiAgY29uc3QgbGFtYmRhTmFtZSA9IGAke1JFTkVXX0xBTUJEQV9OQU1FfSR7bmFtZVN1ZmZpeH1gO1xuXG4gIHByaW50U2VjdGlvbignU2NoZWR1bGUgUmVuZXdhbCcpO1xuICBwcmludEluZm8oJ1BhcmFtZXRlcnMnLCB7XG4gICAgc3RhY2s6IHN0YWNrTmFtZSxcbiAgICBzY2hlZHVsZTogb3B0cy5maXZlRmllbGRDcm9uLFxuICAgIGV2ZW50YnJpZGdlOiBzY2hlZHVsZUV4cHJlc3Npb24sXG4gICAgcmVuZXdEYXlzOiBvcHRzLmRheXMsXG4gIH0pO1xuXG4gIC8vIFN0ZXAgMTogaW5mcmEgKExhbWJkYSBnZXRzIHBsYWNlaG9sZGVyIGNvZGUgb24gZmlyc3QgY3JlYXRlKS5cbiAgY29uc3QgdGVtcGxhdGVQYXRoID0gcGF0aC5qb2luKF9fZGlybmFtZSwgJy4uL3RlbXBsYXRlcy90b2tlbi1yZW5ldy1zdGFjay5qc29uJyk7XG4gIGNvbnN0IGNmbkFyZ3MgPSBbXG4gICAgJ2Nsb3VkZm9ybWF0aW9uJywgJ2RlcGxveScsXG4gICAgJy0tc3RhY2stbmFtZScsIHN0YWNrTmFtZSxcbiAgICAnLS10ZW1wbGF0ZS1maWxlJywgdGVtcGxhdGVQYXRoLFxuICAgICctLXBhcmFtZXRlci1vdmVycmlkZXMnLFxuICAgIGBQbGF0Zm9ybUJhc2VVcmw9JHtvcHRzLnBsYXRmb3JtVXJsfWAsXG4gICAgYFBsYXRmb3JtU2VjcmV0TmFtZT0ke29wdHMuc2VjcmV0TmFtZX1gLFxuICAgIGBSZW5ld0RheXM9JHtvcHRzLmRheXN9YCxcbiAgICBgU2NoZWR1bGVFeHByZXNzaW9uPSR7c2NoZWR1bGVFeHByZXNzaW9ufWAsXG4gICAgYE5hbWVTdWZmaXg9JHtuYW1lU3VmZml4fWAsXG4gICAgLy8gUGluIHRoZSBoYW5kbGVyJ3MgcnVudGltZSBucG0gaW5zdGFsbCB0byBUSElTIENMSSdzIHZlcnNpb24gKHJlcHJvZHVjaWJsZVxuICAgIC8vIHJlbmV3YWxzIGluc3RlYWQgb2YgYSBmbG9hdGluZyBcImxhdGVzdFwiKS5cbiAgICBgUGlwZWxpbmVNYW5hZ2VyVmVyc2lvbj0ke0FQUF9WRVJTSU9OfWAsXG4gICAgJy0tY2FwYWJpbGl0aWVzJywgJ0NBUEFCSUxJVFlfTkFNRURfSUFNJyxcbiAgICAnLS1uby1mYWlsLW9uLWVtcHR5LWNoYW5nZXNldCcsXG4gICAgJy0tcmVnaW9uJywgb3B0cy5yZWdpb24sXG4gIF07XG4gIGlmIChvcHRzLnByb2ZpbGUpIGNmbkFyZ3MucHVzaCgnLS1wcm9maWxlJywgb3B0cy5wcm9maWxlKTtcbiAgZXhlY0ZpbGVTeW5jKCdhd3MnLCBjZm5BcmdzLCB7IHN0ZGlvOiAnaW5oZXJpdCcgfSk7XG5cbiAgLy8gU3RlcCAyOiB1cGxvYWQgdGhlIHJlYWwgaGFuZGxlci4gSXQncyBFU00sIHNvIHRoZSB6aXAgZW50cnkgbXVzdCBiZSBpbmRleC5tanNcbiAgLy8gKEhhbmRsZXIgc3RheXMgaW5kZXguaGFuZGxlciDigJQgbm9kZWpzMjQueCByZXNvbHZlcyB0aGUgLm1qcyBleHRlbnNpb24pLlxuICBjb25zdCBoYW5kbGVyU3JjID0gcGF0aC5qb2luKF9fZGlybmFtZSwgJy4uL2xhbWJkYS90b2tlbi1yZW5ldy1oYW5kbGVyLmpzJyk7XG4gIGlmICghZnMuZXhpc3RzU3luYyhoYW5kbGVyU3JjKSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgVG9rZW4tcmVuZXcgaGFuZGxlciBub3QgZm91bmQgYXQgJHtoYW5kbGVyU3JjfSDigJQgd2FzIHRoZSBwYWNrYWdlIGJ1aWx0P2ApO1xuICB9XG4gIGNvbnN0IHRtcERpciA9IGZzLm1rZHRlbXBTeW5jKHBhdGguam9pbihvcy50bXBkaXIoKSwgJ3Rva2VuLXJlbmV3LScpKTtcbiAgdHJ5IHtcbiAgICBmcy5jb3B5RmlsZVN5bmMoaGFuZGxlclNyYywgcGF0aC5qb2luKHRtcERpciwgJ2luZGV4Lm1qcycpKTtcbiAgICBjb25zdCB6aXBQYXRoID0gcGF0aC5qb2luKHRtcERpciwgJ2luZGV4LnppcCcpO1xuICAgIGV4ZWNGaWxlU3luYygnemlwJywgWyctaicsIHppcFBhdGgsICdpbmRleC5tanMnXSwgeyBjd2Q6IHRtcERpciwgc3RkaW86ICdwaXBlJyB9KTtcblxuICAgIGNvbnN0IGxhbWJkYUNsaWVudCA9IG5ldyBMYW1iZGFDbGllbnQoeyByZWdpb246IG9wdHMucmVnaW9uIH0pO1xuICAgIGF3YWl0IGxhbWJkYUNsaWVudC5zZW5kKG5ldyBVcGRhdGVGdW5jdGlvbkNvZGVDb21tYW5kKHtcbiAgICAgIEZ1bmN0aW9uTmFtZTogbGFtYmRhTmFtZSxcbiAgICAgIFppcEZpbGU6IGZzLnJlYWRGaWxlU3luYyh6aXBQYXRoKSxcbiAgICB9KSk7XG4gIH0gZmluYWxseSB7XG4gICAgZnMucm1TeW5jKHRtcERpciwgeyByZWN1cnNpdmU6IHRydWUsIGZvcmNlOiB0cnVlIH0pO1xuICB9XG5cbiAgcHJpbnRTdWNjZXNzKGBSZW5ld2FsIHNjaGVkdWxlZCAoJHtzY2hlZHVsZUV4cHJlc3Npb259KWApO1xuICByZXR1cm4gc2NoZWR1bGVFeHByZXNzaW9uO1xufVxuXG4vKipcbiAqIFJlZ2lzdGVycyB0aGUgYHN0b3JlLXRva2VuYCBjb21tYW5kIHdpdGggdGhlIENMSSBwcm9ncmFtLlxuICpcbiAqIEdlbmVyYXRlcyBhIGxvbmctbGl2ZWQgSldUIHRva2VuIHZpYSB0aGUgcGxhdGZvcm0gQVBJIGFuZCBzdG9yZXMgaXRcbiAqIGluIEFXUyBTZWNyZXRzIE1hbmFnZXIgZm9yIHVzZSBieSB0aGUgc3ludGgvZGVwbG95IC0tc3RvcmUtdG9rZW5zIGZsYWcuXG4gKlxuICogUmVxdWlyZXMgUExBVEZPUk1fVE9LRU4gdG8gYmUgc2V0LCBvciB1c2UgLS1lbWFpbC8tLXBhc3N3b3JkIHRvIGxvZ2luIGlubGluZS5cbiAqXG4gKiBCeSBkZWZhdWx0IGl0IE9OTFkgd3JpdGVzIHRoZSBzZWNyZXQuIFBhc3MgLS1zY2hlZHVsZSB0byBhbHNvIGRlcGxveSB0aGUgZGFpbHlcbiAqIHRva2VuLXJlbmV3YWwgc3RhY2sgKGEgTGFtYmRhIHRoYXQgYXV0by1yZW5ld3MgdGhpcyB0b2tlbiBiZWZvcmUgaXQgZXhwaXJlcykuXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYGJhc2hcbiAqIHBpcGVsaW5lLW1hbmFnZXIgaW5mcmEgc3RvcmUtdG9rZW4gLS1yZWdpb24gdXMtZWFzdC0xXG4gKiBwaXBlbGluZS1tYW5hZ2VyIGluZnJhIHN0b3JlLXRva2VuIC0tZGF5cyA5MCAtLXJlZ2lvbiB1cy1lYXN0LTFcbiAqIHBpcGVsaW5lLW1hbmFnZXIgaW5mcmEgc3RvcmUtdG9rZW4gLS1zY2hlZHVsZSAtLXJlZ2lvbiB1cy1lYXN0LTEgICAgICAgICAgIyArIGRhaWx5IGF1dG8tcmVuZXdhbFxuICogcGlwZWxpbmUtbWFuYWdlciBpbmZyYSBzdG9yZS10b2tlbiAtLXNjaGVkdWxlIC0tY3JvbiAnMCAzICogKiAqJyAgICAgICAgICAjIGN1c3RvbSByZW5ld2FsIHRpbWVcbiAqIHBpcGVsaW5lLW1hbmFnZXIgaW5mcmEgc3RvcmUtdG9rZW4gLS1kYXlzIDcgLS1uby12ZXJpZnktc3NsXG4gKiBQTEFURk9STV9TRUNSRVRfTkFNRT1teS1jdXN0b20tc2VjcmV0IHBpcGVsaW5lLW1hbmFnZXIgaW5mcmEgc3RvcmUtdG9rZW4gICAjIG92ZXJyaWRlIHRoZSBkZXJpdmVkIG5hbWVcbiAqIHBpcGVsaW5lLW1hbmFnZXIgaW5mcmEgc3RvcmUtdG9rZW4gLS1kcnktcnVuXG4gKiBwaXBlbGluZS1tYW5hZ2VyIGluZnJhIHN0b3JlLXRva2VuIC1lIGFkbWluIC1wICcqKionIC0tcmVnaW9uIHVzLWVhc3QtMVxuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzdG9yZVRva2VuKHByb2dyYW06IENvbW1hbmQpOiB2b2lkIHtcbiAgd2l0aFNzbE9wdGlvbnMoXG4gICAgd2l0aFByb2ZpbGVPcHRpb24oXG4gICAgICB3aXRoUmVnaW9uT3B0aW9uKHByb2dyYW1cbiAgICAgICAgLmNvbW1hbmQoJ3N0b3JlLXRva2VuJylcbiAgICAgICAgLmRlc2NyaXB0aW9uKCdHZW5lcmF0ZSBKV1QgdG9rZW4gYW5kIHN0b3JlIGluIEFXUyBTZWNyZXRzIE1hbmFnZXIgZm9yIENESyBkZXBsb3ltZW50cycpXG4gICAgICAgIC5vcHRpb24oJy11LCAtLWlkZW50aWZpZXIgPGlkZW50aWZpZXI+JywgJ1VzZXJuYW1lIG9yIGVtYWlsIChza2lwcyBQTEFURk9STV9UT0tFTiByZXF1aXJlbWVudCknKVxuICAgICAgICAub3B0aW9uKCctcCwgLS1wYXNzd29yZCA8cGFzc3dvcmQ+JywgJ0xvZ2luIHBhc3N3b3JkICh1c2VkIHdpdGggLS1pZGVudGlmaWVyKScpXG4gICAgICAgIC5vcHRpb24oJy0tZGF5cyA8ZGF5cz4nLCAnVG9rZW4gbGlmZXRpbWUgaW4gZGF5cycsICczMCcpXG4gICAgICAgIC5vcHRpb24oJy0tc2NvcGUgPHNjb3BlPicsICdNaW50IGEgbmFycm93LXNjb3BlIG1hY2hpbmUgdG9rZW4gKGUuZy4gXCJyZXBvcnRpbmc6aW5nZXN0XCIpIGFuZCBzdG9yZSBpdCBhdCBhIHNjb3BlLXNwZWNpZmljIHNlY3JldCBwYXRoIGluc3RlYWQgb2YgdGhlIHNoYXJlZCBwbGF0Zm9ybSBzZWNyZXQnKVxuICAgICAgICAub3B0aW9uKCctLWRyeS1ydW4nLCAnU2hvdyB3aGF0IHdvdWxkIGJlIHN0b3JlZCB3aXRob3V0IHdyaXRpbmcgdG8gU2VjcmV0cyBNYW5hZ2VyJywgZmFsc2UpKSxcbiAgICApXG4gICAgICAub3B0aW9uKCctLXNjaGVkdWxlJywgJ0Fsc28gZGVwbG95IHRoZSBkYWlseSB0b2tlbi1yZW5ld2FsIHN0YWNrIHRoYXQgYXV0by1yZW5ld3MgdGhpcyB0b2tlbiAob2ZmIGJ5IGRlZmF1bHQpJywgZmFsc2UpXG4gICAgICAub3B0aW9uKCctLWNyb24gPGV4cHI+JywgJ1JlbmV3YWwgc2NoZWR1bGUgYXMgYSA1LWZpZWxkIGNyb24sIHVzZWQgd2l0aCAtLXNjaGVkdWxlIChkZWZhdWx0OiBUT0tFTl9SRU5FV19TQ0hFRFVMRSBlbnYgb3IgXCIwIDAgKiAqICpcIjsgbWluIGV2ZXJ5IDE1IG1pbnV0ZXMpJylcbiAgICAgIC5vcHRpb24oJy0tanNvbicsICdPdXRwdXQgcmVzdWx0IGFzIEpTT04nLCBmYWxzZSksXG4gIClcbiAgICAuYWN0aW9uKGFzeW5jIChvcHRpb25zKSA9PiB7XG4gICAgICBjb25zdCBleGVjdXRpb25JZCA9IHByaW50Q29tbWFuZEhlYWRlcignU3RvcmUgVG9rZW4nLCB1bmRlZmluZWQsIHsgcXVpZXQ6IG9wdGlvbnMuanNvbiB9KTtcblxuICAgICAgdHJ5IHtcbiAgICAgICAgcHJpbnRTc2xXYXJuaW5nKG9wdGlvbnMudmVyaWZ5U3NsKTtcblxuICAgICAgICBjb25zdCByZWdpb24gPSByZXNvbHZlQXdzUmVnaW9uKG9wdGlvbnMucmVnaW9uKTtcblxuICAgICAgICBjb25zdCBkYXlzID0gdmFsaWRhdGVOdW1iZXIob3B0aW9ucy5kYXlzLCAnZGF5cycsIDEsIDM2NSk7XG4gICAgICAgIGNvbnN0IGV4cGlyZXNJblNlY29uZHMgPSBkYXlzICogMjQgKiA2MCAqIDYwO1xuXG4gICAgICAgIC8vIFN0ZXAgMDogbG9nIGluIGZpcnN0IHdoZW4gY3JlZHMgYXJlIGF2YWlsYWJsZSBhbmQgbm8gUExBVEZPUk1fVE9LRU4gaXMgc2V0XG4gICAgICAgIC8vIChzaGFyZWQgd2l0aCBzZXR1cC1ldmVudHMpLiBDcmVkcyBjb21lIGZyb20gLS1lbWFpbC8tLXBhc3N3b3JkIE9SIHRoZSBlbnZcbiAgICAgICAgLy8gdmFycyBQTEFURk9STV9JREVOVElGSUVSL1BMQVRGT1JNX1BBU1NXT1JEIOKAlCB0aGUgZW52IHBhdGggbGV0cyBjYWxsZXJzIGxpa2VcbiAgICAgICAgLy8gYHByb3Zpc2lvbiAtLXdpdGgtZXZlbnRzYCBwYXNzIHRoZW0gd2l0aG91dCBwdXR0aW5nIHRoZSBwYXNzd29yZCBvbiB0aGVcbiAgICAgICAgLy8gY29tbWFuZCBsaW5lICh3aGVyZSBpdCB3b3VsZCBzaG93IGluIHBsYW5zL2xvZ3MpLlxuICAgICAgICBhd2FpdCBlbnN1cmVQbGF0Zm9ybVRva2VuKG9wdGlvbnMpO1xuXG4gICAgICAgIC8vIFN0ZXAgMTogQXV0aGVudGljYXRlIGFuZCBnZW5lcmF0ZSBsb25nLWxpdmVkIHRva2VuXG4gICAgICAgIHByaW50U2VjdGlvbignR2VuZXJhdGUgVG9rZW4nKTtcblxuICAgICAgICBjb25zdCBjbGllbnQgPSBhd2FpdCBjcmVhdGVBdXRoZW50aWNhdGVkQ2xpZW50QXN5bmMob3B0aW9ucyk7XG5cbiAgICAgICAgLy8gUmVzb2x2ZSBzZWNyZXQgbmFtZSBmcm9tIHRoZSB0b2tlbidzIG9yZ2FuaXphdGlvbklkLiBBbiBleHBsaWNpdFxuICAgICAgICAvLyBQTEFURk9STV9TRUNSRVRfTkFNRSBlbnYgd2lucyAoZXNjYXBlIGhhdGNoIGZvciBzeXN0ZW0vbm8tb3JnIHRva2VucyBhbmRcbiAgICAgICAgLy8gdGhlIHJlbmV3YWwgTGFtYmRhKTsgb3RoZXJ3aXNlIGRlcml2ZSBge3ByZWZpeH0ve29yZ0lkfS9wbGF0Zm9ybWAuXG4gICAgICAgIC8vIEEgYC0tc2NvcGVgIHRva2VuIGlzIGEgZGlzdGluY3QgbWFjaGluZSBjcmVkZW50aWFsIOKAlCBzdG9yZSBpdCBhdCBhXG4gICAgICAgIC8vIHNjb3BlLXNwZWNpZmljIHBhdGggKGAuLi4vcmVwb3J0aW5nLWluZ2VzdGApIHNvIGl0IG5ldmVyIGNsb2JiZXJzIHRoZVxuICAgICAgICAvLyBmdWxsLXByaXZpbGVnZSBwbGF0Zm9ybSB0b2tlbiB1c2VkIGJ5IHN5bnRoL2RlcGxveSBjYWxsYmFja3MuXG4gICAgICAgIGNvbnN0IHNjb3BlID0gb3B0aW9ucy5zY29wZSBhcyBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gICAgICAgIGNvbnN0IGJhc2VTZWNyZXROYW1lID0gcHJvY2Vzcy5lbnYuUExBVEZPUk1fU0VDUkVUX05BTUUgfHwgcmVzb2x2ZVNlY3JldE5hbWUocHJvY2Vzcy5lbnYuUExBVEZPUk1fVE9LRU4hKTtcbiAgICAgICAgY29uc3Qgc2VjcmV0TmFtZSA9IHNjb3BlICYmICFwcm9jZXNzLmVudi5QTEFURk9STV9TRUNSRVRfTkFNRVxuICAgICAgICAgID8gYmFzZVNlY3JldE5hbWUucmVwbGFjZSgvXFwvcGxhdGZvcm0kLywgYC8ke3Njb3BlLnJlcGxhY2UoL1teYS16MC05XSsvZ2ksICctJyl9YClcbiAgICAgICAgICA6IGJhc2VTZWNyZXROYW1lO1xuXG4gICAgICAgIGF1ZGl0TG9nKCdzdG9yZS10b2tlbicsIHsgZXhlY3V0aW9uSWQsIHNlY3JldE5hbWUsIGRheXMsIGRyeVJ1bjogb3B0aW9ucy5kcnlSdW4gfSk7XG5cbiAgICAgICAgcHJpbnRJbmZvKCdQYXJhbWV0ZXJzJywge1xuICAgICAgICAgIHNlY3JldE5hbWUsXG4gICAgICAgICAgcmVnaW9uLFxuICAgICAgICAgIGRheXMsXG4gICAgICAgICAgZXhwaXJlc0luOiBgJHtleHBpcmVzSW5TZWNvbmRzfXNgLFxuICAgICAgICAgIGRyeVJ1bjogb3B0aW9ucy5kcnlSdW4sXG4gICAgICAgIH0pO1xuXG4gICAgICAgIHByaW50SW5mbygnUmVxdWVzdGluZyB0b2tlbicsIHsgZXhwaXJlc0luOiBgJHtleHBpcmVzSW5TZWNvbmRzfXMgKCR7ZGF5c30gZGF5cylgIH0pO1xuXG4gICAgICAgIGNvbnN0IHRva2VuUmVzcG9uc2UgPSBhd2FpdCBjbGllbnQucG9zdDxSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj4oXG4gICAgICAgICAgJy9hcGkvdXNlci9nZW5lcmF0ZS10b2tlbicsXG4gICAgICAgICAgeyBleHBpcmVzSW46IGV4cGlyZXNJblNlY29uZHMsIC4uLihzY29wZSA/IHsgc2NvcGUgfSA6IHt9KSB9LFxuICAgICAgICApO1xuXG4gICAgICAgIGNvbnN0IHRva2VuRGF0YSA9ICh0b2tlblJlc3BvbnNlIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+KT8uZGF0YSA/PyB0b2tlblJlc3BvbnNlO1xuICAgICAgICBjb25zdCBhY2Nlc3NUb2tlbiA9ICh0b2tlbkRhdGEgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4pPy5hY2Nlc3NUb2tlbiBhcyBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gICAgICAgIGNvbnN0IHJlZnJlc2hUb2tlbiA9ICh0b2tlbkRhdGEgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4pPy5yZWZyZXNoVG9rZW4gYXMgc3RyaW5nIHwgdW5kZWZpbmVkO1xuICAgICAgICBjb25zdCBhY3R1YWxFeHBpcmVzSW4gPSAoKHRva2VuRGF0YSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik/LmV4cGlyZXNJbiBhcyBudW1iZXIpID8/IGV4cGlyZXNJblNlY29uZHM7XG5cbiAgICAgICAgaWYgKCFhY2Nlc3NUb2tlbikge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcignVG9rZW4gZ2VuZXJhdGlvbiBmYWlsZWQg4oCUIG5vIGFjY2VzcyB0b2tlbiBpbiByZXNwb25zZScpO1xuICAgICAgICB9XG5cbiAgICAgICAgcHJpbnRTdWNjZXNzKGBUb2tlbiBnZW5lcmF0ZWQgKGV4cGlyZXMgaW4gJHthY3R1YWxFeHBpcmVzSW59cylgKTtcblxuICAgICAgICBjb25zdCBleHBpcmVzQXQgPSBuZXcgRGF0ZShEYXRlLm5vdygpICsgYWN0dWFsRXhwaXJlc0luICogMTAwMCkudG9JU09TdHJpbmcoKTtcblxuICAgICAgICAvLyBTY2hlbWE6IHsgdXNlcm5hbWU6IG9yZ0lkLCBwYXNzd29yZDogSldULCAuLi5tZXRhZGF0YSB9XG4gICAgICAgIC8vIC0gdXNlcm5hbWUvcGFzc3dvcmQgZmllbGRzIHNhdGlzZnkgQ29kZUJ1aWxkJ3MgYHNlY3JldHNNYW5hZ2VyQ3JlZGVudGlhbHNgXG4gICAgICAgIC8vICAgKEhUVFAgQmFzaWMsIHNlbnQgdG8gcGlwZWxpbmUtaW1hZ2UtcmVnaXN0cnkncyAvdG9rZW4gZW5kcG9pbnQpXG4gICAgICAgIC8vIC0gVGhlIHNhbWUgSldUIGlzIGNvbnN1bWVkIGJ5IHRoZSBwbHVnaW4tbG9va3VwIExhbWJkYSBieSByZWFkaW5nXG4gICAgICAgIC8vICAgdGhlIGBwYXNzd29yZGAgZmllbGRcbiAgICAgICAgLy8gLSBPbmUgU2VjcmV0IHBlciBjdXN0b21lciBhY2NvdW50IHJlcGxhY2VzIHRoZSBwcmV2aW91cyB0d28tc2VjcmV0IG1vZGVsXG4gICAgICAgIC8vIERlY29kZSBKV1QgZm9yIG9yZ0lkIOKAlCBpdCdzIGEgc3RhYmxlIGlkZW50aWZpZXIgZm9yIHRoZSB1c2VybmFtZSBmaWVsZDtcbiAgICAgICAgLy8gdGhlIGFjdHVhbCBhdXRoIHVzZXMgdGhlIHBhc3N3b3JkIChKV1QpIHdoaWNoIHRoZSB0b2tlbiBzZXJ2aWNlIHZlcmlmaWVzLlxuICAgICAgICAvLyBgfHxgIChub3QgYD8/YCk6IGFuIEVNUFRZLXN0cmluZyBvcmdhbml6YXRpb25JZCBtdXN0IGFsc28gZmFsbCBiYWNrLiBBXG4gICAgICAgIC8vIHN5c2FkbWluL3N5c3RlbSB0b2tlbiBvZnRlbiBjYXJyaWVzIG9yZ2FuaXphdGlvbklkPVwiXCIsIGFuZCBDb2RlQnVpbGRcbiAgICAgICAgLy8gcmVqZWN0cyBhIHJlZ2lzdHJ5IGNyZWRlbnRpYWwgd2hvc2UgYHVzZXJuYW1lYCBmaWVsZCBpcyBlbXB0eSB3aXRoXG4gICAgICAgIC8vIFwiQXV0aG9yaXphdGlvbkRhdGEgaXMgbWFsZm9ybWVkLCBlbXB0eSBmaWVsZFwiIOKAlCBzbyB1c2VybmFtZSBtdXN0IGFsd2F5c1xuICAgICAgICAvLyBiZSBhIG5vbi1lbXB0eSB2YWx1ZS5cbiAgICAgICAgY29uc3QgcGF5bG9hZCA9IGRlY29kZVRva2VuUGF5bG9hZChhY2Nlc3NUb2tlbik7XG4gICAgICAgIGNvbnN0IG9yZ0lkID0gcGF5bG9hZD8ub3JnYW5pemF0aW9uSWQ/LnRyaW0oKSB8fCAndW5rbm93bi1vcmcnO1xuXG4gICAgICAgIGNvbnN0IHNlY3JldFZhbHVlID0gSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICAgIHVzZXJuYW1lOiBvcmdJZCxcbiAgICAgICAgICAvLyBgcGFzc3dvcmRgIGlzIHRoZSBjYW5vbmljYWwgSldUIGZpZWxkIOKAlCByZWFkIGJ5IENvZGVCdWlsZCBjcmVkcyxcbiAgICAgICAgICAvLyBwbHVnaW4tbG9va3VwLCB0b2tlbi1yZW5ldywgYW5kIHRoZSBldmVudC1pbmdlc3Rpb24gTGFtYmRhLlxuICAgICAgICAgIHBhc3N3b3JkOiBhY2Nlc3NUb2tlbixcbiAgICAgICAgICAuLi4ocmVmcmVzaFRva2VuICYmIHsgcmVmcmVzaFRva2VuIH0pLFxuICAgICAgICAgIHBsYXRmb3JtVXJsOiBjbGllbnQuZ2V0QmFzZVVybCgpLFxuICAgICAgICAgIGV4cGlyZXNJbjogYWN0dWFsRXhwaXJlc0luLFxuICAgICAgICAgIGV4cGlyZXNBdCxcbiAgICAgICAgICBjcmVhdGVkQXQ6IG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKSxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gRHJ5LXJ1bjogc2hvdyB3aGF0IHdvdWxkIGJlIHN0b3JlZFxuICAgICAgICBpZiAob3B0aW9ucy5kcnlSdW4pIHtcbiAgICAgICAgICBpZiAob3B0aW9ucy5qc29uKSB7XG4gICAgICAgICAgICBjb25zb2xlLmxvZyhKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgICAgICAgIHN1Y2Nlc3M6IHRydWUsXG4gICAgICAgICAgICAgIGRyeVJ1bjogdHJ1ZSxcbiAgICAgICAgICAgICAgc2VjcmV0TmFtZSxcbiAgICAgICAgICAgICAgcmVnaW9uLFxuICAgICAgICAgICAgICBleHBpcmVzSW5EYXlzOiBkYXlzLFxuICAgICAgICAgICAgICBleHBpcmVzQXQsXG4gICAgICAgICAgICAgIHRva2VuTGVuZ3RoOiBhY2Nlc3NUb2tlbi5sZW5ndGgsXG4gICAgICAgICAgICAgIGhhc1JlZnJlc2hUb2tlbjogISFyZWZyZXNoVG9rZW4sXG4gICAgICAgICAgICB9LCBudWxsLCAyKSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKCcnKTtcbiAgICAgICAgICAgIHByaW50U2VjdGlvbignRHJ5IFJ1biDigJQgTm8gQ2hhbmdlcyBNYWRlJyk7XG4gICAgICAgICAgICBwcmludEtleVZhbHVlKHtcbiAgICAgICAgICAgICAgJ1NlY3JldCBOYW1lJzogc2VjcmV0TmFtZSxcbiAgICAgICAgICAgICAgJ1JlZ2lvbic6IHJlZ2lvbixcbiAgICAgICAgICAgICAgJ0V4cGlyZXMgSW4nOiBgJHtkYXlzfSBkYXlzYCxcbiAgICAgICAgICAgICAgJ1JlbmV3IEJ5JzogZXhwaXJlc0F0LFxuICAgICAgICAgICAgICAnVG9rZW4gTGVuZ3RoJzogYCR7YWNjZXNzVG9rZW4ubGVuZ3RofSBjaGFyc2AsXG4gICAgICAgICAgICAgICdIYXMgUmVmcmVzaCBUb2tlbic6IHJlZnJlc2hUb2tlbiA/ICdZZXMnIDogJ05vJyxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcHJpbnRTdWNjZXNzKCdEcnkgcnVuIGNvbXBsZXRlIOKAlCBubyBzZWNyZXQgd2FzIGNyZWF0ZWQgb3IgdXBkYXRlZCcpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICAvLyBTdGVwIDI6IFN0b3JlIHRva2VuIGluIFNlY3JldHMgTWFuYWdlclxuICAgICAgICBwcmludFNlY3Rpb24oJ1N0b3JlIFRva2VuJyk7XG5cbiAgICAgICAgY29uc3QgZGVzY3JpcHRpb24gPSBgUGxhdGZvcm0gSldUIHRva2VuIChyZW5ldyBieSAke2V4cGlyZXNBdH0pYDtcbiAgICAgICAgYXdhaXQgdXBzZXJ0U2VjcmV0KHNlY3JldE5hbWUsIHNlY3JldFZhbHVlLCBkZXNjcmlwdGlvbiwgeyByZWdpb24sIHByb2ZpbGU6IG9wdGlvbnMucHJvZmlsZSB9KTtcblxuICAgICAgICBjb25zdCBhcm4gPSBhd2FpdCBnZXRTZWNyZXRBcm4oc2VjcmV0TmFtZSwgeyByZWdpb24sIHByb2ZpbGU6IG9wdGlvbnMucHJvZmlsZSB9KTtcblxuICAgICAgICAvLyBPcHRpb25hbGx5IGluc3RhbGwgdGhlIG9uY2UtYS1kYXkgcmVuZXdhbCBzdGFjayBzbyB0aGlzIHRva2VuIG5ldmVyIGxhcHNlcy5cbiAgICAgICAgLy8gT2ZmIGJ5IGRlZmF1bHQg4oCUIG9wdCBpbiB3aXRoIC0tc2NoZWR1bGUgKGUuZy4gZm9yIHRoZSBBV1MgZXZlbnQtaW5nZXN0aW9uXG4gICAgICAgIC8vIGJ1bmRsZSB3aG9zZSBMYW1iZGEgbmVlZHMgYSBub24tZXhwaXJpbmcgdG9rZW4pLlxuICAgICAgICBsZXQgc2NoZWR1bGVFeHByZXNzaW9uOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gICAgICAgIGlmIChvcHRpb25zLnNjaGVkdWxlKSB7XG4gICAgICAgICAgY29uc3QgZml2ZUZpZWxkQ3JvbiA9IG9wdGlvbnMuY3JvbiB8fCBwcm9jZXNzLmVudi5UT0tFTl9SRU5FV19TQ0hFRFVMRSB8fCBERUZBVUxUX1JFTkVXX0NST047XG4gICAgICAgICAgc2NoZWR1bGVFeHByZXNzaW9uID0gYXdhaXQgZGVwbG95UmVuZXdTY2hlZHVsZSh7XG4gICAgICAgICAgICBwbGF0Zm9ybVVybDogY2xpZW50LmdldEJhc2VVcmwoKSxcbiAgICAgICAgICAgIHNlY3JldE5hbWUsXG4gICAgICAgICAgICBkYXlzLFxuICAgICAgICAgICAgZml2ZUZpZWxkQ3JvbixcbiAgICAgICAgICAgIHJlZ2lvbixcbiAgICAgICAgICAgIHByb2ZpbGU6IG9wdGlvbnMucHJvZmlsZSxcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChvcHRpb25zLmpzb24pIHtcbiAgICAgICAgICBjb25zb2xlLmxvZyhKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgICAgICBzdWNjZXNzOiB0cnVlLFxuICAgICAgICAgICAgc2VjcmV0TmFtZSxcbiAgICAgICAgICAgIHNlY3JldEFybjogYXJuLFxuICAgICAgICAgICAgcmVnaW9uLFxuICAgICAgICAgICAgZXhwaXJlc0luRGF5czogZGF5cyxcbiAgICAgICAgICAgIGV4cGlyZXNBdCxcbiAgICAgICAgICAgIHNjaGVkdWxlOiBzY2hlZHVsZUV4cHJlc3Npb24gPz8gbnVsbCxcbiAgICAgICAgICB9LCBudWxsLCAyKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY29uc29sZS5sb2coJycpO1xuICAgICAgICAgIHByaW50U2VjdGlvbignVG9rZW4gU3RvcmVkJyk7XG5cbiAgICAgICAgICBwcmludEtleVZhbHVlKHtcbiAgICAgICAgICAgICdTZWNyZXQgTmFtZSc6IHNlY3JldE5hbWUsXG4gICAgICAgICAgICAnU2VjcmV0IEFSTic6IGFybixcbiAgICAgICAgICAgICdSZWdpb24nOiByZWdpb24sXG4gICAgICAgICAgICAnRXhwaXJlcyBJbic6IGAke2RheXN9IGRheXNgLFxuICAgICAgICAgICAgJ1JlbmV3IEJ5JzogZXhwaXJlc0F0LFxuICAgICAgICAgICAgJ0F1dG8tUmVuZXcnOiBzY2hlZHVsZUV4cHJlc3Npb24gPyBg4pyTICR7c2NoZWR1bGVFeHByZXNzaW9ufWAgOiAnb2ZmIChwYXNzIC0tc2NoZWR1bGUgdG8gZW5hYmxlKScsXG4gICAgICAgICAgICAnU3RhdHVzJzogJ+KckyBTdG9yZWQnLFxuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgY29uc29sZS5sb2coJycpO1xuICAgICAgICAgIHByaW50U3VjY2VzcygnVG9rZW4gc3RvcmVkLiBUbyB1c2Ugd2l0aCBzeW50aC9kZXBsb3k6Jyk7XG4gICAgICAgICAgcHJpbnRJbmZvKGAgIGV4cG9ydCBQTEFURk9STV9TRUNSRVRfTkFNRT0ke3NlY3JldE5hbWV9YCk7XG4gICAgICAgICAgcHJpbnRJbmZvKCcgIHBpcGVsaW5lLW1hbmFnZXIgcGlwZWxpbmUgc3ludGggLS1pZCA8cGlwZWxpbmUtaWQ+IC0tc3RvcmUtdG9rZW5zJyk7XG4gICAgICAgICAgY29uc29sZS5sb2coJycpO1xuICAgICAgICAgIGlmIChzY2hlZHVsZUV4cHJlc3Npb24pIHtcbiAgICAgICAgICAgIHByaW50SW5mbyhgQXV0by1yZW5ld2FsIGlzIGFjdGl2ZSAoJHtzY2hlZHVsZUV4cHJlc3Npb259KTsgdGhlIHNlY3JldCByZWZyZXNoZXMgYmVmb3JlICR7ZXhwaXJlc0F0fS5gKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcHJpbnRJbmZvKGBSZW5ldyBiZWZvcmUgJHtleHBpcmVzQXR9IHdpdGg6IHBpcGVsaW5lLW1hbmFnZXIgaW5mcmEgc3RvcmUtdG9rZW4gLS1kYXlzICR7ZGF5c31gKTtcbiAgICAgICAgICAgIHByaW50SW5mbygnICAob3IgcGFzcyAtLXNjaGVkdWxlIHRvIGluc3RhbGwgYSBkYWlseSBhdXRvLXJlbmV3YWwgc3RhY2spJyk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIGhhbmRsZUVycm9yKGVycm9yLCBFUlJPUl9DT0RFUy5BUElfUkVRVUVTVCwge1xuICAgICAgICAgIGRlYnVnOiBwcm9ncmFtLm9wdHMoKS5kZWJ1ZyxcbiAgICAgICAgICBleGl0OiB0cnVlLFxuICAgICAgICAgIGNvbnRleHQ6IHtcbiAgICAgICAgICAgIGNvbW1hbmQ6ICdzdG9yZS10b2tlbicsXG4gICAgICAgICAgICBleGVjdXRpb25JZCxcbiAgICAgICAgICAgIHNlY3JldE5hbWU6IHByb2Nlc3MuZW52LlBMQVRGT1JNX1NFQ1JFVF9OQU1FIHx8ICcoZGVyaXZlZCBmcm9tIHRva2VuKScsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfSk7XG59XG4iXX0=
387
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RvcmUtdG9rZW4uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY29tbWFuZHMvc3RvcmUtdG9rZW4udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsK0NBQStDO0FBQy9DLHNDQUFzQztBQUV0QyxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzdDLE9BQU8sS0FBSyxFQUFFLE1BQU0sSUFBSSxDQUFDO0FBQ3pCLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFDekMsT0FBTyxLQUFLLEVBQUUsTUFBTSxJQUFJLENBQUM7QUFDekIsT0FBTyxJQUFJLE1BQU0sTUFBTSxDQUFDO0FBQ3hCLE9BQU8sRUFBRSxZQUFZLEVBQUUseUJBQXlCLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUNqRixPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQ3BDLE9BQU8sRUFBRSxXQUFXLEVBQUUsY0FBYyxFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFDekUsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQ2pELE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ3ZELE9BQU8sRUFBRSxZQUFZLEVBQUUsWUFBWSxFQUFFLGNBQWMsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQ3JGLE9BQU8sRUFBRSw4QkFBOEIsRUFBRSxrQkFBa0IsRUFBRSxlQUFlLEVBQUUsaUJBQWlCLEVBQUUsZ0JBQWdCLEVBQUUsY0FBYyxFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDckssT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDckQsT0FBTyxFQUFFLFdBQVcsRUFBRSxXQUFXLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUNyRSxPQUFPLEVBQUUsU0FBUyxFQUFFLGFBQWEsRUFBRSxZQUFZLEVBQUUsWUFBWSxFQUFFLFlBQVksRUFBRSxN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aEIsWUFBWSxDQUFDLHVDQUF1QyxDQUFDLENBQUM7Z0JBQ3RELFNBQVMsQ0FBQyxpQ0FBaUMsVUFBVSxFQUFFLENBQUMsQ0FBQztnQkFDekQsU0FBUyxDQUFDLHFFQUFxRSxDQUFDLENBQUM7Z0JBQ2pGLE9BQU8sQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUM7Z0JBQ2hCLElBQUksa0JBQWtCLEVBQUUsQ0FBQztvQkFDdkIsU0FBUyxDQUFDLDRCQUE0QixrQkFBa0Isb0NBQW9DLFdBQVcsQ0FBQyxTQUFTLEdBQUcsQ0FBQyxDQUFDO2dCQUN4SCxDQUFDO3FCQUFNLENBQUM7b0JBQ04sU0FBUyxDQUFDLGlCQUFpQixXQUFXLENBQUMsU0FBUyxvREFBb0QsSUFBSSxFQUFFLENBQUMsQ0FBQztvQkFDNUcsU0FBUyxDQUFDLCtEQUErRCxDQUFDLENBQUM7Z0JBQzdFLENBQUM7WUFDSCxDQUFDO1FBRUgsQ0FBQztRQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7WUFDZixXQUFXLENBQUMsS0FBSyxFQUFFLFdBQVcsQ0FBQyxXQUFXLEVBQUU7Z0JBQzFDLEtBQUssRUFBRSxPQUFPLENBQUMsSUFBSSxFQUFFLENBQUMsS0FBSztnQkFDM0IsSUFBSSxFQUFFLElBQUk7Z0JBQ1YsT0FBTyxFQUFFO29CQUNQLE9BQU8sRUFBRSxhQUFhO29CQUN0QixXQUFXO29CQUNYLFVBQVUsRUFBRSxPQUFPLENBQUMsR0FBRyxDQUFDLG9CQUFvQixJQUFJLHdCQUF3QjtpQkFDekU7YUFDRixDQUFDLENBQUM7UUFDTCxDQUFDO0lBQ0gsQ0FBQyxDQUFDLENBQUM7QUFDUCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IDIwMjYgUGlwZWxpbmUgQnVpbGRlciBDb250cmlidXRvcnNcbi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG5cbmltcG9ydCB7IGV4ZWNGaWxlU3luYyB9IGZyb20gJ2NoaWxkX3Byb2Nlc3MnO1xuaW1wb3J0ICogYXMgZnMgZnJvbSAnZnMnO1xuaW1wb3J0IHsgZmlsZVVSTFRvUGF0aCB9IGZyb20gJ25vZGU6dXJsJztcbmltcG9ydCAqIGFzIG9zIGZyb20gJ29zJztcbmltcG9ydCBwYXRoIGZyb20gJ3BhdGgnO1xuaW1wb3J0IHsgTGFtYmRhQ2xpZW50LCBVcGRhdGVGdW5jdGlvbkNvZGVDb21tYW5kIH0gZnJvbSAnQGF3cy1zZGsvY2xpZW50LWxhbWJkYSc7XG5pbXBvcnQgeyBDb21tYW5kIH0gZnJvbSAnY29tbWFuZGVyJztcbmltcG9ydCB7IEFQUF9WRVJTSU9OLCB2YWxpZGF0ZU51bWJlciB9IGZyb20gJy4uL2NvbmZpZy9jbGkuY29uc3RhbnRzLmpzJztcbmltcG9ydCB7IGF1ZGl0TG9nIH0gZnJvbSAnLi4vdXRpbHMvYXVkaXQtbG9nLmpzJztcbmltcG9ydCB7IHJlc29sdmVBd3NSZWdpb24gfSBmcm9tICcuLi91dGlscy9hd3MtZW52LmpzJztcbmltcG9ydCB7IHVwc2VydFNlY3JldCwgZ2V0U2VjcmV0QXJuLCBnZXRTZWNyZXRWYWx1ZSB9IGZyb20gJy4uL3V0aWxzL2F3cy1zZWNyZXRzLmpzJztcbmltcG9ydCB7IGNyZWF0ZUF1dGhlbnRpY2F0ZWRDbGllbnRBc3luYywgcHJpbnRDb21tYW5kSGVhZGVyLCBwcmludFNzbFdhcm5pbmcsIHdpdGhQcm9maWxlT3B0aW9uLCB3aXRoUmVnaW9uT3B0aW9uLCB3aXRoU3NsT3B0aW9ucyB9IGZyb20gJy4uL3V0aWxzL2NvbW1hbmQtdXRpbHMuanMnO1xuaW1wb3J0IHsgdG9FdmVudEJyaWRnZUNyb24gfSBmcm9tICcuLi91dGlscy9jcm9uLmpzJztcbmltcG9ydCB7IEVSUk9SX0NPREVTLCBoYW5kbGVFcnJvciB9IGZyb20gJy4uL3V0aWxzL2Vycm9yLWhhbmRsZXIuanMnO1xuaW1wb3J0IHsgcHJpbnRJbmZvLCBwcmludEtleVZhbHVlLCBwcmludFNlY3Rpb24sIHByaW50U3VjY2VzcywgcHJpbnRXYXJuaW5nIH0gZnJvbSAnLi4vdXRpbHMvb3V0cHV0LXV0aWxzLmpzJztcbmltcG9ydCB7IGVuc3VyZVBsYXRmb3JtVG9rZW4sIHNjb3BlU2VjcmV0TGVhZiwgc2VjcmV0TmFtZUZvck9yZyB9IGZyb20gJy4uL3V0aWxzL3BsYXRmb3JtLXNlY3JldC5qcyc7XG5pbXBvcnQgeyBwcm92aXNpb25TZXJ2aWNlQWNjb3VudEtleSwgcmV2b2tlU2VydmljZUFjY291bnRLZXkgfSBmcm9tICcuLi91dGlscy9zZXJ2aWNlLWFjY291bnQuanMnO1xuXG4vLyBFU00gaGFzIG5vIF9fZGlybmFtZTsgZGVyaXZlIGl0IGZyb20gdGhpcyBtb2R1bGUncyBVUkwuXG5jb25zdCBfX2Rpcm5hbWUgPSBwYXRoLmRpcm5hbWUoZmlsZVVSTFRvUGF0aChpbXBvcnQubWV0YS51cmwpKTtcblxuY29uc3QgUkVORVdfU1RBQ0tfTkFNRSA9ICdwaXBlbGluZS1idWlsZGVyLXRva2VuLXJlbmV3Jztcbi8vIENGTi1tYW5hZ2VkIExhbWJkYSBmdW5jdGlvbiBuYW1lIOKAlCBrZWVwIGluIHN5bmMgd2l0aCB0b2tlbi1yZW5ldy1zdGFjay5qc29uLlxuY29uc3QgUkVORVdfTEFNQkRBX05BTUUgPSAncGlwZWxpbmUtYnVpbGRlci10b2tlbi1yZW5ldyc7XG4vLyBEZWZhdWx0IDUtZmllbGQgY3JvbiAoZGFpbHkgYXQgbWlkbmlnaHQpIHdoZW4gbmVpdGhlciAtLWNyb24gbm9yIFRPS0VOX1JFTkVXX1NDSEVEVUxFIGlzIHNldC5cbmNvbnN0IERFRkFVTFRfUkVORVdfQ1JPTiA9ICcwIDAgKiAqIConO1xuXG4vKipcbiAqIENhcGFiaWxpdHkgc2NvcGVzIGEgc3RvcmVkIGNyZWRlbnRpYWwgbWF5IGNhcnJ5LCBhbmQgd2hhdCBlYWNoIG9uZSBpcyBGT1IuXG4gKlxuICogQSBzY29wZWQga2V5IGV4Y2hhbmdlcyB0byBhIHRva2VuIHdpdGggbm8gcGVybWlzc2lvbnMgYW5kIG5vIGFkbWluIGZsYWdzIGF0XG4gKiBhbGwg4oCUIG9ubHkgdGhlIG9uZSBjYXBhYmlsaXR5IOKAlCBzbyBpdCBpcyB0aGUgc2hhcGUgZXZlcnkgYXV0b21hdGlvbiB0aGF0IGRvZXNcbiAqIGV4YWN0bHkgb25lIHRoaW5nIHNob3VsZCBob2xkICgjMTIpLiBUaGUgdW5zY29wZWQgYHBsYXRmb3JtYCBjcmVkZW50aWFsIGlzIHRoZVxuICogcmVtYWluaW5nIGZ1bGwtcHJpdmlsZWdlIG9uZTogc3ludGgvZGVwbG95IGNhbGxiYWNrcyBhbmQgdGhlIHBsdWdpbi1sb29rdXBcbiAqIExhbWJkYSBjYWxsIHRoZSBvcmRpbmFyeSBBUEkgc3VyZmFjZSwgd2hpY2ggbm8gc2luZ2xlIHNjb3BlIGNvdmVycy5cbiAqL1xuY29uc3QgU0NPUEVfQ0FUQUxPRzogUmVjb3JkPHN0cmluZywgeyBhY2NvdW50OiBzdHJpbmc7IGRlc2NyaXB0aW9uOiBzdHJpbmcgfT4gPSB7XG4gICdyZXBvcnRpbmc6aW5nZXN0Jzoge1xuICAgIGFjY291bnQ6ICdyZXBvcnRpbmctaW5nZXN0JyxcbiAgICBkZXNjcmlwdGlvbjogJ0FXUyBwaXBlbGluZS1ldmVudCBpbmdlc3Rpb24gKHRoZSBldmVudHMgTGFtYmRhIFBPU1RzIC9yZXBvcnRzL2V2ZW50cyknLFxuICB9LFxuICAncmVnaXN0cnk6cHVzaCc6IHtcbiAgICBhY2NvdW50OiAncmVnaXN0cnktcHVzaCcsXG4gICAgZGVzY3JpcHRpb246ICdDSSBpbWFnZSBwdXNoZXMgaW50byB0aGlzIG9yZ+KAmXMgcmVnaXN0cnkgbmFtZXNwYWNlIChDb2RlQnVpbGQg4oaSIC90b2tlbiknLFxuICB9LFxufTtcblxuLyoqIFRoZSBhY2NvdW50IHRoYXQgaG9sZHMgdGhlIHVuc2NvcGVkLCBmdWxsLXByaXZpbGVnZSBzdG9yZWQgY3JlZGVudGlhbC4gKi9cbmNvbnN0IFBMQVRGT1JNX0FDQ09VTlQgPSB7XG4gIGFjY291bnQ6ICdwbGF0Zm9ybS1hdXRvbWF0aW9uJyxcbiAgZGVzY3JpcHRpb246ICdTdG9yZWQgcGxhdGZvcm0gY3JlZGVudGlhbCBmb3IgQ0RLIHN5bnRoL2RlcGxveSwgcGx1Z2luIGxvb2t1cCBhbmQgaW1hZ2UgcHVzaGVzJyxcbn07XG5cbi8qKlxuICogRGVwbG95IChvciB1cGRhdGUpIHRoZSBvbmNlLWEtZGF5IEtFWSBST1RBVElPTiBzdGFjazogYSBzY2hlZHVsZWQgTGFtYmRhIHRoYXRcbiAqIHJlcGxhY2VzIHRoZSBzZXJ2aWNlLWFjY291bnQga2V5IGluIHRoaXMgc2VjcmV0IGJlZm9yZSBpdCBleHBpcmVzLiBNaXJyb3JzXG4gKiBzZXR1cC1ldmVudHMg4oCUIGBhd3MgY2xvdWRmb3JtYXRpb24gZGVwbG95YCBmb3IgdGhlIGluZnJhLCB0aGVuIGEgZGlyZWN0XG4gKiBVcGRhdGVGdW5jdGlvbkNvZGUgd2l0aCB0aGUgcm90YXRvciBoYW5kbGVyIGNvbXBpbGVkIGFsb25nc2lkZSB0aGlzIENMSSAoc2VlXG4gKiBzcmMvbGFtYmRhL3Rva2VuLXJlbmV3LWhhbmRsZXIudHMpLlxuICovXG5hc3luYyBmdW5jdGlvbiBkZXBsb3lSZW5ld1NjaGVkdWxlKG9wdHM6IHtcbiAgcGxhdGZvcm1Vcmw6IHN0cmluZztcbiAgc2VjcmV0TmFtZTogc3RyaW5nO1xuICBkYXlzOiBudW1iZXI7XG4gIGZpdmVGaWVsZENyb246IHN0cmluZztcbiAgcmVnaW9uOiBzdHJpbmc7XG4gIHByb2ZpbGU/OiBzdHJpbmc7XG59KTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgY29uc3Qgc2NoZWR1bGVFeHByZXNzaW9uID0gdG9FdmVudEJyaWRnZUNyb24ob3B0cy5maXZlRmllbGRDcm9uKTsgLy8gdmFsaWRhdGVzICsgMTUtbWluIGd1YXJkXG5cbiAgLy8gTmFtZSByZW5ld2FsIHJlc291cmNlcyBwZXItc2VjcmV0IHNvIGEgc2NvcGVkLWNyZWRlbnRpYWwgc3RhY2sgKGUuZy4gdGhlXG4gIC8vIHJlcG9ydGluZy1pbmdlc3Qga2V5IHRoZSBldmVudCBMYW1iZGEgcmVhZHMpIGNvZXhpc3RzIHdpdGggdGhlXG4gIC8vIHBsYXRmb3JtLWNyZWRlbnRpYWwgc3RhY2sgaW5zdGVhZCBvZiBjb2xsaWRpbmcgb24gdGhlIChhY2NvdW50LWdsb2JhbCkgSUFNXG4gIC8vIHJvbGUgLyBMYW1iZGEgLyBydWxlIG5hbWVzLiBUaGUgcGxhdGZvcm0gc2VjcmV0IGtlZXBzIHRoZSBiYXJlIG5hbWVcbiAgLy8gKHN1ZmZpeCAnJykgc28gZXhpc3RpbmcgZGVwbG95bWVudHMnIHN0YWNrIGlzIHVwZGF0ZWQgaW4gcGxhY2UsIG5vdFxuICAvLyBkdXBsaWNhdGVkOyBhbnkgb3RoZXIgc2VjcmV0IGFwcGVuZHMgaXRzIHRyYWlsaW5nIHBhdGggc2VnbWVudC5cbiAgY29uc3Qgc2VjcmV0TGVhZiA9IG9wdHMuc2VjcmV0TmFtZS5yZXBsYWNlKC8uKlxcLy8sICcnKTsgLy8gJ3BsYXRmb3JtJyB8ICdyZXBvcnRpbmctaW5nZXN0JyB8IOKAplxuICBjb25zdCBuYW1lU3VmZml4ID0gc2VjcmV0TGVhZiA9PT0gJ3BsYXRmb3JtJyA/ICcnIDogYC0ke3NlY3JldExlYWYucmVwbGFjZSgvW15hLXowLTldKy9naSwgJy0nKX1gO1xuICBjb25zdCBzdGFja05hbWUgPSBgJHtSRU5FV19TVEFDS19OQU1FfSR7bmFtZVN1ZmZpeH1gO1xuICBjb25zdCBsYW1iZGFOYW1lID0gYCR7UkVORVdfTEFNQkRBX05BTUV9JHtuYW1lU3VmZml4fWA7XG5cbiAgcHJpbnRTZWN0aW9uKCdTY2hlZHVsZSBSb3RhdGlvbicpO1xuICBwcmludEluZm8oJ1BhcmFtZXRlcnMnLCB7XG4gICAgc3RhY2s6IHN0YWNrTmFtZSxcbiAgICBzY2hlZHVsZTogb3B0cy5maXZlRmllbGRDcm9uLFxuICAgIGV2ZW50YnJpZGdlOiBzY2hlZHVsZUV4cHJlc3Npb24sXG4gICAgcmVuZXdEYXlzOiBvcHRzLmRheXMsXG4gIH0pO1xuXG4gIC8vIFN0ZXAgMTogaW5mcmEgKExhbWJkYSBnZXRzIHBsYWNlaG9sZGVyIGNvZGUgb24gZmlyc3QgY3JlYXRlKS5cbiAgY29uc3QgdGVtcGxhdGVQYXRoID0gcGF0aC5qb2luKF9fZGlybmFtZSwgJy4uL3RlbXBsYXRlcy90b2tlbi1yZW5ldy1zdGFjay5qc29uJyk7XG4gIGNvbnN0IGNmbkFyZ3MgPSBbXG4gICAgJ2Nsb3VkZm9ybWF0aW9uJywgJ2RlcGxveScsXG4gICAgJy0tc3RhY2stbmFtZScsIHN0YWNrTmFtZSxcbiAgICAnLS10ZW1wbGF0ZS1maWxlJywgdGVtcGxhdGVQYXRoLFxuICAgICctLXBhcmFtZXRlci1vdmVycmlkZXMnLFxuICAgIGBQbGF0Zm9ybUJhc2VVcmw9JHtvcHRzLnBsYXRmb3JtVXJsfWAsXG4gICAgYFBsYXRmb3JtU2VjcmV0TmFtZT0ke29wdHMuc2VjcmV0TmFtZX1gLFxuICAgIGBSZW5ld0RheXM9JHtvcHRzLmRheXN9YCxcbiAgICBgU2NoZWR1bGVFeHByZXNzaW9uPSR7c2NoZWR1bGVFeHByZXNzaW9ufWAsXG4gICAgYE5hbWVTdWZmaXg9JHtuYW1lU3VmZml4fWAsXG4gICAgLy8gUmVjb3JkZWQgZm9yIHByb3ZlbmFuY2Ugb25seSDigJQgdGhlIHJvdGF0b3Igbm8gbG9uZ2VyIGluc3RhbGxzIHRoZSBDTEkgYXRcbiAgICAvLyBydW50aW1lIChpdCBzcGVha3MgdG8gdGhlIHBsYXRmb3JtIGRpcmVjdGx5KSwgYnV0IGtub3dpbmcgd2hpY2ggQ0xJXG4gICAgLy8gZGVwbG95ZWQgYSBzdGFjayBpcyB3b3J0aCBrZWVwaW5nLlxuICAgIGBQaXBlbGluZU1hbmFnZXJWZXJzaW9uPSR7QVBQX1ZFUlNJT059YCxcbiAgICAnLS1jYXBhYmlsaXRpZXMnLCAnQ0FQQUJJTElUWV9OQU1FRF9JQU0nLFxuICAgICctLW5vLWZhaWwtb24tZW1wdHktY2hhbmdlc2V0JyxcbiAgICAnLS1yZWdpb24nLCBvcHRzLnJlZ2lvbixcbiAgXTtcbiAgaWYgKG9wdHMucHJvZmlsZSkgY2ZuQXJncy5wdXNoKCctLXByb2ZpbGUnLCBvcHRzLnByb2ZpbGUpO1xuICBleGVjRmlsZVN5bmMoJ2F3cycsIGNmbkFyZ3MsIHsgc3RkaW86ICdpbmhlcml0JyB9KTtcblxuICAvLyBTdGVwIDI6IHVwbG9hZCB0aGUgcmVhbCBoYW5kbGVyLiBJdCdzIEVTTSwgc28gdGhlIHppcCBlbnRyeSBtdXN0IGJlIGluZGV4Lm1qc1xuICAvLyAoSGFuZGxlciBzdGF5cyBpbmRleC5oYW5kbGVyIOKAlCBub2RlanMyNC54IHJlc29sdmVzIHRoZSAubWpzIGV4dGVuc2lvbikuXG4gIGNvbnN0IGhhbmRsZXJTcmMgPSBwYXRoLmpvaW4oX19kaXJuYW1lLCAnLi4vbGFtYmRhL3Rva2VuLXJlbmV3LWhhbmRsZXIuanMnKTtcbiAgaWYgKCFmcy5leGlzdHNTeW5jKGhhbmRsZXJTcmMpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBUb2tlbi1yZW5ldyBoYW5kbGVyIG5vdCBmb3VuZCBhdCAke2hhbmRsZXJTcmN9IOKAlCB3YXMgdGhlIHBhY2thZ2UgYnVpbHQ/YCk7XG4gIH1cbiAgY29uc3QgdG1wRGlyID0gZnMubWtkdGVtcFN5bmMocGF0aC5qb2luKG9zLnRtcGRpcigpLCAndG9rZW4tcmVuZXctJykpO1xuICB0cnkge1xuICAgIGZzLmNvcHlGaWxlU3luYyhoYW5kbGVyU3JjLCBwYXRoLmpvaW4odG1wRGlyLCAnaW5kZXgubWpzJykpO1xuICAgIGNvbnN0IHppcFBhdGggPSBwYXRoLmpvaW4odG1wRGlyLCAnaW5kZXguemlwJyk7XG4gICAgZXhlY0ZpbGVTeW5jKCd6aXAnLCBbJy1qJywgemlwUGF0aCwgJ2luZGV4Lm1qcyddLCB7IGN3ZDogdG1wRGlyLCBzdGRpbzogJ3BpcGUnIH0pO1xuXG4gICAgY29uc3QgbGFtYmRhQ2xpZW50ID0gbmV3IExhbWJkYUNsaWVudCh7IHJlZ2lvbjogb3B0cy5yZWdpb24gfSk7XG4gICAgYXdhaXQgbGFtYmRhQ2xpZW50LnNlbmQobmV3IFVwZGF0ZUZ1bmN0aW9uQ29kZUNvbW1hbmQoe1xuICAgICAgRnVuY3Rpb25OYW1lOiBsYW1iZGFOYW1lLFxuICAgICAgWmlwRmlsZTogZnMucmVhZEZpbGVTeW5jKHppcFBhdGgpLFxuICAgIH0pKTtcbiAgfSBmaW5hbGx5IHtcbiAgICBmcy5ybVN5bmModG1wRGlyLCB7IHJlY3Vyc2l2ZTogdHJ1ZSwgZm9yY2U6IHRydWUgfSk7XG4gIH1cblxuICBwcmludFN1Y2Nlc3MoYFJvdGF0aW9uIHNjaGVkdWxlZCAoJHtzY2hlZHVsZUV4cHJlc3Npb259KWApO1xuICByZXR1cm4gc2NoZWR1bGVFeHByZXNzaW9uO1xufVxuXG4vKiogUmVhZCB0aGUga2V5IGlkIGEgcHJldmlvdXMgcnVuIHN0b3JlZCwgc28gdGhpcyBydW4gY2FuIHJldGlyZSBpdC4gKi9cbmFzeW5jIGZ1bmN0aW9uIHByZXZpb3VzS2V5SWQoXG4gIHNlY3JldE5hbWU6IHN0cmluZyxcbiAgYXdzOiB7IHJlZ2lvbjogc3RyaW5nOyBwcm9maWxlPzogc3RyaW5nIH0sXG4pOiBQcm9taXNlPHsga2V5SWQ/OiBzdHJpbmc7IHNlcnZpY2VBY2NvdW50SWQ/OiBzdHJpbmcgfT4ge1xuICB0cnkge1xuICAgIGNvbnN0IHJhdyA9IGF3YWl0IGdldFNlY3JldFZhbHVlKHNlY3JldE5hbWUsIGF3cyk7XG4gICAgY29uc3QgcGFyc2VkID0gSlNPTi5wYXJzZShyYXcpIGFzIHsga2V5SWQ/OiBzdHJpbmc7IHNlcnZpY2VBY2NvdW50SWQ/OiBzdHJpbmcgfTtcbiAgICByZXR1cm4geyBrZXlJZDogcGFyc2VkLmtleUlkLCBzZXJ2aWNlQWNjb3VudElkOiBwYXJzZWQuc2VydmljZUFjY291bnRJZCB9O1xuICB9IGNhdGNoIHtcbiAgICAvLyBObyBzZWNyZXQgeWV0IChmaXJzdCBydW4pLCBvciBvbmUgd3JpdHRlbiBiZWZvcmUgdGhlIHNlcnZpY2UtYWNjb3VudFxuICAgIC8vIGN1dG92ZXIgKG5vIGtleUlkKS4gRWl0aGVyIHdheSB0aGVyZSBpcyBub3RoaW5nIHRoaXMgcnVuIGNhbiByZXRpcmUuXG4gICAgcmV0dXJuIHt9O1xuICB9XG59XG5cbi8qKlxuICogUmVnaXN0ZXJzIHRoZSBgc3RvcmUtdG9rZW5gIGNvbW1hbmQgd2l0aCB0aGUgQ0xJIHByb2dyYW0uXG4gKlxuICogUHJvdmlzaW9ucyB0aGUgb3JnJ3MgbWFjaGluZSBpZGVudGl0eSDigJQgYSBTRVJWSUNFIEFDQ09VTlQgYW5kIG9uZSBgcGJfc2Ff4oCmYFxuICoga2V5IOKAlCBhbmQgc3RvcmVzIHRoZSBrZXkgaW4gQVdTIFNlY3JldHMgTWFuYWdlciBmb3IgQ0RLIGRlcGxveW1lbnRzLFxuICogQ29kZUJ1aWxkJ3MgcmVnaXN0cnkgY3JlZGVudGlhbHMsIHRoZSBwbHVnaW4tbG9va3VwIExhbWJkYSBhbmQgdGhlIGV2ZW50XG4gKiBpbmdlc3Rpb24gTGFtYmRhICgjMTIgLyAjTjIpLiBOb3RoaW5nIHN0b3JlZCBpcyB0aWVkIHRvIGEgcGVyc29uJ3Mgc2Vzc2lvbiBhbnlcbiAqIG1vcmU6IHRoZSBhY2NvdW50IG91dGxpdmVzIGl0cyBjcmVhdG9yLCB0YWtlcyBubyBzZWF0LCBhbmQgZXZlcnkgYXVkaXQgcm93IGl0XG4gKiBwcm9kdWNlcyBuYW1lcyB0aGUgYWNjb3VudC5cbiAqXG4gKiBCZWNhdXNlIGNyZWF0aW5nIGFuIGFjY291bnQgYW5kIGlzc3VpbmcgaXRzIGtleSBhcmUgc3RlcC11cCBnYXRlZCwgdGhpcyBuZWVkc1xuICogdGhlIG9wZXJhdG9yJ3MgcGFzc3dvcmQg4oCUIGAtLXBhc3N3b3JkYCwgb3IgdGhlIGBQTEFURk9STV9QQVNTV09SRGAgZW52IHZhclxuICogKHByZWZlcnJlZDogaXQga2VlcHMgdGhlIHBhc3N3b3JkIG91dCBvZiBzaGVsbCBoaXN0b3J5IGFuZCBwbGFuIG91dHB1dCkuXG4gKlxuICogQnkgZGVmYXVsdCBpdCBPTkxZIHdyaXRlcyB0aGUgc2VjcmV0LiBQYXNzIC0tc2NoZWR1bGUgdG8gYWxzbyBkZXBsb3kgdGhlIGRhaWx5XG4gKiBLRVkgUk9UQVRJT04gc3RhY2sgKGEgTGFtYmRhIHRoYXQgcmVwbGFjZXMgdGhlIGtleSBiZWZvcmUgaXQgZXhwaXJlcykuXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYGJhc2hcbiAqIFBMQVRGT1JNX1BBU1NXT1JEPSoqKiBwaXBlbGluZS1tYW5hZ2VyIGluZnJhIHN0b3JlLXRva2VuIC0tcmVnaW9uIHVzLWVhc3QtMVxuICogUExBVEZPUk1fUEFTU1dPUkQ9KioqIHBpcGVsaW5lLW1hbmFnZXIgaW5mcmEgc3RvcmUtdG9rZW4gLS1kYXlzIDkwIC0tcmVnaW9uIHVzLWVhc3QtMVxuICogUExBVEZPUk1fUEFTU1dPUkQ9KioqIHBpcGVsaW5lLW1hbmFnZXIgaW5mcmEgc3RvcmUtdG9rZW4gLS1zY2hlZHVsZSAtLXJlZ2lvbiB1cy1lYXN0LTEgICAgICMgKyBkYWlseSByb3RhdGlvblxuICogUExBVEZPUk1fUEFTU1dPUkQ9KioqIHBpcGVsaW5lLW1hbmFnZXIgaW5mcmEgc3RvcmUtdG9rZW4gLS1zY29wZSByZXBvcnRpbmc6aW5nZXN0IC0tc2NoZWR1bGVcbiAqIFBMQVRGT1JNX1BBU1NXT1JEPSoqKiBwaXBlbGluZS1tYW5hZ2VyIGluZnJhIHN0b3JlLXRva2VuIC0tc2NvcGUgcmVnaXN0cnk6cHVzaCAtLXNjaGVkdWxlXG4gKiBwaXBlbGluZS1tYW5hZ2VyIGluZnJhIHN0b3JlLXRva2VuIC0tZHJ5LXJ1blxuICogcGlwZWxpbmUtbWFuYWdlciBpbmZyYSBzdG9yZS10b2tlbiAtdSBhZG1pbiAtcCAnKioqJyAtLXJlZ2lvbiB1cy1lYXN0LTFcbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gc3RvcmVUb2tlbihwcm9ncmFtOiBDb21tYW5kKTogdm9pZCB7XG4gIHdpdGhTc2xPcHRpb25zKFxuICAgIHdpdGhQcm9maWxlT3B0aW9uKFxuICAgICAgd2l0aFJlZ2lvbk9wdGlvbihwcm9ncmFtXG4gICAgICAgIC5jb21tYW5kKCdzdG9yZS10b2tlbicpXG4gICAgICAgIC5kZXNjcmlwdGlvbignUHJvdmlzaW9uIGFuIG9yZyBzZXJ2aWNlLWFjY291bnQga2V5IChpdHMgb3duIG1hY2hpbmUgaWRlbnRpdHkpIGFuZCBzdG9yZSBpdCBpbiBBV1MgU2VjcmV0cyBNYW5hZ2VyIGZvciBDREsgZGVwbG95bWVudHMnKVxuICAgICAgICAub3B0aW9uKCctdSwgLS1pZGVudGlmaWVyIDxpZGVudGlmaWVyPicsICdVc2VybmFtZSBvciBlbWFpbCAoc2tpcHMgUExBVEZPUk1fVE9LRU4gcmVxdWlyZW1lbnQpJylcbiAgICAgICAgLm9wdGlvbignLXAsIC0tcGFzc3dvcmQgPHBhc3N3b3JkPicsICdMb2dpbiBwYXNzd29yZCDigJQgYWxzbyB1c2VkIGZvciB0aGUgc3RlcC11cCBldmVyeSBrZXkgd3JpdGUgcmVxdWlyZXMgKHByZWZlciBQTEFURk9STV9QQVNTV09SRCknKVxuICAgICAgICAub3B0aW9uKCctLWRheXMgPGRheXM+JywgJ0tleSBsaWZldGltZSBpbiBkYXlzIChtYXggMzY1KScsICczMCcpXG4gICAgICAgIC5vcHRpb24oJy0tc2NvcGUgPHNjb3BlPicsIGBQcm92aXNpb24gYSBsZWFzdC1wcml2aWxlZ2Ugc2NvcGVkIGtleSBpbnN0ZWFkIG9mIHRoZSBmdWxsLXByaXZpbGVnZSBwbGF0Zm9ybSBvbmUuIE9uZSBvZjogJHtPYmplY3Qua2V5cyhTQ09QRV9DQVRBTE9HKS5qb2luKCcsICcpfWApXG4gICAgICAgIC5vcHRpb24oJy0tYWNjb3VudCA8bmFtZT4nLCAnT3ZlcnJpZGUgdGhlIHNlcnZpY2UtYWNjb3VudCBuYW1lIHRoaXMga2V5IGlzIGlzc3VlZCBvbiAoZGVmYXVsdDogZGVyaXZlZCBmcm9tIC0tc2NvcGUpJylcbiAgICAgICAgLm9wdGlvbignLS1kcnktcnVuJywgJ1Nob3cgd2hhdCB3b3VsZCBiZSBwcm92aXNpb25lZCB3aXRob3V0IGNhbGxpbmcgdGhlIHBsYXRmb3JtIG9yIHdyaXRpbmcgdG8gU2VjcmV0cyBNYW5hZ2VyJywgZmFsc2UpKSxcbiAgICApXG4gICAgICAub3B0aW9uKCctLXNjaGVkdWxlJywgJ0Fsc28gZGVwbG95IHRoZSBkYWlseSBrZXktcm90YXRpb24gc3RhY2sgdGhhdCByZXBsYWNlcyB0aGlzIGtleSBiZWZvcmUgaXQgZXhwaXJlcyAob2ZmIGJ5IGRlZmF1bHQpJywgZmFsc2UpXG4gICAgICAub3B0aW9uKCctLWNyb24gPGV4cHI+JywgJ1JvdGF0aW9uIHNjaGVkdWxlIGFzIGEgNS1maWVsZCBjcm9uLCB1c2VkIHdpdGggLS1zY2hlZHVsZSAoZGVmYXVsdDogVE9LRU5fUkVORVdfU0NIRURVTEUgZW52IG9yIFwiMCAwICogKiAqXCI7IG1pbiBldmVyeSAxNSBtaW51dGVzKScpXG4gICAgICAub3B0aW9uKCctLWpzb24nLCAnT3V0cHV0IHJlc3VsdCBhcyBKU09OJywgZmFsc2UpLFxuICApXG4gICAgLmFjdGlvbihhc3luYyAob3B0aW9ucykgPT4ge1xuICAgICAgY29uc3QgZXhlY3V0aW9uSWQgPSBwcmludENvbW1hbmRIZWFkZXIoJ1N0b3JlIFRva2VuJywgdW5kZWZpbmVkLCB7IHF1aWV0OiBvcHRpb25zLmpzb24gfSk7XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIHByaW50U3NsV2FybmluZyhvcHRpb25zLnZlcmlmeVNzbCk7XG5cbiAgICAgICAgY29uc3QgcmVnaW9uID0gcmVzb2x2ZUF3c1JlZ2lvbihvcHRpb25zLnJlZ2lvbik7XG4gICAgICAgIGNvbnN0IGF3cyA9IHsgcmVnaW9uLCBwcm9maWxlOiBvcHRpb25zLnByb2ZpbGUgYXMgc3RyaW5nIHwgdW5kZWZpbmVkIH07XG5cbiAgICAgICAgY29uc3QgZGF5cyA9IHZhbGlkYXRlTnVtYmVyKG9wdGlvbnMuZGF5cywgJ2RheXMnLCAxLCAzNjUpO1xuICAgICAgICBjb25zdCBleHBpcmVzSW5TZWNvbmRzID0gZGF5cyAqIDI0ICogNjAgKiA2MDtcblxuICAgICAgICBjb25zdCBzY29wZSA9IG9wdGlvbnMuc2NvcGUgYXMgc3RyaW5nIHwgdW5kZWZpbmVkO1xuICAgICAgICBjb25zdCBjYXRhbG9ndWVkID0gc2NvcGUgPyBTQ09QRV9DQVRBTE9HW3Njb3BlXSA6IHVuZGVmaW5lZDtcbiAgICAgICAgaWYgKHNjb3BlICYmICFjYXRhbG9ndWVkKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbmtub3duIC0tc2NvcGUgXCIke3Njb3BlfVwiLiBTdXBwb3J0ZWQ6ICR7T2JqZWN0LmtleXMoU0NPUEVfQ0FUQUxPRykuam9pbignLCAnKX1gKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBXaGljaCBtYWNoaW5lIGlkZW50aXR5IHRoaXMgY3JlZGVudGlhbCBiZWxvbmdzIHRvOiB0aGUgc2NvcGUncyBvd25cbiAgICAgICAgLy8gYWNjb3VudCwgb3IgdGhlIG9yZydzIHNpbmdsZSBmdWxsLXByaXZpbGVnZSBhdXRvbWF0aW9uIGFjY291bnQuXG4gICAgICAgIGNvbnN0IGlkZW50aXR5ID0gY2F0YWxvZ3VlZCA/PyBQTEFURk9STV9BQ0NPVU5UO1xuICAgICAgICBjb25zdCBhY2NvdW50TmFtZSA9IChvcHRpb25zLmFjY291bnQgYXMgc3RyaW5nIHwgdW5kZWZpbmVkKSA/PyBpZGVudGl0eS5hY2NvdW50O1xuXG4gICAgICAgIC8vIFN0ZXAgMDogbG9nIGluIGZpcnN0IHdoZW4gY3JlZHMgYXJlIGF2YWlsYWJsZSBhbmQgbm8gUExBVEZPUk1fVE9LRU4gaXNcbiAgICAgICAgLy8gc2V0IChzaGFyZWQgd2l0aCBzZXR1cC1ldmVudHMpLiBDcmVkcyBjb21lIGZyb20gLS1pZGVudGlmaWVyLy0tcGFzc3dvcmRcbiAgICAgICAgLy8gT1IgdGhlIGVudiB2YXJzIFBMQVRGT1JNX0lERU5USUZJRVIvUExBVEZPUk1fUEFTU1dPUkQg4oCUIHRoZSBlbnYgcGF0aFxuICAgICAgICAvLyBsZXRzIGNhbGxlcnMgbGlrZSBgcHJvdmlzaW9uIC0td2l0aC1ldmVudHNgIHBhc3MgdGhlbSB3aXRob3V0IHB1dHRpbmdcbiAgICAgICAgLy8gdGhlIHBhc3N3b3JkIG9uIHRoZSBjb21tYW5kIGxpbmUgKHdoZXJlIGl0IHdvdWxkIHNob3cgaW4gcGxhbnMvbG9ncykuXG4gICAgICAgIGF3YWl0IGVuc3VyZVBsYXRmb3JtVG9rZW4ob3B0aW9ucyk7XG5cbiAgICAgICAgLy8gVGhlIHBhc3N3b3JkIGlzIEFMU08gdGhlIHN0ZXAtdXAgZmFjdG9yIGZvciBib3RoIHdyaXRlcyBiZWxvdywgc28gaXQgaXNcbiAgICAgICAgLy8gcmVxdWlyZWQgZXZlbiB3aGVuIFBMQVRGT1JNX1RPS0VOIGlzIGFscmVhZHkgc2V0LiBTYXkgdGhhdCBwbGFpbmx5XG4gICAgICAgIC8vIHJhdGhlciB0aGFuIGZhaWxpbmcgdGhyZWUgY2FsbHMgbGF0ZXIgd2l0aCBhIDQwMy5cbiAgICAgICAgY29uc3QgcGFzc3dvcmQgPSAob3B0aW9ucy5wYXNzd29yZCBhcyBzdHJpbmcgfCB1bmRlZmluZWQpIHx8IHByb2Nlc3MuZW52LlBMQVRGT1JNX1BBU1NXT1JEO1xuICAgICAgICBpZiAoIXBhc3N3b3JkICYmICFvcHRpb25zLmRyeVJ1bikge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgICdBIHBhc3N3b3JkIGlzIHJlcXVpcmVkOiBjcmVhdGluZyBhIHNlcnZpY2UgYWNjb3VudCBhbmQgaXNzdWluZyBpdHMga2V5IGFyZSBib3RoIHN0ZXAtdXAgZ2F0ZWQuICdcbiAgICAgICAgICAgICsgJ1NldCBQTEFURk9STV9QQVNTV09SRCAocHJlZmVycmVkKSBvciBwYXNzIC0tcGFzc3dvcmQuJyxcbiAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgcHJpbnRTZWN0aW9uKCdQcm92aXNpb24gU2VydmljZS1BY2NvdW50IEtleScpO1xuXG4gICAgICAgIGNvbnN0IGNsaWVudCA9IGF3YWl0IGNyZWF0ZUF1dGhlbnRpY2F0ZWRDbGllbnRBc3luYyhvcHRpb25zKTtcblxuICAgICAgICBpZiAob3B0aW9ucy5kcnlSdW4pIHtcbiAgICAgICAgICAvLyBEcnkgcnVuIHN0YXlzIGVudGlyZWx5IE9GRkxJTkUg4oCUIGl0IG11c3Qgbm90IGNyZWF0ZSBhbiBhY2NvdW50IG9yXG4gICAgICAgICAgLy8gYnVybiBhIGtleSBqdXN0IHRvIHNob3cgd2hhdCBpdCB3b3VsZCBkby5cbiAgICAgICAgICBjb25zdCBwbGFuID0ge1xuICAgICAgICAgICAgc2VydmljZUFjY291bnQ6IGFjY291bnROYW1lLFxuICAgICAgICAgICAgcm9sZXM6IHNjb3BlID8gJ25vbmUgKHNjb3BlZCwgbGVhc3QgcHJpdmlsZWdlKScgOiAnb3JnIGFkbWluJyxcbiAgICAgICAgICAgIHNjb3BlOiBzY29wZSA/PyAnKG5vbmUg4oCUIGZ1bGwgcGxhdGZvcm0gY3JlZGVudGlhbCknLFxuICAgICAgICAgICAgc2VjcmV0TmFtZTogcHJvY2Vzcy5lbnYuUExBVEZPUk1fU0VDUkVUX05BTUUgfHwgYCR7c2VjcmV0TmFtZUZvck9yZygnPG9yZ0lkPicsIHNjb3BlID8gc2NvcGVTZWNyZXRMZWFmKHNjb3BlKSA6ICdwbGF0Zm9ybScpfWAsXG4gICAgICAgICAgICByZWdpb24sXG4gICAgICAgICAgICBleHBpcmVzSW5EYXlzOiBkYXlzLFxuICAgICAgICAgIH07XG4gICAgICAgICAgaWYgKG9wdGlvbnMuanNvbikge1xuICAgICAgICAgICAgY29uc29sZS5sb2coSlNPTi5zdHJpbmdpZnkoeyBzdWNjZXNzOiB0cnVlLCBkcnlSdW46IHRydWUsIC4uLnBsYW4gfSwgbnVsbCwgMikpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zb2xlLmxvZygnJyk7XG4gICAgICAgICAgICBwcmludFNlY3Rpb24oJ0RyeSBSdW4g4oCUIE5vIENoYW5nZXMgTWFkZScpO1xuICAgICAgICAgICAgcHJpbnRLZXlWYWx1ZSh7XG4gICAgICAgICAgICAgICdTZXJ2aWNlIEFjY291bnQnOiBwbGFuLnNlcnZpY2VBY2NvdW50LFxuICAgICAgICAgICAgICAnUm9sZXMnOiBwbGFuLnJvbGVzLFxuICAgICAgICAgICAgICAnS2V5IFNjb3BlJzogcGxhbi5zY29wZSxcbiAgICAgICAgICAgICAgJ1NlY3JldCBOYW1lJzogcGxhbi5zZWNyZXROYW1lLFxuICAgICAgICAgICAgICAnUmVnaW9uJzogcGxhbi5yZWdpb24sXG4gICAgICAgICAgICAgICdFeHBpcmVzIEluJzogYCR7ZGF5c30gZGF5c2AsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHByaW50U3VjY2VzcygnRHJ5IHJ1biBjb21wbGV0ZSDigJQgbm8gYWNjb3VudCwga2V5IG9yIHNlY3JldCB3YXMgY3JlYXRlZCcpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBrZXlOYW1lID0gYCR7YWNjb3VudE5hbWV9LSR7bmV3IERhdGUoKS50b0lTT1N0cmluZygpLnNsaWNlKDAsIDEwKX1gO1xuICAgICAgICBjb25zdCBwcm92aXNpb25lZCA9IGF3YWl0IHByb3Zpc2lvblNlcnZpY2VBY2NvdW50S2V5KHtcbiAgICAgICAgICBjbGllbnQsXG4gICAgICAgICAgcGFzc3dvcmQ6IHBhc3N3b3JkISxcbiAgICAgICAgICBhY2NvdW50TmFtZSxcbiAgICAgICAgICBkZXNjcmlwdGlvbjogaWRlbnRpdHkuZGVzY3JpcHRpb24sXG4gICAgICAgICAgcm9sZXM6IHNjb3BlID8gJ25vbmUnIDogJ2FkbWluJyxcbiAgICAgICAgICAuLi4oc2NvcGUgPyB7IHNjb3BlIH0gOiB7fSksXG4gICAgICAgICAgZXhwaXJlc0luU2Vjb25kcyxcbiAgICAgICAgICBrZXlOYW1lLFxuICAgICAgICB9KTtcblxuICAgICAgICBwcmludFN1Y2Nlc3MoYEtleSBpc3N1ZWQgb24gc2VydmljZSBhY2NvdW50ICcke2FjY291bnROYW1lfScgKGV4cGlyZXMgJHtwcm92aXNpb25lZC5leHBpcmVzQXR9KWApO1xuXG4gICAgICAgIC8vIEFuIGV4cGxpY2l0IFBMQVRGT1JNX1NFQ1JFVF9OQU1FIHN0aWxsIHdpbnMgKHRoZSBlc2NhcGUgaGF0Y2ggZm9yXG4gICAgICAgIC8vIGhhbmQtbWFuYWdlZCBwYXRocyk7IG90aGVyd2lzZSBkZXJpdmUgaXQgZnJvbSB0aGUgb3JnIHRoZSBwbGF0Zm9ybVxuICAgICAgICAvLyByZXBvcnRlZCwgd2hpY2ggd29ya3Mgd2l0aCBhbiBvcGFxdWUgYWNjZXNzIGtleSBhcyBQTEFURk9STV9UT0tFTiDigJRcbiAgICAgICAgLy8gYSBrZXkgY2FycmllcyBubyBvcmcgY2xhaW0gdG8gZGVjb2RlLlxuICAgICAgICBjb25zdCBzZWNyZXROYW1lID0gcHJvY2Vzcy5lbnYuUExBVEZPUk1fU0VDUkVUX05BTUVcbiAgICAgICAgICB8fCBzZWNyZXROYW1lRm9yT3JnKHByb3Zpc2lvbmVkLm9yZ2FuaXphdGlvbklkLCBzY29wZSA/IHNjb3BlU2VjcmV0TGVhZihzY29wZSkgOiAncGxhdGZvcm0nKTtcblxuICAgICAgICBhdWRpdExvZygnc3RvcmUtdG9rZW4nLCB7XG4gICAgICAgICAgZXhlY3V0aW9uSWQsXG4gICAgICAgICAgc2VjcmV0TmFtZSxcbiAgICAgICAgICBkYXlzLFxuICAgICAgICAgIHNlcnZpY2VBY2NvdW50OiBhY2NvdW50TmFtZSxcbiAgICAgICAgICBzY29wZTogc2NvcGUgPz8gbnVsbCxcbiAgICAgICAgICBrZXlJZDogcHJvdmlzaW9uZWQua2V5SWQsXG4gICAgICAgIH0pO1xuXG4gICAgICAgIHByaW50SW5mbygnUGFyYW1ldGVycycsIHtcbiAgICAgICAgICBzZWNyZXROYW1lLFxuICAgICAgICAgIHJlZ2lvbixcbiAgICAgICAgICBzZXJ2aWNlQWNjb3VudDogYWNjb3VudE5hbWUsXG4gICAgICAgICAgc2NvcGU6IHNjb3BlID8/ICcobm9uZSknLFxuICAgICAgICAgIGRheXMsXG4gICAgICAgICAgZXhwaXJlc0luOiBgJHtleHBpcmVzSW5TZWNvbmRzfXNgLFxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBXaGF0IHRoaXMgcnVuIGlzIFJFUExBQ0lORywgcmVhZCBiZWZvcmUgdGhlIHdyaXRlIHNvIHRoZSBvbGQga2V5IGNhbiBiZVxuICAgICAgICAvLyByZXRpcmVkIGFmdGVyIHRoZSBuZXcgb25lIGlzIHNhZmVseSBzdG9yZWQuXG4gICAgICAgIGNvbnN0IHByZXZpb3VzID0gYXdhaXQgcHJldmlvdXNLZXlJZChzZWNyZXROYW1lLCBhd3MpO1xuXG4gICAgICAgIC8vIFNjaGVtYTogeyB1c2VybmFtZTogb3JnSWQsIHBhc3N3b3JkOiA8cGJfc2FfIGtleT4sIC4uLm1ldGFkYXRhIH1cbiAgICAgICAgLy8gLSB1c2VybmFtZS9wYXNzd29yZCBzYXRpc2Z5IENvZGVCdWlsZCdzIGBzZWNyZXRzTWFuYWdlckNyZWRlbnRpYWxzYFxuICAgICAgICAvLyAgIChIVFRQIEJhc2ljLCBzZW50IHRvIHBpcGVsaW5lLWltYWdlLXJlZ2lzdHJ5J3MgL3Rva2VuIGVuZHBvaW50LCB3aGljaFxuICAgICAgICAvLyAgIGV4Y2hhbmdlcyB0aGUgb3BhcXVlIGtleSBsaWtlIGV2ZXJ5IG90aGVyIHNlcnZpY2UgZG9lcylcbiAgICAgICAgLy8gLSBgcGFzc3dvcmRgIHN0YXlzIHRoZSBjYW5vbmljYWwgZmllbGQ6IHRoZSBwbHVnaW4tbG9va3VwIExhbWJkYSwgdGhlXG4gICAgICAgIC8vICAgZXZlbnRzIExhbWJkYSBhbmQgYC0tc3RvcmUtdG9rZW5zYCBhbGwgcmVhZCBpdC4gT25seSBpdHMgVkFMVUUgY2hhbmdlZCxcbiAgICAgICAgLy8gICBmcm9tIGEgbWFjaGluZS1zZXNzaW9uIEpXVCB0byBhbiBvcGFxdWUgc2VydmljZS1hY2NvdW50IGtleS5cbiAgICAgICAgLy8gLSBrZXlJZCAvIHNlcnZpY2VBY2NvdW50SWQgYXJlIHdoYXQgdGhlIHJvdGF0aW9uIExhbWJkYSBuZWVkcyB0byByZXRpcmVcbiAgICAgICAgLy8gICB0aGUga2V5IGl0IHJlcGxhY2VzLlxuICAgICAgICBjb25zdCBzZWNyZXRWYWx1ZSA9IEpTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgICB1c2VybmFtZTogcHJvdmlzaW9uZWQub3JnYW5pemF0aW9uSWQsXG4gICAgICAgICAgcGFzc3dvcmQ6IHByb3Zpc2lvbmVkLmtleSxcbiAgICAgICAgICBwbGF0Zm9ybVVybDogY2xpZW50LmdldEJhc2VVcmwoKSxcbiAgICAgICAgICBvcmdhbml6YXRpb25JZDogcHJvdmlzaW9uZWQub3JnYW5pemF0aW9uSWQsXG4gICAgICAgICAgc2VydmljZUFjY291bnRJZDogcHJvdmlzaW9uZWQuc2VydmljZUFjY291bnRJZCxcbiAgICAgICAgICBzZXJ2aWNlQWNjb3VudE5hbWU6IHByb3Zpc2lvbmVkLnNlcnZpY2VBY2NvdW50TmFtZSxcbiAgICAgICAgICBrZXlJZDogcHJvdmlzaW9uZWQua2V5SWQsXG4gICAgICAgICAgc2NvcGU6IHByb3Zpc2lvbmVkLnNjb3BlLFxuICAgICAgICAgIGV4cGlyZXNJbjogZXhwaXJlc0luU2Vjb25kcyxcbiAgICAgICAgICBleHBpcmVzQXQ6IHByb3Zpc2lvbmVkLmV4cGlyZXNBdCxcbiAgICAgICAgICBjcmVhdGVkQXQ6IG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKSxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgcHJpbnRTZWN0aW9uKCdTdG9yZSBLZXknKTtcblxuICAgICAgICBjb25zdCBkZXNjcmlwdGlvbiA9IGBQaXBlbGluZSBCdWlsZGVyIHNlcnZpY2UtYWNjb3VudCBrZXkgKCR7YWNjb3VudE5hbWV9OyByZW5ldyBieSAke3Byb3Zpc2lvbmVkLmV4cGlyZXNBdH0pYDtcbiAgICAgICAgYXdhaXQgdXBzZXJ0U2VjcmV0KHNlY3JldE5hbWUsIHNlY3JldFZhbHVlLCBkZXNjcmlwdGlvbiwgYXdzKTtcblxuICAgICAgICBjb25zdCBhcm4gPSBhd2FpdCBnZXRTZWNyZXRBcm4oc2VjcmV0TmFtZSwgYXdzKTtcblxuICAgICAgICAvLyBSZXRpcmUgdGhlIGNyZWRlbnRpYWwgdGhpcyBydW4gcmVwbGFjZWQg4oCUIEFGVEVSIHRoZSBuZXcgb25lIGlzIHN0b3JlZCxcbiAgICAgICAgLy8gbmV2ZXIgYmVmb3JlLiBBIGZhaWx1cmUgaGVyZSBsZWF2ZXMgYSBzdXBlcmZsdW91cyBrZXkgdGhhdCBleHBpcmVzIG9uXG4gICAgICAgIC8vIGl0cyBvd247IGRvaW5nIGl0IGluIHRoZSBvdGhlciBvcmRlciB3b3VsZCBsZWF2ZSB0aGUgc2VjcmV0IG5hbWluZyBhXG4gICAgICAgIC8vIHJldm9rZWQga2V5IGlmIHRoZSB3cml0ZSBmYWlsZWQuXG4gICAgICAgIGlmIChwcmV2aW91cy5rZXlJZCAmJiBwcmV2aW91cy5zZXJ2aWNlQWNjb3VudElkID09PSBwcm92aXNpb25lZC5zZXJ2aWNlQWNjb3VudElkKSB7XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGF3YWl0IHJldm9rZVNlcnZpY2VBY2NvdW50S2V5KFxuICAgICAgICAgICAgICBjbGllbnQsIHBhc3N3b3JkISwgcHJvdmlzaW9uZWQub3JnYW5pemF0aW9uSWQsIHByb3Zpc2lvbmVkLnNlcnZpY2VBY2NvdW50SWQsIHByZXZpb3VzLmtleUlkLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIHByaW50U3VjY2VzcyhgUmV0aXJlZCB0aGUgcHJldmlvdXMga2V5ICgke3ByZXZpb3VzLmtleUlkfSlgKTtcbiAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgIHByaW50V2FybmluZyhcbiAgICAgICAgICAgICAgYFN0b3JlZCB0aGUgbmV3IGtleSwgYnV0IGNvdWxkIG5vdCByZXZva2UgdGhlIHByZXZpb3VzIG9uZSAoJHtwcmV2aW91cy5rZXlJZH0pOiBgXG4gICAgICAgICAgICAgICsgYCR7ZXJyIGluc3RhbmNlb2YgRXJyb3IgPyBlcnIubWVzc2FnZSA6IFN0cmluZyhlcnIpfS4gSXQgZXhwaXJlcyBvbiBpdHMgb3duOyByZXZva2UgaXQgZnJvbSBgXG4gICAgICAgICAgICAgICsgJ1NldHRpbmdzIOKGkiBTZXJ2aWNlIGFjY291bnRzIGlmIHlvdSB3YW50IGl0IGdvbmUgbm93LicsXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIE9wdGlvbmFsbHkgaW5zdGFsbCB0aGUgb25jZS1hLWRheSByb3RhdGlvbiBzdGFjayBzbyB0aGlzIGtleSBuZXZlciBsYXBzZXMuXG4gICAgICAgIGxldCBzY2hlZHVsZUV4cHJlc3Npb246IHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgICAgICAgaWYgKG9wdGlvbnMuc2NoZWR1bGUpIHtcbiAgICAgICAgICBjb25zdCBmaXZlRmllbGRDcm9uID0gb3B0aW9ucy5jcm9uIHx8IHByb2Nlc3MuZW52LlRPS0VOX1JFTkVXX1NDSEVEVUxFIHx8IERFRkFVTFRfUkVORVdfQ1JPTjtcbiAgICAgICAgICBzY2hlZHVsZUV4cHJlc3Npb24gPSBhd2FpdCBkZXBsb3lSZW5ld1NjaGVkdWxlKHtcbiAgICAgICAgICAgIHBsYXRmb3JtVXJsOiBjbGllbnQuZ2V0QmFzZVVybCgpLFxuICAgICAgICAgICAgc2VjcmV0TmFtZSxcbiAgICAgICAgICAgIGRheXMsXG4gICAgICAgICAgICBmaXZlRmllbGRDcm9uLFxuICAgICAgICAgICAgcmVnaW9uLFxuICAgICAgICAgICAgcHJvZmlsZTogb3B0aW9ucy5wcm9maWxlLFxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKG9wdGlvbnMuanNvbikge1xuICAgICAgICAgIGNvbnNvbGUubG9nKEpTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgICAgIHN1Y2Nlc3M6IHRydWUsXG4gICAgICAgICAgICBzZWNyZXROYW1lLFxuICAgICAgICAgICAgc2VjcmV0QXJuOiBhcm4sXG4gICAgICAgICAgICByZWdpb24sXG4gICAgICAgICAgICBzZXJ2aWNlQWNjb3VudDogYWNjb3VudE5hbWUsXG4gICAgICAgICAgICBzZXJ2aWNlQWNjb3VudElkOiBwcm92aXNpb25lZC5zZXJ2aWNlQWNjb3VudElkLFxuICAgICAgICAgICAga2V5SWQ6IHByb3Zpc2lvbmVkLmtleUlkLFxuICAgICAgICAgICAgc2NvcGU6IHByb3Zpc2lvbmVkLnNjb3BlLFxuICAgICAgICAgICAgZXhwaXJlc0luRGF5czogZGF5cyxcbiAgICAgICAgICAgIGV4cGlyZXNBdDogcHJvdmlzaW9uZWQuZXhwaXJlc0F0LFxuICAgICAgICAgICAgc2NoZWR1bGU6IHNjaGVkdWxlRXhwcmVzc2lvbiA/PyBudWxsLFxuICAgICAgICAgIH0sIG51bGwsIDIpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjb25zb2xlLmxvZygnJyk7XG4gICAgICAgICAgcHJpbnRTZWN0aW9uKCdLZXkgU3RvcmVkJyk7XG5cbiAgICAgICAgICBwcmludEtleVZhbHVlKHtcbiAgICAgICAgICAgICdTZWNyZXQgTmFtZSc6IHNlY3JldE5hbWUsXG4gICAgICAgICAgICAnU2VjcmV0IEFSTic6IGFybixcbiAgICAgICAgICAgICdSZWdpb24nOiByZWdpb24sXG4gICAgICAgICAgICAnU2VydmljZSBBY2NvdW50JzogYWNjb3VudE5hbWUsXG4gICAgICAgICAgICAnS2V5IFNjb3BlJzogcHJvdmlzaW9uZWQuc2NvcGUgPz8gJyhub25lIOKAlCBmdWxsIHBsYXRmb3JtIGNyZWRlbnRpYWwpJyxcbiAgICAgICAgICAgICdLZXkgSWQnOiBwcm92aXNpb25lZC5rZXlJZCxcbiAgICAgICAgICAgICdFeHBpcmVzIEluJzogYCR7ZGF5c30gZGF5c2AsXG4gICAgICAgICAgICAnUmVuZXcgQnknOiBwcm92aXNpb25lZC5leHBpcmVzQXQsXG4gICAgICAgICAgICAnQXV0by1Sb3RhdGUnOiBzY2hlZHVsZUV4cHJlc3Npb24gPyBg4pyTICR7c2NoZWR1bGVFeHByZXNzaW9ufWAgOiAnb2ZmIChwYXNzIC0tc2NoZWR1bGUgdG8gZW5hYmxlKScsXG4gICAgICAgICAgICAnU3RhdHVzJzogJ+KckyBTdG9yZWQnLFxuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgY29uc29sZS5sb2coJycpO1xuICAgICAgICAgIHByaW50U3VjY2VzcygnS2V5IHN0b3JlZC4gVG8gdXNlIHdpdGggc3ludGgvZGVwbG95OicpO1xuICAgICAgICAgIHByaW50SW5mbyhgICBleHBvcnQgUExBVEZPUk1fU0VDUkVUX05BTUU9JHtzZWNyZXROYW1lfWApO1xuICAgICAgICAgIHByaW50SW5mbygnICBwaXBlbGluZS1tYW5hZ2VyIHBpcGVsaW5lIHN5bnRoIC0taWQgPHBpcGVsaW5lLWlkPiAtLXN0b3JlLXRva2VucycpO1xuICAgICAgICAgIGNvbnNvbGUubG9nKCcnKTtcbiAgICAgICAgICBpZiAoc2NoZWR1bGVFeHByZXNzaW9uKSB7XG4gICAgICAgICAgICBwcmludEluZm8oYEF1dG8tcm90YXRpb24gaXMgYWN0aXZlICgke3NjaGVkdWxlRXhwcmVzc2lvbn0pOyB0aGUgc2VjcmV0IGlzIHJlcGxhY2VkIGJlZm9yZSAke3Byb3Zpc2lvbmVkLmV4cGlyZXNBdH0uYCk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHByaW50SW5mbyhgUm90YXRlIGJlZm9yZSAke3Byb3Zpc2lvbmVkLmV4cGlyZXNBdH0gd2l0aDogcGlwZWxpbmUtbWFuYWdlciBpbmZyYSBzdG9yZS10b2tlbiAtLWRheXMgJHtkYXlzfWApO1xuICAgICAgICAgICAgcHJpbnRJbmZvKCcgIChvciBwYXNzIC0tc2NoZWR1bGUgdG8gaW5zdGFsbCBhIGRhaWx5IGF1dG8tcm90YXRpb24gc3RhY2spJyk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIGhhbmRsZUVycm9yKGVycm9yLCBFUlJPUl9DT0RFUy5BUElfUkVRVUVTVCwge1xuICAgICAgICAgIGRlYnVnOiBwcm9ncmFtLm9wdHMoKS5kZWJ1ZyxcbiAgICAgICAgICBleGl0OiB0cnVlLFxuICAgICAgICAgIGNvbnRleHQ6IHtcbiAgICAgICAgICAgIGNvbW1hbmQ6ICdzdG9yZS10b2tlbicsXG4gICAgICAgICAgICBleGVjdXRpb25JZCxcbiAgICAgICAgICAgIHNlY3JldE5hbWU6IHByb2Nlc3MuZW52LlBMQVRGT1JNX1NFQ1JFVF9OQU1FIHx8ICcoZGVyaXZlZCBmcm9tIHRoZSBvcmcpJyxcbiAgICAgICAgICB9LFxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9KTtcbn1cbiJdfQ==