artifact-engine 1.271.1 → 2.272.0

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.
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.publishEvent = void 0;
4
4
  var tl = require('azure-pipelines-task-lib');
5
5
  var packagejson = require('../package.json');
6
- const area = 'artifact-engine';
6
+ const area = 'artifact-engine-v2';
7
7
  function getDefaultProps() {
8
8
  var hostType = (tl.getVariable('SYSTEM.HOSTTYPE') || "").toLowerCase();
9
9
  var isReleaseHost = hostType === 'release' || hostType === "deployment";
@@ -11,7 +11,7 @@ class BasicCredentialHandler {
11
11
  // currently implements pre-authorization
12
12
  // TODO: support preAuth = false where it hooks on 401
13
13
  prepareRequest(options) {
14
- options.headers['Authorization'] = 'Basic ' + new Buffer(this.username + ':' + this.password).toString('base64');
14
+ options.headers['Authorization'] = 'Basic ' + Buffer.from(this.username + ':' + this.password, 'utf8').toString('base64');
15
15
  options.headers['X-TFS-FedAuthRedirect'] = 'Suppress';
16
16
  }
17
17
  // This handler cannot handle 401
@@ -1,6 +1,15 @@
1
1
  "use strict";
2
2
  // Copyright (c) Microsoft. All rights reserved.
3
3
  // Licensed under the MIT license. See LICENSE file in the project root for full license information.
4
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
5
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
6
+ return new (P || (P = Promise))(function (resolve, reject) {
7
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
8
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
9
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
10
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
11
+ });
12
+ };
4
13
  Object.defineProperty(exports, "__esModule", { value: true });
5
14
  exports.NtlmCredentialHandler = void 0;
6
15
  const http = require("http");
@@ -91,26 +100,28 @@ class NtlmCredentialHandler {
91
100
  }
92
101
  // The following method is an adaptation of code found at https://github.com/SamDecrock/node-http-ntlm/blob/master/httpntlm.js
93
102
  sendType3Message(httpClient, protocol, options, objs, keepaliveAgent, res, callback) {
94
- if (!res.headers['www-authenticate']) {
95
- return callback(new Error('www-authenticate not found on response of second request'));
96
- }
97
- // parse type2 message from server:
98
- var type2msg = ntlm.parseType2Message(res.headers['www-authenticate']);
99
- // create type3 message:
100
- var type3msg = ntlm.createType3Message(type2msg, options);
101
- // build type3 request:
102
- var type3options = {
103
- headers: {
104
- 'Authorization': type3msg
105
- },
106
- allowRedirects: false,
107
- agent: keepaliveAgent
108
- };
109
- // pass along other options:
110
- type3options.headers = _.extend(type3options.headers, options.headers);
111
- type3options = _.extend(type3options, _.omit(options, 'headers'));
112
- // send type3 message to server:
113
- httpClient.requestInternal(protocol, type3options, objs, callback);
103
+ return __awaiter(this, void 0, void 0, function* () {
104
+ if (!res.headers['www-authenticate']) {
105
+ return callback(new Error('www-authenticate not found on response of second request'));
106
+ }
107
+ // parse type2 message from server:
108
+ var type2msg = ntlm.parseType2Message(res.headers['www-authenticate']);
109
+ // create type3 message:
110
+ var type3msg = yield ntlm.createType3Message(type2msg, options);
111
+ // build type3 request:
112
+ var type3options = {
113
+ headers: {
114
+ 'Authorization': type3msg
115
+ },
116
+ allowRedirects: false,
117
+ agent: keepaliveAgent
118
+ };
119
+ // pass along other options:
120
+ type3options.headers = _.extend(type3options.headers, options.headers);
121
+ type3options = _.extend(type3options, _.omit(options, 'headers'));
122
+ // send type3 message to server:
123
+ httpClient.requestInternal(protocol, type3options, objs, callback);
124
+ });
114
125
  }
115
126
  }
