@pipeline-builder/pipeline-manager 4.1.4 → 4.1.6
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
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
// Copyright 2026 Pipeline Builder Contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
/**
|
|
4
|
+
* On-disk session store for `auth login`.
|
|
5
|
+
*
|
|
6
|
+
* `~/.pipeline-manager/credentials.json`, owner-only (0600 file inside the 0700
|
|
7
|
+
* directory the audit log already creates), keyed by platform base URL so one
|
|
8
|
+
* machine can hold sessions for several platforms at once.
|
|
9
|
+
*
|
|
10
|
+
* It holds a real session — the access token AND its refresh token — because
|
|
11
|
+
* that is what the device flow hands back and what lets the CLI keep working for
|
|
12
|
+
* days without another browser round trip. Nothing else about the account is
|
|
13
|
+
* stored: no password (the CLI no longer has one to store) and no identifier.
|
|
14
|
+
*
|
|
15
|
+
* Resolution order everywhere else in the CLI is unchanged in spirit: an
|
|
16
|
+
* explicit `PLATFORM_TOKEN` in the environment always wins, so CI keeps using an
|
|
17
|
+
* access key and is never affected by whatever a developer's laptop has cached.
|
|
18
|
+
*/
|
|
19
|
+
import fs from 'fs';
|
|
20
|
+
import os from 'os';
|
|
21
|
+
import path from 'path';
|
|
22
|
+
import { printDebug, printWarning } from './output-utils.js';
|
|
23
|
+
const STORE_DIR = path.join(os.homedir(), '.pipeline-manager');
|
|
24
|
+
const STORE_FILE = path.join(STORE_DIR, 'credentials.json');
|
|
25
|
+
/** Re-authenticate rather than hand out a token this close to expiry. */
|
|
26
|
+
const EXPIRY_SKEW_MS = 60_000;
|
|
27
|
+
/** Where the sessions live — surfaced in help text and errors. */
|
|
28
|
+
export function credentialStorePath() {
|
|
29
|
+
return STORE_FILE;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Trailing slashes and case differences in the host would otherwise split one
|
|
33
|
+
* platform into several entries.
|
|
34
|
+
*/
|
|
35
|
+
function storeKey(baseUrl) {
|
|
36
|
+
return baseUrl.trim().replace(/\/+$/, '').toLowerCase();
|
|
37
|
+
}
|
|
38
|
+
function readStore() {
|
|
39
|
+
try {
|
|
40
|
+
const parsed = JSON.parse(fs.readFileSync(STORE_FILE, 'utf-8'));
|
|
41
|
+
if (parsed?.version === 1 && parsed.sessions && typeof parsed.sessions === 'object') {
|
|
42
|
+
return parsed;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
// Missing or unreadable: treat as empty. A corrupt file must not break every
|
|
47
|
+
// command — the next successful login rewrites it.
|
|
48
|
+
}
|
|
49
|
+
return { version: 1, sessions: {} };
|
|
50
|
+
}
|
|
51
|
+
function writeStore(store) {
|
|
52
|
+
fs.mkdirSync(STORE_DIR, { recursive: true, mode: 0o700 });
|
|
53
|
+
// Write through a temp file so an interrupted write can't leave a truncated
|
|
54
|
+
// store behind, and create it 0600 from the start (never briefly world-readable).
|
|
55
|
+
const tmp = `${STORE_FILE}.tmp`;
|
|
56
|
+
fs.writeFileSync(tmp, `${JSON.stringify(store, null, 2)}\n`, { mode: 0o600 });
|
|
57
|
+
fs.renameSync(tmp, STORE_FILE);
|
|
58
|
+
}
|
|
59
|
+
/** Persist the session for `baseUrl`, replacing any previous one. */
|
|
60
|
+
export function saveSession(baseUrl, session) {
|
|
61
|
+
const store = readStore();
|
|
62
|
+
store.sessions[storeKey(baseUrl)] = { ...session, savedAt: new Date().toISOString() };
|
|
63
|
+
writeStore(store);
|
|
64
|
+
printDebug('Session stored', { path: STORE_FILE, platform: storeKey(baseUrl) });
|
|
65
|
+
}
|
|
66
|
+
/** The stored session for `baseUrl`, or undefined. Expiry is NOT checked here —
|
|
67
|
+
* callers decide whether to use, refresh or ignore it. */
|
|
68
|
+
export function loadSession(baseUrl) {
|
|
69
|
+
return readStore().sessions[storeKey(baseUrl)];
|
|
70
|
+
}
|
|
71
|
+
/** Forget the session for `baseUrl` (sign-out, or a refresh the platform rejected). */
|
|
72
|
+
export function clearSession(baseUrl) {
|
|
73
|
+
const store = readStore();
|
|
74
|
+
if (!(storeKey(baseUrl) in store.sessions))
|
|
75
|
+
return;
|
|
76
|
+
delete store.sessions[storeKey(baseUrl)];
|
|
77
|
+
try {
|
|
78
|
+
writeStore(store);
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
// Losing the ability to clear a dead session is a nuisance, not a failure.
|
|
82
|
+
printWarning('Could not update the stored credentials', {
|
|
83
|
+
path: STORE_FILE,
|
|
84
|
+
error: error instanceof Error ? error.message : String(error),
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
/** True when the stored access token is still usable (with a little slack). */
|
|
89
|
+
export function isSessionUsable(session) {
|
|
90
|
+
return !!session?.accessToken && session.expiresAt - EXPIRY_SKEW_MS > Date.now();
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY3JlZGVudGlhbC1zdG9yZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlscy9jcmVkZW50aWFsLXN0b3JlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLCtDQUErQztBQUMvQyxzQ0FBc0M7QUFFdEM7Ozs7Ozs7Ozs7Ozs7OztHQWVHO0FBRUgsT0FBTyxFQUFFLE1BQU0sSUFBSSxDQUFDO0FBQ3BCLE9BQU8sRUFBRSxNQUFNLElBQUksQ0FBQztBQUNwQixPQUFPLElBQUksTUFBTSxNQUFNLENBQUM7QUFDeEIsT0FBTyxFQUFFLFVBQVUsRUFBRSxZQUFZLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUU3RCxNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxPQUFPLEVBQUUsRUFBRSxtQkFBbUIsQ0FBQyxDQUFDO0FBQy9ELE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLGtCQUFrQixDQUFDLENBQUM7QUFFNUQseUVBQXlFO0FBQ3pFLE1BQU0sY0FBYyxHQUFHLE1BQU0sQ0FBQztBQW1COUIsa0VBQWtFO0FBQ2xFLE1BQU0sVUFBVSxtQkFBbUI7SUFDakMsT0FBTyxVQUFVLENBQUM7QUFDcEIsQ0FBQztBQUVEOzs7R0FHRztBQUNILFNBQVMsUUFBUSxDQUFDLE9BQWU7SUFDL0IsT0FBTyxPQUFPLENBQUMsSUFBSSxFQUFFLENBQUMsT0FBTyxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUMsQ0FBQyxXQUFXLEVBQUUsQ0FBQztBQUMxRCxDQUFDO0FBRUQsU0FBUyxTQUFTO0lBQ2hCLElBQUksQ0FBQztRQUNILE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLFlBQVksQ0FBQyxVQUFVLEVBQUUsT0FBTyxDQUFDLENBQUMsQ0FBQztRQUNoRSxJQUFJLE1BQU0sRUFBRSxPQUFPLEtBQUssQ0FBQyxJQUFJLE1BQU0sQ0FBQyxRQUFRLElBQUksT0FBTyxNQUFNLENBQUMsUUFBUSxLQUFLLFFBQVEsRUFBRSxDQUFDO1lBQ3BGLE9BQU8sTUFBbUIsQ0FBQztRQUM3QixDQUFDO0lBQ0gsQ0FBQztJQUFDLE1BQU0sQ0FBQztRQUNQLDZFQUE2RTtRQUM3RSxtREFBbUQ7SUFDckQsQ0FBQztJQUNELE9BQU8sRUFBRSxPQUFPLEVBQUUsQ0FBQyxFQUFFLFFBQVEsRUFBRSxFQUFFLEVBQUUsQ0FBQztBQUN0QyxDQUFDO0FBRUQsU0FBUyxVQUFVLENBQUMsS0FBZ0I7SUFDbEMsRUFBRSxDQUFDLFNBQVMsQ0FBQyxTQUFTLEVBQUUsRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDO0lBQzFELDRFQUE0RTtJQUM1RSxrRkFBa0Y7SUFDbEYsTUFBTSxHQUFHLEdBQUcsR0FBRyxVQUFVLE1BQU0sQ0FBQztJQUNoQyxFQUFFLENBQUMsYUFBYSxDQUFDLEdBQUcsRUFBRSxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxFQUFFLElBQUksRUFBRSxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7SUFDOUUsRUFBRSxDQUFDLFVBQVUsQ0FBQyxHQUFHLEVBQUUsVUFBVSxDQUFDLENBQUM7QUFDakMsQ0FBQztBQUVELHFFQUFxRTtBQUNyRSxNQUFNLFVBQVUsV0FBVyxDQUFDLE9BQWUsRUFBRSxPQUF1QztJQUNsRixNQUFNLEtBQUssR0FBRyxTQUFTLEVBQUUsQ0FBQztJQUMxQixLQUFLLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQyxHQUFHLEVBQUUsR0FBRyxPQUFPLEVBQUUsT0FBTyxFQUFFLElBQUksSUFBSSxFQUFFLENBQUMsV0FBVyxFQUFFLEVBQUUsQ0FBQztJQUN0RixVQUFVLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDbEIsVUFBVSxDQUFDLGdCQUFnQixFQUFFLEVBQUUsSUFBSSxFQUFFLFVBQVUsRUFBRSxRQUFRLEVBQUUsUUFBUSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsQ0FBQztBQUNsRixDQUFDO0FBRUQ7MkRBQzJEO0FBQzNELE1BQU0sVUFBVSxXQUFXLENBQUMsT0FBZTtJQUN6QyxPQUFPLFNBQVMsRUFBRSxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQztBQUNqRCxDQUFDO0FBRUQsdUZBQXVGO0FBQ3ZGLE1BQU0sVUFBVSxZQUFZLENBQUMsT0FBZTtJQUMxQyxNQUFNLEtBQUssR0FBRyxTQUFTLEVBQUUsQ0FBQztJQUMxQixJQUFJLENBQUMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLElBQUksS0FBSyxDQUFDLFFBQVEsQ0FBQztRQUFFLE9BQU87SUFDbkQsT0FBTyxLQUFLLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO0lBQ3pDLElBQUksQ0FBQztRQUNILFVBQVUsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUNwQixDQUFDO0lBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztRQUNmLDJFQUEyRTtRQUMzRSxZQUFZLENBQUMseUNBQXlDLEVBQUU7WUFDdEQsSUFBSSxFQUFFLFVBQVU7WUFDaEIsS0FBSyxFQUFFLEtBQUssWUFBWSxLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUM7U0FDOUQsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztBQUNILENBQUM7QUFFRCwrRUFBK0U7QUFDL0UsTUFBTSxVQUFVLGVBQWUsQ0FBQyxPQUFrQztJQUNoRSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsV0FBVyxJQUFJLE9BQU8sQ0FBQyxTQUFTLEdBQUcsY0FBYyxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztBQUNuRixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IDIwMjYgUGlwZWxpbmUgQnVpbGRlciBDb250cmlidXRvcnNcbi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG5cbi8qKlxuICogT24tZGlzayBzZXNzaW9uIHN0b3JlIGZvciBgYXV0aCBsb2dpbmAuXG4gKlxuICogYH4vLnBpcGVsaW5lLW1hbmFnZXIvY3JlZGVudGlhbHMuanNvbmAsIG93bmVyLW9ubHkgKDA2MDAgZmlsZSBpbnNpZGUgdGhlIDA3MDBcbiAqIGRpcmVjdG9yeSB0aGUgYXVkaXQgbG9nIGFscmVhZHkgY3JlYXRlcyksIGtleWVkIGJ5IHBsYXRmb3JtIGJhc2UgVVJMIHNvIG9uZVxuICogbWFjaGluZSBjYW4gaG9sZCBzZXNzaW9ucyBmb3Igc2V2ZXJhbCBwbGF0Zm9ybXMgYXQgb25jZS5cbiAqXG4gKiBJdCBob2xkcyBhIHJlYWwgc2Vzc2lvbiDigJQgdGhlIGFjY2VzcyB0b2tlbiBBTkQgaXRzIHJlZnJlc2ggdG9rZW4g4oCUIGJlY2F1c2VcbiAqIHRoYXQgaXMgd2hhdCB0aGUgZGV2aWNlIGZsb3cgaGFuZHMgYmFjayBhbmQgd2hhdCBsZXRzIHRoZSBDTEkga2VlcCB3b3JraW5nIGZvclxuICogZGF5cyB3aXRob3V0IGFub3RoZXIgYnJvd3NlciByb3VuZCB0cmlwLiBOb3RoaW5nIGVsc2UgYWJvdXQgdGhlIGFjY291bnQgaXNcbiAqIHN0b3JlZDogbm8gcGFzc3dvcmQgKHRoZSBDTEkgbm8gbG9uZ2VyIGhhcyBvbmUgdG8gc3RvcmUpIGFuZCBubyBpZGVudGlmaWVyLlxuICpcbiAqIFJlc29sdXRpb24gb3JkZXIgZXZlcnl3aGVyZSBlbHNlIGluIHRoZSBDTEkgaXMgdW5jaGFuZ2VkIGluIHNwaXJpdDogYW5cbiAqIGV4cGxpY2l0IGBQTEFURk9STV9UT0tFTmAgaW4gdGhlIGVudmlyb25tZW50IGFsd2F5cyB3aW5zLCBzbyBDSSBrZWVwcyB1c2luZyBhblxuICogYWNjZXNzIGtleSBhbmQgaXMgbmV2ZXIgYWZmZWN0ZWQgYnkgd2hhdGV2ZXIgYSBkZXZlbG9wZXIncyBsYXB0b3AgaGFzIGNhY2hlZC5cbiAqL1xuXG5pbXBvcnQgZnMgZnJvbSAnZnMnO1xuaW1wb3J0IG9zIGZyb20gJ29zJztcbmltcG9ydCBwYXRoIGZyb20gJ3BhdGgnO1xuaW1wb3J0IHsgcHJpbnREZWJ1ZywgcHJpbnRXYXJuaW5nIH0gZnJvbSAnLi9vdXRwdXQtdXRpbHMuanMnO1xuXG5jb25zdCBTVE9SRV9ESVIgPSBwYXRoLmpvaW4ob3MuaG9tZWRpcigpLCAnLnBpcGVsaW5lLW1hbmFnZXInKTtcbmNvbnN0IFNUT1JFX0ZJTEUgPSBwYXRoLmpvaW4oU1RPUkVfRElSLCAnY3JlZGVudGlhbHMuanNvbicpO1xuXG4vKiogUmUtYXV0aGVudGljYXRlIHJhdGhlciB0aGFuIGhhbmQgb3V0IGEgdG9rZW4gdGhpcyBjbG9zZSB0byBleHBpcnkuICovXG5jb25zdCBFWFBJUllfU0tFV19NUyA9IDYwXzAwMDtcblxuLyoqIE9uZSBwbGF0Zm9ybSdzIHN0b3JlZCBzZXNzaW9uLiAqL1xuZXhwb3J0IGludGVyZmFjZSBTdG9yZWRTZXNzaW9uIHtcbiAgYWNjZXNzVG9rZW46IHN0cmluZztcbiAgLyoqIFJvdGF0ZWQgb24gZXZlcnkgcmVmcmVzaDsgYWJzZW50IG9ubHkgaWYgdGhlIHBsYXRmb3JtIHN0b3BwZWQgaXNzdWluZyBvbmUuICovXG4gIHJlZnJlc2hUb2tlbj86IHN0cmluZztcbiAgLyoqIEVwb2NoIG1zIHRoZSBhY2Nlc3MgdG9rZW4gZXhwaXJlcy4gKi9cbiAgZXhwaXJlc0F0OiBudW1iZXI7XG4gIC8qKiBUaGUgb3JnIHRoZSBzZXNzaW9uIHdhcyBzY29wZWQgdG8gd2hlbiBpdCB3YXMgc3RvcmVkIChpbmZvcm1hdGlvbmFsKS4gKi9cbiAgb3JnYW5pemF0aW9uSWQ/OiBzdHJpbmc7XG4gIHNhdmVkQXQ6IHN0cmluZztcbn1cblxuaW50ZXJmYWNlIFN0b3JlRmlsZSB7XG4gIHZlcnNpb246IDE7XG4gIHNlc3Npb25zOiBSZWNvcmQ8c3RyaW5nLCBTdG9yZWRTZXNzaW9uPjtcbn1cblxuLyoqIFdoZXJlIHRoZSBzZXNzaW9ucyBsaXZlIOKAlCBzdXJmYWNlZCBpbiBoZWxwIHRleHQgYW5kIGVycm9ycy4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVkZW50aWFsU3RvcmVQYXRoKCk6IHN0cmluZyB7XG4gIHJldHVybiBTVE9SRV9GSUxFO1xufVxuXG4vKipcbiAqIFRyYWlsaW5nIHNsYXNoZXMgYW5kIGNhc2UgZGlmZmVyZW5jZXMgaW4gdGhlIGhvc3Qgd291bGQgb3RoZXJ3aXNlIHNwbGl0IG9uZVxuICogcGxhdGZvcm0gaW50byBzZXZlcmFsIGVudHJpZXMuXG4gKi9cbmZ1bmN0aW9uIHN0b3JlS2V5KGJhc2VVcmw6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiBiYXNlVXJsLnRyaW0oKS5yZXBsYWNlKC9cXC8rJC8sICcnKS50b0xvd2VyQ2FzZSgpO1xufVxuXG5mdW5jdGlvbiByZWFkU3RvcmUoKTogU3RvcmVGaWxlIHtcbiAgdHJ5IHtcbiAgICBjb25zdCBwYXJzZWQgPSBKU09OLnBhcnNlKGZzLnJlYWRGaWxlU3luYyhTVE9SRV9GSUxFLCAndXRmLTgnKSk7XG4gICAgaWYgKHBhcnNlZD8udmVyc2lvbiA9PT0gMSAmJiBwYXJzZWQuc2Vzc2lvbnMgJiYgdHlwZW9mIHBhcnNlZC5zZXNzaW9ucyA9PT0gJ29iamVjdCcpIHtcbiAgICAgIHJldHVybiBwYXJzZWQgYXMgU3RvcmVGaWxlO1xuICAgIH1cbiAgfSBjYXRjaCB7XG4gICAgLy8gTWlzc2luZyBvciB1bnJlYWRhYmxlOiB0cmVhdCBhcyBlbXB0eS4gQSBjb3JydXB0IGZpbGUgbXVzdCBub3QgYnJlYWsgZXZlcnlcbiAgICAvLyBjb21tYW5kIOKAlCB0aGUgbmV4dCBzdWNjZXNzZnVsIGxvZ2luIHJld3JpdGVzIGl0LlxuICB9XG4gIHJldHVybiB7IHZlcnNpb246IDEsIHNlc3Npb25zOiB7fSB9O1xufVxuXG5mdW5jdGlvbiB3cml0ZVN0b3JlKHN0b3JlOiBTdG9yZUZpbGUpOiB2b2lkIHtcbiAgZnMubWtkaXJTeW5jKFNUT1JFX0RJUiwgeyByZWN1cnNpdmU6IHRydWUsIG1vZGU6IDBvNzAwIH0pO1xuICAvLyBXcml0ZSB0aHJvdWdoIGEgdGVtcCBmaWxlIHNvIGFuIGludGVycnVwdGVkIHdyaXRlIGNhbid0IGxlYXZlIGEgdHJ1bmNhdGVkXG4gIC8vIHN0b3JlIGJlaGluZCwgYW5kIGNyZWF0ZSBpdCAwNjAwIGZyb20gdGhlIHN0YXJ0IChuZXZlciBicmllZmx5IHdvcmxkLXJlYWRhYmxlKS5cbiAgY29uc3QgdG1wID0gYCR7U1RPUkVfRklMRX0udG1wYDtcbiAgZnMud3JpdGVGaWxlU3luYyh0bXAsIGAke0pTT04uc3RyaW5naWZ5KHN0b3JlLCBudWxsLCAyKX1cXG5gLCB7IG1vZGU6IDBvNjAwIH0pO1xuICBmcy5yZW5hbWVTeW5jKHRtcCwgU1RPUkVfRklMRSk7XG59XG5cbi8qKiBQZXJzaXN0IHRoZSBzZXNzaW9uIGZvciBgYmFzZVVybGAsIHJlcGxhY2luZyBhbnkgcHJldmlvdXMgb25lLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNhdmVTZXNzaW9uKGJhc2VVcmw6IHN0cmluZywgc2Vzc2lvbjogT21pdDxTdG9yZWRTZXNzaW9uLCAnc2F2ZWRBdCc+KTogdm9pZCB7XG4gIGNvbnN0IHN0b3JlID0gcmVhZFN0b3JlKCk7XG4gIHN0b3JlLnNlc3Npb25zW3N0b3JlS2V5KGJhc2VVcmwpXSA9IHsgLi4uc2Vzc2lvbiwgc2F2ZWRBdDogbmV3IERhdGUoKS50b0lTT1N0cmluZygpIH07XG4gIHdyaXRlU3RvcmUoc3RvcmUpO1xuICBwcmludERlYnVnKCdTZXNzaW9uIHN0b3JlZCcsIHsgcGF0aDogU1RPUkVfRklMRSwgcGxhdGZvcm06IHN0b3JlS2V5KGJhc2VVcmwpIH0pO1xufVxuXG4vKiogVGhlIHN0b3JlZCBzZXNzaW9uIGZvciBgYmFzZVVybGAsIG9yIHVuZGVmaW5lZC4gRXhwaXJ5IGlzIE5PVCBjaGVja2VkIGhlcmUg4oCUXG4gKiAgY2FsbGVycyBkZWNpZGUgd2hldGhlciB0byB1c2UsIHJlZnJlc2ggb3IgaWdub3JlIGl0LiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGxvYWRTZXNzaW9uKGJhc2VVcmw6IHN0cmluZyk6IFN0b3JlZFNlc3Npb24gfCB1bmRlZmluZWQge1xuICByZXR1cm4gcmVhZFN0b3JlKCkuc2Vzc2lvbnNbc3RvcmVLZXkoYmFzZVVybCldO1xufVxuXG4vKiogRm9yZ2V0IHRoZSBzZXNzaW9uIGZvciBgYmFzZVVybGAgKHNpZ24tb3V0LCBvciBhIHJlZnJlc2ggdGhlIHBsYXRmb3JtIHJlamVjdGVkKS4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjbGVhclNlc3Npb24oYmFzZVVybDogc3RyaW5nKTogdm9pZCB7XG4gIGNvbnN0IHN0b3JlID0gcmVhZFN0b3JlKCk7XG4gIGlmICghKHN0b3JlS2V5KGJhc2VVcmwpIGluIHN0b3JlLnNlc3Npb25zKSkgcmV0dXJuO1xuICBkZWxldGUgc3RvcmUuc2Vzc2lvbnNbc3RvcmVLZXkoYmFzZVVybCldO1xuICB0cnkge1xuICAgIHdyaXRlU3RvcmUoc3RvcmUpO1xuICB9IGNhdGNoIChlcnJvcikge1xuICAgIC8vIExvc2luZyB0aGUgYWJpbGl0eSB0byBjbGVhciBhIGRlYWQgc2Vzc2lvbiBpcyBhIG51aXNhbmNlLCBub3QgYSBmYWlsdXJlLlxuICAgIHByaW50V2FybmluZygnQ291bGQgbm90IHVwZGF0ZSB0aGUgc3RvcmVkIGNyZWRlbnRpYWxzJywge1xuICAgICAgcGF0aDogU1RPUkVfRklMRSxcbiAgICAgIGVycm9yOiBlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZXJyb3IubWVzc2FnZSA6IFN0cmluZyhlcnJvciksXG4gICAgfSk7XG4gIH1cbn1cblxuLyoqIFRydWUgd2hlbiB0aGUgc3RvcmVkIGFjY2VzcyB0b2tlbiBpcyBzdGlsbCB1c2FibGUgKHdpdGggYSBsaXR0bGUgc2xhY2spLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzU2Vzc2lvblVzYWJsZShzZXNzaW9uOiBTdG9yZWRTZXNzaW9uIHwgdW5kZWZpbmVkKTogc2Vzc2lvbiBpcyBTdG9yZWRTZXNzaW9uIHtcbiAgcmV0dXJuICEhc2Vzc2lvbj8uYWNjZXNzVG9rZW4gJiYgc2Vzc2lvbi5leHBpcmVzQXQgLSBFWFBJUllfU0tFV19NUyA+IERhdGUubm93KCk7XG59XG4iXX0=
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type https from 'https';
|
|
2
|
+
/** `POST /auth/device/code` — RFC 8628 §3.2. */
|
|
3
|
+
export interface DeviceCodeResponse {
|
|
4
|
+
device_code: string;
|
|
5
|
+
user_code: string;
|
|
6
|
+
verification_uri: string;
|
|
7
|
+
verification_uri_complete?: string;
|
|
8
|
+
expires_in: number;
|
|
9
|
+
interval: number;
|
|
10
|
+
}
|
|
11
|
+
/** `POST /auth/device/token` on success — RFC 8628 §3.5. */
|
|
12
|
+
export interface DeviceTokenResponse {
|
|
13
|
+
access_token: string;
|
|
14
|
+
refresh_token?: string;
|
|
15
|
+
token_type: string;
|
|
16
|
+
expires_in: number;
|
|
17
|
+
/** Present only when the device asked for one at `/code` (`auth pat`). */
|
|
18
|
+
step_up_token?: string;
|
|
19
|
+
}
|
|
20
|
+
/** Connection settings shared by both calls. */
|
|
21
|
+
export interface DeviceAuthTransport {
|
|
22
|
+
url: string;
|
|
23
|
+
httpsAgent: https.Agent;
|
|
24
|
+
timeout: number;
|
|
25
|
+
}
|
|
26
|
+
/** Raised for every terminal outcome, so callers can print one clear message. */
|
|
27
|
+
export declare class DeviceAuthError extends Error {
|
|
28
|
+
readonly code: string;
|
|
29
|
+
constructor(message: string, code: string);
|
|
30
|
+
}
|
|
31
|
+
/** Ask the platform to open a device authorization. */
|
|
32
|
+
export declare function requestDeviceCode(transport: DeviceAuthTransport, options?: {
|
|
33
|
+
stepUp?: boolean;
|
|
34
|
+
}): Promise<DeviceCodeResponse>;
|
|
35
|
+
/**
|
|
36
|
+
* Poll `/auth/device/token` until the browser decides, the code expires, or
|
|
37
|
+
* `signal` says to stop.
|
|
38
|
+
*
|
|
39
|
+
* Interval handling is the RFC's: start at the advertised `interval`, and widen
|
|
40
|
+
* it by 5 seconds (or to whatever the platform names) on every `slow_down`. The
|
|
41
|
+
* platform also enforces the interval, so a client that ignores it is throttled
|
|
42
|
+
* rather than trusted.
|
|
43
|
+
*/
|
|
44
|
+
export declare function pollForDeviceToken(transport: DeviceAuthTransport, code: DeviceCodeResponse, hooks?: {
|
|
45
|
+
onPending?: () => void;
|
|
46
|
+
}): Promise<DeviceTokenResponse>;
|
|
47
|
+
/**
|
|
48
|
+
* Try to open `url` in the default browser. Returns false — never throws — when
|
|
49
|
+
* the environment has no browser to open (a CI runner, an SSH session, a
|
|
50
|
+
* non-interactive shell) or the opener isn't installed, so the caller falls back
|
|
51
|
+
* to printing the URL.
|
|
52
|
+
*
|
|
53
|
+
* The URL is passed as an ARGUMENT, never through a shell, and only http(s) is
|
|
54
|
+
* accepted: the value comes from the platform's response, and handing an
|
|
55
|
+
* arbitrary scheme to the OS opener is how "click this link" turns into "run
|
|
56
|
+
* this program".
|
|
57
|
+
*/
|
|
58
|
+
export declare function openInBrowser(url: string): boolean;
|
|
59
|
+
//# sourceMappingURL=device-auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"device-auth.d.ts","sourceRoot":"","sources":["../../src/utils/device-auth.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAI/B,gDAAgD;AAChD,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,MAAM,CAAC;IACzB,yBAAyB,CAAC,EAAE,MAAM,CAAC;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,4DAA4D;AAC5D,MAAM,WAAW,mBAAmB;IAClC,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,0EAA0E;IAC1E,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AASD,gDAAgD;AAChD,MAAM,WAAW,mBAAmB;IAClC,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,KAAK,CAAC,KAAK,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,iFAAiF;AACjF,qBAAa,eAAgB,SAAQ,KAAK;IACX,QAAQ,CAAC,IAAI,EAAE,MAAM;IAAlD,YAAY,OAAO,EAAE,MAAM,EAAW,IAAI,EAAE,MAAM,EAGjD;CACF;AAED,uDAAuD;AACvD,wBAAsB,iBAAiB,CACrC,SAAS,EAAE,mBAAmB,EAC9B,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAO,GACjC,OAAO,CAAC,kBAAkB,CAAC,CAiB7B;AAOD;;;;;;;;GAQG;AACH,wBAAsB,kBAAkB,CACtC,SAAS,EAAE,mBAAmB,EAC9B,IAAI,EAAE,kBAAkB,EACxB,KAAK,GAAE;IAAE,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;CAAO,GACrC,OAAO,CAAC,mBAAmB,CAAC,CAkD9B;AAUD;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAsBlD"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
// Copyright 2026 Pipeline Builder Contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
/**
|
|
4
|
+
* OAuth 2.0 device authorization grant client (RFC 8628) — how the CLI signs in.
|
|
5
|
+
*
|
|
6
|
+
* The CLI asks the platform for a code, shows it (and opens the browser when it
|
|
7
|
+
* can), then polls until the person approves in that browser. No password and no
|
|
8
|
+
* long-lived token ever passes through the command line, shell history, `ps`
|
|
9
|
+
* output or a CI log; the browser is where SSO, step-up and later MFA already
|
|
10
|
+
* apply, so the terminal inherits all of it without implementing any of it.
|
|
11
|
+
*/
|
|
12
|
+
import { spawn } from 'child_process';
|
|
13
|
+
import axios from 'axios';
|
|
14
|
+
import { printDebug } from './output-utils.js';
|
|
15
|
+
/** Raised for every terminal outcome, so callers can print one clear message. */
|
|
16
|
+
export class DeviceAuthError extends Error {
|
|
17
|
+
code;
|
|
18
|
+
constructor(message, code) {
|
|
19
|
+
super(message);
|
|
20
|
+
this.code = code;
|
|
21
|
+
this.name = 'DeviceAuthError';
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
/** Ask the platform to open a device authorization. */
|
|
25
|
+
export async function requestDeviceCode(transport, options = {}) {
|
|
26
|
+
const codeUrl = `${transport.url}/api/auth/device/code`;
|
|
27
|
+
printDebug('POST', { url: codeUrl });
|
|
28
|
+
const response = await axios.post(codeUrl, { ...(options.stepUp ? { step_up: true } : {}) }, {
|
|
29
|
+
headers: { 'Content-Type': 'application/json', 'X-Pb-Client': 'cli' },
|
|
30
|
+
httpsAgent: transport.httpsAgent,
|
|
31
|
+
timeout: transport.timeout,
|
|
32
|
+
});
|
|
33
|
+
const data = response.data;
|
|
34
|
+
if (!data?.device_code || !data.user_code) {
|
|
35
|
+
throw new DeviceAuthError('The platform did not return a device code.', 'invalid_response');
|
|
36
|
+
}
|
|
37
|
+
return data;
|
|
38
|
+
}
|
|
39
|
+
/** Sleep, without pulling in a timers dependency. */
|
|
40
|
+
function wait(ms) {
|
|
41
|
+
return new Promise((resolve) => { setTimeout(resolve, ms); });
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Poll `/auth/device/token` until the browser decides, the code expires, or
|
|
45
|
+
* `signal` says to stop.
|
|
46
|
+
*
|
|
47
|
+
* Interval handling is the RFC's: start at the advertised `interval`, and widen
|
|
48
|
+
* it by 5 seconds (or to whatever the platform names) on every `slow_down`. The
|
|
49
|
+
* platform also enforces the interval, so a client that ignores it is throttled
|
|
50
|
+
* rather than trusted.
|
|
51
|
+
*/
|
|
52
|
+
export async function pollForDeviceToken(transport, code, hooks = {}) {
|
|
53
|
+
const tokenUrl = `${transport.url}/api/auth/device/token`;
|
|
54
|
+
const deadline = Date.now() + code.expires_in * 1000;
|
|
55
|
+
let intervalMs = Math.max(1, code.interval) * 1000;
|
|
56
|
+
while (Date.now() < deadline) {
|
|
57
|
+
await wait(intervalMs);
|
|
58
|
+
printDebug('POST', { url: tokenUrl });
|
|
59
|
+
const response = await axios.post(tokenUrl, { device_code: code.device_code }, {
|
|
60
|
+
headers: { 'Content-Type': 'application/json', 'X-Pb-Client': 'cli' },
|
|
61
|
+
httpsAgent: transport.httpsAgent,
|
|
62
|
+
timeout: transport.timeout,
|
|
63
|
+
// The RFC's pending/backoff signals arrive as HTTP 400, which axios would
|
|
64
|
+
// otherwise throw: they are protocol states, not failures.
|
|
65
|
+
validateStatus: (status) => (status >= 200 && status < 300) || status === 400,
|
|
66
|
+
});
|
|
67
|
+
if (response.status === 200) {
|
|
68
|
+
if (!response.data?.access_token) {
|
|
69
|
+
throw new DeviceAuthError('The platform approved the sign-in but returned no token.', 'invalid_response');
|
|
70
|
+
}
|
|
71
|
+
return response.data;
|
|
72
|
+
}
|
|
73
|
+
switch (response.data?.error) {
|
|
74
|
+
case 'authorization_pending':
|
|
75
|
+
hooks.onPending?.();
|
|
76
|
+
break;
|
|
77
|
+
case 'slow_down':
|
|
78
|
+
intervalMs = Math.max(intervalMs + 5_000, (response.data.interval ?? 0) * 1000);
|
|
79
|
+
printDebug('Polling slowed by the platform', { intervalMs });
|
|
80
|
+
break;
|
|
81
|
+
case 'access_denied':
|
|
82
|
+
throw new DeviceAuthError('The sign-in was denied in the browser.', 'access_denied');
|
|
83
|
+
case 'expired_token':
|
|
84
|
+
throw new DeviceAuthError('The sign-in code expired before it was approved.', 'expired_token');
|
|
85
|
+
default:
|
|
86
|
+
throw new DeviceAuthError(response.data?.error_description || 'The platform refused the device sign-in.', response.data?.error || 'invalid_request');
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
throw new DeviceAuthError('Timed out waiting for the sign-in to be approved.', 'expired_token');
|
|
90
|
+
}
|
|
91
|
+
/** The OS command that opens a URL in the default browser. */
|
|
92
|
+
function openCommand() {
|
|
93
|
+
if (process.platform === 'darwin')
|
|
94
|
+
return { command: 'open', args: [] };
|
|
95
|
+
if (process.platform === 'win32')
|
|
96
|
+
return { command: 'cmd', args: ['/c', 'start', ''] };
|
|
97
|
+
if (process.platform === 'linux')
|
|
98
|
+
return { command: 'xdg-open', args: [] };
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Try to open `url` in the default browser. Returns false — never throws — when
|
|
103
|
+
* the environment has no browser to open (a CI runner, an SSH session, a
|
|
104
|
+
* non-interactive shell) or the opener isn't installed, so the caller falls back
|
|
105
|
+
* to printing the URL.
|
|
106
|
+
*
|
|
107
|
+
* The URL is passed as an ARGUMENT, never through a shell, and only http(s) is
|
|
108
|
+
* accepted: the value comes from the platform's response, and handing an
|
|
109
|
+
* arbitrary scheme to the OS opener is how "click this link" turns into "run
|
|
110
|
+
* this program".
|
|
111
|
+
*/
|
|
112
|
+
export function openInBrowser(url) {
|
|
113
|
+
let parsed;
|
|
114
|
+
try {
|
|
115
|
+
parsed = new URL(url);
|
|
116
|
+
}
|
|
117
|
+
catch {
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
if (parsed.protocol !== 'https:' && parsed.protocol !== 'http:')
|
|
121
|
+
return false;
|
|
122
|
+
if (process.env.CI || process.env.SSH_CONNECTION || process.env.SSH_TTY)
|
|
123
|
+
return false;
|
|
124
|
+
if (!process.stdout.isTTY)
|
|
125
|
+
return false;
|
|
126
|
+
const opener = openCommand();
|
|
127
|
+
if (!opener)
|
|
128
|
+
return false;
|
|
129
|
+
try {
|
|
130
|
+
const child = spawn(opener.command, [...opener.args, url], { stdio: 'ignore', detached: true });
|
|
131
|
+
child.on('error', () => { });
|
|
132
|
+
child.unref();
|
|
133
|
+
return true;
|
|
134
|
+
}
|
|
135
|
+
catch {
|
|
136
|
+
return false;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGV2aWNlLWF1dGguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdXRpbHMvZGV2aWNlLWF1dGgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsK0NBQStDO0FBQy9DLHNDQUFzQztBQUV0Qzs7Ozs7Ozs7R0FRRztBQUVILE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFFdEMsT0FBTyxLQUFLLE1BQU0sT0FBTyxDQUFDO0FBQzFCLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQW9DL0MsaUZBQWlGO0FBQ2pGLE1BQU0sT0FBTyxlQUFnQixTQUFRLEtBQUs7SUFDRixJQUFJO0lBQTFDLFlBQVksT0FBZSxFQUFXLElBQVk7UUFDaEQsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDO29CQURxQixJQUFJO1FBRXhDLElBQUksQ0FBQyxJQUFJLEdBQUcsaUJBQWlCLENBQUM7SUFDaEMsQ0FBQztDQUNGO0FBRUQsdURBQXVEO0FBQ3ZELE1BQU0sQ0FBQyxLQUFLLFVBQVUsaUJBQWlCLENBQ3JDLFNBQThCLEVBQzlCLE9BQU8sR0FBeUIsRUFBRTtJQUVsQyxNQUFNLE9BQU8sR0FBRyxHQUFHLFNBQVMsQ0FBQyxHQUFHLHVCQUF1QixDQUFDO0lBQ3hELFVBQVUsQ0FBQyxNQUFNLEVBQUUsRUFBRSxHQUFHLEVBQUUsT0FBTyxFQUFFLENBQUMsQ0FBQztJQUNyQyxNQUFNLFFBQVEsR0FBRyxNQUFNLEtBQUssQ0FBQyxJQUFJLENBQy9CLE9BQU8sRUFDUCxFQUFFLEdBQUcsQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFDaEQ7UUFDRSxPQUFPLEVBQUUsRUFBRSxjQUFjLEVBQUUsa0JBQWtCLEVBQUUsYUFBYSxFQUFFLEtBQUssRUFBRTtRQUNyRSxVQUFVLEVBQUUsU0FBUyxDQUFD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QVEsSUFBSSxNQUFNLENBQUMsUUFBUSxLQUFLLE9BQU87UUFBRSxPQUFPLEtBQUssQ0FBQztJQUM5RSxJQUFJLE9BQU8sQ0FBQyxHQUFHLENBQUMsRUFBRSxJQUFJLE9BQU8sQ0FBQyxHQUFHLENBQUMsY0FBYyxJQUFJLE9BQU8sQ0FBQyxHQUFHLENBQUMsT0FBTztRQUFFLE9BQU8sS0FBSyxDQUFDO0lBQ3RGLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLEtBQUs7UUFBRSxPQUFPLEtBQUssQ0FBQztJQUV4QyxNQUFNLE1BQU0sR0FBRyxXQUFXLEVBQUUsQ0FBQztJQUM3QixJQUFJLENBQUMsTUFBTTtRQUFFLE9BQU8sS0FBSyxDQUFDO0lBRTFCLElBQUksQ0FBQztRQUNILE1BQU0sS0FBSyxHQUFHLEtBQUssQ0FBQyxNQUFNLENBQUMsT0FBTyxFQUFFLENBQUMsR0FBRyxNQUFNLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxFQUFFLEVBQUUsS0FBSyxFQUFFLFFBQVEsRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztRQUNoRyxLQUFLLENBQUMsRUFBRSxDQUFDLE9BQU8sRUFBRSxHQUFHLEVBQUUsR0FBMEQsQ0FBQyxDQUFDLENBQUM7UUFDcEYsS0FBSyxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQ2QsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBQUMsTUFBTSxDQUFDO1FBQ1AsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0FBQ0gsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAyMDI2IFBpcGVsaW5lIEJ1aWxkZXIgQ29udHJpYnV0b3JzXG4vLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuXG4vKipcbiAqIE9BdXRoIDIuMCBkZXZpY2UgYXV0aG9yaXphdGlvbiBncmFudCBjbGllbnQgKFJGQyA4NjI4KSDigJQgaG93IHRoZSBDTEkgc2lnbnMgaW4uXG4gKlxuICogVGhlIENMSSBhc2tzIHRoZSBwbGF0Zm9ybSBmb3IgYSBjb2RlLCBzaG93cyBpdCAoYW5kIG9wZW5zIHRoZSBicm93c2VyIHdoZW4gaXRcbiAqIGNhbiksIHRoZW4gcG9sbHMgdW50aWwgdGhlIHBlcnNvbiBhcHByb3ZlcyBpbiB0aGF0IGJyb3dzZXIuIE5vIHBhc3N3b3JkIGFuZCBub1xuICogbG9uZy1saXZlZCB0b2tlbiBldmVyIHBhc3NlcyB0aHJvdWdoIHRoZSBjb21tYW5kIGxpbmUsIHNoZWxsIGhpc3RvcnksIGBwc2BcbiAqIG91dHB1dCBvciBhIENJIGxvZzsgdGhlIGJyb3dzZXIgaXMgd2hlcmUgU1NPLCBzdGVwLXVwIGFuZCBsYXRlciBNRkEgYWxyZWFkeVxuICogYXBwbHksIHNvIHRoZSB0ZXJtaW5hbCBpbmhlcml0cyBhbGwgb2YgaXQgd2l0aG91dCBpbXBsZW1lbnRpbmcgYW55IG9mIGl0LlxuICovXG5cbmltcG9ydCB7IHNwYXduIH0gZnJvbSAnY2hpbGRfcHJvY2Vzcyc7XG5pbXBvcnQgdHlwZSBodHRwcyBmcm9tICdodHRwcyc7XG5pbXBvcnQgYXhpb3MgZnJvbSAnYXhpb3MnO1xuaW1wb3J0IHsgcHJpbnREZWJ1ZyB9IGZyb20gJy4vb3V0cHV0LXV0aWxzLmpzJztcblxuLyoqIGBQT1NUIC9hdXRoL2RldmljZS9jb2RlYCDigJQgUkZDIDg2MjggwqczLjIuICovXG5leHBvcnQgaW50ZXJmYWNlIERldmljZUNvZGVSZXNwb25zZSB7XG4gIGRldmljZV9jb2RlOiBzdHJpbmc7XG4gIHVzZXJfY29kZTogc3RyaW5nO1xuICB2ZXJpZmljYXRpb25fdXJpOiBzdHJpbmc7XG4gIHZlcmlmaWNhdGlvbl91cmlfY29tcGxldGU/OiBzdHJpbmc7XG4gIGV4cGlyZXNfaW46IG51bWJlcjtcbiAgaW50ZXJ2YWw6IG51bWJlcjtcbn1cblxuLyoqIGBQT1NUIC9hdXRoL2RldmljZS90b2tlbmAgb24gc3VjY2VzcyDigJQgUkZDIDg2MjggwqczLjUuICovXG5leHBvcnQgaW50ZXJmYWNlIERldmljZVRva2VuUmVzcG9uc2Uge1xuICBhY2Nlc3NfdG9rZW46IHN0cmluZztcbiAgcmVmcmVzaF90b2tlbj86IHN0cmluZztcbiAgdG9rZW5fdHlwZTogc3RyaW5nO1xuICBleHBpcmVzX2luOiBudW1iZXI7XG4gIC8qKiBQcmVzZW50IG9ubHkgd2hlbiB0aGUgZGV2aWNlIGFza2VkIGZvciBvbmUgYXQgYC9jb2RlYCAoYGF1dGggcGF0YCkuICovXG4gIHN0ZXBfdXBfdG9rZW4/OiBzdHJpbmc7XG59XG5cbi8qKiBUaGUgUkZDIGVycm9yIGJvZHksIHBsdXMgdGhlIGBpbnRlcnZhbGAgdGhlIHBsYXRmb3JtIHNlbmRzIHdpdGggYHNsb3dfZG93bmAuICovXG5pbnRlcmZhY2UgRGV2aWNlRXJyb3JSZXNwb25zZSB7XG4gIGVycm9yPzogc3RyaW5nO1xuICBlcnJvcl9kZXNjcmlwdGlvbj86IHN0cmluZztcbiAgaW50ZXJ2YWw/OiBudW1iZXI7XG59XG5cbi8qKiBDb25uZWN0aW9uIHNldHRpbmdzIHNoYXJlZCBieSBib3RoIGNhbGxzLiAqL1xuZXhwb3J0IGludGVyZmFjZSBEZXZpY2VBdXRoVHJhbnNwb3J0IHtcbiAgdXJsOiBzdHJpbmc7XG4gIGh0dHBzQWdlbnQ6IGh0dHBzLkFnZW50O1xuICB0aW1lb3V0OiBudW1iZXI7XG59XG5cbi8qKiBSYWlzZWQgZm9yIGV2ZXJ5IHRlcm1pbmFsIG91dGNvbWUsIHNvIGNhbGxlcnMgY2FuIHByaW50IG9uZSBjbGVhciBtZXNzYWdlLiAqL1xuZXhwb3J0IGNsYXNzIERldmljZUF1dGhFcnJvciBleHRlbmRzIEVycm9yIHtcbiAgY29uc3RydWN0b3IobWVzc2FnZTogc3RyaW5nLCByZWFkb25seSBjb2RlOiBzdHJpbmcpIHtcbiAgICBzdXBlcihtZXNzYWdlKTtcbiAgICB0aGlzLm5hbWUgPSAnRGV2aWNlQXV0aEVycm9yJztcbiAgfVxufVxuXG4vKiogQXNrIHRoZSBwbGF0Zm9ybSB0byBvcGVuIGEgZGV2aWNlIGF1dGhvcml6YXRpb24uICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcmVxdWVzdERldmljZUNvZGUoXG4gIHRyYW5zcG9ydDogRGV2aWNlQXV0aFRyYW5zcG9ydCxcbiAgb3B0aW9uczogeyBzdGVwVXA/OiBib29sZWFuIH0gPSB7fSxcbik6IFByb21pc2U8RGV2aWNlQ29kZVJlc3BvbnNlPiB7XG4gIGNvbnN0IGNvZGVVcmwgPSBgJHt0cmFuc3BvcnQudXJsfS9hcGkvYXV0aC9kZXZpY2UvY29kZWA7XG4gIHByaW50RGVidWcoJ1BPU1QnLCB7IHVybDogY29kZVVybCB9KTtcbiAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBheGlvcy5wb3N0PERldmljZUNvZGVSZXNwb25zZT4oXG4gICAgY29kZVVybCxcbiAgICB7IC4uLihvcHRpb25zLnN0ZXBVcCA/IHsgc3RlcF91cDogdHJ1ZSB9IDoge30pIH0sXG4gICAge1xuICAgICAgaGVhZGVyczogeyAnQ29udGVudC1UeXBlJzogJ2FwcGxpY2F0aW9uL2pzb24nLCAnWC1QYi1DbGllbnQnOiAnY2xpJyB9LFxuICAgICAgaHR0cHNBZ2VudDogdHJhbnNwb3J0Lmh0dHBzQWdlbnQsXG4gICAgICB0aW1lb3V0OiB0cmFuc3BvcnQudGltZW91dCxcbiAgICB9LFxuICApO1xuICBjb25zdCBkYXRhID0gcmVzcG9uc2UuZGF0YTtcbiAgaWYgKCFkYXRhPy5kZXZpY2VfY29kZSB8fCAhZGF0YS51c2VyX2NvZGUpIHtcbiAgICB0aHJvdyBuZXcgRGV2aWNlQXV0aEVycm9yKCdUaGUgcGxhdGZvcm0gZGlkIG5vdCByZXR1cm4gYSBkZXZpY2UgY29kZS4nLCAnaW52YWxpZF9yZXNwb25zZScpO1xuICB9XG4gIHJldHVybiBkYXRhO1xufVxuXG4vKiogU2xlZXAsIHdpdGhvdXQgcHVsbGluZyBpbiBhIHRpbWVycyBkZXBlbmRlbmN5LiAqL1xuZnVuY3Rpb24gd2FpdChtczogbnVtYmVyKTogUHJvbWlzZTx2b2lkPiB7XG4gIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4geyBzZXRUaW1lb3V0KHJlc29sdmUsIG1zKTsgfSk7XG59XG5cbi8qKlxuICogUG9sbCBgL2F1dGgvZGV2aWNlL3Rva2VuYCB1bnRpbCB0aGUgYnJvd3NlciBkZWNpZGVzLCB0aGUgY29kZSBleHBpcmVzLCBvclxuICogYHNpZ25hbGAgc2F5cyB0byBzdG9wLlxuICpcbiAqIEludGVydmFsIGhhbmRsaW5nIGlzIHRoZSBSRkMnczogc3RhcnQgYXQgdGhlIGFkdmVydGlzZWQgYGludGVydmFsYCwgYW5kIHdpZGVuXG4gKiBpdCBieSA1IHNlY29uZHMgKG9yIHRvIHdoYXRldmVyIHRoZSBwbGF0Zm9ybSBuYW1lcykgb24gZXZlcnkgYHNsb3dfZG93bmAuIFRoZVxuICogcGxhdGZvcm0gYWxzbyBlbmZvcmNlcyB0aGUgaW50ZXJ2YWwsIHNvIGEgY2xpZW50IHRoYXQgaWdub3JlcyBpdCBpcyB0aHJvdHRsZWRcbiAqIHJhdGhlciB0aGFuIHRydXN0ZWQuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBwb2xsRm9yRGV2aWNlVG9rZW4oXG4gIHRyYW5zcG9ydDogRGV2aWNlQXV0aFRyYW5zcG9ydCxcbiAgY29kZTogRGV2aWNlQ29kZVJlc3BvbnNlLFxuICBob29rczogeyBvblBlbmRpbmc/OiAoKSA9PiB2b2lkIH0gPSB7fSxcbik6IFByb21pc2U8RGV2aWNlVG9rZW5SZXNwb25zZT4ge1xuICBjb25zdCB0b2tlblVybCA9IGAke3RyYW5zcG9ydC51cmx9L2FwaS9hdXRoL2RldmljZS90b2tlbmA7XG4gIGNvbnN0IGRlYWRsaW5lID0gRGF0ZS5ub3coKSArIGNvZGUuZXhwaXJlc19pbiAqIDEwMDA7XG4gIGxldCBpbnRlcnZhbE1zID0gTWF0aC5tYXgoMSwgY29kZS5pbnRlcnZhbCkgKiAxMDAwO1xuXG4gIHdoaWxlIChEYXRlLm5vdygpIDwgZGVhZGxpbmUpIHtcbiAgICBhd2FpdCB3YWl0KGludGVydmFsTXMpO1xuXG4gICAgcHJpbnREZWJ1ZygnUE9TVCcsIHsgdXJsOiB0b2tlblVybCB9KTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGF4aW9zLnBvc3Q8RGV2aWNlVG9rZW5SZXNwb25zZSAmIERldmljZUVycm9yUmVzcG9uc2U+KFxuICAgICAgdG9rZW5VcmwsXG4gICAgICB7IGRldmljZV9jb2RlOiBjb2RlLmRldmljZV9jb2RlIH0sXG4gICAgICB7XG4gICAgICAgIGhlYWRlcnM6IHsgJ0NvbnRlbnQtVHlwZSc6ICdhcHBsaWNhdGlvbi9qc29uJywgJ1gtUGItQ2xpZW50JzogJ2NsaScgfSxcbiAgICAgICAgaHR0cHNBZ2VudDogdHJhbnNwb3J0Lmh0dHBzQWdlbnQsXG4gICAgICAgIHRpbWVvdXQ6IHRyYW5zcG9ydC50aW1lb3V0LFxuICAgICAgICAvLyBUaGUgUkZDJ3MgcGVuZGluZy9iYWNrb2ZmIHNpZ25hbHMgYXJyaXZlIGFzIEhUVFAgNDAwLCB3aGljaCBheGlvcyB3b3VsZFxuICAgICAgICAvLyBvdGhlcndpc2UgdGhyb3c6IHRoZXkgYXJlIHByb3RvY29sIHN0YXRlcywgbm90IGZhaWx1cmVzLlxuICAgICAgICB2YWxpZGF0ZVN0YXR1czogKHN0YXR1cykgPT4gKHN0YXR1cyA+PSAyMDAgJiYgc3RhdHVzIDwgMzAwKSB8fCBzdGF0dXMgPT09IDQwMCxcbiAgICAgIH0sXG4gICAgKTtcblxuICAgIGlmIChyZXNwb25zZS5zdGF0dXMgPT09IDIwMCkge1xuICAgICAgaWYgKCFyZXNwb25zZS5kYXRhPy5hY2Nlc3NfdG9rZW4pIHtcbiAgICAgICAgdGhyb3cgbmV3IERldmljZUF1dGhFcnJvcignVGhlIHBsYXRmb3JtIGFwcHJvdmVkIHRoZSBzaWduLWluIGJ1dCByZXR1cm5lZCBubyB0b2tlbi4nLCAnaW52YWxpZF9yZXNwb25zZScpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3BvbnNlLmRhdGE7XG4gICAgfVxuXG4gICAgc3dpdGNoIChyZXNwb25zZS5kYXRhPy5lcnJvcikge1xuICAgICAgY2FzZSAnYXV0aG9yaXphdGlvbl9wZW5kaW5nJzpcbiAgICAgICAgaG9va3Mub25QZW5kaW5nPy4oKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdzbG93X2Rvd24nOlxuICAgICAgICBpbnRlcnZhbE1zID0gTWF0aC5tYXgoaW50ZXJ2YWxNcyArIDVfMDAwLCAocmVzcG9uc2UuZGF0YS5pbnRlcnZhbCA/PyAwKSAqIDEwMDApO1xuICAgICAgICBwcmludERlYnVnKCdQb2xsaW5nIHNsb3dlZCBieSB0aGUgcGxhdGZvcm0nLCB7IGludGVydmFsTXMgfSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnYWNjZXNzX2RlbmllZCc6XG4gICAgICAgIHRocm93IG5ldyBEZXZpY2VBdXRoRXJyb3IoJ1RoZSBzaWduLWluIHdhcyBkZW5pZWQgaW4gdGhlIGJyb3dzZXIuJywgJ2FjY2Vzc19kZW5pZWQnKTtcbiAgICAgIGNhc2UgJ2V4cGlyZWRfdG9rZW4nOlxuICAgICAgICB0aHJvdyBuZXcgRGV2aWNlQXV0aEVycm9yKCdUaGUgc2lnbi1pbiBjb2RlIGV4cGlyZWQgYmVmb3JlIGl0IHdhcyBhcHByb3ZlZC4nLCAnZXhwaXJlZF90b2tlbicpO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IERldmljZUF1dGhFcnJvcihcbiAgICAgICAgICByZXNwb25zZS5kYXRhPy5lcnJvcl9kZXNjcmlwdGlvbiB8fCAnVGhlIHBsYXRmb3JtIHJlZnVzZWQgdGhlIGRldmljZSBzaWduLWluLicsXG4gICAgICAgICAgcmVzcG9uc2UuZGF0YT8uZXJyb3IgfHwgJ2ludmFsaWRfcmVxdWVzdCcsXG4gICAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgdGhyb3cgbmV3IERldmljZUF1dGhFcnJvcignVGltZWQgb3V0IHdhaXRpbmcgZm9yIHRoZSBzaWduLWluIHRvIGJlIGFwcHJvdmVkLicsICdleHBpcmVkX3Rva2VuJyk7XG59XG5cbi8qKiBUaGUgT1MgY29tbWFuZCB0aGF0IG9wZW5zIGEgVVJMIGluIHRoZSBkZWZhdWx0IGJyb3dzZXIuICovXG5mdW5jdGlvbiBvcGVuQ29tbWFuZCgpOiB7IGNvbW1hbmQ6IHN0cmluZzsgYXJnczogc3RyaW5nW10gfSB8IG51bGwge1xuICBpZiAocHJvY2Vzcy5wbGF0Zm9ybSA9PT0gJ2RhcndpbicpIHJldHVybiB7IGNvbW1hbmQ6ICdvcGVuJywgYXJnczogW10gfTtcbiAgaWYgKHByb2Nlc3MucGxhdGZvcm0gPT09ICd3aW4zMicpIHJldHVybiB7IGNvbW1hbmQ6ICdjbWQnLCBhcmdzOiBbJy9jJywgJ3N0YXJ0JywgJyddIH07XG4gIGlmIChwcm9jZXNzLnBsYXRmb3JtID09PSAnbGludXgnKSByZXR1cm4geyBjb21tYW5kOiAneGRnLW9wZW4nLCBhcmdzOiBbXSB9O1xuICByZXR1cm4gbnVsbDtcbn1cblxuLyoqXG4gKiBUcnkgdG8gb3BlbiBgdXJsYCBpbiB0aGUgZGVmYXVsdCBicm93c2VyLiBSZXR1cm5zIGZhbHNlIOKAlCBuZXZlciB0aHJvd3Mg4oCUIHdoZW5cbiAqIHRoZSBlbnZpcm9ubWVudCBoYXMgbm8gYnJvd3NlciB0byBvcGVuIChhIENJIHJ1bm5lciwgYW4gU1NIIHNlc3Npb24sIGFcbiAqIG5vbi1pbnRlcmFjdGl2ZSBzaGVsbCkgb3IgdGhlIG9wZW5lciBpc24ndCBpbnN0YWxsZWQsIHNvIHRoZSBjYWxsZXIgZmFsbHMgYmFja1xuICogdG8gcHJpbnRpbmcgdGhlIFVSTC5cbiAqXG4gKiBUaGUgVVJMIGlzIHBhc3NlZCBhcyBhbiBBUkdVTUVOVCwgbmV2ZXIgdGhyb3VnaCBhIHNoZWxsLCBhbmQgb25seSBodHRwKHMpIGlzXG4gKiBhY2NlcHRlZDogdGhlIHZhbHVlIGNvbWVzIGZyb20gdGhlIHBsYXRmb3JtJ3MgcmVzcG9uc2UsIGFuZCBoYW5kaW5nIGFuXG4gKiBhcmJpdHJhcnkgc2NoZW1lIHRvIHRoZSBPUyBvcGVuZXIgaXMgaG93IFwiY2xpY2sgdGhpcyBsaW5rXCIgdHVybnMgaW50byBcInJ1blxuICogdGhpcyBwcm9ncmFtXCIuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBvcGVuSW5Ccm93c2VyKHVybDogc3RyaW5nKTogYm9vbGVhbiB7XG4gIGxldCBwYXJzZWQ6IFVSTDtcbiAgdHJ5IHtcbiAgICBwYXJzZWQgPSBuZXcgVVJMKHVybCk7XG4gIH0gY2F0Y2gge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICBpZiAocGFyc2VkLnByb3RvY29sICE9PSAnaHR0cHM6JyAmJiBwYXJzZWQucHJvdG9jb2wgIT09ICdodHRwOicpIHJldHVybiBmYWxzZTtcbiAgaWYgKHByb2Nlc3MuZW52LkNJIHx8IHByb2Nlc3MuZW52LlNTSF9DT05ORUNUSU9OIHx8IHByb2Nlc3MuZW52LlNTSF9UVFkpIHJldHVybiBmYWxzZTtcbiAgaWYgKCFwcm9jZXNzLnN0ZG91dC5pc1RUWSkgcmV0dXJuIGZhbHNlO1xuXG4gIGNvbnN0IG9wZW5lciA9IG9wZW5Db21tYW5kKCk7XG4gIGlmICghb3BlbmVyKSByZXR1cm4gZmFsc2U7XG5cbiAgdHJ5IHtcbiAgICBjb25zdCBjaGlsZCA9IHNwYXduKG9wZW5lci5jb21tYW5kLCBbLi4ub3BlbmVyLmFyZ3MsIHVybF0sIHsgc3RkaW86ICdpZ25vcmUnLCBkZXRhY2hlZDogdHJ1ZSB9KTtcbiAgICBjaGlsZC5vbignZXJyb3InLCAoKSA9PiB7IC8qIG5vIGJyb3dzZXIgaGVyZTsgdGhlIHByaW50ZWQgVVJMIGlzIHRoZSBmYWxsYmFjayAqLyB9KTtcbiAgICBjaGlsZC51bnJlZigpO1xuICAgIHJldHVybiB0cnVlO1xuICB9IGNhdGNoIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn1cbiJdfQ==
|
|
@@ -43,7 +43,7 @@ export async function printResolvedOrExit(propsWithIds) {
|
|
|
43
43
|
const { resolveSelfReferencing } = await import('@pipeline-builder/pipeline-core');
|
|
44
44
|
const scope = { metadata: propsWithIds.metadata ?? {}, vars: propsWithIds.vars ?? {} };
|
|
45
45
|
const isTpl = (f) => f === 'projectName' || f.startsWith('metadata.') || f.startsWith('vars.');
|
|
46
|
-
const result = resolveSelfReferencing(propsWithIds, scope, isTpl, (f) => (isTpl(f) ? f : null)
|
|
46
|
+
const result = resolveSelfReferencing(propsWithIds, scope, isTpl, (f) => (isTpl(f) ? f : null));
|
|
47
47
|
if (result.errors.length) {
|
|
48
48
|
console.error('Resolution errors:');
|
|
49
49
|
for (const e of result.errors)
|
|
@@ -52,4 +52,4 @@ export async function printResolvedOrExit(propsWithIds) {
|
|
|
52
52
|
}
|
|
53
53
|
console.log(JSON.stringify(propsWithIds, null, 2));
|
|
54
54
|
}
|
|
55
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
55
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGlwZWxpbmUtY29uZmlnLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3V0aWxzL3BpcGVsaW5lLWNvbmZpZy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwrQ0FBK0M7QUFDL0Msc0NBQXNDO0FBU3RDLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUM5QyxPQUFPLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUM5RCxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDckQsT0FBTyxFQUFFLHFCQUFxQixFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFZNUQ7Ozs7Ozs7O0dBUUc7QUFDSCxNQUFNLENBQUMsS0FBSyxVQUFVLGtCQUFrQixDQUFDLE1BQWlCLEVBQUUsVUFBa0I7SUFDNUUsTUFBTSxNQUFNLEdBQUcsTUFBTSxDQUFDLFNBQVMsRUFBRSxDQUFDO0lBQ2xDLE1BQU0sUUFBUSxHQUFHLE1BQU0sTUFBTSxDQUFDLEdBQUcsQ0FBMEIsR0FBRyxNQUFNLENBQUMsR0FBRyxDQUFDLFdBQVcsSUFBSSxVQUFVLEVBQUUsQ0FBQyxDQUFDO0lBQ3RHLE1BQU0sUUFBUSxHQUFHLHFCQUFxQixDQUFXLFFBQVEsRUFBRSxVQUFVLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFDaEYsSUFBSSxDQUFDLFFBQVEsRUFBRSxLQUFLLEVBQUUsQ0FBQztRQUNyQixNQUFNLElBQUksS0FBSyxDQUFDLDZDQUE2QyxVQUFVLEVBQUUsQ0FBQyxDQUFDO0lBQzdFLENBQUM7SUFFRCxNQUFNLFlBQVksR0FBNEI7UUFDNUMsR0FBSSxRQUFRLENBQUMsS0FBaUM7UUFDOUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxFQUFFLFFBQVEsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1FBQ3BELFVBQVUsRUFBRSxRQUFRLENBQUMsRUFBRSxJQUFJLFVBQVU7S0FDdEMsQ0FBQztJQUVGLE1BQU0sZUFBZSxHQUFHLE1BQU0sc0JBQXNCLENBQUMsTUFBTSxFQUFFLFlBQVksQ0FBQyxDQUFDO0lBQzNFLElBQUksTUFBTSxDQUFDLElBQUksQ0FBQyxlQUFlLENBQUMsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFLENBQUM7UUFDNUMsWUFBWSxDQUFDLGVBQWUsR0FBRyxlQUFlLENBQUM7UUFDL0MsU0FBUyxDQUFDLHNCQUFzQixFQUFFLEVBQUUsS0FBSyxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQztJQUNwRixDQUFDO0lBRUQsb0JBQW9CLENBQUMsWUFBWSxFQUFFLE1BQU0sQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDdkQsT0FBTyxFQUFFLFFBQVEsRUFBRSxZQUFZLEVBQUUsT0FBTyxFQUFFLE1BQU0sQ0FBQyxHQUFHLENBQUMsT0FBTyxFQUFFLENBQUM7QUFDakUsQ0FBQztBQUVEOzs7OztHQUtHO0FBQ0gsTUFBTSxDQUFDLEtBQUssVUFBVSxtQkFBbUIsQ0FBQyxZQUFxQztJQUM3RSxNQUFNLEVBQUUsc0JBQXNCLEVBQUUsR0FBRyxNQUFNLE1BQU0sQ0FBQyxpQ0FBaUMsQ0FBQyxDQUFDO0lBQ25GLE1BQU0sS0FBSyxHQUFHLEVBQUUsUUFBUSxFQUFFLFlBQVksQ0FBQyxRQUFRLElBQUksRUFBRSxFQUFFLElBQUksRUFBRSxZQUFZLENBQUMsSUFBSSxJQUFJLEVBQUUsRUFBRSxDQUFDO0lBQ3ZGLE1BQU0sS0FBSyxHQUFHLENBQUMsQ0FBUyxFQUFFLEVBQUUsQ0FBQyxDQUFDLEtBQUssYUFBYSxJQUFJLENBQUMsQ0FBQyxVQUFVLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUN2RyxNQUFNLE1BQU0sR0FBRyxzQkFBc0IsQ0FBQyxZQUFZLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxDQUFDLENBQVMsRUFBRSxFQUFFLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztJQUN4RyxJQUFJLE1BQU0sQ0FBQyxNQUFNLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDekIsT0FBTyxDQUFDLEtBQUssQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDO1FBQ3BDLEtBQUssTUFBTSxDQUFDLElBQUksTUFBTSxDQUFDLE1BQU07WUFBRSxPQUFPLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLEtBQUssSUFBSSxHQUFHLEtBQUssQ0FBQyxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUM7UUFDbkYsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNsQixDQUFDO0lBQ0QsT0FBTyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLFlBQVksRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUNyRCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IDIwMjYgUGlwZWxpbmUgQnVpbGRlciBDb250cmlidXRvcnNcbi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG5cbi8qKlxuICogU2hhcmVkIHBpcGVsaW5lLWNvbmZpZyByZXNvbHV0aW9uIHVzZWQgYnkgYm90aCBgc3ludGhgIGFuZCBgZGVwbG95YCBzbyB0aGUgdHdvXG4gKiBjb21tYW5kcyBmZXRjaCwgcGx1Z2luLXJlc29sdmUsIHJlZ2lzdHJ5LWJha2UsIGFuZCB0ZW1wbGF0ZS1wcmV2aWV3IGlkZW50aWNhbGx5XG4gKiAodGhleSBwcmV2aW91c2x5IGtlcHQgbmVhci1kdXBsaWNhdGUgY29waWVzIHRoYXQgY291bGQgZHJpZnQpLlxuICovXG5cbmltcG9ydCB0eXBlIHsgQXBpQ2xpZW50IH0gZnJvbSAnLi9hcGktY2xpZW50LmpzJztcbmltcG9ydCB7IHByaW50SW5mbyB9IGZyb20gJy4vb3V0cHV0LXV0aWxzLmpzJztcbmltcG9ydCB7IHJlc29sdmVQbHVnaW5zRm9yUHJvcHMgfSBmcm9tICcuL3BsdWdpbi1yZXNvbHZlci5qcyc7XG5pbXBvcnQgeyBiYWtlUGxhdGZvcm1SZWdpc3RyeSB9IGZyb20gJy4vcmVnaXN0cnkuanMnO1xuaW1wb3J0IHsgZXh0cmFjdFNpbmdsZVJlc3BvbnNlIH0gZnJvbSAnLi9yZXNwb25zZS11dGlscy5qcyc7XG5pbXBvcnQgdHlwZSB7IFBpcGVsaW5lIH0gZnJvbSAnLi4vdHlwZXMvcGlwZWxpbmUuanMnO1xuXG5leHBvcnQgaW50ZXJmYWNlIEZldGNoZWRQaXBlbGluZSB7XG4gIC8qKiBUaGUgcmF3IHBpcGVsaW5lIHJlY29yZCAoaWQvb3JnL3Byb2plY3QvZmxhZ3MpIGFzIHJldHVybmVkIGJ5IHRoZSBwbGF0Zm9ybS4gKi9cbiAgcmVhZG9ubHkgcGlwZWxpbmU6IFBpcGVsaW5lO1xuICAvKiogcHJvcHMgKyBwaXBlbGluZUlkICgrIG9yZ0lkKSArIHJlc29sdmVkUGx1Z2lucywgd2l0aCB0aGUgcmVnaXN0cnkgcHVsbC1ob3N0IGJha2VkIGluLiAqL1xuICByZWFkb25seSBwcm9wc1dpdGhJZHM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICAvKiogVGhlIHJlc29sdmVkIHBsYXRmb3JtIGJhc2UgVVJMIHRoZSBjb25maWcgd2FzIGZldGNoZWQgYWdhaW5zdC4gKi9cbiAgcmVhZG9ubHkgYmFzZVVybDogc3RyaW5nO1xufVxuXG4vKipcbiAqIEZldGNoIGEgcGlwZWxpbmUgYnkgaWQgYW5kIGJ1aWxkIHRoZSBzeW50aC9kZXBsb3kgcHJvcHM6XG4gKiAgLSBHRVQgdGhlIHBpcGVsaW5lIGFuZCB2YWxpZGF0ZSBpdCBoYXMgYHByb3BzYCxcbiAqICAtIGFzc2VtYmxlIGBwcm9wc1dpdGhJZHNgIChwcm9wcyArIHBpcGVsaW5lSWQgKyBvcmdJZCksXG4gKiAgLSBwcmUtcmVzb2x2ZSBwbHVnaW5zIHNvIHRoZSB0ZW1wbGF0ZSBzaGlwcyByZWFsIENvZGVCdWlsZCBpbWFnZSBVUklzXG4gKiAgICAob3RoZXJ3aXNlIENESyBmYWxscyBiYWNrIHRvIHN0YW5kYXJkOjcuMCBhdCBkZXBsb3kgdGltZSksXG4gKiAgLSBiYWtlIHRoZSByZWdpc3RyeSBwdWxsLWhvc3QgZnJvbSB0aGUgcGxhdGZvcm0gVVJMIChuby1vcCB3aGVuXG4gKiAgICBJTUFHRV9SRUdJU1RSWV9QVUxMX0hPU1QgaXMgc2V0KS5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGZldGNoUGlwZWxpbmVQcm9wcyhjbGllbnQ6IEFwaUNsaWVudCwgcGlwZWxpbmVJZDogc3RyaW5nKTogUHJvbWlzZTxGZXRjaGVkUGlwZWxpbmU+IHtcbiAgY29uc3QgY29uZmlnID0gY2xpZW50LmdldENvbmZpZygpO1xuICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGNsaWVudC5nZXQ8UmVjb3JkPHN0cmluZywgdW5rbm93bj4+KGAke2NvbmZpZy5hcGkucGlwZWxpbmVVcmx9LyR7cGlwZWxpbmVJZH1gKTtcbiAgY29uc3QgcGlwZWxpbmUgPSBleHRyYWN0U2luZ2xlUmVzcG9uc2U8UGlwZWxpbmU+KHJlc3BvbnNlLCAncGlwZWxpbmUnLCAncHJvcHMnKTtcbiAgaWYgKCFwaXBlbGluZT8ucHJvcHMpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYEZhaWxlZCB0byByZXRyaWV2ZSBwaXBlbGluZSBwcm9wcyBmb3IgSUQ6ICR7cGlwZWxpbmVJZH1gKTtcbiAgfVxuXG4gIGNvbnN0IHByb3BzV2l0aElkczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4gPSB7XG4gICAgLi4uKHBpcGVsaW5lLnByb3BzIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+KSxcbiAgICAuLi4ocGlwZWxpbmUub3JnSWQgPyB7IG9yZ0lkOiBwaXBlbGluZS5vcmdJZCB9IDoge30pLFxuICAgIHBpcGVsaW5lSWQ6IHBpcGVsaW5lLmlkIHx8IHBpcGVsaW5lSWQsXG4gIH07XG5cbiAgY29uc3QgcmVzb2x2ZWRQbHVnaW5zID0gYXdhaXQgcmVzb2x2ZVBsdWdpbnNGb3JQcm9wcyhjbGllbnQsIHByb3BzV2l0aElkcyk7XG4gIGlmIChPYmplY3Qua2V5cyhyZXNvbHZlZFBsdWdpbnMpLmxlbmd0aCA+IDApIHtcbiAgICBwcm9wc1dpdGhJZHMucmVzb2x2ZWRQbHVnaW5zID0gcmVzb2x2ZWRQbHVnaW5zO1xuICAgIHByaW50SW5mbygnUHJlLXJlc29sdmVkIHBsdWdpbnMnLCB7IGNvdW50OiBPYmplY3Qua2V5cyhyZXNvbHZlZFBsdWdpbnMpLmxlbmd0aCB9KTtcbiAgfVxuXG4gIGJha2VQbGF0Zm9ybVJlZ2lzdHJ5KHByb3BzV2l0aElkcywgY29uZmlnLmFwaS5iYXNlVXJsKTtcbiAgcmV0dXJuIHsgcGlwZWxpbmUsIHByb3BzV2l0aElkcywgYmFzZVVybDogY29uZmlnLmFwaS5iYXNlVXJsIH07XG59XG5cbi8qKlxuICogQXBwbHkgcGFzcy0xIHNlbGYtcmVmZXJlbmNpbmcgdGVtcGxhdGUgcmVzb2x1dGlvbiB0byBgcHJvcHNXaXRoSWRzYCBhbmQgcHJpbnQgaXRcbiAqIHRvIHN0ZG91dCAodXNlZCBieSBgc3ludGggLS1zaG93LXJlc29sdmVkYCAvIGBkZXBsb3kgLS1zaG93LXJlc29sdmVkYCkuIEV4aXRzIHdpdGhcbiAqIGNvZGUgMSBpZiByZXNvbHV0aW9uIHJlcG9ydHMgZXJyb3JzLiBgcmVzb2x2ZVNlbGZSZWZlcmVuY2luZ2AgbXV0YXRlcyB0aGUgb2JqZWN0XG4gKiBpbiBwbGFjZSwgc28gdGhlIHByaW50ZWQgSlNPTiByZWZsZWN0cyB0aGUgZXhwYW5kZWQgdGVtcGxhdGVzLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcHJpbnRSZXNvbHZlZE9yRXhpdChwcm9wc1dpdGhJZHM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KTogUHJvbWlzZTx2b2lkPiB7XG4gIGNvbnN0IHsgcmVzb2x2ZVNlbGZSZWZlcmVuY2luZyB9ID0gYXdhaXQgaW1wb3J0KCdAcGlwZWxpbmUtYnVpbGRlci9waXBlbGluZS1jb3JlJyk7XG4gIGNvbnN0IHNjb3BlID0geyBtZXRhZGF0YTogcHJvcHNXaXRoSWRzLm1ldGFkYXRhID8/IHt9LCB2YXJzOiBwcm9wc1dpdGhJZHMudmFycyA/PyB7fSB9O1xuICBjb25zdCBpc1RwbCA9IChmOiBzdHJpbmcpID0+IGYgPT09ICdwcm9qZWN0TmFtZScgfHwgZi5zdGFydHNXaXRoKCdtZXRhZGF0YS4nKSB8fCBmLnN0YXJ0c1dpdGgoJ3ZhcnMuJyk7XG4gIGNvbnN0IHJlc3VsdCA9IHJlc29sdmVTZWxmUmVmZXJlbmNpbmcocHJvcHNXaXRoSWRzLCBzY29wZSwgaXNUcGwsIChmOiBzdHJpbmcpID0+IChpc1RwbChmKSA/IGYgOiBudWxsKSk7XG4gIGlmIChyZXN1bHQuZXJyb3JzLmxlbmd0aCkge1xuICAgIGNvbnNvbGUuZXJyb3IoJ1Jlc29sdXRpb24gZXJyb3JzOicpO1xuICAgIGZvciAoY29uc3QgZSBvZiByZXN1bHQuZXJyb3JzKSBjb25zb2xlLmVycm9yKGAgIFske2UuZmllbGQgPz8gJz8nfV0gJHtlLm1lc3NhZ2V9YCk7XG4gICAgcHJvY2Vzcy5leGl0KDEpO1xuICB9XG4gIGNvbnNvbGUubG9nKEpTT04uc3RyaW5naWZ5KHByb3BzV2l0aElkcywgbnVsbCwgMikpO1xufVxuIl19
|
|
@@ -1,10 +1,28 @@
|
|
|
1
1
|
/** Login/secret options shared across the platform-secret helpers. */
|
|
2
2
|
export interface PlatformSecretOptions {
|
|
3
|
-
/**
|
|
3
|
+
/**
|
|
4
|
+
* Login identifier (username OR email) for the NON-INTERACTIVE machine login
|
|
5
|
+
* below. This is the only password path left in the CLI: `auth login` and
|
|
6
|
+
* `auth pat` sign in through the browser (device authorization), but
|
|
7
|
+
* `store-token` / `setup-events` run on hosts with nobody present to approve a
|
|
8
|
+
* code, and what they mint is a machine credential, not a person's session.
|
|
9
|
+
*/
|
|
4
10
|
readonly identifier?: string;
|
|
5
11
|
readonly password?: string;
|
|
6
12
|
readonly verifySsl?: boolean;
|
|
7
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* The Secrets Manager path a stored machine credential lives at:
|
|
16
|
+
* `{SECRETS_PATH_PREFIX}/{orgId}/{leaf}`.
|
|
17
|
+
*
|
|
18
|
+
* `leaf` is `platform` for the org's full-privilege automation credential, and
|
|
19
|
+
* the scope's slug (`reporting-ingest`, `registry-push`) for a least-privilege
|
|
20
|
+
* one — so a scoped credential can never clobber the platform one, and the
|
|
21
|
+
* events Lambda's secret is a different object from CodeBuild's.
|
|
22
|
+
*/
|
|
23
|
+
export declare function secretNameForOrg(orgId: string, leaf?: string): string;
|
|
24
|
+
/** A capability scope as a secret-path leaf: `reporting:ingest` → `reporting-ingest`. */
|
|
25
|
+
export declare function scopeSecretLeaf(scope: string): string;
|
|
8
26
|
/**
|
|
9
27
|
* Derive the platform secret path from a JWT's organizationId.
|
|
10
28
|
* Pattern: `{SECRETS_PATH_PREFIX}/{orgId}/platform`.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"platform-secret.d.ts","sourceRoot":"","sources":["../../src/utils/platform-secret.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"platform-secret.d.ts","sourceRoot":"","sources":["../../src/utils/platform-secret.ts"],"names":[],"mappings":"AAmBA,sEAAsE;AACtE,MAAM,WAAW,qBAAqB;IACpC;;;;;;OAMG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,GAAE,MAAmB,GAAG,MAAM,CAEjF;AAED,yFAAyF;AACzF,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAErD;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAevD;AAED;;;;;GAKG;AACH,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAyCvF;AAED;;;;GAIG;AACH,wBAAsB,yBAAyB,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,MAAM,CAAC,CAY/F"}
|
|
@@ -7,24 +7,47 @@
|
|
|
7
7
|
* lives here once: derive `{SECRETS_PATH_PREFIX}/{orgId}/platform` from the JWT's
|
|
8
8
|
* organizationId, logging in first if needed to obtain the token.
|
|
9
9
|
*/
|
|
10
|
+
import { isOpaqueApiKey } from '@pipeline-builder/api-core';
|
|
10
11
|
import { CoreConstants } from '@pipeline-builder/pipeline-core';
|
|
11
12
|
import axios from 'axios';
|
|
12
13
|
import { decodeTokenPayload } from './auth-guard.js';
|
|
13
14
|
import { getApiConfig } from './config-loader.js';
|
|
14
15
|
import { printInfo, printSection, printSuccess, printWarning } from './output-utils.js';
|
|
15
16
|
import { assertSslDisableAllowed } from './tls.js';
|
|
17
|
+
/**
|
|
18
|
+
* The Secrets Manager path a stored machine credential lives at:
|
|
19
|
+
* `{SECRETS_PATH_PREFIX}/{orgId}/{leaf}`.
|
|
20
|
+
*
|
|
21
|
+
* `leaf` is `platform` for the org's full-privilege automation credential, and
|
|
22
|
+
* the scope's slug (`reporting-ingest`, `registry-push`) for a least-privilege
|
|
23
|
+
* one — so a scoped credential can never clobber the platform one, and the
|
|
24
|
+
* events Lambda's secret is a different object from CodeBuild's.
|
|
25
|
+
*/
|
|
26
|
+
export function secretNameForOrg(orgId, leaf = 'platform') {
|
|
27
|
+
return `${CoreConstants.SECRETS_PATH_PREFIX}/${orgId}/${leaf}`;
|
|
28
|
+
}
|
|
29
|
+
/** A capability scope as a secret-path leaf: `reporting:ingest` → `reporting-ingest`. */
|
|
30
|
+
export function scopeSecretLeaf(scope) {
|
|
31
|
+
return scope.replace(/[^a-z0-9]+/gi, '-');
|
|
32
|
+
}
|
|
16
33
|
/**
|
|
17
34
|
* Derive the platform secret path from a JWT's organizationId.
|
|
18
35
|
* Pattern: `{SECRETS_PATH_PREFIX}/{orgId}/platform`.
|
|
19
36
|
* @throws if the token carries no organizationId (caller should fall back to PLATFORM_SECRET_NAME).
|
|
20
37
|
*/
|
|
21
38
|
export function resolveSecretName(token) {
|
|
39
|
+
// An ACCESS KEY (`pb_pat_…`) is opaque — it carries no org claim to read, by
|
|
40
|
+
// design. Say so instead of the generic decode failure, since exporting a key
|
|
41
|
+
// as PLATFORM_TOKEN is now the normal way to authenticate the CLI.
|
|
42
|
+
if (isOpaqueApiKey(token)) {
|
|
43
|
+
throw new Error('PLATFORM_TOKEN is an opaque access key, which carries no organizationId — set PLATFORM_SECRET_NAME to name the secret explicitly.');
|
|
44
|
+
}
|
|
22
45
|
const payload = decodeTokenPayload(token);
|
|
23
46
|
const orgId = payload?.organizationId;
|
|
24
47
|
if (!orgId) {
|
|
25
48
|
throw new Error('Token does not contain organizationId — cannot derive secret name. Set PLATFORM_SECRET_NAME to specify it explicitly.');
|
|
26
49
|
}
|
|
27
|
-
return
|
|
50
|
+
return secretNameForOrg(orgId);
|
|
28
51
|
}
|
|
29
52
|
/**
|
|
30
53
|
* Ensure `process.env.PLATFORM_TOKEN` is set. No-op if it already is. Otherwise,
|
|
@@ -57,8 +80,7 @@ export async function ensurePlatformToken(options) {
|
|
|
57
80
|
const rejectUnauthorized = options.verifySsl === false ? false : apiConfig.api.rejectUnauthorized;
|
|
58
81
|
const loginResponse = await axios.post(`${apiConfig.api.baseUrl}/api/auth/login`,
|
|
59
82
|
// The server's loginSchema requires `identifier` (email OR username), not
|
|
60
|
-
// `email` — sending `email` fails zod validation with a 400.
|
|
61
|
-
// canonical `postLogin` body.
|
|
83
|
+
// `email` — sending `email` fails zod validation with a 400.
|
|
62
84
|
{ identifier: loginIdentifier, password: loginPassword }, {
|
|
63
85
|
httpsAgent: rejectUnauthorized === false
|
|
64
86
|
? new (await import('https')).Agent({ rejectUnauthorized: false })
|
|
@@ -89,4 +111,4 @@ export async function resolvePlatformSecretName(options) {
|
|
|
89
111
|
}
|
|
90
112
|
return resolveSecretName(process.env.PLATFORM_TOKEN);
|
|
91
113
|
}
|
|
92
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGxhdGZvcm0tc2VjcmV0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3V0aWxzL3BsYXRmb3JtLXNlY3JldC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwrQ0FBK0M7QUFDL0Msc0NBQXNDO0FBRXRDOzs7Ozs7R0FNRztBQUVILE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUNoRSxPQUFPLEtBQUssTUFBTSxPQUFPLENBQUM7QUFDMUIsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDckQsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQ2xELE9BQU8sRUFBRSxTQUFTLEVBQUUsWUFBWSxFQUFFLFlBQVksRUFBRSxZQUFZLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUN4RixPQUFPLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFVbkQ7Ozs7R0FJRztBQUNILE1BQU0sVUFBVSxpQkFBaUIsQ0FBQyxLQUFhO0lBQzdDLE1BQU0sT0FBTyxHQUFHLGtCQUFrQixDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQzFDLE1BQU0sS0FBSyxHQUFHLE9BQU8sRUFBRSxjQUFjLENBQUM7SUFDdEMsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQ1gsTUFBTSxJQUFJLEtBQUssQ0FBQyx1SEFBdUgsQ0FBQyxDQUFDO0lBQzNJLENBQUM7SUFDRCxPQUFPLEdBQUcsYUFBYSxDQUFDLG1CQUFtQixJQUFJLEtBQUssV0FBVyxDQUFDO0FBQ2xFLENBQUM7QUFFRDs7Ozs7R0FLRztBQUNILE1BQU0sQ0FBQyxLQUFLLFVBQVUsbUJBQW1CLENBQUMsT0FBOEI7SUFDdEUsSUFBSSxPQUFPLENBQUMsR0FBRyxDQUFDLGNBQWM7UUFBRSxPQUFPO0lBQ3ZDLE1BQU0sZUFBZSxHQUFHLE9BQU8sQ0FBQyxVQUFVLElBQUksT0FBTyxDQUFDLEdBQUcsQ0FBQyxtQkFBbUIsQ0FBQztJQUM5RSxNQUFNLGFBQWEsR0FBRyxPQUFPLENBQUMsUUFBUSxJQUFJLE9BQU8sQ0FBQyxHQUFHLENBQUMsaUJBQWlCLENBQUM7SUFDeEUsSUFBSSxDQUFDLGVBQWUsSUFBSSxDQUFDLGFBQWE7UUFBRSxPQUFPO0lBRS9DLElBQUksT0FBTyxDQUFDLFFBQVEsRUFBRSxDQUFDO1FBQ3JCLFlBQVksQ0FBQywrR0FBK0csQ0FBQyxDQUFDO0lBQ2hJLENBQUM7SUFFRCxZQUFZLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDdEIsU0FBUyxDQUFDLDRDQUE0QyxDQUFDLENBQUM7SUFDeEQsd0VBQXdFO0lBQ3hFLDJFQUEyRTtJQUMzRSwrRUFBK0U7SUFDL0UsTUFBTSxTQUFTLEdBQUcsWUFBWSxFQUFFLENBQUM7SUFDakMseUVBQXlFO0lBQ3pFLDZFQUE2RTtJQUM3RSx1RUFBdUU7SUFDdkUsSUFBSSxPQUFPLENBQUMsU0FBUyxLQUFLLEtBQUssRUFBRSxDQUFDO1FBQ2hDLHVCQUF1QixDQUFDLGNBQWMsQ0FBQyxDQUFDO0lBQzFDLENBQUM7SUFDRCxNQUFNLGtCQUFrQixHQUFHLE9BQU8sQ0FBQyxTQUFTLEtBQUssS0FBSyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsa0JBQWtCLENBQUM7SUFDbEcsTUFBTSxhQUFhLEdBQUcsTUFBTSxLQUFLLENBQUMsSUFBSSxDQUNwQyxHQUFHLFNBQVMsQ0FBQyxHQUFHLENBQUMsT0FBTyxpQkFBaUI7SUFDekMsMEVBQTBFO0lBQzFFLHdFQUF3RTtJQUN4RSw4QkFBOEI7SUFDOUIsRUFBRSxVQUFVLEVBQUUsZUFBZSxFQUFFLFFBQVEsRUFBRSxhQUFhLEVBQUUsRUFDeEQ7UUFDRSxVQUFVLEVBQUUsa0JBQWtCLEtBQUssS0FBSztZQUN0QyxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQU0sTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLEVBQUUsa0JBQWtCLEVBQUUsS0FBSyxFQUFFLENBQUM7WUFDbEUsQ0FBQyxDQUFDLFNBQVM7S0FDZCxDQUNGLENBQUM7SUFDRixNQUFNLFNBQVMsR0FBRyxhQUFhLENBQUMsSUFBSSxFQUFFLElBQUksSUFBSSxhQUFhLENBQUMsSUFBSSxDQUFDO0lBQ2pFLE1BQU0sVUFBVSxHQUFHLFNBQVMsRUFBRSxXQUFXLENBQUM7SUFDMUMsSUFBSSxDQUFDLFVBQVUsSUFBSSxPQUFPLFVBQVUsS0FBSyxRQUFRLEVBQUUsQ0FBQztRQUNsRCxNQUFNLElBQUksS0FBSyxDQUFDLDRDQUE0QyxDQUFDLENBQUM7SUFDaEUsQ0FBQztJQUNELE9BQU8sQ0FBQyxHQUFHLENBQUMsY0FBYyxHQUFHLFVBQVUsQ0FBQztJQUN4QyxZQUFZLENBQUMsa0JBQWtCLENBQUMsQ0FBQztBQUNuQyxDQUFDO0FBRUQ7Ozs7R0FJRztBQUNILE1BQU0sQ0FBQyxLQUFLLFVBQVUseUJBQXlCLENBQUMsT0FBOEI7SUFDNUUsTUFBTSxRQUFRLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQyxvQkFBb0IsQ0FBQztJQUNsRCxJQUFJLFFBQVE7UUFBRSxPQUFPLFFBQVEsQ0FBQztJQUM5QixNQUFNLG1CQUFtQixDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ25DLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLGNBQWMsRUFBRSxDQUFDO1FBQ2hDLE1BQU0sSUFBSSxLQUFLLENBQ2IsZ0ZBQWdGO2NBQzlFLG1EQUFtRDtjQUNuRCxxRUFBcUUsQ0FDeEUsQ0FBQztJQUNKLENBQUM7SUFDRCxPQUFPLGlCQUFpQixDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsY0FBYyxDQUFDLENBQUM7QUFDdkQsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAyMDI2IFBpcGVsaW5lIEJ1aWxkZXIgQ29udHJpYnV0b3JzXG4vLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuXG4vKipcbiAqIFNoYXJlZCBwbGF0Zm9ybS10b2tlbiDihpIgc2VjcmV0LW5hbWUgcmVzb2x1dGlvbiwgdXNlZCBieSBib3RoIGBzdG9yZS10b2tlbmBcbiAqICh3aGljaCBXUklURVMgdGhlIEpXVCB0byBTZWNyZXRzIE1hbmFnZXIpIGFuZCBgc2V0dXAtZXZlbnRzYCAod2hpY2ggZGVwbG95cyB0aGVcbiAqIExhbWJkYSB0aGF0IFJFQURTIGl0KS4gQm90aCBtdXN0IGFncmVlIG9uIHRoZSBzYW1lIHNlY3JldCBwYXRoLCBzbyB0aGUgbG9naWNcbiAqIGxpdmVzIGhlcmUgb25jZTogZGVyaXZlIGB7U0VDUkVUU19QQVRIX1BSRUZJWH0ve29yZ0lkfS9wbGF0Zm9ybWAgZnJvbSB0aGUgSldUJ3NcbiAqIG9yZ2FuaXphdGlvbklkLCBsb2dnaW5nIGluIGZpcnN0IGlmIG5lZWRlZCB0byBvYnRhaW4gdGhlIHRva2VuLlxuICovXG5cbmltcG9ydCB7IENvcmVDb25zdGFudHMgfSBmcm9tICdAcGlwZWxpbmUtYnVpbGRlci9waXBlbGluZS1jb3JlJztcbmltcG9ydCBheGlvcyBmcm9tICdheGlvcyc7XG5pbXBvcnQgeyBkZWNvZGVUb2tlblBheWxvYWQgfSBmcm9tICcuL2F1dGgtZ3VhcmQuanMnO1xuaW1wb3J0IHsgZ2V0QXBpQ29uZmlnIH0gZnJvbSAnLi9jb25maWctbG9hZGVyLmpzJztcbmltcG9ydCB7IHByaW50SW5mbywgcHJpbnRTZWN0aW9uLCBwcmludFN1Y2Nlc3MsIHByaW50V2FybmluZyB9IGZyb20gJy4vb3V0cHV0LXV0aWxzLmpzJztcbmltcG9ydCB7IGFzc2VydFNzbERpc2FibGVBbGxvd2VkIH0gZnJvbSAnLi90bHMuanMnO1xuXG4vKiogTG9naW4vc2VjcmV0IG9wdGlvbnMgc2hhcmVkIGFjcm9zcyB0aGUgcGxhdGZvcm0tc2VjcmV0IGhlbHBlcnMuICovXG5leHBvcnQgaW50ZXJmYWNlIFBsYXRmb3JtU2VjcmV0T3B0aW9ucyB7XG4gIC8qKiBMb2dpbiBpZGVudGlmaWVyICh1c2VybmFtZSBPUiBlbWFpbCkg4oCUIG1hdGNoZXMgYGF1dGggbG9naW5gIC8gYGF1dGggcGF0YC4gKi9cbiAgcmVhZG9ubHkgaWRlbnRpZmllcj86IHN0cmluZztcbiAgcmVhZG9ubHkgcGFzc3dvcmQ/OiBzdHJpbmc7XG4gIHJlYWRvbmx5IHZlcmlmeVNzbD86IGJvb2xlYW47XG59XG5cbi8qKlxuICogRGVyaXZlIHRoZSBwbGF0Zm9ybSBzZWNyZXQgcGF0aCBmcm9tIGEgSldUJ3Mgb3JnYW5pemF0aW9uSWQuXG4gKiBQYXR0ZXJuOiBge1NFQ1JFVFNfUEFUSF9QUkVGSVh9L3tvcmdJZH0vcGxhdGZvcm1gLlxuICogQHRocm93cyBpZiB0aGUgdG9rZW4gY2FycmllcyBubyBvcmdhbml6YXRpb25JZCAoY2FsbGVyIHNob3VsZCBmYWxsIGJhY2sgdG8gUExBVEZPUk1fU0VDUkVUX05BTUUpLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVzb2x2ZVNlY3JldE5hbWUodG9rZW46IHN0cmluZyk6IHN0cmluZyB7XG4gIGNvbnN0IHBheWxvYWQgPSBkZWNvZGVUb2tlblBheWxvYWQodG9rZW4pO1xuICBjb25zdCBvcmdJZCA9IHBheWxvYWQ/Lm9yZ2FuaXphdGlvbklkO1xuICBpZiAoIW9yZ0lkKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdUb2tlbiBkb2VzIG5vdCBjb250YWluIG9yZ2FuaXphdGlvbklkIOKAlCBjYW5ub3QgZGVyaXZlIHNlY3JldCBuYW1lLiBTZXQgUExBVEZPUk1fU0VDUkVUX05BTUUgdG8gc3BlY2lmeSBpdCBleHBsaWNpdGx5LicpO1xuICB9XG4gIHJldHVybiBgJHtDb3JlQ29uc3RhbnRzLlNFQ1JFVFNfUEFUSF9QUkVGSVh9LyR7b3JnSWR9L3BsYXRmb3JtYDtcbn1cblxuLyoqXG4gKiBFbnN1cmUgYHByb2Nlc3MuZW52LlBMQVRGT1JNX1RPS0VOYCBpcyBzZXQuIE5vLW9wIGlmIGl0IGFscmVhZHkgaXMuIE90aGVyd2lzZSxcbiAqIGlmIGxvZ2luIGNyZWRzIGFyZSBhdmFpbGFibGUgKGAtLWlkZW50aWZpZXIvLS1wYXNzd29yZGAgb3IgYFBMQVRGT1JNX0lERU5USUZJRVJgL1xuICogYFBMQVRGT1JNX1BBU1NXT1JEYCBlbnYg4oCUIHRoZSBlbnYgcGF0aCBsZXRzIGBwcm92aXNpb25gIHBhc3MgY3JlZHMgd2l0aG91dFxuICogcHV0dGluZyB0aGUgcGFzc3dvcmQgb24gdGhlIGNvbW1hbmQgbGluZSksIGxvZyBpbiBhbmQgc2V0IFBMQVRGT1JNX1RPS0VOLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZW5zdXJlUGxhdGZvcm1Ub2tlbihvcHRpb25zOiBQbGF0Zm9ybVNlY3JldE9wdGlvbnMpOiBQcm9taXNlPHZvaWQ+IHtcbiAgaWYgKHByb2Nlc3MuZW52LlBMQVRGT1JNX1RPS0VOKSByZXR1cm47XG4gIGNvbnN0IGxvZ2luSWRlbnRpZmllciA9IG9wdGlvbnMuaWRlbnRpZmllciB8fCBwcm9jZXNzLmVudi5QTEFURk9STV9JREVOVElGSUVSO1xuICBjb25zdCBsb2dpblBhc3N3b3JkID0gb3B0aW9ucy5wYXNzd29yZCB8fCBwcm9jZXNzLmVudi5QTEFURk9STV9QQVNTV09SRDtcbiAgaWYgKCFsb2dpbklkZW50aWZpZXIgfHwgIWxvZ2luUGFzc3dvcmQpIHJldHVybjtcblxuICBpZiAob3B0aW9ucy5wYXNzd29yZCkge1xuICAgIHByaW50V2FybmluZygnUGFzc2luZyAtLXBhc3N3b3JkIG9uIHRoZSBjb21tYW5kIGxpbmUgY2FuIGV4cG9zZSBpdCB2aWEgc2hlbGwgaGlzdG9yeTsgcHJlZmVyIHRoZSBQTEFURk9STV9QQVNTV09SRCBlbnYgdmFyLicpO1xuICB9XG5cbiAgcHJpbnRTZWN0aW9uKCdMb2dpbicpO1xuICBwcmludEluZm8oJ0F1dGhlbnRpY2F0aW5nIHdpdGggaWRlbnRpZmllci9wYXNzd29yZC4uLicpO1xuICAvLyBSZXNvbHZlIHRoZSBiYXNlIFVSTCBXSVRIT1VUIGRlbWFuZGluZyBhIHRva2VuIOKAlCB0aGlzIGxvZ2luIHN0ZXAgcnVuc1xuICAvLyBwcmUtYXV0aCAobm8gUExBVEZPUk1fVE9LRU4geWV0KSwgc28gYGdldENvbmZpZygpYCB3b3VsZCB0aHJvdyBoZXJlLiBUaGVcbiAgLy8gdG9rZW4tb3B0aW9uYWwgbG9hZGVyIHN0aWxsIGhvbm9ycyBjb25maWcgZmlsZXMgKyBQTEFURk9STV9CQVNFX1VSTC9UTFMgZW52LlxuICBjb25zdCBhcGlDb25maWcgPSBnZXRBcGlDb25maWcoKTtcbiAgLy8gU0VDVVJJVFk6IHRoaXMgaW5saW5lIGxvZ2luIFBPU1RzIHRoZSBwYXNzd29yZC4gUmVmdXNlIHRvIGRpc2FibGUgY2VydFxuICAvLyB2ZXJpZmljYXRpb24gaW4gcHJvZHVjdGlvbiAobWlycm9ycyBjb25maWctbG9hZGVyIC8gbG9naW4pIHNvIGEgTUlUTSBjYW4ndFxuICAvLyBoYXJ2ZXN0IGl0OyBob25vcmVkIGluIG5vbi1wcm9kdWN0aW9uIGZvciBzZWxmLXNpZ25lZCBkZXYgcGxhdGZvcm1zLlxuICBpZiAob3B0aW9ucy52ZXJpZnlTc2wgPT09IGZhbHNlKSB7XG4gICAgYXNzZXJ0U3NsRGlzYWJsZUFsbG93ZWQoJ2lubGluZSBsb2dpbicpO1xuICB9XG4gIGNvbnN0IHJlamVjdFVuYXV0aG9yaXplZCA9IG9wdGlvbnMudmVyaWZ5U3NsID09PSBmYWxzZSA/IGZhbHNlIDogYXBpQ29uZmlnLmFwaS5yZWplY3RVbmF1dGhvcml6ZWQ7XG4gIGNvbnN0IGxvZ2luUmVzcG9uc2UgPSBhd2FpdCBheGlvcy5wb3N0KFxuICAgIGAke2FwaUNvbmZpZy5hcGkuYmFzZVVybH0vYXBpL2F1dGgvbG9naW5gLFxuICAgIC8vIFRoZSBzZXJ2ZXIncyBsb2dpblNjaGVtYSByZXF1aXJlcyBgaWRlbnRpZmllcmAgKGVtYWlsIE9SIHVzZXJuYW1lKSwgbm90XG4gICAgLy8gYGVtYWlsYCDigJQgc2VuZGluZyBgZW1haWxgIGZhaWxzIHpvZCB2YWxpZGF0aW9uIHdpdGggYSA0MDAuIE1pcnJvciB0aGVcbiAgICAvLyBjYW5vbmljYWwgYHBvc3RMb2dpbmAgYm9keS5cbiAgICB7IGlkZW50aWZpZXI6IGxvZ2luSWRlbnRpZmllciwgcGFzc3dvcmQ6IGxvZ2luUGFzc3dvcmQgfSxcbiAgICB7XG4gICAgICBodHRwc0FnZW50OiByZWplY3RVbmF1dGhvcml6ZWQgPT09IGZhbHNlXG4gICAgICAgID8gbmV3IChhd2FpdCBpbXBvcnQoJ2h0dHBzJykpLkFnZW50KHsgcmVqZWN0VW5hdXRob3JpemVkOiBmYWxzZSB9KVxuICAgICAgICA6IHVuZGVmaW5lZCxcbiAgICB9LFxuICApO1xuICBjb25zdCBsb2dpbkRhdGEgPSBsb2dpblJlc3BvbnNlLmRhdGE/LmRhdGEgPz8gbG9naW5SZXNwb25zZS5kYXRhO1xuICBjb25zdCBsb2dpblRva2VuID0gbG9naW5EYXRhPy5hY2Nlc3NUb2tlbjtcbiAgaWYgKCFsb2dpblRva2VuIHx8IHR5cGVvZiBsb2dpblRva2VuICE9PSAnc3RyaW5nJykge1xuICAgIHRocm93IG5ldyBFcnJvcignTG9naW4gZmFpbGVkIOKAlCBubyBhY2Nlc3MgdG9rZW4gaW4gcmVzcG9uc2UnKTtcbiAgfVxuICBwcm9jZXNzLmVudi5QTEFURk9STV9UT0tFTiA9IGxvZ2luVG9rZW47XG4gIHByaW50U3VjY2VzcygnTG9naW4gc3VjY2Vzc2Z1bCcpO1xufVxuXG4vKipcbiAqIFJlc29sdmUgdGhlIHBsYXRmb3JtIHNlY3JldCBuYW1lOiBhbiBleHBsaWNpdCBgUExBVEZPUk1fU0VDUkVUX05BTUVgIGVudiB3aW5zO1xuICogb3RoZXJ3aXNlIGxvZyBpbiBpZiBuZWVkZWQgYW5kIGRlcml2ZSBpdCBmcm9tIHRoZSBwbGF0Zm9ybSB0b2tlbidzIG9yZyDigJQgdGhlXG4gKiBzYW1lIHRva2VuIGBpbml0LXBsYXRmb3JtLnNoYCAocmVnaXN0ZXIpIG1pbnRzLCBzbyB3cml0ZXIgYW5kIHJlYWRlciBhZ3JlZS5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlc29sdmVQbGF0Zm9ybVNlY3JldE5hbWUob3B0aW9uczogUGxhdGZvcm1TZWNyZXRPcHRpb25zKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgY29uc3QgZXhwbGljaXQgPSBwcm9jZXNzLmVudi5QTEFURk9STV9TRUNSRVRfTkFNRTtcbiAgaWYgKGV4cGxpY2l0KSByZXR1cm4gZXhwbGljaXQ7XG4gIGF3YWl0IGVuc3VyZVBsYXRmb3JtVG9rZW4ob3B0aW9ucyk7XG4gIGlmICghcHJvY2Vzcy5lbnYuUExBVEZPUk1fVE9LRU4pIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAnQ2Fubm90IGRlcml2ZSB0aGUgcGxhdGZvcm0gc2VjcmV0IG5hbWU6IG5vIFBMQVRGT1JNX1RPS0VOIGFuZCBubyBsb2dpbiBjcmVkcy4gJ1xuICAgICAgKyAnU2V0IFBMQVRGT1JNX1NFQ1JFVF9OQU1FLCBvciBwcm92aWRlIGxvZ2luIGNyZWRzICdcbiAgICAgICsgJygtLWlkZW50aWZpZXIvLS1wYXNzd29yZCBvciBQTEFURk9STV9JREVOVElGSUVSL1BMQVRGT1JNX1BBU1NXT1JEKS4nLFxuICAgICk7XG4gIH1cbiAgcmV0dXJuIHJlc29sdmVTZWNyZXROYW1lKHByb2Nlc3MuZW52LlBMQVRGT1JNX1RPS0VOKTtcbn1cbiJdfQ==
|
|
114
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGxhdGZvcm0tc2VjcmV0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3V0aWxzL3BsYXRmb3JtLXNlY3JldC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwrQ0FBK0M7QUFDL0Msc0NBQXNDO0FBRXRDOzs7Ozs7R0FNRztBQUVILE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUM1RCxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDaEUsT0FBTyxLQUFLLE1BQU0sT0FBTyxDQUFDO0FBQzFCLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQ3JELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUNsRCxPQUFPLEVBQUUsU0FBUyxFQUFFLFlBQVksRUFBRSxZQUFZLEVBQUUsWUFBWSxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDeEYsT0FBTyxFQUFFLHVCQUF1QixFQUFFLE1BQU0sVUFBVSxDQUFDO0FBZ0JuRDs7Ozs7Ozs7R0FRRztBQUNILE1BQU0sVUFBVSxnQkFBZ0IsQ0FBQyxLQUFhLEVBQUUsSUFBSSxHQUFXLFVBQVU7SUFDdkUsT0FBTyxHQUFHLGFBQWEsQ0FBQyxtQkFBbUIsSUFBSSxLQUFLLElBQUksSUFBSSxFQUFFLENBQUM7QUFDakUsQ0FBQztBQUVELHlGQUF5RjtBQUN6RixNQUFNLFVBQVUsZUFBZSxDQUFDLEtBQWE7SUFDM0MsT0FBTyxLQUFLLENBQUMsT0FBTyxDQUFDLGNBQWMsRUFBRSxHQUFHLENBQUMsQ0FBQztBQUM1QyxDQUFDO0FBRUQ7Ozs7R0FJRztBQUNILE1BQU0sVUFBVSxpQkFBaUIsQ0FBQyxLQUFhO0lBQzdDLDZFQUE2RTtJQUM3RSw4RUFBOEU7SUFDOUUsbUVBQW1FO0lBQ25FLElBQUksY0FBYyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUM7UUFDMUIsTUFBTSxJQUFJLEtBQUssQ0FDYixtSUFB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QUFNLG1CQUFtQixDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ25DLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLGNBQWMsRUFBRSxDQUFDO1FBQ2hDLE1BQU0sSUFBSSxLQUFLLENBQ2IsZ0ZBQWdGO2NBQzlFLG1EQUFtRDtjQUNuRCxxRUFBcUUsQ0FDeEUsQ0FBQztJQUNKLENBQUM7SUFDRCxPQUFPLGlCQUFpQixDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsY0FBYyxDQUFDLENBQUM7QUFDdkQsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAyMDI2IFBpcGVsaW5lIEJ1aWxkZXIgQ29udHJpYnV0b3JzXG4vLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuXG4vKipcbiAqIFNoYXJlZCBwbGF0Zm9ybS10b2tlbiDihpIgc2VjcmV0LW5hbWUgcmVzb2x1dGlvbiwgdXNlZCBieSBib3RoIGBzdG9yZS10b2tlbmBcbiAqICh3aGljaCBXUklURVMgdGhlIEpXVCB0byBTZWNyZXRzIE1hbmFnZXIpIGFuZCBgc2V0dXAtZXZlbnRzYCAod2hpY2ggZGVwbG95cyB0aGVcbiAqIExhbWJkYSB0aGF0IFJFQURTIGl0KS4gQm90aCBtdXN0IGFncmVlIG9uIHRoZSBzYW1lIHNlY3JldCBwYXRoLCBzbyB0aGUgbG9naWNcbiAqIGxpdmVzIGhlcmUgb25jZTogZGVyaXZlIGB7U0VDUkVUU19QQVRIX1BSRUZJWH0ve29yZ0lkfS9wbGF0Zm9ybWAgZnJvbSB0aGUgSldUJ3NcbiAqIG9yZ2FuaXphdGlvbklkLCBsb2dnaW5nIGluIGZpcnN0IGlmIG5lZWRlZCB0byBvYnRhaW4gdGhlIHRva2VuLlxuICovXG5cbmltcG9ydCB7IGlzT3BhcXVlQXBpS2V5IH0gZnJvbSAnQHBpcGVsaW5lLWJ1aWxkZXIvYXBpLWNvcmUnO1xuaW1wb3J0IHsgQ29yZUNvbnN0YW50cyB9IGZyb20gJ0BwaXBlbGluZS1idWlsZGVyL3BpcGVsaW5lLWNvcmUnO1xuaW1wb3J0IGF4aW9zIGZyb20gJ2F4aW9zJztcbmltcG9ydCB7IGRlY29kZVRva2VuUGF5bG9hZCB9IGZyb20gJy4vYXV0aC1ndWFyZC5qcyc7XG5pbXBvcnQgeyBnZXRBcGlDb25maWcgfSBmcm9tICcuL2NvbmZpZy1sb2FkZXIuanMnO1xuaW1wb3J0IHsgcHJpbnRJbmZvLCBwcmludFNlY3Rpb24sIHByaW50U3VjY2VzcywgcHJpbnRXYXJuaW5nIH0gZnJvbSAnLi9vdXRwdXQtdXRpbHMuanMnO1xuaW1wb3J0IHsgYXNzZXJ0U3NsRGlzYWJsZUFsbG93ZWQgfSBmcm9tICcuL3Rscy5qcyc7XG5cbi8qKiBMb2dpbi9zZWNyZXQgb3B0aW9ucyBzaGFyZWQgYWNyb3NzIHRoZSBwbGF0Zm9ybS1zZWNyZXQgaGVscGVycy4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUGxhdGZvcm1TZWNyZXRPcHRpb25zIHtcbiAgLyoqXG4gICAqIExvZ2luIGlkZW50aWZpZXIgKHVzZXJuYW1lIE9SIGVtYWlsKSBmb3IgdGhlIE5PTi1JTlRFUkFDVElWRSBtYWNoaW5lIGxvZ2luXG4gICAqIGJlbG93LiBUaGlzIGlzIHRoZSBvbmx5IHBhc3N3b3JkIHBhdGggbGVmdCBpbiB0aGUgQ0xJOiBgYXV0aCBsb2dpbmAgYW5kXG4gICAqIGBhdXRoIHBhdGAgc2lnbiBpbiB0aHJvdWdoIHRoZSBicm93c2VyIChkZXZpY2UgYXV0aG9yaXphdGlvbiksIGJ1dFxuICAgKiBgc3RvcmUtdG9rZW5gIC8gYHNldHVwLWV2ZW50c2AgcnVuIG9uIGhvc3RzIHdpdGggbm9ib2R5IHByZXNlbnQgdG8gYXBwcm92ZSBhXG4gICAqIGNvZGUsIGFuZCB3aGF0IHRoZXkgbWludCBpcyBhIG1hY2hpbmUgY3JlZGVudGlhbCwgbm90IGEgcGVyc29uJ3Mgc2Vzc2lvbi5cbiAgICovXG4gIHJlYWRvbmx5IGlkZW50aWZpZXI/OiBzdHJpbmc7XG4gIHJlYWRvbmx5IHBhc3N3b3JkPzogc3RyaW5nO1xuICByZWFkb25seSB2ZXJpZnlTc2w/OiBib29sZWFuO1xufVxuXG4vKipcbiAqIFRoZSBTZWNyZXRzIE1hbmFnZXIgcGF0aCBhIHN0b3JlZCBtYWNoaW5lIGNyZWRlbnRpYWwgbGl2ZXMgYXQ6XG4gKiBge1NFQ1JFVFNfUEFUSF9QUkVGSVh9L3tvcmdJZH0ve2xlYWZ9YC5cbiAqXG4gKiBgbGVhZmAgaXMgYHBsYXRmb3JtYCBmb3IgdGhlIG9yZydzIGZ1bGwtcHJpdmlsZWdlIGF1dG9tYXRpb24gY3JlZGVudGlhbCwgYW5kXG4gKiB0aGUgc2NvcGUncyBzbHVnIChgcmVwb3J0aW5nLWluZ2VzdGAsIGByZWdpc3RyeS1wdXNoYCkgZm9yIGEgbGVhc3QtcHJpdmlsZWdlXG4gKiBvbmUg4oCUIHNvIGEgc2NvcGVkIGNyZWRlbnRpYWwgY2FuIG5ldmVyIGNsb2JiZXIgdGhlIHBsYXRmb3JtIG9uZSwgYW5kIHRoZVxuICogZXZlbnRzIExhbWJkYSdzIHNlY3JldCBpcyBhIGRpZmZlcmVudCBvYmplY3QgZnJvbSBDb2RlQnVpbGQncy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNlY3JldE5hbWVGb3JPcmcob3JnSWQ6IHN0cmluZywgbGVhZjogc3RyaW5nID0gJ3BsYXRmb3JtJyk6IHN0cmluZyB7XG4gIHJldHVybiBgJHtDb3JlQ29uc3RhbnRzLlNFQ1JFVFNfUEFUSF9QUkVGSVh9LyR7b3JnSWR9LyR7bGVhZn1gO1xufVxuXG4vKiogQSBjYXBhYmlsaXR5IHNjb3BlIGFzIGEgc2VjcmV0LXBhdGggbGVhZjogYHJlcG9ydGluZzppbmdlc3RgIOKGkiBgcmVwb3J0aW5nLWluZ2VzdGAuICovXG5leHBvcnQgZnVuY3Rpb24gc2NvcGVTZWNyZXRMZWFmKHNjb3BlOiBzdHJpbmcpOiBzdHJpbmcge1xuICByZXR1cm4gc2NvcGUucmVwbGFjZSgvW15hLXowLTldKy9naSwgJy0nKTtcbn1cblxuLyoqXG4gKiBEZXJpdmUgdGhlIHBsYXRmb3JtIHNlY3JldCBwYXRoIGZyb20gYSBKV1QncyBvcmdhbml6YXRpb25JZC5cbiAqIFBhdHRlcm46IGB7U0VDUkVUU19QQVRIX1BSRUZJWH0ve29yZ0lkfS9wbGF0Zm9ybWAuXG4gKiBAdGhyb3dzIGlmIHRoZSB0b2tlbiBjYXJyaWVzIG5vIG9yZ2FuaXphdGlvbklkIChjYWxsZXIgc2hvdWxkIGZhbGwgYmFjayB0byBQTEFURk9STV9TRUNSRVRfTkFNRSkuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZXNvbHZlU2VjcmV0TmFtZSh0b2tlbjogc3RyaW5nKTogc3RyaW5nIHtcbiAgLy8gQW4gQUNDRVNTIEtFWSAoYHBiX3BhdF/igKZgKSBpcyBvcGFxdWUg4oCUIGl0IGNhcnJpZXMgbm8gb3JnIGNsYWltIHRvIHJlYWQsIGJ5XG4gIC8vIGRlc2lnbi4gU2F5IHNvIGluc3RlYWQgb2YgdGhlIGdlbmVyaWMgZGVjb2RlIGZhaWx1cmUsIHNpbmNlIGV4cG9ydGluZyBhIGtleVxuICAvLyBhcyBQTEFURk9STV9UT0tFTiBpcyBub3cgdGhlIG5vcm1hbCB3YXkgdG8gYXV0aGVudGljYXRlIHRoZSBDTEkuXG4gIGlmIChpc09wYXF1ZUFwaUtleSh0b2tlbikpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAnUExBVEZPUk1fVE9LRU4gaXMgYW4gb3BhcXVlIGFjY2VzcyBrZXksIHdoaWNoIGNhcnJpZXMgbm8gb3JnYW5pemF0aW9uSWQg4oCUIHNldCBQTEFURk9STV9TRUNSRVRfTkFNRSB0byBuYW1lIHRoZSBzZWNyZXQgZXhwbGljaXRseS4nLFxuICAgICk7XG4gIH1cbiAgY29uc3QgcGF5bG9hZCA9IGRlY29kZVRva2VuUGF5bG9hZCh0b2tlbik7XG4gIGNvbnN0IG9yZ0lkID0gcGF5bG9hZD8ub3JnYW5pemF0aW9uSWQ7XG4gIGlmICghb3JnSWQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1Rva2VuIGRvZXMgbm90IGNvbnRhaW4gb3JnYW5pemF0aW9uSWQg4oCUIGNhbm5vdCBkZXJpdmUgc2VjcmV0IG5hbWUuIFNldCBQTEFURk9STV9TRUNSRVRfTkFNRSB0byBzcGVjaWZ5IGl0IGV4cGxpY2l0bHkuJyk7XG4gIH1cbiAgcmV0dXJuIHNlY3JldE5hbWVGb3JPcmcob3JnSWQpO1xufVxuXG4vKipcbiAqIEVuc3VyZSBgcHJvY2Vzcy5lbnYuUExBVEZPUk1fVE9LRU5gIGlzIHNldC4gTm8tb3AgaWYgaXQgYWxyZWFkeSBpcy4gT3RoZXJ3aXNlLFxuICogaWYgbG9naW4gY3JlZHMgYXJlIGF2YWlsYWJsZSAoYC0taWRlbnRpZmllci8tLXBhc3N3b3JkYCBvciBgUExBVEZPUk1fSURFTlRJRklFUmAvXG4gKiBgUExBVEZPUk1fUEFTU1dPUkRgIGVudiDigJQgdGhlIGVudiBwYXRoIGxldHMgYHByb3Zpc2lvbmAgcGFzcyBjcmVkcyB3aXRob3V0XG4gKiBwdXR0aW5nIHRoZSBwYXNzd29yZCBvbiB0aGUgY29tbWFuZCBsaW5lKSwgbG9nIGluIGFuZCBzZXQgUExBVEZPUk1fVE9LRU4uXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBlbnN1cmVQbGF0Zm9ybVRva2VuKG9wdGlvbnM6IFBsYXRmb3JtU2VjcmV0T3B0aW9ucyk6IFByb21pc2U8dm9pZD4ge1xuICBpZiAocHJvY2Vzcy5lbnYuUExBVEZPUk1fVE9LRU4pIHJldHVybjtcbiAgY29uc3QgbG9naW5JZGVudGlmaWVyID0gb3B0aW9ucy5pZGVudGlmaWVyIHx8IHByb2Nlc3MuZW52LlBMQVRGT1JNX0lERU5USUZJRVI7XG4gIGNvbnN0IGxvZ2luUGFzc3dvcmQgPSBvcHRpb25zLnBhc3N3b3JkIHx8IHByb2Nlc3MuZW52LlBMQVRGT1JNX1BBU1NXT1JEO1xuICBpZiAoIWxvZ2luSWRlbnRpZmllciB8fCAhbG9naW5QYXNzd29yZCkgcmV0dXJuO1xuXG4gIGlmIChvcHRpb25zLnBhc3N3b3JkKSB7XG4gICAgcHJpbnRXYXJuaW5nKCdQYXNzaW5nIC0tcGFzc3dvcmQgb24gdGhlIGNvbW1hbmQgbGluZSBjYW4gZXhwb3NlIGl0IHZpYSBzaGVsbCBoaXN0b3J5OyBwcmVmZXIgdGhlIFBMQVRGT1JNX1BBU1NXT1JEIGVudiB2YXIuJyk7XG4gIH1cblxuICBwcmludFNlY3Rpb24oJ0xvZ2luJyk7XG4gIHByaW50SW5mbygnQXV0aGVudGljYXRpbmcgd2l0aCBpZGVudGlmaWVyL3Bhc3N3b3JkLi4uJyk7XG4gIC8vIFJlc29sdmUgdGhlIGJhc2UgVVJMIFdJVEhPVVQgZGVtYW5kaW5nIGEgdG9rZW4g4oCUIHRoaXMgbG9naW4gc3RlcCBydW5zXG4gIC8vIHByZS1hdXRoIChubyBQTEFURk9STV9UT0tFTiB5ZXQpLCBzbyBgZ2V0Q29uZmlnKClgIHdvdWxkIHRocm93IGhlcmUuIFRoZVxuICAvLyB0b2tlbi1vcHRpb25hbCBsb2FkZXIgc3RpbGwgaG9ub3JzIGNvbmZpZyBmaWxlcyArIFBMQVRGT1JNX0JBU0VfVVJML1RMUyBlbnYuXG4gIGNvbnN0IGFwaUNvbmZpZyA9IGdldEFwaUNvbmZpZygpO1xuICAvLyBTRUNVUklUWTogdGhpcyBpbmxpbmUgbG9naW4gUE9TVHMgdGhlIHBhc3N3b3JkLiBSZWZ1c2UgdG8gZGlzYWJsZSBjZXJ0XG4gIC8vIHZlcmlmaWNhdGlvbiBpbiBwcm9kdWN0aW9uIChtaXJyb3JzIGNvbmZpZy1sb2FkZXIgLyBsb2dpbikgc28gYSBNSVRNIGNhbid0XG4gIC8vIGhhcnZlc3QgaXQ7IGhvbm9yZWQgaW4gbm9uLXByb2R1Y3Rpb24gZm9yIHNlbGYtc2lnbmVkIGRldiBwbGF0Zm9ybXMuXG4gIGlmIChvcHRpb25zLnZlcmlmeVNzbCA9PT0gZmFsc2UpIHtcbiAgICBhc3NlcnRTc2xEaXNhYmxlQWxsb3dlZCgnaW5saW5lIGxvZ2luJyk7XG4gIH1cbiAgY29uc3QgcmVqZWN0VW5hdXRob3JpemVkID0gb3B0aW9ucy52ZXJpZnlTc2wgPT09IGZhbHNlID8gZmFsc2UgOiBhcGlDb25maWcuYXBpLnJlamVjdFVuYXV0aG9yaXplZDtcbiAgY29uc3QgbG9naW5SZXNwb25zZSA9IGF3YWl0IGF4aW9zLnBvc3QoXG4gICAgYCR7YXBpQ29uZmlnLmFwaS5iYXNlVXJsfS9hcGkvYXV0aC9sb2dpbmAsXG4gICAgLy8gVGhlIHNlcnZlcidzIGxvZ2luU2NoZW1hIHJlcXVpcmVzIGBpZGVudGlmaWVyYCAoZW1haWwgT1IgdXNlcm5hbWUpLCBub3RcbiAgICAvLyBgZW1haWxgIOKAlCBzZW5kaW5nIGBlbWFpbGAgZmFpbHMgem9kIHZhbGlkYXRpb24gd2l0aCBhIDQwMC5cbiAgICB7IGlkZW50aWZpZXI6IGxvZ2luSWRlbnRpZmllciwgcGFzc3dvcmQ6IGxvZ2luUGFzc3dvcmQgfSxcbiAgICB7XG4gICAgICBodHRwc0FnZW50OiByZWplY3RVbmF1dGhvcml6ZWQgPT09IGZhbHNlXG4gICAgICAgID8gbmV3IChhd2FpdCBpbXBvcnQoJ2h0dHBzJykpLkFnZW50KHsgcmVqZWN0VW5hdXRob3JpemVkOiBmYWxzZSB9KVxuICAgICAgICA6IHVuZGVmaW5lZCxcbiAgICB9LFxuICApO1xuICBjb25zdCBsb2dpbkRhdGEgPSBsb2dpblJlc3BvbnNlLmRhdGE/LmRhdGEgPz8gbG9naW5SZXNwb25zZS5kYXRhO1xuICBjb25zdCBsb2dpblRva2VuID0gbG9naW5EYXRhPy5hY2Nlc3NUb2tlbjtcbiAgaWYgKCFsb2dpblRva2VuIHx8IHR5cGVvZiBsb2dpblRva2VuICE9PSAnc3RyaW5nJykge1xuICAgIHRocm93IG5ldyBFcnJvcignTG9naW4gZmFpbGVkIOKAlCBubyBhY2Nlc3MgdG9rZW4gaW4gcmVzcG9uc2UnKTtcbiAgfVxuICBwcm9jZXNzLmVudi5QTEFURk9STV9UT0tFTiA9IGxvZ2luVG9rZW47XG4gIHByaW50U3VjY2VzcygnTG9naW4gc3VjY2Vzc2Z1bCcpO1xufVxuXG4vKipcbiAqIFJlc29sdmUgdGhlIHBsYXRmb3JtIHNlY3JldCBuYW1lOiBhbiBleHBsaWNpdCBgUExBVEZPUk1fU0VDUkVUX05BTUVgIGVudiB3aW5zO1xuICogb3RoZXJ3aXNlIGxvZyBpbiBpZiBuZWVkZWQgYW5kIGRlcml2ZSBpdCBmcm9tIHRoZSBwbGF0Zm9ybSB0b2tlbidzIG9yZyDigJQgdGhlXG4gKiBzYW1lIHRva2VuIGBpbml0LXBsYXRmb3JtLnNoYCAocmVnaXN0ZXIpIG1pbnRzLCBzbyB3cml0ZXIgYW5kIHJlYWRlciBhZ3JlZS5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlc29sdmVQbGF0Zm9ybVNlY3JldE5hbWUob3B0aW9uczogUGxhdGZvcm1TZWNyZXRPcHRpb25zKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgY29uc3QgZXhwbGljaXQgPSBwcm9jZXNzLmVudi5QTEFURk9STV9TRUNSRVRfTkFNRTtcbiAgaWYgKGV4cGxpY2l0KSByZXR1cm4gZXhwbGljaXQ7XG4gIGF3YWl0IGVuc3VyZVBsYXRmb3JtVG9rZW4ob3B0aW9ucyk7XG4gIGlmICghcHJvY2Vzcy5lbnYuUExBVEZPUk1fVE9LRU4pIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAnQ2Fubm90IGRlcml2ZSB0aGUgcGxhdGZvcm0gc2VjcmV0IG5hbWU6IG5vIFBMQVRGT1JNX1RPS0VOIGFuZCBubyBsb2dpbiBjcmVkcy4gJ1xuICAgICAgKyAnU2V0IFBMQVRGT1JNX1NFQ1JFVF9OQU1FLCBvciBwcm92aWRlIGxvZ2luIGNyZWRzICdcbiAgICAgICsgJygtLWlkZW50aWZpZXIvLS1wYXNzd29yZCBvciBQTEFURk9STV9JREVOVElGSUVSL1BMQVRGT1JNX1BBU1NXT1JEKS4nLFxuICAgICk7XG4gIH1cbiAgcmV0dXJuIHJlc29sdmVTZWNyZXROYW1lKHByb2Nlc3MuZW52LlBMQVRGT1JNX1RPS0VOKTtcbn1cbiJdfQ==
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provisioning the org's MACHINE identity for stored credentials (#12 / #N2).
|
|
3
|
+
*
|
|
4
|
+
* Every credential the CLI parks in AWS Secrets Manager used to be a machine
|
|
5
|
+
* SESSION belonging to whoever ran the command: a person's JWT, renewed daily by
|
|
6
|
+
* re-minting it under that person's session. It outlived their employment, it
|
|
7
|
+
* carried their authority, and the audit trail read as if they had personally
|
|
8
|
+
* pushed every image.
|
|
9
|
+
*
|
|
10
|
+
* What it writes instead is a `pb_sa_…` key on an org SERVICE ACCOUNT:
|
|
11
|
+
* - the account is the principal, so audit rows name it, not the operator;
|
|
12
|
+
* - its Roles are the narrowest that work — for a SCOPED credential that is no
|
|
13
|
+
* Roles at all, just the one capability (`reporting:ingest`, `registry:push`);
|
|
14
|
+
* - the key is opaque and short-lived at the point of use (5-minute exchanged
|
|
15
|
+
* tokens), so revoking it actually stops the automation;
|
|
16
|
+
* - it takes no seat and survives the operator leaving.
|
|
17
|
+
*
|
|
18
|
+
* Creating an account and issuing a key are BOTH step-up gated on the platform —
|
|
19
|
+
* they mint durable bearer credentials, the same class of action a personal key
|
|
20
|
+
* is gated for. So this module needs the operator's password (`--password` or
|
|
21
|
+
* `PLATFORM_PASSWORD`), which is also the only reason `store-token` still has a
|
|
22
|
+
* password path at all. A step-up token is single-use and lives about a minute,
|
|
23
|
+
* so one is minted immediately before each gated call.
|
|
24
|
+
*/
|
|
25
|
+
import type { ApiClient } from './api-client.js';
|
|
26
|
+
/** What the caller wants provisioned. */
|
|
27
|
+
export interface ProvisionKeyOptions {
|
|
28
|
+
/** An authenticated client for the operator's own session. */
|
|
29
|
+
client: ApiClient;
|
|
30
|
+
/** The operator's password — required, because every key write is step-up gated. */
|
|
31
|
+
password: string;
|
|
32
|
+
/** Machine name of the service account (`[a-z0-9][a-z0-9_-]{1,63}`). */
|
|
33
|
+
accountName: string;
|
|
34
|
+
/** Human description recorded on a newly created account. */
|
|
35
|
+
description: string;
|
|
36
|
+
/**
|
|
37
|
+
* Roles to grant a NEWLY created account: `'admin'` for the full-privilege
|
|
38
|
+
* platform credential (synth/deploy callbacks, plugin lookup, image push),
|
|
39
|
+
* `'none'` for a scoped credential, which needs no Roles at all.
|
|
40
|
+
*/
|
|
41
|
+
roles: 'admin' | 'none';
|
|
42
|
+
/** Narrow capability scope stamped on the KEY (not the account). */
|
|
43
|
+
scope?: string;
|
|
44
|
+
/** Key lifetime in seconds (platform caps this at 365 days). */
|
|
45
|
+
expiresInSeconds: number;
|
|
46
|
+
/** Key label — shown on the org's service-accounts page. */
|
|
47
|
+
keyName: string;
|
|
48
|
+
}
|
|
49
|
+
/** A freshly minted key, plus everything the secret needs to record about it. */
|
|
50
|
+
export interface ProvisionedKey {
|
|
51
|
+
/** The raw `pb_sa_…` key — returned ONCE by the platform, never readable again. */
|
|
52
|
+
key: string;
|
|
53
|
+
keyId: string;
|
|
54
|
+
serviceAccountId: string;
|
|
55
|
+
serviceAccountName: string;
|
|
56
|
+
organizationId: string;
|
|
57
|
+
expiresAt: string;
|
|
58
|
+
scope: string | null;
|
|
59
|
+
}
|
|
60
|
+
/** The org the operator's token is active in. */
|
|
61
|
+
export declare function resolveOrganizationId(client: ApiClient): Promise<string>;
|
|
62
|
+
/** Revoke one of an account's keys. Best-effort by contract — see the call sites. */
|
|
63
|
+
export declare function revokeServiceAccountKey(client: ApiClient, password: string, orgId: string, accountId: string, keyId: string): Promise<void>;
|
|
64
|
+
/**
|
|
65
|
+
* Ensure the named service account exists and issue it a fresh key.
|
|
66
|
+
*
|
|
67
|
+
* Deliberately does NOT revoke anything the caller was previously holding: the
|
|
68
|
+
* caller stores the new key first and retires the old one afterwards (see
|
|
69
|
+
* `store-token`), so a failure at any point leaves a working credential in the
|
|
70
|
+
* secret rather than an empty one.
|
|
71
|
+
*/
|
|
72
|
+
export declare function provisionServiceAccountKey(opts: ProvisionKeyOptions): Promise<ProvisionedKey>;
|
|
73
|
+
//# sourceMappingURL=service-account.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service-account.d.ts","sourceRoot":"","sources":["../../src/utils/service-account.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAMjD,yCAAyC;AACzC,MAAM,WAAW,mBAAmB;IAClC,8DAA8D;IAC9D,MAAM,EAAE,SAAS,CAAC;IAClB,oFAAoF;IACpF,QAAQ,EAAE,MAAM,CAAC;IACjB,wEAAwE;IACxE,WAAW,EAAE,MAAM,CAAC;IACpB,6DAA6D;IAC7D,WAAW,EAAE,MAAM,CAAC;IACpB;;;;OAIG;IACH,KAAK,EAAE,OAAO,GAAG,MAAM,CAAC;IACxB,oEAAoE;IACpE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gEAAgE;IAChE,gBAAgB,EAAE,MAAM,CAAC;IACzB,4DAA4D;IAC5D,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,iFAAiF;AACjF,MAAM,WAAW,cAAc;IAC7B,mFAAmF;IACnF,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,gBAAgB,EAAE,MAAM,CAAC;IACzB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAiDD,iDAAiD;AACjD,wBAAsB,qBAAqB,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CAO9E;AA0DD,qFAAqF;AACrF,wBAAsB,uBAAuB,CAC3C,MAAM,EAAE,SAAS,EACjB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,IAAI,CAAC,CAKf;AAyCD;;;;;;;GAOG;AACH,wBAAsB,0BAA0B,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,cAAc,CAAC,CAanG"}
|