From 39c0b08d9db707bd9bd5fc86fd462c64142f2927 Mon Sep 17 00:00:00 2001 From: Matheus Cansian Date: Sat, 5 Oct 2019 17:17:23 -0300 Subject: [PATCH] Remove aws-sdk dependency from AWS Lambda node --- .../nodes-base/nodes/Aws/AwsLambda.node.ts | 45 ++++++++++++------ .../nodes-base/nodes/Aws/GenericFunctions.ts | 47 ++++++++++++++++++- packages/nodes-base/package.json | 2 + 3 files changed, 78 insertions(+), 16 deletions(-) diff --git a/packages/nodes-base/nodes/Aws/AwsLambda.node.ts b/packages/nodes-base/nodes/Aws/AwsLambda.node.ts index 87685c75b..70e254342 100644 --- a/packages/nodes-base/nodes/Aws/AwsLambda.node.ts +++ b/packages/nodes-base/nodes/Aws/AwsLambda.node.ts @@ -8,7 +8,7 @@ import { IDataObject } from 'n8n-workflow'; -import { awsConfigCredentials } from './GenericFunctions'; +import { awsApiRequest } from './GenericFunctions'; import { Lambda } from 'aws-sdk'; @@ -89,13 +89,9 @@ export class AwsLambda implements INodeType { methods = { loadOptions: { async getFunctions(this: ILoadOptionsFunctions): Promise { - await awsConfigCredentials.call(this); - const returnData: INodePropertyOptions[] = []; - - let lambda = new Lambda(); try { - var data = await lambda.listFunctions({}).promise(); + var data = await awsApiRequest.call(this, 'lambda', 'GET', '/2015-03-31/functions/'); } catch (err) { throw new Error(`AWS Error: ${err}`); } @@ -116,9 +112,6 @@ export class AwsLambda implements INodeType { const items = this.getInputData(); const returnData: IDataObject[] = []; - await awsConfigCredentials.call(this); - const lambda = new Lambda(); - for (let i = 0; i < items.length; i++) { const params = { FunctionName: this.getNodeParameter('function', i) as string, @@ -128,16 +121,38 @@ export class AwsLambda implements INodeType { }; try { - var responseData = await lambda.invoke(params).promise(); + + var responseData = await awsApiRequest.call( + this, + 'lambda', + 'POST', + `/2015-03-31/functions/${params.FunctionName}/invocations?Qualifier=${params.Qualifier}`, + params.Payload, + { + 'X-Amz-Invocation-Type': params.InvocationType, + 'Content-Type': 'application/x-amz-json-1.0', + }, + ); } catch (err) { throw new Error(`AWS Error: ${err}`); } - returnData.push({ - StatusCode: responseData.StatusCode, - Result: responseData.Payload, - Error: responseData.FunctionError, - } as IDataObject); + if (responseData.errorMessage === undefined) { + returnData.push({ + FunctionName: params.FunctionName, + FunctionQualifier: params.Qualifier, + Result: responseData, + } as IDataObject); + } else { + returnData.push({ + FunctionName: params.FunctionName, + FunctionQualifier: params.Qualifier, + ErrorMessage: responseData.errorMessage, + ErrorType: responseData.errorType, + ErrorStackTrace: responseData.stackTrace, + } as IDataObject); + } + } return [this.helpers.returnJsonArray(returnData)]; diff --git a/packages/nodes-base/nodes/Aws/GenericFunctions.ts b/packages/nodes-base/nodes/Aws/GenericFunctions.ts index 2bfd2c027..30b3f2f94 100644 --- a/packages/nodes-base/nodes/Aws/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Aws/GenericFunctions.ts @@ -6,7 +6,7 @@ import { import { config } from 'aws-sdk'; import { OptionsWithUri } from 'request'; - +import { sign } from 'aws4'; export async function awsConfigCredentials(this: IHookFunctions | IExecuteFunctions | ILoadOptionsFunctions): Promise { const credentials = this.getCredentials('aws'); @@ -21,3 +21,48 @@ export async function awsConfigCredentials(this: IHookFunctions | IExecuteFuncti secretAccessKey: `${credentials.secretAccessKey}`, }); } + +export async function awsApiRequest(this: IHookFunctions | IExecuteFunctions | ILoadOptionsFunctions, service: string, method: string, path: string, body?: string, headers?: object): Promise { // tslint:disable-line:no-any + const credentials = this.getCredentials('aws'); + + if (credentials === undefined) { + throw new Error('No credentials got returned!'); + } + + const endpoint = `${service}.${credentials.region}.amazonaws.com` + + // Sign AWS API request with the user credentials + const signOpts = {headers: headers || {}, host: endpoint, method: method, path: path, body: body} + sign(signOpts, {accessKeyId: `${credentials.accessKeyId}`, secretAccessKey: `${credentials.secretAccessKey}`}) + + const options: OptionsWithUri = { + headers: signOpts.headers, + method: method, + uri: `https://${endpoint}${signOpts.path}`, + body: signOpts.body, + }; + + let response: string + try { + response = await this.helpers.request!(options); + } catch (error) { + console.error(error); + + const errorMessage = error.response.body.message || error.response.body.Message; + if (error.statusCode === 403) { + if (errorMessage == 'The security token included in the request is invalid.') { + throw new Error('The AWS credentials are not valid!'); + } else if (errorMessage.startsWith('The request signature we calculated does not match the signature you provided')) { + throw new Error('The AWS credentials are not valid!'); + } + } + + throw errorMessage; + } + + try { + return JSON.parse(response); + } catch (e) { + return response + } +} diff --git a/packages/nodes-base/package.json b/packages/nodes-base/package.json index 54a83b531..4ee7ae8d6 100644 --- a/packages/nodes-base/package.json +++ b/packages/nodes-base/package.json @@ -106,6 +106,7 @@ ] }, "devDependencies": { + "@types/aws4": "^1.5.1", "@types/basic-auth": "^1.1.2", "@types/cron": "^1.6.1", "@types/express": "^4.16.1", @@ -126,6 +127,7 @@ "typescript": "~3.5.2" }, "dependencies": { + "aws4": "^1.8.0", "aws-sdk": "^2.543.0", "basic-auth": "^2.0.1", "cron": "^1.6.0",