@positronic/cli 0.0.58 → 0.0.60
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/src/commands/helpers.js +47 -36
- package/dist/src/components/auth-login.js +3 -3
- package/dist/src/components/auth-logout.js +3 -3
- package/dist/src/lib/jwt-auth.js +579 -0
- package/dist/src/lib/ssh-agent-signer.js +296 -0
- package/dist/src/lib/ssh-key-utils.js +7 -7
- package/dist/src/types/sshpk-agent.d.js +0 -0
- package/dist/types/commands/helpers.d.ts.map +1 -1
- package/dist/types/lib/jwt-auth.d.ts +86 -0
- package/dist/types/lib/jwt-auth.d.ts.map +1 -0
- package/dist/types/lib/ssh-agent-signer.d.ts +31 -0
- package/dist/types/lib/ssh-agent-signer.d.ts.map +1 -0
- package/dist/types/lib/ssh-key-utils.d.ts +4 -2
- package/dist/types/lib/ssh-key-utils.d.ts.map +1 -1
- package/package.json +6 -4
- package/dist/src/lib/request-signer.js +0 -208
- package/dist/types/lib/request-signer.d.ts +0 -51
- package/dist/types/lib/request-signer.d.ts.map +0 -1
|
@@ -0,0 +1,579 @@
|
|
|
1
|
+
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
|
|
2
|
+
try {
|
|
3
|
+
var info = gen[key](arg);
|
|
4
|
+
var value = info.value;
|
|
5
|
+
} catch (error) {
|
|
6
|
+
reject(error);
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
if (info.done) {
|
|
10
|
+
resolve(value);
|
|
11
|
+
} else {
|
|
12
|
+
Promise.resolve(value).then(_next, _throw);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
function _async_to_generator(fn) {
|
|
16
|
+
return function() {
|
|
17
|
+
var self = this, args = arguments;
|
|
18
|
+
return new Promise(function(resolve, reject) {
|
|
19
|
+
var gen = fn.apply(self, args);
|
|
20
|
+
function _next(value) {
|
|
21
|
+
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
|
|
22
|
+
}
|
|
23
|
+
function _throw(err) {
|
|
24
|
+
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
|
|
25
|
+
}
|
|
26
|
+
_next(undefined);
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
function _class_call_check(instance, Constructor) {
|
|
31
|
+
if (!(instance instanceof Constructor)) {
|
|
32
|
+
throw new TypeError("Cannot call a class as a function");
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function _defineProperties(target, props) {
|
|
36
|
+
for(var i = 0; i < props.length; i++){
|
|
37
|
+
var descriptor = props[i];
|
|
38
|
+
descriptor.enumerable = descriptor.enumerable || false;
|
|
39
|
+
descriptor.configurable = true;
|
|
40
|
+
if ("value" in descriptor) descriptor.writable = true;
|
|
41
|
+
Object.defineProperty(target, descriptor.key, descriptor);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
function _create_class(Constructor, protoProps, staticProps) {
|
|
45
|
+
if (protoProps) _defineProperties(Constructor.prototype, protoProps);
|
|
46
|
+
if (staticProps) _defineProperties(Constructor, staticProps);
|
|
47
|
+
return Constructor;
|
|
48
|
+
}
|
|
49
|
+
function _define_property(obj, key, value) {
|
|
50
|
+
if (key in obj) {
|
|
51
|
+
Object.defineProperty(obj, key, {
|
|
52
|
+
value: value,
|
|
53
|
+
enumerable: true,
|
|
54
|
+
configurable: true,
|
|
55
|
+
writable: true
|
|
56
|
+
});
|
|
57
|
+
} else {
|
|
58
|
+
obj[key] = value;
|
|
59
|
+
}
|
|
60
|
+
return obj;
|
|
61
|
+
}
|
|
62
|
+
function _instanceof(left, right) {
|
|
63
|
+
if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) {
|
|
64
|
+
return !!right[Symbol.hasInstance](left);
|
|
65
|
+
} else {
|
|
66
|
+
return left instanceof right;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
function _ts_generator(thisArg, body) {
|
|
70
|
+
var f, y, t, _ = {
|
|
71
|
+
label: 0,
|
|
72
|
+
sent: function() {
|
|
73
|
+
if (t[0] & 1) throw t[1];
|
|
74
|
+
return t[1];
|
|
75
|
+
},
|
|
76
|
+
trys: [],
|
|
77
|
+
ops: []
|
|
78
|
+
}, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
79
|
+
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() {
|
|
80
|
+
return this;
|
|
81
|
+
}), g;
|
|
82
|
+
function verb(n) {
|
|
83
|
+
return function(v) {
|
|
84
|
+
return step([
|
|
85
|
+
n,
|
|
86
|
+
v
|
|
87
|
+
]);
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
function step(op) {
|
|
91
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
92
|
+
while(g && (g = 0, op[0] && (_ = 0)), _)try {
|
|
93
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
94
|
+
if (y = 0, t) op = [
|
|
95
|
+
op[0] & 2,
|
|
96
|
+
t.value
|
|
97
|
+
];
|
|
98
|
+
switch(op[0]){
|
|
99
|
+
case 0:
|
|
100
|
+
case 1:
|
|
101
|
+
t = op;
|
|
102
|
+
break;
|
|
103
|
+
case 4:
|
|
104
|
+
_.label++;
|
|
105
|
+
return {
|
|
106
|
+
value: op[1],
|
|
107
|
+
done: false
|
|
108
|
+
};
|
|
109
|
+
case 5:
|
|
110
|
+
_.label++;
|
|
111
|
+
y = op[1];
|
|
112
|
+
op = [
|
|
113
|
+
0
|
|
114
|
+
];
|
|
115
|
+
continue;
|
|
116
|
+
case 7:
|
|
117
|
+
op = _.ops.pop();
|
|
118
|
+
_.trys.pop();
|
|
119
|
+
continue;
|
|
120
|
+
default:
|
|
121
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
|
|
122
|
+
_ = 0;
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
|
|
126
|
+
_.label = op[1];
|
|
127
|
+
break;
|
|
128
|
+
}
|
|
129
|
+
if (op[0] === 6 && _.label < t[1]) {
|
|
130
|
+
_.label = t[1];
|
|
131
|
+
t = op;
|
|
132
|
+
break;
|
|
133
|
+
}
|
|
134
|
+
if (t && _.label < t[2]) {
|
|
135
|
+
_.label = t[2];
|
|
136
|
+
_.ops.push(op);
|
|
137
|
+
break;
|
|
138
|
+
}
|
|
139
|
+
if (t[2]) _.ops.pop();
|
|
140
|
+
_.trys.pop();
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
op = body.call(thisArg, _);
|
|
144
|
+
} catch (e) {
|
|
145
|
+
op = [
|
|
146
|
+
6,
|
|
147
|
+
e
|
|
148
|
+
];
|
|
149
|
+
y = 0;
|
|
150
|
+
} finally{
|
|
151
|
+
f = t = 0;
|
|
152
|
+
}
|
|
153
|
+
if (op[0] & 5) throw op[1];
|
|
154
|
+
return {
|
|
155
|
+
value: op[0] ? op[1] : void 0,
|
|
156
|
+
done: true
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
import { SignJWT, importPKCS8, base64url } from 'jose';
|
|
161
|
+
import { existsSync } from 'fs';
|
|
162
|
+
import { createPrivateKey } from 'crypto';
|
|
163
|
+
import { loadPrivateKey, getPrivateKeyFingerprint, getPublicKeyFingerprint, resolvePrivateKeyPath } from './ssh-key-utils.js';
|
|
164
|
+
import { ProjectConfigManager } from '../commands/project-config-manager.js';
|
|
165
|
+
import { AgentSigner } from './ssh-agent-signer.js';
|
|
166
|
+
/**
|
|
167
|
+
* Check if an error indicates an encrypted key
|
|
168
|
+
*/ function isEncryptedKeyError(error) {
|
|
169
|
+
if (_instanceof(error, Error) && error.name === 'KeyEncryptedError') {
|
|
170
|
+
return true;
|
|
171
|
+
}
|
|
172
|
+
return false;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* JWT Auth Provider for authenticating API requests
|
|
176
|
+
* Uses SSH private keys to sign short-lived JWTs
|
|
177
|
+
* Falls back to ssh-agent for encrypted keys
|
|
178
|
+
*/ export var JwtAuthProvider = /*#__PURE__*/ function() {
|
|
179
|
+
"use strict";
|
|
180
|
+
function JwtAuthProvider() {
|
|
181
|
+
_class_call_check(this, JwtAuthProvider);
|
|
182
|
+
_define_property(this, "privateKey", null);
|
|
183
|
+
_define_property(this, "fingerprint", null);
|
|
184
|
+
_define_property(this, "initialized", false);
|
|
185
|
+
_define_property(this, "initError", null);
|
|
186
|
+
// Agent fallback support
|
|
187
|
+
_define_property(this, "encryptedKeyPath", null);
|
|
188
|
+
_define_property(this, "agentSigner", null);
|
|
189
|
+
_define_property(this, "agentKey", null);
|
|
190
|
+
_define_property(this, "useAgent", false);
|
|
191
|
+
this.initialize();
|
|
192
|
+
}
|
|
193
|
+
_create_class(JwtAuthProvider, [
|
|
194
|
+
{
|
|
195
|
+
key: "initialize",
|
|
196
|
+
value: function initialize() {
|
|
197
|
+
try {
|
|
198
|
+
// Get configured path from project config manager
|
|
199
|
+
var configManager = new ProjectConfigManager();
|
|
200
|
+
var configuredPath = configManager.getPrivateKeyPath();
|
|
201
|
+
var keyPath = resolvePrivateKeyPath(configuredPath);
|
|
202
|
+
if (!existsSync(keyPath)) {
|
|
203
|
+
this.initError = new Error("Private key not found at ".concat(keyPath, ". Run 'px auth login' to configure your SSH key, or set POSITRONIC_PRIVATE_KEY environment variable."));
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
this.privateKey = loadPrivateKey(keyPath);
|
|
207
|
+
this.fingerprint = getPrivateKeyFingerprint(this.privateKey);
|
|
208
|
+
this.initialized = true;
|
|
209
|
+
} catch (error) {
|
|
210
|
+
if (isEncryptedKeyError(error)) {
|
|
211
|
+
// Store the path for agent fallback - we'll try the agent in createToken()
|
|
212
|
+
var configManager1 = new ProjectConfigManager();
|
|
213
|
+
var configuredPath1 = configManager1.getPrivateKeyPath();
|
|
214
|
+
this.encryptedKeyPath = resolvePrivateKeyPath(configuredPath1);
|
|
215
|
+
this.initError = _instanceof(error, Error) ? error : new Error('Key is encrypted');
|
|
216
|
+
} else {
|
|
217
|
+
this.initError = _instanceof(error, Error) ? error : new Error('Failed to initialize JWT auth provider');
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
/**
|
|
224
|
+
* Check if the provider is ready to create JWTs
|
|
225
|
+
* Returns true if we have a direct key OR if we have an encrypted key
|
|
226
|
+
* that might work with agent fallback
|
|
227
|
+
*/ key: "isReady",
|
|
228
|
+
value: function isReady() {
|
|
229
|
+
// Direct key is loaded and ready
|
|
230
|
+
if (this.initialized && this.privateKey !== null) {
|
|
231
|
+
return true;
|
|
232
|
+
}
|
|
233
|
+
// Encrypted key might work with agent fallback
|
|
234
|
+
if (this.encryptedKeyPath !== null) {
|
|
235
|
+
return true;
|
|
236
|
+
}
|
|
237
|
+
return false;
|
|
238
|
+
}
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
/**
|
|
242
|
+
* Check if we have an encrypted key that requires agent fallback
|
|
243
|
+
*/ key: "hasEncryptedKey",
|
|
244
|
+
value: function hasEncryptedKey() {
|
|
245
|
+
return this.encryptedKeyPath !== null;
|
|
246
|
+
}
|
|
247
|
+
},
|
|
248
|
+
{
|
|
249
|
+
/**
|
|
250
|
+
* Get the error that occurred during initialization, if any
|
|
251
|
+
*/ key: "getError",
|
|
252
|
+
value: function getError() {
|
|
253
|
+
return this.initError;
|
|
254
|
+
}
|
|
255
|
+
},
|
|
256
|
+
{
|
|
257
|
+
/**
|
|
258
|
+
* Get the fingerprint of the loaded private key
|
|
259
|
+
*/ key: "getFingerprint",
|
|
260
|
+
value: function getFingerprint() {
|
|
261
|
+
return this.fingerprint;
|
|
262
|
+
}
|
|
263
|
+
},
|
|
264
|
+
{
|
|
265
|
+
key: "getAlgorithm",
|
|
266
|
+
value: /**
|
|
267
|
+
* Map SSH key type to JWT algorithm
|
|
268
|
+
*/ function getAlgorithm() {
|
|
269
|
+
if (!this.privateKey) {
|
|
270
|
+
throw new Error('Private key not loaded');
|
|
271
|
+
}
|
|
272
|
+
return this.getAlgorithmForKeyType(this.privateKey.type, this.privateKey.curve);
|
|
273
|
+
}
|
|
274
|
+
},
|
|
275
|
+
{
|
|
276
|
+
key: "getAlgorithmForKeyType",
|
|
277
|
+
value: /**
|
|
278
|
+
* Map SSH key type string to JWT algorithm
|
|
279
|
+
*/ function getAlgorithmForKeyType(keyType, curve) {
|
|
280
|
+
if (keyType === 'rsa') {
|
|
281
|
+
return 'RS256';
|
|
282
|
+
} else if (keyType === 'ecdsa') {
|
|
283
|
+
// ECDSA curve determines algorithm
|
|
284
|
+
if (curve === 'nistp256') {
|
|
285
|
+
return 'ES256';
|
|
286
|
+
} else if (curve === 'nistp384') {
|
|
287
|
+
return 'ES384';
|
|
288
|
+
} else if (curve === 'nistp521') {
|
|
289
|
+
return 'ES512';
|
|
290
|
+
}
|
|
291
|
+
// Default to ES256 for unknown curves
|
|
292
|
+
return 'ES256';
|
|
293
|
+
} else if (keyType === 'ed25519') {
|
|
294
|
+
return 'EdDSA';
|
|
295
|
+
}
|
|
296
|
+
throw new Error("Unsupported key type: ".concat(keyType));
|
|
297
|
+
}
|
|
298
|
+
},
|
|
299
|
+
{
|
|
300
|
+
key: "getPkcs8Pem",
|
|
301
|
+
value: /**
|
|
302
|
+
* Convert the SSH private key to PKCS8 PEM format
|
|
303
|
+
* Ed25519 keys need special handling because sshpk's PKCS8 output
|
|
304
|
+
* is not compatible with Node.js/OpenSSL
|
|
305
|
+
*/ function getPkcs8Pem() {
|
|
306
|
+
if (!this.privateKey) {
|
|
307
|
+
throw new Error('Private key not loaded');
|
|
308
|
+
}
|
|
309
|
+
if (this.privateKey.type === 'ed25519') {
|
|
310
|
+
// For Ed25519, sshpk's PKCS8 output includes the public key in a format
|
|
311
|
+
// that Node.js/OpenSSL doesn't understand. Instead, we construct a JWK
|
|
312
|
+
// from the raw key parts and let Node's crypto handle the conversion.
|
|
313
|
+
// sshpk stores Ed25519 key data in 'k' (seed) and 'A' (public) parts
|
|
314
|
+
var parts = this.privateKey.part;
|
|
315
|
+
var seed = parts.k.data;
|
|
316
|
+
var publicKey = parts.A.data;
|
|
317
|
+
// Construct JWK and let Node's crypto convert to PKCS8
|
|
318
|
+
var jwk = {
|
|
319
|
+
kty: 'OKP',
|
|
320
|
+
crv: 'Ed25519',
|
|
321
|
+
d: seed.toString('base64url'),
|
|
322
|
+
x: publicKey.toString('base64url')
|
|
323
|
+
};
|
|
324
|
+
var keyObj = createPrivateKey({
|
|
325
|
+
key: jwk,
|
|
326
|
+
format: 'jwk'
|
|
327
|
+
});
|
|
328
|
+
return keyObj.export({
|
|
329
|
+
type: 'pkcs8',
|
|
330
|
+
format: 'pem'
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
// For RSA and ECDSA, sshpk's PKCS8 output works fine
|
|
334
|
+
return this.privateKey.toString('pkcs8');
|
|
335
|
+
}
|
|
336
|
+
},
|
|
337
|
+
{
|
|
338
|
+
key: "createToken",
|
|
339
|
+
value: /**
|
|
340
|
+
* Create a short-lived JWT for authentication
|
|
341
|
+
*/ function createToken() {
|
|
342
|
+
return _async_to_generator(function() {
|
|
343
|
+
return _ts_generator(this, function(_state) {
|
|
344
|
+
switch(_state.label){
|
|
345
|
+
case 0:
|
|
346
|
+
// If we have a direct private key, use the standard jose signing path
|
|
347
|
+
if (this.privateKey && this.fingerprint) {
|
|
348
|
+
return [
|
|
349
|
+
2,
|
|
350
|
+
this.createTokenDirect()
|
|
351
|
+
];
|
|
352
|
+
}
|
|
353
|
+
if (!this.encryptedKeyPath) return [
|
|
354
|
+
3,
|
|
355
|
+
2
|
|
356
|
+
];
|
|
357
|
+
return [
|
|
358
|
+
4,
|
|
359
|
+
this.tryAgentFallback()
|
|
360
|
+
];
|
|
361
|
+
case 1:
|
|
362
|
+
_state.sent();
|
|
363
|
+
_state.label = 2;
|
|
364
|
+
case 2:
|
|
365
|
+
// If agent fallback succeeded, use agent signing
|
|
366
|
+
if (this.useAgent && this.agentSigner && this.agentKey && this.fingerprint) {
|
|
367
|
+
return [
|
|
368
|
+
2,
|
|
369
|
+
this.createTokenWithAgent()
|
|
370
|
+
];
|
|
371
|
+
}
|
|
372
|
+
// No authentication method available
|
|
373
|
+
throw this.initError || new Error('JWT auth provider not initialized');
|
|
374
|
+
}
|
|
375
|
+
});
|
|
376
|
+
}).call(this);
|
|
377
|
+
}
|
|
378
|
+
},
|
|
379
|
+
{
|
|
380
|
+
key: "createTokenDirect",
|
|
381
|
+
value: /**
|
|
382
|
+
* Create JWT using direct private key (jose library)
|
|
383
|
+
*/ function createTokenDirect() {
|
|
384
|
+
return _async_to_generator(function() {
|
|
385
|
+
var algorithm, pkcs8Pem, joseKey, jwt;
|
|
386
|
+
return _ts_generator(this, function(_state) {
|
|
387
|
+
switch(_state.label){
|
|
388
|
+
case 0:
|
|
389
|
+
if (!this.privateKey || !this.fingerprint) {
|
|
390
|
+
throw new Error('Private key not loaded');
|
|
391
|
+
}
|
|
392
|
+
algorithm = this.getAlgorithm();
|
|
393
|
+
// Convert SSH private key to PKCS8 PEM format
|
|
394
|
+
pkcs8Pem = this.getPkcs8Pem();
|
|
395
|
+
return [
|
|
396
|
+
4,
|
|
397
|
+
importPKCS8(pkcs8Pem, algorithm)
|
|
398
|
+
];
|
|
399
|
+
case 1:
|
|
400
|
+
joseKey = _state.sent();
|
|
401
|
+
return [
|
|
402
|
+
4,
|
|
403
|
+
new SignJWT({}).setProtectedHeader({
|
|
404
|
+
alg: algorithm
|
|
405
|
+
}).setSubject(this.fingerprint).setIssuedAt().setExpirationTime('30s').sign(joseKey)
|
|
406
|
+
];
|
|
407
|
+
case 2:
|
|
408
|
+
jwt = _state.sent();
|
|
409
|
+
return [
|
|
410
|
+
2,
|
|
411
|
+
jwt
|
|
412
|
+
];
|
|
413
|
+
}
|
|
414
|
+
});
|
|
415
|
+
}).call(this);
|
|
416
|
+
}
|
|
417
|
+
},
|
|
418
|
+
{
|
|
419
|
+
key: "tryAgentFallback",
|
|
420
|
+
value: /**
|
|
421
|
+
* Try to use ssh-agent for signing when private key is encrypted
|
|
422
|
+
*/ function tryAgentFallback() {
|
|
423
|
+
return _async_to_generator(function() {
|
|
424
|
+
var pubKeyPath, fingerprint, agent, agentKey;
|
|
425
|
+
return _ts_generator(this, function(_state) {
|
|
426
|
+
switch(_state.label){
|
|
427
|
+
case 0:
|
|
428
|
+
if (!this.encryptedKeyPath) {
|
|
429
|
+
return [
|
|
430
|
+
2
|
|
431
|
+
];
|
|
432
|
+
}
|
|
433
|
+
// Get fingerprint from public key file
|
|
434
|
+
pubKeyPath = this.encryptedKeyPath + '.pub';
|
|
435
|
+
if (!existsSync(pubKeyPath)) {
|
|
436
|
+
throw new Error("Key is encrypted and public key file not found at ".concat(pubKeyPath, ".\n") + "Cannot determine key fingerprint for ssh-agent lookup.");
|
|
437
|
+
}
|
|
438
|
+
fingerprint = getPublicKeyFingerprint(pubKeyPath);
|
|
439
|
+
agent = new AgentSigner();
|
|
440
|
+
if (!agent.isAvailable()) {
|
|
441
|
+
throw new Error("Key is encrypted and ssh-agent is not running.\n" + "Start ssh-agent or use an unencrypted key.");
|
|
442
|
+
}
|
|
443
|
+
return [
|
|
444
|
+
4,
|
|
445
|
+
agent.hasKey(fingerprint)
|
|
446
|
+
];
|
|
447
|
+
case 1:
|
|
448
|
+
agentKey = _state.sent();
|
|
449
|
+
if (!agentKey) {
|
|
450
|
+
throw new Error("Key is encrypted and not loaded in ssh-agent.\n" + "Run: ssh-add ".concat(this.encryptedKeyPath));
|
|
451
|
+
}
|
|
452
|
+
this.agentSigner = agent;
|
|
453
|
+
this.agentKey = agentKey;
|
|
454
|
+
this.fingerprint = fingerprint;
|
|
455
|
+
this.useAgent = true;
|
|
456
|
+
this.initError = null;
|
|
457
|
+
this.initialized = true;
|
|
458
|
+
return [
|
|
459
|
+
2
|
|
460
|
+
];
|
|
461
|
+
}
|
|
462
|
+
});
|
|
463
|
+
}).call(this);
|
|
464
|
+
}
|
|
465
|
+
},
|
|
466
|
+
{
|
|
467
|
+
key: "createTokenWithAgent",
|
|
468
|
+
value: /**
|
|
469
|
+
* Create JWT using ssh-agent for signing
|
|
470
|
+
* Manually constructs the JWT since jose expects to do signing itself
|
|
471
|
+
*/ function createTokenWithAgent() {
|
|
472
|
+
return _async_to_generator(function() {
|
|
473
|
+
var keyType, curve, algorithm, header, encodedHeader, now, payload, encodedPayload, signingInput, signature, signatureBytes, encodedSignature;
|
|
474
|
+
return _ts_generator(this, function(_state) {
|
|
475
|
+
switch(_state.label){
|
|
476
|
+
case 0:
|
|
477
|
+
if (!this.agentSigner || !this.agentKey || !this.fingerprint) {
|
|
478
|
+
throw new Error('Agent signing not configured');
|
|
479
|
+
}
|
|
480
|
+
// Get algorithm from agent key type
|
|
481
|
+
keyType = this.agentKey.type;
|
|
482
|
+
curve = this.agentKey.curve;
|
|
483
|
+
algorithm = this.getAlgorithmForKeyType(keyType, curve);
|
|
484
|
+
// Build JWT header
|
|
485
|
+
header = {
|
|
486
|
+
alg: algorithm
|
|
487
|
+
};
|
|
488
|
+
encodedHeader = base64url.encode(JSON.stringify(header));
|
|
489
|
+
// Build JWT payload
|
|
490
|
+
now = Math.floor(Date.now() / 1000);
|
|
491
|
+
payload = {
|
|
492
|
+
sub: this.fingerprint,
|
|
493
|
+
iat: now,
|
|
494
|
+
exp: now + 30
|
|
495
|
+
};
|
|
496
|
+
encodedPayload = base64url.encode(JSON.stringify(payload));
|
|
497
|
+
// Create signing input
|
|
498
|
+
signingInput = "".concat(encodedHeader, ".").concat(encodedPayload);
|
|
499
|
+
return [
|
|
500
|
+
4,
|
|
501
|
+
this.agentSigner.sign(this.agentKey, Buffer.from(signingInput))
|
|
502
|
+
];
|
|
503
|
+
case 1:
|
|
504
|
+
signature = _state.sent();
|
|
505
|
+
// Convert sshpk.Signature to raw bytes for JWT
|
|
506
|
+
// sshpk's toBuffer() gives us the raw signature bytes
|
|
507
|
+
signatureBytes = signature.toBuffer('raw');
|
|
508
|
+
encodedSignature = base64url.encode(signatureBytes);
|
|
509
|
+
return [
|
|
510
|
+
2,
|
|
511
|
+
"".concat(signingInput, ".").concat(encodedSignature)
|
|
512
|
+
];
|
|
513
|
+
}
|
|
514
|
+
});
|
|
515
|
+
}).call(this);
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
]);
|
|
519
|
+
return JwtAuthProvider;
|
|
520
|
+
}();
|
|
521
|
+
// Singleton instance
|
|
522
|
+
var providerInstance = null;
|
|
523
|
+
/**
|
|
524
|
+
* Get the singleton JWT auth provider instance
|
|
525
|
+
*/ export function getJwtAuthProvider() {
|
|
526
|
+
if (!providerInstance) {
|
|
527
|
+
providerInstance = new JwtAuthProvider();
|
|
528
|
+
}
|
|
529
|
+
return providerInstance;
|
|
530
|
+
}
|
|
531
|
+
/**
|
|
532
|
+
* Reset the JWT auth provider singleton
|
|
533
|
+
* Call this after auth config changes to force reinitialization with new key
|
|
534
|
+
*/ export function resetJwtAuthProvider() {
|
|
535
|
+
providerInstance = null;
|
|
536
|
+
}
|
|
537
|
+
/**
|
|
538
|
+
* Check if JWT auth is available
|
|
539
|
+
*/ export function isAuthAvailable() {
|
|
540
|
+
return getJwtAuthProvider().isReady();
|
|
541
|
+
}
|
|
542
|
+
/**
|
|
543
|
+
* Get the Authorization header if auth is available
|
|
544
|
+
* Throws if there's an auth configuration error
|
|
545
|
+
* Returns empty object with warning if no key is configured
|
|
546
|
+
*/ export function getAuthHeader() {
|
|
547
|
+
return _async_to_generator(function() {
|
|
548
|
+
var provider, error, token;
|
|
549
|
+
return _ts_generator(this, function(_state) {
|
|
550
|
+
switch(_state.label){
|
|
551
|
+
case 0:
|
|
552
|
+
provider = getJwtAuthProvider();
|
|
553
|
+
if (!provider.isReady()) {
|
|
554
|
+
error = provider.getError();
|
|
555
|
+
if (error) {
|
|
556
|
+
throw error;
|
|
557
|
+
}
|
|
558
|
+
console.warn('Warning: No SSH key configured for authentication. Run "px auth login" to configure.');
|
|
559
|
+
return [
|
|
560
|
+
2,
|
|
561
|
+
{}
|
|
562
|
+
];
|
|
563
|
+
}
|
|
564
|
+
return [
|
|
565
|
+
4,
|
|
566
|
+
provider.createToken()
|
|
567
|
+
];
|
|
568
|
+
case 1:
|
|
569
|
+
token = _state.sent();
|
|
570
|
+
return [
|
|
571
|
+
2,
|
|
572
|
+
{
|
|
573
|
+
Authorization: "Bearer ".concat(token)
|
|
574
|
+
}
|
|
575
|
+
];
|
|
576
|
+
}
|
|
577
|
+
});
|
|
578
|
+
})();
|
|
579
|
+
}
|