MongoDB - 権限

提供: MochiuWiki : SUSE, EC, PCB

概要

MongoDBの権限管理は、ロールベースアクセス制御 (RBAC: Role-Based Access Control) として実装されている。
RBACは、ユーザに直接権限を付与するのではなく、ロールを通じて権限を付与する仕組みである。

MongoDBのセキュリティは、認証 (Authentication) と 認可 (Authorization) の2つの概念に分けられる。
認証はユーザの身元を確認するプロセスであり、認可はユーザが実行できる操作を制御するプロセスである。

MySQLはユーザに直接権限を付与するのに対して、MongoDBはロールを通じて権限を付与する。
MongoDBでは、各ロールに複数の権限 (アクション) が含まれており、ユーザには1つまたは複数のロールを付与することで、必要な権限を与える。

MongoDBはデフォルトで認証が無効になっているため、本番環境では必ず認証を有効化する必要がある。
認証を有効化しないと、誰でも制限なくデータベースにアクセスできてしまう。


認証の有効化

MongoDBはデフォルトで認証が無効になっており、ネットワークからアクセス可能な状態でMongoDBを起動すると、誰でもデータベースにアクセスできてしまう。
本番環境では、必ず認証を有効化する必要がある。

コマンドラインオプションでの有効化

MongoDBサーバを起動する時に、--auth オプションを指定することで認証を有効化できる。

# 認証を有効にしてMongoDBを起動
mongod --auth --dbpath /var/lib/mongodb


設定ファイルでの有効化

設定ファイル (mongod.conf) で認証を有効化するには、以下に示すように設定する。

 security:
   authorization: enabled


設定ファイルを使用してMongoDBを起動する場合は、以下に示すコマンドを実行する。

# 設定ファイルを指定してMongoDBを起動
mongod --config /etc/mongod.conf


localhost例外

MongoDBには、localhost例外 (Localhost Exception) という仕組みが用意されている。
これは、認証を有効化した状態でユーザが1人も存在しない場合、localhostからのみ最初の管理者ユーザを作成できる仕組みである。

この例外により、認証を有効化した後でも、最初の管理者ユーザを作成することができる。
ただし、最初のユーザを作成した後は、この例外は無効になる。

管理者ユーザの作成

認証を有効化する前に、まず管理者ユーザを作成する必要がある。
以下の手順で、adminデータベースに管理者ユーザを作成する。

 // MongoDBシェルに接続
 mongosh
 
 // adminデータベースに切り替え
 use admin
 
 // 管理者ユーザを作成
 db.createUser({
   user: "admin",
   pwd: "securePassword123",
   roles: [
     { role: "userAdminAnyDatabase", db: "admin" },
     { role: "readWriteAnyDatabase", db: "admin" },
     { role: "dbAdminAnyDatabase", db: "admin" }
   ]
 })


管理者ユーザを作成した後、MongoDBサーバを再起動して認証を有効化する。
認証を有効化した後は、以下のようにユーザ名とパスワードを指定して接続する。

# 認証情報を指定してMongoDBに接続
mongosh -u admin -p securePassword123 --authenticationDatabase admin
</syntaxhighlight>



組み込みロール

MongoDBには、様々な用途に応じた組み込みロールが用意されている。

これらのロールは、データベースユーザロール、データベース管理ロール、クラスタ管理ロール、全データベースロール、スーパーユーザロールの5つのカテゴリに分類される。

データベースユーザロール

データベースユーザロールは、特定のデータベースに対する読み取りおよび書き込み権限を提供する。

データベースユーザロール
ロール 説明
read 非システムコレクションの読み取り専用アクセス権限を提供する。

find、count、aggregate等の読み取り操作が可能。
readWrite 非システムコレクションの読み取りおよび書き込み権限を提供する。

readロールの権限に加えて、insert、update、remove、createCollection等の書き込み操作が可能。


データベース管理ロール

データベース管理ロールは、データベースの管理タスクを実行するための権限を提供する。

データベース管理ロール
ロール 説明
dbAdmin スキーマ関連タスク、インデックス作成、統計情報の収集が可能。
ただし、ユーザおよびロールの管理権限は含まれない。

createIndex、dropCollection、collStats等の管理操作が可能。
dbOwner 特定のデータベースに対する完全な管理権限を持つ。
readWrite、dbAdmin、userAdminロールの全権限を組み合わせたロール。

