@adinsure-ops/ops-cli 5.4.2 → 5.5.0-rc1
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 +140 -2
- package/bin/run.js +2 -6
- package/lib/command.base.d.ts +7 -1
- package/lib/command.base.jira.d.ts +23 -5
- package/lib/command.base.jira.js +47 -12
- package/lib/command.base.js +37 -8
- package/lib/command.download.d.ts +11 -0
- package/lib/command.download.js +27 -0
- package/lib/commands/config/get.d.ts +1 -1
- package/lib/commands/config/list.js +1 -1
- package/lib/commands/config/set.d.ts +2 -2
- package/lib/commands/config/set.js +2 -2
- package/lib/commands/config/unset.d.ts +1 -1
- package/lib/commands/docker/update-image-version.d.ts +31 -3
- package/lib/commands/docker/update-image-version.js +112 -6
- package/lib/commands/doctor.d.ts +1 -1
- package/lib/commands/download/client.d.ts +7 -20
- package/lib/commands/download/client.js +12 -47
- package/lib/commands/download/identity-server.d.ts +7 -20
- package/lib/commands/download/identity-server.js +12 -47
- package/lib/commands/download/jmeter.d.ts +3 -3
- package/lib/commands/download/jmeter.js +9 -11
- package/lib/commands/download/keycloak-scim.d.ts +4 -4
- package/lib/commands/download/keycloak-scim.js +9 -11
- package/lib/commands/download/platform.d.ts +7 -20
- package/lib/commands/download/platform.js +12 -47
- package/lib/commands/download/scheduler.d.ts +7 -20
- package/lib/commands/download/scheduler.js +12 -47
- package/lib/commands/download/server.d.ts +7 -20
- package/lib/commands/download/server.js +12 -47
- package/lib/commands/download/signalr.d.ts +7 -20
- package/lib/commands/download/signalr.js +12 -47
- package/lib/commands/download/studio.d.ts +12 -24
- package/lib/commands/download/studio.js +14 -48
- package/lib/commands/gitlab/get-tag-pipeline.d.ts +7 -7
- package/lib/commands/gitlab/get-tag-pipeline.js +5 -5
- package/lib/commands/gitlab/next-nightly-tag.d.ts +7 -7
- package/lib/commands/gitlab/next-nightly-tag.js +6 -6
- package/lib/commands/jira/issue.d.ts +4 -4
- package/lib/commands/jira/issue.js +2 -2
- package/lib/commands/jira/labels.d.ts +8 -9
- package/lib/commands/jira/labels.js +11 -10
- package/lib/commands/log/add.d.ts +10 -5
- package/lib/commands/log/add.js +42 -13
- package/lib/commands/log/generate.d.ts +6 -6
- package/lib/commands/log/generate.js +16 -8
- package/lib/commands/log/validate.js +2 -2
- package/lib/commands/login.d.ts +25 -5
- package/lib/commands/login.js +162 -40
- package/lib/commands/login.ru.d.ts +2 -2
- package/lib/commands/login.ru.js +1 -1
- package/lib/commands/npm/check-publish.d.ts +4 -4
- package/lib/commands/npm/check-publish.js +1 -1
- package/lib/commands/npm/dependency-update.d.ts +17 -4
- package/lib/commands/npm/dependency-update.js +64 -41
- package/lib/commands/npm/publish.d.ts +5 -5
- package/lib/commands/npm/publish.js +2 -2
- package/lib/commands/nuget/dependency-update.d.ts +3 -3
- package/lib/commands/prepare-content.d.ts +3 -3
- package/lib/commands/prepare-content.js +24 -41
- package/lib/commands/sql.d.ts +17 -17
- package/lib/commands/sql.js +23 -27
- package/lib/commands/translate.d.ts +8 -8
- package/lib/commands/translate.js +10 -8
- package/lib/commands/version.d.ts +10 -10
- package/lib/commands/version.js +6 -7
- package/lib/lib/command.d.ts +5 -3
- package/lib/lib/command.js +44 -44
- package/lib/lib/config.js +1 -1
- package/lib/lib/gitlab.d.ts +3 -1
- package/lib/lib/gitlab.js +13 -7
- package/lib/lib/http.d.ts +37 -0
- package/lib/lib/http.js +278 -0
- package/lib/lib/npm.d.ts +7 -4
- package/lib/lib/npm.js +15 -6
- package/lib/lib/npmrc.js +3 -3
- package/lib/lib/yarnrc.js +3 -3
- package/lib/security/cache.js +1 -1
- package/lib/security/context.d.ts +10 -8
- package/lib/security/context.js +49 -64
- package/oclif.manifest.json +533 -532
- package/package.json +71 -62
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
import
|
|
1
|
+
import { ParsedUrlQuery } from 'node:querystring';
|
|
2
|
+
import HttpClient from '../lib/http.js';
|
|
3
3
|
/**
|
|
4
4
|
* Security context that keeps track of current authentication token.
|
|
5
5
|
* It's not recommended you instantiate this class on your own but rather inherit your commands from [[CommandBase]].
|
|
6
6
|
*/
|
|
7
7
|
export default class SecurityContext {
|
|
8
|
+
private readonly http;
|
|
8
9
|
private readonly clientId;
|
|
9
10
|
private readonly devopsResourceId;
|
|
10
11
|
private readonly managementCoreWindowsNet;
|
|
@@ -25,7 +26,7 @@ export default class SecurityContext {
|
|
|
25
26
|
* Initializes [[SecurityContext]] with config directory where access token JSON will be stored.
|
|
26
27
|
* @param configDir Directory where CLI configuration is stored
|
|
27
28
|
*/
|
|
28
|
-
constructor(configDir: string);
|
|
29
|
+
constructor(configDir: string, http?: HttpClient);
|
|
29
30
|
/**
|
|
30
31
|
* Get the accessTokenPath, as it is a private variable
|
|
31
32
|
* @returns {string} Returns access token path
|
|
@@ -42,10 +43,10 @@ export default class SecurityContext {
|
|
|
42
43
|
*/
|
|
43
44
|
getConfigPath(): string;
|
|
44
45
|
/**
|
|
45
|
-
*
|
|
46
|
+
* Generates a PKCE pair and builds the AAD sign-in URL for the interactive browser login.
|
|
47
|
+
* The PKCE verifier is kept for the following [[acquireToken]] call.
|
|
46
48
|
*
|
|
47
|
-
* @
|
|
48
|
-
* @returns [[Promise<TokenResponse>]]
|
|
49
|
+
* @returns Promise that resolves the authorization URL to open in the browser
|
|
49
50
|
*/
|
|
50
51
|
getLoginUrl(): Promise<string>;
|
|
51
52
|
/**
|
|
@@ -83,8 +84,9 @@ export default class SecurityContext {
|
|
|
83
84
|
/**
|
|
84
85
|
* Contacts authority server, fetches and saves the authentication token to be used in subsequent requests.
|
|
85
86
|
*
|
|
86
|
-
* @param query
|
|
87
|
-
* @
|
|
87
|
+
* @param query Query of the AAD redirect: `code` and `client_info`, or `error` and `error_description`.
|
|
88
|
+
* @throws Error when the redirect carries an error, the PKCE verifier is missing or the code exchange fails
|
|
89
|
+
* @returns Promise that resolves the signed-in account's display name, username, or '' when neither is known
|
|
88
90
|
*/
|
|
89
91
|
acquireToken(query: ParsedUrlQuery): Promise<string>;
|
|
90
92
|
/**
|
package/lib/security/context.js
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import { __awaiter } from "tslib";
|
|
2
2
|
import { AuthError, ConfidentialClientApplication, CryptoProvider, InteractionRequiredAuthError, PublicClientApplication, } from '@azure/msal-node';
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import fs from 'fs';
|
|
6
|
-
import querystring from 'querystring';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import fs from 'node:fs';
|
|
7
5
|
import LocalCachePlugin from './cache.js';
|
|
8
|
-
import
|
|
6
|
+
import HttpClient from '../lib/http.js';
|
|
9
7
|
/**
|
|
10
8
|
* Security context that keeps track of current authentication token.
|
|
11
9
|
* It's not recommended you instantiate this class on your own but rather inherit your commands from [[CommandBase]].
|
|
@@ -15,7 +13,8 @@ export default class SecurityContext {
|
|
|
15
13
|
* Initializes [[SecurityContext]] with config directory where access token JSON will be stored.
|
|
16
14
|
* @param configDir Directory where CLI configuration is stored
|
|
17
15
|
*/
|
|
18
|
-
constructor(configDir) {
|
|
16
|
+
constructor(configDir, http = new HttpClient()) {
|
|
17
|
+
this.http = http;
|
|
19
18
|
this.clientId = 'bed40d09-53d7-4af8-bf63-3288658b65fb';
|
|
20
19
|
this.devopsResourceId = '499b84ac-1321-427f-aa17-267ca6975798';
|
|
21
20
|
this.managementCoreWindowsNet = 'https://management.core.windows.net//';
|
|
@@ -63,38 +62,25 @@ export default class SecurityContext {
|
|
|
63
62
|
return this._accessConfigPath;
|
|
64
63
|
}
|
|
65
64
|
/**
|
|
66
|
-
*
|
|
65
|
+
* Generates a PKCE pair and builds the AAD sign-in URL for the interactive browser login.
|
|
66
|
+
* The PKCE verifier is kept for the following [[acquireToken]] call.
|
|
67
67
|
*
|
|
68
|
-
* @
|
|
69
|
-
* @returns [[Promise<TokenResponse>]]
|
|
68
|
+
* @returns Promise that resolves the authorization URL to open in the browser
|
|
70
69
|
*/
|
|
71
70
|
getLoginUrl() {
|
|
72
|
-
return
|
|
71
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
73
72
|
// Generate PKCE Codes before starting the authorization flow
|
|
74
|
-
this._cryptoProvider
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
this.
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
// Get url to sign user in and consent to scopes needed for applicatio
|
|
86
|
-
this._pca
|
|
87
|
-
.getAuthCodeUrl(authCodeUrlParameters)
|
|
88
|
-
.then((url) => {
|
|
89
|
-
resolve(url);
|
|
90
|
-
})
|
|
91
|
-
.catch((error) => {
|
|
92
|
-
reject(JSON.stringify(error));
|
|
93
|
-
});
|
|
94
|
-
})
|
|
95
|
-
.catch((error) => {
|
|
96
|
-
reject(error);
|
|
97
|
-
});
|
|
73
|
+
const { verifier, challenge } = yield this._cryptoProvider.generatePkceCodes();
|
|
74
|
+
this._verifier = verifier;
|
|
75
|
+
this._challenge = challenge;
|
|
76
|
+
const authCodeUrlParameters = {
|
|
77
|
+
scopes: [this.resource + '/.default', 'offline_access'],
|
|
78
|
+
redirectUri: this.redirectUri,
|
|
79
|
+
codeChallenge: this._challenge,
|
|
80
|
+
codeChallengeMethod: 'S256',
|
|
81
|
+
};
|
|
82
|
+
// Get url to sign user in and consent to scopes needed for application
|
|
83
|
+
return this._pca.getAuthCodeUrl(authCodeUrlParameters);
|
|
98
84
|
});
|
|
99
85
|
}
|
|
100
86
|
/**
|
|
@@ -155,7 +141,7 @@ export default class SecurityContext {
|
|
|
155
141
|
forceCache: true,
|
|
156
142
|
});
|
|
157
143
|
if (tokenRespone === null) {
|
|
158
|
-
throw new AuthError('Cannot retrieve user cache and use the refresh token!');
|
|
144
|
+
throw new AuthError('refresh_token_failed', '', 'Cannot retrieve user cache and use the refresh token!');
|
|
159
145
|
}
|
|
160
146
|
resolve(tokenRespone.accessToken);
|
|
161
147
|
//eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -205,9 +191,7 @@ export default class SecurityContext {
|
|
|
205
191
|
})
|
|
206
192
|
.then((response) => {
|
|
207
193
|
if (response) {
|
|
208
|
-
|
|
209
|
-
console.log(accessToken);
|
|
210
|
-
resolve(accessToken);
|
|
194
|
+
resolve(response.accessToken);
|
|
211
195
|
}
|
|
212
196
|
else {
|
|
213
197
|
reject(new Error('Error getting token, please call `ops login`.'));
|
|
@@ -219,7 +203,7 @@ export default class SecurityContext {
|
|
|
219
203
|
}
|
|
220
204
|
}
|
|
221
205
|
else {
|
|
222
|
-
|
|
206
|
+
reject(new Error('You are not authenticated, please call `ops login`.'));
|
|
223
207
|
}
|
|
224
208
|
}));
|
|
225
209
|
});
|
|
@@ -242,7 +226,7 @@ export default class SecurityContext {
|
|
|
242
226
|
//eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
243
227
|
}
|
|
244
228
|
catch (err) {
|
|
245
|
-
throw new Error(`Failed to retrieve GitLabRu token: ${err.message}
|
|
229
|
+
throw new Error(`Failed to retrieve GitLabRu token: ${err.message}`, { cause: err });
|
|
246
230
|
}
|
|
247
231
|
}
|
|
248
232
|
getAADToken() {
|
|
@@ -287,7 +271,7 @@ export default class SecurityContext {
|
|
|
287
271
|
// service=<registry>
|
|
288
272
|
// tenant=<tenantId>
|
|
289
273
|
// access_token=<aadAccessToken>
|
|
290
|
-
const postData =
|
|
274
|
+
const postData = new URLSearchParams({
|
|
291
275
|
grant_type: 'access_token',
|
|
292
276
|
service: this.registry, // e.g., "adinsure.azurecr.io"
|
|
293
277
|
tenant: this.tenantId, // e.g., "cdeb9156-219a-49e3-b414-f63acd298e9c"
|
|
@@ -296,7 +280,7 @@ export default class SecurityContext {
|
|
|
296
280
|
// Define the URL for token exchange:
|
|
297
281
|
const url = `https://${this.registry}/oauth2/exchange`;
|
|
298
282
|
// Make the POST request with the appropriate headers.
|
|
299
|
-
const response = yield
|
|
283
|
+
const response = yield this.http.postForm(url, postData, {
|
|
300
284
|
headers: {
|
|
301
285
|
'Content-Type': 'application/x-www-form-urlencoded',
|
|
302
286
|
},
|
|
@@ -311,20 +295,28 @@ export default class SecurityContext {
|
|
|
311
295
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
312
296
|
}
|
|
313
297
|
catch (error) {
|
|
314
|
-
throw new Error('Failed to retrieve ACR token: ' + error.message);
|
|
298
|
+
throw new Error('Failed to retrieve ACR token: ' + error.message, { cause: error });
|
|
315
299
|
}
|
|
316
300
|
});
|
|
317
301
|
}
|
|
318
302
|
/**
|
|
319
303
|
* Contacts authority server, fetches and saves the authentication token to be used in subsequent requests.
|
|
320
304
|
*
|
|
321
|
-
* @param query
|
|
322
|
-
* @
|
|
305
|
+
* @param query Query of the AAD redirect: `code` and `client_info`, or `error` and `error_description`.
|
|
306
|
+
* @throws Error when the redirect carries an error, the PKCE verifier is missing or the code exchange fails
|
|
307
|
+
* @returns Promise that resolves the signed-in account's display name, username, or '' when neither is known
|
|
323
308
|
*/
|
|
324
309
|
acquireToken(query) {
|
|
325
|
-
return
|
|
310
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
311
|
+
var _a, _b, _c, _d, _e, _f;
|
|
326
312
|
if (this._verifier === null) {
|
|
327
|
-
throw new Error(
|
|
313
|
+
throw new Error('PKCE verifier missing.');
|
|
314
|
+
}
|
|
315
|
+
if (!query.code) {
|
|
316
|
+
const reason = (_b = (_a = query.error_description) !== null && _a !== void 0 ? _a : query.error) !== null && _b !== void 0 ? _b : 'Authorization code missing.';
|
|
317
|
+
// The redirect query is untrusted input; keep terminal control sequences out of the message.
|
|
318
|
+
// eslint-disable-next-line no-control-regex
|
|
319
|
+
throw new Error(`Login failed: ${String(reason).replace(/[\u0000-\u001f\u007f-\u009f]/g, '')}`);
|
|
328
320
|
}
|
|
329
321
|
// Add PKCE code verifier to token request object
|
|
330
322
|
const tokenRequest = {
|
|
@@ -334,25 +326,18 @@ export default class SecurityContext {
|
|
|
334
326
|
codeVerifier: this._verifier,
|
|
335
327
|
clientInfo: query.client_info,
|
|
336
328
|
};
|
|
337
|
-
|
|
338
|
-
.acquireTokenByCode(tokenRequest)
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
resolve(token.account.name);
|
|
343
|
-
}
|
|
344
|
-
})
|
|
345
|
-
.catch((error) => {
|
|
329
|
+
try {
|
|
330
|
+
const token = yield this._pca.acquireTokenByCode(tokenRequest);
|
|
331
|
+
return (_f = (_d = (_c = token.account) === null || _c === void 0 ? void 0 : _c.name) !== null && _d !== void 0 ? _d : (_e = token.account) === null || _e === void 0 ? void 0 : _e.username) !== null && _f !== void 0 ? _f : '';
|
|
332
|
+
}
|
|
333
|
+
catch (error) {
|
|
346
334
|
if (error instanceof AuthError) {
|
|
347
|
-
|
|
348
|
-
console.
|
|
349
|
-
console.
|
|
350
|
-
console.log(`Inner error message: + ${authError.errorMessage}`);
|
|
351
|
-
console.log(`Error correlation id: + ${authError.correlationId}`);
|
|
352
|
-
console.error();
|
|
335
|
+
// The message itself is reported by the caller; add only what helps trace the request.
|
|
336
|
+
console.error(`Error name: ${error.name}`);
|
|
337
|
+
console.error(`Error correlation id: ${error.correlationId}`);
|
|
353
338
|
}
|
|
354
|
-
throw
|
|
355
|
-
}
|
|
339
|
+
throw error;
|
|
340
|
+
}
|
|
356
341
|
});
|
|
357
342
|
}
|
|
358
343
|
/**
|