@itentialopensource/adapter-utils
Advanced tools
Comparing version 5.9.4 to 5.9.5
## 5.9.5 [11-06-2024] | ||
* more role chain changes for AWS | ||
See merge request itentialopensource/adapter-utils!309 | ||
--- | ||
## 5.9.4 [10-14-2024] | ||
@@ -3,0 +11,0 @@ |
@@ -49,2 +49,111 @@ /* @copyright Itential, LLC 2023 */ | ||
/** | ||
* @summary Assume an AWS STS Role | ||
* | ||
* @function assumeAWSSTSRole | ||
* @param {object} [options] - the AWS options | ||
* @param {object} [stsParams] - STS Parameters to use for authentication. | ||
* | ||
* @return {Object} the headers to add to the request | ||
*/ | ||
assumeAWSSTSRole(accessKey, secretKey, sessionT, options, STSParams, provideSign, callback) { | ||
const meth = 'authenticationHandler-assumeAWSRole'; | ||
const origin = `${this.myid}-${meth}`; | ||
log.trace(origin); | ||
try { | ||
// set up the config object | ||
const configObj = { | ||
sessionToken: this.allProps.authentication.aws_session_token, | ||
accessKeyId: this.allProps.authentication.aws_access_key, | ||
secretAccessKey: this.allProps.authentication.aws_secret_key, | ||
region: options.region | ||
}; | ||
// override the adapter config (ex. IAM and then Assume Role) | ||
if (accessKey) { | ||
configObj.accessKeyId = accessKey; | ||
} | ||
if (secretKey) { | ||
configObj.secretAccessKey = secretKey; | ||
} | ||
if (sessionT) { | ||
configObj.sessionToken = sessionT; | ||
} | ||
// Add optional config items (ssl, endpoint, proxy) | ||
if (this.allProps.authentication.aws_sts) { | ||
if (this.allProps.authentication.aws_sts.sslEnable === false) { | ||
configObj.sslEnabled = false; | ||
} | ||
if (this.allProps.authentication.aws_sts.endpoint) { | ||
configObj.endpoint = this.allProps.authentication.aws_sts.endpoint; | ||
} | ||
if (this.allProps.authentication.aws_sts.region) { | ||
configObj.region = this.allProps.authentication.aws_sts.region; | ||
} | ||
if (this.allProps.authentication.aws_sts.proxy) { | ||
configObj.httpOptions = { | ||
proxy: this.allProps.authentication.aws_sts.proxy | ||
}; | ||
if (this.allProps.authentication.aws_sts.proxyagent) { | ||
configObj.httpOptions.agent = this.allProps.authentication.aws_sts.proxyagent; | ||
} | ||
} | ||
} | ||
// set the original AWS access information (from properties) | ||
AWS.config.update(configObj); | ||
const sts = new AWS.STS(); | ||
log.debug(`STS OPTIONS: ${JSON.stringify(configObj)}`); | ||
// use STS to get the AWS access information for the user defined in STWS Params | ||
const stsData = { | ||
RoleArn: STSParams.RoleArn, | ||
RoleSessionName: STSParams.RoleSessionName, | ||
DurationSeconds: 3600 | ||
}; | ||
if (this.allProps.authentication.aws_sts && this.allProps.authentication.aws_sts.externalId) { | ||
stsData.ExternalId = this.allProps.authentication.aws_sts.externalId; | ||
} | ||
if (STSParams.ExternalId) { | ||
stsData.ExternalId = STSParams.ExternalId; | ||
} | ||
return sts.assumeRole(stsData, (err, data) => { | ||
if (err) { | ||
const errorObj = this.requestHandlerInst.formatErrorObject(this.myid, meth, `AWS Assume Role Error ${err}`, null, null, null, null); | ||
log.error(`${origin}: ${errorObj.IAPerror.displayString}`); | ||
return callback(null, errorObj); | ||
} | ||
if (!data || !data.Credentials || !data.Credentials.AccessKeyId || !data.Credentials.SecretAccessKey) { | ||
const errorObj = this.requestHandlerInst.formatErrorObject(this.myid, meth, 'AWS Assume Role did not return credentials', null, null, null, null); | ||
log.error(`${origin}: ${errorObj.IAPerror.displayString}`); | ||
return callback(null, errorObj); | ||
} | ||
// if not providing a signature | ||
if (!provideSign) { | ||
return callback(data); | ||
} | ||
// extract the user specific info from the response | ||
const accessKeyId = data.Credentials.AccessKeyId; | ||
const secretAccessKey = data.Credentials.SecretAccessKey; | ||
const sessionToken = data.Credentials.SessionToken; | ||
// call the signature with the user specific information | ||
const authOpts = aws4.sign(options, { accessKeyId, secretAccessKey, sessionToken }); | ||
if (sessionToken) { | ||
authOpts.headers['X-Amz-Security-Token'] = sessionToken; | ||
} | ||
// return the headers | ||
return callback(authOpts.headers); | ||
}); | ||
} catch (e) { | ||
const errorObj = this.requestHandlerInst.formatErrorObject(this.myid, meth, 'Caught Exception', null, null, null, e); | ||
log.error(`${origin}: ${errorObj.IAPerror.displayString}`); | ||
return callback(null, errorObj); | ||
} | ||
} | ||
/** | ||
* @summary Gets the hcma authorization for the call | ||
@@ -117,73 +226,15 @@ * | ||
/* STS AUTHENTICATION */ | ||
if (STSParams) { | ||
/* BASIC STS AUTHENTICATION */ | ||
// This will use the adapter role via the credentials provided to identify primary role and then assume the role | ||
// provided in the STSParams. If no adapter role credentials are provided, it will use AWS Environment | ||
// variables (access and secret key are null) and attempt to assume the role with those. | ||
// If the role assumption is successful the call is signed with the assumed role. If it fails, the call will error. | ||
if (STSParams && !roleName && !this.allProps.authentication.aws_iam_role) { | ||
log.info('Using STS for AWS Authentication'); | ||
// set up the config object | ||
const configObj = { | ||
sessionToken: this.allProps.authentication.aws_session_token, | ||
accessKeyId: this.allProps.authentication.aws_access_key, | ||
secretAccessKey: this.allProps.authentication.aws_secret_key, | ||
region: options.region | ||
}; | ||
// Add optional config items (ssl, endpoint, proxy) | ||
if (this.allProps.authentication.aws_sts) { | ||
if (this.allProps.authentication.aws_sts.sslEnable === false) { | ||
configObj.sslEnabled = false; | ||
} | ||
if (this.allProps.authentication.aws_sts.endpoint) { | ||
configObj.endpoint = this.allProps.authentication.aws_sts.endpoint; | ||
} | ||
if (this.allProps.authentication.aws_sts.region) { | ||
configObj.region = this.allProps.authentication.aws_sts.region; | ||
} | ||
if (this.allProps.authentication.aws_sts.proxy) { | ||
configObj.httpOptions = { | ||
proxy: this.allProps.authentication.aws_sts.proxy | ||
}; | ||
if (this.allProps.authentication.aws_sts.proxyagent) { | ||
configObj.httpOptions.agent = this.allProps.authentication.aws_sts.proxyagent; | ||
} | ||
} | ||
} | ||
// set the original AWS access information (from properties) | ||
AWS.config.update(configObj); | ||
log.debug(`STS OPTIONS: ${JSON.stringify(configObj)}`); | ||
// use STS to get the AWS access information for the user defined in STWS Params | ||
const sts = new AWS.STS(); | ||
const stsData = { | ||
RoleArn: STSParams.RoleArn, | ||
RoleSessionName: STSParams.RoleSessionName, | ||
DurationSeconds: 3600 | ||
}; | ||
return sts.assumeRole(stsData, (err, data) => { | ||
if (err) { | ||
const errorObj = this.requestHandlerInst.formatErrorObject(this.myid, meth, `AWS Assume Role Error ${err}`, null, null, null, null); | ||
log.error(`${origin}: ${errorObj.IAPerror.displayString}`); | ||
return callback(null, errorObj); | ||
} | ||
if (!data || !data.Credentials || !data.Credentials.AccessKeyId || !data.Credentials.SecretAccessKey) { | ||
const errorObj = this.requestHandlerInst.formatErrorObject(this.myid, meth, 'AWS Assume Role did not return credentials', null, null, null, null); | ||
log.error(`${origin}: ${errorObj.IAPerror.displayString}`); | ||
return callback(null, errorObj); | ||
} | ||
// extract the user specific info from the response | ||
const accessKeyId = data.Credentials.AccessKeyId; | ||
const secretAccessKey = data.Credentials.SecretAccessKey; | ||
const sessionToken = data.Credentials.SessionToken; | ||
// call the signature with the user specific information | ||
const authOpts = aws4.sign(options, { accessKeyId, secretAccessKey, sessionToken }); | ||
if (sessionToken) { | ||
authOpts.headers['X-Amz-Security-Token'] = sessionToken; | ||
} | ||
// return the headers | ||
return callback(authOpts.headers); | ||
}); | ||
return this.assumeAWSSTSRole(null, null, null, options, STSParams, true, callback); | ||
} | ||
/* ADAPTER PROPERTIES AUTHENTICATION */ | ||
// This will use the adapter role via the credentials provided to sign the call. If no adapter role credentials | ||
// are provided, it will use AWS Environment variables (access and secret key are null) to sign the call. | ||
if (!roleName && !this.allProps.authentication.aws_iam_role) { | ||
@@ -203,12 +254,22 @@ log.info('Using Adapter PROPERTIES for AWS Authentication'); | ||
/* ROLE NAME AUTHENTICATION */ | ||
// Different scenarios to discuss here | ||
// 1. IAM to internal AWS Server - either Task Role (roleName) or Adapter Role (aws_iam_role) | ||
// 2. Adapter Role (aws_iam_role) assumes Task Role (STSParams or roleName) | ||
// a. IAM to internal AWS Server for Adapter Role | ||
// b. AWS STS for assuming Task Role(s) using Adapter Role | ||
// 3. Pod Role assumes Adapter Role (aws_iam_role) assumes Task Role (STSParams, RoleName) | ||
// a. AWS STS for assuming Adapter Role using AWS Environment (Pod Role) | ||
// b. AWS STS for assuming Task Role(s) using Adapter Role | ||
log.info('Using roleName for AWS Authentication'); | ||
// determine where to get roleName (task is higher priority) | ||
// get the role to use for first credential call | ||
let myRole = roleName; | ||
if (!roleName) { | ||
if (this.allProps.authentication.aws_iam_role) { | ||
myRole = this.allProps.authentication.aws_iam_role; | ||
} | ||
// set up data for first assume role call | ||
const stsrole = new AWS.STS(); | ||
const myDate = new Date().getTime(); | ||
const mySess = `${this.myid}-${myDate}`; | ||
const sts = new AWS.STS(); | ||
const stsData = { | ||
@@ -221,3 +282,3 @@ RoleArn: myRole, | ||
// change role to the role name provided | ||
return sts.assumeRole(stsData, (err, data) => { | ||
return stsrole.assumeRole(stsData, (err, data) => { | ||
if (err) { | ||
@@ -239,2 +300,13 @@ const errorObj = this.requestHandlerInst.formatErrorObject(this.myid, meth, `AWS Assume Role Error ${err}`, null, null, null, null); | ||
/* ASSUMING TASK ROLE */ | ||
if (roleName && this.allProps.authentication.aws_iam_role) { | ||
stsData.RoleArn = roleName; | ||
log.info('Assuming Task Role after Adapter Role'); | ||
return this.assumeAWSSTSRole(accessKeyId, secretAccessKey, sessionToken, options, stsData, true, callback); | ||
} | ||
if (STSParams) { | ||
log.info('Assuming Task Role (STS) after Adapter Role'); | ||
return this.assumeAWSSTSRole(accessKeyId, secretAccessKey, sessionToken, options, STSParams, true, callback); | ||
} | ||
// sign the request | ||
@@ -241,0 +313,0 @@ const authOpts = aws4.sign(options, { accessKeyId, secretAccessKey, sessionToken }); |
{ | ||
"name": "@itentialopensource/adapter-utils", | ||
"version": "5.9.4", | ||
"version": "5.9.5", | ||
"description": "Itential Adapter Utility Libraries", | ||
@@ -5,0 +5,0 @@ "scripts": { |
@@ -14,2 +14,10 @@ { | ||
}, | ||
"region": { | ||
"type": "string", | ||
"description": "region of the server", | ||
"default": "", | ||
"examples": [ | ||
"us-east-1" | ||
] | ||
}, | ||
"port": { | ||
@@ -294,3 +302,5 @@ "type": "integer", | ||
"enum": [ | ||
"http", "https", "" | ||
"http", | ||
"https", | ||
"" | ||
] | ||
@@ -344,2 +354,79 @@ }, | ||
} | ||
}, | ||
"aws_access_key": { | ||
"type": "string", | ||
"description": "AWS access key for authentication", | ||
"default": "", | ||
"examples": [ | ||
"accesskey" | ||
] | ||
}, | ||
"aws_secret_key": { | ||
"type": "string", | ||
"description": "AWS secret key for authentication", | ||
"default": "", | ||
"examples": [ | ||
"secretkey" | ||
] | ||
}, | ||
"aws_session_token": { | ||
"type": "string", | ||
"description": "AWS session token for all calls - not all systems require this", | ||
"default": "", | ||
"examples": [ | ||
"sessionToken" | ||
] | ||
}, | ||
"aws_iam_role": { | ||
"type": "string", | ||
"description": "AWS IAM Role for all calls - not all systems require this", | ||
"default": "", | ||
"examples": [ | ||
"roleOnAllCalls" | ||
] | ||
}, | ||
"aws_sts": { | ||
"type": "object", | ||
"properties": { | ||
"region": { | ||
"type": "string", | ||
"description": "add a region to calls used for assume role", | ||
"default": "", | ||
"examples": [ | ||
"us-east-1" | ||
] | ||
}, | ||
"sslEnable": { | ||
"type": "boolean", | ||
"description": "This can disable the ssl for the sts requests", | ||
"default": true | ||
}, | ||
"endpoint": { | ||
"type": "string", | ||
"description": "change the sts endpoint used for assume role", | ||
"default": "", | ||
"enum": [ | ||
"sts.amazonaws.com", | ||
"sts.us-east-2.amazonaws.com", | ||
"" | ||
] | ||
}, | ||
"proxy": { | ||
"type": "string", | ||
"description": "add a proxy to calls used for assume role", | ||
"default": "", | ||
"examples": [ | ||
"https://1.1.1.1" | ||
] | ||
}, | ||
"proxyagent": { | ||
"type": "string", | ||
"description": "define a proxy agent for calls to assume role", | ||
"default": "", | ||
"examples": [ | ||
"https", | ||
"http" | ||
] | ||
} | ||
} | ||
} | ||
@@ -426,3 +513,3 @@ }, | ||
"default": 300000, | ||
"minimum": 60000, | ||
"minimum": 30000, | ||
"maximum": 3600000 | ||
@@ -950,2 +1037,7 @@ }, | ||
"properties": { | ||
"enabled": { | ||
"type": "boolean", | ||
"description": "Whether or not the device broker calls have been mapped", | ||
"default": false | ||
}, | ||
"getDevice": { | ||
@@ -971,3 +1063,6 @@ "type": "array", | ||
"additionalProperties": { | ||
"type": ["string", "number"] | ||
"type": [ | ||
"string", | ||
"number" | ||
] | ||
} | ||
@@ -979,3 +1074,6 @@ }, | ||
"additionalProperties": { | ||
"type": ["string", "number"] | ||
"type": [ | ||
"string", | ||
"number" | ||
] | ||
} | ||
@@ -987,3 +1085,6 @@ }, | ||
"additionalProperties": { | ||
"type": ["string", "number"] | ||
"type": [ | ||
"string", | ||
"number" | ||
] | ||
} | ||
@@ -1004,3 +1105,6 @@ }, | ||
"additionalProperties": { | ||
"type": ["string", "number"] | ||
"type": [ | ||
"string", | ||
"number" | ||
] | ||
}, | ||
@@ -1018,3 +1122,6 @@ "properties": {} | ||
"additionalProperties": { | ||
"type": ["string", "number"] | ||
"type": [ | ||
"string", | ||
"number" | ||
] | ||
}, | ||
@@ -1104,3 +1211,6 @@ "properties": { | ||
"additionalProperties": { | ||
"type": ["string", "number"] | ||
"type": [ | ||
"string", | ||
"number" | ||
] | ||
} | ||
@@ -1112,3 +1222,6 @@ }, | ||
"additionalProperties": { | ||
"type": ["string", "number"] | ||
"type": [ | ||
"string", | ||
"number" | ||
] | ||
} | ||
@@ -1120,3 +1233,6 @@ }, | ||
"additionalProperties": { | ||
"type": ["string", "number"] | ||
"type": [ | ||
"string", | ||
"number" | ||
] | ||
} | ||
@@ -1137,3 +1253,6 @@ }, | ||
"additionalProperties": { | ||
"type": ["string", "number"] | ||
"type": [ | ||
"string", | ||
"number" | ||
] | ||
}, | ||
@@ -1151,3 +1270,6 @@ "properties": {} | ||
"additionalProperties": { | ||
"type": ["string", "number"] | ||
"type": [ | ||
"string", | ||
"number" | ||
] | ||
}, | ||
@@ -1205,3 +1327,6 @@ "properties": { | ||
"additionalProperties": { | ||
"type": ["string", "number"] | ||
"type": [ | ||
"string", | ||
"number" | ||
] | ||
} | ||
@@ -1213,3 +1338,6 @@ }, | ||
"additionalProperties": { | ||
"type": ["string", "number"] | ||
"type": [ | ||
"string", | ||
"number" | ||
] | ||
} | ||
@@ -1221,3 +1349,6 @@ }, | ||
"additionalProperties": { | ||
"type": ["string", "number"] | ||
"type": [ | ||
"string", | ||
"number" | ||
] | ||
} | ||
@@ -1238,3 +1369,6 @@ }, | ||
"additionalProperties": { | ||
"type": ["string", "number"] | ||
"type": [ | ||
"string", | ||
"number" | ||
] | ||
}, | ||
@@ -1252,3 +1386,6 @@ "properties": {} | ||
"additionalProperties": { | ||
"type": ["string", "number"] | ||
"type": [ | ||
"string", | ||
"number" | ||
] | ||
}, | ||
@@ -1291,3 +1428,6 @@ "properties": { | ||
"additionalProperties": { | ||
"type": ["string", "number"] | ||
"type": [ | ||
"string", | ||
"number" | ||
] | ||
} | ||
@@ -1299,3 +1439,6 @@ }, | ||
"additionalProperties": { | ||
"type": ["string", "number"] | ||
"type": [ | ||
"string", | ||
"number" | ||
] | ||
} | ||
@@ -1307,3 +1450,6 @@ }, | ||
"additionalProperties": { | ||
"type": ["string", "number"] | ||
"type": [ | ||
"string", | ||
"number" | ||
] | ||
} | ||
@@ -1324,3 +1470,6 @@ }, | ||
"additionalProperties": { | ||
"type": ["string", "number"] | ||
"type": [ | ||
"string", | ||
"number" | ||
] | ||
}, | ||
@@ -1338,3 +1487,6 @@ "properties": {} | ||
"additionalProperties": { | ||
"type": ["string", "number"] | ||
"type": [ | ||
"string", | ||
"number" | ||
] | ||
}, | ||
@@ -1366,3 +1518,6 @@ "properties": {} | ||
"additionalProperties": { | ||
"type": ["string", "number"] | ||
"type": [ | ||
"string", | ||
"number" | ||
] | ||
} | ||
@@ -1374,3 +1529,6 @@ }, | ||
"additionalProperties": { | ||
"type": ["string", "number"] | ||
"type": [ | ||
"string", | ||
"number" | ||
] | ||
} | ||
@@ -1382,3 +1540,6 @@ }, | ||
"additionalProperties": { | ||
"type": ["string", "number"] | ||
"type": [ | ||
"string", | ||
"number" | ||
] | ||
} | ||
@@ -1399,3 +1560,6 @@ }, | ||
"additionalProperties": { | ||
"type": ["string", "number"] | ||
"type": [ | ||
"string", | ||
"number" | ||
] | ||
}, | ||
@@ -1413,3 +1577,6 @@ "properties": {} | ||
"additionalProperties": { | ||
"type": ["string", "number"] | ||
"type": [ | ||
"string", | ||
"number" | ||
] | ||
}, | ||
@@ -1520,3 +1687,6 @@ "properties": {} | ||
"additionalProperties": { | ||
"type": ["string", "number"] | ||
"type": [ | ||
"string", | ||
"number" | ||
] | ||
} | ||
@@ -1528,3 +1698,6 @@ }, | ||
"additionalProperties": { | ||
"type": ["string", "number"] | ||
"type": [ | ||
"string", | ||
"number" | ||
] | ||
} | ||
@@ -1536,3 +1709,6 @@ }, | ||
"additionalProperties": { | ||
"type": ["string", "number"] | ||
"type": [ | ||
"string", | ||
"number" | ||
] | ||
} | ||
@@ -1553,3 +1729,6 @@ }, | ||
"additionalProperties": { | ||
"type": ["string", "number"] | ||
"type": [ | ||
"string", | ||
"number" | ||
] | ||
}, | ||
@@ -1567,3 +1746,6 @@ "properties": {} | ||
"additionalProperties": { | ||
"type": ["string", "number"] | ||
"type": [ | ||
"string", | ||
"number" | ||
] | ||
} | ||
@@ -1570,0 +1752,0 @@ } |
Sorry, the diff of this file is not supported yet
833371
16900