mongodb权限控制

数据库安全性非常重要,不能轻易给普通用户写权限。一般只需要创建一个只读权限的账号,供普通用户查看即可。
mongodb权限控制方式 mongodb权限控制
mongodb用户管理权限控制
mongodb是基于RBAC权限模型来实现权限控制的。RBAC(Role-Based Access Control) 认为授权就是“Who对What进行How的操作”。也就是说,我们通过给角色授权,然后将该角色授给某个用户,这样这个用户就拥有了该角色所拥有的所有权利。所以为了帮助我们更好的管理数据库mongodb内置了很多的角色。常用的有:

  • read: 只能读取指定数据库
  • readWrite: 能读写指定数据库
  • dbAdmin: 能执行管理函数,如索引创建、删除,查看统计或访问 system.profile
  • dbOwner: 对当前数据库有全部权限
  • userAdmin: 能创建、删除和管理用户
  • clusterAdmin: 只能在 admin 数据库中可用,能赋予用户所有分片和复制集相关函数的管理权限
  • readAnyDatabase: 只能在 admin 数据库中可用,能赋予用户所有数据库的读权限
  • readWriteAnyDatabase: 只能在 admin 数据库中可用,能赋予用户所有数据库的读写权限
  • userAdminAnyDatabase: 只能在 admin 数据库中可用,能赋予用户所有数据库的 userAdmin 权限
  • dbAdminAnyDatabase: 只能在 admin 数据库中可用,能赋予用户所有数据库的 dbAdmin 权限
  • root: 只能在 admin 数据库中可用。超级权限
要想管理所有的数据库,就只能切换到admin数据库中,然后在该数据库中创建用户。如果只管理某个数据库,那就切换到要管理的数据库中,创建用户即可。创建的命令如下
use xxx_db db.createUser({user:'user_name', pwd:'password', roles:[{role:'read', db:'xxx_db'}]})

在哪个数据库中创建的用户,就需要到该数据库中进行认证。为了方便管理,最好在要管理的数据库中创建用户,这样直接在该数据库中执认证命令即可,db.auth('user', 'pwd')。否则我们认证时还要先切换到我们创建用户时的数据库,认证完后再切换回来,这样会给我们带来不必要的麻烦,和管理上的混乱。
mongod开启权限认证 【mongodb权限控制】由于我给了普通用户写权限,为了安全起见,需要赶紧创建个只读权限的账户,然后修改写权限账户的密码。创建完只读权限的用户之后,发现没有生效,用户仍然可以修改数据。以为修改没有生效,重启mongodb的docker容器,重启失败,使用docker logs查看日志,发现报错
Failed to unlink socket file /tmp/mongodb-27017.sock Permission denied
网上找到解决方案需要删除sock文件,docker没有docker rm命令,只能利用find / -name 'mongodb-27017.sock'命令在宿主机找到,然后删除该文件
重启成功后,发现没有效果,用户仍然可以修改数据。在stackoverflow找到了原因created user in mongo with read role can insert,没有开启权限认证。
发现不仅用户登录某个账户后不受role字段的约束,而且直接在无账户密码验证模式下就可以登录。
docker ps -a --no-trunc 发现容器的启动命令是通过docker-entrypoint.sh启动,在文章dockerfile介绍中介绍了:ENTRYPOINT 和CMD很相似,都是指定启动命令,不同之处在于ENTRYPOINT 指定的命令无法被docker run 参数取代。
在docker-entrypoint.sh文件中,并且参考文章Docker系列教程02-MongoDB默认开启鉴权,发现只有在创建容器时指定环境变量MONGO_INITDB_ROOT_USERNAME与MONGO_INITDB_ROOT_PASSWORD时,数据库才会开启权限认证。但是目前容器已经创建,无法重新指定环境变量。想通过修改docker-entrypoint.sh文件,开启权限认证。直接给MONGO_INITDB_ROOT_USERNAME与MONGO_INITDB_ROOT_PASSWORD赋值,然后重启容器,但是容器启动失败,报错
BadValue: security.keyFile is required when authorization is enabled with replica sets
然后突然意识到,容器启动失败,不能通过docker exec进入容器修改docker-entrypoint.sh了,并且是生产环境使用的数据库,需要尽快恢复正常。然后想到,可以利用docker cp命令。之前把docker-entrypoint.sh的内容复制到了本地windows电脑上了一份,现在正好复制到宿主机上,然后docker cp复制到容器内部。再次重启,报错
/usr/local/bin/docker-entrypoint.sh: line 382: warning: here-document at line 222 delimited by end-of-file (wanted `EOF’)
/usr/local/bin/docker-entrypoint.sh: line 383: syntax error: unexpected end of file
按照文章syntax error: unexpected end of file完美解决方案 set ff=unix没用。
想到其实不应该用windows复制的内容,应该先把容器中修改entrypoint文件复制出来,修改正确后再复制进去,但是来不及了。
最后,利用mongo镜像开启新的mongo容器,使用docker cp命令把新容器docker-entrypoint.sh复制出来,然后再复制到出问题的容器中,解决。
总结反思 1. 不能在生产环境下随意改动,不然出问题后,可能造成严重后果,而且需要立即修复。
2. 在修改重要文件之前,一定要先备份,这样在出错之后,可以立即恢复。

    推荐阅读