« Trac 0.11 rc1 -> Trac0.11.1へのアップデート | Main | PYTHON_EGG_CACHE »

2008.09.25

Pythonでxmlrpc

 普段はJavaでTrac XML-RPC Pluginにアクセスしているのですが、どうせならPythonだけで完結できるように・・・ってことで、Pythonを用いてアクセスしてみるテスト。

 単純にアクセスするだけであれば、実はすごく簡単。

import xmlrpclib
srcServer = xmlrpclib.ServerProxy('http://hostname/trac/test/xmlrpc')
srcTicket = srcServer.ticket.get(1)

って感じで、実行すると、チケット#1の内容を取得することができます。Basic認証が必要な場合は、
srcServer = xmlrpclib.ServerProxy('http://username:password@hostname/trac/test/login/xmlrpc')

となります。SSLでの通信も、単純にプロトコルをhttpsにするだけで問題なく行えます。
srcServer = xmlrpclib.ServerProxy('https://username:password@hostname/trac/test/login/xmlrpc')

Pythonのhttps通信では、サーバ証明書のチェックは特に行っていないようで、自己署名証明書等を用いた場合でも特にエラー等は出たりしないようです(Python2.5.1で動作確認)。

 なお、標準状態では、SSLクライアント証明書を利用したXML-RPCアクセスはできないようです。ただ、PythonのhttplibのHTTPSConnectionはSSLクライアント証明書を利用できるようなので、方法はあるはず・・・。

【普通にSSLクライアント証明書を用いてアクセス】
p12形式のファイルだと使用できないとのことなので、

openssl pkcs12 -nodes -in someclient.p12 -out someclient.pem

で変換しておきます。なお、-nodesでパスワードも除去していますので、取り扱いには注意が必要となります。証明書ファイルを用いて、
import httplib
h = httplib.HTTPSConnection('hostname',443,'someclient.pem','someclient.pem'))
h.connect()
h.request('GET','/')
response = h.getresponse()
print response.read()

のような感じでアクセスできるようになります。

【SSLクライアント証明書を用いてXML-RPC】
SSLクライアント証明書が必要となるところにアクセスした時のトレースを見たところ、内部的にはhttplibを利用しているようです。となると、httplibを用いたhttps通信においてはクライアント証明書を使用することができるので、xmlrpclibでも実現は可能なはず。

ってことで、いろいろと試行錯誤してできたパッチがこんな感じ(python2.5.1のxmlrpclib.pyに対するパッチです)。

@@ -1346,6 +1346,10 @@
     """Handles an HTTPS transaction to an XML-RPC server."""

     # FIXME: mostly untested
+    def __init__(self, use_datetime=0,key_file=None,cert_file=None):
+        self._use_datetime = use_datetime
+        self._key_file = key_file
+        self._cert_file = cert_file

     def make_connection(self, host):
         # create a HTTPS connection object from a host descriptor
@@ -1359,7 +1363,7 @@
                 "your version of httplib doesn't support HTTPS"
                 )
         else:
-            return HTTPS(host, None, **(x509 or {}))
+            return HTTPS(host, None, self._key_file, self._cert_file)

##
# Standard server proxy. This class establishes a virtual connection
@@ -1401,7 +1405,7 @@
     """

     def __init__(self, uri, transport=None, encoding=None, verbose=0,
-                 allow_none=0, use_datetime=0):
+                 allow_none=0, use_datetime=0, key_file=None, cert_file=None):
         # establish a "logical" server connection

         # get the url
@@ -1415,7 +1419,7 @@

         if transport is None:
            if type == "https":
-                transport = SafeTransport(use_datetime=use_datetime)
+                transport = SafeTransport(use_datetime=use_datetime, key_file=key_file, cert_file=cert_file)
             else:
                 transport = Transport(use_datetime=use_datetime)
         self.__transport = transport

上記のパッチを適用すると、

srcServer = xmlrpclib.ServerProxy('https://username:password@hostname/trac/test/login/xmlrpc',None,None,0,0,0,'someclient.pem','someclient.pem')

のような感じでServerProxyを作成するとSSLクライアント証明書が必要となるところへもアクセスできるようになりました(^^)。

http://bugs.python.org/issue1581 xmlrpclib.ServerProxy() doesn't use x509 dataが関連してそうな内容ですが、これによるとx509への対応はPython2.6で対応予定? なお、そこに添付されているパッチの内容を見ても、よくわかりませんでした・・・(汗

|

« Trac 0.11 rc1 -> Trac0.11.1へのアップデート | Main | PYTHON_EGG_CACHE »

Subversion・Trac・etc.」カテゴリの記事

Comments

Post a comment



(Not displayed with comment.)


Comments are moderated, and will not appear on this weblog until the author has approved them.



TrackBack


Listed below are links to weblogs that reference Pythonでxmlrpc:

« Trac 0.11 rc1 -> Trac0.11.1へのアップデート | Main | PYTHON_EGG_CACHE »