-
How to use client certificate authentication with Suds
Posted on July 15th, 2011 No comments
Print
This is related to my last post. I was finally able to communicate to an SSL-enabled SOAP service with my computer behind a proxy but then ran into another problem: certificate-based authentication.
Suds actually doesn’t support certificate authentication directly, but fortunately someone created a custom transport for it: http://stackoverflow.com/questions/6277027/suds-over-https-with-cert
I tried his code but then ran into connection issues again, I had to modify it a little bit to include the proxy settings in the transport. Here’s the slightly modified code, I basically just added a proxy handler to his transport:
import urllib2 as u2 from suds.client import Client from suds.transport.http import HttpTransport, Reply, TransportError import httplib class HTTPSClientAuthHandler(u2.HTTPSHandler): def __init__(self, key, cert): u2.HTTPSHandler.__init__(self) self.key = key self.cert = cert def https_open(self, req): # Rather than pass in a reference to a connection class, we pass in # a reference to a function which, for all intents and purposes, # will behave as a constructor return self.do_open(self.getConnection, req) def getConnection(self, host, timeout=300): return httplib.HTTPSConnection(host, key_file=self.key, cert_file=self.cert) class HTTPSClientCertTransport(HttpTransport): def __init__(self, key, cert, proxy_settings=None, *args, **kwargs): HttpTransport.__init__(self, *args, **kwargs) self.key = key self.cert = cert self.proxy_settings = proxy_settings def u2open(self, u2request): """ Open a connection. @param u2request: A urllib2 request. @type u2request: urllib2.Requet. @return: The opened file-like urllib2 object. @rtype: fp """ tm = self.options.timeout https_client_auth_handler = HTTPSClientAuthHandler(self.key, self.cert) # Add a proxy handler if the proxy settings is specified. # Otherwise, just use the HTTPSClientAuthHandler. if self.proxy_settings: proxy_handler = u2.ProxyHandler(self.proxy_settings) url = u2.build_opener(proxy_handler, https_client_auth_handler) else: url = u2.build_opener(https_client_auth_handler) url = u2.build_opener() if self.u2ver() < 2.6: socket.setdefaulttimeout(tm) return url.open(u2request) else: return url.open(u2request, timeout=tm) # Test # if __name__ == '__main__': key= r'D:\key_nopass.pem' cert = r'D:\cert.pem' proxy_settings = {'https': 'http://user:password@host:port'} transport = HTTPSClientCertTransport(key, cert, proxy_settings) service_url = 'https://services.domain.com/test/hello.wsdl' client = Client(service_url, transport=transport) print clientHis code also only supports certificates/keys in PEM format so you may need to convert your client certificate. In our case, we were issued a PKCS#12 certificate and we had to extract the key and certificate to PEM format using OpenSSL:
Extract the key:
openssl.exe pkcs12 -nocerts -in ClientCert.p12 -out key.pem
Extract the certificate:
openssl.exe pkcs12 -clcerts -nokeys -in ClientCert.p12 -out cert.pem
You may also want to remove the passphrase from the key:
openssl.exe rsa -in key.pem -out key_nopass.pem
-
How to connect to a SOAP-based web service with Suds over a proxy that requires authentication
I’m writing a small Python program to connect to a SOAP-based web service using Suds and just ran into an issue with authenticating to our proxy server. I’m able to connect fine if the web service runs on http, but the web service we need to connect to uses https and the urllib2 module threw an error:
urllib2.URLError: <urlopen error Tunnel connection failed: 407 Proxy Authentication Required>
The solution in my case is to upgrade to a newer patch version of Python 2.6 (I upgraded mine to 2.6.6), it looks like the older urllib2 module that I was using didn’t support this scenario as mentioned here, so make sure first that you have at least Python 2.6.4 before trying the sample code below:
from suds.client import Client service_url = 'https://services.domain.com/test/hello.wsdl' proxy_settings = dict(http='http://user:password@host:port', https='http://user:password@host:port') client = Client(service_url, proxy=proxy_settings) print client -
How to enable Telnet on Windows 7
We have a computer at work that runs on Windows 7 and I needed to check whether it can connect to our internal SMTP server so I can use it to send emails. The quickest way to do this is to telnet to the SMTP server on port 25 but it turned out telnet is disabled/not installed by default on Windows 7. It gave the message “‘telnet’ is not recognized as an internal or external command, operable program or batch file.”
Here’s how to enable it:
- Go to Control Panel -> Programs.
- Under Programs and Features, click Turn Windows features on or off.
- Check Telnet Client and click OK.


Recent Comments