【问题标题】:AccessDeniedException when using Fine-Grained Access control for DynamoDb对 DynamoDb 使用细粒度访问控制时出现 AccessDeniedException
【发布时间】: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


【问题讨论】:

    标签: amazon-web-services aws-lambda amazon-dynamodb amazon-cognito amazon-iam


    【解决方案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 的策略条件。