Following on from the proof of concept, I’ve come up with the Guanxi Shibb Kit (GSK). In a nutshell, it’s a separate Sakai portal (/shibb) that acts as a “holding area” for shibboleth users who want to get into a normal Sakai. Think of it as quarantine for users until they can be verified via shibboleth transactions. Once they get their SAML jab, the GSK puts a Sakai name badge on them and sends them off to the main Sakai portal, which is usually /portal. The whole shibboleth process is turned on and off via one setting in sakai.properties, shibb.enabled. If this is set to false then all shibboleth functionality is turned off.
Now, they say a picture is worth a thousand words. In this case it’s worth a few million, so here it is. Click on the image to get a bigger version.

As you can see, normal Sakai users are in no way inconvenienced by their Shibboleth counterparts, lepers that they are. That lot go in the back door, via the /shibb portal, where they are immediately halted, marked as unclean and told to go off and authenticate at their Identity Provider. It’s the Guanxi Guard that does this. What it does is, when it detects an access attempt on the shibb portal, it handshakes with the Engine, which is the Guanxi SAML Engine and tells it that it wants a new session set up. The Engine responds with the WAYF location once it has verified the Guard is who it says it is and the Guard then redirects the user to the WAYF and their Identity Provider (IdP).
The user authenticates at their IdP and the resulting SAML AuthenticationStatement is sent to the Engine, not the Guard. That’s how Guanxi works. It’s a distributed Service Provider, based on secure web services. This means you can have the Engine anywhere and I mean anywhere, not just in the Sakai domain. It can be anywhere on the ‘net. The secure web services and metadata make sure that Engines trust (or don’t trust) Guards. Not cookies. That means you could have one Engine providing SAML services to hundreds of Sakai /shibb portals. All Sakai instances on the planet could use a small set of Guanxi SAML Engines to provide shibboleth services to their Guards in their /shibb portals. But that’s another story.
Once the Engine gets the AuthenticationStatement, it matches up an ID in it with a session that a Guard previously set up with the Engine. The Engine then gets the attributes for the user identified in the AuthenticationStatement by constructing a SAML Attribute Query and sending it to the user’s Attribute Authority (AA). The AA sends the attributes back to the Engine, which forwards them on to the Guard.
Now that the Guard has attributes for the user it can inspect them and apply any policies about getting in to the main Sakai portal. If all is well, the Guard will construct a Pod into which it will bung all the SAML attributes for the user. It then stamps the user’s forehead with a big “OK” and sends them off to the main /portal site via a browser redirect. That’s the user now in Sakai. They’ve been given the green light by /shibb and if /portal needs to know about them it will get access to their info via a couple of federated providers, which we’ll take a look at now.
Although you can turn shibboleth on and off from sakai.properties, you also need a couple of special providers for all this to work. These are:
- FilterUserDirectoryProvider, developed by CARET which “chains” User Directory Providers (UDP) together. If one UDP fails to recognise the user, the next one in the chain is tried. In this way requests for info on a shibboleth user will fail against an LDAP UDP but pass against a Pod UDP.
- FilterGroupProvider, developed by UHI, which “chain” Group Providers (GP) together. If one GP fails to recognise the user, the next one in the chain is tried. In this way requests for info on a shibboleth user will fail against an LDAP GP but pass against a Pod GP.
So what’s a Pod UDP and GP? They’re interfaces onto a collection of Guanxi Pods that hold SAML attributes on users that the /shibb portal has processed and passed. Whereas an LDAP UDP gets it’s info from an LDAP store, a Pod UDP gets it’s info from a Guanxi Pod. The Pod UDP will know how to get the right Pod for the user and will use that to give info on the user to Sakai. Likewise the Pod GP.
Pods can be persisted to the Sakai database so that shibboleth users are “always there” if you want to add them to groups when they’re not logged in to Sakai. However, there’s a caveat to bear in mind. Their persisted presence in Sakai is subject to the Time To Live (TTL) of their SAML attribute assertions. i.e. if their AA states that they are a member of UHI but only for the next 24 hours then their Pod will refuse to acknowledge them after those 24 hours have elapsed and Sakai will have to say goodbye to them. This is all policy for eLearning though. If an AA is only dishing out short lived assertions then it’s no use for eLearning.
And that, dear readers, is a whole different kettle of fish…
This is the Dorain release (Beinn Dorain), one of my favourite mountains in the Central Highlands. This release focuses on the SP with major enhancements to the web services and SSL. The release also contains an updated IdP and SP.
Full details are on the Guanxi Wiki
IdP
- v1.3.0
- Updated org.guanxi.idp.attributors.LDAPAttributor to fix bug if no GuanxiPrincipal was available and also to add support for eduPersonPrincipalName
- Updated WEB-INF/web.xml to put tags in correct order
- Updated org.guanxi.idp.Setup to use BOUNCY_CASTLE_PROVIDER_NAME defined in org.guanxi.common.definitions.Guanxi
- Deleted org.guanxi.idp.Setup
- Moved setup functionality to org.guanxi.idp.SSO.init()
- org.guanxi.idp.SSO now loads on startup to remove manual setup
- Updated org.guanxi.idp.AttributeAuthority to use XMLBeans. Added syphoning of attribute assertions being sent to SP
- Updated org.guanxi.idp.SSO to use XMLBeans
- Added jar versioning support to build.xml and build.properties
SP
- v1.3.0
- Updated org.guanxi.sp.engine.EngineSetup, added new comments and fixed bug where web service couldn’t be installed via ssl. Added new SSL layer probing support to remove need for truststore when setting up the internal web services.
- Updated org.guanxi.sp.guard.GuardSetup, added new comments and fixed bug where web service couldn’t be installed via ssl. Added new SSL layer probing support to remove need for truststore when setting up the internal web services.
- Updated resources/guanxi_sp/index.jsp to remove hard coded http
- Updated org.guanxi.sp.engine.Engine to add the XMLBeans generated Engine config object to the servlet context to allow other parts of the system to use the sam config file
- Updated WEB-INF/config/guanxi-sp-engine.xml, added new Keystore options for secure web services communications
- Updated WEB-INF/guanxi_sp_guard/config/guanxi-sp-guard.xml, added web services trust options for keystore and truststore. Updated Cooke Age to be transient so it goes away when you close the browser.
- Updated org.guanxi.sp.guard.Guard to use XMLBeans for configuration information.
- Updated org.guanxi.sp.engine.Engine to use new Log directory information
- Updated org.guanxi.sp.guard.AttributeConsumer to use new Log directory information
- Updated org.guanxi.sp.engine.CA to use new Log directory information
- Added WEB-INF/guanxi_sp_guard/logs
- Added WEB-INF/guanxi_sp_guard/keystore/guard.jks
- Added WEB-INF/guanxi_sp_guard/truststore/guard.jks
- Updated org.guanxi.sp.guard.GuardHandler, tidied up unused stuff and converted to use XMLBeans for configuration.
- Updated org.guanxi.sp.guard.Guard, refactored to use XMLBeans for configuration and to place the Guard XMLBeans object in the servlet context to share with other parts of the Guard.
- Updated org.guanxi.sp.guard.Guard to transfer new parameters to GuardRequest to fix problems with spring based applications
- Added testsrc/org.guanxi.sp.engine.GuanxiSSLLayerTest, JUnit tests for the SSL layer
- Updated build.xml to not copy logs to WEB-INF for Guard
- Updated org.guanxi.sp.guard.GuardRequest to add support for request attributes to fix problems with spring based applications
- Updated org.guanxi.sp.engine.Engine to fail gracefully if no signature is found on an AuthenticationStatement from an IdP
- Updated org.guanxi.sp.engine.Engine, removed getAttributes(), getGuardNativeMetadata()
- Updated org.guanxi.sp.engine.Engine, init() now loads BouncyCastle security provider and destroy() unloads it. Now creates a self signed keystore if none exists. This is used for secure comms to Guards
- Updated org.guanxi.sp.engine.Engine, modified loadGuardMetadata() to check whether each registered Guard is using HTTPS and if so, to probe it for it’s X509 certificate and add it to the Engine’s truststore.
- Added org.guanxi.sp.engine.WAYFLocation REST service to replace Axis RPC call for getting the WAYF location
- Updated org.guanxi.sp.engine.CA for new Engine metadata
- Added org.guanxi.sp.guard.SessionVerifier REST service to replace Axis RPC call for verifying a Guard session
- Added org.guanxi.sp.Util
- Converted org.guanxi.sp.guard.Guard to use the Engine’s REST WAYFLocation service instead of Axis RPC
- Updated org.guanxi.sp.engine.Engine, now creates it’s own keystore and supports secure communications to Guards
- Updated web.xml for Engine and Guard to remove Axis
- Removed org.guanxi.sp.metadata package as it has been superceded by XMLBeans. Also deleted org.guanxi.sp.engine.MetadataTest
- Removed org.guanxi.sp.engine.EngineSetup, org.guanxi.sp.engine.EngineHandler, org.guanxi.sp.guard.GuardSetup, org.guanxi.sp.guard.GuardHandler as the Engine and Guard now communicate via REST and use auto setup
- Updated org.guanxi.sp.engine.Engine, improved error handling when the trust layer doesn’t recognise entity certificates
- Updated org.guanxi.sp.guard.Podder to redirect using scheme and hostname as it was redirecting to HTTPS if the Guard was using HTTPS
- Updated org.guanxi.sp.guard.Guard to add request scheme and hostname to pod
- Updated org.guanxi.sp.guard.AttributeConsumer to use XMLBeans instead of org.guanxi.common.SOAPUtils for working with SOAP messages
- Added jar versioning support to build.xml and build.properties
- Updated build.xml, added inheritall=”false” to buildDependencies task to fix bug where dependencies were inheriting SP settings
- Updated org.guanxi.sp.guard.Guard to create a default keystore and truststore if they don’t exist
- Updated org.guanxi.sp.engine.Engine to create a default keystore and truststore if they don’t exist
- Updated org.guanxi.sp.engine.CA to get keystore info from xml config file instead of web.xml
- Updated org.guanxi.sp.engine.CA::createSignedCertificateChain() as it was hardcoded to create RSA keys. Now gets key type from config file. Updated to support SHA224WITHECDSA encryption
- Updated WEB-INF/config/guanxi-sp-engine.xml, added KeyType
Core
- 1.0.3
- Updated xsd/guanxi-sp.xsd, added Keystore, KeystorePassword and CertificateAlias elements to the Engine and Guard elements. Added TrustStore, TrustStorePassword to the Guard element This is to allow configuration of secure web services.
- Updated xsd/guanxi-sp.xsd, pdated engineInfoType, replaced WAYFMethod with WAYFLocationService. Added KeyType to Engine.
- Updated xsd/guanxi-idp.xsd, added optional Debug node for idp.xml with optional SypthonAttributeAssertions and SypthonAttributeQueries nodes
Common
- v1.2.9
- Added org.guanxi.common.security.ssl.GuanxiSocketFactory to provide custom keystore and truststore handling for secure web services communication
- Updated org.guanxi.common.definitions.Guanxi, added AxisProperties definitions for secure web services communication. Added ENGINE_CONFIG_OBJECT, GUARD_CONFIG_OBJECT.
- Updated org.guanxi.common.definitions.Logging to split log dirs into Engine and Guard versions as the Guard should log inside WEB-INF/guanxi_sp_guard
- Updated org.guanxi.common.EntityConnection, added getServerCertificates(), disconnect() and javadocs. Added new boolean parameter to the constructor to allow for probing servers for their certificates. This tells EntityConnection to use a special Guanxi TrustManager that allows HTTPS connections in order to inspect the certificate.
- Updated org.guanxi.common.security.ssl.SSL, added new boolean parameter to getTrustManagers(). If this is true then the method will return a special Guanxi TrustManager to allow for probing servers for their certificates.
- Added org.guanxi.common.security.ssl.GuanxiX509ProbingTrustManager to allow probing for server certs via HTTPS.
- Updated org.guanxi.common.AttributeMap to provide mapping to support eduPersonPrincipalName
- Updated org.guanxi.common.Pod to fix bug when adding extra request parameters for non spring applications
- Updated org.guanxi.common.EntityConnection, added getServerCertChain() and getServerCertificate()
- Updated org.guanxi.common.definitions.Guanxi, added BOUNCY_CASTLE_PROVIDER_NAME
- Updated org.guanxi.common.definitions.Guanxi, added new constants to support REST services
- Updated org.guanxi.common.Errors, added GUARD_CERT_PROBE_FAILED and MISSING_PARAM
- Updated org.guanxi.common.security.SecUtils, added createSelfSignedKeystore()
- Updated org.guanxi.common.EntityConnection, PROBING_ON and PROBING_OFF moved from Engine. Added getServerCertChain(), getServerCertificate(), getContentLength(), getContentAsString()
- Updated org.guanxi.common.Pod, added support for request scheme and hostname to fix HTTPS bug when Guard comms are using HTTPS
- Updated org.guanxi.common.Utils, added createNCNameID()
- Updated org.guanxi.common.definitions.Shibboleth, added more namespace and prefix definitions
- Added org.guanxi.common.security.SecUtilsConfig as a configuration object for methods in SecUtils
- Updated org.guanxi.common.security.SecUtils, modified sign() to use SecUtilsConfig
- Added jar versioning support to build.xml and build.properties
- Updated org.guanxi.common.security.SecUtils, added createTrustStore()
gx_lib
- v1.3.4
- Updated guanxibeans.jar with latest schemata
- Added hsqldb v1.8.0.4 for IdP demoing and integration testing
- Updated jsr173_1.0_api.jar and xbean.jar to XMLBeans 2.2.0
WAYF
- v1.2.6
- Updated build.xml to fix xalan bug. xalan-2.4.1.jar was renamed to xalan.jar in gx_lib but not here.
- Updated build.xml to add log4.jar
- Added jar versioning support to build.xml and build.properties
We were at the Orion Mountaineering Club dinner at the weekend and had a mass ascent of the corbett Sgurr nan Eugallt at the head of Loch Hourn. The road over Glen Garry was quite bad with the snow and it was down to one lane at the viewpoint. We’d also had a near miss with a gigantic stag just before Clunie but we were going slow due to the snow and had time to brake and swerve to avoid it. Superb specimen it was too.
Anyway, we made it to the Tomdoun Hotel for the dinner and we all had a mass ascent of Sgurr nan Eugallt. Wading through, in places, waist deep snow. There was even some ice here and there. The amount of snow on the hills was incredible. here’s a pick of Loch Quoich from Spidean Mialach (I think) that a friend took the same day:

