用户: arn:aws:sts::{account_id}:assumed-role/* 无权对资源执行: sts:AssumeRole: arn:aws:iam::{account_id}:role/*

Sha*_*upe 5 java amazon-s3 amazon-web-services aws-cloudformation aws-lambda

我正在使用 cloudformation 模板创建两个资源 AWS Lambda 函数和角色。
我使用角色 arn 作为环境变量。稍后在 S3 连接的代码中使用它。但出现异常

com.amazonaws.services.securitytoken.model.AWSSecurityTokenServiceException: 
User: arn:aws:sts::{account_id}:assumed-role/* is not authorized to perform: sts:AssumeRole on resource: arn:aws:iam::{account_id}:role/* 
Service: AWSSecurityTokenService; Status Code: 403; Error Code: AccessDenied; Request ID: ; Proxy: null)
Run Code Online (Sandbox Code Playgroud)

如何在信任关系和内联策略中添加相同的角色 arn?
如何克服上述异常?

其他解决方案表示赞赏

CF 模板片段

com.amazonaws.services.securitytoken.model.AWSSecurityTokenServiceException: 
User: arn:aws:sts::{account_id}:assumed-role/* is not authorized to perform: sts:AssumeRole on resource: arn:aws:iam::{account_id}:role/* 
Service: AWSSecurityTokenService; Status Code: 403; Error Code: AccessDenied; Request ID: ; Proxy: null)
Run Code Online (Sandbox Code Playgroud)

AWS S3 连接代码片段

Resources:
  LambdaFunctionExecutionRole:
    Type: 'AWS::IAM::Role'
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
#             AWS:
#               - {Role ARN}
            Action:
              - 'sts:AssumeRole'
      Path: /
      ManagedPolicyArns:
        - 'arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole'
        - 'arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole'
        - 'arn:aws:iam::aws:policy/SecretsManagerReadWrite'
        - 'arn:aws:iam::aws:policy/AmazonS3FullAccess'
        - 'arn:aws:iam::aws:policy/CloudWatchLogsFullAccess'
        - 'arn:aws:iam::aws:policy/AmazonSSMReadOnlyAccess'
        - 'arn:aws:iam::aws:policy/service-role/AWSLambdaRole'
      Policies:
      - PolicyName: CustomLambdaPolicy
        PolicyDocument:
          Statement:
          - Effect: Allow
            Action:
            - 'ec2:Describe*'
            - 'ec2:Get*'
            Resource: '*'

  LambdaFunction:
    Type: AWS::Serverless::Function
    Properties:
      Description: !Ref Name
      FunctionName: !Ref Name
      Handler: com.fileservice::handleRequest
      Role: !GetAtt LambdaFunctionExecutionRole.Arn
      Timeout: 900
      MemorySize: 512
      Environment:
        Variables:
          bucketName: !Ref S3BucketName
          roleARN: !GetAtt LambdaFunctionExecutionRole.Arn
      CodeUri: target/fileservice-1.0.0.jar
      Runtime: java11
Run Code Online (Sandbox Code Playgroud)

Kau*_*kar 2

LambdaFunction:
  Type: AWS::Serverless::Function
  Properties:
    Role: !GetAtt LambdaFunctionExecutionRole.Arn
Run Code Online (Sandbox Code Playgroud)

如果您使用 AWS::Serverless::Function 的角色属性,则无需在 Lambda 代码中再次承担该角色。任何 AWS 开发工具包或 CLI 都会自动检索与该角色关联的凭证。

参考: https: //docs.aws.amazon.com/lambda/latest/dg/lambda-intro-execution-role.html(来自文档:您在创建函数时提供此角色,并且 Lambda 在以下情况下承担该角色:您的函数被调用。)

忽略您不应该有理由允许角色自行承担这一事实,使用 CloudFormation,不可能在角色定义本身内引用角色的 ARN。尝试在 LambdaFunctionExecutionRole 的信任策略中使用 !GetAtt LambdaFunctionExecutionRole.Arn 会出现循环依赖错误。

编辑OP现在已包含在问题中的代码更改:

代替:

public AmazonS3 connectS3(String roleArn, String region) {
    STSAssumeRoleSessionCredentialsProvider stsAssumeRoleSessionCredentialsProvider = new STSAssumeRoleSessionCredentialsProvider.Builder(
            roleArn, "MySession").withStsClient(AWSSecurityTokenServiceClientBuilder.standard().build())
                    .withRoleSessionDurationSeconds(900).build();

    BasicSessionCredentials basicSessionCredentials = new BasicSessionCredentials(
            stsAssumeRoleSessionCredentialsProvider.getCredentials().getAWSAccessKeyId(),
            stsAssumeRoleSessionCredentialsProvider.getCredentials().getAWSSecretKey(),
            stsAssumeRoleSessionCredentialsProvider.getCredentials().getSessionToken());

    System.out.println("serviceEndpoint:- "+ String.format("https://s3.%s.amazonaws.com", region) );
    AmazonS3 s3Client = AmazonS3ClientBuilder.standard().withCredentials(new AWSStaticCredentialsProvider(basicSessionCredentials))
                            .withEndpointConfiguration( new EndpointConfiguration( String.format("https://s3.%s.amazonaws.com", region), region) )
                            .build();
    return s3Client;
}
Run Code Online (Sandbox Code Playgroud)

为什么不直接这样做呢?

public AmazonS3 connectS3(String region) {
   
    AmazonS3 s3Client = AmazonS3ClientBuilder.standard().withRegion(region).build();
    return s3Client;
}
Run Code Online (Sandbox Code Playgroud)

如果您的代码在 AWS Lambda 函数中运行,则无需执行 AssumeRole 操作来获取凭证,您可以直接使用分配给 Lambda 函数的角色来访问 S3。尝试担任角色的唯一原因是它是一个完全独立的角色,并且具有分配给 AWS Lambda 函数的角色所没有的所需权限。