116
127
  exports.NtlmCredentialHandler = NtlmCredentialHandler;
@@ -10,7 +10,7 @@ class PersonalAccessTokenCredentialHandler {
10
10
  // currently implements pre-authorization
11
11
  // TODO: support preAuth = false where it hooks on 401
12
12
  prepareRequest(options) {
13
- options.headers['Authorization'] = 'Basic ' + new Buffer('PAT:' + this.token).toString('base64');
13
+ options.headers['Authorization'] = 'Basic ' + Buffer.from('PAT:' + this.token, 'utf8').toString('base64');
14
14
  options.headers['X-TFS-FedAuthRedirect'] = 'Suppress';
15
15
  }
16
16
  // This handler cannot handle 401
@@ -1,4 +1,5 @@
1
1
  var crypto = require('crypto');
2
+ var hashwasm = require('hash-wasm');
2
3
 
3
4
  var flags = {
4
5
  NTLM_NegotiateUnicode : 0x00000001,
@@ -70,7 +71,7 @@ function createType1Message(options){
70
71
  type1flags = type1flags - flags.NTLM_NegotiateOemDomainSupplied;
71
72
 
72
73
  var pos = 0;
73
- var buf = new Buffer(BODY_LENGTH + domain.length + workstation.length);
74
+ var buf = Buffer.alloc(BODY_LENGTH + domain.length + workstation.length);
74
75
 
75
76
 
76
77
  buf.write(protocol, pos, protocol.length); pos += protocol.length; // protocol
@@ -105,7 +106,7 @@ function parseType2Message(rawmsg, callback){
105
106
  if(!match || !match[1])
106
107
  return callback(new Error("Couldn't find NTLM in the message type2 comming from the server"));
107
108
 
108
- var buf = new Buffer(match[1], 'base64');
109
+ var buf = Buffer.from(match[1], 'base64');
109
110
 
110
111
  var msg = {};
111
112
 
@@ -133,7 +134,7 @@ function parseType2Message(rawmsg, callback){
133
134
  return msg;
134
135
  }
135
136
 
136
- function createType3Message(msg2, options){
137
+ async function createType3Message(msg2, options){
137
138
  var nonce = msg2.serverChallenge;
138
139
  var username = options.username;
139
140
  var password = options.password;
@@ -151,27 +152,27 @@ function createType3Message(msg2, options){
151
152
 
152
153
  var encryptedRandomSessionKey = "";
153
154
  if(isUnicode){
154
- workstationBytes = new Buffer(workstation, 'utf16le');
155
- domainNameBytes = new Buffer(domainName, 'utf16le');
156
- usernameBytes = new Buffer(username, 'utf16le');
157
- encryptedRandomSessionKeyBytes = new Buffer(encryptedRandomSessionKey, 'utf16le');
155
+ workstationBytes = Buffer.from(workstation, 'utf16le');
156
+ domainNameBytes = Buffer.from(domainName, 'utf16le');
157
+ usernameBytes = Buffer.from(username, 'utf16le');
158
+ encryptedRandomSessionKeyBytes = Buffer.from(encryptedRandomSessionKey, 'utf16le');
158
159
  }else{
159
- workstationBytes = new Buffer(workstation, 'ascii');
160
- domainNameBytes = new Buffer(domainName, 'ascii');
161
- usernameBytes = new Buffer(username, 'ascii');
162
- encryptedRandomSessionKeyBytes = new Buffer(encryptedRandomSessionKey, 'ascii');
160
+ workstationBytes = Buffer.from(workstation, 'ascii');
161
+ domainNameBytes = Buffer.from(domainName, 'ascii');
162
+ usernameBytes = Buffer.from(username, 'ascii');
163
+ encryptedRandomSessionKeyBytes = Buffer.from(encryptedRandomSessionKey, 'ascii');
163
164
  }
164
165
 
165
166
  var lmChallengeResponse = calc_resp(create_LM_hashed_password_v1(password), nonce);
166
- var ntChallengeResponse = calc_resp(create_NT_hashed_password_v1(password), nonce);
167
+ var ntChallengeResponse = calc_resp(await create_NT_hashed_password_v1(password), nonce);
167
168
 
168
169
  if(isNegotiateExtendedSecurity){
169
- var pwhash = create_NT_hashed_password_v1(password);
170
+ var pwhash = await create_NT_hashed_password_v1(password);
170
171
  var clientChallenge = "";
171
172
  for(var i=0; i < 8; i++){
172
173
  clientChallenge += String.fromCharCode( Math.floor(Math.random()*256) );
173
174
  }
174
- var clientChallengeBytes = new Buffer(clientChallenge, 'ascii');
175
+ var clientChallengeBytes = Buffer.from(clientChallenge, 'ascii');
175
176
  var challenges = ntlm2sr_calc_resp(pwhash, nonce, clientChallengeBytes);
176
177
  lmChallengeResponse = challenges.lmChallengeResponse;
177
178
  ntChallengeResponse = challenges.ntChallengeResponse;
@@ -180,7 +181,7 @@ function createType3Message(msg2, options){
180
181
  var signature = 'NTLMSSP\0';
181
182
 
182
183
  var pos = 0;
183
- var buf = new Buffer(BODY_LENGTH + domainNameBytes.length + usernameBytes.length + workstationBytes.length + lmChallengeResponse.length + ntChallengeResponse.length + encryptedRandomSessionKeyBytes.length);
184
+ var buf = Buffer.alloc(BODY_LENGTH + domainNameBytes.length + usernameBytes.length + workstationBytes.length + lmChallengeResponse.length + ntChallengeResponse.length + encryptedRandomSessionKeyBytes.length);
184
185
 
185
186
  buf.write(signature, pos, signature.length); pos += signature.length;
186
187
  buf.writeUInt32LE(3, pos); pos += 4; // type 1
@@ -232,9 +233,9 @@ function createType3Message(msg2, options){
232
233
  function create_LM_hashed_password_v1(password){
233
234
  // fix the password length to 14 bytes
234
235
  password = password.toUpperCase();
235
- var passwordBytes = new Buffer(password, 'ascii');
236
+ var passwordBytes = Buffer.from(password, 'ascii');
236
237
 
237
- var passwordBytesPadded = new Buffer(14);
238
+ var passwordBytesPadded = Buffer.alloc(14);
238
239
  passwordBytesPadded.fill("\0");
239
240
  var sourceEnd = 14;
240
241
  if(passwordBytes.length < 14) sourceEnd = passwordBytes.length;
@@ -329,23 +330,22 @@ function binaryArray2bytes(array){
329
330
  var hexchar1 = binary2hex[binString1];
330
331
  var hexchar2 = binary2hex[binString2];
331
332
 
332
- var buf = new Buffer(hexchar1 + '' + hexchar2, 'hex');
333
+ var buf = Buffer.from(hexchar1 + '' + hexchar2, 'hex');
333
334
  bufArray.push(buf);
334
335
  }
335
336
 
336
337
  return Buffer.concat(bufArray);
337
338
  }
338
339
 
339
- function create_NT_hashed_password_v1(password){
340
- var buf = new Buffer(password, 'utf16le');
341
- var md4 = crypto.createHash('md4'); // CodeQL [SM04514] Suppress - NTLM only supports md4 and md5 hashing algorithms which are weak but cannot be changed to sha256 as the protocol does not support it
342
- md4.update(buf); // CodeQL [SM01511] Suppress - NTLM only supports md4 and md5 hashing algorithms which are weak but cannot be changed to sha256 as the protocol does not support it
343
- return new Buffer(md4.digest());
340
+ async function create_NT_hashed_password_v1(password){
341
+ var buf = Buffer.from(password, 'utf16le');
342
+ var hexHash = await hashwasm.md4(buf); // CodeQL [SM04514] [SM01511] Suppress - NTLM requires md4 hashing which is weak but cannot be changed as the protocol does not support stronger algorithms. Using hash-wasm (pure JS/WASM) since crypto.createHash('md4') was removed in Node 17+ (OpenSSL 3.0)
343
+ return Buffer.from(hexHash, 'hex');
344
344
  }
345
345
 
346
346
  function calc_resp(password_hash, server_challenge){
347
347
  // padding with zeros to make the hash 21 bytes long
348
- var passHashPadded = new Buffer(21);
348
+ var passHashPadded = Buffer.alloc(21);
349
349
  passHashPadded.fill("\0");
350
350
  password_hash.copy(passHashPadded, 0, 0, password_hash.length);
351
351
 
@@ -365,7 +365,7 @@ function calc_resp(password_hash, server_challenge){
365
365
 
366
366
  function ntlm2sr_calc_resp(responseKeyNT, serverChallenge, clientChallenge){
367
367
  // padding with zeros to make the hash 16 bytes longer
368
- var lmChallengeResponse = new Buffer(clientChallenge.length + 16);
368
+ var lmChallengeResponse = Buffer.alloc(clientChallenge.length + 16);
369
369
  lmChallengeResponse.fill("\0");
370
370
  clientChallenge.copy(lmChallengeResponse, 0, 0, clientChallenge.length);
371
371
 
@@ -383,7 +383,4 @@ function ntlm2sr_calc_resp(responseKeyNT, serverChallenge, clientChallenge){
383
383
 
384
384
  exports.createType1Message = createType1Message;
385
385
  exports.parseType2Message = parseType2Message;
386
- exports.createType3Message = createType3Message;
387
-
388
-
389
-
386
+ exports.createType3Message = createType3Message;
@@ -47,11 +47,14 @@ class WebClientFactory {
47
47
  if (lookupKey && lookupKey.indexOf(':') > 0) {
48
48
  let lookupInfo = lookupKey.split(':', 2);
49
49
  // file contains encryption key
50
- let keyFile = new Buffer(lookupInfo[0], 'base64').toString('utf8');
51
- let encryptKey = new Buffer(fs.readFileSync(keyFile, 'utf8'), 'base64');
52
- let encryptedContent = new Buffer(lookupInfo[1], 'base64').toString('utf8');
53
- // @ts-ignore there is no type definition for createDecipher method
54
- let decipher = crypto.createDecipher("aes-256-ctr", encryptKey);
50
+ let keyFile = Buffer.from(lookupInfo[0], 'base64').toString('utf8');
51
+ let encryptKey = Buffer.from(fs.readFileSync(keyFile, 'utf8'), 'base64');
52
+ let encryptedContent = Buffer.from(lookupInfo[1], 'base64').toString('utf8');
53
+ // Ensure key is 32 bytes for AES-256
54
+ const key = encryptKey.length === 32 ? encryptKey : crypto.createHash('sha256').update(encryptKey).digest();
55
+ // Use zero IV for AES-256-CTR (must match encryption side)
56
+ const iv = Buffer.alloc(16, 0);
57
+ let decipher = crypto.createDecipheriv("aes-256-ctr", key, iv);
55
58
  let decryptedContent = decipher.update(encryptedContent, 'hex', 'utf8');
56
59
  decryptedContent += decipher.final('utf8');
57
60
  return decryptedContent;
package/README.md CHANGED
@@ -16,7 +16,7 @@ To use Artifact engine in your tasks or app have a look at [E2E.ts](E2ETests/jen
16
16
  ## Development
17
17
  **Build**
18
18
  ---------
19
- 1. Run npm install in ArtifactEngine folder
19
+ 1. Run npm install in ArtifactEngineV2 folder
20
20
  2. Use command ctrl-shift-b to build from vscode
21
21
 
22
22
  **Testing**
@@ -30,10 +30,10 @@ To use Artifact engine in your tasks or app have a look at [E2E.ts](E2ETests/jen
30
30
  ------
31
31
  1. To run ArtifactEngine integration and unit tests from root directory use
32
32
 
33
- `gulp test --suite=ArtifactEngine`
33
+ `gulp test --suite=ArtifactEngineV2`
34
34
  2. To run Performance tests update [test config file](test.config.json.example) and rename it to test.config.json and run
35
35
 
36
- `gulp test --suite=ArtifactEngine --perf`
36
+ `gulp test --suite=ArtifactEngineV2 --perf`
37
37
  3. To run End-to-End tests update [test config file](test.config.json.example) and rename it to test.config.json and run
38
38
 
39
- `gulp test --suite=ArtifactEngine --e2e`
39
+ `gulp test --suite=ArtifactEngineV2 --e2e`
package/lib.json CHANGED
@@ -7,8 +7,8 @@
7
7
  "UnableToReadDirectory": "Unable to read directory %s. Error: %s",
8
8
  "RetryingDownload": "Retrying download of %s, retry count: %s",
9
9
  "SkippingItem": "Skipped processing item %s",
10
- "UnhandledRejection": "artifact-engine: unhandled rejection %s",
11
- "UnhandledException": "artifact-engine: unhandled exception %s",
10
+ "UnhandledRejection": "artifact-engine-v2: unhandled rejection %s",
11
+ "UnhandledException": "artifact-engine-v2: unhandled exception %s",
12
12
  "FailedRequest": "Failed request: (statusCode)"
13
13
  }
14
14
  }
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "artifact-engine",
3
- "version": "1.271.1",
3
+ "version": "2.272.0",
4
4
  "description": "Artifact Engine to download artifacts from jenkins, teamcity, vsts",
5
5
  "repository": {
6
6
  "type": "git",
7
- "url": "https://github.com/Microsoft/azure-pipelines-extensions/tree/master/Extensions/ArtifactEngine"
7
+ "url": "https://github.com/Microsoft/azure-pipelines-extensions/tree/master/Extensions/ArtifactEngineV2"
8
8
  },
9
9
  "keywords": [
10
10
  "artifact"
@@ -18,25 +18,23 @@
18
18
  "dependencies": {
19
19
  "azure-pipelines-task-lib": "^5.2.8",
20
20
  "handlebars": "4.7.7",
21
- "minimatch": "3.1.5",
21
+ "hash-wasm": "^4.12.0",
22
+ "minimatch": "^10.0.1",
22
23
  "tunnel": "0.0.4"
23
24
  },
24
- "overrides": {
25
- "minimatch": "3.1.5"
26
- },
27
25
  "devDependencies": {
28
- "@types/minimatch": "^2.0.29",
26
+ "@types/minimatch": "^5.1.2",
29
27
  "@types/mocha": "^10.0.10",
30
- "@types/node": "^10.17.0",
28
+ "@types/node": "^22.10.5",
31
29
  "@types/xml2js": "^0.4.8",
32
30
  "assert": "1.4.1",
33
31
  "mocha": "^11.7.5",
34
32
  "mocha-tap-reporter": "0.1.3",
35
33
  "nconf": "^0.12.0",
36
- "nock": "9.1.0",
37
- "nyc": "^15.0.0",
38
- "sinon": "4.0.1",
39
- "typescript": "4.0.2",
34
+ "nock": "^13.5.6",
35
+ "nyc": "^17.1.0",
36
+ "sinon": "^19.0.2",
37
+ "typescript": "^5.7.2",
40
38
  "xml2js": "^0.6.2"
41
39
  },
42
40
  "files": [
@@ -56,7 +54,8 @@
56
54
  "Strings/**"
57
55
  ],
58
56
  "scripts": {
59
- "test": "nyc ./node_modules/mocha/bin/_mocha --reporter mocha-tap-reporter **/*Tests.js",
57
+ "test": "mocha",
58
+ "test:coverage": "nyc mocha",
60
59
  "build": "tsc"
61
60
  }
62
61
  }