データベースの所有者として、あらゆる操作が可能。
userAdmin 現在のデータベースでユーザとロールを作成・変更する権限を持つ。
createUser、dropUser、grantRole、revokeRole等のユーザ管理操作が可能。

実質的に、そのデータベースに対するあらゆる権限を付与できるため、注意が必要。


クラスタ管理ロール

クラスタ管理ロールは、レプリカセットやシャードクラスタ全体の管理に使用される。

クラスタ管理ロール
ロール 説明
clusterAdmin クラスタ管理の最大権限を持つ。
clusterManager、clusterMonitor、hostManagerロールの全権限を含む。

レプリカセット設定、シャーディング設定等のクラスタ全体の管理が可能。
clusterManager クラスタの管理・監視アクションを実行できる。
configおよびlocalデータベースへのアクセス権限を持つ。

レプリカセットの設定変更、シャードの追加・削除等が可能。
clusterMonitor 監視ツール (MongoDB Compass、監視エージェント等) 用の読み取り専用アクセス権限。
serverStatus、dbStats、collStats等の統計情報取得が可能。

書き込み操作は一切できない。
hostManager サーバの監視・管理権限を持つ。
サーバプロセスの起動・停止、ログの確認、診断コマンドの実行が可能。


全データベースロール

全データベースロールは、adminデータベースで付与され、全てのデータベースに対する権限を提供する。

全データベースロール
ロール 説明
readAnyDatabase 全てのデータベースに対する読み取り権限を持つ。
adminデータベースで付与する必要がある。

readロールを全てのデータベースに適用したもの。
readWriteAnyDatabase 全てのデータベースに対する読み書き権限を持つ。
adminデータベースで付与する必要がある。

readWriteロールを全てのデータベースに適用したもの。
userAdminAnyDatabase 全てのデータベースに対するユーザ管理権限を持つ。
adminデータベースで付与する必要がある。

userAdminロールを全てのデータベースに適用したもの。
dbAdminAnyDatabase 全てのデータベースに対する管理権限を持つ。
adminデータベースで付与する必要がある。

dbAdminロールを全てのデータベースに適用したもの。



スーパーユーザロール

rootロールは、MongoDBにおける最も強力な権限を持つスーパーユーザロールである。

スーパーユーザロール
ロール 説明
root 全ての権限を持つスーパーユーザ
readWriteAnyDatabase、dbAdminAnyDatabase、userAdminAnyDatabase、
clusterAdmin、restore、backupロールの全権限を含む。

システム全体のあらゆる操作が可能であり、使用には十分な注意が必要。



権限アクション

MongoDBの権限は、アクション (Action) という単位で定義される。
各ロールには、複数のアクションが含まれており、これらのアクションによって実行可能な操作が決定される。

クエリ・書き込みアクション

ドキュメントの読み取りおよび書き込みに関連するアクションである。

クエリ・書き込みアクション
アクション 説明
find ドキュメントの読み取り権限
find()、findOne()、aggregate()等のクエリ操作が可能
insert ドキュメントの挿入権限
insertOne()、insertMany()等の挿入操作が可能
update ドキュメントの更新権限
updateOne()、updateMany()、replaceOne()等の更新操作が可能
remove ドキュメントの削除権限
deleteOne()、deleteMany()等の削除操作が可能


コレクション管理アクション

コレクションおよびインデックスの管理に関連するアクションである。

コレクション管理アクション
アクション 説明
createCollection コレクションの作成権限
createCollection()コマンドの実行が可能
dropCollection コレクションの削除権限
drop()コマンドの実行が可能
createIndex インデックスの作成権限
createIndex()コマンドの実行が可能
dropIndex インデックスの削除権限
dropIndex()、dropIndexes()コマンドの実行が可能


データベース管理アクション

データベース全体の管理に関連するアクションである。

データベース管理アクション
アクション 説明
listCollections データベース内のコレクション一覧を取得する権限

show collectionsコマンド、listCollectionsコマンドの実行が可能
listDatabases サーバ内のデータベース一覧を取得する権限

show dbsコマンド、listDatabasesコマンドの実行が可能
dropDatabase データベース全体を削除する権限

dropDatabaseコマンドの実行が可能


