首页 > 解决方案 > AWS lambda 无法承担由 cloudformation 触发的角色

问题描述

通过 CloudFormation 脚本触发时,Lambda 无法承担跨账户角色。

我有一个 CloudFormation 脚本,它在账户 A 中创建并触发一个 Lambda 函数。该函数需要从账户 B 复制一个对象。我正在使用基于角色的跨账户访问。

在帐户 B 上,我具有以下角色,出于测试目的,我使用 S3 完全访问权限。

CrossAccountAccessRole: 
    Type: 'AWS::IAM::Role'
    Properties: 
      RoleName: 'CrossAccountAccessRole'
      Path: '/'
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
        - Effect: Allow
          Principal: 
            AWS: !Sub 'arn:aws:iam::<AccountA>:role/CustomerCrossAccountAccessRole'
          Action: sts:AssumeRole  
  CrossAccountAccessPolicy:
    Type: "AWS::IAM::ManagedPolicy"
    Properties:
      Path: '/'
      ManagedPolicyName: CrossAccountAccessPolicy
      Roles: 
        - !Ref CrossAccountAccessRole
      PolicyDocument:
        Version: "2012-10-17"
        Statement:       
        - Effect: Allow
          Action:
            - s3:*  

在账户 A 上,我具有以下角色,具有 lambda 执行、S3 完全访问权限和代入角色策略。

  CustomerCrossAccountAccessRole:
    Type: 'AWS::IAM::Role'
    Properties:
      RoleName: CustomerCrossAccountAccessRole
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service: lambda.amazonaws.com
            Action: sts:AssumeRole
      Path: /
      Policies:
        - PolicyName: LambdaBasicExecutionPolicy
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action:
                  - 'logs:CreateLogGroup'
                  - 'logs:CreateLogStream'
                  - 'logs:PutLogEvents'
                Resource: '*'
        - PolicyName: LambdaSourceBucketPolicy
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              Effect: Allow
              Action: 's3:*'
              Resource: '*'
        - PolicyName: LambdaAssumeRolePolicy
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
            - Effect: Allow
              Action: sts:AssumeRole
              Resource: !Sub 'arn:aws:iam::<AccountA>:role/CrossAccountAccessRole'

我在我的 lambda 函数中运行这个 python 脚本,

    try:
        print('Assume role of a cross account access role')
        boto_sts_client=boto3.client('sts', region_name='ap-southeast-2')
        stsresponse = boto_sts_client.assume_role(
            RoleSessionName = 'CrossAccountAccessSession',
            RoleArn = 'arn:aws:iam::<AccountA>:role/CrossAccountAccessRole',
                DurationSeconds = 3000
        )

        s3_assumed_client = boto3.client(
            's3',
            region_name='ap-southeast-2',
            aws_access_key_id = stsresponse["Credentials"]["AccessKeyId"],
            aws_secret_access_key = stsresponse["Credentials"]["SecretAccessKey"],
            aws_session_token = stsresponse["Credentials"]["SessionToken"]
        )
        s3_assumed_client.download_file(<BucketName>, <FilePath>,<FileName>)
    except:
        traceback.print_exc()

CloudFormation 脚本返回以下错误,

botocore.exceptions.ClientError: An error occurred (AccessDenied) when calling the AssumeRole operation: Access denied

但是,如果我在测试模式下(使用 AWS 控制台上的“测试”按钮)运行相同的 Lambda(使用 CloudFormation 脚本创建),它会下载文件而不会出现任何错误。

谢谢

标签: amazon-web-servicesaws-lambdaamazon-cloudformationassume-role

解决方案


您的保单包含以下错误:

  • 信任策略应将账户 A 指定为 Principal,这意味着来自该账户的授权用户可以使用 CrossAccountAccessRole 角色。您不能直接在策略中指定不同账户中用户/角色的 ARN。
  • 账户 A 中的管理员必须附加一个策略,允许该角色为 CrossAccountAccessRole 的 ARN 调用 AssumeRole。
  • 确保在创建时将 CustomerCrossAccountAccessRole 分配给 Lambda。
CrossAccountAccessRole: 
    Type: 'AWS::IAM::Role'
    Properties: 
      RoleName: 'CrossAccountAccessRole'
      Path: '/'
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
        - Effect: Allow
          Principal: 
            AWS: 'arn:aws:iam::<AccountA>:root'
...
- PolicyName: LambdaAssumeRolePolicy
      PolicyDocument:
        Version: '2012-10-17'
        Statement:
        - Effect: Allow
          Action: sts:AssumeRole
          Resource: 'arn:aws:iam::<AccountB>:role/CrossAccountAccessRole'
stsresponse = boto_sts_client.assume_role(
   RoleSessionName = 'CrossAccountAccessSession',
   RoleArn = 'arn:aws:iam::<Account-B>:role/CrossAccountAccessRole',
   DurationSeconds = 3000
)

您在实际上应该是 Account-B 的几个地方 (ARN) 中编写了 Account-A,但我猜这些是拼写错误。


推荐阅读