From: rohe0002 Date: Tue, 25 Oct 2011 11:27:00 +0000 (+0200) Subject: Allow for using AA or ECP X-Git-Url: http://www.project-moonshot.org/gitweb/?p=freeradius-pysaml2.git;a=commitdiff_plain;h=9419ac5045f6e069fe27e2fac834462e38c1e350 Allow for using AA or ECP --- diff --git a/README b/README index 97e4b6f..8fc935d 100644 --- a/README +++ b/README @@ -1,52 +1,56 @@ moonshot ======== A python module usable in a Moonshot environment to allow a freeradius server -to fetch information about a user from a SAML2 Attribute Authority. +to fetch information about a user from a SAML2 Attribute Authority (AA) or +Identity Provider (IdP). +There are some things you have to do disregarding how you want the SP to +talk to the IdP/AA. So I take those first. -Installing +Basic Installing ---------- -sudo python setup.py install - -eventually also - -sudo easy_install moonshot - -When the python module is installed a couple of changes to the freeradius -configuration are necessary. +A couple of changes to the freeradius configuration are necessary. +This is one way of doing it. How you chose to do it depends on your local +preferences. 1) create raddb/modules/python -You can use the provided '/usr/local/etc/moonshot/template/modules_python' file -as is. +You can use one of the provided 'template/modules_python_aa' or +'template/modules_python_ecp' files as they are. Which one depends of your +choice of using ECP or AA. Rename of copy the one you want to use to +'template/modules_python' and copy it to raddb/modules. + +Regarding the configuration of outer/inner tunnel this is still a bit +undecided. The extension module can be use in either. 2) Edit raddb/sites-available/default To the 'post-auth' section add one line referencing the python module. You can see how it can be done in -'/usr/local/etc/moonshot/template/sites-available_default". +'template/sites-available_default". 3) Edit raddb/sites-available/inner-tunnel. To the 'post-auth' section add one line referencing the python module. You can see how it can be done in -'/usr/local/etc/moonshot/template/sites-available_inner-tunnel". +'template/sites-available_inner-tunnel". -Now, you should have the basic setup. +Now, you should have the basic freeradius setup. To get it working you have to do a couple of more things: -I) Get the SAML2 metadata for the Attribute Authority (AA) you want to use. - -Place it in the '/usr/local/etc/moonshot/' directory +I) Get the SAML2 metadata for the AA or IDP you want to use. Rename it to +metadata.xml and place it in the 'etc' directory. -II) Change the configuration in /usr/local/etc/moonshot/config.py +II) Chose one of the configuration files for the extension you want to use. +There are two choices (etc/aa_config.py and etc/ecp_config.py). +Rename (or copy) the one you want to use to config.py and edit it. -You must change the value of ATTRIBUTE_AUTHORITY so it is the identifier of the -SAML2 AA you want to use. +You must change the value of ATTRIBUTE_AUTHORITY/IDP_ENTITYID so it is the +identifier (entityID) of the SAML2 AA/IdP you want to use. -III) Change the configuration '/usr/local/etc/moonshot/pysaml_config.py'. +III) Change the pysaml2 configuration file 'etc/pysaml_config.py'. A couple of things: BASE : This is the identifier of the SP (=this module) you are running. @@ -56,6 +60,8 @@ organization: Information about the organization running this service contact_person: Information about a person people can contact to ask about this service +xmlsec_binary: where the xmlsec1 binaries are located. This is only needed if +these binaries are somewhere outside the normal PATH. IV) Create your own key pair. @@ -64,14 +70,28 @@ $ openssl genrsa 1024 > ssl.key $ openssl req -new -x509 -nodes -sha1 -days 365 -key ssl.key > ssl.cert $ sudo mv ssl.key ssl.cert /usr/local/etc/moonshot/pki -If you chose other names for you key and cert you have to change accordingly -in pysaml_config.py . +If you chose other names for you key and cert you have to change +pysaml_config.py accordingly. + + +V) + +Now you can install the package: + +python setup.py install + +should place everything in it's place. +One thing that might happen is that a new directory is created. +/usr/local/etc/moonshot +You may have to change the premissions on this directory to make it possible +for the freeradius extension to access the information in the directory. +VI) Create the metadata file for your SP. -V) Create the metadata file for your SP. +$ cd etc +$ make_metadata.py pysaml_config.py > sp.xml -$ make_metadata.py /usr/local/etc/moonshot/pysaml_config.py > sp.xml -This file you have to give to the person/organization that runs the AA you +This file you have to give to the person/organization that runs the AA/IdP you want to get information from. !!! That should be it !!! diff --git a/etc/aa_config.py b/etc/aa_config.py new file mode 100644 index 0000000..d180bce --- /dev/null +++ b/etc/aa_config.py @@ -0,0 +1,27 @@ +# You shouldn't change these three lines unless you know what you are doing +CONFIG = 'pysaml_config' # PySAML2 Configuration file name +IDENTITY_CACHE = "identity_cache" +STATE_CACHE = "state_cache" +METADATA_FILE=metadata.xml + +DEBUG=0 + +# Should the SP sign the request +SIGN=False + +# This depends on the AA configuration +SP_NAME_QUALIFIER="" +NAME_QUALIFIER="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent" +NAMEID_FORMAT="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent" + +# This is necessary to pick information about the right AA from the metadata +# file. This must be the entity ID of the AA not the endpoint +ATTRIBUTE_AUTHORITY = "http://localhost:8088/" + +# Attribute filters per service@hostname +# the key are GSS-Acceptor-Service-Name+':'+GSS-Acceptor-Host-Name +# and the attribute names are the so called friendly-names + +ATTRIBUTE_FILTER = { + "ldap:example.com" : ["email", "givenName", "surname"], +} \ No newline at end of file diff --git a/etc/config.py b/etc/config.py index d180bce..94806f1 100644 --- a/etc/config.py +++ b/etc/config.py @@ -1,27 +1,17 @@ -# You shouldn't change these three lines unless you know what you are doing +# You shouldn't change this line unless you know what you are doing CONFIG = 'pysaml_config' # PySAML2 Configuration file name -IDENTITY_CACHE = "identity_cache" -STATE_CACHE = "state_cache" -METADATA_FILE=metadata.xml + +METADATA_FILE="/usr/local/etc/moonshot/metadata.xml" DEBUG=0 -# Should the SP sign the request +# Should the SP sign the request ? SIGN=False -# This depends on the AA configuration -SP_NAME_QUALIFIER="" -NAME_QUALIFIER="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent" -NAMEID_FORMAT="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent" - -# This is necessary to pick information about the right AA from the metadata -# file. This must be the entity ID of the AA not the endpoint -ATTRIBUTE_AUTHORITY = "http://localhost:8088/" - -# Attribute filters per service@hostname -# the key are GSS-Acceptor-Service-Name+':'+GSS-Acceptor-Host-Name -# and the attribute names are the so called friendly-names +# This is needed in order to pick information about the right IdP from the +# metadata file. This must be the entity ID of the IdP not an endpoint +IDP_ENTITYID = "http://localhost:8087/idp" -ATTRIBUTE_FILTER = { - "ldap:example.com" : ["email", "givenName", "surname"], -} \ No newline at end of file +# The password that should be used when authenticating with the IdP +# This password will be used disregarding which user it is. +PASSWD = "foobar" \ No newline at end of file diff --git a/etc/ecp_config.py b/etc/ecp_config.py index e67803f..933e1ee 100644 --- a/etc/ecp_config.py +++ b/etc/ecp_config.py @@ -1,9 +1,7 @@ # You shouldn't change this line unless you know what you are doing CONFIG = 'pysaml_config' # PySAML2 Configuration file name -#IDENTITY_CACHE = "identity_cache" -#STATE_CACHE = "state_cache" -METADATA_FILE="../idp/idp.xml" +METADATA_FILE="metadata.xml" DEBUG=0 @@ -14,10 +12,6 @@ SIGN=False # metadata file. This must be the entity ID of the IdP not an endpoint IDP_ENTITYID = "http://example.com/idp" -# Attribute filters per service@hostname -# the key are GSS-Acceptor-Service-Name+':'+GSS-Acceptor-Host-Name -# and the attribute names are the so called friendly-names - -ATTRIBUTE_FILTER = { - "ldap:example.com" : ["email", "givenName", "surname"], -} \ No newline at end of file +# The password that should be used when authenticating with the IdP +# This password will be used disregarding which user it is. +PASSWD = "foobar" \ No newline at end of file diff --git a/etc/pysaml_config.py b/etc/pysaml_config.py index 46c4742..2370cf9 100644 --- a/etc/pysaml_config.py +++ b/etc/pysaml_config.py @@ -4,7 +4,7 @@ from saml2 import BINDING_PAOS # *** Change this line *** BASE= "http://localhost:8088/" -# Don't change this line +# Don't change this line unless you know exactly what you are doing BASEDIR = "/usr/local/etc/moonshot/" CONFIG = { diff --git a/freeradius_pysaml2.py b/freeradius_aa.py similarity index 100% rename from freeradius_pysaml2.py rename to freeradius_aa.py diff --git a/freeradius_ecp.py b/freeradius_ecp.py index a1ac9d8..913289f 100644 --- a/freeradius_ecp.py +++ b/freeradius_ecp.py @@ -5,6 +5,7 @@ # The freeradius extension using ECP # __author__ = 'rolandh' +__version__ = "0.0.5a" import radiusd import saml2 @@ -19,11 +20,11 @@ from saml2.response import authn_response from saml2.ecp_client import Client # Where's the configuration file is -#CONFIG_DIR = "/usr/local/etc/moonshot" -CONFIG_DIR = "../etc" +CONFIG_DIR = "/usr/local/etc/moonshot" +#CONFIG_DIR = "../etc" sys.path.insert(0, CONFIG_DIR) -import ecp_config +import config # Globals CLIENT = None @@ -68,7 +69,7 @@ def instantiate(p): # Use IdP info retrieved from the SP when metadata is missing try: - CLIENT = Saml2Client(ecp_config.DEBUG, config_file=ecp_config.CONFIG) + CLIENT = Saml2Client(config.DEBUG, config_file=config.CONFIG) except Exception, e: # Report the error and return -1 for failure. @@ -77,7 +78,8 @@ def instantiate(p): return -1 try: - ECP = Client("", "", None, metadata_file=ecp_config.METADATA_FILE) + ECP = Client("", config.PASSWD, None, + metadata_file=config.METADATA_FILE) except Exception, err: log(radiusd.L_ERR, str(err)) return -1 @@ -107,8 +109,13 @@ def authentication_request(cls, ecp, idp_entity_id, destination, log = cls.logger session_id = sid() - acsu = cls.config.endpoint('assertion_consumer_service', - saml2.BINDING_PAOS)[0] + acsus = cls.config.endpoint('assertion_consumer_service', + saml2.BINDING_PAOS) + if not acsus: + if log: + log.error("Couldn't find own PAOS endpoint for") + acsu = acsus[0] + spentityid = cls.config.entityid # create the request @@ -187,12 +194,12 @@ def post_auth(authData): global CLIENT global HTTP + global ECP # Extract the data we need. userName = None serviceName = "" hostName = "" - #userPasswd = None for t in authData: if t[0] == 'User-Name': @@ -207,17 +214,28 @@ def post_auth(authData): # Find the endpoint to use - attribute_service = CLIENT.config.attribute_services(ecp_config.IDP_ENTITYID) - location = attribute_service[0].location + sso_service = CLIENT.config.single_sign_on_services(config.IDP_ENTITYID, + saml2.BINDING_PAOS) + if not sso_service: + log(radiusd.L_DBG, + "Couldn't find an single sign on endpoint for: %s" % ( + config.IDP_ENTITYID,)) + return radiusd.RLM_MODULE_FAIL + + location = sso_service[0] log(radiusd.L_DBG, "location: %s" % location) + ECP.http.clear_credentials() + ECP.user = userName + log(radiusd.L_DBG, "Login using user:%s password:'%s'" % (ECP.user, + ECP.passwd)) _assertion = authentication_request(CLIENT, ECP, - ecp_config.IDP_ENTITYID, + config.IDP_ENTITYID, location, log=LOG(), - sign=ecp_config.SIGN) + sign=config.SIGN) if _assertion is None: return radiusd.RLM_MODULE_FAIL @@ -228,12 +246,6 @@ def post_auth(authData): # remove the subject confirmation if there is one _assertion.subject.subject_confirmation = [] - # Only allow attributes that the service should have - try: - _assertion = only_allowed_attributes(CLIENT, _assertion, - ecp_config.ATTRIBUTE_FILTER[_srv]) - except KeyError: - pass log(radiusd.L_DBG, "Assertion: %s" % _assertion) diff --git a/setup.py b/setup.py index c75840b..29e93e7 100644 --- a/setup.py +++ b/setup.py @@ -2,8 +2,10 @@ import os -"""Setup script for the pyparsing module distribution.""" -from distutils.core import setup +try: + from setuptools import setup +except ImportError: + from distutils.core import setup __author__ = 'rolandh' @@ -12,12 +14,12 @@ def read(fname): setup(# Distribution meta-data name = "freeradius_pysaml2", - version = "0.0.4", - description = "FreeRadius python module to be used in Moonshot", + version = "0.0.5", + description = "FreeRadius python modules to be used in Moonshot", author = "Roland Hedberg", author_email = "roland.hedberg@adm.umu.se", license = "MIT License", - py_modules = ['freeradius_pysaml2','radiusd', "freeradius_ecp"], + py_modules = ['freeradius_aa','radiusd', "freeradius_ecp"], classifiers=[ 'Development Status :: 4 - Beta', 'Intended Audience :: Developers', @@ -35,12 +37,9 @@ setup(# Distribution meta-data 'attributemaps/saml_uri.py', 'attributemaps/shibboleth_uri.py']), ('/usr/local/etc/moonshot/pki', - ['pki/ssl.cert', 'pki/ssl.key']), - ('/usr/local/etc/moonshot/template', - ['template/modules_python', - 'template/sites-available_default', - 'template/sites-available_inner-tunnel'])], - install_requires=[ - 'pysaml2' - ] + ['pki/ssl.cert', 'pki/ssl.key'])], + zip_safe=False, +# install_requires=[ +# 'pysaml2' +# ] ) diff --git a/template/modules_python b/template/modules_python index c30cc0c..0062df5 100644 --- a/template/modules_python +++ b/template/modules_python @@ -5,8 +5,8 @@ # Persistent, embedded Python interpreter. # python { - mod_instantiate = "freeradius-pysaml2" + mod_instantiate = "freeradius_ecp" func_instantiate = "instantiate" - mod_post_auth= "freeradius-pysaml2" + mod_post_auth= "freeradius_ecp" func_post_auth= "post_auth" } diff --git a/template/modules_python_aa b/template/modules_python_aa new file mode 100644 index 0000000..3740673 --- /dev/null +++ b/template/modules_python_aa @@ -0,0 +1,12 @@ +# -*- text -*- +# +# $Id$ + +# Persistent, embedded Python interpreter. +# +python { + mod_instantiate = "freeradius_pysaml2" + func_instantiate = "instantiate" + mod_post_auth= "freeradius_pysaml2" + func_post_auth= "post_auth" +} diff --git a/template/modules_python_ecp b/template/modules_python_ecp new file mode 100644 index 0000000..0062df5 --- /dev/null +++ b/template/modules_python_ecp @@ -0,0 +1,12 @@ +# -*- text -*- +# +# $Id$ + +# Persistent, embedded Python interpreter. +# +python { + mod_instantiate = "freeradius_ecp" + func_instantiate = "instantiate" + mod_post_auth= "freeradius_ecp" + func_post_auth= "post_auth" +} diff --git a/template/sites-available_inner-tunnel.dont_use b/template/sites-available_inner-tunnel similarity index 100% rename from template/sites-available_inner-tunnel.dont_use rename to template/sites-available_inner-tunnel