MongoDB用户验证和权限那些事儿

用过MongoDB的朋友都知道MongoDB默认不需要用户名和密码就可以以最高权限访问数据库进行任何操作,这种状态开发环境下还好,如果部署到生产环境下非常危险。因为MongoDB更新迅速,2.6版本和最新的3.2版本设置差距很大,我在设置用户和权限的时候遇到了很多坑,这里决定以最新的3.2版本为例理一理关于MongoDB用户和权限的一些事情,并加入我对数据库用户和权限设置和备份的一些配置实践,防止大家继续入坑。

基本概念

先说一下关于用户、验证和角色的基本概念。

用户

要在MongoDB中验证客户端,必须向MongoDB添加相应的用户。

添加用户

添加用户使用MongoDB的用户管理接口,此接口提供db.createUser()的方式添加用户(这里有坑,网络上很多关于MongoDB添加用户的内容还都在使用db.addUser(),这是2.6版本的添加用户方式)。
假如我们有test数据库,要为此数据库添加用户,我们可以在mongo shell下使用以下语句:

> db.createUser({
    user: "user1",//用户名
    pwd: "12345678",//密码(实际操作中设置密码要尽量复杂)
    roles: [//权限数组
        {
            role: "readWrite",
            db: "test"//test数据库的读写权限
        }
    ]
})

执行后的返回结果:

这样我们就为test数据库创建了一个拥有读写权限的用户。

验证

验证是认证客户端身份的过程。 当访问控制(即授权)被启用时,MongoDB要求所有客户端对其自身进行认证,以确定其访问。

开启验证

我们刚刚创建了一个用户,但如果我们是以默认的方式启动mongod,验证并没有生效,那么我们来停掉mongod服务并在启动时增加配置项使验证生效。

通过增加mongod参数来开启验证

在启动mongod的时候增加--auth参数就可以使验证生效。

mongod --auth
通过修改配置文件来开启验证

我们也可以通过修改MongoDB的配置文件来启用验证。
在Linux服务器上配置文件一般存放在/etc文件夹中,如果没有我们就创建一个。

vim /etc/mongodb.conf
# mongodb.conf
# Where to store the data.
dbpath=/var/lib/mongo
#where to log
logpath=/var/log/mongodb/mongod.log
logappend=true
bind_ip = 0.0.0.0
port = 27017
# Enable journaling, http://www.mongodb.org/display/DOCS/Journaling
journal=true
#fork
fork = true
# Enables periodic logging of CPU utilization and I/O wait
#cpu = true
# Turn on/off security.  Off is currently the default
#noauth = true
#我们把启用验证的设置加载这里
auth = true
#。。。。。。

我只截取了配置文件的一部分,这个配置文件的其他内容我不再赘述了,我们只需要知道怎样配置开启验证。
保存后执行下面的代码来启动mongod

mongod -f /etc/mongodb.conf

使用验证

我们刚刚开启了验证,下面两种方式可以使用刚才创建的用户来操作需要验证访问的数据库。

在连接时验证

使用-u ,-p 和--authenticationDatabase 命令行选项启动mongo shell:

mongo -uuser1 -p12345678 --authenticationDatabase test

在连接后验证

通过mongo shell连接MongoDB。

mongo

切换到对应的数据库。

> use test

然后使用db.auth(<username>, <pwd>)的方式验证用户。

>  db.auth('user1', '12345678')

两种验证方式均可以使用该用户操作对应的数据库。

用户角色

角色授予对资源执行指定操作的权限,我们在这里只讨论MongoDB的常用内置角色(对我已经足够了)。

数据库用户角色

每个数据库都包含以下权限:

角色 描述
read 提供读取所有非系统集合以及以下系统集合上的数据的能力:system.indexes,system.js和system.namespaces集合。
readWrite 提供读取角色的所有权限,并能够修改所有非系统集合和system.js集合上的数据。

数据库管理员角色

每个数据库都包含以下数据库管理员权限:

角色 描述
dbAdmin 提供执行管理任务的能力,例如与结构相关的任务,索引,收集统计信息,此角色不能直接管理用户和管理用户角色。
dbOwner 提供对数据库执行任何管理操作的能力,此角色由readWritedbAdminuserAdmin组合而成。
userAdmin 提供在当前数据库上创建和修改角色和用户的功能。

备份和恢复角色

admin数据库中包括以下用于备份和恢复数据的角色:

角色 描述
backup 提供数据备份所需的权限,此用户可以使用mongodump
restore 提供数据恢复所需的权限,此用户可以使用mongorestore(只能还原不包含system.profile集合的数据)。

超级用户角色

下面的角色为所有资源提供所有权限:

角色 描述
root 超级用户权限,提供对数据库的全部操作权限。

配置实践

我对MongoDB的配置思路是建立一个对现有生产数据库的可读写权限的用户供程序使用,建立一个超级用户和一个备份还原用户,每小时对数据库执行一次备份。这并不是一个推荐的配置方式,只是满足我当前对数据库安全的需求。

为应用程序建立可读写用户

在mongoshell下执行以下命令:

> use test   
> db.createUser({
    user: "user1",//用户名
    pwd: "12345678",//密码(实际操作中设置密码要尽量复杂)
    roles: [//权限数组
        {
            role: "readWrite",
            db: "test"//test数据库的读写权限
        }
    ]
})

建立后修改程序中对MongoDB的连接配置即可测试程序与数据库的连接。

建立超级用户

在mongoshell下执行以下命令:

> use admin
> db.createUser({
    user: "su",
    pwd: "12345678",
    roles: [
        {
            role: "root",
            db: "admin"
        }
    ]
})

建立备份还原用户

在mongoshell下执行以下命令:

> use admin
> db.createUser({
    user: "dbbackup",
    pwd: "12345678",
    roles: [
        {
            role: "backup",
            db: "admin"
        }, {
            role: "restore",
            db: "admin"
        }
    ]
})

配置数据库定时备份

数据库备份

数据库备份我直接从github上搜到了一个备份的脚本,修改脚本中的参数,并修改文件命名方式支持每小时备份。地址在这里
这里我们用到了刚刚创建的具有备份和恢复权限的用户,将其写入配置文件中:

### Set server settings
HOST="localhost"
PORT="27017" # default mongoDb port is 27017
USERNAME="dbbackup"
PASSWORD="12345678"

配置后执行脚本测试:


执行成功后会在配置好的目录生成打包的备份文件。

加入定时任务

使用crontab将数据库备份加入定时任务中,在bash中执行以下语句:

crontab -e

进入crontab的编辑模式,加上每小时执行一次备份的脚本:

0 * * * * /path/to/shell/directory/mongodb-backup.sh

保存后启动crontab。

service crond start

将crontab加入开机启动:

chkconfig crond on

过几个小时再看备份目录中已经有了打包好的备份文件了,搞定!

恢复数据库

恢复数据库这块儿有一个坑,就是3.2版本的mongorestore参数和2.6版本的不一样了。网上搜到的大部分恢复数据库定位备份文件的参数都是--directoryperdb而实际使用时会报错,后来查看mongorestore帮助文档才发现变成了--dir。下面是恢复命令:

mongorestore --port 27017 -uuser1 -p12345678 --db test --dir=/path/to/backup/directory/test/
Comments
Write a Comment