前回はデータを確認してみました。今回は少しわき道にそれてパスワードを設定します。

Introduction

前回まで、無防備状態でデータベースにアクセスしたり、サーバー走らせたりと、やりたい放題でした。

さすがにそれは不味い、ということでMongoDBとmongo-expressにパスワードを設定します。

Explanation

mongo-express

早急にこっちをどうにかします。サーバーの脆弱性、とかいうお寒い状態は嫌なので。

公式ページによればパスワードは config.js を修正する、って書いてあります。

ME_CONFIG_BASICAUTH_USERNAME ME_CONFIG_BASICAUTH_PASSWORD

この2つのようです。

書きえて、mongo-expressを再起動します。

どうも、ローカルでインストールした場合、node app で動いているコマンドプロンプトを終了または Ctrl + C で落とせば終了するようです。

で、書き換えて再起動すると、ちゃんと変わっていることが確認できました。

BASIC 認証ってださいよねー

その名の通り。

というか1Passwordが使えないから面倒。

で、もう一度調べてみると。

mongo-express login name. Sending an empty string will disable basic authentication.

訳: mongo-expreessのログイン名。空文字列を送ると、BASIC認証を無効化。 という記述を発見。

ん?でもこれだと、ユーザー名はどうなるの?と思ったが試してみることに。

あれ?BASIC認証のまま。

というか、ユーザ名が空文字でパスワードが変わらないだけじゃん。

どうも、BASIC認証を無効にして、別の認証にするわけではなく、そもそも認証があるかどうかしかないようだ。

でも空文字にしても設定が有効じゃん。

試行錯誤した結果

1
2
-  useBasicAuth: process.env.ME_CONFIG_BASICAUTH_USERNAME !== '',
+ useBasicAuth: process.env.ME_CONFIG_BASICAUTH_USERNAME || false,

にすると、認証そのものがなくなり、さらなる無防備状態になるようだ。

もうこれでいいような。

MongoDB

今度はこっちにパスワードを設定する。

mongo-expressからはそういうことはできないご様子。

ただ、さっきの config.js

1
// >>>> If you are using an admin mongodb account, or no admin account exists, fill out section below // >>>> Using an admin account allows you to view and edit all databases, and view stats 

という記述があるのを発見。

MongoDBにはAdminユーザがあるってこと?と思いぐぐる。

Enable Client Access Controlによると、

Considerations With access control enabled, ensure you have a user with userAdmin or userAdminAnyDatabase role in the admin database. You can create users before enabling access control or you can create users after enabling access control. If you enable access control before creating any user, MongoDB provides a localhost exception which allows you to create a user administrator in the admin database. Once created, authenticate as the user administrator to create additional users as needed.

`訳: 検討 アクセス制御を有効にすると、(あなたが)userAdminまたはuserAdminAnyDataaseロールを保持しているかどうかをadminデータベースで確認します。

(あなたが)アクセス制御を有効にする前にユーザーを作成することもできますし、アクセス制御を有効にした後でもユーザを作成することができます。もし、ユーザを作成する前にアクセス制御を有効にすると、MongoDBは、adminデータベース内にadministratorユーザを作成することを許可するlocalhost例外を提供します。一度作成すると、必要に応じて追加ユーザを作成するのにadministratorユーザとして認証します。`

とあるので、アクセス制御さえ有効にしてしまえば、外部からアクセスされる心配はないってことでは? 少なくとも、外部からMongoDBにつなぐことは今のところないし。

でも一応管理者ユーザを作っておきます。

まずは、アクセス制御を有効にします。

現在はサービスとして有効にしているので、サービス起動時に読み込んでいる設定ファイルに必要な設定を書き込みます。

私の場合は、D:\MongoDB\mongd.cfg になります。

Configuration File Options によれば、

1
2
security:
authorization: <string>

とある。

既定は disabled なので enabled で追加してみる。

次はユーザを追加する。

まずはデータベースに接続します。ポート番号とは既定のままとします。

