wiki:Howtos/ndgOAuthWithModWSGI

Deploying ndg_oauth with mod_wsgi

Instructions for deploying an example client, authorisation server and resource server (with PySAML2 SP). Platform is Ubuntu 11.10

mod_wsgi

Ubuntu provides a package for this but it is built against Python 2.6 whereas the default system Python is 2.7. Download and install against the 2.7 version to be safe.

  1. Install pre-requisites:
    apt-get install python-dev apache2-prefork-dev
    
  2. Download and build
    wget http://modwsgi.googlecode.com/files/mod_wsgi-3.4.tar.gz
    tar zxvf mod_wsgi-3.4.tar.gz
    cd mod_wsgi-3.4
    ./configure
    make
    sudo make install
    
  3. Make a load config file and enable
    cat > /etc/apache2/mods-available/wsgi.load << EOF
    LoadModule wsgi_module /usr/lib/apache2/modules/mod_wsgi.so
    EOF
    
    a2enmod wsgi
    

Python environment

  1. Prerequisites
    apt-get install python-setuptools python-virtualenv xmlsec1
    
  2. Make virtualenv in some suitable location e.g.
    sudo virtualenv /usr/local/contrail_faas
    
  3. Make a requirements text file
    cat > /usr/local/contrail_faas/requirements.txt << EOF
    ndg_oauth_client
    ndg_oauth_server
    argparse
    Beaker
    decorator
    Genshi
    httplib2
    ndg-httpsclient
    Paste
    PasteDeploy
    PasteScript
    pyasn1
    pyOpenSSL
    pysaml2
    python-memcached
    repoze.who
    repoze.who.deprecatedplugins
    WebOb
    wsgiref
    zope.interface
    EOF
    
  4. Activate environment and install packages
    . /usr/local/contrail_faas/bin/activate
    pip install -r requirements.txt
    

Python Configuration files

  1. Make directories for the python client and server copying the bearer token example directories given in the respective packages - ndg.oauth.client.examples.bearer_tok and ndg.oauth.server.examples.bearer_tok. Also include the shared_config/ dirs as these include test PKI files.
  2. Add in the additional config needed for the PySAML2 SP following the config in  http://websvn.ow2.org/listing.php?repname=contrail&path=%2Fbranches%2Fxlab%2Falesc%2Foauth%2F apart from:
    cat /usr/local/contrail_faas/oauth_server/sp_conf.py << EOF
    from os import path
    
    import saml2
    from saml2 import BINDING_HTTP_REDIRECT
    from saml2.saml import NAME_FORMAT_URI
    
    BASE= "https://localhost/oauth-server/"
    HERE_DIR = path.dirname(path.abspath(__file__))
    
    CONFIG = {
        "entityid" : "https://localhost",
        "description": "OAuth authentication",
        "service": {
            "sp":{
                "name" : "Contrail OAuth Auz",
                "endpoints":{
                    "assertion_consumer_service": [BASE],
                    "single_logout_service" : [(BASE+"slo",
                                                BINDING_HTTP_REDIRECT)],
                },
                "required_attributes": ["surname", "givenname",
                                        "edupersonaffiliation"],
                "optional_attributes": ["title"],
                "idp": 
    {
    	 'https://federation.contrail-idp.egi-cloud5.zam.kfa-juelich.de/simplesaml/saml2/idp/metadata.php': {
                      'single_sign_on_service': {
                          saml2.BINDING_HTTP_REDIRECT: 'https://federation.contrail-idp.egi-cloud5.zam.kfa-juelich.de/simplesaml/saml2/idp/SSOService.php',
                          },
                      'single_logout_service': {
                          saml2.BINDING_HTTP_REDIRECT: 'https://federation.contrail-idp.egi-cloud5.zam.kfa-juelich.de/simplesaml/saml2/idp/SingleLogoutService.php',
                          },
                      },
    }
    ,
            }
        },
        "debug" : 1,
        "key_file" : path.join(HERE_DIR, "pki/mykey.pem"),
        "cert_file" : path.join(HERE_DIR, "pki/mycert.pem"),
        "attribute_map_dir" : path.join(HERE_DIR, "attributemaps"),
        'metadata': {
          'local': [path.join(HERE_DIR, "idp-egi-cloud.xml")],
          },
        # -- below used by make_metadata --
        "organization": {
            "name": "Contrail",
            "display_name": [("Contrail","en"),("Contrail","en")],
            "url":"http://www.contrail-project.eu",
        },
        "contact_person": [{
            "given_name":"Ales",
            "sur_name": "Cernivec",
            "email_address": ["ales.cernivec@xlab.si"],
            "contact_type": "technical",
            },
        ],
        "xmlsec_binary":"/usr/bin/xmlsec1",
        "name_form": NAME_FORMAT_URI
    }
    EOF
    
  3. In the repoze_who.ini file config for the OAuth server make sure to use absolute paths by using the here substitution:
    [plugin:saml2auth]
    use = s2repoze.plugins.sp:make_plugin
    saml_conf = sp_conf
    rememberer_name = auth_tkt
    debug = 1
    sid_store = %(here)s/outstanding
    identity_cache = %(here)s/identities
    

