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.
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.
$ 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 !!!
--- /dev/null
+# 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
-# 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
# 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
# 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
# *** 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 = {
# The freeradius extension using ECP
#
__author__ = 'rolandh'
+__version__ = "0.0.5a"
import radiusd
import saml2
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
# 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.
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
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
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':
# 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
# 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)
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'
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',
'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'
+# ]
)
# 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"
}
--- /dev/null
+# -*- text -*-
+#
+# $Id$
+
+# Persistent, embedded Python interpreter.
+#
+python {
+ mod_instantiate = "freeradius_pysaml2"
+ func_instantiate = "instantiate"
+ mod_post_auth= "freeradius_pysaml2"
+ func_post_auth= "post_auth"
+}
--- /dev/null
+# -*- text -*-
+#
+# $Id$
+
+# Persistent, embedded Python interpreter.
+#
+python {
+ mod_instantiate = "freeradius_ecp"
+ func_instantiate = "instantiate"
+ mod_post_auth= "freeradius_ecp"
+ func_post_auth= "post_auth"
+}