@itentialopensource/adapter-utils 5.1.4 → 5.1.5

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,12 @@
1
1
 
2
+ ## 5.1.5 [08-29-2023]
3
+
4
+ * fix awsroleauth and add authdata to generic
5
+
6
+ See merge request itentialopensource/adapter-utils!272
7
+
8
+ ---
9
+
2
10
  ## 5.1.4 [08-28-2023]
3
11
 
4
12
  * 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
 
@@ -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.5",
4
4
  "description": "Itential Adapter Utility Libraries",
5
5
  "scripts": {
6
6
  "postinstall": "node utils/setup.js",
Binary file