Create WSGI scripts

  1. Scripts dir
    mkdir /var/www/wsgi-scripts/
    
  2. Client script
    cat /var/www/wsgi-scripts//oauth-client.wsgi << EOF
    ALLDIRS = [
        '/usr/local/contrail_faas/lib/python2.7/site-packages',
        '/usr/local/contrail_faas/oauth_client'
    ]
    
    import sys 
    import site 
    
    # Remember original sys.path.
    prev_sys_path = list(sys.path) 
    
    # Add each new site-packages directory.
    for directory in ALLDIRS:
      site.addsitedir(directory)
    
    # Reorder sys.path so new directories at the front.
    new_sys_path = [] 
    for item in list(sys.path): 
        if item not in prev_sys_path: 
            new_sys_path.append(item) 
            sys.path.remove(item) 
    sys.path[:0] = new_sys_path 
    
    from paste.deploy import loadapp
    from logging.config import fileConfig
    config_filepath = '/usr/local/contrail_faas/oauth_client/bearer_tok_client_app.ini'
    fileConfig(config_filepath)
    application = loadapp('config:%s' % config_filepath)
    EOF
    
  3. Server script
    cat /var/www/wsgi-scripts/oauth-server.wsgi 
    ALLDIRS = [
        '/usr/local/contrail_faas/lib/python2.7/site-packages',
        '/usr/local/contrail_faas/oauth_server'
    ]
    
    import sys 
    import site 
    
    # Remember original sys.path.
    prev_sys_path = list(sys.path) 
    
    # Add each new site-packages directory.
    for directory in ALLDIRS:
      site.addsitedir(directory)
    
    # Reorder sys.path so new directories at the front.
    new_sys_path = [] 
    for item in list(sys.path): 
        if item not in prev_sys_path: 
            new_sys_path.append(item) 
            sys.path.remove(item) 
    sys.path[:0] = new_sys_path 
    
    from paste.deploy import loadapp
    from logging.config import fileConfig
    config_filepath = '/usr/local/contrail_faas/oauth_server/bearer_tok_server_app.ini'
    fileConfig(config_filepath)
    application = loadapp('config:%s' % config_filepath)
    
    

Apache config WSGI Directives

  1. Prerequisites: working config with SSL enabled
  2. Edit /etc/apache2/sites-available/default-ssl adding:
    	<Directory /var/www/wsgi-scripts>
    		Order allow,deny
    		Allow from all
    	</Directory>
    
    	WSGIDaemonProcess contrail processes=2 threads=15
    	WSGIProcessGroup contrail
    	WSGIScriptAlias /oauth-client /var/www/wsgi-scripts/oauth-client.wsgi
    	WSGIScriptAlias /oauth-server /var/www/wsgi-scripts/oauth-server.wsgi
    

Testing

Restart Apache, enter  https://localhost/oauth-client/ into ab browser and tail the logs to check for errors.