DynamoDB如何进行细粒度的访问控制?

时间:2020-09-16 17:44:24

标签: node.js amazon-web-services amazon-dynamodb amazon-cognito

第一次发布问题,所以如果我不能正确解释,请告诉我。我对AWS还是很陌生,并努力学习。

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

我正在与AWS DynamoDB一起尝试遵循这个想法:

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

每个UserId将用作其分区键,并且它们只能读取,写入和删除其特定行/项目上的信息。

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

dynamodb table image

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

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身份提供程序”,然后从用户池“游戏者”池ID中选择Amazon Cognito和身份池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溢出帖子似乎只是在更高级别上谈论此问题,或者不在我尝试做的范围之内。

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

可能不需要的额外信息:我目前有一个AWS Amplify Web应用程序,该应用程序具有一个工作界面,该界面具有对用户池的有效身份验证。我想添加这种细粒度的访问控制功能,以便用户登录时可以访问编辑其个人资料信息(姓名,年龄等),而不能查看其他个人资料信息。如果我可以得到这种细粒度的访问控制工具的有效原型,那么我应该能够弄清楚如何使其适用于我的Amplify应用程序。

1 个答案:

答案 0 :(得分:0)

对于碰巧碰到我的帖子的任何人,我最终都走了一条略有不同的路线。它可能对您没有用,但解决了我的问题。

因为我使用的是AWS Amplify,所以我向他们表示不满(向undef_obj喊叫以回答我!),他说了以下话:

查看您的链接,您尝试将IAM策略变量用于Cognito身份并制定自己的访问控制矩阵解决方案。尽管这是可能的,但是如果实现错误,将花费大量精力并进行潜在的安全性测试。提供协助不在Amplify框架的范围内。但是,如果您正在寻找使用Amplify进行细粒度的授权,则它内置在GraphQL Transformer @auth指令中,我建议您看一下。有很多示例显示了如何将React应用程序设置为使用AWS AppSync和DynamoDB作为后备存储的Amplify GraphQL终端节点。

所以我调查了一下,发现使用AWS AppSync对我有用!

我去了THIS LINK,并按照那里的一些指示进行。特别: 放大添加API 已选择:GraphQl 授权类型:Amazon Cognito用户池 (我已经将用户池添加到了项目中,因此它跳过了创建新用户池的过程) 我一直选择默认值,直到“选择架构模板”为止 我选择了“具有细粒度访问控制的对象(例如, ect管理应用程序(具有基于所有者的授权)”

从那里建立一个示例项目,我可以开始学习GraphQL以及如何实现细粒度的访问控制。使用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
  }
}`);

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