Using M2Crypto with boto – Secure Access to Amazon Web Services

Many companies run services in the Amazon cloud infrastructure, so it makes an attractive target for criminals as well. You need to make sure that you really are talking to the right Amazon servers when you use the cloud services.

boto seems to have emerged as the winner in the scramble to develop Python libraries to deal with Amazon Web Services (AWS). By default, boto will use the stdlib httplib.HTTPSConnection. This is a problem, because the stdlib does not provide secure SSL out of the box. However, boto designers have made it easy to plug in alternative SSL implementations that conform to the httplib.HTTPSConnection interface. M2Crypto provides this in httpslib.HTTPSConnection.

The first step is to get CA certificates that we can use to verify that the Amazon servers we will be talking to have valid certificates issued by trusted certificate authorities.

Amazon offers various services that boto provides access to, so the exact details vary a little bit (namely what connection class to instantiate). I’ll use the SimpleDB as an example, because the first 25 machine hours per month are free so it makes a great test system (you still need to sign up for AWS and provide credit card information).

#!/usr/bin/env python
 
import sys
 
from M2Crypto import httpslib, SSL
from boto.sdb.connection import SDBConnection
 
def https_connection_factory(host, port=None, strict=0, **ssl):
    """HTTPS connection factory that creates secure connections
    using M2Crypto."""
    ctx = SSL.Context('tlsv1')
    ctx.set_verify(SSL.verify_peer | SSL.verify_fail_if_no_peer_cert, depth=9)
    if ctx.load_verify_locations('cacert.pem') != 1:
        raise Exception('No CA certs')
    return httpslib.HTTPSConnection(host, port=port, strict=strict,
                                    ssl_context=ctx)
 
def create_connection(aws_access_key_id, aws_secret_access_key):
    """Create SimpleDB connection."""
    conn = SDBConnection(aws_access_key_id=aws_access_key_id,
                         aws_secret_access_key=aws_secret_access_key,
                         https_connection_factory=(https_connection_factory, ()))
    return conn
 
if __name__ == '__main__':
    # Sample usage
    if len(sys.argv) != 3:
        sys.exit('Usage: %s aws_access_key_id aws_secret_access_key' % sys.argv[0])
 
    conn = create_connection(*sys.argv[1:])
    domain = conn.create_domain('mytest')
    try:
        item, key, value = 'item1', 'key1', 'value1'    
        domain.put_attributes(item, {key: value})
        assert value == domain.get_attributes(item)[key]
    finally:
        conn.delete_domain(domain)
 
    print 'Usage:', conn.get_usage()

The sample application takes your AWS access key and secret access key as parameters, and it assumes cacert.pem file containing the CA certificates is in the same directory. Typically running that application shows that it uses less than 0.006 secondshours of Amazon computing facilities so you could run this application over 15 million4500 times a month without charge.

Update:I mixed up units, which Mocky pointed out; fixed above.

Similar Posts:

2 Comments

  1. Mocky:

    Great info. Small correction:
    the 0.006 box usage is in hours not seconds. So 4500 will use up your free usage tier, not 15 million.

    But that’s only because create domain and delete domain are heavy weight operations, orders of magnitude more expensive than the others. For instance list domains which can weigh in at 0.000007 hours and allow up to 3.5 million per month for free.

  2. Jason H:

    Using M2Crypto with boto – Secure Access to Amazon Web Services Open & Custom Courses, Webinars Learn from our Python Experts

    Free California Service Listing