Friday, 25 June 2010

Introspecting Identity with Yadis

Yadis is a powerful tool for service discovery. It answers the question, given an identity URI, what identity services can I invoke on it?  The Earth System Grid security architecture has OpenID as its core identity service but there are others: MyProxy from the Globus toolkit enables users to obtain a short lived X.509 certificate for SSL based authentication to secured resources.  In addition there is the SAML Attribute Service enabling a client to query attribute information about a given subject.   Locating these services is a problem and this was illustrated in a use case recently: a trusted service in the federation would like to notify a user by e-mail.  The service has their OpenID but it doesn't have access to the usual attributes available through the Attribute Exchange interface - they're not signed in.  How can I query their e-mail address to contact them?

OpenID (v2.0) already supports the Yadis protocol, and its uses is mandatory for ESG OpenID Providers.   If I HTTP GET a user's identity URI, I get a document containing the OpenID Provider endpoint:

Extending this I can include the corresponding MyProxy and the Attribute Service URIs:


<?xml version="1.0"; encoding="UTF-8"?>
<xrds:XRDS xmlns:xrds="xri://$xrds" xmlns="xri://$xrd*($v*2.0)">
  <XRD>
    <Service priority="0">
      <Type>http://specs.openid.net/auth/2.0/signon</Type>
      <Type>http://openid.net/signon/1.0</Type>
      <URI>https://openid.provider.somewhere.ac.uk</URI>
      <LocalID>https://somewhere.ac.uk/openid/PJKershaw</LocalID>
    </Service>
    <Service priority="1">
      <Type>urn:esg:security:myproxy-service</Type>
      <URI>socket://myproxy-server.somewhere.ac.uk:7512</URI>
      <LocalID>https://somewhere.ac.uk/openid/PJKershaw</LocalID>
    </Service>
    <Service priority="20">
      <Type>urn:esg:security:attribute-service</Type>
      <URI>https://attributeservice.somewhere.ac.uk</URI>
      <LocalID>https://somewhere.ac.uk/openid/PJKershaw</LocalID>
    </Service>
  </XRD>
</xrds:XRDS>

The priority attribute for each <Service/> element lets the client know which is the preferred service for authentication. The Attribute Service is of course not an authentication service but I'd argue it has a place here as it is an identity service. [17/03/11 - Note correction for this use case: each service element is in the single XRD element, not many XRD elements each with a single service element as I had before!]

Taking this a step further, I can combine it with MyProxy's provisioning functionality, the ability to provision a client with trusted CA certificates it needs to bootstrap trust.

Given an identity URI, I can:
  1. retrieve the Yadis document
  2. parse the MyProxy server endpoint
  3. retrieve the trust roots to bootstrap trust in the identity services for this identity URI.

Wednesday, 23 June 2010

Earth System Grid Security Architecture Blueprint

We now have a blueprint documented for the ESG security architecture:

http://esg-pcmdi.llnl.gov/esgf/esgf-security-interface-control-documents/esgf-security-interface-control-document-1.0/

The Interface Control Document describes all the interfaces that make up the federated security infrastructure.  This is the product of a lot of collaboration work and discussion.  Given the parellel Java and Python implementations this has been a true test of interoperability.

Thursday, 10 June 2010

Python SAML 2.0 Released

I've been working on a Python implementation of SAML 2.0 for some months now and recently pushed this to the Python repository PyPI.  SAML is an important tool in the Earth System Grid Security architecture that I've been working on and the NERC DataGrid security framework which predates it. It's used for attribute retrieval and authorisation decision queries.  The code focusses on these aspects of the specification.  This example illustrates an client attribute query to an Attribute Authority:


from ndg.saml.saml2.core import (AttributeQuery, SAMLVersion, Issuer, Subject,
                                 NameID, Attribute, XSStringAttributeValue)
from uuid import uuid4
from datetime import datetime

attributeQuery = AttributeQuery()
attributeQuery.version = SAMLVersion(SAMLVersion.VERSION_20)
attributeQuery.id = str(uuid4())
attributeQuery.issueInstant = datetime.utcnow()

attributeQuery.issuer = Issuer()
attributeQuery.issuer.format = Issuer.X509_SUBJECT
attributeQuery.issuer.value = '/O=NDG/OU=BADC/CN=PolicyInformationPoint'
                
attributeQuery.subject = Subject()  
attributeQuery.subject.nameID = NameID()
attributeQuery.subject.nameID.format = NameID.X509_SUBJECT
attributeQuery.subject.nameID.value = '/O=NDG/OU=BADC/CN=PhilipKershaw'

# special case handling for 'LastName' attribute
emailAddressAttribute = Attribute()
emailAddressAttribute.name = "urn:esg:email:address"
emailAddressAttribute.nameFormat = "%s#%s" % (
                                XSStringAttributeValue.TYPE_NAME.namespaceURI,
                                XSStringAttributeValue.TYPE_NAME.localPart)

emailAddress = XSStringAttributeValue()
emailAddress.value = 'pjk@somewhere.ac.uk'
emailAddressAttribute.attributeValues.append(emailAddress)

attributeQuery.attributes.append(emailAddressAttribute)

# Convert to ElementTree representation
from ndg.saml.xml.etree import AttributeQueryElementTree, prettyPrint

elem = AttributeQueryElementTree.toXML(attributeQuery)

# Serialise as string
xmlOut = prettyPrint(elem)
print(xmlOut)



The XML representation and serialisation is independent of the core code. The ndg.saml.xml.etree ElementTree representation comes with the rest of the code but it would be straightforward to add an adaptor for another Python XML package such as 4Suite-XML.

Here's the serialised output:


<samlp:attributequery id="1c15e748-0f74-41f1-848c-1fbdfeef2a06" issueinstant="2010-06-01T13:19:50.690263Z" version="2.0" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol">
    <saml:issuer format="urn:oasis:names:tc:SAML:1.1:nameid-format:x509SubjectName" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">/O=NDG/OU=BADC/CN=PolicyInformationPoint</saml:issuer>
    <saml:subject xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">
        <saml:nameid format="urn:oasis:names:tc:SAML:1.1:nameid-format:x509SubjectName">/O=NDG/OU=BADC/CN=PhilipKershaw</saml:nameid>
    </saml:subject>
    <saml:attribute name="urn:esg:email:address" nameformat="http://www.w3.org/2001/XMLSchema#string" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">
        <saml:attributevalue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">pjk@somewhere.ac.uk</saml:attributevalue>
    </saml:attribute>
</samlp:attributequery>


More to follow - including client/server SOAP bindings - as I migrate the SAML specific code out of the NERC DataGrid security package.