使用 Python SSL

Python SSL 程式庫的 2.7 版已遭淘汰。請改用最新版本 (目前為 2.7.11)。

App Engine 透過 SSL 函式庫支援 Python 2.7 運行時的原生 Python SSL 函式庫,您必須將函式庫新增至應用程式中。

指定 SSL 函式庫

如要使用原生 Python SSL,請在應用程式的 app.yaml 中,為 libraries 設定指定 ssl,藉此啟用這項功能。您應使用最新版本的程式庫,目前為2.7.11 版。此版本支援 TLS 的 1.0、1.1 以及 1.2 版本,並且對應於 Python 2.7.11 及後續版本的 SSL 版本。

libraries:
- name: ssl
  version: latest

提供授權憑證

若需執行 SSL 交握,您必須擁有包含串連憑證授權之憑證的檔案。您可以上傳自己的檔案,或使用 App Engine 提供的檔案:/etc/ca-certificates.crt

執行 SSL 交握

Python 2.7 wrap_socket 方法會採用兩個檔案名稱參數,其中包含用戶端的金鑰和憑證。在 App Engine 的環境中,此方法有所限制,因為應用程式無法寫入檔案,以動態提供不同的金鑰和憑證。如要解決這項限制,ssl.wrap_socket 方法的 certfilekeyfile 參數可以是「類似檔案」的物件,讓應用程式能以其他方式儲存憑證和金鑰,而不只是上傳的應用程式檔案。 (「類檔案」物件是具有「讀取」方法的物件,將整個憑證以字串型態傳回)。

  # 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

App Engine 實作的 wrap_socket 方法包含必要參數 ca_certs,用於指定包含串連憑證授權單位憑證的特殊檔案。

驗證憑證

您的應用程式需要驗證憑證,以預防安全漏洞,例如「攔截式」攻擊。

現在說明一下操作方式:

  1. 編輯 app.yaml 檔案,新增設為 1 的環境變數 PYTHONHTTPSVERIFY

     env_variables:
       PYTHONHTTPSVERIFY: 1
    
  2. 重新部署您的應用程式。

除了在 app.yaml 中指定憑證驗證,您也可以在成功執行 SSL 交握後,明確呼叫 SSL 程式庫進行驗證,如下所示:

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

上述程式碼使用 match_hostname 功能,該功能從 Python 3.2 回溯移植,成為 App Engine Python 2.7.11 SSL 模組的一部分。此呼叫確保對等方提供的憑證會與對等方憑證中的一個指定主機相符。

在 dev_appserver 上執行

您可以使用 urlfetch API 發出 HTTPS 請求,使用 httplib 的 Dev_server 憑證驗證行為所用的 urlfetch,與生產 App Engine 環境的相同。Dev_appserver 不支援使用通訊端的請求。