ユーザ管理アクション

ユーザおよびロールの管理に関連するアクションである。

ユーザ管理アクション
アクション 説明
createUser ユーザの作成権限

createUserコマンドの実行が可能
dropUser ユーザの削除権限

dropUserコマンドの実行が可能
grantRole ロールの付与権限

grantRolesToUserコマンド、grantRolesToRoleコマンドの実行が可能
revokeRole ロールの取り消し権限

revokeRolesFromUserコマンド、revokeRolesFromRoleコマンドの実行が可能
viewUser ユーザ情報の表示権限

getUserコマンド、getUsersコマンドの実行が可能



ユーザの作成

MongoDBでユーザを作成するには、db.createUser メソッドを使用する。
ユーザは特定のデータベースに作成され、そのデータベースが認証データベースとなる。

基本構文

db.createUser メソッドの基本構文は以下の通りである。

 db.createUser({
   user: "ユーザ名",
   pwd: "パスワード",
   roles: [
     { role: "ロール名", db: "データベース名" },
     // 複数のロールを指定可能
   ]
 })


認証データベースの概念

MongoDBでは、ユーザは特定のデータベースに作成される。
ユーザを作成したデータベースが、そのユーザの認証データベース (Authentication Database) となる。

ユーザが接続する際には、認証データベースを指定する必要がある。
ただし、認証データベースとは異なるデータベースに対する権限を持つこともできる。

管理者ユーザの作成

以下の例では、adminデータベースに管理者ユーザを作成している。

 // adminデータベースに切り替え
 use admin
 
 // 管理者ユーザを作成
 db.createUser({
   user: "dbadmin",
   pwd: "adminPassword456",
   roles: [
     { role: "userAdminAnyDatabase", db: "admin" },
     { role: "readWriteAnyDatabase", db: "admin" },
     { role: "dbAdminAnyDatabase", db: "admin" }
   ]
 })


特定データベースへの読み書きユーザの作成

以下の例では、特定のデータベースに対する読み書き権限を持つユーザを作成している。

このユーザは、myappデータベースに対してのみ読み書き権限を持つ。
他のデータベースにはアクセスできない。

 // myappデータベースに切り替え
 use myapp
 
 // myappデータベースへの読み書き権限を持つユーザを作成
 db.createUser({
   user: "appuser",
   pwd: "appPassword789",
   roles: [
     { role: "readWrite", db: "myapp" }
   ]
 })


読み取り専用ユーザの作成

以下の例では、読み取り専用権限を持つユーザを作成している。

 // reportsデータベースに切り替え
 use reports
 
 // 読み取り専用ユーザを作成
 db.createUser({
   user: "readonly",
   pwd: "readOnlyPassword123",
   roles: [
     { role: "read", db: "reports" }
   ]
 })


複数データベースへのアクセス権を持つユーザの作成

以下の例では、複数のデータベースに対する権限を持つユーザを作成している。

 // adminデータベースに切り替え
 use admin
 
 // 複数のデータベースへのアクセス権を持つユーザを作成
 db.createUser({
   user: "multidbuser",
   pwd: "multiDbPassword456",
   roles: [
     { role: "readWrite", db: "sales" },
     { role: "read", db: "analytics" },
     { role: "dbAdmin", db: "inventory" }
   ]
 })



権限の付与

既存のユーザに追加のロールを付与するには、db.grantRolesToUser メソッドを使用する。

基本構文

db.grantRolesToUser メソッドの基本構文は以下の通りである。

 db.grantRolesToUser(
   "ユーザ名",
   [
     { role: "ロール名", db: "データベース名" },
     // 複数のロールを指定可能
   ]
 )


特定データベースへのロール付与

以下の例では、既存ユーザに、特定のデータベースへのロールを付与している。

 // adminデータベースに切り替え
 use admin
 
 // appuserに、logsデータベースへの読み取り権限を付与
 db.grantRolesToUser(
   "appuser",
   [
     { role: "read", db: "logs" }
   ]
 )


複数ロールの一括付与

以下の例では、複数のロールを同時に付与している。

 // adminデータベースに切り替え
 use admin
 
 // appuserに複数のロールを付与
 db.grantRolesToUser(
   "appuser",
   [
     { role: "readWrite", db: "inventory" },
     { role: "dbAdmin", db: "inventory" },
     { role: "read", db: "analytics" }
   ]
 )



