CentOS8でMongoDBを保護する方法
このチュートリアルの以前のバージョンは、 MelissaAndersonによって作成されました。
序章
MongoDB は、 Mongo とも呼ばれ、多くの最新のWebアプリケーションで使用されているオープンソースのドキュメントデータベースです。 従来のテーブルベースのリレーショナルデータベース構造に依存しないため、NoSQLデータベースとして分類されます。 代わりに、動的スキーマを持つJSONのようなドキュメントを使用します。
MongoDBでは、デフォルトで認証が有効になっていません。つまり、データベースがインストールされているサーバーにアクセスできるユーザーは、制限なしにデータを追加および削除できます。 この脆弱性を保護するために、このチュートリアルでは、管理ユーザーの作成と認証の有効化について説明します。 次に、この管理ユーザーのみがデータベースにアクセスできることを確認するためにテストします。
前提条件
このチュートリアルを完了するには、次のものが必要です。
- このチュートリアルを完了するには、CentOS8を実行しているサーバーが必要です。 このサーバーには、管理者権限を持つroot以外のユーザーと、
firewalld
で構成されたファイアウォールが必要です。 これを設定するには、CentOS8の初期サーバーセットアップガイドに従ってください。 - サーバーにインストールされているMongoDB。 このチュートリアルは、MongoDBバージョン 4.4 を使用して検証されましたが、通常、古いバージョンのMongoDBでも機能するはずです。 サーバーにMongoをインストールするには、 CentOS8にMongoDBをインストールする方法に関するチュートリアルに従ってください。
ステップ1—管理ユーザーの追加
バージョン3.0のリリース以降、MongoDBデーモンは、ローカルのUnixソケットからの接続のみを受け入れるように構成されており、より広いインターネットに対して自動的に開かれることはありません。 ただし、認証はデフォルトで無効のままです。 これは、MongoDBがインストールされているサーバーにアクセスできるすべてのユーザーが、データベースにも完全にアクセスできることを意味します。
この脆弱性を保護するための最初のステップとして、管理ユーザーを作成します。 後で、認証を有効にし、この管理ユーザーとして接続してデータベースにアクセスします。
管理ユーザーを追加するには、最初にMongoシェルに接続する必要があります。 認証が無効になっているため、mongo
コマンドを使用して、他のオプションなしで認証を行うことができます。
- mongo
Mongoシェルプロンプトの上にいくつかの出力があります。 認証をまだ有効にしていないため、これには、データベースに対してアクセス制御が有効になっておらず、データへの読み取りおよび書き込みアクセスとデータベースの構成が制限されていないという警告が含まれます。
OutputMongoDB shell version v4.4.1
. . .
---
The server generated these startup warnings when booting:
2020-10-02T14:38:03.448+00:00: ***** SERVER RESTARTED *****
2020-10-02T14:38:04.209+00:00: Access control is not enabled for the database. Read and write access to data and configuration is unrestricted
---
. . .
>
2番目の警告は、認証を有効にすると消えますが、今のところ、CentOSサーバーにアクセスできる人なら誰でもデータベースを制御できることを意味します。
注:前提条件にリンクされているチュートリアル以外のチュートリアルに従ってMongoDBをインストールした場合、プロンプトに次のような別の警告が表示される場合があります。
Output. . .
2020-10-02T14:38:04.633+00:00: /sys/kernel/mm/transparent_hugepage/enabled is 'always'. We suggest setting it to 'never'
. . .
この警告は、CentOS8でデフォルトで有効になっているLinuxメモリ管理システムであるTransparentHuge Pages(THP)に関するものです。 THPは、特大のメモリページを使用して、大量のメモリを搭載したマシンでのトランスレーションルックアサイドバッファルックアップの影響を軽減します。 ただし、この警告が示すように、このシステムはデータベースのパフォーマンスに悪影響を与える可能性があるため、MongoDBのドキュメントでは無効にすることを推奨しています。
透過的な巨大ページを無効にする方法の詳細については、 CentOS8にMongoDBをインストールする方法に関するガイドのステップ2を参照してください。
説明のために、Mongoのshow dbs
コマンドを実行します。
- show dbs
このコマンドは、サーバー上のすべてのデータベースのリストを返します。 ただし、認証が有効になっている場合、リストはMongoユーザーの role 、または特定のデータベースへのアクセスレベルに基づいて変更されます。 ただし、認証が無効になっているため、現在システム上にあるすべてのデータベースが制限なしで返されます。
Outputadmin 0.000GB
config 0.000GB
local 0.000GB
この出力例では、デフォルトのデータベースのみが表示されます。 ただし、システム上に機密データを保持しているデータベースがある場合、すべてのユーザーがこのコマンドでそれらを見つけることができます。
この脆弱性を軽減する一環として、この手順では管理ユーザーの追加に重点を置いています。 これを行うには、最初にadmin
データベースに接続する必要があります。 これは、ユーザー名、パスワード、役割などのユーザーに関する情報が保存される場所です。
- use admin
Outputswitched to db admin
MongoDBには、データベースの管理に使用できるJavaScriptベースのシェルメソッドが多数インストールされています。 これらの1つであるdb.createUser
メソッドは、メソッドが実行されるデータベース上に新しいユーザーを作成するために使用されます。
db.createUser
メソッドを開始します。
- db.createUser(
この方法では、ユーザーのユーザー名とパスワード、およびユーザーに付与する役割を指定する必要があります。 MongoDBはデータをJSONのようなドキュメントに保存することを思い出してください。 新しいユーザーを作成するときは、適切なユーザーデータを個々のフィールドとして保持するドキュメントを作成するだけです。
JSONのオブジェクトと同様に、MongoDBのドキュメントは中括弧({
および}
)で開始および終了します。 ユーザーの追加を開始するには、最初の中括弧を入力します。
注:Mongoは、閉じ括弧を入力するまで、db.createUser
メソッドを完了として登録しません。 そうするまで、プロンプトは大なり記号(>
)から省略記号(...
)に変わります。
- {
次に、user:
フィールドに、希望するユーザー名を二重引用符で囲んだ値にコンマを付けて入力します。 次の例では、ユーザー名 AdminSammy を指定していますが、任意のユーザー名を入力できます。
- user: "AdminSammy",
次に、passwordPrompt()
メソッドを値としてpwd
フィールドに入力します。 db.createUser
メソッドを実行すると、passwordPrompt()
メソッドはパスワードの入力を求めるプロンプトを表示します。 これは、ユーザー名の場合と同じようにパスワードをクリアテキストで入力するという代替手段よりも安全です。
注:passwordPrompt()
メソッドは、MongoDBバージョン4.2以降とのみ互換性があります。 古いバージョンのMongoを使用している場合は、ユーザー名を書き出すのと同じように、パスワードをクリアテキストで書き出す必要があります。
- pwd: "password",
このフィールドの後には、必ずコンマを付けてください。
- pwd: passwordPrompt(),
次に、管理ユーザーに付与する役割を入力します。 管理ユーザーを作成しているため、少なくとも、admin
データベースに対するuserAdminAnyDatabase
ロールをユーザーに付与する必要があります。 これにより、管理ユーザーは新しいユーザーとロールを作成および変更できます。 管理ユーザーはadmin
データベースでこの役割を持っているため、クラスター全体へのスーパーユーザーアクセスも許可されます。
さらに、次の例では、管理ユーザーにreadWriteAnyDatabase
ロールも付与しています。 これにより、管理ユーザーは、config
およびlocal
データベースを除くクラスター内の任意のデータベースのデータを読み取って変更できるようになります。これらのデータベースは主に内部で使用されます。
- roles: [ { role: "userAdminAnyDatabase", db: "admin" }, "readWriteAnyDatabase" ]
続いて、ドキュメントの終わりを示すために閉じ中括弧を入力します。
- }
次に、閉じ括弧を入力して、db.createUser
メソッドを閉じて実行します。
- )
まとめると、db.createUser
メソッドは次のようになります。
> db.createUser(
... {
... user: "AdminSammy",
... pwd: passwordPrompt(),
... roles: [ { role: "userAdminAnyDatabase", db: "admin" }, "readWriteAnyDatabase" ]
... }
... )
各行の構文が正しい場合、メソッドは正しく実行され、パスワードの入力を求められます。
OutputEnter password:
選択した強力なパスワードを入力します。 次に、ユーザーが追加されたという確認を受け取ります。
OutputSuccessfully added user: {
"user" : "AdminSammy",
"roles" : [
{
"role" : "userAdminAnyDatabase",
"db" : "admin"
},
"readWriteAnyDatabase"
]
}
その後、MongoDBクライアントを終了できます。
- exit
この時点で、ユーザーは資格情報を入力できるようになります。 ただし、認証を有効にしてMongoDBデーモンを再起動するまでは、そうする必要はありません。
ステップ2—認証を有効にする
認証を有効にするには、MongoDBの構成ファイルであるmongod.conf
を編集する必要があります。 これを有効にしてMongoサービスを再起動すると、ユーザーは認証なしでデータベースに接続できます。 ただし、正しいユーザー名とパスワードを提供するまで、データを読み取ったり変更したりすることはできません。
好みのテキストエディタで設定ファイルを開きます。 ここでは、nano
を使用します。
- sudo nano /etc/mongod.conf
下にスクロールして、コメントアウトされたsecurity
セクションを見つけます。
. . .
#security:
#operationProfiling:
. . .
ポンド記号(#
)を削除して、この行のコメントを解除します。
. . .
security:
#operationProfiling:
. . .
次に、authorization
パラメーターを追加し、"enabled"
に設定します。 完了すると、行は次のようになります。
. . .
security:
authorization: "enabled"
. . .
security:
行の先頭にはスペースがありませんが、authorization:
行は2つのスペースでインデントされていることに注意してください。
これらの行を追加したら、ファイルを保存して閉じます。 nano
を使用してファイルを開く場合は、CTRL + X
、Y
、ENTER
の順に押します。
次に、デーモンを再起動して、これらの新しい変更を有効にします。
- sudo systemctl restart mongod
次に、サービスのステータスをチェックして、サービスが正しく再起動したことを確認します。
- sudo systemctl status mongod
restart
コマンドが成功すると、mongod
サービスがアクティブで、最近開始されたことを示す出力が表示されます。
Output● mongod.service - MongoDB Database Server
Loaded: loaded (/usr/lib/systemd/system/mongod.service; enabled; vendor preset: disabled)
Active: active (running) since Fri 2020-10-02 14:57:31 UTC; 7s ago
Docs: https://docs.mongodb.org/manual
Process: 15667 ExecStart=/usr/bin/mongod $OPTIONS (code=exited, status=0/SUCCESS)
Process: 15665 ExecStartPre=/usr/bin/chmod 0755 /var/run/mongodb (code=exited, status=0/SUCCESS)
Process: 15662 ExecStartPre=/usr/bin/chown mongod:mongod /var/run/mongodb (code=exited, status=0/SUCCESS)
Process: 15659 ExecStartPre=/usr/bin/mkdir -p /var/run/mongodb (code=exited, status=0/SUCCESS)
Main PID: 15669 (mongod)
Memory: 159.2M
CGroup: /system.slice/mongod.service
└─15669 /usr/bin/mongod -f /etc/mongod.conf
デーモンがバックアップされて実行されていることを確認したら、追加した認証設定が期待どおりに機能することをテストできます。
ステップ3—認証設定のテスト
前の手順で追加した認証要件が正しく機能していることをテストするには、資格情報を指定せずに接続して、アクションが実際に制限されていることを確認します。
- mongo
認証を有効にしたので、以前に発生した警告は表示されません。
OutputMongoDB shell version v4.4.1
connecting to: mongodb://127.0.0.1:27017/?compressors=disabled&gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("d57987e5-24dc-427e-89b7-9ab362ebac6b") }
MongoDB server version: 4.4.1
>
show dbs
コマンドを再度実行して、アクセスが制限されているかどうかを確認します。
- show dbs
ステップ1から、サーバーに少なくともいくつかのデフォルトデータベースがあることを思い出してください。 ただし、この場合、特権ユーザーとして認証されていないため、コマンドには出力がありません。
このコマンドは情報を返さないため、認証設定が期待どおりに機能していると言っても差し支えありません。 また、最初に認証しないと、ユーザーを作成したり、他の特権タスクを実行したりすることはできません。
先に進み、MongoDBシェルを終了します。
注:前の手順1で行ったように次のexit
コマンドを実行する代わりに、シェルを閉じる別の方法は、CTRL + C
を押すことです。
- exit
次に、次のmongo
コマンドを実行してこのユーザーとして接続し、管理ユーザーが正しく認証できることを確認します。 このコマンドには、接続するユーザーの名前の前にある-u
フラグが含まれています。 必ずAdminSammyを自分の管理ユーザーのユーザー名に置き換えてください。 また、ユーザーのパスワードの入力を求める-p
フラグが含まれ、指定されたユーザー名が作成された認証データベースとしてadmin
を指定します。
- mongo -u AdminSammy -p --authenticationDatabase admin
プロンプトが表示されたらユーザーのパスワードを入力すると、シェルにドロップされます。 そこで、show dbs
コマンドをもう一度発行してみてください。
- show dbs
今回は、正しく認証されているため、コマンドは現在サーバー上にあるすべてのデータベースのリストを正常に返します。
Outputadmin 0.000GB
config 0.000GB
local 0.000GB
これにより、認証が正常に有効になったことを確認できます。
結論
このガイドを完了することで、管理用のMongoDBユーザーを設定しました。このユーザーを使用して、新しいユーザーとロールを作成および変更したり、MongoDBインスタンスを管理したりできます。 また、ユーザーがデータを操作する前に、有効なユーザー名とパスワードで認証することを要求するようにMongoDBインスタンスを構成しました。
MongoDBユーザーを管理する方法の詳細については、主題に関する公式ドキュメントを確認してください。 また、MongoDBで認証がどのように機能するかについて詳しく知ることもできます。
また、MongoDBインスタンスをリモートで操作する場合は、 CentOS8でMongoDBのリモートアクセスを構成する方法に関するガイドに従うことができます。