基於MongodbDB的使用者認證-運維筆記

散盡浮華發表於2018-09-21

 

MongoDB預設是不認證的,預設沒有賬號,只要能連線上服務就可以對資料庫進行各種操作,MongoDB認為安全最好的方法就是在一個可信的環境中執行它,保證之後可信的機器才能訪問它,可能這些對一些要求高的環境,安全還不夠。MongoDB提供使用者認證,需要在啟動時加上--auth開啟認證

一、MongoDB安裝

Mongodb各版本下載地址:https://www.mongodb.org/dl/linux/x86_64-rhel62
本案例的Mongodbv3.2百度下載地址:https://pan.baidu.com/s/194ef261BpcypxzAl9aRaQg
提取密碼:tv8m
下載放到伺服器的/usr/local/src目錄下

1.1)安裝MongoDB
[root@MongoDB-server ~]# cd /usr/local/src/
[root@MongoDB-server src]# ll mongodb-linux-x86_64-rhel62-v3.2-latest.tgz
-rw-r--r-- 1 root root 86699142 Nov 22  2017 mongodb-linux-x86_64-rhel62-v3.2-latest.tgz
[root@MongoDB-server src]# tar -zvxf mongodb-linux-x86_64-rhel62-v3.2-latest.tgz
[root@MongoDB-server src]# mv mongodb-linux-x86_64-rhel62-3.2.17-34-g4c1bae566c /usr/local/mongodb
  
[root@MongoDB-server src]# ll /usr/local/mongodb              //Mongodb主目錄
total 100
drwxr-xr-x 2 root root  4096 Sep 20 22:33 bin
-rw-r--r-- 1 root root 34520 Nov 21  2017 GNU-AGPL-3.0
-rw-r--r-- 1 root root 16726 Nov 21  2017 MPL-2
-rw-r--r-- 1 root root  2262 Nov 21  2017 README
-rw-r--r-- 1 root root 35910 Nov 21  2017 THIRD-PARTY-NOTICES
  
[root@MongoDB-server src]# mkdir /usr/local/mongodb/data     //Mongodb資料目錄,可以存放在一個獨立的大分割槽上
[root@MongoDB-server src]# mkdir /usr/local/mongodb/log      //Mongodb日誌目錄
  
1.2)啟動MongoDB
使用mongod命令建立一個mongodb資料庫連結,資料庫的路徑為/usr/local/mongodb/data,日誌路徑為/usr/local/mongodb/log/mongo.log
mongodb的啟動程式放在後臺執行,下面命令執行後,按ctrl+c。
[root@MongoDB-server src]# nohup /usr/local/mongodb/bin/mongod --dbpath=/usr/local/mongodb/data/ --logpath=/usr/local/mongodb/log/mongo.log &
  
==========================================
mongodb的引數說明:
--dbpath 資料庫路徑(資料檔案)
--logpath 日誌檔案路徑
--master 指定為主機器
--slave 指定為從機器
--source 指定主機器的IP地址
--pologSize 指定日誌檔案大小不超過64M.因為resync是非常操作量大且耗時,最好通過設定一個足夠大的oplogSize來避免resync(預設的 oplog大小是空閒磁碟大小的5%)。
--logappend 日誌檔案末尾新增
--port 啟用埠號
--fork 在後臺執行
--only 指定只複製哪一個資料庫
--slavedelay 指從複製檢測的時間間隔
--auth 是否需要驗證許可權登入(使用者名稱和密碼)
==========================================
  
[root@MongoDB-server src]# ps -ef|grep mongodb
root     13216 10204  0 22:38 pts/1    00:00:00 /usr/local/mongodb/bin/mongod --dbpath=/usr/local/mongodb/data/ --logpath=/usr/local/mongodb/log/mongo.log
root     14185 10204  0 22:42 pts/1    00:00:00 grep mongodb
  
MongoDB預設埠是27017,啟動後,等一會兒埠就會起來。如果啟動後,發現埠沒有起來,可以檢視日誌/usr/local/mongodb/log/mongo.log
[root@MongoDB-server src]# lsof -i:27017
COMMAND   PID USER   FD   TYPE  DEVICE SIZE/OFF NODE NAME
mongod  13216 root    6u  IPv4 4260453      0t0  TCP *:27017 (LISTEN)
  