権限の確認

ユーザおよびロールの情報を確認するには、いくつかのメソッドが用意されている。

特定ユーザの情報取得

db.getUser メソッドを使用して、特定のユーザの情報を取得できる。

このメソッドは、ユーザ名、ロール、認証データベース等の情報を含むドキュメントを返す。

 // adminデータベースに切り替え
 use admin
 
 // appuserの情報を取得
 db.getUser("appuser")


全ユーザの情報取得

db.getUsers メソッドを使用して、現在のデータベースに作成された全てのユーザを取得できる。

 // adminデータベースに切り替え
 use admin
 
 // 全てのユーザを取得
 db.getUsers()


ロール情報の取得

db.getRoles メソッドを使用して、データベース内のロール情報を取得できる。

 // adminデータベースに切り替え
 use admin
 
 // 全てのロールを取得 (詳細情報を含む)
 db.getRoles({ showPrivileges: true })


現在のユーザの権限確認

現在接続しているユーザの権限を確認するには、以下に示すコマンドを実行する。

このコマンドは、現在のユーザ名、認証データベース、付与されているロール等の情報を表示する。

 // 現在のユーザ情報を取得
 db.runCommand({ connectionStatus: 1 })



権限の削除

ユーザから特定のロールを削除するには、db.revokeRolesFromUser メソッドを使用する。

基本構文

db.revokeRolesFromUser メソッドの基本構文は以下の通りである。

 db.revokeRolesFromUser(
   "ユーザ名",
   [
     { role: "ロール名", db: "データベース名" },
     // 複数のロールを指定可能
   ]
 )


特定ロールの削除

以下の例では、ユーザから特定のロールを削除している。

 // adminデータベースに切り替え
 use admin
 
 // appuserからlogsデータベースへの読み取り権限を削除
 db.revokeRolesFromUser(
   "appuser",
   [
     { role: "read", db: "logs" }
   ]
 )


複数ロールの削除例

以下の例では、複数のロールを同時に削除している。

 // adminデータベースに切り替え
 use admin
 
 // appuserから複数のロールを削除
 db.revokeRolesFromUser(
   "appuser",
   [
     { role: "dbAdmin", db: "inventory" },
     { role: "read", db: "analytics" }
   ]
 )


ユーザの削除

ユーザ自体を削除するには、db.dropUser メソッドを使用する。

 // adminデータベースに切り替え
 use admin
 
 // appuserを削除
 db.dropUser("appuser")


※注意
ユーザを削除すると、そのユーザは完全に削除され、復元できない。
削除前に、必ず対象ユーザが正しいことを確認すること。


カスタムロールの作成

MongoDBでは、組み込みロールだけでなく、独自のカスタムロールを作成することができる。
カスタムロールを使用することで、業務要件に合わせた細かい権限制御が可能になる。

基本構文

db.createRole メソッドを使用してカスタムロールを作成する。

 db.createRole({
   role: "ロール名",
   privileges: [
     {
       resource: { db: "データベース名", collection: "コレクション名" },
       actions: [ "アクション1", "アクション2", ... ]
     }
   ],
   roles: [
     // 継承する既存のロール (オプション)
     { role: "既存ロール名", db: "データベース名" }
   ]
 })


privilegesの指定方法

privileges配列には、リソース (resource) と アクション (actions) の組み合わせを指定する。

リソースの指定方法
対象 指定方法
特定のコレクション { db: "mydb", collection: "mycollection" }
データベース全体 { db: "mydb", collection: "" }
全てのデータベース { db: "", collection: "" }
クラスタ全体 { cluster: true }


特定コレクションのみ読み書き可能なロールの作成

以下の例では、usersコレクションのみに読み書き権限を持つカスタムロールを作成している。

このロールを持つユーザは、myappデータベースのusersコレクションに対してのみ、読み取りおよび書き込み操作を実行できる。

 // myappデータベースに切り替え
 use myapp
 
 // usersコレクションのみ読み書き可能なロールを作成
 db.createRole({
   role: "usersReadWrite",
   privileges: [
     {
       resource: { db: "myapp", collection: "users" },
       actions: [ "find", "insert", "update", "remove" ]
     }
   ],
   roles: []
 })


