From 217cabe5a2b0950b9ac4090568aa8986d51f4fc5 Mon Sep 17 00:00:00 2001 From: Rob Crittenden Date: Thu, 19 Mar 2015 15:15:26 -0400 Subject: Implement urn:oasis:names:tc:SAML:2.0:nameid-format:persistent This also makes persistent the default NameID format when generating metadata. https://fedorahosted.org/ipsilon/ticket/27 Signed-off-by: Rob Crittenden Reviewed-by: Simo Sorce --- ipsilon/install/ipsilon-server-install | 3 ++- ipsilon/providers/saml2/auth.py | 13 +++++++++++-- ipsilon/providers/saml2idp.py | 16 +++++++++++++--- quickrun.py | 3 ++- tests/fconf.py | 6 +++++- 5 files changed, 33 insertions(+), 8 deletions(-) diff --git a/ipsilon/install/ipsilon-server-install b/ipsilon/install/ipsilon-server-install index 307f1e4..edcccb6 100755 --- a/ipsilon/install/ipsilon-server-install +++ b/ipsilon/install/ipsilon-server-install @@ -116,7 +116,8 @@ def install(plugins, args): 'transdb': args['database_url'] % { 'datadir': args['data_dir'], 'dbname': 'transactions'}, 'secure': "False" if args['secure'] == "no" else "True", - 'debugging': "True" if args['server_debugging'] else "False"} + 'debugging': "True" if args['server_debugging'] else "False", + } # Testing database sessions if 'session_type' in args: confopts['sesstype'] = args['session_type'] diff --git a/ipsilon/providers/saml2/auth.py b/ipsilon/providers/saml2/auth.py index 71bfc9a..4bfbc1a 100644 --- a/ipsilon/providers/saml2/auth.py +++ b/ipsilon/providers/saml2/auth.py @@ -28,6 +28,7 @@ import cherrypy import datetime import lasso import uuid +import hashlib class UnknownProvider(ProviderException): @@ -183,8 +184,16 @@ class AuthenticateRequest(ProviderPageBase): nameid = None if nameidfmt == lasso.SAML2_NAME_IDENTIFIER_FORMAT_PERSISTENT: - # TODO map to something else ? - nameid = provider.normalize_username(user.name) + idpsalt = self.cfg.idp_nameid_salt + if idpsalt is None: + raise AuthenticationError( + "idp nameid salt is not set in configuration" + ) + value = hashlib.sha512() + value.update(idpsalt) + value.update(login.remoteProviderId) + value.update(user.name) + nameid = '_' + value.hexdigest() elif nameidfmt == lasso.SAML2_NAME_IDENTIFIER_FORMAT_TRANSIENT: nameid = '_' + uuid.uuid4().hex elif nameidfmt == lasso.SAML2_NAME_IDENTIFIER_FORMAT_KERBEROS: diff --git a/ipsilon/providers/saml2idp.py b/ipsilon/providers/saml2idp.py index 96a7d11..5d8aa03 100644 --- a/ipsilon/providers/saml2idp.py +++ b/ipsilon/providers/saml2idp.py @@ -33,6 +33,7 @@ from datetime import timedelta import lasso import os import time +import uuid class Redirect(AuthenticateRequest): @@ -194,6 +195,10 @@ Provides SAML 2.0 authentication infrastructure. """ 'idp key file', 'The IdP Certificate Key genearated at install time.', 'certificate.key'), + pconfig.String( + 'idp nameid salt', + 'The salt used for persistent Name IDs.', + None), pconfig.Condition( 'allow self registration', 'Allow authenticated users to register applications.', @@ -252,6 +257,10 @@ Provides SAML 2.0 authentication infrastructure. """ return os.path.join(self.idp_storage_path, self.get_config_value('idp key file')) + @property + def idp_nameid_salt(self): + return self.get_config_value('idp nameid salt') + @property def default_allowed_nameids(self): return self.get_config_value('default allowed nameids') @@ -323,10 +332,10 @@ class IdpMetadataGenerator(object): '%s/saml2/SSO/Redirect' % url) self.meta.add_service(metadata.SAML2_SERVICE_MAP['logout-redirect'], '%s/saml2/SLO/Redirect' % url) - self.meta.add_allowed_name_format( - lasso.SAML2_NAME_IDENTIFIER_FORMAT_TRANSIENT) self.meta.add_allowed_name_format( lasso.SAML2_NAME_IDENTIFIER_FORMAT_PERSISTENT) + self.meta.add_allowed_name_format( + lasso.SAML2_NAME_IDENTIFIER_FORMAT_TRANSIENT) self.meta.add_allowed_name_format( lasso.SAML2_NAME_IDENTIFIER_FORMAT_EMAIL) @@ -379,7 +388,8 @@ class Installer(ProviderInstaller): config = {'idp storage path': path, 'idp metadata file': 'metadata.xml', 'idp certificate file': cert.cert, - 'idp key file': cert.key} + 'idp key file': cert.key, + 'idp nameid salt': uuid.uuid4().hex} po.save_plugin_config(config) # Update global config to add login plugin diff --git a/quickrun.py b/quickrun.py index 0722c7b..57cdcb7 100755 --- a/quickrun.py +++ b/quickrun.py @@ -80,7 +80,8 @@ def config(workdir): 'sesstype': 'file', 'sessopt': 'path', 'sessval': os.path.join(workdir, 'sessions'), - 'secure': 'False'}) + 'secure': 'False', + }) conf = os.path.join(workdir, 'ipsilon.conf') with open(conf, 'w+') as f: f.write(text) diff --git a/tests/fconf.py b/tests/fconf.py index 16738cb..409c975 100755 --- a/tests/fconf.py +++ b/tests/fconf.py @@ -25,6 +25,7 @@ import os import pwd import sys from string import Template +import uuid idpname = 'idp1' @@ -66,6 +67,7 @@ saml2 idp key file = ${TESTDIR}/lib/${NAME}/saml2/idp.key saml2 idp storage path = ${TESTDIR}/lib/${NAME}/saml2 saml2 idp metadata file = metadata.xml saml2 idp certificate file = ${TESTDIR}/lib/${NAME}/saml2/idp.pem +saml2 idp nameid salt = ${IDPSALT} [saml2_data] 811d0231-9362-46c9-a105-a01a64818904 id = http://${SPADDR}:${SPPORT}/saml2 811d0231-9362-46c9-a105-a01a64818904 type = SP @@ -116,10 +118,12 @@ def fixup_idp_conf(testdir): idpuri = "http://%s:%s/%s" % (idpaddr, idpport, idpname) + idpsalt = uuid.uuid4().hex t = Template(idp_file_conf) text = t.substitute({'NAME': idpname, 'IDPURI': idpuri, 'SPNAME': spname, 'SPADDR': spaddr, 'SPPORT': spport, - 'SPMETA': spmeta, 'TESTDIR': testdir}) + 'SPMETA': spmeta, 'TESTDIR': testdir, + 'IDPSALT': idpsalt}) adminconf = os.path.join(testdir, 'etc/admin.conf') with open(adminconf, 'w+') as f: -- cgit