本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。
基于角色的访问控制限制数据库访问
您可以使用以下方式限制对用户可对数据库执行的操作的访问基于角色的访问控制Amazon DocumentDB 中的(RBAC)(与 MongoDB 兼容)。RBAC 的原理是向用户授予一个或多个角色。这些角色决定了用户可以对数据库资源执行的操作。Amazon DocumentDB 目前支持数据库级别范围内的两个内置角色,例如:read、readWrite、readAnyDatabase、clusterAdmin,以及用户定义的角色,这些角色可以限定为特定操作以及基于您的要求的精细资源(例如集合)。
RBAC 的常见使用案例包括通过创建对集群中数据库或集合具有只读访问权限的用户来强制执行最低权限,以及允许单个用户访问集群中给定数据库或集合的多租户应用程序设计。
所有在 2020 年 3 月 26 日之前创建的新用户都已被授予 dbAdminAnyDatabase、readWriteAnyDatabase 和 clusterAdmin 角色。建议您重新评估所有现有用户并根据需要修改角色,以便为您的集群强制执行最低权限。
RBAC 概念
以下是与基于角色的访问控制相关的重要术语和概念。有关 Amazon DocumentDB 用户的更多信息,请参阅Amazon DocumentDB 用户.
-
用户— 可以对数据库进行身份验证并执行操作的单个实体。
-
密码— 用于对用户进行身份验证的密钥。
-
角色— 授权用户对一个或多个数据库执行操作。
-
管理数据库— 用户在其中存储和授权的数据库。
-
数据库 (
db)— 集群中包含用于存储文档的集合的命名空间。
以下命令创建名为 sample-user 的用户。
db.createUser({user: "sample-user", pwd: "abc123", roles: [{role: "read", db: "sample-database"}]})
在此示例中:
-
user: "sample-user"— 表示用户名。 -
pwd: "abc123"— 表示用户密码。 -
role: "read", "db: "sample-database"— 表示用户sample-user将在中具有读取权限sample-database.
以下示例显示您为用户 sample-user 指定 db.getUser(sample-user) 后的输出。在此示例中,用户 sample-user 驻留在 admin 数据库中,但具有 sample-database 数据库的读取角色。
创建用户时,如果省略db在字段中,Amazon DocumentDB 会隐式地将该角色归属于发出连接的数据库。例如,如果您的连接是针对数据库 sample-database 发出的,并且您运行以下命令,则用户 sample-user 将在 admin 数据库中创建并具有对数据库 sample-database 的 readWrite 权限。
db.createUser({user: "sample-user", pwd: "abc123", roles: ["readWrite"]})
此操作的输出将类似于下文。
{
"user":"sample-user",
"roles":[
{
"db":"sample-database",
"role":"readWrite"
}
]
}
创建具有跨所有数据库范围的角色的用户(例如,readAnyDatabase)需要在创建用户时处于 admin 数据库的上下文,或者在创建用户时明确指定角色的数据库。要针对 admin 数据库发出命令,可以使用命令 use admin。有关更多信息,请参阅常见命令。
RBAC 内置角色入门
为帮助您掌握基于角色的访问控制,本部分将向您介绍通过为三个用户创建具有不同职能的角色来强制执行最低权限的示例方案。
-
user1是一位新上任的经理,需要能够查看和访问集群中的所有数据库。 -
user2是一位新员工,只需访问同一集群中的一个数据库sample-database-1。 -
user3是现有员工,需要查看和访问同一集群中其以前无权访问的不同数据库sample-database-2。
在这之后,user1 和 user2 都离开了公司,所以必须撤销他们的访问权限。
要创建用户和授予角色,进入集群用于进行身份验证的用户必须具有可以为 createUser 和 grantRole 执行操作的关联角色。例如,角色 admin 和 userAdminAnyDatabase 都可以授予执行上述功能的权限。有关每个角色的操作,请参阅基于角色的访问控制限制数据库访问。
在 Amazon DocumentDB 中,所有用户和角色操作(例如,create、get、drop、grant、revoke等)隐式执行在admin数据库无论您是否针对admin数据库。
首先,要了解集群中的当前用户和角色,可以运行 show users 命令,如以下示例所示。您将看到两个用户,即集群的 serviceadmin 和主用户。这两个用户始终存在,无法将它们删除。有关更多信息,请参阅Amazon DocumentDB 用户。
show users
对于 user1,使用以下命令创建具有对整个集群中所有数据库的读写访问权限的角色。
db.createUser({user: "user1", pwd: "abc123", roles: [{role: "readWriteAnyDatabase", db: "admin"}]})
此操作的输出将类似于下文。
{
"user":"user1",
"roles":[
{
"role":"readWriteAnyDatabase",
"db":"admin"
}
]
}
对于 user2,使用以下命令创建对数据库 sample-database-1 具有只读访问权限的角色。
db.createUser({user: "user2", pwd: "abc123", roles: [{role: "read", db: "sample-database-1"}]})
此操作的输出将类似于下文。
{
"user":"user2",
"roles":[
{
"role":"read",
"db":"sample-database-1"
}
]
}
要模拟 user3 是现有用户的方案,请先创建用户 user3,然后将新角色分配给 user3。
db.createUser({user: "user3", pwd: "abc123", roles: [{role: "readWrite", db: "sample-database-1"}]})
此操作的输出将类似于下文。
{ "user":"user3", "roles":[ { "role":"readWrite", "db":"sample-database-1" } ] }
现在已创建了用户 user3,请为 user3 分配可对 sample-database-2 进行 read 的角色。
db.grantRolesToUser("user3", [{role: "read", db: "sample-database-2"}])
最后,user1 和 user2 都离开了公司,需要撤销他们对集群的访问权限。您可以通过删除用户来执行此操作,如下所示。
db.dropUser("user1") db.dropUser("user2")
要确保所有用户都具有适当角色,可使用以下命令列出所有用户。
show users
此操作的输出将类似于下文。
{
"_id":"serviceadmin",
"user":"serviceadmin",
"db":"admin",
"roles":[
{
"db":"admin",
"role":"root"
}
]
}
{
"_id":"master-user",
"user":"master-user",
"db":"admin",
"roles":[
{
"db":"admin",
"role":"root"
}
]
}
{
"_id":"user3",
"user":"user3",
"db":"admin",
"roles":[
{
"db":"sample-database-2",
"role":"read"
},
{
"db":"sample-database-1",
"role":"readWrite"
}
]
}
RBAC 用户定义的角色入门
为帮助您掌握用户定义的角色,本部分将向您介绍通过为三个用户创建具有不同职能的角色来强制执行最低权限的示例方案。
在此示例中,以下条件适用:
-
user1是一位新上任的经理,需要能够查看和访问集群中的所有数据库。 -
user2是一位新员工,只需要对一个数据库执行 “查找” 操作,sample-database-1,在同一个集群中。 -
user3是现有员工,需要查看和访问不同数据库中的特定集合,col2,sample-database-2在同一集群中,他们以前无权访问。 -
对于
user1,使用以下命令创建具有对整个集群中所有数据库的读写访问权限的角色。
db.createUser( { user: "user1", pwd: "abc123", roles: [{role: "readWriteAnyDatabase", db: "admin"}] } )
此操作的输出将类似于下文。
{ "user":"user1", "roles":[ { "role":"readWriteAnyDatabase", "db":"admin" } ] }
适用于user2,创建一个对数据库中所有集合具有 “查找” 权限的角色sample-database-1使用以下命令。请注意,此角色将确保所有关联的用户只能运行查找查询。
db.createRole( { role: "findRole", privileges: [ { resource: {db: "sample-database-1", collection: ""}, actions: ["find"] }], roles: [] } )
此操作的输出将类似于下文。
{ "role":"findRole", "privileges":[ { "resource":{ "db":"sample-database-1", "collection":"" }, "actions":[ "find" ] } ], "roles":[ ] }
下一步,创建用户(user2) 并附加最近创建的角色findRole给用户。
db.createUser( { user: "user2", pwd: "abc123", roles: [] }) db.grantRolesToUser("user2",["findRole"])
为了模拟那个场景user3是现有用户,首先创建用户user3,然后创建一个名为 CollectionRole 的新角色,我们将在下一步中分配给该角色user3.
现在你可以将新角色分配给user3. 这个新角色将允许user3以便能够在中插入、更新、删除和查找对一个特定集合的访问权限 col2sample-database-2.
db.createUser( { user: "user3", pwd: "abc123", roles: [] }) db.createRole( { role: "collectionRole", privileges: [ { resource: {db: "sample-database-2", collection: "col2"}, actions: ["find", "update", "insert", "remove"] }], roles: [] } )
此操作的输出将类似于下文。
{ "role":"collectionRole", "privileges":[ { "resource":{ "db":"sample-database-2", "collection":"col2" }, "actions":[ "find", "update", "insert", "remove" ] } ], "roles":[ ] }
现在用户user3已创建,您可以授予user3角色collectionFind.
db.grantRolesToUser("user3",["collectionRole"])
最后,user1 和 user2 都离开了公司,需要撤销他们对集群的访问权限。您可以通过删除用户来执行此操作,如下所示。
db.dropUser("user1") db.dropUser("user2")
要确保所有用户都具有适当角色,可使用以下命令列出所有用户。
show users
此操作的输出将类似于下文。
{ "_id":"serviceadmin", "user":"serviceadmin", "db":"admin", "roles":[ { "db":"admin", "role":"root" } ] } { "_id":"master-user", "user":"master-user", "db":"admin", "roles":[ { "db":"admin", "role":"root" } ] } { "_id":"user3", "user":"user3", "db":"admin", "roles":[ { "db":"admin", "role":"collectionRole" } ] }
以用户身份连接到 Amazon DocumentDB
在连接到 Amazon DocumentDB 集群时,需要在特定数据库的上下文中进行连接。默认情况下,如果未在连接字符串中指定数据库,则会在 test 数据库上下文中自动连接到集群。所有集合级别命令(如 insert 和 find)都是针对 test 数据库中的集合发出的。
要查看您所在上下文或者换句话说对其发出命令的数据库,请使用db命令在 mongo shell 中执行,如下所示。
查询:
db
输出:
test
尽管默认连接可能位于 test 数据库的上下文中,但这并不一定意味着与连接关联的用户有权对 test 数据库执行操作。在上述示例方案中,如果您用于进行身份验证的用户 user3 是具有对 sample-database-1 数据库的 readWrite 权限的角色,则连接的默认上下文是 test 数据库。但是,如果您尝试将文档插入 test 数据库中的集合中,您将收到 Authorization failure (授权失败) 错误消息。这是因为该用户未获得对该数据库执行该命令的授权,如下所示。
查询:
db
输出:
test
查询:
db.col.insert({x:1})
输出:
WriteCommandError({ "ok" : 0, "code" : 13, "errmsg" : "Authorization failure" })
如果您将连接上下文更改为 sample-database-1 数据库,则可以写入到集合中,因为该用户具有执行此操作的授权。
查询:
use sample-database-1
输出:
switched to db sample-database-1
查询:
db.col.insert({x:1})
输出:
WriteResult({ "nInserted" : 1})
使用特定用户对集群进行身份验证时,还可以在连接字符串中指定数据库。如果这样做,则用户在通过 admin 数据库的身份验证后,不再需要执行 use 命令。
以下连接字符串根据 admin 数据库对用户进行身份验证,但连接上下文则是 sample-database-1 数据库。
mongo "mongodb://user3:abc123@sample-cluster.node.us-east-1.docdb.amazonaws.com:27017/sample-database-2"
常见命令
本部分提供在 Amazon DocumentDB 中使用基于角色的访问控制的常见命令示例。您必须位于 admin 数据库的上下文中,才能创建和修改用户和角色。您可以使用 use admin 命令切换到 admin 数据库。
对用户和角色的修改将隐式发生在 admin 数据库中。创建具有跨所有数据库范围的角色的用户(例如,readAnyDatabase)需要在创建用户时处于 admin 数据库上下文(即 use
admin),或者在创建用户时明确指定角色的数据库(如本节的示例 2 所示)。
示例 1:使用创建用户read数据库的角色foo.
db.createUser({user: "readInFooBar", pwd: "abc123", roles: [{role: "read", db: "foo"}]})
此操作的输出将类似于下文。
{
"user":"readInFooBar",
"roles":[
{
"role":"read",
"db":"foo"
}
]
}
示例 2:创建具有所有数据库的读取访问权限的用户。
db.createUser({user: "readAllDBs", pwd: "abc123", roles: [{role: "readAnyDatabase", db: "admin"}]})
此操作的输出将类似于下文。
{
"user":"readAllDBs",
"roles":[
{
"role":"readAnyDatabase",
"db":"admin"
}
]
}
示例 3:Grantread角色到新数据库中现有用户。
db.grantRolesToUser("readInFooBar", [{role: "read", db: "bar"}])
示例 4:更新用户的角色。
db.updateUser("readInFooBar", {roles: [{role: "read", db: "foo"}, {role: "read", db: "baz"}]})
示例 5:撤销用户对数据库的访问权限。
db.revokeRolesFromUser("readInFooBar", [{role: "read", db: "baz"}])
示例 6:描述内置角色。
db.getRole("read", {showPrivileges:true})
此操作的输出将类似于下文。
{
"role":"read",
"db":"sample-database-1",
"isBuiltin":true,
"roles":[
],
"inheritedRoles":[
],
"privileges":[
{
"resource":{
"db":"sample-database-1",
"collection":""
},
"actions":[
"changeStream",
"collStats",
"dbStats",
"find",
"killCursors",
"listCollections",
"listIndexes"
]
}
],
"inheritedPrivileges":[
{
"resource":{
"db":"sample-database-1",
"collection":""
},
"actions":[
"changeStream",
"collStats",
"dbStats",
"find",
"killCursors",
"listCollections",
"listIndexes"
]
}
}
示例 7 示例:从集群中删除用户。
db.dropUser("readInFooBar")
此操作的输出将类似于下文。
true
示例 8:创建具有特定集合的读写访问权限的角色
db.createRole( { role: "collectionRole", privileges: [ { resource: {db: "sample-database-2", collection: "col2"}, actions: ["find", "update", "insert", "remove"] }], roles: [] } )
此操作的输出将类似于下文。
{ "role":"collectionRole", "privileges":[ { "resource":{ "db":"sample-database-2", "collection":"col2" }, "actions":[ "find", "update", "insert", "remove" ] } ], "roles":[ ] }
示例 9.:创建用户并分配用户定义的角色
db.createUser( { user: "user3", pwd: "abc123", roles: [] }) db.grantRolesToUser("user3",["collectionRole"])
示例 10.:向用户定义的角色授予额外权限
db.grantPrivilegesToRole( "collectionRole", [ { resource: { db: "sample-database-1", collection: "col1" }, actions: ["find", "update", "insert", "remove"] } ] )
示例 11 示例:从用户定义的角色中删除权限
db.revokePrivilegesFromRole( "collectionRole", [ { resource: { db: "sample-database-1", collection: "col2" }, actions: ["find", "update", "insert", "remove"] } ] )
示例 12.:更新现有用户定义的角色
db.updateRole( "collectionRole", { privileges: [ { resource: {db: "sample-database-3", collection: "sample-collection-3"}, actions: ["find", "update", "insert", "remove"] }], roles: [] } )
功能差异
在 Amazon DocumentDB 中,用户和角色定义存储在admin数据库和用户将根据admin数据库。此功能与 MongoDB 社区版不同,但与 MongoDB Atlas 一致。
Amazon DocumentDB 还支持变更流,该功能提供按时间顺序排列的更改事件,这些事件在您的集群集合内发生。这些区域有:listChangeStreams操作在集群级别(即跨所有数据库)应用,而modifyChangeStreams操作可以在数据库级别和群集级别应用。
限制
下表包含 Amazon DocumentDB 中基于角色的访问控制的限制。
| 描述 | 限制 |
|---|---|
| 每个集群的用户数 | 1000 |
| 与用户关联的角色数 | 1000 |
| 用户定义的角色数 | 100 |
| 与权限关联的资源数 | 100 |
基于角色的访问控制限制数据库访问
借助基于角色的访问控制,您可以创建一个用户并向其授予一个或多个角色,以确定该用户可以在数据库或集群中执行哪些操作。
以下是 Amazon DocumentDB 中目前支持的内置角色的列表。
在 Amazon DocumentDB 4.0 中,ListCollection和ListDatabase命令可以选择使用authorizedCollections和authorizedDatabases用于列出用户有权访问的集合和数据库的参数listCollections和listDatabase角色,分别。此外,用户现在可以杀死自己的光标,而无需KillCursor角色。
| 角色类型 | 角色名称 | 描述 | 操作 |
|---|---|---|---|
| 数据库用户 | read |
授予用户对指定数据库的读取权限。 |
|
readWrite |
授予用户对指定数据库的读取和写入访问权限。 |
使用
|
|
| 集群用户 | readAnyDatabase | 授予用户对集群中所有数据库的读取权限。 |
使用
|
readWriteAnyDatabase |
授予用户对集群中所有数据库的读写权限。 |
使用
|
|
userAdminAnyDatabase |
授予用户为所有用户分配或修改对指定数据库的角色或权限的能力。 |
|
|
dbAdminAnyDatabase |
授予用户对所有指定数据库执行数据库管理角色的能力。 |
使用
|
|
| Superuser | root |
授予用户对以下所有角色的合并资源和操作的访问权限: readWriteAnyDatabase、dbAdminAnyDatabase、userAdminAnyDatabase、clusterAdmin、restore 和 backup。 |
使用 |
| 数据库管理 | dbAdmin |
授予用户对指定数据库执行管理任务的能力。 |
|
dbOwner |
通过合并角色 dbAdmin 和 readWrite 授予用户对指定数据库执行任何管理任务的能力。 |
使用 |
|
| 集群管理 | clusterAdmin |
通过合并 clusterManager、clusterMonitor 和 hostManager 角色授予用户最大的集群管理访问权限。 |
使用
|
clusterManager |
授予用户对指定集群执行管理和监控操作的能力。 |
|
|
clusterMonitor |
授予用户对监控工具可具有只读访问权限的能力。 |
|
|
hostManager |
授予用户监视和管理服务器的能力。 |
|
|
| 备份管理 | backup |
授予用户备份数据所需的访问权限。 |
|
restore |
授予用户还原数据所需的访问权限。 |
|