@itentialopensource/adapter-utils 5.1.4 → 5.1.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/CHANGELOG.md +16 -0
- package/lib/authenticationHandler.js +122 -167
- package/lib/connectorRest.js +10 -6
- package/lib/genericHandler.js +3 -0
- package/package.json +1 -1
- package/refs?service=git-upload-pack +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,4 +1,20 @@
|
|
|
1
1
|
|
|
2
|
+
## 5.1.6 [09-06-2023]
|
|
3
|
+
|
|
4
|
+
* add fixes to connector that are missing
|
|
5
|
+
|
|
6
|
+
See merge request itentialopensource/adapter-utils!275
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## 5.1.5 [08-29-2023]
|
|
11
|
+
|
|
12
|
+
* fix awsroleauth and add authdata to generic
|
|
13
|
+
|
|
14
|
+
See merge request itentialopensource/adapter-utils!272
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
2
18
|
## 5.1.4 [08-28-2023]
|
|
3
19
|
|
|
4
20
|
* Switching order of params on aws auth
|
|
@@ -8,7 +8,6 @@
|
|
|
8
8
|
|
|
9
9
|
const aws4 = require('aws4');
|
|
10
10
|
const AWS = require('aws-sdk');
|
|
11
|
-
const http = require('http');
|
|
12
11
|
const querystring = require('querystring');
|
|
13
12
|
|
|
14
13
|
/*
|
|
@@ -61,86 +60,145 @@ class AuthenticationHandler {
|
|
|
61
60
|
* @return {Object} the headers to add to the request
|
|
62
61
|
*/
|
|
63
62
|
getAWSAuthorization(method, requestObj, uriPath, service, STSParams, roleName, callback) {
|
|
64
|
-
const
|
|
63
|
+
const meth = 'authenticationHandler-getAWSAuthorization';
|
|
64
|
+
const origin = `${this.myid}-${meth}`;
|
|
65
65
|
log.trace(origin);
|
|
66
66
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
67
|
+
try {
|
|
68
|
+
// Form path
|
|
69
|
+
let uriPathTranslated = '';
|
|
70
|
+
if (requestObj.uriQuery && uriPath.indexOf('?') === -1) {
|
|
71
|
+
const query = requestObj.uriQuery;
|
|
72
|
+
uriPathTranslated = `${uriPath}?${querystring.stringify(query)}`;
|
|
73
|
+
} else if (requestObj.uriQuery && uriPath.endsWith('?')) {
|
|
74
|
+
const query = requestObj.uriQuery;
|
|
75
|
+
uriPathTranslated = `${uriPath}${querystring.stringify(query)}`;
|
|
76
|
+
} else {
|
|
77
|
+
uriPathTranslated = uriPath;
|
|
78
|
+
}
|
|
78
79
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
80
|
+
// set up the options for the AWS signature
|
|
81
|
+
const options = {
|
|
82
|
+
host: this.allProps.host,
|
|
83
|
+
method,
|
|
84
|
+
path: uriPathTranslated.replace(/\/\/+/g, '/'),
|
|
85
|
+
service,
|
|
86
|
+
region: this.allProps.region
|
|
87
|
+
};
|
|
87
88
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
}
|
|
92
|
-
// remove ? if there is no query and the last character is ?
|
|
93
|
-
if (options.path.endsWith('?')) {
|
|
94
|
-
options.path = options.path.substring(0, options.path.length - 1);
|
|
95
|
-
}
|
|
96
|
-
// If there is a body (POST, PATCH, PUT) add the body to the call
|
|
97
|
-
if (method !== 'GET' && method !== 'DELETE') {
|
|
98
|
-
if (typeof requestObj.payload === 'string') {
|
|
99
|
-
options.body = requestObj.payload;
|
|
100
|
-
} else {
|
|
101
|
-
options.body = JSON.stringify(requestObj.payload);
|
|
89
|
+
// add any provided headers for the call
|
|
90
|
+
if (requestObj.addlHeaders) {
|
|
91
|
+
options.headers = requestObj.addlHeaders;
|
|
102
92
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
if (requestObj.callProperties.host) {
|
|
107
|
-
options.host = requestObj.callProperties.host;
|
|
93
|
+
// remove ? if there is no query and the last character is ?
|
|
94
|
+
if (options.path.endsWith('?')) {
|
|
95
|
+
options.path = options.path.substring(0, options.path.length - 1);
|
|
108
96
|
}
|
|
109
|
-
|
|
110
|
-
|
|
97
|
+
// If there is a body (POST, PATCH, PUT) add the body to the call
|
|
98
|
+
if (method !== 'GET' && method !== 'DELETE') {
|
|
99
|
+
if (typeof requestObj.payload === 'string') {
|
|
100
|
+
options.body = requestObj.payload;
|
|
101
|
+
} else {
|
|
102
|
+
options.body = JSON.stringify(requestObj.payload);
|
|
103
|
+
}
|
|
111
104
|
}
|
|
112
|
-
|
|
113
|
-
|
|
105
|
+
// override anything set in callProperties
|
|
106
|
+
if (requestObj.callProperties) {
|
|
107
|
+
if (requestObj.callProperties.host) {
|
|
108
|
+
options.host = requestObj.callProperties.host;
|
|
109
|
+
}
|
|
110
|
+
if (requestObj.callProperties.region) {
|
|
111
|
+
options.region = requestObj.callProperties.region;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
log.debug(`SIG OPTIONS: ${JSON.stringify(options)}`);
|
|
115
|
+
|
|
116
|
+
/* STS AUTHENTICATION */
|
|
117
|
+
if (STSParams) {
|
|
118
|
+
log.info('Using STS for AWS Authentication');
|
|
119
|
+
|
|
120
|
+
// set the original AWS access information (from properties)
|
|
121
|
+
AWS.config.update({
|
|
122
|
+
sessionToken: this.allProps.authentication.aws_session_token,
|
|
123
|
+
accessKeyId: this.allProps.authentication.aws_access_key,
|
|
124
|
+
secretAccessKey: this.allProps.authentication.aws_secret_key,
|
|
125
|
+
region: this.allProps.region
|
|
126
|
+
});
|
|
114
127
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
128
|
+
// use STS to get the AWS access information for the user defined in STWS Params
|
|
129
|
+
const sts = new AWS.STS();
|
|
130
|
+
const stsData = {
|
|
131
|
+
RoleArn: STSParams.RoleArn,
|
|
132
|
+
RoleSessionName: STSParams.RoleSessionName,
|
|
133
|
+
DurationSeconds: 3600
|
|
134
|
+
};
|
|
135
|
+
return sts.assumeRole(stsData, (err, data) => {
|
|
136
|
+
if (err) {
|
|
137
|
+
const errorObj = this.requestHandlerInst.formatErrorObject(this.myid, meth, `AWS Assume Role Error ${err}`, null, null, null, null);
|
|
138
|
+
log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
|
|
139
|
+
return callback(null, errorObj);
|
|
140
|
+
}
|
|
141
|
+
// extract the user specific info from the response
|
|
142
|
+
const accessKeyId = data.Credentials.AccessKeyId;
|
|
143
|
+
const secretAccessKey = data.Credentials.SecretAccessKey;
|
|
144
|
+
const sessionToken = data.Credentials.SessionToken;
|
|
145
|
+
|
|
146
|
+
// call the signature with the user specific information
|
|
147
|
+
const authOpts = aws4.sign(options, { accessKeyId, secretAccessKey, sessionToken });
|
|
148
|
+
if (sessionToken) {
|
|
149
|
+
authOpts.headers['X-Amz-Security-Token'] = sessionToken;
|
|
150
|
+
}
|
|
118
151
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
secretAccessKey: this.allProps.authentication.aws_secret_key,
|
|
124
|
-
region: this.allProps.region
|
|
125
|
-
});
|
|
152
|
+
// return the headers
|
|
153
|
+
return callback(authOpts.headers);
|
|
154
|
+
});
|
|
155
|
+
}
|
|
126
156
|
|
|
127
|
-
|
|
157
|
+
/* ADAPTER PROPERTIES AUTHENTICATION */
|
|
158
|
+
if (!roleName && !this.allProps.authentication.aws_iam_role) {
|
|
159
|
+
log.info('Using Adapter PROPERTIES for AWS Authentication');
|
|
160
|
+
|
|
161
|
+
// call the signature with the property information
|
|
162
|
+
const authOpts = aws4.sign(options, { accessKeyId: this.allProps.authentication.aws_access_key, secretAccessKey: this.allProps.authentication.aws_secret_key, sessionToken: this.allProps.authentication.aws_session_token });
|
|
163
|
+
if (this.allProps.authentication.aws_session_token) {
|
|
164
|
+
authOpts.headers['X-Amz-Security-Token'] = this.allProps.authentication.aws_session_token;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// return the headers
|
|
168
|
+
return callback(authOpts.headers);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/* ROLE NAME AUTHENTICATION */
|
|
172
|
+
log.info('Using roleName for AWS Authentication');
|
|
173
|
+
|
|
174
|
+
// determine where to get roleName (task is higher priority)
|
|
175
|
+
let myRole = roleName;
|
|
176
|
+
if (!roleName) {
|
|
177
|
+
myRole = this.allProps.authentication.aws_iam_role;
|
|
178
|
+
}
|
|
179
|
+
const myDate = new Date().getTime();
|
|
180
|
+
const mySess = `${this.myid}-${myDate}`;
|
|
128
181
|
const sts = new AWS.STS();
|
|
129
182
|
const stsData = {
|
|
130
|
-
RoleArn:
|
|
131
|
-
RoleSessionName:
|
|
183
|
+
RoleArn: myRole,
|
|
184
|
+
RoleSessionName: mySess,
|
|
132
185
|
DurationSeconds: 3600
|
|
133
186
|
};
|
|
187
|
+
|
|
188
|
+
// change role to the role name provided
|
|
134
189
|
return sts.assumeRole(stsData, (err, data) => {
|
|
135
190
|
if (err) {
|
|
136
|
-
|
|
191
|
+
const errorObj = this.requestHandlerInst.formatErrorObject(this.myid, meth, `AWS Assume Role Error ${err}`, null, null, null, null);
|
|
192
|
+
log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
|
|
193
|
+
return callback(null, errorObj);
|
|
137
194
|
}
|
|
138
|
-
|
|
195
|
+
|
|
196
|
+
// get role keys from response so we can sign the request
|
|
139
197
|
const accessKeyId = data.Credentials.AccessKeyId;
|
|
140
198
|
const secretAccessKey = data.Credentials.SecretAccessKey;
|
|
141
199
|
const sessionToken = data.Credentials.SessionToken;
|
|
142
200
|
|
|
143
|
-
//
|
|
201
|
+
// sign the request
|
|
144
202
|
const authOpts = aws4.sign(options, { accessKeyId, secretAccessKey, sessionToken });
|
|
145
203
|
if (sessionToken) {
|
|
146
204
|
authOpts.headers['X-Amz-Security-Token'] = sessionToken;
|
|
@@ -149,114 +207,11 @@ class AuthenticationHandler {
|
|
|
149
207
|
// return the headers
|
|
150
208
|
return callback(authOpts.headers);
|
|
151
209
|
});
|
|
210
|
+
} catch (e) {
|
|
211
|
+
const errorObj = this.requestHandlerInst.formatErrorObject(this.myid, meth, 'Caught Exception', null, null, null, e);
|
|
212
|
+
log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
|
|
213
|
+
return callback(null, errorObj);
|
|
152
214
|
}
|
|
153
|
-
|
|
154
|
-
/* ADAPTER PROPERTIES AUTHENTICATION */
|
|
155
|
-
if (!roleName && !this.allProps.authentication.aws_iam_role) {
|
|
156
|
-
log.info('Using Adapter PROPERTIES for AWS Authentication');
|
|
157
|
-
|
|
158
|
-
// call the signature with the property information
|
|
159
|
-
const authOpts = aws4.sign(options, { accessKeyId: this.allProps.authentication.aws_access_key, secretAccessKey: this.allProps.authentication.aws_secret_key, sessionToken: this.allProps.authentication.aws_session_token });
|
|
160
|
-
if (this.allProps.authentication.aws_session_token) {
|
|
161
|
-
authOpts.headers['X-Amz-Security-Token'] = this.allProps.authentication.aws_session_token;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
// return the headers
|
|
165
|
-
return callback(authOpts.headers);
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
/* ROLE NAME AUTHENTICATION */
|
|
169
|
-
log.info('Using roleName for AWS Authentication');
|
|
170
|
-
|
|
171
|
-
// set up information for token - this is always ec2!
|
|
172
|
-
const getTokenOptions = {
|
|
173
|
-
method: 'PUT',
|
|
174
|
-
url: 'http://169.254.169.254/latest/api/token',
|
|
175
|
-
headers: {
|
|
176
|
-
'X-aws-ec2-metadata-token-ttl-seconds': 21600
|
|
177
|
-
}
|
|
178
|
-
};
|
|
179
|
-
|
|
180
|
-
// get token from AWS internal server
|
|
181
|
-
const req1 = http.request(getTokenOptions, (res1) => {
|
|
182
|
-
let response = '';
|
|
183
|
-
|
|
184
|
-
// HERE??? - can we check status here or does this need to be in end???
|
|
185
|
-
if (res1.statusCode < 200 || res1.statusCode >= 300) {
|
|
186
|
-
return callback(null, new Error(`Invalid status code recieved: ${res1.statusCode}`));
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
// add data to the response
|
|
190
|
-
res1.on('data', (resp) => {
|
|
191
|
-
response += resp;
|
|
192
|
-
});
|
|
193
|
-
|
|
194
|
-
// process everything when the call finishes
|
|
195
|
-
res1.on('end', () => {
|
|
196
|
-
if (!response) {
|
|
197
|
-
return callback(null, 'No authentication token');
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
// get token and set up to make IAM role call - this is always ec2!
|
|
201
|
-
const tokenKey = response;
|
|
202
|
-
let myRole = roleName;
|
|
203
|
-
if (!roleName) {
|
|
204
|
-
myRole = this.allProps.authentication.aws_iam_role;
|
|
205
|
-
}
|
|
206
|
-
const toptions = {
|
|
207
|
-
method: 'GET',
|
|
208
|
-
hostname: '169.254.169.254',
|
|
209
|
-
path: `/latest/meta-data/iam/security-credentials/${myRole}`,
|
|
210
|
-
headers: {
|
|
211
|
-
'X-aws-ec2-metadata-token': tokenKey
|
|
212
|
-
}
|
|
213
|
-
};
|
|
214
|
-
|
|
215
|
-
// IAM Role call
|
|
216
|
-
const req2 = http.request(toptions, (res2) => {
|
|
217
|
-
let response2 = '';
|
|
218
|
-
|
|
219
|
-
// HERE??? - can we check status here or does this need to be in end???
|
|
220
|
-
if (res2.statusCode < 200 || res2.statusCode >= 300) {
|
|
221
|
-
return callback(null, new Error(`Invalid status code recieved: ${res2.statusCode}`));
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
// add data to the response
|
|
225
|
-
res2.on('data', (chunk) => {
|
|
226
|
-
response2 += chunk;
|
|
227
|
-
});
|
|
228
|
-
|
|
229
|
-
// process everything when the call finishes
|
|
230
|
-
res2.on('end', () => {
|
|
231
|
-
if (!response2) {
|
|
232
|
-
return callback(null, 'No authentication token');
|
|
233
|
-
}
|
|
234
|
-
try {
|
|
235
|
-
// get role keys from response so we can sign the request
|
|
236
|
-
const awsResponse = JSON.parse(response2);
|
|
237
|
-
const accessKeyId = awsResponse.AccessKeyId;
|
|
238
|
-
const secretAccessKey = awsResponse.SecretAccessKey;
|
|
239
|
-
const sessionToken = awsResponse.Token;
|
|
240
|
-
|
|
241
|
-
// sign the request
|
|
242
|
-
const authOpts = aws4.sign(options, { accessKeyId, secretAccessKey, sessionToken });
|
|
243
|
-
if (sessionToken) {
|
|
244
|
-
authOpts.headers['X-Amz-Security-Token'] = sessionToken;
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
// return the headers
|
|
248
|
-
return callback(authOpts.headers);
|
|
249
|
-
} catch (e) {
|
|
250
|
-
return callback(null, e);
|
|
251
|
-
}
|
|
252
|
-
});
|
|
253
|
-
});
|
|
254
|
-
req2.on('error', (err2) => callback(null, err2));
|
|
255
|
-
req2.end();
|
|
256
|
-
});
|
|
257
|
-
});
|
|
258
|
-
req1.on('error', (err1) => callback(null, err1));
|
|
259
|
-
req1.end();
|
|
260
215
|
}
|
|
261
216
|
}
|
|
262
217
|
|
package/lib/connectorRest.js
CHANGED
|
@@ -408,7 +408,7 @@ function returnStub(request, entitySchema, callProperties) {
|
|
|
408
408
|
return callResp;
|
|
409
409
|
}
|
|
410
410
|
|
|
411
|
-
const mockresponses = entitySchema
|
|
411
|
+
const { mockresponses } = entitySchema;
|
|
412
412
|
let specificResp = null;
|
|
413
413
|
|
|
414
414
|
// if there is a request body, see if there is something that matches a specific input
|
|
@@ -814,8 +814,8 @@ function makeRequest(request, entitySchema, callProperties, startTrip, attempt,
|
|
|
814
814
|
|
|
815
815
|
if (attempt < useRedirect && res.statusCode >= 300 && res.statusCode <= 308 && res.headers.location) {
|
|
816
816
|
// retries = 0 go here, retries = 1 it doesn't
|
|
817
|
-
const newProp =
|
|
818
|
-
const newRequest =
|
|
817
|
+
const newProp = { ...callProperties };
|
|
818
|
+
const newRequest = { ...request };
|
|
819
819
|
const nextAtt = attempt + 1;
|
|
820
820
|
|
|
821
821
|
// if there is a protocol on the new location use it
|
|
@@ -1931,7 +1931,7 @@ async function buildTokenRequest(reqPath, reqBody, callProperties, callback) {
|
|
|
1931
1931
|
}
|
|
1932
1932
|
|
|
1933
1933
|
// remove the path vars from the reqBody
|
|
1934
|
-
const actReqBody =
|
|
1934
|
+
const actReqBody = { ...reqBody };
|
|
1935
1935
|
if (actReqBody && actReqBody.uriPathVars) {
|
|
1936
1936
|
delete actReqBody.uriPathVars;
|
|
1937
1937
|
}
|
|
@@ -4304,7 +4304,9 @@ class ConnectorRest {
|
|
|
4304
4304
|
|
|
4305
4305
|
// if there is a healthcheck schema, over ride the properties
|
|
4306
4306
|
if (healthSchema) {
|
|
4307
|
-
|
|
4307
|
+
if (!healthcheckpath) {
|
|
4308
|
+
options.path = healthSchema.entitypath;
|
|
4309
|
+
}
|
|
4308
4310
|
options.method = healthSchema.method;
|
|
4309
4311
|
|
|
4310
4312
|
// save it in memory
|
|
@@ -4463,8 +4465,10 @@ class ConnectorRest {
|
|
|
4463
4465
|
};
|
|
4464
4466
|
|
|
4465
4467
|
// if there is a healthcheck schema, over ride the properties
|
|
4466
|
-
if (healthSchema !== null) {
|
|
4468
|
+
if (healthSchema !== null && !healthcheckpath) {
|
|
4467
4469
|
request.origPath = healthSchema.entitypath;
|
|
4470
|
+
} else if (healthcheckpath) {
|
|
4471
|
+
request.origPath = healthcheckpath;
|
|
4468
4472
|
}
|
|
4469
4473
|
|
|
4470
4474
|
// call to make the request
|
package/lib/genericHandler.js
CHANGED
|
@@ -111,6 +111,9 @@ class GenericHandler {
|
|
|
111
111
|
if (metadata && metadata.datatype) {
|
|
112
112
|
reqObj.datatype = metadata.datatype;
|
|
113
113
|
}
|
|
114
|
+
if (metadata && metadata.authData) {
|
|
115
|
+
reqObj.authData = metadata.authData;
|
|
116
|
+
}
|
|
114
117
|
|
|
115
118
|
// determine the call and return flag
|
|
116
119
|
let action = 'getGenerics';
|
package/package.json
CHANGED
|
Binary file
|