1. 程式人生 > 實用技巧 >MongoDB 4.2 使用者管理

MongoDB 4.2 使用者管理

背景

最近在掃盲MongoDB 4.2 的相關知識點,順便記錄下日常的一些操作。包括:使用者管理、索引管理、引擎管理、副本集管理、分片管理等。本文對MongoDB的使用者管理進行說明。

本文MongoDB的配置檔案模板:

systemLog:
   verbosity: 0
   quiet: false
   traceAllExceptions: false
   syslogFacility: user
   path: /data/mongodb/logs/mongodb.log
   logAppend: true
   logRotate: rename
   destination: file
   timeStampFormat: iso8601
-local component: accessControl: verbosity: 0 command: verbosity: 0 control: verbosity: 0 ftdc: verbosity: 0 geo: verbosity: 0 index: verbosity: 0 network: verbosity: 0 query: verbosity:
0 replication: verbosity: 0 election: verbosity: 0 heartbeats: verbosity: 0 initialSync: verbosity: 0 rollback: verbosity: 0 sharding: verbosity: 0 storage: verbosity: 0 journal: verbosity:
0 recovery: verbosity: 0 transaction: verbosity: 0 write: verbosity: 0 processManagement: fork: true pidFilePath: /data/mongodb/data/mongodb.pid # timeZoneInfo: <string> net: port: 27017 bindIp: 0.0.0.0 maxIncomingConnections: 65536 wireObjectCheck: true ipv6: false unixDomainSocket: enabled: true pathPrefix: /tmp filePermissions: 0700 tls: mode: disabled compression: compressors: snappy,zstd,zlib serviceExecutor: synchronous #security: # keyFile: <string> # clusterAuthMode: keyFile # authorization: enabled # transitionToAuth: false # javascriptEnabled: true # redactClientLogData: <boolean> # clusterIpSourceWhitelist: # - 127.0.0.1 # - ::1 storage: dbPath: /data/mongodb/data/ indexBuildRetry: true journal: enabled: true commitIntervalMs: 500 directoryPerDB: true syncPeriodSecs: 60 engine: wiredTiger wiredTiger: engineConfig: # cacheSizeGB: <number> journalCompressor: snappy directoryForIndexes: false operationProfiling: # 指定應分析哪些操作,預設off:分析器已關閉,並且不收集任何資料;slowOp:收集比slowms的時間長的資料;all:收集所有操作的資料 mode: slowOp slowOpThresholdMs: 100 slowOpSampleRate: 1 replication: # 複製日誌(oplog)的最大大小(以M為單位),僅適用於mongod。操作日誌通常是可用磁碟空間的5%,更改正在執行的副本整合員的操作日誌大小,請使用replSetResizeOplog管理命令。 oplogSizeMB: 100 # replSetName: <string> #sharding: # 分片群集中扮演的角色,可選值configsvr:配置伺服器,埠27019開始;shardsvr:分片,埠27018開始;需要將例項部署為副本整合員,使用replSetName設定並指定副本集的名稱,僅適用於mongod。 # clusterRole: <string> # configDB: <string>
View Code

使用者管理

在一個新的例項上,建立的第一個使用者應該是具有管理其他使用者許可權的使用者管理員。在MongoDB部署上啟用訪問控制會強制執行身份驗證,要求使用者認證自己,使用者只能執行根據其角色確定的操作。具體的使用者管理可以看官方文件或則MongoDB使用者建立,本文做下補充。

1,建立使用者:db.createUser(user,writeConcern)

user:包含有關要建立的使用者的身份驗證和訪問資訊。
writeConcern:可選,建立操作的寫關注級別。 writeConcern文件的欄位與getLastError命令的欄位相同。

MongoDB4.2開始,可以使用passwordPrompt()方法來提示輸入密碼,不需要在命令中指定密碼。但仍然可以像使用早期版本的MongoDB一樣直接指定密碼。格式:

