Using the automatic revocation interface

Motivation

If institutions have a large number of issued certificates, revocation of certificates for employees who leave the institution can become a cumbersome process. The automatic revocation interface enables institutions to automate that process by integrating employee management with certificate revocation.

Automatic revocation interface explained in 20 seconds

If you are a subscriber admin, you can upload a X.509 certificate to the portal that will identify the revocation client. The same X.509 certificate can be used by the revocation client to sign XML revocation requests that it sends to Confusa.

Automatic revocation interface step by step

Uploading a certificate identifying the client to the portal

 

  1. Get a certificate for the client. If you can't get a certificate for your client elsewhere, you can create a self-signed one. One way to achieve this is by doing something like
    openssl req -new -newkey rsa:2048 -subj "/C=SE/O=KTH/OU=PDC/CN=Confusa Client hawaii.pdc.kth.se" \
    -out automatic_revocation.pem -keyout automatic_revocation.key -x509 -days 365

  2. Upload the certificate to Confusa. You can find the section for uploading certificates in "subscriber admin" -> "Certificates" -> "Robot"
    Robot menu itemcertificate upload form
  3. If uploading the certificate was successful you should be able to see the certificate in "Subscriber-Admin" -> "Certificates" -> "Robot" -> "List":

Using the revocation functions from a client

The client is identified by using HTTPS certificate client authentication. On top of a connection with HTTPS client authentication that uses the uploaded certificate your revocation application can send HTTP POST calls to https://confusahost.example.org/ri.php.

Simple example code (python)

import time, xml.sax.handler, urllib, urllib2
import Parser
from Timeout import Timeout, TimeoutException
from HTTPSClient import HTTPSClientAuthHandler
import xml.etree.ElementTree as ET

class Confusa_Client:
    def __init__(self, key, cert, url):
        """
        Constructor, set the keypair to use for AuthN and the URL to connect to.

        """
        self.https_client = HTTPSClientAuthHandler(key, cert)
        self.url          = url

    def get_list(self):
        """
        Returns the list of users with valid certificates.

        """
        self.data    = urllib.urlencode({ 'action' : 'cert_list' })
        return self.execute().get_list(True)

    def send_revoke_list(self, eppn_list):
        """
        Send a list of users for which all certificates should be revoked.

        eppn_list is an array, each line with a revokeCert-dictionary entry on the form
        {'eppn' : <name>, 'fulllDN' : <dn> , 'count' : <count>}

        Only eppn will be used, the rest are optional and will be discarded
        """
        # Is list set properly?
        if (not eppn_list or not len(eppn_list) > 0):
            print "Too short list, aborting"
            return

        post = { 'action' : 'revoke_list' }


        # Construct the XML-message
        foundElements = 0
        root = ET.Element("ConfusaRobot")
        root.set("date", time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
        root.set("subscriber", "") # not used, determined from certificate
        root.set("version", "1.0")
        rev = ET.SubElement(root, "revocationList")
        list = ""
        for i in eppn_list:
            if 'uid' in i:
                le = ET.SubElement(rev, "listElement")
                le.set("uid", i['uid'])
                foundElements += 1

        if foundElements ==  0:
            print "No elements found, aborting"
            return

        if foundElements != len(eppn_list):
            print "\nErrors with supplied data, length of list is not equal to number of valid entries"
            print "This may prove to be a minor detail, continuing\n"

        root.set("elementCount", "%d" % foundElements)
        post['list'] = ET.tostring(root)
        self.data = urllib.urlencode(post)
        return self.execute().get_list(False)

    def execute(self, timeout=60):
        """
        execute()

        Connect to the URL and send POST-data.  The returned data will
        be passed to ConfusaParser, and either an array of
        dictionary-entries or None will be returned.

        """
        # Get the result and parse it
        opener  = urllib2.build_opener(self.https_client)
        t = Timeout(timeout)
        try:
            res = opener.open(self.url, self.data)
        except xml.sax._exceptions.SAXParseException:
            t.cancel_timeout()
            return None
        except TimeoutException:
            print "Did not receive a timely answer (%s seconds), aborting" % (timeout)
            return None

        t.cancel_timeout()
        return Parser.Parser(res)

The example code is also available in Confusa's Git tree.

Why isn't this part of Confusa's REST-API?

Because the automatic revocation interface was part of Confusa before the REST-API, we sometimes discuss too little and there is this general lack of time that is plaguing us.