对 DynamoDb 使用细粒度访问控制时出现 AccessDeniedException

Posted

技术标签:

【中文标题】对 DynamoDb 使用细粒度访问控制时出现 AccessDeniedException【英文标题】:AccessDeniedException when using Fine-Grained Access control for DynamoDb 【发布时间】:2021-10-01 00:38:46 【问题描述】:

我在 API 网关(准确地说是 Apollo 服务器)后面有一个 lambda 函数,我通过一个 React 应用程序访问它,方法是传递我在使用 Amplify Auth 登录后获得的 JWT IdToken。

但是,当我尝试运行此应用程序时,我不断得到:

AccessDeniedException:用户:arn:aws:sts::AWS 账户 ID:assumed-role/shop-app-xxx-XXX-CognitoAuthorizedRole-XXXXXXXXXX/CognitoIdentityCredentials 无权执行:dynamodb:GetItem on resource:arn:aws :dynamodb:us-east-1:AWS Account ID:table/Shop"

我的角色策略中的以下条件导致了这种情况(完整角色/策略见下文)。我不太了解我的政策是否有问题,或者我获取凭据的方式是否有问题。我的角色中的 sts:AssumeRoleWithWebIdentity 操作是否导致我不再使用 cognito 身份访问资源?

                Condition:
                    ForAllValues:StringEquals:
                            dynamodb:LeadingKeys:
                                - "$cognito-identity.amazonaws.com:sub
const identityToken = event.headers.Authorization;

AWS.config.credentials = new AWS.CognitoIdentityCredentials(
      IdentityPoolId: `$process.env.IDENTITY_POOL_ID`,
      Logins: 
        [`cognito-idp.$awsConfig.region.amazonaws.com/$process.env.USER_POOL_ID`]: identityToken
          
);

(AWS.config.credentials as AWS.CognitoIdentityCredentials).refresh(function(err)
      if(!err) 
        console.log("no error");
        let dynamoDbClient:AWS.DynamoDB.DocumentClient = new AWS.DynamoDB.DocumentClient();
        getShopModel(user,dynamoDbClient).shop().then((shop)=>console.log(shop));
       else 
        console.log("got an error!");
        console.log(err);
      
);

以下是我的授权角色和映射。如果我从内联策略中删除了 LeadingKeys 条件,那么一切正常。但是我当然没有细粒度的控制。

  CognitoAuthorizedRole:
    Type: "AWS::IAM::Role"
    Properties:
      AssumeRolePolicyDocument: 
        Version: "2012-10-17"
        Statement:
          - Effect: "Allow"
            Principal: 
              Federated: "cognito-identity.amazonaws.com"
            Action: 
              - "sts:AssumeRoleWithWebIdentity"
            Condition:
              StringEquals: 
                "cognito-identity.amazonaws.com:aud": !Ref ShopIdentityPool
              "ForAnyValue:StringLike":
                "cognito-identity.amazonaws.com:amr": authenticated
      Policies:
        - PolicyName: "CognitoAuthorizedPolicy"
          PolicyDocument: 
            Version: "2012-10-17"
            Statement: 
              - Effect: "Allow"
                Action:
                  - "cognito-sync:*"
                  - "cognito-identity:*"
                Resource: "*"
              - Effect: "Allow"
                Action:
                  - "lambda:InvokeFunction"
                Resource: "*"
              - Effect: Allow
                Action:
                  - 'dynamodb:GetItem'
                  - 'dynamodb:PutItem'
                  - 'dynamodb:Query'
                  - 'dynamodb:Scan'
                  - 'dynamodb:Delete*'
                  - 'dynamodb:Update*'
                Resource: [
                  !Sub "arn:aws:dynamodb:$AWS::Region:*:table/$ShopTable",
                  !Sub "arn:aws:dynamodb:$AWS::Region:*:table/$ShopTable/index/*"]
                Condition:
                    ForAllValues:StringEquals:
                            dynamodb:LeadingKeys:
                                - "$cognito-identity.amazonaws.com:sub"

  ShopIdentityPoolRoleMapping:
    Type: "AWS::Cognito::IdentityPoolRoleAttachment"
    Properties:
      IdentityPoolId: !Ref ShopIdentityPool
      Roles:
        authenticated: !GetAtt CognitoAuthorizedRole.Arn
        unauthenticated: !GetAtt CognitoUnAuthorizedRole.Arn


【问题讨论】:

【参考方案1】:

似乎 yaml 和 json 在 Resource 部分混合在一起。

更改资源部分
Resource: [
  !Sub "arn:aws:dynamodb:$AWS::Region:*:table/$ShopTable",
  !Sub "arn:aws:dynamodb:$AWS::Region:*:table/$ShopTable/index/*"]

Resource:
  - !Sub "arn:aws:dynamodb:$AWS::Region:*:table/$ShopTable",
  - !Sub "arn:aws:dynamodb:$AWS::Region:*:table/$ShopTable/index/*"

【讨论】:

不幸的是,这并没有解决它@shimo。如果将其更改为正确的 yaml 结构,但似乎 cloudformation 并不介意。还有其他想法吗? $cognito-identity.amazonaws.com:sub 用于身份 ID。如果您使用的是身份池,请改用...:aud 感谢@shimo。我想知道为什么我需要使用 :aud 值来代替?您是说因为我使用联合身份登录,所以子值不可用?这似乎很奇怪。我也使用 sub 在 dynamodb 中创建了我的记录。 对不起,如果不起作用。我注意到 id pool 用于查看您的代码,并在 this aws blog 中找到了带有 aud 的策略条件。

以上是关于对 DynamoDb 使用细粒度访问控制时出现 AccessDeniedException的主要内容,如果未能解决你的问题,请参考以下文章

使用 dynamoDB 和用户组进行细粒度访问

IAM 策略条件中的 cognito 用户池自定义属性与 Dynamodb 细粒度访问

如何在 Spring-Data-Rest 中实现细粒度的访问控制?

粗粒度与细粒度权限控制

粗粒度与细粒度权限控制

Lambda 代入具有细粒度权限的 AWS IAM 角色