As you can see there’s a lot of snow for November in Scotland!
So after dabbling in assembler again, I thought I’d lurch forward a few decades and have a look at C#. I have a load of C++ code that I wrote to interface to Groupwise and create accounts in the postoffices automatically and it’s getting time to think about upgrading it. At the moment it’s an exe invoked via Java so it’s quite slow. I was going to do it as a DLL and keep it in memory while the main Java application was running but I thought it might have uses outside the Java app. Turned out that wasn’t the case and so it’s a slow exe being loaded on every call.
So instead of doing a DLL during the upgrade I took a look at C# to see what it’s about. To play around with it on OS X, I downloaded Mono, which brings .NET to the Mac. The DMG installs Mono in /Library/Frameworks/Mono.framework and it comes with the C# compiler mcs.
I then did a simple hello world in C#:
using System;
namespace HelloNameSpace {
public class HelloWorld {
static void Main(string[] args) {
Console.WriteLine(“Hello World!”);
}
}
}
and compiled it using mcs
mcs HelloWorld.cs
and then ran it using Mono:
mono HelloWorld.exe
and it worked a treat!
As we’ve just got the Listserv mailing list server and it has a C application for sending commands down a pipe, I got all nostalgic and started looking at Axis2 C to build a web service to stick in front of it. Then I thought, why stop at C? So I went right back to my old driver days and got back into assembler. So here’s a Hello World that will run on Linux. I got it from here. Now that I’ve remembered how it works I’m going to try and do a simple web service in assembler!
To compile you’ll need nasm and if you get the error:
/usr/bin/install: cannot create regular file `/usr/local/nasm/bin/nasm’: No such file or directory
set the prefix to /usr/local instead.
Then do:
nasm -f elf helloworld.asm
ld -s -o helloworld helloworld.o
section .data
hello: db ‘Hello world!’,10
helloLen: equ $-hello
section .text
global _start
_start:
mov eax,4
mov ebx,1
mov ecx,hello
mov edx,helloLen
int 80h
mov eax,1
mov ebx,0
int 80h
Well, it was like treading on egg shells but I finally managed to shibb Sakai. At the moment, to be strict, it’s just shibbing the admin workspace as the Guanxi portal will auto log you in based on your email address which it gets from your IdP.
What it means is, as a proof of concept, you can specify a bunch of email addresses, the owners of which can admin your sakai. So how is it done? Well I won’t go into too much detail here as the patient is in transit to Dr. Guanxi’s Shibb Clinic but it was ultra easy in the end.
Normally, to login to Sakai, you go to:
http://groovysite.com/portal
and login as admin. Now, to shibb-in as the admin user, you go to:
http://groovysite.com/shibb/gx
it’s a new shibb portal (portal-shibb) with a Guanxi binding (gx). The /gx servlet is an auto-login servlet. That’s all it does. It checks your email address from the SAML attributes and if it matches, it logs you in and redirects to the main Sakai site on /portal.
The Guanxi SAML Engine is completely separate at the moment. It’s actually running on another server but I’ll add it to the portal in due course. The main action happens in the Guard which is protecting /shibb/gx. Before you get anywhere near the auto-login servler, you’re hooked, spun round and sent off to the WAYF and then your IdP. The SAML Engine then gets your attributes and sends them to the Guard via their web services. The Guard then steps aside and lets you in to /shibb/gx.
The next part is the gx servlet pulls your email address from the headers and logs you in as admin if you’re in the list. Voila, one shibbed Sakai!
The next steps are to remove dependence on request headers and code up a UserDirectoryProvider and GroupProvider to work with the Pod of SAML attributes that are injected into the user’s Sakai session.
Once the providers are done that will remove the restriction on logging in as admin and you’ll be able to login as yourself and use tools in Sakai that you have permissions for, based on your SAML attributes.
So, after much hair pulling and gnashing of teeth, I finally got round my session propagation problem. I’ve created a new Sakai portal, /shibb but not matter where I authenticated, either in charon first, as admin, or as admin in /shibb, the session was never passed between the portals. So logging in using /shibb resulted in the usual login page on charon after the redirect.
Now, I’m using Eclipse, which is probably worst DE on the planet. DE? yes, it’s hardly integrated with anything! So I went into shell mode and did some find dotting and grepping to get into the SessionManager, which eventually led me into the RequestFilter. It then struck me that RequestFilter was never invoked on /shibb and so when it was invoked on /portal, it was finding the cookie but no session. So it was creating a new one, hence the loss of user info in the session created in /shibb.
So I looked at /shibb’s web.xml and DOH! I’d just copied the mercury portal’s web.xml and forgot to change the filter mapping. It was still invoking the request filter for sakai.portal.mercury. I changed it to sakai.portal.shibb and lo and behold, all began working!
So now I can login using code in /shibb and redirect to /portal and the user is still logged in.
Now it’s time to stick a Guanxi Guard in front of /shibb and start coding up some Sakai SAML providers.
So we’ve bought Listserve and I’ve been looking at the tcp application it comes with for sending commands direct to it’s port. It’s written in C so I decided to use Eclipse’s CDT to build and debug it. However, I kept getting this error when debugging:
“No source file named lcmdx.c”
and the breakpoints would never work. I’m used to C/C++ development on Windows so I’ve always used VisualStudio to manage the debug/release builds but now I’m building on OS X and I need to use make. I’ve also never used gdb so after some snuffling about on Google I got rid of the error by building a debug version, doh!
gcc -g -c -v lcmdx.c
Now it works just fine and I can’t get all nostalgic and start coding in C again. Might even add some assembler.
Programming on the islands is never boring. Just up the road at Broadford, the staff saw a couple of otters trying to get into the hospital!
Read about it here