@pipeline-builder/pipeline-manager 4.1.4 → 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.
- package/README.md +2 -1
- package/dist/agent/env-file.d.ts +1 -1
- package/dist/agent/env-file.js +2 -2
- package/dist/agent/post-steps.d.ts.map +1 -1
- package/dist/agent/post-steps.js +38 -18
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +19 -9
- package/dist/commands/audit-tokens.d.ts.map +1 -1
- package/dist/commands/audit-tokens.js +32 -21
- package/dist/commands/create-pat.d.ts +20 -13
- package/dist/commands/create-pat.d.ts.map +1 -1
- package/dist/commands/create-pat.js +93 -98
- package/dist/commands/login.d.ts +14 -8
- package/dist/commands/login.d.ts.map +1 -1
- package/dist/commands/login.js +89 -124
- package/dist/commands/setup-events.d.ts.map +1 -1
- package/dist/commands/setup-events.js +6 -5
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +9 -3
- package/dist/commands/store-token.d.ts +16 -11
- package/dist/commands/store-token.d.ts.map +1 -1
- package/dist/commands/store-token.js +213 -131
- package/dist/lambda/token-renew-handler.d.ts.map +1 -1
- package/dist/lambda/token-renew-handler.js +134 -97
- package/dist/templates/events-stack.json +1 -1
- package/dist/templates/token-renew-stack.json +9 -10
- package/dist/utils/auth-utils.d.ts +21 -38
- package/dist/utils/auth-utils.d.ts.map +1 -1
- package/dist/utils/auth-utils.js +20 -33
- package/dist/utils/command-utils.d.ts +8 -6
- package/dist/utils/command-utils.d.ts.map +1 -1
- package/dist/utils/command-utils.js +71 -15
- package/dist/utils/config-loader.d.ts +2 -1
- package/dist/utils/config-loader.d.ts.map +1 -1
- package/dist/utils/config-loader.js +18 -8
- package/dist/utils/credential-store.d.ts +23 -0
- package/dist/utils/credential-store.d.ts.map +1 -0
- package/dist/utils/credential-store.js +92 -0
- package/dist/utils/device-auth.d.ts +59 -0
- package/dist/utils/device-auth.d.ts.map +1 -0
- package/dist/utils/device-auth.js +139 -0
- package/dist/utils/pipeline-config.js +2 -2
- package/dist/utils/platform-secret.d.ts +19 -1
- package/dist/utils/platform-secret.d.ts.map +1 -1
- package/dist/utils/platform-secret.js +26 -4
- package/dist/utils/service-account.d.ts +73 -0
- package/dist/utils/service-account.d.ts.map +1 -0
- package/dist/utils/service-account.js +158 -0
- package/package.json +4 -4
- package/dist/utils/rate-limiter.d.ts +0 -15
- package/dist/utils/rate-limiter.d.ts.map +0 -1
- 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,
|
|
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
|
-
*
|
|
29
|
-
*
|
|
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
|
|
32
|
-
*
|
|
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-
|
|
38
|
-
// reporting-ingest
|
|
39
|
-
// platform-
|
|
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
|
|
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
|
-
//
|
|
67
|
-
//
|
|
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(`
|
|
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
|
-
*
|
|
103
|
-
* in AWS Secrets Manager for
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
|
115
|
-
* pipeline-manager infra store-token --
|
|
116
|
-
* pipeline-manager infra store-token --
|
|
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 -
|
|
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('
|
|
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
|
|
128
|
-
.option('--days <days>', '
|
|
129
|
-
.option('--scope <scope>',
|
|
130
|
-
.option('--
|
|
131
|
-
.option('--
|
|
132
|
-
.option('--
|
|
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
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
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
|
-
//
|
|
148
|
-
|
|
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
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
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
|
-
|
|
170
|
-
|
|
171
|
-
const
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
//
|
|
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:
|
|
197
|
-
|
|
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
|
-
|
|
203
|
-
|
|
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
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
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
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
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
|
-
//
|
|
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('
|
|
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-
|
|
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('
|
|
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-
|
|
366
|
+
printInfo(`Auto-rotation is active (${scheduleExpression}); the secret is replaced before ${provisioned.expiresAt}.`);
|
|
285
367
|
}
|
|
286
368
|
else {
|
|
287
|
-
printInfo(`
|
|
288
|
-
printInfo(' (or pass --schedule to install a daily auto-
|
|
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
|
|
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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RvcmUtdG9rZW4uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY29tbWFuZHMvc3RvcmUtdG9rZW4udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsK0NBQStDO0FBQy9DLHNDQUFzQztBQUV0QyxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzdDLE9BQU8sS0FBSyxFQUFFLE1BQU0sSUFBSSxDQUFDO0FBQ3pCLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFDekMsT0FBTyxLQUFLLEVBQUUsTUFBTSxJQUFJLENBQUM7QUFDekIsT0FBTyxJQUFJLE1BQU0sTUFBTSxDQUFDO0FBQ3hCLE9BQU8sRUFBRSxZQUFZLEVBQUUseUJBQXlCLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUNqRixPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQ3BDLE9BQU8sRUFBRSxXQUFXLEVBQUUsY0FBYyxFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFDekUsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQ2pELE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQzVELE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ3ZELE9BQU8sRUFBRSxZQUFZLEVBQUUsWUFBWSxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDckUsT0FBTyxFQUFFLDhCQUE4QixFQUFFLGtCQUFrQixFQUFFLGVBQWUsRUFBRSxpQkFBaUIsRUFBRSxnQkFBZ0IsRUFBRSxjQUFjLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUNySyxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUNyRCxPQUFPLEVBQUUsV0FBVyxFQUFFLFdBQVcsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQ3JFLE9BQU8sRUFBRSxTQUFTLEVBQUUsYUFBYSxF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QUM7UUFFSCxDQUFDO1FBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztZQUNmLFdBQVcsQ0FBQyxLQUFLLEVBQUUsV0FBVyxDQUFDLFdBQVcsRUFBRTtnQkFDMUMsS0FBSyxFQUFFLE9BQU8sQ0FBQyxJQUFJLEVBQUUsQ0FBQyxLQUFLO2dCQUMzQixJQUFJLEVBQUUsSUFBSTtnQkFDVixPQUFPLEVBQUU7b0JBQ1AsT0FBTyxFQUFFLGFBQWE7b0JBQ3RCLFdBQVc7b0JBQ1gsVUFBVSxFQUFFLE9BQU8sQ0FBQyxHQUFHLENBQUMsb0JBQW9CLElBQUksc0JBQXNCO2lCQUN2RTthQUNGLENBQUMsQ0FBQztRQUNMLENBQUM7SUFDSCxDQUFDLENBQUMsQ0FBQztBQUNQLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgMjAyNiBQaXBlbGluZSBCdWlsZGVyIENvbnRyaWJ1dG9yc1xuLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcblxuaW1wb3J0IHsgZXhlY0ZpbGVTeW5jIH0gZnJvbSAnY2hpbGRfcHJvY2Vzcyc7XG5pbXBvcnQgKiBhcyBmcyBmcm9tICdmcyc7XG5pbXBvcnQgeyBmaWxlVVJMVG9QYXRoIH0gZnJvbSAnbm9kZTp1cmwnO1xuaW1wb3J0ICogYXMgb3MgZnJvbSAnb3MnO1xuaW1wb3J0IHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQgeyBMYW1iZGFDbGllbnQsIFVwZGF0ZUZ1bmN0aW9uQ29kZUNvbW1hbmQgfSBmcm9tICdAYXdzLXNkay9jbGllbnQtbGFtYmRhJztcbmltcG9ydCB7IENvbW1hbmQgfSBmcm9tICdjb21tYW5kZXInO1xuaW1wb3J0IHsgQVBQX1ZFUlNJT04sIHZhbGlkYXRlTnVtYmVyIH0gZnJvbSAnLi4vY29uZmlnL2NsaS5jb25zdGFudHMuanMnO1xuaW1wb3J0IHsgYXVkaXRMb2cgfSBmcm9tICcuLi91dGlscy9hdWRpdC1sb2cuanMnO1xuaW1wb3J0IHsgZGVjb2RlVG9rZW5QYXlsb2FkIH0gZnJvbSAnLi4vdXRpbHMvYXV0aC1ndWFyZC5qcyc7XG5pbXBvcnQgeyByZXNvbHZlQXdzUmVnaW9uIH0gZnJvbSAnLi4vdXRpbHMvYXdzLWVudi5qcyc7XG5pbXBvcnQgeyB1cHNlcnRTZWNyZXQsIGdldFNlY3JldEFybiB9IGZyb20gJy4uL3V0aWxzL2F3cy1zZWNyZXRzLmpzJztcbmltcG9ydCB7IGNyZWF0ZUF1dGhlbnRpY2F0ZWRDbGllbnRBc3luYywgcHJpbnRDb21tYW5kSGVhZGVyLCBwcmludFNzbFdhcm5pbmcsIHdpdGhQcm9maWxlT3B0aW9uLCB3aXRoUmVnaW9uT3B0aW9uLCB3aXRoU3NsT3B0aW9ucyB9IGZyb20gJy4uL3V0aWxzL2NvbW1hbmQtdXRpbHMuanMnO1xuaW1wb3J0IHsgdG9FdmVudEJyaWRnZUNyb24gfSBmcm9tICcuLi91dGlscy9jcm9uLmpzJztcbmltcG9ydCB7IEVSUk9SX0NPREVTLCBoYW5kbGVFcnJvciB9IGZyb20gJy4uL3V0aWxzL2Vycm9yLWhhbmRsZXIuanMnO1xuaW1wb3J0IHsgcHJpbnRJbmZvLCBwcmludEtleVZhbHVlLCBwcmludFNlY3Rpb24sIHByaW50U3VjY2VzcyB9IGZyb20gJy4uL3V0aWxzL291dHB1dC11dGlscy5qcyc7XG5pbXBvcnQgeyBlbnN1cmVQbGF0Zm9ybVRva2VuLCByZXNvbHZlU2VjcmV0TmFtZSB9IGZyb20gJy4uL3V0aWxzL3BsYXRmb3JtLXNlY3JldC5qcyc7XG5cbi8vIEVTTSBoYXMgbm8gX19kaXJuYW1lOyBkZXJpdmUgaXQgZnJvbSB0aGlzIG1vZHVsZSdzIFVSTC5cbmNvbnN0IF9fZGlybmFtZSA9IHBhdGguZGlybmFtZShmaWxlVVJMVG9QYXRoKGltcG9ydC5tZXRhLnVybCkpO1xuXG5jb25zdCBSRU5FV19TVEFDS19OQU1FID0gJ3BpcGVsaW5lLWJ1aWxkZXItdG9rZW4tcmVuZXcnO1xuLy8gQ0ZOLW1hbmFnZWQgTGFtYmRhIGZ1bmN0aW9uIG5hbWUg4oCUIGtlZXAgaW4gc3luYyB3aXRoIHRva2VuLXJlbmV3LXN0YWNrLmpzb24uXG5jb25zdCBSRU5FV19MQU1CREFfTkFNRSA9ICdwaXBlbGluZS1idWlsZGVyLXRva2VuLXJlbmV3Jztcbi8vIERlZmF1bHQgNS1maWVsZCBjcm9uIChkYWlseSBhdCBtaWRuaWdodCkgd2hlbiBuZWl0aGVyIC0tY3JvbiBub3IgVE9LRU5fUkVORVdfU0NIRURVTEUgaXMgc2V0LlxuY29uc3QgREVGQVVMVF9SRU5FV19DUk9OID0gJzAgMCAqICogKic7XG5cbi8qKlxuICogRGVwbG95IChvciB1cGRhdGUpIHRoZSBvbmNlLWEtZGF5IHRva2VuLXJlbmV3YWwgc3RhY2s6IGEgc2NoZWR1bGVkIExhbWJkYSB0aGF0XG4gKiByZS1taW50cyB0aGUgcGxhdGZvcm0gSldUIGluIHRoaXMgc2FtZSBzZWNyZXQgYmVmb3JlIGl0IGV4cGlyZXMuIE1pcnJvcnNcbiAqIHNldHVwLWV2ZW50cyDigJQgYGF3cyBjbG91ZGZvcm1hdGlvbiBkZXBsb3lgIGZvciB0aGUgaW5mcmEsIHRoZW4gYSBkaXJlY3RcbiAqIFVwZGF0ZUZ1bmN0aW9uQ29kZSB3aXRoIHRoZSB0aGluIG9yY2hlc3RyYXRvciBoYW5kbGVyIGNvbXBpbGVkIGFsb25nc2lkZSB0aGlzXG4gKiBDTEkgKHRoZSBoYW5kbGVyIG5wbS1pbnN0YWxscyBwaXBlbGluZS1tYW5hZ2VyIGF0IHJ1bnRpbWUgYW5kIHJlLXJ1bnNcbiAqIHN0b3JlLXRva2VuOyBzZWUgc3JjL2xhbWJkYS90b2tlbi1yZW5ldy1oYW5kbGVyLnRzKS5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gZGVwbG95UmVuZXdTY2hlZHVsZShvcHRzOiB7XG4gIHBsYXRmb3JtVXJsOiBzdHJpbmc7XG4gIHNlY3JldE5hbWU6IHN0cmluZztcbiAgZGF5czogbnVtYmVyO1xuICBmaXZlRmllbGRDcm9uOiBzdHJpbmc7XG4gIHJlZ2lvbjogc3RyaW5nO1xuICBwcm9maWxlPzogc3RyaW5nO1xufSk6IFByb21pc2U8c3RyaW5nPiB7XG4gIGNvbnN0IHNjaGVkdWxlRXhwcmVzc2lvbiA9IHRvRXZlbnRCcmlkZ2VDcm9uKG9wdHMuZml2ZUZpZWxkQ3Jvbik7IC8vIHZhbGlkYXRlcyArIDE1LW1pbiBndWFyZFxuXG4gIC8vIE5hbWUgcmVuZXdhbCByZXNvdXJjZXMgcGVyLXNlY3JldCBzbyBhIHNjb3BlZC10b2tlbiBzdGFjayAoZS5nLiB0aGVcbiAgLy8gcmVwb3J0aW5nLWluZ2VzdCBjcmVkZW50aWFsIHRoZSBldmVudCBMYW1iZGEgcmVhZHMpIGNvZXhpc3RzIHdpdGggdGhlXG4gIC8vIHBsYXRmb3JtLXRva2VuIHN0YWNrIGluc3RlYWQgb2YgY29sbGlkaW5nIG9uIHRoZSAoYWNjb3VudC1nbG9iYWwpIElBTVxuICAvLyByb2xlIC8gTGFtYmRhIC8gcnVsZSBuYW1lcy4gVGhlIHBsYXRmb3JtIHNlY3JldCBrZWVwcyB0aGUgYmFyZSBuYW1lXG4gIC8vIChzdWZmaXggJycpIHNvIGV4aXN0aW5nIGRlcGxveW1lbnRzJyBzdGFjayBpcyB1cGRhdGVkIGluIHBsYWNlLCBub3RcbiAgLy8gZHVwbGljYXRlZDsgYW55IG90aGVyIHNlY3JldCBhcHBlbmRzIGl0cyB0cmFpbGluZyBwYXRoIHNlZ21lbnQuXG4gIGNvbnN0IHNlY3JldExlYWYgPSBvcHRzLnNlY3JldE5hbWUucmVwbGFjZSgvLipcXC8vLCAnJyk7IC8vICdwbGF0Zm9ybScgfCAncmVwb3J0aW5nLWluZ2VzdCcgfCDigKZcbiAgY29uc3QgbmFtZVN1ZmZpeCA9IHNlY3JldExlYWYgPT09ICdwbGF0Zm9ybScgPyAnJyA6IGAtJHtzZWNyZXRMZWFmLnJlcGxhY2UoL1teYS16MC05XSsvZ2ksICctJyl9YDtcbiAgY29uc3Qgc3RhY2tOYW1lID0gYCR7UkVORVdfU1RBQ0tfTkFNRX0ke25hbWVTdWZmaXh9YDtcbiAgY29uc3QgbGFtYmRhTmFtZSA9IGAke1JFTkVXX0xBTUJEQV9OQU1FfSR7bmFtZVN1ZmZpeH1gO1xuXG4gIHByaW50U2VjdGlvbignU2NoZWR1bGUgUmVuZXdhbCcpO1xuICBwcmludEluZm8oJ1BhcmFtZXRlcnMnLCB7XG4gICAgc3RhY2s6IHN0YWNrTmFtZSxcbiAgICBzY2hlZHVsZTogb3B0cy5maXZlRmllbGRDcm9uLFxuICAgIGV2ZW50YnJpZGdlOiBzY2hlZHVsZUV4cHJlc3Npb24sXG4gICAgcmVuZXdEYXlzOiBvcHRzLmRheXMsXG4gIH0pO1xuXG4gIC8vIFN0ZXAgMTogaW5mcmEgKExhbWJkYSBnZXRzIHBsYWNlaG9sZGVyIGNvZGUgb24gZmlyc3QgY3JlYXRlKS5cbiAgY29uc3QgdGVtcGxhdGVQYXRoID0gcGF0aC5qb2luKF9fZGlybmFtZSwgJy4uL3RlbXBsYXRlcy90b2tlbi1yZW5ldy1zdGFjay5qc29uJyk7XG4gIGNvbnN0IGNmbkFyZ3MgPSBbXG4gICAgJ2Nsb3VkZm9ybWF0aW9uJywgJ2RlcGxveScsXG4gICAgJy0tc3RhY2stbmFtZScsIHN0YWNrTmFtZSxcbiAgICAnLS10ZW1wbGF0ZS1maWxlJywgdGVtcGxhdGVQYXRoLFxuICAgICctLXBhcmFtZXRlci1vdmVycmlkZXMnLFxuICAgIGBQbGF0Zm9ybUJhc2VVcmw9JHtvcHRzLnBsYXRmb3JtVXJsfWAsXG4gICAgYFBsYXRmb3JtU2VjcmV0TmFtZT0ke29wdHMuc2VjcmV0TmFtZX1gLFxuICAgIGBSZW5ld0RheXM9JHtvcHRzLmRheXN9YCxcbiAgICBgU2NoZWR1bGVFeHByZXNzaW9uPSR7c2NoZWR1bGVFeHByZXNzaW9ufWAsXG4gICAgYE5hbWVTdWZmaXg9JHtuYW1lU3VmZml4fWAsXG4gICAgLy8gUGluIHRoZSBoYW5kbGVyJ3MgcnVudGltZSBucG0gaW5zdGFsbCB0byBUSElTIENMSSdzIHZlcnNpb24gKHJlcHJvZHVjaWJsZVxuICAgIC8vIHJlbmV3YWxzIGluc3RlYWQgb2YgYSBmbG9hdGluZyBcImxhdGVzdFwiKS5cbiAgICBgUGlwZWxpbmVNYW5hZ2VyVmVyc2lvbj0ke0FQUF9WRVJTSU9OfWAsXG4gICAgJy0tY2FwYWJpbGl0aWVzJywgJ0NBUEFCSUxJVFlfTkFNRURfSUFNJyxcbiAgICAnLS1uby1mYWlsLW9uLWVtcHR5LWNoYW5nZXNldCcsXG4gICAgJy0tcmVnaW9uJywgb3B0cy5yZWdpb24sXG4gIF07XG4gIGlmIChvcHRzLnByb2ZpbGUpIGNmbkFyZ3MucHVzaCgnLS1wcm9maWxlJywgb3B0cy5wcm9maWxlKTtcbiAgZXhlY0ZpbGVTeW5jKCdhd3MnLCBjZm5BcmdzLCB7IHN0ZGlvOiAnaW5oZXJpdCcgfSk7XG5cbiAgLy8gU3RlcCAyOiB1cGxvYWQgdGhlIHJlYWwgaGFuZGxlci4gSXQncyBFU00sIHNvIHRoZSB6aXAgZW50cnkgbXVzdCBiZSBpbmRleC5tanNcbiAgLy8gKEhhbmRsZXIgc3RheXMgaW5kZXguaGFuZGxlciDigJQgbm9kZWpzMjQueCByZXNvbHZlcyB0aGUgLm1qcyBleHRlbnNpb24pLlxuICBjb25zdCBoYW5kbGVyU3JjID0gcGF0aC5qb2luKF9fZGlybmFtZSwgJy4uL2xhbWJkYS90b2tlbi1yZW5ldy1oYW5kbGVyLmpzJyk7XG4gIGlmICghZnMuZXhpc3RzU3luYyhoYW5kbGVyU3JjKSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgVG9rZW4tcmVuZXcgaGFuZGxlciBub3QgZm91bmQgYXQgJHtoYW5kbGVyU3JjfSDigJQgd2FzIHRoZSBwYWNrYWdlIGJ1aWx0P2ApO1xuICB9XG4gIGNvbnN0IHRtcERpciA9IGZzLm1rZHRlbXBTeW5jKHBhdGguam9pbihvcy50bXBkaXIoKSwgJ3Rva2VuLXJlbmV3LScpKTtcbiAgdHJ5IHtcbiAgICBmcy5jb3B5RmlsZVN5bmMoaGFuZGxlclNyYywgcGF0aC5qb2luKHRtcERpciwgJ2luZGV4Lm1qcycpKTtcbiAgICBjb25zdCB6aXBQYXRoID0gcGF0aC5qb2luKHRtcERpciwgJ2luZGV4LnppcCcpO1xuICAgIGV4ZWNGaWxlU3luYygnemlwJywgWyctaicsIHppcFBhdGgsICdpbmRleC5tanMnXSwgeyBjd2Q6IHRtcERpciwgc3RkaW86ICdwaXBlJyB9KTtcblxuICAgIGNvbnN0IGxhbWJkYUNsaWVudCA9IG5ldyBMYW1iZGFDbGllbnQoeyByZWdpb246IG9wdHMucmVnaW9uIH0pO1xuICAgIGF3YWl0IGxhbWJkYUNsaWVudC5zZW5kKG5ldyBVcGRhdGVGdW5jdGlvbkNvZGVDb21tYW5kKHtcbiAgICAgIEZ1bmN0aW9uTmFtZTogbGFtYmRhTmFtZSxcbiAgICAgIFppcEZpbGU6IGZzLnJlYWRGaWxlU3luYyh6aXBQYXRoKSxcbiAgICB9KSk7XG4gIH0gZmluYWxseSB7XG4gICAgZnMucm1TeW5jKHRtcERpciwgeyByZWN1cnNpdmU6IHRydWUsIGZvcmNlOiB0cnVlIH0pO1xuICB9XG5cbiAgcHJpbnRTdWNjZXNzKGBSZW5ld2FsIHNjaGVkdWxlZCAoJHtzY2hlZHVsZUV4cHJlc3Npb259KWApO1xuICByZXR1cm4gc2NoZWR1bGVFeHByZXNzaW9uO1xufVxuXG4vKipcbiAqIFJlZ2lzdGVycyB0aGUgYHN0b3JlLXRva2VuYCBjb21tYW5kIHdpdGggdGhlIENMSSBwcm9ncmFtLlxuICpcbiAqIEdlbmVyYXRlcyBhIGxvbmctbGl2ZWQgSldUIHRva2VuIHZpYSB0aGUgcGxhdGZvcm0gQVBJIGFuZCBzdG9yZXMgaXRcbiAqIGluIEFXUyBTZWNyZXRzIE1hbmFnZXIgZm9yIHVzZSBieSB0aGUgc3ludGgvZGVwbG95IC0tc3RvcmUtdG9rZW5zIGZsYWcuXG4gKlxuICogUmVxdWlyZXMgUExBVEZPUk1fVE9LRU4gdG8gYmUgc2V0LCBvciB1c2UgLS1lbWFpbC8tLXBhc3N3b3JkIHRvIGxvZ2luIGlubGluZS5cbiAqXG4gKiBCeSBkZWZhdWx0IGl0IE9OTFkgd3JpdGVzIHRoZSBzZWNyZXQuIFBhc3MgLS1zY2hlZHVsZSB0byBhbHNvIGRlcGxveSB0aGUgZGFpbHlcbiAqIHRva2VuLXJlbmV3YWwgc3RhY2sgKGEgTGFtYmRhIHRoYXQgYXV0by1yZW5ld3MgdGhpcyB0b2tlbiBiZWZvcmUgaXQgZXhwaXJlcykuXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYGJhc2hcbiAqIHBpcGVsaW5lLW1hbmFnZXIgaW5mcmEgc3RvcmUtdG9rZW4gLS1yZWdpb24gdXMtZWFzdC0xXG4gKiBwaXBlbGluZS1tYW5hZ2VyIGluZnJhIHN0b3JlLXRva2VuIC0tZGF5cyA5MCAtLXJlZ2lvbiB1cy1lYXN0LTFcbiAqIHBpcGVsaW5lLW1hbmFnZXIgaW5mcmEgc3RvcmUtdG9rZW4gLS1zY2hlZHVsZSAtLXJlZ2lvbiB1cy1lYXN0LTEgICAgICAgICAgIyArIGRhaWx5IGF1dG8tcmVuZXdhbFxuICogcGlwZWxpbmUtbWFuYWdlciBpbmZyYSBzdG9yZS10b2tlbiAtLXNjaGVkdWxlIC0tY3JvbiAnMCAzICogKiAqJyAgICAgICAgICAjIGN1c3RvbSByZW5ld2FsIHRpbWVcbiAqIHBpcGVsaW5lLW1hbmFnZXIgaW5mcmEgc3RvcmUtdG9rZW4gLS1kYXlzIDcgLS1uby12ZXJpZnktc3NsXG4gKiBQTEFURk9STV9TRUNSRVRfTkFNRT1teS1jdXN0b20tc2VjcmV0IHBpcGVsaW5lLW1hbmFnZXIgaW5mcmEgc3RvcmUtdG9rZW4gICAjIG92ZXJyaWRlIHRoZSBkZXJpdmVkIG5hbWVcbiAqIHBpcGVsaW5lLW1hbmFnZXIgaW5mcmEgc3RvcmUtdG9rZW4gLS1kcnktcnVuXG4gKiBwaXBlbGluZS1tYW5hZ2VyIGluZnJhIHN0b3JlLXRva2VuIC1lIGFkbWluIC1wICcqKionIC0tcmVnaW9uIHVzLWVhc3QtMVxuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzdG9yZVRva2VuKHByb2dyYW06IENvbW1hbmQpOiB2b2lkIHtcbiAgd2l0aFNzbE9wdGlvbnMoXG4gICAgd2l0aFByb2ZpbGVPcHRpb24oXG4gICAgICB3aXRoUmVnaW9uT3B0aW9uKHByb2dyYW1cbiAgICAgICAgLmNvbW1hbmQoJ3N0b3JlLXRva2VuJylcbiAgICAgICAgLmRlc2NyaXB0aW9uKCdHZW5lcmF0ZSBKV1QgdG9rZW4gYW5kIHN0b3JlIGluIEFXUyBTZWNyZXRzIE1hbmFnZXIgZm9yIENESyBkZXBsb3ltZW50cycpXG4gICAgICAgIC5vcHRpb24oJy11LCAtLWlkZW50aWZpZXIgPGlkZW50aWZpZXI+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==
|