{
  user: "<name>",   -- 使用者名稱
  pwd: passwordPrompt(),    -- 提示輸入密碼,也可以直接寫密碼
  customData: { <any information> },  -- 可選,可用於儲存與此特定使用者關聯的任何資料。 例如,這可以是使用者的全名或員工ID。
  roles: [
    { role: "<role>", db: "<database>" } | "<role>",
    ...
  ],     -- 授予使用者的角色。 可以指定一個空陣列[]來建立沒有角色的使用者
  authenticationRestrictions: [
     {
       clientSource: ["<IP>" | "<CIDR range>", ...],
       serverAddress: ["<IP>" | "<CIDR range>", ...]
     },
     ...
  ],  -- 可選,伺服器對建立的使用者強制執行的身份驗證限制,指定允許使用者連線到伺服器或伺服器可以接受使用者的IP地址和CIDR(無類別域間路由)範圍的列表
  mechanisms: [ "<SCRAM-SHA-1|SCRAM-SHA-256>", ... ],  --可選,指定特定的SCRAM機制或用於建立SCRAM使用者憑據的機制
  passwordDigestor: "<server|client>"  --可選,指伺服器還是客戶端提取密碼。
}

其中在roles欄位中,可以指定內建角色使用者定義的角色:

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

具體許可權

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

建立使用者:

db.createUser(
{
user:'dba',
pwd:passwordPrompt(),
roles:[{role:'root',db:'admin'}],
customData:{name:'運維賬號'},
authenticationRestrictions: [ {
        clientSource: ["192.168.163.134"],
        serverAddress: ["192.168.163.134"]
     } ]
}
)

說明建立一個使用者名稱為dba的管理角色(root)的賬號,且備註為運維賬號,並只能在IP為192.168.163.134的主機上訪問。

use xxx
db.createUser(
{
user:'zjy',
pwd:passwordPrompt(),
roles:[{role:'readAnyDatabase',db:'admin'},
"readWrite"
],
customData:{name:'運維賬號'},
authenticationRestrictions: [ {
        clientSource: ["192.168.163.134"],
        serverAddress: ["192.168.163.134"]
     } ]
},
{ w: "majority" , wtimeout: 5000 }
)

說明建立一個使用者名稱為zjy的賬號,對當前庫(xxx)有readWrite許可權,對指定庫(admin)有readAnyDatabase許可權;且備註為運維賬號,並只能在IP為192.168.163.134的主機上訪問。

關於賬號許可權的一些說明可以看MongoDB使用者建立

2,修改使用者密碼:db.changeUserPassword(username,password)

db.changeUserPassword('user','pwd')

3,檢視指定使用者:db.getUser(username, args)

格式:

db.getUser( "<username>", {
   showCredentials: <Boolean>,
   showPrivileges: <Boolean>,
   showAuthenticationRestrictions: <Boolean>,
   filter: <document>
} )

其中"<username>"表示資料庫使用者,其他的引數都是可選項:

  • showCredentials:檢視使用者證書
  • showPrivileges:檢視使用者許可權
  • showAuthenticationRestrictions:檢視使用者限制條件
> db.getUser('dba')
{
    "_id" : "admin.dba",
    "userId" : UUID("6a1c2217-0c5b-4aa6-a29b-de50ac1d84ae"),
    "user" : "dba",
    "db" : "admin",
    "customData" : {
        "name" : "運維賬號abc"
    },
    "roles" : [
        {
            "role" : "root",
            "db" : "admin"
        }
    ],
    "mechanisms" : [
        "SCRAM-SHA-1",
        "SCRAM-SHA-256"
    ]
}

> db.getUser('dba',{showPrivileges:1})
...
...

4,檢視當前庫的所有使用者:db.getUsers(<options>)

