pythonsslcertificatecherrypypyamf

Where (at which point in the code) does pyAMF client accept SSL certificate?


I've set up a server listening on an SSL port. I am able to connect to it and with proper credentials I am able to access the services (echo service in the example below)

The code below works fine, but I don't understand at which point the client accepts the certificate

Server:

import os.path
import logging
import cherrypy
from pyamf.remoting.gateway.wsgi import WSGIGateway

logging.basicConfig(
    level=logging.DEBUG,
    format='%(asctime)s %(levelname)-5.5s [%(name)s] %(message)s'
)

def auth(username, password):
    users = {"user": "pwd"}
    if (users.has_key(username) and users[username] == password):
            return True
    return False

def echo(data):
   return data

class Root(object):
    @cherrypy.expose
    def index(self):
            return "This is your main website"

gateway = WSGIGateway({'myservice.echo': echo,}, logger=logging, debug=True, authenticator=auth)

localDir = os.path.abspath(os.path.dirname(__file__))
CA = os.path.join(localDir, 'new.cert.cert')
KEY = os.path.join(localDir, 'new.cert.key')
global_conf = {'global': {'server.socket_port': 8443,
                      'environment': 'production',
                      'log.screen': True,
                      'server.ssl_certificate': CA,
                      'server.ssl_private_key': KEY}}

cherrypy.tree.graft(gateway, '/gateway/')
cherrypy.quickstart(Root(), config=global_conf)

Client:

import logging
from pyamf.remoting.client import RemotingService

logging.basicConfig(
    level=logging.DEBUG,
    format='%(asctime)s %(levelname)-5.5s [%(name)s] %(message)s'
)

client = RemotingService('https://localhost:8443/gateway', logger=logging)
client.setCredentials('user', 'pwd')

service = client.getService('myservice')
print service.echo('Echo this')

Now, when I run this, it runs OK, the client log is below:

2010-01-18 00:50:56,323 INFO  [root] Connecting to https://localhost:8443/gateway
2010-01-18 00:50:56,323 DEBUG [root] Referer: None
2010-01-18 00:50:56,323 DEBUG [root] User-Agent: PyAMF/0.5.1
2010-01-18 00:50:56,323 DEBUG [root] Adding request myservice.echo('Echo this',)
2010-01-18 00:50:56,324 DEBUG [root] Executing single request: /1
2010-01-18 00:50:56,324 DEBUG [root] AMF version: 0
2010-01-18 00:50:56,324 DEBUG [root] Client type: 0
2010-01-18 00:50:56,326 DEBUG [root] Sending POST request to /gateway
2010-01-18 00:50:56,412 DEBUG [root] Waiting for response...
2010-01-18 00:50:56,467 DEBUG [root] Got response status: 200
2010-01-18 00:50:56,467 DEBUG [root] Content-Type: application/x-amf
2010-01-18 00:50:56,467 DEBUG [root] Content-Length: 41
2010-01-18 00:50:56,467 DEBUG [root] Server: PyAMF/0.5.1 Python/2.5.2
2010-01-18 00:50:56,467 DEBUG [root] Read 41 bytes for the response
2010-01-18 00:50:56,468 DEBUG [root] Response: <Envelope amfVersion=0 clientType=0>
 (u'/1', <Response status=/onResult>u'Echo this'</Response>)
</Envelope>
2010-01-18 00:50:56,468 DEBUG [root] Removing request: /1
Echo this

The line 2010-01-18 00:50:56,467 DEBUG [root] Read 41 bytes for the response looks suspicious, since the response is too short (the certificate is ~1K) and I'd expect the cert transfer to be in the debug log.

Question: At which point does the client accept the certificate? Where would it be stored by default? Which config parameter sets the default location?


Solution

  • PyAMF uses httplib under the hood to power the remoting requests. When connecting via https://, httplib.HTTPSConnection is used as the connection attribute to the RemotingService.

    It states in the docs that (in reference to HTTPSConnection):

    Note: This does not do any certificate verification

    So, in answer to your question certificates are basically ignored, even if you supply key_file/cert_file arguments to connection.

    The actual ignoring is done when the connect method is called - when the request is actually made to the gateway ..

    [root] Sending POST request to /gateway

    The Read 41 bytes for the response is the unencrypted http response length.

    This answer may not contain all the info you require but should go some way to explaining the behaviour you're seeing.