mongo認證配置又出問題了?來看看這個

前言

某個晴朗的工作日,我正在自己的工位上勤勤懇懇的工(hua)作(shui),此時總監突然微信我:“小劉,這會兒工作忙嗎?”,我當下後背就是一涼,慌忙回覆到:“總監,我這會兒閒的很,哦不,是忙的很”。沉默了2秒之後,總監繼續說到:“…這樣啊,我這兒有個任務交給你,公司有兩臺服務器的mongo沒有做安全配置,你去給它們加上”

雖然沒有給mongo做過安全配置,但是身爲Google小能手的我,很快就找到了相應的教程,熟練的開始抄起了作業。理想是美好的,現實卻很殘酷,配置過程中踩坑不斷,本篇中會將這些坑都一一記錄下來,防止以後踩坑歷史重演:)

正常配置過程

建議可以先看看官方文檔:Mongo Enable Access Control
網上也有很多中文翻譯,比如:MongoDB 設置用戶名密碼登錄

具體的配置我在這裏簡單的說一下:
首先,進入mongo終端(此時還沒有認證);
之後,選擇使用mongo自帶的admin表,該表是用來管理mongo賬戶的;
爲mongo數據庫添加賬戶

>> use admin
>> db.createUser(
  {
    user: "Admin",
    pwd: "admin_password",
    roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]
  }
)

在使用配置文件啓動的情況下,需要在配置文件中加上這麼一句:

security:
    authorization: enabled

重啓mongo後,認證功能便會打開,我們有兩種方式繼續使用mongo客戶端

  1. 像之前進入mongo,在客戶端內進行認證(否則你無法正常使用mongo的語句和接口),我們
>> use admin
>> db.auth("Admin", "admin_password")  # 之前配置的賬戶密碼
1  # 返回1表示認證成功,我們就可以繼續像平時那樣繼續操作了
  1. 在鏈接mongo的同時進行認證操作(推薦,這個比較省事兒)
mongo --port 27017  --authenticationDatabase "admin" -u "Admin" -p "admin_password"

其中稍微需要注意一下的就這個authenticationDatabase參數

Authentication Database
When adding a user, you create the user in a specific database. This database is the authentication database for the user.
A user can have privileges across different databases; that is, a user’s privileges are not limited to their authentication database. By assigning to the user roles in other databases, a user created in one database can have permissions to act on other databases. For more information on roles, see Role-Based Access Control.
The user’s name and authentication database serve as a unique identifier for that user. That is, if two users have the same name but are created in different databases, they are two separate users. If you intend to have a single user with permissions on multiple databases, create a single user with roles in the applicable databases instead of creating the user multiple times in different databases.

簡單來說,authenticationDatabase 就是用來做認證的那個數據庫,這裏就是admin這個庫,我們也可以爲其他每個數據庫單獨建立賬戶,後面的-u-p分別是用戶名和密碼。

這就是爲mongo添加安全認證的步驟,整個過程看起來很簡單,而然其中有些坑不容易被發現,一不小心就會出問題(血淚警告)。

坑1: 起mongo終端引起的權限問題

