如何做 DynamoDB 细粒度访问控制?

How to do DynamoDB Fine-Grained Access Control?

第一次发布问题,如果我没有正确解释,请告诉我。我对 AWS 还是很陌生,正在努力学习。

主要问题:我测试以下设置是否按预期工作的最简单方法是什么?

我正在使用 AWS DynamoDB 尝试遵循这个想法:

https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/specifying-conditions.html

其中每个 UserId 都是他们的分区键,他们只能读取、写入和删除其特定 row/items 上的信息。

我首先创建一个 table 使用相同名称的 GameScores

dynamodb table image

我还使用所有默认设置创建了一个名为“gamers”的用户池。

enter image description here

我使用他们在文档中的策略创建了一个策略并将其称为“dynmodbgametable”,我唯一更改的是“资源”以匹配 dynamoDB“GameScores”的 ARN 我只是已创建。

{
"Version": "2012-10-17",
"Statement": [
    {
        "Sid": "AllowAccessToOnlyItemsMatchingUserID",
        "Effect": "Allow",
        "Action": [
            "dynamodb:GetItem",
            "dynamodb:BatchGetItem",
            "dynamodb:Query",
            "dynamodb:PutItem",
            "dynamodb:UpdateItem",
            "dynamodb:DeleteItem",
            "dynamodb:BatchWriteItem"
        ],
        "Resource": [
            "arn:aws:dynamodb:us-..rest of arn../GameScores"
        ],
        "Condition": {
            "ForAllValues:StringEquals": {
                "dynamodb:LeadingKeys": [
                    "${www.amazon.com:user_id}"
                ],
                "dynamodb:Attributes": [
                    "UserId",
                    "GameTitle",
                    "Wins",
                    "Losses",
                    "TopScore",
                    "TopScoreDateTime"
                ]
            },
            "StringEqualsIfExists": {
                "dynamodb:Select": "SPECIFIC_ATTRIBUTES"
            }
        }
    }
]

}

我创建了一个角色。单击 Web 身份以获取受信任实体的类型并选择 Web 身份提供商 I select Amazon Cognito 和身份池 ID 作为来自用户池“游戏玩家”池 ID 的池 ID,然后附加我刚刚创建的名为“ dynmodbgametable”。我称这个角色为“GameRole”

enter image description here

我继续在“玩家”用户池中创建两个用户。

在这一点上,我不知道我应该做什么来测试它,看看我是否正确地遵循了说明。我开始设置这个 Nodejs 脚本进行测试,它可以从数据库中放入和获取东西,但我知道它使用的是保存在我本地机器上的默认根证书。我想我应该将“AWS.config.credentials”设置为包含用户池的内容,并输入其中一个用户名及其关联的密码。但是我并没有太多运气来弄清楚我应该如何做到这一点。是否有必要为“游戏玩家”用户群创建一个客户端应用程序,然后才能运行? 如果有帮助的话,这是我正在尝试的小脚本。

    var AWS = require("aws-sdk");


AWS.config.update({ region: "us-east-2" });


var ddb = new AWS.DynamoDB({ apiVersion: "2012-08-10" });

var params = {
  TableName: "GameScores",
  Item: {
    UserId: { S: "user id" },
    GameTitle: { S: "hobo" },
  },
};


ddb.putItem(params, function (err, data) {
  if (err) {
    console.log("Error", err);
  } else {
    console.log("Success", data);
  }
});

我真的不知道如何获取“${www.amazon.com:user_id}”以及在何处或如何传递它。数据库本身有一些端点吗?我是否应该创建某种端点来指向?我只知道这是用来确定分区键的变量。

如果我能弄清楚如何测试它是否正常工作,我觉得其中一些对我来说会很有意义。现在我觉得我不太理解概念上发生了什么。我在网上阅读的所有 YouTube 视频、文档和其他 Stack overflow 帖子似乎只是在更高层次上谈论这个问题,或者不在我试图做的范围内。

感谢您提供的任何帮助!如果缺少某些内容,我一定会进行编辑。

可能不需要额外信息:我目前有一个 AWS Amplify Web 应用程序,它有一个工作界面,可以使用用户池进行工作身份验证。我想添加这种细粒度访问控制的能力,这样当用户登录时,他们将有权编辑他们的个人资料信息(姓名、年龄等),而不能查看其他个人资料信息。如果我能得到这种细粒度访问控制的工作原型,我应该能够弄清楚如何让它为我的 Amplify 应用程序工作。

对于偶然发现我的 post 的任何人,我最终选择了一条略有不同的路线。它可能对你没有用,但它解决了我的问题。

因为我使用的是 AWS Amplify,所以我联系了他们的不和谐(大声喊 undef_obj 来回答我!)他说了以下内容:

looking at your link, you're attempting to leverage the IAM policy variables for Cognito Identity and craft your own access control matrix solution. While this is possible, it's going to be a lot of effort and testing with potential for security issues if something is implemented wrong. Assistance with that is outside the scope of the Amplify framework. However, if you're looking for fine grained authorization with Amplify this is built into the GraphQL Transformer @auth directive and I'd recommend looking at that. There are plenty of examples showing how to setup a React app to an Amplify GraphQL endpoint which uses AWS AppSync and DynamoDB as the backing store.

所以我对此进行了调查,发现使用 AWS AppSync 对我很有效!

我去了 THIS LINK 并按照那里的一些说明进行了操作。具体来说: 放大添加 api 已选择:GraphQl 授权类型:Amazon Cognito 用户池 (我已经将用户池添加到项目中,因此它跳过了创建新用户池的过程) 我一直选择默认值,直到“选择模式模板” 我选择了“具有 fine-grained 访问控制的对象(例如,一个项目 具有 owner-based 授权的 ect 管理应用程序)"

从那里它设置了一个示例项目,我可以从中开始学习 GraphQL 以及如何实现 fine-grained 访问控制。使用 getPrivateNote 解析器中的代码可能是最有用的东西。我还使用这个 appsync starter application 来弄清楚如何从我的 React 客户端与 GraphQL 交互。整个过程花了我好几个小时才弄清楚,目前我仍在努力完全理解它是如何工作的,但到目前为止,这个 AppSync GraphQL 似乎是最适合我的场景。 AppSync 的内置查询系统使测试访问控制变得更加容易(即以一个用户登录并查看我是否只能访问我自己的项目)

这是我的 reactjs 代码在客户端最终的样子:

import { API, graphqlOperation } from 'aws-amplify';
import QueryUserInfo from './graphql/QueryUserInfo';

...

getRequest = (evt) => {
      
    return new Promise((resolve, reject) =>
    {
      API.graphql(graphqlOperation(QueryUserInfo))
      .then((data) => {
        if(data) {
          console.log(data);
          resolve(data);
        } else {
          console.log(data);
          resolve(null);
        }
      })
      .catch((err) => {
        console.log(err);
        resolve(null);
      });
    });
  }

实际的 QueryUserInfo.js 文件是这样的:

import gql from "graphql-tag";

export default gql(`
query QueryName {
  getUser(id: "c35...rest of cognito user id...69") {
    id
    email
    name
  }
}`);

解析器代码太长 post,但我只是使用了 Amplify 的模板代码,我想我只需要更改 #set( $allowedOwners0 = $util.defaultIfNull($ctx.result.owner, []) )#set( $allowedOwners0 = $util.defaultIfNull($ctx.result.id, []) ) 因为“id”是我在我的 dynamoDB table 上使用的,而不是“所有者”。祝所有阅读本文的人好运!