1
cd c:\Program Files\MongoDB\Server\3.2\bin mongo --port 27017 

次にユーザを追加します。

ユーザ名とパスワードは適宜変更を。

1
2
use admin
> db.createUser( { user: "admin", pwd: "password", roles: [ { role: "root", db: "admin" } ] })

上は、role に root を指定しています。

公式は userAdminAnyDatabase を使え、って言ってますが、それだと、mongo-expressが動きません。

これで 3時間くらい 無駄にしました。

入力が終わると、

1
2
3
4
5
6
7
8
9
Successfully added user: {
"user" : "admin",
"roles" : [
{
"role" : "root",
"db" : "admin"
}
]
}

と出力されれば成功です。これでadminデータベースにadminユーザが追加されました。

一度exitで終了します。

1
> exit 

サービスを再起動します。

もう一度データベースに接続し、

1
2
> use admin
> show users

とすると

1
2015-12-30T00:17:41.833+0900 E QUERY    [thread1] Error: not authorized on admin to execute command { usersInfo: 1.0 } :

と返ってきて認証エラーでユーザ一覧が表示できないことがわかります。

再度exitで終了しますが、今度は、

1
mongo --port 27017 -u "admin" -p "password" --authenticationDatabase "admin"

でログインし、adminデータベースにつないで、show usersします。

今度は、

1
2
3
4
5
6
7
8
9
10
11
12
> show users
{
"_id" : "admin.admin",
"user" : "admin",
"db" : "admin",
"roles" : [
{
"role" : "root",
"db" : "admin"
}
]
}

となり、認証機能が働いていることがわかります。

mongo-expressのadmin対応

もう一度、config.jsを開き、

1
2
3
4
//set admin to true if you want to turn on admin features
//if admin is true, the auth list below will be ignored
//if admin is true, you will need to enter an admin username/password below (if it is needed)
admin: false,

1
2
3
4
//set admin to true if you want to turn on admin features
//if admin is true, the auth list below will be ignored
//if admin is true, you will need to enter an admin username/password below (if it is needed)
admin: true,

に修正。

1
2
3
//leave username and password empty if no admin account exists
adminUsername: process.env.ME_CONFIG_MONGODB_ADMINUSERNAME || '',
adminPassword: process.env.ME_CONFIG_MONGODB_ADMINPASSWORD || '',

1
2
3
//leave username and password empty if no admin account exists
adminUsername: process.env.ME_CONFIG_MONGODB_ADMINUSERNAME || 'admin',
adminPassword: process.env.ME_CONFIG_MONGODB_ADMINPASSWORD || 'password',

に修正。

ユーザ名とパスワードは適宜変更を。

これでmongo-expressが動きます。

プログラムからもデータベースを操作

以前のプログラムで、TestConnect メソッドを呼ぶと、ListDatabases メソッドをコールした時点で下記の例外が発生します。

型 'MongoDB.Driver.MongoCommandException' のハンドルされていない例外が MongoDB.Driver.Core.dll で発生しました 追加情報:Command listDatabases failed: not authorized on admin to execute command { listDatabases: 1 }.

認証情報が足りないためなので、接続文字列を下記のように修正します。

修正後のソースはこちら

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
private const string UserName = "admin";

private const string Password = "password";

static void Main()
{
var mongoClient = new MongoClient(string.Format("mongodb://{0}:{1}@localhost", UserName, Password));
・・TestConnect(mongoClient);

InsertData(mongoClient);
TestConnect(mongoClient);

Console.WriteLine("Please enter any key...");
Console.ReadKey();
}

ユーザ名とパスワードは適宜変更を。

これで新しいデータベースも追加できるようになりました。

Conclusion

公式の罠にはまりましたが、何とかなりました。

詳しい原因はできたら次回以降に説明できればな、と思います。

Source Code

https://github.com/takuya-takeuchi/Demo/tree/master/Database/MongoDB/MongoDB4