2016-04-05 8 views
-1

ほとんどのコンテンツをローカルデータベースに保持するWebサーバーがありますが、ユーザー情報を取得するためにバックエンドディレクトリサービスに問い合わせる必要があります。ディレクトリクエリはスタンドアロン操作として正常に動作しますが、Webサーバーがクエリを実行すると、sslはエラーを返します。Apache/mod_sslは2層操作をサポートできますか?

サーバーはCentOS 7-2.1511/Django 1.9.3/PostgreSQL 9.2.15/Apache 2.4.6-40/mod_ssl 1:2.4.6-40/OpenSSL 1:1.0.1/Python 3.4.3に基づいています。 Apacheはmod_sslを使用してクライアント(ブラウザ)からhttps:要求を提供していますが、Pythonのssl.pyが同じエンジンを使用してhttps:要求をディレクトリサーバーに送信すると仮定しています。 Python SSLは、その実装はOpenSSLに基づいていると言います。 Yumは、明らかにmod_sslの依存関係を一覧表示できませんが、インストールされているバージョンのopensslも使用していると仮定します。

次のコードは、(SSL_CLIENT_CERTから抽出された)ユーザーの識別名を取得し、RESTfulなインターフェースを使用して、ユーザーの属性のディレクトリサーバーを照会します:

import requests, urllib 

URL = 'https://example.com/rest/user_info/' 

def get_user_info(dn) 
    query = URL + urllib.parse.quote(dn) 
    return requests.get(query, cert=('server.crt', 'server.key'), 
         verify='ca_bundle.crt').json() 

私は、ユーザーApacheなどのサーバー上で実行していた場合それはOSERを発生させ、

$ python 
>>> import auth 
>>> dn='cn=Me,o=Company,c=US' 
>>> attr = auth.get_user_info(dn) 

しかし、Apacheが同じDNと同じ関数を呼び出すとき、それはWSGIスクリプト(views.py)だから:サーバーのWSGIディレクトリには、ルーチンが正しくのdict含むユーザ属性を返します。 ROR:

OSError(0, 'Error') 
Line 810, /lib64/python3.4/ssl.py 

803 def do_handshake(self, block=False): 
804  """Perform a TLS/SSL handshake.""" 
805  self._check_connected() 
806  timeout = self.gettimeout() 
807  try: 
808   if timeout == 0.0 and block: 
809    self.settimeout(None) 
810   self._sslobj.do_handshake() 

OpenSSLのための提案として、私はロックの研究が開始されます(私はこれらのエラーを引き起こしてしまう何かを考えることができないので)が、バックエンドのクエリのためにSSLを使用してウェブサーバがにISNと信じるのは難しいですすでによく旅された道です。質問:

  1. これらのエラーの原因として、マルチスレッド/ロック/リエントラントが正しいツリーを吠えていますか?
  2. すでにWebサーバーとバックエンドの接続にSSLを使用した例はありますか?
+0

私の目の前で最初に起こったことは、証明書ファイルに相対pathesを使用していることです。 Apache環境では、作業ディレクトリが異なる場合があります。 –

+0

良い考えですが、実際に実行しているサンプルコードを単純化しました。私の作業ディレクトリは、サーバ(Djangoアプリディレクトリ '/ srv/django/myapp')上で動作するコードと同じで、SERVER_CERT、SERVER_KEY、CA_BUNDLEの絶対パス変数があります。 Apache仮想ホストWSGIDaemonコマンドと私のコマンドライン実験で使用されるサーバー上にPython仮想環境が1つあります。私はユーザーの下で実行しています:group apache:apache。 – Dave

答えて

0

私はあきらめます。以下は、美しさと効率の両方を犠牲にして、確実に機能します。最初にrequestsクエリを試行し、それが爆発した場合は、サブプロセスでpuntを呼び出してwgetを呼び出します。インラインリクエストが失敗したかどうかをページビューに知らせるメタアイテム$methodを返します。

def get_user_info(dn, sub=True, ttl=300): 
    query = URL + urllib.parse.quote(dn) 
    try: 
     info = requests.get(query, cert=(SERVER_CERT, SERVER_KEY), 
          verify=CA_CERT).json() 
     info['$method'] = 'requests' 
     return info 
    except OSError: 
     if sub: 
      args = ['wget', '-O', '-', 
       '--certificate=' + SERVER_CERT, 
       '--private-key=' + SERVER_KEY, 
       query] 
      bytes = subprocess.check_output(args, timeout=5) 
      info = json.loads(bytes.decode(encoding='utf-8')) 
      info['$method'] = 'subprocess' 
      return info 
     else: 
      raise 

OpenSSLがグローバル変数の代わりにコンテキストを使用していれば、確かにいいです。

関連する問題