> db.getUsers() == show users
[
    {
        "_id" : "xxx.zjy",
        "userId" : UUID("2ad9f4c9-e156-4e71-b8f9-3915beb322e8"),
        "user" : "zjy",
        "db" : "xxx",
        "customData" : {
            "name" : "運維賬號"
        },
        "roles" : [
            {
                "role" : "readAnyDatabase",
                "db" : "admin"
            },
            {
                "role" : "readWrite",
                "db" : "xxx"
            }
        ],
        "mechanisms" : [
            "SCRAM-SHA-1",
            "SCRAM-SHA-256"
        ]
    }
]

5,移除、刪除指定使用者:db.removeUser(username)db.dropUser(username, writeConcern)

> db.removeUser('zjy')
WARNING: db.removeUser has been deprecated, please use db.dropUser instead  --不推薦使用
true

> db.dropUser('accountAdmin01',{w: "majority", wtimeout: 5000})
true

如果在副本集上執行,則預設情況下使用多數寫關注來執行db.dropUser()。

6,刪除當前庫所有使用者:db.dropAllUsers(writeConcern)

> db.dropAllUsers({w: "majority", wtimeout: 5000})
NumberLong(4)

7,更新指定使用者:db.updateUser(username, update, writeConcern)

格式:

db.updateUser(
   "<username>",
   {
     customData : { <any information> },
     roles : [
       { role: "<role>", db: "<database>" } | "<role>",
       ...
     ],
     pwd: passwordPrompt(),      // Or  "<cleartext password>"
     authenticationRestrictions: [
        {
          clientSource: ["<IP>" | "<CIDR range>", ...],
          serverAddress: ["<IP>", | "<CIDR range>", ...]
        },
        ...
     ],
     mechanisms: [ "<SCRAM-SHA-1|SCRAM-SHA-256>", ... ],
     passwordDigestor: "<server|client>"
   },
   writeConcern: { <write concern> }
)

上面各個引數的意思和createUser一致。

> db.updateUser(
... 'user123',
... {
... pwd:passwordPrompt(),
... roles:['read'],
... customData:{name:'運維賬號'},
... authenticationRestrictions: [ {
...         clientSource: ["192.168.163.134"],
...         serverAddress: ["192.168.163.134"]
...      } ]
... },
... { w: "majority" , wtimeout: 5000 }
... )

8,授權role給指定使用者:db.grantRolesToUser(username, roles, writeConcern)

格式:

db.grantRolesToUser( "<username>", [ <roles> ], { <writeConcern> } )
> show users;
{
    "_id" : "products.user123",
    "userId" : UUID("b71e3c9d-1e57-4178-b6f8-48445ee2ebfc"),
    "user" : "user123",
    "db" : "products",
    "roles" : [
        {
            "role" : "read",
            "db" : "products"
        }
    ],
    "customData" : {
        "name" : "運維賬號"
    },
    "mechanisms" : [
        "SCRAM-SHA-1",
        "SCRAM-SHA-256"
    ]
}
> db.grantRolesToUser('user123',['readWrite',{role:'read',db:'test'}])
> show users; { "_id" : "products.user123", "userId" : UUID("b71e3c9d-1e57-4178-b6f8-48445ee2ebfc"), "user" : "user123", "db" : "products", "roles" : [ { "role" : "readWrite", "db" : "products" }, { "role" : "read", "db" : "test" }, { "role" : "read", "db" : "products" } ], "customData" : { "name" : "運維賬號" }, "mechanisms" : [ "SCRAM-SHA-1", "SCRAM-SHA-256" ] }

說明:在已有使用者(user123)的許可權下,新增當前庫(products)的readWrite role和test庫的read role。

9,移除指定使用者的role:db.revokeRolesFromUser()

格式:

