无法调用Lambda跨帐户来创建由Lambda支持的自定义资源

时间:2017-05-19 17:07:45

标签: amazon-web-services aws-lambda amazon-cloudformation amazon-iam

我正在尝试实现一个用例,可以通过 AWS CloudFormation 模板跨帐户调用Lambda函数。

我正在account B部署 AWS CloudFormation 堆栈,该堆栈具有调用account A中定义的Lambda函数的自定义资源。 我已在account A中创建了一个跨帐户角色,account B为可信实体。此外,account B中的用户附加了一个允许其承担此角色的策略。 不幸的是,堆栈创建失败了访问错误。

非常感谢任何帮助。这是帐户B 的模板:

{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Resources": {
    "GetNwInterfaces":{
      "Type": "Custom::GetNwInterfaces",
      "Properties": {
        "ServiceToken": "arn:aws:lambda:ap-northeast-2:XXXXXXXXXX:function:getini2",
        "region": "us-west-2",
        "uid" : "01100"
      }
    }
  }
}

1 个答案:

答案 0 :(得分:0)

使用适当的权限在帐户A中创建Lambda函数,例如,使用此云信息模板:

Parameters:
  OtherAccountId:
    Type: String

Resources:
  TestFunction:
    Type: AWS::Lambda::Function
    Properties:
      Runtime: python2.7
      Handler: index.handler
      Role: !GetAtt TestRole.Arn
      Code:
        ZipFile: !Sub |
          from botocore.vendored import requests
          import json


          def send(event, context, responseStatus, responseData, physicalResourceId):
              responseUrl = event['ResponseURL']

              print responseUrl

              responseBody = {}
              responseBody['Status'] = responseStatus
              responseBody['Reason'] = 'See the details in CloudWatch Log Stream: ' + context.log_stream_name
              responseBody['PhysicalResourceId'] = physicalResourceId or context.log_stream_name
              responseBody['StackId'] = event['StackId']
              responseBody['RequestId'] = event['RequestId']
              responseBody['LogicalResourceId'] = event['LogicalResourceId']
              responseBody['Data'] = responseData

              json_responseBody = json.dumps(responseBody)

              print "Response body:\n" + json_responseBody

              headers = {
                  'content-type' : '',
                  'content-length' : str(len(json_responseBody))
              }

              try:
                  response = requests.put(responseUrl,
                                          data=json_responseBody,
                                          headers=headers)
                  print "Status code: " + response.reason
              except Exception as e:
                  print "send(..) failed executing requests.put(..): " + str(e)

          def handler(event, context):
              print event
              print context

              responseData = {}

              send(event, context, "SUCCESS", responseData, "CustomResourcePhysicalID")

  CrossAccountPermission:
    Type: AWS::Lambda::Permission
    Properties:
      Action: lambda:InvokeFunction
      FunctionName: !Ref TestFunction
      Principal: !Ref OtherAccountId

  TestRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          -
            Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
            Action:
              - sts:AssumeRole
      Policies:
        - PolicyName: AllowAccess
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action:
                  - "logs:*"
                Resource: "arn:aws:logs:*:*:*"

此处CrossAccountPermission记录非常重要,我们会授予对帐户B的访问权限。

在帐户B中,使用以下模板对其进行测试:

Parameters:
  LambdaArn:
    Type: String

Resources:
  CustomResourceTest:
    Type: Custom::Demo
    Properties:
      ServiceToken: !Ref LambdaArn

此处还有一个可能的问题:在帐户B中运行cloudformation的用户/角色还需要权限才能执行Lambda函数,如果您运行的CF管理员用户不应该是问题,就像您一样无论如何,对资源lambda:*拥有*权限。