読み取り専用+特定コレクションへの書き込み権限の作成

以下の例では、データベース全体への読み取り権限と特定のコレクションへの書き込み権限を持つロールを作成している。

 // myappデータベースに切り替え
 use myapp
 
 // データベース全体読み取り+logsコレクションへの書き込み権限
 db.createRole({
   role: "readWithLogging",
   privileges: [
     {
       resource: { db: "myapp", collection: "" },
       actions: [ "find" ]
     },
     {
       resource: { db: "myapp", collection: "logs" },
       actions: [ "insert", "update" ]
     }
   ],
   roles: []
 })


既存ロールの継承

以下の例では、既存のロールを継承してカスタムロールを作成している。

このロールは、readロールの全ての権限に加えて、logsコレクションへの挿入権限を持つ。

 // myappデータベースに切り替え
 use myapp
 
 // readロールを継承し、logsコレクションへの書き込み権限を追加
 db.createRole({
   role: "readPlusLogging",
   privileges: [
     {
       resource: { db: "myapp", collection: "logs" },
       actions: [ "insert" ]
     }
   ],
   roles: [
     { role: "read", db: "myapp" }
   ]
 })


ロールの更新

既存のカスタムロールを更新するには、db.updateRole メソッドを使用する。

 // myappデータベースに切り替え
 use myapp
 
 // usersReadWriteロールに、removeアクションを追加
 db.updateRole(
   "usersReadWrite",
   {
     privileges: [
       {
         resource: { db: "myapp", collection: "users" },
         actions: [ "find", "insert", "update", "remove", "createIndex" ]
       }
     ]
   }
 )


※注意
db.updateRole メソッドは、指定した内容でロールを完全に置き換える。
既存の権限を保持したい場合は、既存の権限も含めて全て指定する必要がある。

ロールの削除

カスタムロールを削除するには、db.dropRole メソッドを使用する。

 // myappデータベースに切り替え
 use myapp

 // usersReadWriteロールを削除
 db.dropRole("usersReadWrite")



推奨される事柄

MongoDBの権限管理において、セキュリティを確保するための推奨される事柄を以下に示す。

最小権限の原則

ユーザには、業務遂行に必要な最小限の権限のみを付与する。
例えば、読み取りのみで十分な場合は、readロールのみを付与し、readWriteロールを付与しない。

また、特定のコレクションのみにアクセスが必要な場合は、カスタムロールを作成して対象を限定する。

過剰な権限を付与すると、誤操作やセキュリティリスクが増大する。

管理者アカウントの分離

日常的な操作用のアカウントと、管理用のアカウントを分離する。
例えば、管理者権限 (rootやuserAdminAnyDatabase) を持つアカウントは、管理作業時のみ使用し、アプリケーションからの接続には使用しない。

これにより、アプリケーションの脆弱性や設定ミスによる被害を最小限に抑えることができる。

認証の必須化

本番環境では、必ず認証を有効化する。

認証を無効にしたまま運用すると、誰でもデータベースにアクセスできてしまい、データの漏洩、改竄、削除等の重大なセキュリティインシデントにつながる。

開発環境であっても、できる限り認証を有効化することを推奨する。

定期的な権限監査

ユーザとその権限を定期的に確認し、不要になったユーザやロールを削除する。

例えば、退職した従業員のアカウントや使用されなくなったアプリケーション用のアカウントが残っていないかどうかを確認する。

また、過剰な権限が付与されていないかを定期的に確認して、必要に応じて権限を見直す。

カスタムロールの活用

組み込みロールだけでは細かい制御ができない場合は、カスタムロールを積極的に活用する。
業務要件に合わせた適切なロール設計により、セキュリティと利便性を両立できる。

例えば、特定のコレクションのみにアクセスを許可したり、読み取りは全体、書き込みは特定コレクションのみといった細かい制御が可能になる。

パスワードポリシー

強力なパスワードを使用する。

パスワードは、以下に示す要件を満たすことを推奨する。

  • 最低12文字以上
  • 英大文字、英小文字、数字、記号を組み合わせる。
  • 辞書に載っている単語や、推測しやすい文字列を避ける。


また、パスワードは定期的に変更し、同じパスワードを複数のアカウントで使い回さない。

可能であれば、SCRAM-SHA-256等の強力な認証メカニズムを使用する。