MongoDB事件出現後,公司要給MongoDB加Auth,因而我就調研了一番。
mongodb
如今MongoDB在生產中通常使用Replica Set的方式部署,若是一臺宕機,另一臺Secondary會變成Master繼續服務,提升可用性。docker
使用docker搭個集羣測試,首先建個network bridgeshell
1 |
docker network new mongo-network |
而後就是運行MongoDB的容器,集羣名爲test-repbash
1 |
docker run --rm -it --name mongo1 --net=mongo-network mongo --replSet test-rep |
而後再運行一個鏈接到上述三個MongoDB的容器服務器
1 |
docker run --rm -it --name mongo-client --net=mongo-network mongo /bin/bash |
而後在容器中執行運維
1 |
mongo --host mongo1 |
發現鏈接上了,說明MongoDB的配置沒有問題,而後是配置Replica Set。Replica Set要求配置的members中不能有localhost,而我配置爲mongo2,mongo3這種一直都報相似的錯誤,我索性找出了幾個容器的IP,配置上去post
1 |
docker network inspect mongo-network |
能夠看到幾個容器的IP測試
而後就可使用IP地址配置了spa
1 |
config = {_id:"test-rep", version:1, members:[{_id:0, host:"172.19.0.5:27017", priority:5}, {_id:1, host:"172.19.0.3:27017", priority:2}, {_id:2, host:"172.19.0.4:27017", priority:3}]} |
再去看mongod的log,發現集羣同步成功code
把mongo1停掉,mongo2會成爲primary
而後按照MongoDB的文檔增長用戶
1 |
db.createUser( |
重啓mongod的進程,增長–auth參數,表示啓用權限校驗
1 |
docker run --rm -it --name mongo1 --net=mongo-network mongo --replSet test-rep --auth |
發現一直報Error in heartbeat request to 172.19.0.5:27017; Unauthorized: not authorized on admin to execute command
的錯誤,查了好久,發現Replica Set要使用keyFile的校驗方式,讓集羣的member之間同步,也就是說,經過keyFile得到__system用戶在local上的權限。local存放着Replica Set的配置和同步信息。
MongoDB官方推薦的keyFile的生產方式
1 |
openssl rand -base64 756 > <path-to-keyfile> |
先結束掉mongod的進程,由於要放入keyFile,因而我啓動docker的時候,默認不啓動mongod
1 |
docker run --rm -it --name mongo1 --net=mongo-network mongo /bin/bash |
容器裏沒有裝openssl,我偷懶使用瞭如下命令
1 |
echo 'I8au1RERvEQkIiIB7vhTMhfceA8oH/L0mT6xxeVgaJg/mYnnZe89dGWjMrQSXI7A' > /data/key_file |
而後啓動mongod進程
1 |
mongod --replSet test-rep --auth --keyFile=/data/key_file |
在mongo2,mongo3上按照上述命令,依次啓動。發現漂亮的同步成功的標誌
收工
生產上的MongoDB,切換到須要Auth,是否能夠在不停機的情況下進行呢?
某同窗猜測,mongod不採用Auth的時候,客戶端使用密碼,可不能夠呢?Python鏈接MongoDB的代碼很簡單
pymongo.MongoClient('mongodb://user:user1@mongo1:27017,mongo2:27017,mongo3:27017/mydb?authMechanism=SCRAM-SHA-1')
訪問mydb的時候,直接就拋Authentication failed
錯誤了。若是我先添加了user呢?在mongo shell中執行
1 |
db.createUser( |
剛剛的admin,只是訪問admin庫的用戶名和密碼,能夠管理用戶信息,user用戶能夠用來讀寫相應的庫。此時,mongod依然沒有使用--auth
啓動,所以是沒有權限檢查的,再次鏈接,一切正常。
所以配置步驟以下
1 |
use admin |
1 |
pymongo.MongoClient('mongodb://user:user1@mongo1:27017,mongo2:27017,mongo3:27017/mydb?authMechanism=SCRAM-SHA-1') |
1 |
openssl rand -base64 756 > /data/key_file |
1 |
security: |
這樣只有重啓的那一剎那不可用