Python SSL の使用

Python SSL ライブラリのバージョン 2.7 は非推奨になっています。代わりに、最新バージョン(現在は 2.7.11)を使用してください。

App Engine は、Python 2.7 ランタイムでの SSL ライブラリを介したネイティブ Python SSL ライブラリをサポートしています(ユーザーは使用するアプリにライブラリを追加する必要があります)。

SSL ライブラリを指定する

ネイティブ Python SSL を使用するには、アプリケーションの app.yamllibraries 構成に ssl を指定して有効にする必要があります。必ず最新バージョン(現在はバージョン 2.7.11)のライブラリを使用してください。このバージョンは TLS バージョン 1.0、1.1、1.2 をサポートし、Python 2.7.11 以降の SSL バージョンに対応しています。

libraries:
- name: ssl
  version: latest

認証局の証明書を指定する

SSL handshake を行うには、関連付けられた認証局の証明書が含まれたファイルが必要です。アプリケーションと一緒に独自のファイルをアップロードすることも、App Engine から提供されるファイル(/etc/ca-certificates.crt)を使用することもできます。

SSL handshake を実行する

python 2.7 wrap_socket メソッドは、クライアントのキーと証明書が含まれた 2 つのファイル名パラメータをとります。App Engine 環境では、アプリケーションが別のキーと証明書を動的に提供するようにファイルに書き込むことができないため、これが限定されます。この制約を回避するには、ssl.wrap_socket メソッドの certfile パラメータと keyfile パラメータを「ファイルに似た」オブジェクトにして、アップロードしたアプリケーション ファイル以外の方法でアプリケーションが証明書とキーを保存できるようにします(「ファイルに似た」オブジェクトとは、証明書全体を文字列として返す「read」メソッドを持つオブジェクトのことです)。

  # Example of a dynamic key and cert.
  datastore_record_k = ndb.Key('Employee', 'asalieri', 'Address', 1)
  datastore_record = datastore_record_k.get()
  key_str = datastore_record.key_str
  cert_str = datastore_record.cert
  ssl_server = ssl.wrap_socket(server_sock,
                              server_side=False,
                              keyfile=StringIO.StringIO(key_str),
                              certfile=StringIO.StringIO(cert_str),
                              cert_reqs=ssl.CERT_REQUIRED,
                              ssl_version=ssl.PROTOCOL_SSLv23,
                              ca_certs=CERTIFICATE_FILE)

ssl_version パラメータを指定する必要はありません。指定しない場合、2.7.11 ライブラリではデフォルトの PROTOCOL_SSLv23 が使用されます。PROTOCOL_TLSv1PROTOCOL_TLSv1_1PROTOCOL_TLSv1_2 も指定できます。

wrap_socket メソッドの App Engine での実装には必須パラメータ ca_certs が含まれます。これは、関連付けられた認証局証明書が含まれる特別なファイルを指定するのに使用されます。

証明書を検証する

アプリでは、「中間者」攻撃などの特定のセキュリティ脆弱性を防ぐために証明書の検証が必要になります。

手順は次のとおりです。

  1. app.yaml ファイルを編集して、環境変数 PYTHONHTTPSVERIFY1 に設定します。

     env_variables:
       PYTHONHTTPSVERIFY: 1
    
  2. アプリを再デプロイします。

app.yaml に証明書の検証を指定する代わりに、SSL handshake が正常に行われた後で次のように SSL ライブラリを明示的に呼び出して検証を行うこともできます。

    ssl.match_hostname(ssl_server.getpeercert(), 'a.hostname.com')

上記のコードでは match_hostname 機能を使用しています。この機能は、Python 3.2 からバックポートされ、App Engine の Python 2.7.11 SSL モジュールの一部となっています。この呼び出しにより、ピアによって渡された証明書がピアの証明書に指定されているホストのいずれかに一致することが確認されます。

dev_appserver を使用する

HTTPS リクエストは urlfetch API を使用して発行できます。urlfetch を使用した httplib による Dev_server の証明書の検証動作は、App Engine 本番環境と同一です。dev_appserver では、ソケットを使用したリクエストはサポートされません。