MongoDBの基本的なセキュリティ設定についてまとめます。接続を許可するインターフェースを指定したりポート番号を変えたりユーザ認証をしたりする方法をまとめます。
前提
公式ドキュメント
参考になる公式ドキュメントを以下に示します。
動作確認済環境
- Rocky Linux 8.6
- MongoDB Server 6.0.2
構成図
以下の構成で動作確認をします。
172.16.1.0/24 +-----------------+-----------------+ | | | ens192 | .10 ens192 | .20 ens192 | .30 +------+------+ +------+------+ +------+------+ | linux010 | | linux020 | | linux030 | | (Rocky8.6) | | (Rocky8.6) | | (Rocky8.6) | | (Primary) | | (Secondary) | | (Secondary) | +------+------+ +------+------+ +------+------+ ens224 | .10 ens224 | .20 ens224 | .30 | | | +-----------------+-----------------+ 172.16.2.0/24
事前設定
検証シナリオの都合上、「非レプリケーション構成」「レプリケーション構成」の順に動作確認をします。
初期設定時点ではレプリケーションを設定しない状態とします。
ネットワーク接続許可関連の設定
MongoDBはListen状態にするインターフェースを指定したりListenするポート番号を変更したりする事ができます。/etc/mongod.confのnetに関する記述を以下のように変更し、mongodを再起動して設定を反映させます。
net以外の部分は説明を省略します
net: port: 27100 bindIp: 172.16.1.10
net: port: 27100 bindIp: 172.16.1.20
net: port: 27100 bindIp: 172.16.1.30
本シナリオを構成は172.16.1.0/24と172.16.2.0/24の2つのサブネットを持つ構成です。前者の172.16.1.0/24のみmongodがListen状態になるように設定しました。それでは172.16.1.0/24のみ接続可能である事を確認しましょう。
linux020からlinux010に対して、172.16.1.0/24セグメント経由で疎通可能な事を確認します。
[root@linux020 ~]# ping 172.16.1.10 -c 1 PING 172.16.1.10 (172.16.1.10) 56(84) bytes of data. 64 bytes from 172.16.1.10: icmp_seq=1 ttl=64 time=0.509 ms --- 172.16.1.10 ping statistics --- 1 packets transmitted, 1 received, 0% packet loss, time 0ms rtt min/avg/max/mdev = 0.509/0.509/0.509/0.000 ms [root@linux020 ~]# mongosh --quiet mongodb://172.16.1.10:27100/test test>
linux020からlinux010に対して、172.16.2.0/24セグメント経由の接続を試みます。接続が拒否される事を確認します。
[root@linux020 ~]# ping 172.16.2.10 -c 1 PING 172.16.2.10 (172.16.2.10) 56(84) bytes of data. 64 bytes from 172.16.2.10: icmp_seq=1 ttl=64 time=0.456 ms --- 172.16.2.10 ping statistics --- 1 packets transmitted, 1 received, 0% packet loss, time 0ms rtt min/avg/max/mdev = 0.456/0.456/0.456/0.000 ms [root@linux020 ~]# mongosh --quiet mongodb://172.16.2.10:27100/test MongoNetworkError: connect ECONNREFUSED 172.16.2.10:27100 [root@linux020 ~]#
RBAC(Role-Based Access Control)
スタンドアローン構成の場合
ユーザ作成と認証有効化
MongoDBはロール(役割)ベースの権限管理の機能を備えています。さっそく動作確認をしてみましょう。
sample01データベースに対するデータベース管理者を作成します。MongoDBにビルトインで組み込まれているロールを使うならば”dbOwner”と指定します。
use sample01 db.createUser({ user: "dba01", pwd: "P@ssw0rd", roles: [{role: "dbOwner", db: "sample01"}] })
sample02データベースに対しても同様のデータベース管理者を作成します。
use sample02 db.createUser({ user: "dba02", pwd: "P@ssw0rd", roles: [{role: "dbOwner", db: "sample02"}] })
MongoDBに対するrootの管理者を作成します。
use admin db.createUser({ user: "admin", pwd: "P@ssw0rd", roles: [{role: "root", db: "admin"}] })
想定通りのユーザが作成されたか否かはgetUsers()で確認できます。
admin> use sample01 switched to db sample01 sample01> db.getUsers() { users: [ { _id: 'sample01.dba01', userId: new UUID("18dc2907-027e-44db-b3b7-c5b4acb1b594"), user: 'dba01', db: 'sample01', roles: [ { role: 'dbOwner', db: 'sample01' } ], mechanisms: [ 'SCRAM-SHA-1', 'SCRAM-SHA-256' ] } ], ok: 1 } sample01>
スタンドアローン構成で認証を有効にするにはsecurity.authorizationをenabledに変更します。/etc/mongod.confのsecurityに関する記述を以下のように変更し、mongodを再起動して設定を反映させます。
security以外の部分は説明を省略します
security: authorization: enabled
動作確認
それでは認証なしで接続してみましょう。すると、コマンド実行時にエラーが返される事が分かります。
[root@linux010 ~]# mongosh --quiet mongodb://172.16.1.10:27100/test test> show dbs MongoServerError: command listDatabases requires authentication test>
sample01データベースにdba01ユーザで接続します。この場合は適切な権限が与えられているので、Collection作成などの操作が可能です。
[root@linux010 ~]# mongosh --quiet mongodb://172.16.1.10:27100/sample01 -u dba01 -p P@ssw0rd sample01> db.createCollection('employee') { ok: 1 } sample01> db.employee.insertOne({name:"scott",password:"tiger"}) { acknowledged: true, insertedId: ObjectId("63539e3cf4a1e4ac16211a6d") } sample01>
sample02データベースにdba01ユーザでの接続を試みます。この場合は、権限がないので接続そのものを拒否されます。
[root@linux010 ~]# mongosh --quiet mongodb://172.16.1.10:27100/sample02 -u dba01 -p P@ssw0rd MongoServerError: Authentication failed. [root@linux010 ~]#
レプリケーション構成の場合
KeyFileの作成
それではレプリケーション構成の認証を動作確認しましょう。まずはレプリケーション構成に変更するために、/etc/mongod.confに以下を加筆します。
replication: replSetName: "rs0" oplogSizeMB: 1024
設定反映のための再起動を試みます。すると、レプリケーション構成の場合はsecurity.keyFileというパラメタが必須である旨のエラーメッセージが出力されます。
[root@linux010 ~]# systemctl restart mongod.service Job for mongod.service failed because the control process exited with error code. See "systemctl status mongod.service" and "journalctl -xe" for details. [root@linux010 ~]# journalctl -xe 10月 22 16:42:42 linux010.gokatei.go systemd[1]: Starting MongoDB Database Server... -- Subject: Unit mongod.service has begun start-up -- Defined-By: systemd -- Support: https://lists.freedesktop.org/mailman/listinfo/systemd-devel -- -- Unit mongod.service has begun starting up. 10月 22 16:42:42 linux010.gokatei.go mongod[3088]: BadValue: security.keyFile is required when authorization is enabled with replica sets 10月 22 16:42:42 linux010.gokatei.go mongod[3088]: try '/usr/bin/mongod --help' for more information 10月 22 16:42:42 linux010.gokatei.go systemd[1]: mongod.service: Control process exited, code=exited status=2 10月 22 16:42:42 linux010.gokatei.go systemd[1]: mongod.service: Failed with result 'exit-code'. -- Subject: Unit failed -- Defined-By: systemd -- Support: https://lists.freedesktop.org/mailman/listinfo/systemd-devel -- -- The unit mongod.service has entered the 'failed' state with result 'exit-code'. 10月 22 16:42:42 linux010.gokatei.go systemd[1]: Failed to start MongoDB Database Server. -- Subject: Unit mongod.service has failed -- Defined-By: systemd -- Support: https://lists.freedesktop.org/mailman/listinfo/systemd-devel -- -- Unit mongod.service has failed. -- -- The result is failed.
security.keyFileは6文字から1024文字でbase64された文字列のファイルを指定します。このファイルを用いる事によって、レプリケーションを組む(正確にはシャーディング構成のmongosやconfigサーバも含まれる)MongoDB同士の認証をします。
それではkeyFileを作成しましょう。以下は756文字のキーファイルを作成する操作例です。
openssl rand -base64 756 > /etc/mongoKey.txt chown mongod:mongod /etc/mongoKey.txt chmod 400 /etc/mongoKey.txt
作成したキーファイルをすべてのMongoDBサーバへ転送します。
パーミッション含めて正確にコピーください。scpはユーザ含めて転送されませんので、scpコマンドを使用する場合は再度の権限設定が必要です。
rsync -av /etc/mongoKey.txt 172.16.1.20:/etc/ rsync -av /etc/mongoKey.txt 172.16.1.30:/etc/
KeyFileの設定
/etc/mongod.confを以下のように設定し、replicationとkeyFileを設定します。
security.keyFileを設定した場合は、security.authorizationを明示指定しなくても暗黙的に有効になります。
#replication: replication: replSetName: "rs0" oplogSizeMB: 1024 #security: security: authorization: enabled keyFile: /etc/mongoKey.txt
mongodを再起動し、設定を反映させます。
systemctl restart mongod.service
レプリケーションの開始
レプリケーションを開始するにはroot権限が必要です。root権限を持っているのはadminユーザですのでadminユーザでmongodへログインします。その後、rs.initiate()メソッドによりレプリケーションを開始できます。
[root@linux010 ~]# mongosh --quiet mongodb://172.16.1.10:27100/admin -u admin -p P@ssw0rd admin> rs.initiate( ... { ... _id : "rs0", ... members: [ ... { _id : 0, host : "172.16.1.10:27100" , priority : 2 }, ... { _id : 1, host : "172.16.1.20:27100" , priority : 1 }, ... { _id : 2, host : "172.16.1.30:27100" , priority : 0 } ... ] ... } ... ) { ok: 1 } rs0 [direct: other] admin> rs0 [direct: primary] admin>