AWS Lambda 无法调用没有 VPC 的另一个 AWS Lambda - NodeJs

Posted

技术标签:

【中文标题】AWS Lambda 无法调用没有 VPC 的另一个 AWS Lambda - NodeJs【英文标题】:AWS Lambda unable to invoke another AWS Lambda with No VPC - NodeJs 【发布时间】:2019-09-23 16:55:22 【问题描述】:

我有两个 AWS Lambda 函数,函数 A 和函数 B, 这两个 Lambda 函数都在无 VPC 中,因为它们都不需要任何 VPC 资源。 两个 Lambda 函数都附加了 LambdaFull 访问角色。

我可以从本地调用和执行 Lambda B, 但无法从 Lambda A 调用或执行 Lambda B。

我需要同步行为 -

line 1 ..
line 2, invoke lambda, get a response,
line 3 to use the response from line 2

以下是本地代码和 Lambda 代码 -

1.本地 -

let AWS = require('aws-sdk');

let client = new AWS.Lambda(
    region: "us-east-1"
);

let payload = 
    "param1": "ABC",
    "param2": 123
;
payload = JSON.stringify(payload);

let params = 
    FunctionName: 'arn:aws:lambda:us-east-1:awsAccoutNumber:function:test2',
    InvocationType: "RequestResponse", 
    Payload: payload
;

console.log('Invoking Lambda ...');

client.invoke(params, function(err, data) 
    console.log('Lambda invoked!');

    if (err) 
        console.log('Fail Case');
        console.log(err, err.stack);
    
    else     
        console.log('Success Case');
        console.log(data.Payload);
    
);

2。 Lambda A -

let AWS = require('aws-sdk');

exports.handler = async (event) => 

  let client = new AWS.Lambda(
      region: "us-east-1"
  );

  let payload = 
      "param1": "ABC",
      "param2": 123
  ;
  payload = JSON.stringify(payload);

  let params = 
      FunctionName: 'arn:aws:lambda:us-east-1:awsAccountNumber:function:test2',
      InvocationType: "RequestResponse", 
      Payload: payload
  ;

  console.log('Payload => \n', payload);
  console.log('\nParams => \n', params);
  console.log('\nAWS => \n', AWS.Lambda);
  console.log('\nClient => \n', client);

  console.log('Invoking Lambda ...');

  client.invoke(params, function(err, data) 
      console.log('Lambda invoked!');

      if (err) 
          console.log('Fail Case');
          console.log(err, err.stack);
          return err;
      
      else     
          console.log('Success Case');
          console.log(data.Payload);
          return data.Payload;
      
  );

;

3. Lambda B -

exports.handler = async (event) => 
    console.log("Event => ", event);

    // TODO implement
    const response = 
        statusCode: 200,
        body: JSON.stringify('Hello from Lambda!'),
    ;
    return response;
;

IAM Lambda 完全访问策略 -


    "Version": "2012-10-17",
    "Statement": [
        
            "Effect": "Allow",
            "Action": [
                "cloudformation:DescribeChangeSet",
                "cloudformation:DescribeStackResources",
                "cloudformation:DescribeStacks",
                "cloudformation:GetTemplate",
                "cloudformation:ListStackResources",
                "cloudwatch:*",
                "cognito-identity:ListIdentityPools",
                "cognito-sync:GetCognitoEvents",
                "cognito-sync:SetCognitoEvents",
                "dynamodb:*",
                "ec2:DescribeSecurityGroups",
                "ec2:DescribeSubnets",
                "ec2:DescribeVpcs",
                "events:*",
                "iam:GetPolicy",
                "iam:GetPolicyVersion",
                "iam:GetRole",
                "iam:GetRolePolicy",
                "iam:ListAttachedRolePolicies",
                "iam:ListRolePolicies",
                "iam:ListRoles",
                "iam:PassRole",
                "iot:AttachPrincipalPolicy",
                "iot:AttachThingPrincipal",
                "iot:CreateKeysAndCertificate",
                "iot:CreatePolicy",
                "iot:CreateThing",
                "iot:CreateTopicRule",
                "iot:DescribeEndpoint",
                "iot:GetTopicRule",
                "iot:ListPolicies",
                "iot:ListThings",
                "iot:ListTopicRules",
                "iot:ReplaceTopicRule",
                "kinesis:DescribeStream",
                "kinesis:ListStreams",
                "kinesis:PutRecord",
                "kms:ListAliases",
                "lambda:*",
                "logs:*",
                "s3:*",
                "sns:ListSubscriptions",
                "sns:ListSubscriptionsByTopic",
                "sns:ListTopics",
                "sns:Publish",
                "sns:Subscribe",
                "sns:Unsubscribe",
                "sqs:ListQueues",
                "sqs:SendMessage",
                "tag:GetResources",
                "xray:PutTelemetryRecords",
                "xray:PutTraceSegments"
            ],
            "Resource": "*"
        
    ]

日志在一行之后只是空白 -

client.invoke(params, function(err, data) 

“调用 Lambda ...” 是我获得的关于函数执行的最后一个日志

我发现了一些类似的案例,但仍然无法找出问题 - 1.AWS lambda invoke not calling another lambda function - Node.js 2.Nodejs - Invoke an AWS.Lambda function from within another lambda function 3.invoke aws lambda from another lambda asynchronously

【问题讨论】:

“无法呼叫”是什么意思?您是否收到错误消息?日志中是否包含Lambda invoked!?更多细节,请。 日志只是在线空白 - client.invoke(params, function(err, data) , Invoking Lambda ... 是我在函数执行中获得的最后一个日志,本地代码有效,但是在函数上,没有错误,没有成功 您能否提供您的 IAM 政策?您的 lambda 必须有权调用另一个 lambda。 @thomasmichaelwallace 使用 IAM 角色策略更新了问题,我将 AWS AWSLambdaFullAccess 策略附加到 Lambda 角色。 让 res = await client.invoke(params).promise();控制台.log(res);当我遇到同样的问题时,我就是这样做的 【参考方案1】:

问题是您有一个异步 lambda,但您返回的是一个带有回调的同步函数。

这意味着当 AWS 调用 Lambda A 时,它会等待调用 client.invoke(),它会立即返回(您的回调将作为稍后事件的一部分被调用)。这会导致 Lambda A 完成并且 AWS 停止执行。

当您在本地运行时,Node 实际上会继续执行,直到它完成所有回调,这就是本地成功的原因。

要让它工作,你应该返回一个可等待的,例如在 Lambda A 中:

 try 
   const data = await client.invoke(params).promise();
   console.log('Lambda invoked!');
   console.log('Success Case');
   console.log(data.Payload);
   return data.Payload;
  catch (err) 
   console.log('Fail Case');
   console.log(err, err.stack);
   throw err;
 

【讨论】:

以上是关于AWS Lambda 无法调用没有 VPC 的另一个 AWS Lambda - NodeJs的主要内容,如果未能解决你的问题,请参考以下文章

如何从账户 A 中的 Lambda(VPC 中的 Lambda)调用账户 B 中的 AWS Lambda 函数(VPC 中的这个 Lambda)

VPC 中的 AWS Lambda 在 NAT 之后没有互联网访问权限

AWS Lambda 无法访问同一 VPC 中的 EC2 端口

从 VPC 中的 Lambda 访问 AWS S3

如何将 VPC 和安全组分配给 AWS CDK 中的 Lambda?

Terraform 0.11:aws_lambda_function 中的条件 vpc_config