Share the Knowledge
RSS icon Home icon
  • How to use client certificate authentication with Suds

    Posted on July 15th, 2011 webmaster No comments         Print 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 client
    

    His 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

    Posted on July 14th, 2011 webmaster 1 comment         Print Print

    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

    Posted on July 10th, 2011 webmaster 1 comment         Print Print

    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:

    1. Go to Control Panel -> Programs.
    2. Under Programs and Features, click Turn Windows features on or off.
    3. Check Telnet Client and click OK.

    Source: http://www.fettesps.com/windows-7-enable-telnet/