postman-runtime 7.19.0 → 7.21.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.
- package/.eslintrc +1 -1
- package/CHANGELOG.yaml +45 -0
- package/README.md +8 -0
- package/lib/authorizer/aws4.js +1 -1
- package/lib/authorizer/basic.js +1 -3
- package/lib/authorizer/edgegrid.js +1 -1
- package/lib/authorizer/hawk.js +1 -1
- package/lib/authorizer/ntlm.js +79 -4
- package/lib/authorizer/oauth2.js +25 -20
- package/lib/requester/core.js +19 -5
- package/lib/runner/extensions/event.command.js +8 -1
- package/lib/runner/extensions/item.command.js +39 -4
- package/package.json +11 -11
- package/test/fixtures/server.js +123 -9
- package/test/integration/auth-methods/edgegrid.test.js +76 -2
- package/test/integration/auth-methods/ntlm.test.js +232 -6
- package/test/integration/benchmark/large-response.test.js +79 -0
- package/test/integration/sandbox-libraries/console.test.js +167 -0
- package/test/integration/sandbox-libraries/pm.test.js +55 -0
- package/test/integration/sanity/proxy-http.test.js +69 -0
- package/test/unit/auth-handlers.test.js +64 -37
package/.eslintrc
CHANGED
package/CHANGELOG.yaml
CHANGED
|
@@ -1,3 +1,48 @@
|
|
|
1
|
+
7.21.0:
|
|
2
|
+
date: 2019-12-02
|
|
3
|
+
new features:
|
|
4
|
+
- >-
|
|
5
|
+
GH-937 Added ability to use OAuth2 tokens with unknown types as Bearer
|
|
6
|
+
token in OAuth2 authentication
|
|
7
|
+
- GH-934 Added ability to pull domain name from username for NTLM auth
|
|
8
|
+
fixed bugs:
|
|
9
|
+
- >-
|
|
10
|
+
GH-939 Fixed a bug where IPv6 localhost request through IPv4 localhost
|
|
11
|
+
proxy was failing.
|
|
12
|
+
- >-
|
|
13
|
+
GH-928 Fixed a bug where Basic Auth was failing if credentials had
|
|
14
|
+
non-ASCII characters
|
|
15
|
+
- >-
|
|
16
|
+
GH-929 Fixed a bug where error was thrown when `username` or `password`
|
|
17
|
+
fields were empty for NTLM auth
|
|
18
|
+
- >-
|
|
19
|
+
GH-933 Fixed a bug where NTLM could not complete authentication if
|
|
20
|
+
multiple `www-authenticate` headers were sent
|
|
21
|
+
chores:
|
|
22
|
+
- >-
|
|
23
|
+
GH-942 Convert response into a JSON serializable object before executing
|
|
24
|
+
the script
|
|
25
|
+
- Updated dependencies
|
|
26
|
+
|
|
27
|
+
7.20.1:
|
|
28
|
+
date: 2019-11-13
|
|
29
|
+
chores:
|
|
30
|
+
- Updated dependencies
|
|
31
|
+
|
|
32
|
+
7.20.0:
|
|
33
|
+
date: 2019-11-12
|
|
34
|
+
new features:
|
|
35
|
+
- GH-921 Added ability to preserve non-JSON data types in console logs
|
|
36
|
+
- >-
|
|
37
|
+
GH-921 Added an option `script.serializeLogs` to allow sending logs as a
|
|
38
|
+
serialized string which can be parsed using `teleport-javascript`
|
|
39
|
+
fixed bugs:
|
|
40
|
+
- >-
|
|
41
|
+
GH-918 Fixed a bug where requests having binary body with AWS, Hawk or
|
|
42
|
+
EdgeGrid authentication caused the Runtime to crash
|
|
43
|
+
chores:
|
|
44
|
+
- Updated dependencies
|
|
45
|
+
|
|
1
46
|
7.19.0:
|
|
2
47
|
date: 2019-10-16
|
|
3
48
|
new features:
|
package/README.md
CHANGED
|
@@ -135,6 +135,14 @@ runner.run(collection, {
|
|
|
135
135
|
}
|
|
136
136
|
},
|
|
137
137
|
|
|
138
|
+
// Options specific to the script execution
|
|
139
|
+
script: {
|
|
140
|
+
|
|
141
|
+
// Option to set whether to send console logs in serialized format which can be parsed
|
|
142
|
+
// using the `teleport-javascript` serialization library.
|
|
143
|
+
serializeLogs: false
|
|
144
|
+
},
|
|
145
|
+
|
|
138
146
|
// A ProxyConfigList, from the SDK
|
|
139
147
|
proxies: new sdk.ProxyConfigList(),
|
|
140
148
|
|
package/lib/authorizer/aws4.js
CHANGED
|
@@ -63,7 +63,7 @@ var _ = require('lodash'),
|
|
|
63
63
|
return callback();
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
originalReadStream.cloneReadStream(function (err, clonedStream) {
|
|
66
|
+
return originalReadStream.cloneReadStream(function (err, clonedStream) {
|
|
67
67
|
if (err) { return callback(); }
|
|
68
68
|
|
|
69
69
|
clonedStream.on('data', function (chunk) {
|
package/lib/authorizer/basic.js
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
var btoa = require('btoa');
|
|
2
|
-
|
|
3
1
|
/**
|
|
4
2
|
* @implements {AuthHandlerInterface}
|
|
5
3
|
*/
|
|
@@ -70,7 +68,7 @@ module.exports = {
|
|
|
70
68
|
request.removeHeader('Authorization', {ignoreCase: true});
|
|
71
69
|
request.addHeader({
|
|
72
70
|
key: 'Authorization',
|
|
73
|
-
value: 'Basic ' +
|
|
71
|
+
value: 'Basic ' + Buffer.from(`${username}:${password}`, 'utf8').toString('base64'),
|
|
74
72
|
system: true
|
|
75
73
|
});
|
|
76
74
|
|
|
@@ -142,7 +142,7 @@ var _ = require('lodash'),
|
|
|
142
142
|
return callback();
|
|
143
143
|
}
|
|
144
144
|
|
|
145
|
-
originalReadStream.cloneReadStream(function (err, clonedStream) {
|
|
145
|
+
return originalReadStream.cloneReadStream(function (err, clonedStream) {
|
|
146
146
|
if (err) { return callback(); }
|
|
147
147
|
|
|
148
148
|
clonedStream.on('data', function (chunk) {
|
package/lib/authorizer/hawk.js
CHANGED
|
@@ -90,7 +90,7 @@ function computeBodyHash (body, algorithm, digestEncoding, contentType, callback
|
|
|
90
90
|
return callback();
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
-
originalReadStream.cloneReadStream(function (err, clonedStream) {
|
|
93
|
+
return originalReadStream.cloneReadStream(function (err, clonedStream) {
|
|
94
94
|
if (err) { return callback(); }
|
|
95
95
|
|
|
96
96
|
clonedStream.on('data', function (chunk) {
|
package/lib/authorizer/ntlm.js
CHANGED
|
@@ -31,6 +31,58 @@ var ntlmUtil = require('httpntlm').ntlm,
|
|
|
31
31
|
T3_MSG_CREATED: 'T3_MSG_CREATED'
|
|
32
32
|
};
|
|
33
33
|
|
|
34
|
+
/**
|
|
35
|
+
* Parses the username to separate username and domain. It can handle two formats:
|
|
36
|
+
* - Down-Level Logon name format `DOMAIN\USERNAME`
|
|
37
|
+
* - User Principal Name format `USERNAME@DOMAIN`
|
|
38
|
+
*
|
|
39
|
+
* @param {String} username - Username string to parse from
|
|
40
|
+
* @return {Object} - An object with `username` and `domain` fields, which are `strings`.
|
|
41
|
+
*/
|
|
42
|
+
function parseParametersFromUsername (username) {
|
|
43
|
+
var dllParams,
|
|
44
|
+
upnParams;
|
|
45
|
+
|
|
46
|
+
if (!(username && typeof username === 'string')) {
|
|
47
|
+
return {
|
|
48
|
+
username: EMPTY,
|
|
49
|
+
domain: EMPTY
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
dllParams = username.split('\\');
|
|
54
|
+
upnParams = username.split('@');
|
|
55
|
+
|
|
56
|
+
// username should be either of the two formats, not both
|
|
57
|
+
if (dllParams.length > 1 && upnParams.length > 1) {
|
|
58
|
+
return {
|
|
59
|
+
username,
|
|
60
|
+
domain: EMPTY
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// try to parse from "down level logon" format
|
|
65
|
+
if (dllParams.length === 2 && dllParams[0] && dllParams[1]) {
|
|
66
|
+
return {
|
|
67
|
+
username: dllParams[1],
|
|
68
|
+
domain: dllParams[0]
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// try to parse from "user principal name" format
|
|
73
|
+
if (upnParams.length === 2 && upnParams[0] && upnParams[1]) {
|
|
74
|
+
return {
|
|
75
|
+
username: upnParams[0],
|
|
76
|
+
domain: upnParams[1]
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return {
|
|
81
|
+
username,
|
|
82
|
+
domain: EMPTY
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
34
86
|
/**
|
|
35
87
|
* NTLM auth while authenticating requires negotiateMessage (type 1) and authenticateMessage (type 3) to be stored.
|
|
36
88
|
* Also it needs to know which stage is it in (INITIALIZED, T1_MSG_CREATED and T3_MSG_CREATED).
|
|
@@ -96,16 +148,26 @@ module.exports = {
|
|
|
96
148
|
var state = auth.get(STATE),
|
|
97
149
|
domain = auth.get(NTLM_PARAMETERS.DOMAIN) || EMPTY,
|
|
98
150
|
workstation = auth.get(NTLM_PARAMETERS.WORKSTATION) || EMPTY,
|
|
99
|
-
username = auth.get(NTLM_PARAMETERS.USERNAME),
|
|
100
|
-
password = auth.get(NTLM_PARAMETERS.PASSWORD),
|
|
151
|
+
username = auth.get(NTLM_PARAMETERS.USERNAME) || EMPTY,
|
|
152
|
+
password = auth.get(NTLM_PARAMETERS.PASSWORD) || EMPTY,
|
|
101
153
|
negotiateMessage, // type 1
|
|
102
154
|
challengeMessage, // type 2
|
|
103
|
-
authenticateMessage
|
|
155
|
+
authenticateMessage, // type 3
|
|
156
|
+
ntlmType2Header,
|
|
157
|
+
parsedParameters;
|
|
104
158
|
|
|
105
159
|
if (response.code !== 401 && response.code !== 403) {
|
|
106
160
|
return done(null, true);
|
|
107
161
|
}
|
|
108
162
|
|
|
163
|
+
// we try to extract domain from username if not specified.
|
|
164
|
+
if (!domain) {
|
|
165
|
+
parsedParameters = parseParametersFromUsername(username) || {};
|
|
166
|
+
|
|
167
|
+
username = parsedParameters.username;
|
|
168
|
+
domain = parsedParameters.domain;
|
|
169
|
+
}
|
|
170
|
+
|
|
109
171
|
if (state === STATES.INITIALIZED) {
|
|
110
172
|
// Nothing to do if the server does not ask us for auth in the first place.
|
|
111
173
|
if (!(response.headers.has(WWW_AUTHENTICATE, NTLM) ||
|
|
@@ -130,7 +192,20 @@ module.exports = {
|
|
|
130
192
|
}
|
|
131
193
|
else if (state === STATES.T1_MSG_CREATED) {
|
|
132
194
|
// At this point, we can assume that the type 1 message was sent to the server
|
|
133
|
-
|
|
195
|
+
|
|
196
|
+
// there can be multiple headers present with key `www-authenticate`.
|
|
197
|
+
// iterate to get the one which has the NTLM hash. if multiple
|
|
198
|
+
// headers have the NTLM hash, use the first one.
|
|
199
|
+
ntlmType2Header = response.headers.find(function (header) {
|
|
200
|
+
return String(header.key).toLowerCase() === WWW_AUTHENTICATE &&
|
|
201
|
+
header.valueOf().startsWith('NTLM ');
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
if (!ntlmType2Header) {
|
|
205
|
+
return done(new Error('ntlm: server did not send NTLM type 2 message'));
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
challengeMessage = ntlmUtil.parseType2Message(ntlmType2Header.valueOf(), _.noop);
|
|
134
209
|
|
|
135
210
|
if (!challengeMessage) {
|
|
136
211
|
return done(new Error('ntlm: server did not correctly process authentication request'));
|
package/lib/authorizer/oauth2.js
CHANGED
|
@@ -3,6 +3,7 @@ var _ = require('lodash'),
|
|
|
3
3
|
HEADER = 'header',
|
|
4
4
|
QUERY_PARAMS = 'queryParams',
|
|
5
5
|
BEARER = 'bearer',
|
|
6
|
+
MAC = 'mac',
|
|
6
7
|
AUTHORIZATION = 'Authorization',
|
|
7
8
|
ACCESS_TOKEN = 'access_token',
|
|
8
9
|
AUTHORIZATION_PREFIX = 'Bearer ',
|
|
@@ -94,27 +95,31 @@ module.exports = {
|
|
|
94
95
|
tokenType = _.toLower(params.tokenType);
|
|
95
96
|
|
|
96
97
|
// @TODO Add support for HMAC
|
|
97
|
-
if (tokenType ===
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
// and clear them before the sign step for any auth
|
|
101
|
-
request.removeHeader(AUTHORIZATION, {ignoreCase: true});
|
|
102
|
-
request.removeQueryParams([ACCESS_TOKEN]);
|
|
98
|
+
if (tokenType === MAC) {
|
|
99
|
+
return done();
|
|
100
|
+
}
|
|
103
101
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
}
|
|
102
|
+
// treat every token types (other than MAC) as bearer token
|
|
103
|
+
|
|
104
|
+
// clean conflicting headers and query params
|
|
105
|
+
// @todo: we should be able to get conflicting params from auth manifest
|
|
106
|
+
// and clear them before the sign step for any auth
|
|
107
|
+
request.removeHeader(AUTHORIZATION, {ignoreCase: true});
|
|
108
|
+
request.removeQueryParams([ACCESS_TOKEN]);
|
|
109
|
+
|
|
110
|
+
if (params.addTokenTo === QUERY_PARAMS) {
|
|
111
|
+
request.addQueryParams({
|
|
112
|
+
key: ACCESS_TOKEN,
|
|
113
|
+
value: params.accessToken,
|
|
114
|
+
system: true
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
else if (params.addTokenTo === HEADER) {
|
|
118
|
+
request.addHeader({
|
|
119
|
+
key: AUTHORIZATION,
|
|
120
|
+
value: AUTHORIZATION_PREFIX + params.accessToken,
|
|
121
|
+
system: true
|
|
122
|
+
});
|
|
118
123
|
}
|
|
119
124
|
|
|
120
125
|
return done();
|
package/lib/requester/core.js
CHANGED
|
@@ -251,12 +251,14 @@ module.exports = {
|
|
|
251
251
|
self = this,
|
|
252
252
|
bodyParams,
|
|
253
253
|
url = request.url && urlEncoder.toNodeUrl(request.url.toString(true)),
|
|
254
|
-
isSSL,
|
|
254
|
+
isSSL = _.startsWith(url.protocol, HTTPS),
|
|
255
|
+
isTunnelingProxy = request.proxy && (request.proxy.tunnel || isSSL),
|
|
255
256
|
reqOption,
|
|
256
257
|
portNumber,
|
|
257
258
|
behaviorName,
|
|
258
259
|
port = url && url.port,
|
|
259
|
-
hostname = url && url.hostname && url.hostname.toLowerCase()
|
|
260
|
+
hostname = url && url.hostname && url.hostname.toLowerCase(),
|
|
261
|
+
proxyHostname = request.proxy && request.proxy.host;
|
|
260
262
|
|
|
261
263
|
!defaultOpts && (defaultOpts = {});
|
|
262
264
|
!protocolProfileBehavior && (protocolProfileBehavior = {});
|
|
@@ -268,6 +270,10 @@ module.exports = {
|
|
|
268
270
|
hostname = LOCALHOST;
|
|
269
271
|
}
|
|
270
272
|
|
|
273
|
+
if (getTLD(proxyHostname) === LOCALHOST) {
|
|
274
|
+
proxyHostname = LOCALHOST;
|
|
275
|
+
}
|
|
276
|
+
|
|
271
277
|
options.url = url;
|
|
272
278
|
options.method = request.method;
|
|
273
279
|
options.jar = defaultOpts.cookieJar || true;
|
|
@@ -334,9 +340,17 @@ module.exports = {
|
|
|
334
340
|
self.ensureHeaderExists(options.headers, 'Host', url.host);
|
|
335
341
|
|
|
336
342
|
// override DNS lookup
|
|
337
|
-
if (networkOptions.restrictedAddresses || hostname === LOCALHOST ||
|
|
338
|
-
|
|
339
|
-
|
|
343
|
+
if (networkOptions.restrictedAddresses || hostname === LOCALHOST ||
|
|
344
|
+
(!isTunnelingProxy && proxyHostname === LOCALHOST) || networkOptions.hostLookup) {
|
|
345
|
+
// Use proxy port for localhost resolution in case of non-tunneling proxy
|
|
346
|
+
// because the request will be sent to proxy server by postman-request
|
|
347
|
+
if (request.proxy && !isTunnelingProxy) {
|
|
348
|
+
portNumber = Number(request.proxy.port);
|
|
349
|
+
}
|
|
350
|
+
// Otherwise, use request's port
|
|
351
|
+
else {
|
|
352
|
+
portNumber = Number(port) || (isSSL ? HTTPS_DEFAULT_PORT : HTTP_DEFAULT_PORT);
|
|
353
|
+
}
|
|
340
354
|
|
|
341
355
|
_.isFinite(portNumber) && (options.lookup = lookup.bind(this, {
|
|
342
356
|
port: portNumber,
|
|
@@ -428,6 +428,7 @@ module.exports = {
|
|
|
428
428
|
timeout: payload.scriptTimeout, // @todo: Expose this as a property in Collection SDK's Script
|
|
429
429
|
cursor: scriptCursor,
|
|
430
430
|
context: _.pick(payload.context, SAFE_CONTEXT_VARIABLES),
|
|
431
|
+
serializeLogs: _.get(this, 'options.script.serializeLogs'),
|
|
431
432
|
|
|
432
433
|
// legacy options
|
|
433
434
|
legacy: {
|
|
@@ -489,7 +490,13 @@ module.exports = {
|
|
|
489
490
|
result && result.collectionVariables &&
|
|
490
491
|
(result.collectionVariables = new sdk.VariableScope(result.collectionVariables));
|
|
491
492
|
result && result.request && (result.request = new sdk.Request(result.request));
|
|
492
|
-
|
|
493
|
+
|
|
494
|
+
// @note Since postman-sandbox@3.5.2, response object is not included in the execution result.
|
|
495
|
+
// Refer: https://github.com/postmanlabs/postman-sandbox/pull/512
|
|
496
|
+
// Adding back here to avoid breaking change in `script` callback.
|
|
497
|
+
// @todo revisit script callback args in runtime v8.
|
|
498
|
+
payload.context && payload.context.response &&
|
|
499
|
+
(result.response = new sdk.Response(payload.context.response));
|
|
493
500
|
|
|
494
501
|
// persist the pm.variables for the next script
|
|
495
502
|
result && result._variables &&
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
var _ = require('lodash'),
|
|
2
2
|
uuid = require('uuid'),
|
|
3
|
+
Response = require('postman-collection').Response,
|
|
3
4
|
visualizer = require('../../visualizer'),
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
|
-
* List of request properties which can be mutated via
|
|
7
|
+
* List of request properties which can be mutated via pre-request
|
|
7
8
|
*
|
|
8
9
|
* @private
|
|
9
10
|
* @const
|
|
@@ -11,7 +12,8 @@ var _ = require('lodash'),
|
|
|
11
12
|
*/
|
|
12
13
|
ALLOWED_REQUEST_MUTATIONS = ['url', 'method', 'headers'],
|
|
13
14
|
|
|
14
|
-
extractVisualizerData
|
|
15
|
+
extractVisualizerData,
|
|
16
|
+
getResponseJSON;
|
|
15
17
|
|
|
16
18
|
/**
|
|
17
19
|
* Returns visualizer data from the latest execution result.
|
|
@@ -36,7 +38,7 @@ extractVisualizerData = function (prereqExecutions, testExecutions) {
|
|
|
36
38
|
}
|
|
37
39
|
|
|
38
40
|
if (_.isArray(prereqExecutions)) {
|
|
39
|
-
//
|
|
41
|
+
// extract visualizer data from pre-request script results if it is not found earlier
|
|
40
42
|
for (i = prereqExecutions.length - 1; i >= 0; i--) {
|
|
41
43
|
visualizerData = _.get(prereqExecutions[i], 'result.return.visualizer');
|
|
42
44
|
|
|
@@ -47,6 +49,31 @@ extractVisualizerData = function (prereqExecutions, testExecutions) {
|
|
|
47
49
|
}
|
|
48
50
|
};
|
|
49
51
|
|
|
52
|
+
/**
|
|
53
|
+
* Convert response into a JSON serializable object.
|
|
54
|
+
* The stream property is converted to base64 string for performance reasons.
|
|
55
|
+
*
|
|
56
|
+
* @param {Object} response - SDK Response instance
|
|
57
|
+
* @returns {Object}
|
|
58
|
+
*/
|
|
59
|
+
getResponseJSON = function (response) {
|
|
60
|
+
if (!Response.isResponse(response)) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return {
|
|
65
|
+
id: response.id,
|
|
66
|
+
code: response.code,
|
|
67
|
+
status: response.status,
|
|
68
|
+
header: response.headers && response.headers.toJSON(),
|
|
69
|
+
stream: response.stream && {
|
|
70
|
+
type: 'Base64',
|
|
71
|
+
data: response.stream.toString('base64')
|
|
72
|
+
},
|
|
73
|
+
responseTime: response.responseTime
|
|
74
|
+
};
|
|
75
|
+
};
|
|
76
|
+
|
|
50
77
|
/**
|
|
51
78
|
* Add options
|
|
52
79
|
* stopOnError:Boolean
|
|
@@ -173,7 +200,15 @@ module.exports = {
|
|
|
173
200
|
|
|
174
201
|
// also the test object requires the updated request object (since auth helpers may modify it)
|
|
175
202
|
request && (ctxTemplate.request = request);
|
|
176
|
-
|
|
203
|
+
|
|
204
|
+
// @note convert response instance to plain object.
|
|
205
|
+
// we want to avoid calling Response.toJSON() which triggers toJSON on Response.stream buffer.
|
|
206
|
+
// Because that increases the size of stringified object by 3 times.
|
|
207
|
+
// Also, that increases the total number of tokens (buffer.data) whereas Buffer.toString
|
|
208
|
+
// generates a single string that is easier to stringify and sent over the UVM bridge.
|
|
209
|
+
response && (ctxTemplate.response = getResponseJSON(response));
|
|
210
|
+
|
|
211
|
+
// set cookies for this transaction
|
|
177
212
|
cookies && (ctxTemplate.cookies = cookies);
|
|
178
213
|
|
|
179
214
|
// the context template also has a test object to store assertions
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "postman-runtime",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.21.0",
|
|
4
4
|
"description": "Underlying library of executing Postman Collections (used by Newman)",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"directories": {
|
|
@@ -30,21 +30,20 @@
|
|
|
30
30
|
"license": "Apache-2.0",
|
|
31
31
|
"dependencies": {
|
|
32
32
|
"async": "2.6.2",
|
|
33
|
-
"aws4": "1.
|
|
34
|
-
"btoa": "1.2.1",
|
|
33
|
+
"aws4": "1.9.0",
|
|
35
34
|
"crypto-js": "3.1.9-1",
|
|
36
35
|
"eventemitter3": "4.0.0",
|
|
37
|
-
"handlebars": "4.
|
|
36
|
+
"handlebars": "4.5.3",
|
|
38
37
|
"http-reasons": "0.1.0",
|
|
39
38
|
"httpntlm": "1.7.6",
|
|
40
39
|
"inherits": "2.0.4",
|
|
41
40
|
"lodash": "4.17.15",
|
|
42
41
|
"node-oauth1": "1.2.2",
|
|
43
42
|
"performance-now": "2.1.0",
|
|
44
|
-
"postman-collection": "3.5.
|
|
45
|
-
"postman-request": "2.88.1-postman.
|
|
46
|
-
"postman-sandbox": "3.
|
|
47
|
-
"postman-url-encoder": "1.0.
|
|
43
|
+
"postman-collection": "3.5.5",
|
|
44
|
+
"postman-request": "2.88.1-postman.16",
|
|
45
|
+
"postman-sandbox": "3.5.2",
|
|
46
|
+
"postman-url-encoder": "1.0.3",
|
|
48
47
|
"resolve-from": "5.0.0",
|
|
49
48
|
"serialised-error": "1.1.3",
|
|
50
49
|
"tough-cookie": "3.0.1",
|
|
@@ -58,21 +57,22 @@
|
|
|
58
57
|
"eslint": "5.16.0",
|
|
59
58
|
"eslint-plugin-jsdoc": "8.7.0",
|
|
60
59
|
"eslint-plugin-lodash": "5.1.0",
|
|
61
|
-
"eslint-plugin-mocha": "6.2.
|
|
60
|
+
"eslint-plugin-mocha": "6.2.2",
|
|
62
61
|
"eslint-plugin-security": "1.4.0",
|
|
63
62
|
"graphql": "14.5.8",
|
|
64
63
|
"http-proxy": "1.18.0",
|
|
65
64
|
"istanbul": "0.4.5",
|
|
66
65
|
"js-yaml": "3.13.1",
|
|
67
66
|
"jsdoc": "3.6.3",
|
|
68
|
-
"jsdoc-to-markdown": "5.0.
|
|
69
|
-
"mocha": "6.2.
|
|
67
|
+
"jsdoc-to-markdown": "5.0.3",
|
|
68
|
+
"mocha": "6.2.2",
|
|
70
69
|
"parse-gitignore": "0.5.1",
|
|
71
70
|
"postman-jsdoc-theme": "0.0.3",
|
|
72
71
|
"recursive-readdir": "2.2.2",
|
|
73
72
|
"server-destroy": "1.0.1",
|
|
74
73
|
"shelljs": "0.8.3",
|
|
75
74
|
"sinon": "7.5.0",
|
|
75
|
+
"teleport-javascript": "1.0.0",
|
|
76
76
|
"tmp": "0.1.0",
|
|
77
77
|
"yankee": "1.0.8"
|
|
78
78
|
},
|
package/test/fixtures/server.js
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
const fs = require('fs'),
|
|
2
2
|
net = require('net'),
|
|
3
|
+
url = require('url'),
|
|
4
|
+
dns = require('dns'),
|
|
3
5
|
_ = require('lodash'),
|
|
4
6
|
path = require('path'),
|
|
5
7
|
http = require('http'),
|
|
6
8
|
https = require('https'),
|
|
7
9
|
crypto = require('crypto'),
|
|
8
10
|
GraphQL = require('graphql'),
|
|
11
|
+
ntlmUtils = require('httpntlm').ntlm,
|
|
9
12
|
enableServerDestroy = require('server-destroy');
|
|
10
13
|
|
|
11
14
|
/**
|
|
@@ -206,6 +209,7 @@ function createHTTPServer () {
|
|
|
206
209
|
* @param {Object} [options] - Additional options to configure proxy server
|
|
207
210
|
* @param {Object} [options.auth] - Proxy authentication, Basic auth
|
|
208
211
|
* @param {String} [options.agent] - Agent used for http(s).request
|
|
212
|
+
* @param {Boolean} [options.useIPv6] - If true, force using IPv6 address while forwarding request.
|
|
209
213
|
*
|
|
210
214
|
* @example
|
|
211
215
|
* var s = createProxyServer({
|
|
@@ -244,14 +248,22 @@ function createProxyServer (options) {
|
|
|
244
248
|
req.headers = Object.assign(req.headers, options.headers || {});
|
|
245
249
|
|
|
246
250
|
// forward request to the origin and pipe the response
|
|
247
|
-
var
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
251
|
+
var requestUrl = url.parse(req.url),
|
|
252
|
+
fwd = agent.request({
|
|
253
|
+
host: requestUrl.hostname,
|
|
254
|
+
path: requestUrl.path,
|
|
255
|
+
port: requestUrl.port,
|
|
256
|
+
method: req.method.toLowerCase(),
|
|
257
|
+
headers: req.headers,
|
|
258
|
+
lookup: options.useIPv6 && function (hostname, options, callback) {
|
|
259
|
+
!options && (options = {});
|
|
260
|
+
options.family = 6;
|
|
261
|
+
|
|
262
|
+
return dns.lookup(hostname, options, callback);
|
|
263
|
+
}
|
|
264
|
+
}, function (resp) {
|
|
265
|
+
resp.pipe(res);
|
|
266
|
+
});
|
|
255
267
|
|
|
256
268
|
req.pipe(fwd);
|
|
257
269
|
});
|
|
@@ -497,6 +509,106 @@ function createEdgeGridAuthServer (options) {
|
|
|
497
509
|
return server;
|
|
498
510
|
}
|
|
499
511
|
|
|
512
|
+
/**
|
|
513
|
+
* Creates an NTLM server.
|
|
514
|
+
*
|
|
515
|
+
* @param {Object} options - The options for the server
|
|
516
|
+
* @param {String} options.username - Username for authentication
|
|
517
|
+
* @param {String} options.password - Password for authentication
|
|
518
|
+
* @param {String} options.domain - Domain name for authentication
|
|
519
|
+
* @param {String} options.workstation - Workstation for authentication
|
|
520
|
+
* @param {Boolean} options.debug - Enable logging of requests
|
|
521
|
+
*
|
|
522
|
+
* @return {Object} - http server
|
|
523
|
+
*/
|
|
524
|
+
function createNTLMServer (options) {
|
|
525
|
+
options = options || {};
|
|
526
|
+
|
|
527
|
+
var type2Message = 'NTLM ' +
|
|
528
|
+
'TlRMTVNTUAACAAAAHgAeADgAAAAFgoqiBevywvJykjAAAAAAAAAAAJgAmABWAAAA' +
|
|
529
|
+
'CgC6RwAAAA9EAEUAUwBLAFQATwBQAC0ASgBTADQAVQBKAFQARAACAB4ARABFAFMA' +
|
|
530
|
+
'SwBUAE8AUAAtAEoAUwA0AFUASgBUAEQAAQAeAEQARQBTAEsAVABPAFAALQBKAFMA' +
|
|
531
|
+
'NABVAEoAVABEAAQAHgBEAEUAUwBLAFQATwBQAC0ASgBTADQAVQBKAFQARAADAB4A' +
|
|
532
|
+
'RABFAFMASwBUAE8AUAAtAEoAUwA0AFUASgBUAEQABwAIADmguzCHn9UBAAAAAA==',
|
|
533
|
+
parsedType2Message = ntlmUtils.parseType2Message(type2Message, _.noop),
|
|
534
|
+
|
|
535
|
+
username = options.username || 'username',
|
|
536
|
+
password = options.password || 'password',
|
|
537
|
+
domain = options.domain || '',
|
|
538
|
+
workstation = options.workstation || '',
|
|
539
|
+
|
|
540
|
+
type1Message = ntlmUtils.createType1Message({
|
|
541
|
+
domain,
|
|
542
|
+
workstation
|
|
543
|
+
}),
|
|
544
|
+
type3Message = ntlmUtils.createType3Message(parsedType2Message, {
|
|
545
|
+
domain,
|
|
546
|
+
workstation,
|
|
547
|
+
username,
|
|
548
|
+
password
|
|
549
|
+
}),
|
|
550
|
+
|
|
551
|
+
handler = function (req, res) {
|
|
552
|
+
var authHeaders = req.headers.authorization;
|
|
553
|
+
|
|
554
|
+
// send type2 message and ask for type3 message
|
|
555
|
+
if (authHeaders && authHeaders.startsWith(type1Message.slice(0, 20))) {
|
|
556
|
+
res.writeHead(401, {
|
|
557
|
+
|
|
558
|
+
// @note we're sending a 'Negotiate' header here to make
|
|
559
|
+
// sure that runtime can handle it.
|
|
560
|
+
'www-authenticate': [type2Message, 'Negotiate']
|
|
561
|
+
});
|
|
562
|
+
|
|
563
|
+
options.debug && console.info('401: got type1 message');
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
// successful auth
|
|
567
|
+
// @note we don't check if the username and password are correct
|
|
568
|
+
// because I don't know how.
|
|
569
|
+
else if (authHeaders && authHeaders.startsWith(type3Message.slice(0, 100))) {
|
|
570
|
+
res.writeHead(200);
|
|
571
|
+
|
|
572
|
+
options.debug && console.info('200: got type3 message');
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
// no valid auth headers, ask for type1 message
|
|
576
|
+
else {
|
|
577
|
+
res.writeHead(401, {
|
|
578
|
+
'www-authenticate': ['NTLM', 'Negotiate']
|
|
579
|
+
});
|
|
580
|
+
|
|
581
|
+
options.debug && console.info('401: got no authorization header');
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
res.end();
|
|
585
|
+
},
|
|
586
|
+
server = http.createServer(handler);
|
|
587
|
+
|
|
588
|
+
enableServerDestroy(server);
|
|
589
|
+
|
|
590
|
+
return server;
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
/**
|
|
594
|
+
* Custom junk bytes response server.
|
|
595
|
+
*
|
|
596
|
+
* `/${bytes}` returns binary response of given bytes size.
|
|
597
|
+
*/
|
|
598
|
+
function createBytesServer () {
|
|
599
|
+
var server = http.createServer(function (req, res) {
|
|
600
|
+
var bytes = Number(req.url.substr(1)) || 0; // remove leading /
|
|
601
|
+
|
|
602
|
+
res.writeHead(200);
|
|
603
|
+
res.write(Buffer.alloc(bytes));
|
|
604
|
+
res.end();
|
|
605
|
+
});
|
|
606
|
+
|
|
607
|
+
enableServerDestroy(server);
|
|
608
|
+
|
|
609
|
+
return server;
|
|
610
|
+
}
|
|
611
|
+
|
|
500
612
|
module.exports = {
|
|
501
613
|
createSSLServer,
|
|
502
614
|
createHTTPServer,
|
|
@@ -504,5 +616,7 @@ module.exports = {
|
|
|
504
616
|
createRawEchoServer,
|
|
505
617
|
createGraphQLServer,
|
|
506
618
|
createRedirectServer,
|
|
507
|
-
createEdgeGridAuthServer
|
|
619
|
+
createEdgeGridAuthServer,
|
|
620
|
+
createNTLMServer,
|
|
621
|
+
createBytesServer
|
|
508
622
|
};
|