db.revokeRolesFromUser( "<username>", [ <roles> ], { <writeConcern> } )
> show users;
{
    "_id" : "products.user123",
    "userId" : UUID("b71e3c9d-1e57-4178-b6f8-48445ee2ebfc"),
    "user" : "user123",
    "db" : "products",
    "roles" : [
        {
            "role" : "readWrite",
            "db" : "products"
        },
        {
            "role" : "read",
            "db" : "test"
        },
        {
            "role" : "read",
            "db" : "products"
        }
    ],
    "customData" : {
        "name" : "運維賬號"
    },
    "mechanisms" : [
        "SCRAM-SHA-1",
        "SCRAM-SHA-256"
    ]
}

> db.revokeRolesFrom
db.revokeRolesFromRole(  db.revokeRolesFromUser(

> db.revokeRolesFromUser('user123',[{role:'read',db:'test'},'readWrite'])

> show users; { "_id" : "products.user123", "userId" : UUID("b71e3c9d-1e57-4178-b6f8-48445ee2ebfc"), "user" : "user123", "db" : "products", "roles" : [ { "role" : "read", "db" : "products" } ], "customData" : { "name" : "運維賬號" }, "mechanisms" : [ "SCRAM-SHA-1", "SCRAM-SHA-256" ] }

說明:移除已有使用者(user123)在當前庫(products)的readWrite role和test庫的read role許可權。

10,使用者認證:db.auth(username,password)

> db.auth('dba','DBA')
1

以上說明的role都是內建角色,使用者自定義角色可以看官方文件說明。

角色管理

1,建立角色:db.createRole(role, writeConcern)

格式:

{
  role: "<name>",      --新角色的名稱
  privileges: [
     { resource: { <resource> }, actions: [ "<action>", ... ] },
     ...
  ],      --許可權,由resource和actions組成。空陣列表示無許可權
  roles: [
     { role: "<role>", db: "<database>" } | "<role>",
      ...
  ],     --角色的陣列,此角色從中繼承特權,空陣列表示沒有繼承角色
  authenticationRestrictions: [
    {
      clientSource: ["<IP>" | "<CIDR range>", ...],
      serverAddress: ["<IP>" | "<CIDR range>", ...]
    },
    ...
  ]    --驗證限制
}

resource表示資源,包括database或collection也可以是database和collection的組合:

{ db: <database>, collection: <collection> }

actions表示許可權操作,"actions" 定義了"user"能夠對 "resource document"執行的操作:

find、insert、remove、update

privilege表示許可權,"privilege" 是一組"resource" 和 "actions" 的組,關於privileges的詳細資訊見官方說明,裡面有各個命令的許可權說明

>db.createRole(
   {role:"zhoujy", //角色名稱
       privileges: [ // 許可權集
        {resource: //資源 
         {db:"xxx",     // 建立的zhoujy角色具有對xxx庫的操作許可權,具體許可權見actions
          collection:""   // xxx庫下對應的集合名 如果為"" 表示所有集合
         },
          actions: [ "find", "insert", "remove","update" ]   //角色可進行的操作,注意這裡是一個數組
        }
                   ],
         roles: [{ role: "read", db: "admin" }] // 是否繼承其他的角色,如果指定了其他角色那麼新建立的角色自動繼承對應其他角色的所有許可權,該引數必須顯示指定
   },
  { w: "majority" , wtimeout: 5000 }
)

說明:建立了一個zhoujy的role,可以像內建角色一樣來使用。

2,檢視指定角色資訊:db.getRole(rolename, args)

引數:

showBuiltinRoles:可選,在輸出中返回內建角色資訊

showPrivileges:可選,在輸出中返回許可權資訊

> db.getRole('zhoujy')
{
    "role" : "zhoujy",
    "db" : "admin",
    "isBuiltin" : false,
    "roles" : [ ],
    "inheritedRoles" : [ ]
}

> db.getRole('zhoujy',{showPrivileges: true})
{
    "role" : "zhoujy",
    "db" : "admin",
    "isBuiltin" : false,
    "roles" : [ ],
    "inheritedRoles" : [ ],
    "privileges" : [
        {
            "resource" : {
                "db" : "xxx",
                "collection" : ""
            },
            "actions" : [
                "find",
                "insert",
                "remove",
                "update"
            ]
        }
    ],
    "inheritedPrivileges" : [
        {
            "resource" : {
                "db" : "xxx",
                "collection" : ""
            },
            "actions" : [
                "find",
                "insert",
                "remove",
                "update"
            ]
        }
    ]
}

3,檢視當前資料庫中所有的角色資訊:db.getRoles()

不帶引數執行,返回資料庫使用者定義角色的繼承資訊,引數:

rolesInfo:1,返回所有使用者定義的角色資訊

showPrivileges:true,返回所有使用者的許可權資訊

showBuiltinRoles:true,返回內建角色資訊

>db.getRoles(
    {
      rolesInfo: 1,
      showPrivileges:true,
      showBuiltinRoles: true
    }
)

4,角色授權:db.grantPrivilegesToRole(rolename, privileges, writeConcern)

> db.grantPrivilegesToRole(
  "zhoujy",
  [
    {
      resource: { db: "products", collection: "" },
      actions: [ "insert","find"  ]
    }
  ],
  { w: "majority" }
)

說明:在已有的role下面,再追加許可權。

5,角色許可權回收:db.revokePrivilegesFromRole(rolename, privileges, writeConcern)

> db.revokePrivilegesFromRole(
  "zhoujy",
  [
    {
      resource: { db: "products", collection: "" },
      actions: [ "insert" ]
    }
  ],
  { w: "majority" }
)

說明:在已有的role下面,刪除許可權。

6,角色繼承:db.grantRolesToRole(rolename,roles,writeConcern)

> db.grantRolesToRole(  
          "zhoujy",
           [ "zhoujy1","zhoujy2" ],
           { w: "majority" , wtimeout: 5000 }
                    )

說明:將 zhoujy1、zhoujy2 兩個角色(假設之前已經建立好)的許可權授予zhoujy角色

7,繼承角色回收:db.revokeRolesFromRole(rolename,roles,writeConcern)

db.revokeRolesFromRole(
          "zhoujy" ,
          [ "zhoujy2" ]
                      ) 

說明:撤銷zhoujy角色從zhoujy2角色所繼承的所有許可權

8,更新角色:db.updateRole(rolename,update,writeConcern)

格式:

    "<rolename>",  --角色名
    {
      privileges:
          [
            { resource: { <resource> }, actions: [ "<action>", ... ] },
            ...
          ],  --許可權
      roles:
          [
            { role: "<role>", db: "<database>" } | "<role>",
            ...
          ],   --角色
      authenticationRestrictions:
          [
            {
              clientSource: ["<IP>" | "<CIDR range>", ...],
              serverAddress: ["<IP>", | "<CIDR range>", ...]
            },
            ...
          ]
    },    -- 限制
    { <writeConcern> } --寫關注
)
> db.updateRole(
   "zhoujy",
   {
      privileges: 
      [
        {
        resource:{db:"xxx", collection:""},
        actions: [ "find", "insert", "remove","update" ]
        }
       ],
      roles: []
   },
  { w: "majority" , wtimeout: 5000 }
)

9,刪除角色:db.dropRole(rolename,writeConcern)

> db.dropRole('myClusterwideAdmin', { w: "majority" })
true

10,刪除當前庫所有使用者自定義的角色:db.dropAllRoles(writeConcern)

db.dropAllRoles( { w: "majority" } )

到此,關於使用者管理的已經介紹完,更多的詳細資訊可以見官網說明,或可以查閱MongoDB 許可權控制系統簡介需要注意的是,需要開啟伺服器引數中的security.authorization:true,才會使用使用者驗證(db.auth())。

總結

本文大致介紹了MongoDB使用者管理的使用說明,後續根據需要會持續更新本文。關於使用者管理的更多說明可以看官方文件

參考文章:

MongoDB 3.0 使用者建立

MongoDB 許可權控制系統簡介