web-dev-qa-db-ja.com

PyMongoを使用した自己署名SSL接続

PyMongoを使用してMongoDBへの安全なSSL接続を作成しようとしています。目標は、Pythonクライアントに接続できるEC2で実行されているMongoインスタンスにこの構成を使用することです。テストのために、最初に構成をローカルで機能させようとしています。まだ失敗している試みを見つけることができます ここ

私が考えている問題の短いバージョン:クライアント側の認証局ファイルca.pemが正しくありません。私のやり方では、このファイルは実際にはサーバー側で使用しているものと同じです。どちらもx509opensslを使用して作成されており、クライアント側のファイルには何らかの異なるコンテンツが必要だと思われますが、そのコンテンツを生成する方法や、この疑いが均等かどうかはわかりません。正しい。

(Mac El Capitanで)必要な証明書とキーを作成するために私が行ったことの詳細は次のとおりです。

まず、認証局を生成します。

$ mkdir ~/ssl
$ cd ~/ssl
$ openssl req -out ca.pem -new -x509 -days 3650    
# enter info

サーバー.pemファイルを生成します:

$ openssl genrsa -out server.key 2048
$ openssl req -key server.key -new -out server.req
# enter info
$ openssl x509 -req -in server.req -CA ca.pem -CAkey privkey.pem -CAserial file.srl -out server.crt -days 3650
$ cat server.key server.crt > server.pem

クライアントに対しても同じことを行います。

$ openssl genrsa -out client.key 2048
$ openssl req -key client.key -new -out client.req
$ openssl x509 -req -in client.req -CA ca.pem -CAkey privkey.pem -CAserial file.srl -out client.crt -days 3650
$ cat client.key client.crt > client.pem

次に、etc/mongod.confで次の構成を行います。

net:
  ...
  ssl:
    mode: requireSSL
    PEMKeyFile: ~/ssl/server.pem
    CAFile: ~/ssl/ca.pem

今mongo(Mac)を

$ mongod --config /etc/mongod.conf

期待どおりに動作します。プロセスが実行され、構成を受け入れているようです。

次に、Python側(デバッグのためにlocalhostでも実行)で、mongoを呼び出すときに次のことを行います。

import ssl
from pymongo import MongoClient

client = MongoClient(
        '127.0.0.1',
        27017,
        ssl=True,
        ssl_certfile='~/ssl/client.pem',
        ssl_cert_reqs=ssl.CERT_REQUIRED,
        ssl_ca_certs='~/ssl/ca.pem'
        )
# try a simple insert

これを実行すると、MongoClientの作成後にPythonコードブロックが発生し、mongoログに次のように表示されます。

2016-03-03T22:11:30.331-0800 E NETWORK  [conn21] SSL: error:14094418:SSL routines:ssl3_read_bytes:tlsv1 alert unknown ca

以下のWanのコメントに基づいて、「識別名」の情報がそれらの仕様と一致していることを確認して、すべてをやり直しました。古いバージョンでは、サーバーとクライアントの両方に同じ共通名が使用されていました。接続はまだ成功していませんが、メッセージは多少異なります。

2016-03-11T12:29:40.380-0800 I NETWORK  [initandlisten] connection accepted from 127.0.0.1:57363 #3 (1 connection now open)
2016-03-11T12:29:40.386-0800 I NETWORK  [conn3] end connection 127.0.0.1:57363 (0 connections now open)

これらの2つのメッセージは、接続を開こうとするとブロックされるPythonプロセスを停止するまで繰り返されます。これで、end connectionの部分がalert unknown ca行の場所に配置されます。以前はmongoログにありました。

デバッグに関する追加情報:

$ openssl verify -CAfile ca.pem client.pem
client.pem: OK
$ openssl verify -CAfile ca.pem server.pem
server.pem: OK
$ openssl x509 -noout -subject -in server.pem
subject= /C=US/ST=Washington/L=Seattle/O=codeMelon/OU=Engineering/CN=server.com/emailAddress=<my-email-address>@gmail.com
$ openssl x509 -noout -subject -in client.pem
subject= /C=US/ST=Washington/L=Seattle/O=codeMelon/OU=Engineering/CN=client.com/emailAddress=<my-email-address>@gmail.com

