This is a bit of a followup to my last post on Kerberos-based federation so this post will make a lot more sense if you read that one. Kerberos didn’t really suit my needs because there’s no real web sign on to speak of, so getting hold of a Kerberos ticket in a friendly way on non-Windows platforms is problematic. The answer to this is to use SAML,which has some good support in Keystone, and more to come.
Prerequisites
I’m not going to go into too much detail of how SAML works here, and assume you know a little, or are prepared to infer things as you go from this post. There’s more detailed information in the Shibboleth wiki but importantly you must know the concept of an identity provider (which holds authentication data) and a service provider (which protects a resource).
In this example. I’m going to use Shibboleth as a service provider, and the testshib.org service as an identity provider.
As before, I am doing all this on Ubuntu so if you’re on a different OS you’ll have to tweak things.
Important!
Shibboleth is quite solid but its logs and error messages are extremely cryptic and not particularly helpful. There are quite a few gotchas, and it simply doesn’t tell you exactly what went wrong. The main one is that all the entityID configs for Shibboleth and in Keystone MUST match up, and Apache must have its ServerName configured to the matching domain name.
Apache config
You will need the shibboleth module for Apache so go ahead and install it:
sudo apt-get install libapache2-mod-shib2
That will enable the module, so you don’t need to explicity do that. You’ll also have a shibd daemon running after installation.
Inside your Virtualhost block in /etc/apache2/sites-enabled/keystone, you’ll need to add some Shibboleth config:
<Virtualhost *:5000> ... WSGIScriptAliasMatch ^(/v3/OS-FEDERATION/identity_providers/.*?/protocols/.*?/auth)$ /var/www/keystone/main/$1 <Location ~ "/v3/auth/OS-FEDERATION/websso/saml2"> ShibRequestSetting requireSession 1 AuthType shibboleth # ShibRequireAll On # Enable this if you're using 12.043 ShibRequireSession On ShibExportAssertion Off Require valid-user </Location> </Virtualhost> <VirtualHost *:80> <Location /Shibboleth.sso> SetHandler shib </Location> </VirtualHost>
You also need to make sure that your Apache knows what its server name is. If it complains that it doesn’t when you restart it, add an explicit ServerName directive that matches the exact domain name that you are going to give to testshib, shortly.
Now restart Apache.
sudo service apache2 restart
Testshib config
Visit http://testshib.org/ and follow the instructions carefully. It will eventually generate some Shibboleth configuration for your service provider, which you need to save as /etc/shibboleth/shibboleth2.xml
If you take a look in the config, you’ll see three main important things.
<ApplicationDefaults entityID="<your service provider ID>" REMOTE_USER="eppn">
You need to remove REMOTE_USER entirely as this causes Keystone to do the wrong thing.
Inside the ApplicationDefaults you’ll see:
<SSO entityID="https://idp.testshib.org/idp/shibboleth"> SAML2 SAML1 </SSO>
This is the part that tells Shibboleth what the ID of the identity provider is. Further down the file you’ll see something like:
<MetadataProvider type="XML" uri="http://www.testshib.org/metadata/testshib-providers.xml" backingFilePath="testshib-two-idp-metadata.xml" reloadInterval="180000" />
It tells Shibboleth where to get the IdP’s metadata, which describes how to interact with it (mainly URLs and signing keys).
These three parts are the main parts of the config that describe the remote IdP. If you change the IdP for a different one, it’s unlikely you’ll need to edit anything else.
Keystone config
As in the Kerberos post, you need to enable some things in the keystone.conf. Since I wrote that post, I’ve seen that federation is enabled by default in Kilo, so there’s much less to do now. Basically:
- Configure trusted_dashboard,e.g. trusted_dashboard = http://$HOSTNAME/auth/websso/
- Add saml2 to the list of protocols:
[auth] saml2 = keystone.auth.plugins.mapped.Mapped [saml2] remote_id_attribute = Shib-Identity-Provider
- Copy the callback template to the right place:
cp /opt/stack/keystone/etc/sso_callback_template.html /etc/keystone/
- Create the federation database tables if you haven’t already:
keystone-manage db_sync --extension federation
Keystone mapping data configuration
As before, we have to use the v3 API for federation. If you have sourced the credentials file already, you can just do two more environment variables:
export OS_AUTH_URL=http://$HOSTNAME:5000/v3 export OS_IDENTITY_API_VERSION=3
You may remember from the Kerberos post that we need a mapping file. The mapping used for kerberos can be re-used for this SAML authentication, here it is:
[ { "local": [ { "user": { "name": "{0}", "domain": {"name": "Default"} } }, { "group": { "id": "GROUP_ID" } } ], "remote": [ { "type": "REMOTE_USER" } ] } ]
Save this as a file called add-mapping.json. Â Although it can be re-used from before, I’ll re-add it here for completeness:
openstack group create samlusers openstack role add --project demo --group samlusers member openstack identity provider create testshib group_id=`openstack group list|grep samlusers|awk '{print $2}'` cat add-mapping.json|sed s^GROUP_ID^$group_id^ > /tmp/mapping.json openstack mapping create --rules /tmp/mapping.json saml_mapping openstack federation protocol create --identity-provider testshib --mapping saml_mapping saml2 openstack identity provider set --remote-id <your entity ID> testshib
Replace <your entity ID> with the value mentioned above in the SSOÂ entityId in the shibboleth2.xml config. Shibboleth sets Shib-Identiy-Id in the Apache request variables with the value of the entityId used, and we configured keystone to use this in keystone.conf above. This is the “remote id” for the identity provider, and keystone uses this to apply the correct protocol and mapping.
Horizon config
As before, a few Django config tweaks are needed. Edit the /opt/stack/horizon/openstack_dashboard/local/local_settings.py
WEBSSO_ENABLED = True WEBSSO_CHOICES = ( ("credentials", _("Keystone Credentials")), ("testshib", _("Testshib SAML")), ) WEBSSO_INITIAL_CHOICE="testshib" OPENSTACK_API_VERSIONS = { "identity": 3 } OPENSTACK_KEYSTONE_URL="http://$HOSTNAME:5000/v3"
Replace $HOSTNAME with your actual keystone hostname.
Now, restart apache2 and shibd:
service apache2 restart service shibd restart
You should now be all set. After making sure “Testshib SAML” is selected in the login screen, click connect and you will be redirected to the testshib login page. It has its own fixed users and tells you what they are when you visit that page.
Good luck!
Just wondering how could this setup work if you completely remove REMOTE_USER from shibboleth2.xml and at the same time use in mappings remote “type”: “REMOTE_USER”. You should either define how REMOTE_USER to be populate so that mapping can use it or you should change the mapping to not use REMOTE_USER but something else instead (e.g. eppn).
will you able to offer your training to mentor me in keystone federation.