1.3)設定mongodb的環境變數
[root@MongoDB-server src]# vim /etc/profile
......
export PATH=$PATH:/usr/local/mongodb/bin/
[root@MongoDB-server src]# source /etc/profile
[root@MongoDB-server src]# mongod --version
db version v3.2.17-34-g4c1bae566c
git version: 4c1bae566c0c00f996a2feb16febf84936ecaf6f
OpenSSL version: OpenSSL 1.0.1e-fips 11 Feb 2013
allocator: tcmalloc
modules: none
build environment:
    distmod: rhel62
    distarch: x86_64
    target_arch: x86_64
  
1.4)為了更方便的啟動和關閉MongoDB,可以使用Shell寫指令碼,當然也可以加入到service中。更好的方式是採用配置檔案,把MongoDB需要的引數寫入配置檔案,
然後在指令碼中引用;
[root@MongoDB-server src]# vim /usr/local/mongodb/mongodb.conf
#代表埠號,如果不指定則預設為27017
port=27017
#繫結ip
bind_ip=0.0.0.0
#MongoDB資料檔案目錄
dbpath=/usr/local/mongodb/data
#MongoDB日誌檔案目錄
logpath=/usr/local/mongodb/log/mongo.log
#日誌檔案自動累加
logappend=true
  
編寫MongoDB啟動指令碼
[root@MongoDB-server src]# vim /etc/init.d/mongodb
#!/bin/bash
#
# mongod        Start up the MongoDB server daemon
#
     
# source function library
. /etc/rc.d/init.d/functions
#定義命令
CMD=/usr/local/mongodb/bin/mongod
#定義配置檔案路徑
INITFILE=/usr/local/mongodb/mongodb.conf
start()
{
    #&表示後臺啟動,也可以使用fork引數
    $CMD -f $INITFILE &
    echo "MongoDB is running background..."
}
     
stop()
{
    pkill mongod
    echo "MongoDB is stopped."
}
     
case "$1" in
    start)
        start
        ;;
    stop)
        stop
        ;;
    *)
        echo $"Usage: $0 {start|stop}"
esac
  
授予指令碼可執行許可權
[root@MongoDB-server src]# chmod 755 /etc/init.d/mongodb
  
[root@MongoDB-server src]# /etc/init.d/mongodb status
Usage: /etc/init.d/mongodb {start|stop}
[root@MongoDB-server src]# /etc/init.d/mongodb stop
Terminated
[root@MongoDB-server src]# lsof -i:27001
[1]+  Done                    nohup /usr/local/mongodb/bin/mongod --dbpath=/usr/local/mongodb/data/ --logpath=/usr/local/mongodb/log/mongo.log
[root@MongoDB-server src]# lsof -i:27001
[root@MongoDB-server src]# /etc/init.d/mongodb start
MongoDB is running background...
[root@MongoDB-server src]# ps -ef|grep mongodb
root     16060     1  2 22:49 pts/1    00:00:00 /usr/local/mongodb/bin/mongod -f /usr/local/mongodb/mongodb.conf
root     16205 10204  0 22:49 pts/1    00:00:00 grep mongodb
  
[root@MongoDB-server ~]# lsof -i:27001
[root@MongoDB-server ~]#
  
啟動後發現27017埠沒有起來,檢視日誌:
[root@MongoDB-server src]# tail -f /usr/local/mongodb/log/mongo.log
......
2018-09-20T22:55:46.236+0800 I NETWORK  [initandlisten] waiting for connections on port 27017
2018-09-20T22:55:46.290+0800 W NETWORK  [HostnameCanonicalizationWorker] Failed to obtain address information for hostname MongoDB-server: Name or service not known
2018-09-20T22:55:47.014+0800 I FTDC     [ftdc] Unclean full-time diagnostic data capture shutdown detected, found interim file, some metrics may have been lost. OK
  
原因:獲取不到地址對應的主機名,這一般與HOSTS有關
  
解決辦法:
[root@MongoDB-server ~]# ifconfig|grep "inet addr"|grep Bcast|awk -F":" '{print $2}'|awk '{print $1}'
192.168.10.205
[root@MongoDB-server ~]# hostname
MongoDB-server
[root@MongoDB-server ~]# vim /etc/hosts
[root@MongoDB-server ~]# echo "192.168.10.205 MongoDB-server" >> /etc/hosts
[root@MongoDB-server ~]# cat /etc/hosts
......
192.168.10.205 MongoDB-server
  
再次啟動
[root@MongoDB-server ~]# ps -ef|grep mongodb
root     17789     1  0 22:55 pts/0    00:00:01 /usr/local/mongodb/bin/mongod -f /usr/local/mongodb/mongodb.conf
root     18933 16606  0 23:00 pts/0    00:00:00 grep mongodb
[root@MongoDB-server ~]# kill -9 16890
[root@MongoDB-server ~]# ps -ef|grep mongodb
root     18979 16606  0 23:00 pts/0    00:00:00 grep mongodb
[root@MongoDB-server ~]# /etc/init.d/mongodb start
MongoDB is running background...
  