件名を適切に形成した後の結論は、mongoが接続を受け入れて終了し、Pythonプロセスが、意図した挿入を行わずにブロックしていることです。

どんな助けでも大歓迎です!

11

認証局 を使用して、つまりfile.srlを使用せずに、サーバー/クライアントpemを生成する方法は他にもありますが、この回答は質問をフォローアップすることです。

ほとんどのMongoDBv3.0 +ディストリビューションにSSLのサポートが含まれるようになったことに言及する価値があります。必ず、SSLをサポートするパッケージを選択してください。以下の例は、Ubuntu Linux 14.04で PyMongo v3.2.1 を使用して MongoDB v3.2 でテストされています。単一のマシンがデモ目的でCA、サーバー、およびクライアントのpemファイルを生成した場合。

ca.pemprivkey.pemを生成してみましょう。サブジェクト構造は/C=<Country Name>/ST=<State>/L=<Locality Name>/O=<Organisation Name>/emailAddress=<email>/CN=<Common Name>です。

mkdir ~/ssl
cd ~/ssl
openssl req -out ca.pem -new -x509 -days 3650 -subj "/C=AU/ST=NSW/O=Organisation/CN=root/[email protected]"

server .pemファイルを生成します:

hostname  # note down the value
echo "00" > file.srl # two random digits number
openssl genrsa -out server.key 2048
openssl req -key server.key -new -out server.req -subj  "/C=AU/ST=NSW/O=Organisation/CN=server1/CN=<hostname value>/[email protected]"
openssl x509 -req -in server.req -CA ca.pem -CAkey privkey.pem -CAserial file.srl -out server.crt -days 3650
cat server.key server.crt > server.pem
openssl verify -CAfile ca.pem server.pem

IPアドレスをCN値として使用することもできますが、お勧めしません。 RFC-6125 を参照してください。

それでは、client.pemファイルを生成しましょう。

openssl genrsa -out client.key 2048
openssl req -key client.key -new -out client.req -subj "/C=AU/ST=NSW/O=Organisation/CN=client1/[email protected]"
openssl x509 -req -in client.req -CA ca.pem -CAkey privkey.pem -CAserial file.srl -out client.crt -days 3650
cat client.key client.crt > client.pem
openssl verify -CAfile ca.pem client.pem

.pemファイルを生成した後、 mongod を実行できます。例えば:

mongod --sslMode requireSSL --sslPEMKeyFile ~/server.pem --sslCAFile ~/ca.pem

mongo Shell を使用して接続をテストできます。次に例を示します。

mongo --ssl --sslPEMKeyFile ~/client.pem --sslCAFile ~/ca.pem --Host <server hostname>

正常に接続できたら、PyMongoを試すことができます。例えば:

import ssl 
from pymongo import MongoClient
client = MongoClient(
    '<server hostname>',
    27017,
    ssl=True,
    ssl_certfile='~/client.pem',
    ssl_cert_reqs=ssl.CERT_REQUIRED,
    ssl_ca_certs='~/ca.pem'
 )

または、mongodフラグ -sslAllowInvalidHostnames を使用してlocalhostなどを指定することもできます。

本番環境で使用する場合、MongoDBデプロイメントでは、単一の認証局によって生成および署名された有効な証明書を使用する必要があります。自己署名証明書を使用する場合、通信チャネルは暗号化されますが、サーバーIDの検証は行われません。信頼できる認証局によって署名された証明書を使用すると、MongoDBドライバーがサーバーのIDを確認できるようになります。一般に、ネットワークが信頼されていない限り、自己署名証明書の使用は避けてください。

あなたが役に立つと思うかもしれない他の関連リンク:

19
Wan Bachtiar