@verentis/cli 0.2.5 → 0.2.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/dist/index.js +24 -12
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { Command } from 'commander';
|
|
3
3
|
import { mkdir, stat, writeFile, readFile, readdir, realpath, mkdtemp, rm, glob } from 'fs/promises';
|
|
4
|
+
import { Agent } from 'https';
|
|
4
5
|
import { tmpdir, homedir } from 'os';
|
|
5
6
|
import { resolve, basename, dirname, posix, join, isAbsolute, extname, relative, sep } from 'path';
|
|
6
7
|
import { spawn, spawnSync } from 'child_process';
|
|
@@ -12,6 +13,10 @@ import { pipeline } from 'stream/promises';
|
|
|
12
13
|
import * as tar from 'tar';
|
|
13
14
|
import { fileURLToPath } from 'url';
|
|
14
15
|
|
|
16
|
+
var insecureAgent = new Agent({ rejectUnauthorized: false });
|
|
17
|
+
function insecureFetchOptions(insecure) {
|
|
18
|
+
return insecure ? { dispatcher: insecureAgent } : {};
|
|
19
|
+
}
|
|
15
20
|
var configDir = () => process.env.VERENTIS_CONFIG_DIR ?? join(homedir(), ".verentis");
|
|
16
21
|
var configPath = () => join(configDir(), "config.json");
|
|
17
22
|
var keysDir = () => join(configDir(), "keys");
|
|
@@ -53,11 +58,12 @@ function isExpired(token, skewSeconds = 60) {
|
|
|
53
58
|
|
|
54
59
|
// src/auth/deviceFlow.ts
|
|
55
60
|
var CLI_CLIENT_ID = "Verentis.Cli";
|
|
56
|
-
async function startDeviceAuthorization(apiUrl) {
|
|
61
|
+
async function startDeviceAuthorization(apiUrl, insecure) {
|
|
57
62
|
const res = await fetch(`${apiUrl}/connect/device/authorize`, {
|
|
58
63
|
method: "POST",
|
|
59
64
|
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
60
|
-
body: new URLSearchParams({ client_id: CLI_CLIENT_ID })
|
|
65
|
+
body: new URLSearchParams({ client_id: CLI_CLIENT_ID }),
|
|
66
|
+
...insecureFetchOptions(insecure)
|
|
61
67
|
});
|
|
62
68
|
if (!res.ok) {
|
|
63
69
|
const text = await res.text().catch(() => "");
|
|
@@ -65,7 +71,7 @@ async function startDeviceAuthorization(apiUrl) {
|
|
|
65
71
|
}
|
|
66
72
|
return await res.json();
|
|
67
73
|
}
|
|
68
|
-
async function pollForIdentityToken(apiUrl, authorization, onPoll) {
|
|
74
|
+
async function pollForIdentityToken(apiUrl, authorization, insecure, onPoll) {
|
|
69
75
|
let intervalMs = Math.max(authorization.interval, 1) * 1e3;
|
|
70
76
|
const deadline = Date.now() + authorization.expires_in * 1e3;
|
|
71
77
|
while (Date.now() < deadline) {
|
|
@@ -78,7 +84,8 @@ async function pollForIdentityToken(apiUrl, authorization, onPoll) {
|
|
|
78
84
|
grant_type: "device_code",
|
|
79
85
|
device_code: authorization.device_code,
|
|
80
86
|
client_id: CLI_CLIENT_ID
|
|
81
|
-
})
|
|
87
|
+
}),
|
|
88
|
+
...insecureFetchOptions(insecure)
|
|
82
89
|
});
|
|
83
90
|
let payload;
|
|
84
91
|
try {
|
|
@@ -107,7 +114,7 @@ async function pollForIdentityToken(apiUrl, authorization, onPoll) {
|
|
|
107
114
|
}
|
|
108
115
|
var RefreshTokenError = class extends Error {
|
|
109
116
|
};
|
|
110
|
-
async function refreshIdentityToken(apiUrl, refreshToken) {
|
|
117
|
+
async function refreshIdentityToken(apiUrl, refreshToken, insecure) {
|
|
111
118
|
const res = await fetch(`${apiUrl}/connect/token`, {
|
|
112
119
|
method: "POST",
|
|
113
120
|
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
@@ -115,7 +122,8 @@ async function refreshIdentityToken(apiUrl, refreshToken) {
|
|
|
115
122
|
grant_type: "refresh_token",
|
|
116
123
|
refresh_token: refreshToken,
|
|
117
124
|
client_id: CLI_CLIENT_ID
|
|
118
|
-
})
|
|
125
|
+
}),
|
|
126
|
+
...insecureFetchOptions(insecure)
|
|
119
127
|
});
|
|
120
128
|
let payload;
|
|
121
129
|
try {
|
|
@@ -146,6 +154,7 @@ var AUDIENCE = "verentis";
|
|
|
146
154
|
async function createApiClient(overrides) {
|
|
147
155
|
const config = { ...await loadConfig(), ...overrides };
|
|
148
156
|
const apiUrl = requireApiUrl(config);
|
|
157
|
+
const insecure = config.insecure;
|
|
149
158
|
const tokenCache = /* @__PURE__ */ new Map();
|
|
150
159
|
const envIdentity = process.env.VERENTIS_TOKEN;
|
|
151
160
|
let currentIdentity = envIdentity ?? config.identityToken;
|
|
@@ -172,7 +181,7 @@ async function createApiClient(overrides) {
|
|
|
172
181
|
if (!refreshInflight) {
|
|
173
182
|
refreshInflight = (async () => {
|
|
174
183
|
try {
|
|
175
|
-
const refreshed = await refreshIdentityToken(apiUrl, currentRefresh);
|
|
184
|
+
const refreshed = await refreshIdentityToken(apiUrl, currentRefresh, insecure);
|
|
176
185
|
currentIdentity = refreshed.idToken;
|
|
177
186
|
currentRefresh = refreshed.refreshToken ?? currentRefresh;
|
|
178
187
|
await persistTokens(refreshed.idToken, refreshed.refreshToken);
|
|
@@ -217,7 +226,8 @@ async function createApiClient(overrides) {
|
|
|
217
226
|
...options.workspaceId ? { workspaceId: options.workspaceId } : {},
|
|
218
227
|
...options.accountId ? { accountId: options.accountId } : {},
|
|
219
228
|
...options.resourceId ? { resourceId: options.resourceId, resourceKind: options.resourceKind ?? "Node" } : {}
|
|
220
|
-
})
|
|
229
|
+
}),
|
|
230
|
+
...insecureFetchOptions(insecure)
|
|
221
231
|
});
|
|
222
232
|
if (!res.ok) {
|
|
223
233
|
const text = await res.text().catch(() => "");
|
|
@@ -244,7 +254,7 @@ ${truncate(text)}` : ""}`);
|
|
|
244
254
|
headers["Content-Type"] = "application/json";
|
|
245
255
|
}
|
|
246
256
|
for (const [key, value] of Object.entries(options.headers ?? {})) headers[key] = value;
|
|
247
|
-
const res = await fetch(url, { method, headers, body, ...options.rawBody !== void 0 ? { duplex: "half" } : {} });
|
|
257
|
+
const res = await fetch(url, { method, headers, body, ...insecureFetchOptions(insecure), ...options.rawBody !== void 0 ? { duplex: "half" } : {} });
|
|
248
258
|
if (!res.ok) {
|
|
249
259
|
const text = await res.text().catch(() => "");
|
|
250
260
|
throw new ApiError(res.status, `${method} ${path} failed (${res.status}). ${hintFor(res.status)}${formatErrorBody(text)}`);
|
|
@@ -1917,10 +1927,11 @@ function registerKeygen(program2) {
|
|
|
1917
1927
|
|
|
1918
1928
|
// src/commands/login.ts
|
|
1919
1929
|
function registerLogin(program2) {
|
|
1920
|
-
program2.command("login").description("Sign in to Verentis (browser device flow by default; --api-key/--token for non-interactive use)").option("--api-url <url>", "Verentis API gateway URL").option("--api-key <key>", "Verentis API key (vrt_...)").option("--token <token>", "Verentis identity token (exchanged per request for scoped access tokens)").option("--sealing-key <key>", "the platform's base64 X25519 sealing PUBLIC key (used by `pack --encrypt`)").action(async (options) => {
|
|
1930
|
+
program2.command("login").description("Sign in to Verentis (browser device flow by default; --api-key/--token for non-interactive use)").option("--api-url <url>", "Verentis API gateway URL").option("--api-key <key>", "Verentis API key (vrt_...)").option("--token <token>", "Verentis identity token (exchanged per request for scoped access tokens)").option("--sealing-key <key>", "the platform's base64 X25519 sealing PUBLIC key (used by `pack --encrypt`)").option("--insecure", "skip TLS certificate verification (for local dev with self-signed certs)").action(async (options) => {
|
|
1921
1931
|
const config = await loadConfig();
|
|
1922
1932
|
if (options.apiUrl) config.apiUrl = options.apiUrl;
|
|
1923
1933
|
if (options.sealingKey) config.sealingPublicKey = options.sealingKey;
|
|
1934
|
+
if (options.insecure !== void 0) config.insecure = options.insecure;
|
|
1924
1935
|
if (!config.apiUrl) throw new Error("An API URL is required. Pass --api-url <url>.");
|
|
1925
1936
|
if (options.apiKey) {
|
|
1926
1937
|
if (!options.apiKey.startsWith("vrt_")) throw new Error('API keys start with "vrt_".');
|
|
@@ -1940,14 +1951,15 @@ function registerLogin(program2) {
|
|
|
1940
1951
|
return;
|
|
1941
1952
|
}
|
|
1942
1953
|
const apiUrl = config.apiUrl.replace(/\/+$/, "");
|
|
1943
|
-
const
|
|
1954
|
+
const insecure = config.insecure;
|
|
1955
|
+
const authorization = await startDeviceAuthorization(apiUrl, insecure);
|
|
1944
1956
|
console.log("To sign in, open this URL in a browser:");
|
|
1945
1957
|
console.log(`
|
|
1946
1958
|
${authorization.verification_uri_complete ?? authorization.verification_uri}
|
|
1947
1959
|
`);
|
|
1948
1960
|
console.log(`and confirm the code: ${authorization.user_code}`);
|
|
1949
1961
|
console.log("\nWaiting for approval\u2026");
|
|
1950
|
-
const identity = await pollForIdentityToken(apiUrl, authorization, () => process.stderr.write("."));
|
|
1962
|
+
const identity = await pollForIdentityToken(apiUrl, authorization, insecure, () => process.stderr.write("."));
|
|
1951
1963
|
process.stderr.write("\n");
|
|
1952
1964
|
config.identityToken = identity.idToken;
|
|
1953
1965
|
if (identity.refreshToken) config.refreshToken = identity.refreshToken;
|