如果此前你的mongo中已經配置了service啓動(即通過systemctl start mongod啓動mongo服務),並且service中user配置的不是root(通常會另設置一個專門的用戶,比如mongod

那麼,你在根據mongo官方文檔進行賬戶配置的時候就會發生權限問題(包括很多參考官方文檔的博客中沒有詳細提及)

官方文檔會提示你通過mongod啓動一個mongo服務,然後在啓動一個mongo的終端進行上述的配置過程。

然而當你按照官方文檔的步驟做完配置之後,在以systemctl restart mongo 啓動時,就會瘋狂報錯,突然間的報錯可能會讓你猝不及防,這個時候就非常非常非常的推薦看日誌

# 查看mongo啓動日誌, 通常是這個路徑,如果不知道路徑在哪兒,可以查看配置文件
tail -f /var/log/mongodb/mongod.log

報錯信息沒來得及截圖就不放了 = =,基本可以確定是權限問題。原因是你在root用戶下啓動mongo服務後,部分日誌文件的權限就被改爲root,當你後面在想用systemctl啓動時,就會瘋狂權限錯誤。

我們可以看看service文件是如果配置的,使用systemctl status mongo查看一下當前服務的運行狀態和service配置文件的路徑,像這樣
在這裏插入圖片描述
在這裏面我們可以查看mongo的service配置路徑,如果啓動不成功,也可以在這個命令下看到基本的報錯信息。

查看一下mongod.service

[Unit]
Description=High-performance, schema-free document-oriented database
After=network.target
Documentation=https://docs.mongodb.org/manual

[Service]
User=mongod
Group=mongod
Environment="OPTIONS=-f /etc/mongod.conf"
ExecStart=/usr/bin/mongod $OPTIONS
ExecStartPre=/usr/bin/mkdir -p /var/run/mongodb
ExecStartPre=/usr/bin/chown mongod:mongod /var/run/mongodb
ExecStartPre=/usr/bin/chmod 0755 /var/run/mongodb
PermissionsStartOnly=true
PIDFile=/var/run/mongodb/mongod.pid
Type=forking
# file size
LimitFSIZE=infinity
# cpu time
LimitCPU=infinity
# virtual memory size
LimitAS=infinity
# open files
LimitNOFILE=64000
# processes/threads
LimitNPROC=64000
# locked memory
LimitMEMLOCK=infinity
# total threads (user+kernel)
TasksMax=infinity
TasksAccounting=false
# Recommended limits for for mongod as specified in
# http://docs.mongodb.org/manual/reference/ulimit/#recommended-settings

其中,usergroup是用來表示運行服務的用戶,如果你以root權限啓動了mongo,再使用service啓動時,會出現無法運行數據無法寫入的情況。需要手動更改出現Permission denied的文件,下面列出幾個,可以檢查一下,這些在mongo配置文件中也能找到(如果沒有就創建並修改用戶權限)

/var/run/mongodb/mongod.pid  # 進程文件
/var/lib/mongodb  # 數據庫存儲路徑
/var/log/mongodb  # 日誌路徑
# 修改權限
sudo chown -R mongodb:mongodb 文件路徑

至此,一系列全七八糟的權限問題就解決了。

坑2: 集羣中配置認證引起的問題

上面的問題說完了,接下來可以開開心心的完成任務了,通過認證打開mongo終端一看,刷刷刷彈出來一堆錯誤,又來??!!
錯誤信息大致如下:

No primary detected for set xxx
No primary detected for set xxx
No primary detected for set xxx
No primary detected for set xxx
No primary detected for set xxx
No primary detected for set xxx

這裏再次友情推薦,查mongo日誌

# 查看mongo日誌
tail -f /var/log/mongodb/mongod.log

發現日誌中報錯信息如下

MongoDB not authorized on admin to execute command { replSetGetStatus: 1.0 }

原來又是權限 = =,這次是mongo集羣的權限配置有問題,無法執行集羣相關命令,這裏回顧一下創建mongo賬戶時的語句

db.createUser(
  {
    user: "Admin",
    pwd: "admin_password",
    # 這裏roles已經是超級用戶,但是對於集羣來說,權限的級別還是不夠
    roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]  
  }
)

確實是有個roles權限的設置,最終想到是我們的Admin賬號沒有集羣管理的權限,那麼對症下藥,給Admin添加集羣權限。
進入mongo終端(不想看到瘋狂報錯,可以先關了認證),執行以下命令

>> db.grantRolesToUser("Admin", ["clusterAdmin"])

由於複製集之間的互聯也是需要驗證的,所以還要配置keyfile來滿足這個需求,如果配置認了認證 ,投票節點需要通過證書的形式與複製集中的其他節點進行認證。MongoDB的身份認證過程是加密的。

keyfile的配置可以參考這篇博客
我們這裏就直接貼出配置完的結果把,還記得之前mongo中配置的security嗎?我們修改一下

security:
  keyFile: /var/lib/mongo/mongo_key_file  # 這個就是生成keyfile!
  authorization: enabled

注意,每個節點都需要進行配置哦~

mongo的權限分的很多很細,這裏不多做解釋了,通過這篇博客可以進行更進一步的瞭解~

終極權限-root

權限的配置十分細碎,Admin賬戶已經有了
clusterAdmin
userAdminAnyDatabase
兩大角色
看似已經覆蓋到常用的權限,然而你還是可能會遇到not authorized on admin to execute command xxx的情況,比我我後端系統權限都配置好了,然後系統連接數據庫的時候還是報了
not authorized on admin to execute command currentOp
的錯誤,我也是醉了。

如果完全弄清楚角色配置比較麻煩,最簡單粗暴的辦法,可以直接爲賬戶配置最高級的root權限,像這樣

>> db.grantRolesToUser("Admin", ["root"])

總結

至此,mongo的賬戶配置算是完成了,總監點了點頭,露出了滿意的微笑~
如果這篇文章還沒能解決你的問題,歡迎留言一起討論~筆芯~💗

參考文檔

Mongo Enable Access Control
mongodb 3.4.3 Permission denied wiredtiger_kv_engine.cpp 267 error
mongodb 3.4複製集配置
MongoDB開啓訪問控制後currentOp出錯

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章