Moonshot IdP
Moonshot workshop 6.2.2014
Sami Silén, CSC
2Connect | Communicate | Collaborate
About Moonshot IdP
Moonshot IdP is a Radius server capable to authenticate users and deliver user attribute(s) in a SAML assertion.
To Authenticate users in a service side, routing infrastructure is needed
Eduroam
Trust router
Haka?
Eduroam and Trust router?
SAML Assertion with attributes
Fetch from the Attribute Authority
Query from the database and construct in Radius
3Connect | Communicate | Collaborate
Eduroam in a nutshell
User performs anonymous authentication if allowed (eg: [email protected])
Message is routed to the home organization and TTLS protected inner-tunnel is established between client and home server.Inner-tunnel is then used for user authentication with real organizational credentials.
After successful authentication response is sent via outer tunnel.
TLRS (Top Level Radius Server )
.FI
.CSC.FI .OTHER.FI
WLAN.OTHER.FI
User from CSC
4Connect | Communicate | Collaborate
Haka-federation in a nutshell
IdP
Organizationaluser repository
SP
SP user repository
WAYF/DSUser performs login to SP
SP redirects user to DS fordiscovering where user is from.
After discovery SP redirects user to the users organizational identity provider (IdP) where user performs authentication.
IdP fetches user information and encrypts it before submission to the SP (via browser)
5Connect | Communicate | Collaborate
Moonshot in a nutshell
Someone could say it’s ”Eduroam + Haka”
Haka authentication outside the web.
In the world where there are no browser to pass assertion (response from IdP) nor DS for discovery.
Discovery can be handled with Radius routing (or later via Trust router?).
Assertion can be delivered inside Radius reply.
6Connect | Communicate | Collaborate
Moonshot
In a pilot phase topology is similar with eduroam.
Radius server has to reply with assertion containing a EPPN attribute. Either by Creating it itself or requesting it from the SAML IdP.
.FI
.TUT.FI .CSC.FI
SERVICE.CSC.FI
User from TUT
7Connect | Communicate | Collaborate
Radius reply with SAML-AAA-Assertion
Sending Access-Accept of id 16 to 192.168.1.20 port 41746
Message-Authenticator = 0x00000000000000000000000000000000
User-Name = “jsmith"
SAML-AAA-Assertion = "<?xml version='1.0' encoding='UTF-8'?>\n<ns0:Assertion ID=\"_c9edcf8739dd122af271dc4f24621244\" IssueInstant=\"2013-05-29T08:08:04.240Z\" Version=\"2.0\" xmlns:ns0=\"urn:oasis:names:tc:SAML:2.0:assertion\"><ns0:Issuer Format=\"urn:oasis:names:tc:SAML:2.0:na"
SAML-AAA-Assertion = "meid-format:entity\">https://idp.example.com/idp/shibboleth</ns0:Issuer><ns0:Subject><ns0:NameID Format=\"urn:oasis:names:tc:SAML:2.0:nameid-format:uid\" NameQualifier=\"https://idp.example.com/idp/shibboleth\" SPNameQualifier=\"https://idp.example.com"
SAML-AAA-Assertion = "fi/metadata.xml\">[email protected]</ns0:NameID></ns0:Subject><ns0:Conditions NotBefore=\"2013-05-29T08:08:04.240Z\" NotOnOrAfter=\"2013-05-29T08:13:04.240Z\"><ns0:AudienceRestriction><ns0:Audience>https://idp.example.com/metadata.xml</ns0:Audie"
SAML-AAA-Assertion = "nce></ns0:AudienceRestriction></ns0:Conditions><ns0:AttributeStatement><ns0:Attribute FriendlyName=\"schacHomeOrganization\" Name=\"urn:oid:1.3.6.1.4.1.25178.1.2.9\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><ns0:AttributeValue ns1:"
SAML-AAA-Assertion = "type=\"xs:string\" xmlns:ns1=\"http://www.w3.org/2001/XMLSchema-instance\">example.com</ns0:AttributeValue></ns0:Attribute><ns0:Attribute FriendlyName=\"eduPersonPrincipalName\" Name=\"urn:oid:1.3.6.1.4.1.5923.1.1.1.6\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:“in
SAML-AAA-Assertion = "attrname-format:uri\"><ns0:AttributeValue ns1:type=\"xs:string\" xmlns:ns1=\"http://www.w3.org/2001/XMLSchema-instance\">[email protected]</ns0:AttributeValue></ns0:Attribute><ns0:Attribute FriendlyName=\"cn\" Name=\"urn:oid:2.5.4.3\" NameFormat=\"urn:oasis:n"
SAML-AAA-Assertion = "ames:tc:SAML:2.0:attrname-format:uri\"><ns0:AttributeValue ns1:type=\"xs:string\" xmlns:ns1=\"http://www.w3.org/2001/XMLSchema-instance\">jsmith</ns0:AttributeValue></ns0:Attribute><ns0:Attribute FriendlyName=\"schacHomeOrganizationType\" Name=\"urn:oid:1.3"
SAML-AAA-Assertion = ".6.1.4.1.25178.1.2.10\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><ns0:AttributeValue ns1:type=\"xs:string\" xmlns:ns1=\"http://www.w3.org/2001/XMLSchema-instance\">urn:mace:terena.org:schac:homeOrganizationType:fi:university</ns0:At"
SAML-AAA-Assertion = "tributeValue></ns0:Attribute><ns0:Attribute FriendlyName=\"sn\" Name=\"urn:oid:2.5.4.4\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><ns0:AttributeValue ns1:type=\"xs:string\" xmlns:ns1=\"http://www.w3.org/2001/XMLSchema-instance\">Smith<"
SAML-AAA-Assertion = "/ns0:AttributeValue></ns0:Attribute><ns0:Attribute Name=\"urn:oid:1.3.6.1.4.1.16161.3.1\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><ns0:AttributeValue ns1:type=\"xs:string\" xmlns:ns1=\"http://www.w3.org/2001/XMLSchema-instance\">htt"
SAML-AAA-Assertion = "ps://idp.example.com/logout_dummy.jsp</ns0:AttributeValue></ns0:Attribute><ns0:Attribute FriendlyName=\"displayName\" Name=\"urn:oid:2.16.840.1.113730.3.1.241\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><ns0:AttributeValue ns1:type"
SAML-AAA-Assertion = "=\"xs:string\" xmlns:ns1=\"http://www.w3.org/2001/XMLSchema-instance\">jsmith</ns0:AttributeValue></ns0:Attribute></ns0:AttributeStatement></ns0:Assertion>"
MS-MPPE-Recv-Key = 0xf0371df7e2ecc33c199f0b2fcc8e7c89126128ea4f99d3fef24a7d871a332089
MS-MPPE-Send-Key = 0x2a46f3e2a78c497726ceb159427223fb3730475b9dd9863162a9ac2618323c9b
EAP-Message = 0x03080004
8Connect | Communicate | Collaborate
Haka Moonshot Pilot Requirements
Requirements (Server side)• Radius server capable to
• Authenticate users• Deliver assertion with eppn attribute
taito-moonshot.csc.fi
Moonshot PilotRoot server
testidp.funet.fi
SS
H
@[email protected]@tut.fi accounts.csc.fi
Requirements (Client side)• Linux workstation with
• Moonshot UI, libraries and openSSH• Windows workstation with
• Moonshot libraries (Windows SSP)• Credentials in Windows Credential Manager • SSH Client supporting GSS API (Pending)
9Connect | Communicate | Collaborate
Moonshot IdP configuration
Preconditions
• Radius configured according to eduroam instructions• https://info.funet.fi/wiki/display/avoin/FreeRADIUSen+konfigurointi• (FR3) http://confluence.diamond.ac.uk/pages/viewpage.action?pageId=25140711
• Radius configured to add SAML-AAAA-Assertion to reply • Shibboleth Identity Provider with soap endpoint configured
– https://wiki.shibboleth.net/confluence/display/SHIB2/IdPApacheTomcatPrepare– https://wiki.shibboleth.net/confluence/display/SHIB2/IdPJetty7Prepare
OR
• Radius configured to build SAML-AAAA-Assertion itself.– http://confluence.diamond.ac.uk/pages/viewpage.action?pageId=25140711
(Gives an idea how to build assertion with freeradius)
10Connect | Communicate | Collaborate
Assertion with Radius
## Look up our Moonshot local user (the FedId) from our "fed_id_map" table (the glue between CUI and the FedID).# Any non-association will get the CUI as the user## Only requests that contain a GSS attribute will get a SAML assertion#if ( ("%{request:GSS-Acceptor-Service-Name}") && ("%{request:GSS-Acceptor-Host-Name}") ) { update control { Tmp-String-1 := `/bin/date -u +%%FT%%TZ` Tmp-String-2 := `/usr/bin/uuidgen` } update reply { SAML-AAA-Assertion = "<saml:Assertion xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\" IssueInstant=\"%{control:Tmp-String-1}\" ID=\"%{control:Tmp-String-2}\" Version=\"2.0\">" SAML-AAA-Assertion += '<saml:Issuer>urn:mace:incommon:osu.edu</saml:Issuer>' SAML-AAA-Assertion += '<saml:AttributeStatement>' SAML-AAA-Assertion += '<saml:Attribute NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" Name="urn:oid:1.3.6.1.4.1.5923.1.1.1.6">' SAML-AAA-Assertion += "<saml:AttributeValue>%{%{reply:Chargeable-User-Identity}:-unknown}@diamond.ac.uk</saml:AttributeValue>" SAML-AAA-Assertion += '</saml:Attribute>' SAML-AAA-Assertion += '<saml:Attribute NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" Name="urn:oid:1.3.6.1.4.1.5923.1.1.1.7">' SAML-AAA-Assertion += "<saml:AttributeValue>%{%{sql:SELECT fed_id_map.local_uid FROM `fed_id_map` WHERE fed_id_map.rad_cui = '%{reply:Chargeable-User-Identity}'}:-%{reply:Chargeable-User-Identity}}</saml:AttributeValue>" SAML-AAA-Assertion += '</saml:Attribute>' SAML-AAA-Assertion += '</saml:AttributeStatement>' SAML-AAA-Assertion += '</saml:Assertion>' }}
Example: Not testedhttp://confluence.diamond.ac.uk/plugins/viewsource/viewpagesrc.action?pageId=22252823
11Connect | Communicate | Collaborate
Assertion from Shibboleth IdP
Freeradius-pysaml2 is a python module you can use to fetch information about user from a SAML2 Attribute Authority (AA)
Platform requirements
RPMS: libxml2-devel libxslt-devel libtool-ltdl-devel make python-mako memcached python-memcached python-setuptools gcc
Python Modules: argparse (easy_install argparse, needed by make_metadata.py)
Other (download and compile):
– Pysaml2 https://github.com/rohe/pysaml2 – Xmlsec http://www.aleksey.com/xmlsec/download.html– Repoze.who (should install automatically when needed)
12Connect | Communicate | Collaborate
Freeradius-pysaml2
Freeradius-pysaml2 https://github.com/rohe/freeradius_pysaml2
Before compilation configure module accordingly (README).
Destination folder for freeradius-pysaml2 is /usr/local/etc/moonshot
Also trust must be established between radius and IdP (metadata exchange).
Configuration files:
aa_config.py (make a copy of this to config.py)
pysaml_config.py
13Connect | Communicate | Collaborate
Freeradius-pysaml2 config.py
CONFIG = 'pysaml_config' # PySAML2 Configuration file name
IDENTITY_CACHE = "/usr/local/etc/moonshot/identity_cache"
STATE_CACHE = "/usr/local/etc/moonshot/state_cache"
METADATA_FILE = "/usr/local/etc/moonshot/metadata.xml“
SIGN = False
SP_NAME_QUALIFIER = "https://idp.example.com/metadata.xml"
NAME_QUALIFIER = “https://idp.example.com/idp/shibboleth"
NAMEID_FORMAT = "urn:oasis:names:tc:SAML:2.0:nameid-format:eduPersonPrincipalName"
# 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 = "https://idp.example.com/idp/shibboleth"
# 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": ["eduPersonPrincipalName"],
}
14Connect | Communicate | Collaborate
NameID
NameID is used to identify the person that the IdP has issued an assertion about. Name identifiers can be anything; an email address or a Kerberos principal name are common, every-day examples of such information.
In earlier config.py we configuredNAMEID_FORMAT = "urn:oasis:names:tc:SAML:2.0:nameid-format:eduPersonPrincipalName“
From radius server we receive userid with realm, therefore it might be convenient to use eduPersonPrincipalName as a NameID(on most cases I assume that this is eppn).
Example of soap message generated by freeradius-pysaml2
<?xml version="1.0" encoding="UTF-8"?><ns0:Envelope xmlns:ns0="http://schemas.xmlsoap.org/soap/envelope/">
<ns0:Body>
<ns1:AttributeQuery xmlns:ns1="urn:oasis:names:tc:SAML:2.0:protocol" Destination="https://idp.example.com:8443/idp/profile/SAML2/SOAP/AttributeQuery" ID="id-423fc8d4ed912c389ff1dc16b737330b" IssueInstant="2013-05-29T05:05:37Z" Version="2.0">
<ns2:Issuer xmlns:ns2="urn:oasis:names:tc:SAML:2.0:assertion" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">https://idp.example.com/metadata.xml</ns2:Issuer>
<ns2:Subject xmlns:ns2="urn:oasis:names:tc:SAML:2.0:assertion">
<ns2:NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:eduPersonPrincipalName" NameQualifier=" https://idp.example.com/idp/shibboleth " SPNameQualifier="https://idp.example.com/metadata.xml">[email protected]</ns2:NameID>
</ns2:Subject>
</ns1:AttributeQuery>
</ns0:Body>
</ns0:Envelope>
15Connect | Communicate | Collaborate
Direct Principal Connector
IdP maps a name identifier back in to an identifier for the user (e.g. their login id). This identifier is known as a principal name and so the plugin that connects the name identifier to a principal name is known as the PrincipalConnector.
“Direct” assumes the value of the name identifier is the user's principal name and as such performs no mapping
If we’re using following Principal Connector we have to filter domain part before we can match it to login id
<resolver:PrincipalConnector xsi:type="pc:Direct" xmlns="urn:mace:shibboleth:2.0:resolver:pc" id="eduPersonPrincipalName" nameIDFormat="urn:oasis:names:tc:SAML:2.0:nameid-format:eduPersonPrincipalName"/>
16Connect | Communicate | Collaborate
Remove realm from the Principal
RegexSplit for removing everything after @
<resolver:AttributeDefinition xsi:type="RegexSplit" dependencyOnly="true"
xmlns="urn:mace:shibboleth:2.0:resolver:ad" id="regex_principal_split"
sourceAttributeID="principal" regex="^(.*?)(@.*)?$">
<resolver:Dependency ref="principal" />
</resolver:AttributeDefinition>
In resolver:DataConnector add dependency for regex_principal_split and use splitted value, this works if you don’t have any userid with @ on it.
<resolver:Dependency ref="regex_principal_split" />
<FilterTemplate>
<![CDATA[
(sAMAccountName=${regex_principal_split.get(0)})
]]>
</FilterTemplate>
Approach by Paul Caskey https://wiki.shibboleth.net/confluence/display/SHIB2/IdPAttrResolvRemoveKerbRealm
17Connect | Communicate | Collaborate
Freeradius-pysaml2 pysaml_config.py
Sections from pysaml_config.py to be checked out
BASE = https://idp.example.com/
CONFIG = {
"service": {
"sp": {
"required_attributes": ["eduPersonPrincipalName"],
"optional_attributes": ["schacHomeOrganization","schacHomeOrganizationType"],
"key_file": BASEDIR + "pki/ssl.key",
"cert_file": BASEDIR + "pki/ssl.cert",
"xmlsec_binary": "/usr/local/bin/xmlsec1",
"organization": {
},
"contact_person": [{
}],
18Connect | Communicate | Collaborate
Freeradius-pysaml2 installation
• Generate metadata file for radius• make_metadata.py pysaml_config.py > moonshot-radius.xml
• Set metadata for IdP/AA you want to use in etc/metadata.xml• Set key/certificate to the pki directory (ssl.cert, ssl.key)
• modify template/modules_python_aa• Replace freeradius-pysaml2 with freeradius_aa• Copy template/modules_python_aa to
/etc/raddb/modules/modules_python and template/modules_python
• Uncomment following from the freeradius_aa.py,• CONFIG_DIR = "/usr/local/etc/moonshot"• sys.path.insert(0, CONFIG_DIR)
19Connect | Communicate | Collaborate
Freeradius-pysaml2 compilation
Compile freeradius-pysaml2 module
Checkout that radius has access to just created directory structure /usr/local/etc/moonshot (Radius has to have write access).
20Connect | Communicate | Collaborate
Freeradius-pysaml2 deploying instructions
Start radius server in the foreground (radiusd –fXxx)
Before ldap integration, testing with steve/testing may be feasible (enable from users file)
Login can be tested with ’radtest steve "testing" localhost 1 testing123’
It’s easier to test in default before going to inner-tunnel
21Connect | Communicate | Collaborate
Open questions?
Is security of outer-tunnel enough for attributes?
Audiense in response (For who it is)?.
Response/Assertion signing is not working, but maybe this is only valid when audience is used.
22Connect | Communicate | Collaborate
www.geant.net
www.twitter.com/GEANTnews | www.facebook.com/GEANTnetwork | www.youtube.com/GEANTtv
Connect | Communicate | Collaborate
Thank you!