[root@MongoDB-server ~]# ps -ef|grep mongodb
root     17789     1  0 22:55 pts/0    00:00:01 /usr/local/mongodb/bin/mongod -f /usr/local/mongodb/mongodb.conf
root     19132 16606  0 23:00 pts/0    00:00:00 grep mongodb
[root@MongoDB-server ~]# lsof -i:27017
COMMAND   PID USER   FD   TYPE  DEVICE SIZE/OFF NODE NAME
mongod  17789 root    6u  IPv4 4289555      0t0  TCP *:27017 (LISTEN)
  
連線MongoDB服務
[root@MongoDB-server src]# mongo 127.0.0.1:27017    或者直接使用mongo命令進行連線,預設連線的就是127.0.0.1:27017
MongoDB shell version: 3.2.17-34-g4c1bae566c
connecting to: 127.0.0.1:27017/test
Welcome to the MongoDB shell.
For interactive help, type "help".
For more comprehensive documentation, see
        http://docs.mongodb.org/
Questions? Try the support group
        http://groups.google.com/group/mongodb-user
Server has startup warnings:
2018-09-20T22:55:46.232+0800 I CONTROL  [initandlisten] ** WARNING: You are running this process as the root user, which is not recommended.
2018-09-20T22:55:46.233+0800 I CONTROL  [initandlisten]
2018-09-20T22:55:46.233+0800 I CONTROL  [initandlisten]
2018-09-20T22:55:46.233+0800 I CONTROL  [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/enabled is 'always'.
2018-09-20T22:55:46.233+0800 I CONTROL  [initandlisten] **        We suggest setting it to 'never'
2018-09-20T22:55:46.233+0800 I CONTROL  [initandlisten]
2018-09-20T22:55:46.233+0800 I CONTROL  [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always'.
2018-09-20T22:55:46.233+0800 I CONTROL  [initandlisten] **        We suggest setting it to 'never'
2018-09-20T22:55:46.233+0800 I CONTROL  [initandlisten]
> help
        db.help()                    help on db methods
        db.mycoll.help()             help on collection methods
        sh.help()                    sharding helpers
        rs.help()                    replica set helpers
        help admin                   administrative help
        help connect                 connecting to a db help
        help keys                    key shortcuts
        help misc                    misc things to know
        help mr                      mapreduce
  
        show dbs                     show database names
        show collections             show collections in current database
        show users                   show users in current database
        show profile                 show most recent system.profile entries with time >= 1ms
        show logs                    show the accessible logger names
        show log [name]              prints out the last segment of log in memory, 'global' is default
        use <db_name>                set current database
        db.foo.find()                list objects in collection foo
        db.foo.find( { a : 1 } )     list objects in foo where a == 1
        it                           result of the last line evaluated; use to further iterate
        DBQuery.shellBatchSize = x   set default number of items to display on shell
        exit                         quit the mongo shell
> show dbs
local  0.000GB
>

二、MongoDB認證

MongoDB Roles(內建角色)
- 資料庫使用者角色:read、readWrite;
- 資料庫管理角色:dbAdmin、dbOwner、userAdmin;
- 叢集管理角色:clusterAdmin、clusterManager、clusterMonitor、hostManager;
- 備份恢復角色:backup、restore;
- 所有資料庫角色:readAnyDatabase、readWriteAnyDatabase、userAdminAnyDatabase、dbAdminAnyDatabase
- 超級使用者角色:root 
- 這裡還有幾個角色間接或直接提供了系統超級使用者的訪問(dbOwner 、userAdmin、userAdminAnyDatabase)
- 內部角色:__system

具體角色
- Read:允許使用者讀取指定資料庫
- readWrite:允許使用者讀寫指定資料庫
- dbAdmin:允許使用者在指定資料庫中執行管理函式,如索引建立、刪除,檢視統計或訪問system.profile
- userAdmin:允許使用者向system.users集合寫入,可以找指定資料庫裡建立、刪除和管理使用者
- clusterAdmin:只在admin資料庫中可用,賦予使用者所有分片和複製集相關函式的管理許可權。
- readAnyDatabase:只在admin資料庫中可用,賦予使用者所有資料庫的讀許可權
- readWriteAnyDatabase:只在admin資料庫中可用,賦予使用者所有資料庫的讀寫許可權
- userAdminAnyDatabase:只在admin資料庫中可用,賦予使用者所有資料庫的userAdmin許可權
- dbAdminAnyDatabase:只在admin資料庫中可用,賦予使用者所有資料庫的dbAdmin許可權。
- root:只在admin資料庫中可用。超級賬號,超級許可權

認證操作例項如下
初始化資料庫的時候,一定要先禁止使用者驗證功能,然後在建立管理使用者,之後就可以開啟驗證,運算元據庫了。

MongoDB認證前需要新增賬號,新增管理員賬號(預設情況下系統中沒有使用者)
 
謹記:先在不開啟認證的情況下,建立使用者,之後關閉服務,然後再開啟認證,才生效!!!!
 
[root@MongoDB-server src]# mongo 127.0.0.1:27017
......
 
切換到admin庫
> use admin                        
switched to db admin

新增超級使用者
> use admin
switched to db admin
> db.system.users.find(); 
> db.addUser("admin","1234!@#$qwer");
2018-09-21T09:59:56.125+0800 E QUERY    [thread1] TypeError: db.addUser is not a function :
@(shell):1:1

如上建立使用者報錯:報錯addUser is not a function
經過排查原因,由於MongDB3.x版本已經不再支援addUser()方法,用createUser()方法取而代之。
特別注意的是:建立使用者以及設定密碼時,role角色裡面一定要跟role、db引數,認證時對應的庫一定要搞清楚!

admin管理員授權時,role角色最好設定成root,否則認證後可能會有些命令執行不了。

> db.createUser({user: "admin",pwd: "1234!@#$qwer",roles:[{"role":"root","db":"admin"}]});
Successfully added user: {
        "user" : "admin",
        "roles" : [
                {
                        "role" : "root",
                        "db" : "admin"
                }
        ]
}
> 

查詢新增的使用者(必須要先切換到admin庫下進行檢視)
> db.system.users.find();
{ "_id" : "admin.admin", "user" : "admin", "db" : "admin", "credentials" : { "SCRAM-SHA-1" : { "iterationCount" : 10000, "salt" : 
"tnnpiLjweUJWR1mQzC/cuw==", "storedKey" : "Q7G7KqfYQa3eKcHOSsSkxGs2Ci0=", "serverKey" : "GKOG66hhf6DkXNrTmHWGoFHxXFo=" } }, "roles" 
: [ { "role" : "root", "db" : "admin" } ] }

新增普通賬號
切換到kevin庫新增普通使用者(readWrite有讀寫許可權;read有讀許可權)
> use kevin;
switched to db kevin
> db.createUser({user: "kevin",pwd: "kevin@123456",roles:[{"role":"readWrite","db":"kevin"}]});
Successfully added user: {
        "user" : "kevin",
        "roles" : [
                {
                        "role" : "readWrite",
                        "db" : "kevin"
                }
        ]
}

> use grace;
switched to db grace
> db.createUser({user: "grace",pwd: "grace@123",roles:[{"role":"read","db":"grace"}]});
Successfully added user: {
        "user" : "grace",
        "roles" : [
                {
                        "role" : "read",
                        "db" : "grace"
                }
        ]
}

查詢新增的使用者(必須要先切換到admin庫下進行檢視)
> use admin;
switched to db admin
> db.system.users.find();
{ "_id" : "admin.admin", "user" : "admin", "db" : "admin", "credentials" : { "SCRAM-SHA-1" : { "iterationCount" : 10000, "salt" : "tnnpiLjweUJWR1mQzC/cuw==", "storedKey" : "Q7G7KqfYQa3eKcHOSsSkxGs2Ci0=", "serverKey" : "GKOG66hhf6DkXNrTmHWGoFHxXFo=" } }, "roles" : [ { "role" : "root", "db" : "admin" } ] }
{ "_id" : "kevin.kevin", "user" : "kevin", "db" : "kevin", "credentials" : { "SCRAM-SHA-1" : { "iterationCount" : 10000, "salt" : "u3RgCHmt3AfigOIVNKy7OA==", "storedKey" : "Je7SP6SohGPZSb3VBXOJkNlXz20=", "serverKey" : "5laXjac6NfpYuivcmK3SK0GohRo=" } }, "roles" : [ { "role" : "readWrite", "db" : "kevin" } ] }
{ "_id" : "grace.grace", "user" : "grace", "db" : "grace", "credentials" : { "SCRAM-SHA-1" : { "iterationCount" : 10000, "salt" : "9xLjmg7Q8YsZ1Y9vF71P6g==", "storedKey" : "tID4qA9AaJ4IIOgbC1oHZZYqVdg=", "serverKey" : "ayvaN6QkDUOz1KUs+SG3S8IyvAo=" } }, "roles" : [ { "role" : "read", "db" : "grace" } ] }
> 

刪除使用者
> use admin;
switched to db admin
> db.system.users.remove({user:"admin"})
WriteResult({ "nRemoved" : 1 })
> db.system.users.remove({user:"kevin"})
WriteResult({ "nRemoved" : 1 })
> db.system.users.remove({user:"grace"})
WriteResult({ "nRemoved" : 1 })
> db.system.users.find();
> 

修改使用者密碼,可以利用db.changeUserPassword進行密碼重置!!!!!
> use grace;
switched to db grace
> db.changeUserPassword("grace","grace@1986");
> 

以--auth啟動mongodb開啟認證(或者在配置檔案中新增"auth=true")
[root@MongoDB-server ~]# vim /usr/local/mongodb/mongodb.conf
#代表埠號,如果不指定則預設為27017
port=27017
#繫結ip
bind_ip=0.0.0.0
#MongoDB資料檔案目錄
dbpath=/usr/local/mongodb/data
#MongoDB日誌檔案目錄
logpath=/usr/local/mongodb/log/mongo.log
#日誌檔案自動累加
logappend=true
#開啟MongoDB認證
auth=true            
 
[root@MongoDB-server ~]# cat /etc/init.d/mongodb
......
    $CMD -f $INITFILE --auth &
......
 
重啟mongodb
[root@MongoDB-server ~]# ps -ef|grep mongodb
root     17789     1  0 22:55 pts/0    00:00:06 /usr/local/mongodb/bin/mongod -f /usr/local/mongodb/mongodb.conf
root     25161 16606  0 23:24 pts/0    00:00:00 grep mongodb
[root@MongoDB-server ~]# kill -9 17789
[root@MongoDB-server ~]# ps -ef|grep mongodb               
root     25190 16606  0 23:24 pts/0    00:00:00 grep mongodb
 
[root@MongoDB-server ~]# /etc/init.d/mongodb start
MongoDB is running background...
[root@MongoDB-server ~]# ps -ef|grep mongodb     
root      1687     1 12 23:58 pts/0    00:00:00 /usr/local/mongodb/bin/mongod -f /usr/local/mongodb/mongodb.conf --auth
root      1713 16606  0 23:58 pts/0    00:00:00 grep mongodb
[root@MongoDB-server ~]# lsof -i:27017           
COMMAND   PID USER   FD   TYPE  DEVICE SIZE/OFF NODE NAME
mongod  25342 root    6u  IPv4 4330699      0t0  TCP *:27017 (LISTEN)

驗證安全認證:
[root@MongoDB-server ~]# mongo 127.0.0.1:27017
MongoDB shell version: 3.2.17-34-g4c1bae566c
connecting to: 127.0.0.1:27017/test
> use admin;
switched to db admin
> show dbs
2018-09-21T10:11:46.582+0800 E QUERY    [thread1] Error: listDatabases failed:{
        "ok" : 0,
        "errmsg" : "not authorized on admin to execute command { listDatabases: 1.0 }",
        "code" : 13
} :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
Mongo.prototype.getDBs@src/mongo/shell/mongo.js:62:1
shellHelper.show@src/mongo/shell/utils.js:781:19
shellHelper@src/mongo/shell/utils.js:671:15
@(shellhelp2):1:1

> 

如上由於沒有認證,所以檢視不到。需要認證後再次檢視才可以。需要注意:認證時括號裡面的使用者名稱和密碼用雙引號,否則可能會認證失敗!!
> db.auth("admin","1234!@#$qwer");
1
> show dbs
admin  0.000GB
local  0.000GB
> 

普通使用者認證也是一樣
> use grace;
switched to db grace
> db.stats();
{
        "ok" : 0,
        "errmsg" : "not authorized on admin to execute command { serverStatus: 1.0 }",
        "code" : 13
}
> db.auth("grace","grace@1986");
1
> db.stats();
{
        "db" : "grace",
        "collections" : 0,
        "objects" : 0,
        "avgObjSize" : 0,
        "dataSize" : 0,
        "storageSize" : 0,
        "numExtents" : 0,
        "indexes" : 0,
        "indexSize" : 0,
        "fileSize" : 0,
        "ok" : 1
}
> 

以上就表明了該mongodb啟用了認證功能,並且認證成功了!

相關文章