diff --git a/packages/nodes-base/credentials/Aws.credentials.ts b/packages/nodes-base/credentials/Aws.credentials.ts index efb5fe59aa026..26649c29b3f51 100644 --- a/packages/nodes-base/credentials/Aws.credentials.ts +++ b/packages/nodes-base/credentials/Aws.credentials.ts @@ -31,6 +31,29 @@ export class Aws implements ICredentialType { password: true, }, }, + { + displayName: 'Temporary Security Credentials', + name: 'temporaryCredentials', + description: 'Support for temporary credentials from AWS STS', + type: 'boolean', + default: false, + }, + { + displayName: 'Session Token', + name: 'sessionToken', + type: 'string', + displayOptions: { + show: { + temporaryCredentials: [ + true, + ], + }, + }, + default: '', + typeOptions: { + password: true, + }, + }, { displayName: 'Custom Endpoints', name: 'customEndpoints', diff --git a/packages/nodes-base/nodes/Aws/Comprehend/GenericFunctions.ts b/packages/nodes-base/nodes/Aws/Comprehend/GenericFunctions.ts index 40d4c73b90830..7c326694709b8 100644 --- a/packages/nodes-base/nodes/Aws/Comprehend/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Aws/Comprehend/GenericFunctions.ts @@ -46,8 +46,13 @@ export async function awsApiRequest(this: IHookFunctions | IExecuteFunctions | I // Sign AWS API request with the user credentials const signOpts = { headers: headers || {}, host: endpoint.host, method, path, body } as Request; - sign(signOpts, { accessKeyId: `${credentials.accessKeyId}`.trim(), secretAccessKey: `${credentials.secretAccessKey}`.trim() }); + const securityHeaders = { + accessKeyId: `${credentials.accessKeyId}`.trim(), + secretAccessKey: `${credentials.secretAccessKey}`.trim(), + sessionToken: credentials.temporaryCredentials ? `${credentials.sessionToken}`.trim() : undefined, + }; + sign(signOpts, securityHeaders); const options: OptionsWithUri = { headers: signOpts.headers, diff --git a/packages/nodes-base/nodes/Aws/DynamoDB/GenericFunctions.ts b/packages/nodes-base/nodes/Aws/DynamoDB/GenericFunctions.ts index 8b25dd39b0c46..cb25ca70307a4 100644 --- a/packages/nodes-base/nodes/Aws/DynamoDB/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Aws/DynamoDB/GenericFunctions.ts @@ -40,7 +40,11 @@ export async function awsApiRequest(this: IHookFunctions | IExecuteFunctions | I // Concatenate path and instantiate URL object so it parses correctly query strings const endpoint = new URL(getEndpointForService(service, credentials) + path); - + const securityHeaders = { + accessKeyId: `${credentials.accessKeyId}`.trim(), + secretAccessKey: `${credentials.secretAccessKey}`.trim(), + sessionToken: credentials.temporaryCredentials ? `${credentials.sessionToken}`.trim() : undefined, + }; const options = sign({ // @ts-ignore uri: endpoint, @@ -50,10 +54,7 @@ export async function awsApiRequest(this: IHookFunctions | IExecuteFunctions | I path: '/', headers: { ...headers }, body: JSON.stringify(body), - }, { - accessKeyId: credentials.accessKeyId, - secretAccessKey: credentials.secretAccessKey, - }); + }, securityHeaders); try { return JSON.parse(await this.helpers.request!(options)); diff --git a/packages/nodes-base/nodes/Aws/GenericFunctions.ts b/packages/nodes-base/nodes/Aws/GenericFunctions.ts index 1c89db14f55cf..f1d1d13508c3b 100644 --- a/packages/nodes-base/nodes/Aws/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Aws/GenericFunctions.ts @@ -36,8 +36,13 @@ export async function awsApiRequest(this: IHookFunctions | IExecuteFunctions | I // Sign AWS API request with the user credentials const signOpts = { headers: headers || {}, host: endpoint.host, method, path, body } as Request; - sign(signOpts, { accessKeyId: `${credentials.accessKeyId}`.trim(), secretAccessKey: `${credentials.secretAccessKey}`.trim() }); + const securityHeaders = { + accessKeyId: `${credentials.accessKeyId}`.trim(), + secretAccessKey: `${credentials.secretAccessKey}`.trim(), + sessionToken: credentials.temporaryCredentials ? `${credentials.sessionToken}`.trim() : undefined, + }; + sign(signOpts, securityHeaders); const options: OptionsWithUri = { headers: signOpts.headers, diff --git a/packages/nodes-base/nodes/Aws/Rekognition/GenericFunctions.ts b/packages/nodes-base/nodes/Aws/Rekognition/GenericFunctions.ts index 27ba23e4e3202..3a8b98c3607e9 100644 --- a/packages/nodes-base/nodes/Aws/Rekognition/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Aws/Rekognition/GenericFunctions.ts @@ -43,8 +43,13 @@ export async function awsApiRequest(this: IHookFunctions | IExecuteFunctions | I // Sign AWS API request with the user credentials const signOpts = {headers: headers || {}, host: endpoint.host, method, path, body} as Request; + const securityHeaders = { + accessKeyId: `${credentials.accessKeyId}`.trim(), + secretAccessKey: `${credentials.secretAccessKey}`.trim(), + sessionToken: credentials.temporaryCredentials ? `${credentials.sessionToken}`.trim() : undefined, + }; - sign(signOpts, { accessKeyId: `${credentials.accessKeyId}`.trim(), secretAccessKey: `${credentials.secretAccessKey}`.trim()}); + sign(signOpts, securityHeaders); const options: OptionsWithUri = { headers: signOpts.headers, diff --git a/packages/nodes-base/nodes/Aws/S3/AwsS3.node.ts b/packages/nodes-base/nodes/Aws/S3/AwsS3.node.ts index c77fa6d3c6572..5709841f9a7d1 100644 --- a/packages/nodes-base/nodes/Aws/S3/AwsS3.node.ts +++ b/packages/nodes-base/nodes/Aws/S3/AwsS3.node.ts @@ -22,6 +22,7 @@ import { INodeExecutionData, INodeType, INodeTypeDescription, + JsonObject, NodeOperationError, } from 'n8n-workflow'; @@ -632,7 +633,7 @@ export class AwsS3 implements INodeType { } } catch (error) { if (this.continueOnFail()) { - returnData.push({ error: error.message }); + returnData.push({ error: (error as JsonObject).message }); continue; } throw error; diff --git a/packages/nodes-base/nodes/Aws/S3/GenericFunctions.ts b/packages/nodes-base/nodes/Aws/S3/GenericFunctions.ts index 0838622d018ee..d2d7d4d19cca6 100644 --- a/packages/nodes-base/nodes/Aws/S3/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Aws/S3/GenericFunctions.ts @@ -27,7 +27,7 @@ import { } from 'n8n-core'; import { - IDataObject, NodeApiError, NodeOperationError, + IDataObject, JsonObject, NodeApiError, NodeOperationError, } from 'n8n-workflow'; export async function awsApiRequest(this: IHookFunctions | IExecuteFunctions | ILoadOptionsFunctions | IWebhookFunctions, service: string, method: string, path: string, body?: string | Buffer, query: IDataObject = {}, headers?: object, option: IDataObject = {}, region?: string): Promise { // tslint:disable-line:no-any @@ -37,9 +37,13 @@ export async function awsApiRequest(this: IHookFunctions | IExecuteFunctions | I // Sign AWS API request with the user credentials const signOpts = {headers: headers || {}, host: endpoint.host, method, path: `${endpoint.pathname}?${queryToString(query).replace(/\+/g, '%2B')}`, body} as Request; + const securityHeaders = { + accessKeyId: `${credentials.accessKeyId}`.trim(), + secretAccessKey: `${credentials.secretAccessKey}`.trim(), + sessionToken: credentials.temporaryCredentials ? `${credentials.sessionToken}`.trim() : undefined, + }; - - sign(signOpts, { accessKeyId: `${credentials.accessKeyId}`.trim(), secretAccessKey: `${credentials.secretAccessKey}`.trim()}); + sign(signOpts, securityHeaders); const options: OptionsWithUri = { headers: signOpts.headers, @@ -55,7 +59,7 @@ export async function awsApiRequest(this: IHookFunctions | IExecuteFunctions | I try { return await this.helpers.request!(options); } catch (error) { - throw new NodeApiError(this.getNode(), error); + throw new NodeApiError(this.getNode(), (error as JsonObject)); } } diff --git a/packages/nodes-base/nodes/Aws/SES/GenericFunctions.ts b/packages/nodes-base/nodes/Aws/SES/GenericFunctions.ts index 201b03ce51213..09adde5ead19e 100644 --- a/packages/nodes-base/nodes/Aws/SES/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Aws/SES/GenericFunctions.ts @@ -38,7 +38,13 @@ export async function awsApiRequest(this: IHookFunctions | IExecuteFunctions | I // Sign AWS API request with the user credentials const signOpts = { headers: headers || {}, host: endpoint.host, method, path, body } as Request; - sign(signOpts, { accessKeyId: `${credentials.accessKeyId}`.trim(), secretAccessKey: `${credentials.secretAccessKey}`.trim() }); + const securityHeaders = { + accessKeyId: `${credentials.accessKeyId}`.trim(), + secretAccessKey: `${credentials.secretAccessKey}`.trim(), + sessionToken: credentials.temporaryCredentials ? `${credentials.sessionToken}`.trim() : undefined, + }; + + sign(signOpts, securityHeaders); const options: OptionsWithUri = { headers: signOpts.headers, diff --git a/packages/nodes-base/nodes/Aws/Textract/GenericFunctions.ts b/packages/nodes-base/nodes/Aws/Textract/GenericFunctions.ts index f0ba1e8dc6a6f..b2636124631e7 100644 --- a/packages/nodes-base/nodes/Aws/Textract/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Aws/Textract/GenericFunctions.ts @@ -49,8 +49,13 @@ export async function awsApiRequest(this: IHookFunctions | IExecuteFunctions | I // Sign AWS API request with the user credentials const signOpts = { headers: headers || {}, host: endpoint.host, method, path, body } as Request; - sign(signOpts, { accessKeyId: `${credentials.accessKeyId}`.trim(), secretAccessKey: `${credentials.secretAccessKey}`.trim() }); + const securityHeaders = { + accessKeyId: `${credentials.accessKeyId}`.trim(), + secretAccessKey: `${credentials.secretAccessKey}`.trim(), + sessionToken: credentials.temporaryCredentials ? `${credentials.sessionToken}`.trim() : undefined, + }; + sign(signOpts, securityHeaders); const options: OptionsWithUri = { headers: signOpts.headers, @@ -131,7 +136,13 @@ export async function validateCrendetials(this: ICredentialTestFunctions, decryp // Sign AWS API request with the user credentials const signOpts = { host: endpoint.host, method: 'POST', path: '?Action=GetCallerIdentity&Version=2011-06-15' } as Request; - sign(signOpts, { accessKeyId: `${credentials.accessKeyId}`.trim(), secretAccessKey: `${credentials.secretAccessKey}`.trim() }); + const securityHeaders = { + accessKeyId: `${credentials.accessKeyId}`.trim(), + secretAccessKey: `${credentials.secretAccessKey}`.trim(), + sessionToken: credentials.temporaryCredentials ? `${credentials.sessionToken}`.trim() : undefined, + }; + + sign(signOpts, securityHeaders); const options: OptionsWithUri = { headers: signOpts.headers, diff --git a/packages/nodes-base/nodes/Aws/Transcribe/GenericFunctions.ts b/packages/nodes-base/nodes/Aws/Transcribe/GenericFunctions.ts index 4e7b8886cb283..7de8078242efd 100644 --- a/packages/nodes-base/nodes/Aws/Transcribe/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Aws/Transcribe/GenericFunctions.ts @@ -49,8 +49,13 @@ export async function awsApiRequest(this: IHookFunctions | IExecuteFunctions | I // Sign AWS API request with the user credentials const signOpts = { headers: headers || {}, host: endpoint.host, method, path, body } as Request; - sign(signOpts, { accessKeyId: `${credentials.accessKeyId}`.trim(), secretAccessKey: `${credentials.secretAccessKey}`.trim() }); + const securityHeaders = { + accessKeyId: `${credentials.accessKeyId}`.trim(), + secretAccessKey: `${credentials.secretAccessKey}`.trim(), + sessionToken: credentials.temporaryCredentials ? `${credentials.sessionToken}`.trim() : undefined, + }; + sign(signOpts, securityHeaders); const options: OptionsWithUri = { headers: signOpts.headers, diff --git a/packages/nodes-base/nodes/S3/GenericFunctions.ts b/packages/nodes-base/nodes/S3/GenericFunctions.ts index e59fdea25b7a8..8b87646bdc981 100644 --- a/packages/nodes-base/nodes/S3/GenericFunctions.ts +++ b/packages/nodes-base/nodes/S3/GenericFunctions.ts @@ -61,7 +61,13 @@ export async function s3ApiRequest(this: IHookFunctions | IExecuteFunctions | IL body, } as Request; - sign(signOpts, { accessKeyId: `${credentials.accessKeyId}`.trim(), secretAccessKey: `${credentials.secretAccessKey}`.trim() }); + const securityHeaders = { + accessKeyId: `${credentials.accessKeyId}`.trim(), + secretAccessKey: `${credentials.secretAccessKey}`.trim(), + sessionToken: credentials.temporaryCredentials ? `${credentials.sessionToken}`.trim() : undefined, + }; + + sign(signOpts, securityHeaders); const options: OptionsWithUri = { headers: signOpts.headers,