@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 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 origin = `${this.id}-adapter-getAuthorization`;
63
+ const meth = 'authenticationHandler-getAWSAuthorization';
64
+ const origin = `${this.myid}-${meth}`;
65
65
  log.trace(origin);
66
66
 
67
- // Form path
68
- let uriPathTranslated = '';
69
- if (requestObj.uriQuery && uriPath.indexOf('?') === -1) {
70
- const query = requestObj.uriQuery;
71
- uriPathTranslated = `${uriPath}?${querystring.stringify(query)}`;
72
- } else if (requestObj.uriQuery && uriPath.endsWith('?')) {
73
- const query = requestObj.uriQuery;
74
- uriPathTranslated = `${uriPath}${querystring.stringify(query)}`;
75
- } else {
76
- uriPathTranslated = uriPath;
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
- // set up the options for the AWS signature
80
- const options = {
81
- host: this.allProps.host,
82
- method,
83
- path: uriPathTranslated.replace(/\/\/+/g, '/'),
84
- service,
85
- region: this.allProps.region
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
- // add any provided headers for the call
89
- if (requestObj.addlHeaders) {
90
- options.headers = requestObj.addlHeaders;
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
- // override anything set in callProperties
105
- if (requestObj.callProperties) {
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
- if (requestObj.callProperties.region) {
110
- options.region = requestObj.callProperties.region;
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
- log.debug(`SIG OPTIONS: ${JSON.stringify(options)}`);
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
- /* STS AUTHENTICATION */
116
- if (STSParams) {
117
- log.info('Using STS for AWS Authentication');
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
- // set the original AWS access information (from properties)
120
- AWS.config.update({
121
- sessionToken: this.allProps.authentication.aws_session_token,
122
- accessKeyId: this.allProps.authentication.aws_access_key,
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
- // use STS to get the AWS access information for the user defined in STWS Params
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: STSParams.RoleArn,
131
- RoleSessionName: STSParams.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
- throw err;
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
- // extract the user specific info from the response
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
- // call the signature with the user specific information
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
 
@@ -408,7 +408,7 @@ function returnStub(request, entitySchema, callProperties) {
408
408
  return callResp;
409
409
  }
410
410
 
411
- const mockresponses = entitySchema.mockresponses;
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 = Object.assign({}, callProperties);
818
- const newRequest = Object.assign({}, request);
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 = Object.assign({}, reqBody);
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
- options.path = healthSchema.entitypath;
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
@@ -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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@itentialopensource/adapter-utils",
3
- "version": "5.1.4",
3
+ "version": "5.1.6",
4
4
  "description": "Itential Adapter Utility Libraries",
5
5
  "scripts": {
6
6
  "postinstall": "node utils/setup.js",
Binary file