The following are the steps to configure NetScaler as SAML service provider and Shibboleth as SAML identity provider:
In the following configuration section, assume that NetScaler AAA-TM is configured:
nssp.example.com resolves to FQDN of TM vserver.
aaavs.example.com resolves to FQDN of AAA vserver.
idp.wi.int resolves to FQDN of Shibboleth IDP server.
Note: Shibboleth is configured for user authentication against LDAP server "1.1.1.1" and domain "example.com".
Shibboleth version: 2.3.3
Assuming that a working version of Shibboleth is running in the environment.
The following changes pertains to NetScaler as SAML service provider and Shibboleth as LDAP authentication provider. For information about Shibboleth configuration, see Shibboleth documentation.In a successfully installed Shibboleth IDP, there are multiple directories:
[root@idp shibboleth-idp]# ls bin conf credentials lib logs metadata temp war
Configure Shibboleth IDP for LDAP authentication
Edit /conf/login.conf and configure LDAP server as follows:
ShibUserPassAuth { edu.vt.middleware.ldap.jaas.LdapLoginModule required host="1.1.1.1" port="389" baseDn="cn=users,dc=example,dc=com" bindDn="Administrator@example.com" bindCredential="Password" ssl="false" userFilter="sAMAccountName={0}"; };
Here LDAP authentication occurs against "1.1.1.1:389" and user has to authenticate with sAMAccountName.
Create a data connector in attribute-resolver.xml for LDAP authentication.
The following configuration specifies the LDAP server for user authentication and the attributes to extract after user authentication.
<resolver:DataConnector id="myLDAP" xsi:type="dc:LDAPDirectory" ldapURL="ldap://1.1.1.1" baseDN="cn=users,dc=example,dc=com" principal="Administrator@example.com" principalCredential="Password"> <dc:FilterTemplate> <![CDATA[ (cn=$requestContext.principalName) ]]> </dc:FilterTemplate> <dc:ReturnAttributes>userPrincipalName sAMAccountName </dc:ReturnAttributes> </resolver:DataConnector>
Open attribute-resolver.xml to define the return attributes. In attribute-resolver.xml, you can see multiple attribute definitions. Copy one of the definitions and modify it for userPrinicpalName and sAMAccountName.
In the following example, attribute definition is listed for UserPrincipalName. Remember that SourceAttributeID should match with the LDAP return attribute and dependency should match with the LDAP connector ID. Multiple attribute encoders can be specified, in the following example it shows SAML2string.
<resolver:AttributeDefinition xsi:type="ad:Simple" id="userPrincipalName" sourceAttributeID="userPrincipalName"> <resolver:Dependency ref="myLDAP" /> <resolver:AttributeEncoder xsi:type="enc:SAML2String" name="userPrincipalName"/> </resolver:AttributeDefinition> <resolver:AttributeDefinition xsi:type="ad:Simple" id="sAMAccountName" sourceAttributeID="sAMAccountName"> <resolver:Dependency ref="myLDAP" /> <resolver:AttributeEncoder xsi:type="enc:SAML2String" name="sAMAccountName"/> </resolver:AttributeDefinition>
Alternate method
Attribute encoder can be specified with nameFormat and Friendlyname as follows:
<resolver:AttributeEncoder xsi:type="enc:SAML1StringNameIdentifier" nameFormat="urn:mace:shibboleth:1.0:nameIdentifier name="urn:mace:dir:attribute-def:eduPersonTargetedID friendlyName="NameIdentifier"/> <resolver:AttributeEncoder xsi:type="enc:SAML2StringNameID" nameFormat="urn:oasis:names:tc:SAML:2.0:nameid-format:transient" />
Filter the defined attribute to anyone. Edit attribute-filter.xml and add the following lines:
<afp:AttributeFilterPolicy id="userPrincipalName"> <afp:PolicyRequirementRule xsi:type="basic:ANY"/> <afp:AttributeRule attributeID="userPrincipalName"> <afp:PermitValueRule xsi:type="basic:ANY"/> </afp:AttributeRule> </afp:AttributeFilterPolicy>
Here "basic:ANY" means that the value can be provided to anyone (no restriction applied). Remember, the attributeID should match with what is defined in attribute-resolver.xml.
Perform a test to check if the attribute is extracted after user authentication. Run the following command from /opt/shibboleth-idp/bin/, and you can notice that UserprincipalName is returned. Ensure that principal points to a useraccount in the LDAP.
[root@idp bin]# ./aacli.sh --configDir=/opt/shibboleth-idp/conf --principal=user1 <?xml version="1.0" encoding="UTF-8"?><saml2:AttributeStatement xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion"> <saml2:Attribute Name="userPrincipalName" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> <saml2:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">User1@example.com </saml2:AttributeValue> </saml2:Attribute> <saml2:Attribute Name="sAMAccountName" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> <saml2:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">User1</saml2:AttributeValue> </saml2:Attribute> </saml2:AttributeStatement>
To configure a metadata file for NetScaler, use the following example of nssp.example.com and modify it accordingly for your deployment. (The fields highlighted in Yellow should be replaced with hostname of TM vserver). Assume the location of the file is "/opt/shibboleth-idp/metadata/nssp-example-metadata.xml".
This file should be placed in a remote location where IDP can access it. In this case it is placed in NetScaler at "/netscaler/ns_gui/vpn", so it can be accessed from AAA vserver. It is not mandatory to keep the file on NetScaler.
<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" ID="_724200788f8391f96053f72adc628fecc808d09a" entityID="nssp.example.com"> <md:SPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol urn:oasis:names:tc:SAML:1.1:protocol urn:oasis:names:tc:SAML:1.0:protocol"> <md:Extensions> <init:RequestInitiator xmlns:init="urn:oasis:names:tc:SAML:profiles:SSO:request-init" Binding="urn:oasis:names:tc:SAML:profiles:SSO:request-init" Location="https://nssp.example.com/Shibboleth.sso/Login"/> <idpdisc:DiscoveryResponse xmlns:idpdisc="urn:oasis:names:tc:SAML:profiles:SSO:idp-discovery-protocol" Binding="urn:oasis:names:tc:SAML:profiles:SSO:idp-discovery-protocol" Location="https://nssp.example.com/Shibboleth.sso/Login" index="1"/> <init:RequestInitiator xmlns:init="urn:oasis:names:tc:SAML:profiles:SSO:request-init" Binding="urn:oasis:names:tc:SAML:profiles:SSO:request-init" Location="https://nssp.example.com/Shibboleth.sso/Login"/> </md:Extensions> <md:KeyDescriptor> <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> <ds:KeyName>nssp.example.com</ds:KeyName> <ds:X509Data> <ds:X509SubjectName>CN=nssp.example.com</ds:X509SubjectName> <ds:X509Certificate> X509 Certificate (Netscaler Signing Certificate nssp-example.cer) </ds:X509Certificate> </ds:X509Data> </ds:KeyInfo> </md:KeyDescriptor> <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://nssp.example.com/cgi/samlauth" index="0"/> </md:SPSSODescriptor> </md:EntityDescriptor>
Configure the metadata location in relaying-party.xml (/opt/shibboleth-idp/conf). Edit relaying-party.xml and add a relaying party with id: nssp.example.com. Fields highlighted in Yellow specifies which part of the assertion to be signed, NetScaler supports signature verification for both. (signResponses and signAssertions can be set to "always").
If the signature validation fails, then set it to "never" to temporarily disable signing.
<rp:RelyingParty id="nssp.example.com” provider="nssp.example.com" defaultAuthenticationMethod="urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport" defaultSigningCredentialRef="IdPCredential" > <rp:ProfileConfiguration xsi:type="saml:ShibbolethSSOProfile" includeAttributeStatement="false" assertionLifetime="PT5M" signResponses="conditional" signAssertions="never"/> <rp:ProfileConfiguration xsi:type="saml:SAML2SSOProfile" includeAttributeStatement="true" assertionLifetime="PT5M" assertionProxyCount="0" signResponses="always" signAssertions="never" encryptAssertions="never" encryptNameIds="never"/> <rp:ProfileConfiguration xsi:type="saml:SAML2AttributeQueryProfile" /> <rp:ProfileConfiguration xsi:type="saml:SAML2ArtifactResolutionProfile" /> </rp:RelyingParty>
Create a MetadataProvider ID for NetScaler and point to the metadata file created in step 5.
<metadata:MetadataProvider id="URLMDNS" xsi:type="metadata:FileBackedHTTPMetadataProvider" xmlns="urn:mace:shibboleth:2.0:metadata"
metadataURL="https://aaavs.example.com/vpn/nssp-example-metadata.xml"
backingFile="/opt/shibboleth-idp/metadata/nssp-example-metadata.xml">
<metadata:MetadataFilter xsi:type="metadata:ChainingFilter">
<metadata:MetadataFilter xsi:type="metadata:EntityRoleWhiteList">
<metadata:RetainedRole>samlmd:SPSSODescriptor</metadata:RetainedRole>
</metadata:MetadataFilter>
</metadata:MetadataFilter>
</metadata:MetadataProvider>
</metadata:MetadataProvider>
The following section covers, how to configure SAML on NetScaler.
Create a SAML action on the NetScaler, to extract UserPrincipalName from the SAML response.
Create a CertKey for NetScaler (nssp-example-key). Provide the same certificate as nssp-example-metadata.xml and private key associated with that certificate.
add ssl certKey nssp-cert -cert nssp-example.cer -key nssp-example-key
Create a CertKey with Shibboleth signing certificate (idp-cert-key). IDP certificate is accessible from the IDP-METADATA file - https://idp.example.com/idp/profile/Metadata/SAML.
add ssl certKey idp.wi.int -cert "/nsconfig/ssl/idp-cert.cer"
Create a SAML action with redirect URL and point to the IDP and SP signing certificates created in the preceding step.
SAML Redirect URL: https://idp.wi.int/idp/profile/SAML2/POST/SSO
SAML IDP CertName: idp-cert-key
SAML SP CertName: nssp-example-key
> add authentication samlAction shibboleth -samlIdPCertName idp-cert-key -samlSigningCertName nssp-example-key -samlRedirectUrl "https://idp.wi.int/idp/profile/SAML2/POST/SSO" -samlUserField userPrincipalName -samlIssuerName nssp.example.com
Create SAML policy.
> add authentication samlPolicy shibboleth ns_true shibboleth
Bind SAML policy to AAA vserver. Certificate bound to NetScaler vserver is independent of SAML certificate.
> add authentication vserver av1 SSL 10.10.10.2 443 > bind ssl vs av1 –certkey <NS_Certificate> > bind authentication vserver av1 -policy shibboleth
Create load balanced vserver and set authentication to AAA vserver.
> add lb vserver lb1 SSL 10.10.10.1 443 -persistenceType NONE -cltTimeout 180 -AuthenticationHost aaavs.example.com -Authentication ON -authnVsName av1 > bind lb vserver lb1 service_s1 > bind ssl vserver lb1 –certkey <NS_Certificate>
SAMLRequest generated by NetScaler:
(Verify the highlighted fields in Yellow for troubleshooting.)
<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" AssertionConsumerServiceURL="https://nssp.example.com/cgi/samlauth" Destination="https://idp.example.com/idp/profile/SAML2/POST/SSO" ID="_64330a8ef3900a7fa8cedb1271b2ebe5" IssueInstant="2014-09-23T00:55:49Z" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Version="2.0"><saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">nssp.example.com</saml:Issuer><ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:SignedInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></ds:CanonicalizationMethod><ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"></ds:SignatureMethod><ds:Reference URI="#_64330a8ef3900a7fa8cedb1271b2ebe5"><ds:Transforms><ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"></ds:Transform><ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></ds:Transform></ds:Transforms><ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></ds:DigestMethod><ds:DigestValue>Digest_Value</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>Signature_Valuue</ds:SignatureValue><ds:KeyInfo><ds:X509Data><ds:X509Certificate> Netscaler_Signing_Certificate (nssp-example.cer, refer to section: 2.1.a) </ds:X509Certificate></ds:X509Data></ds:KeyInfo></ds:Signature></samlp:AuthnRequest>
SAMLResponse generated by Shibboleth:
(Verify the highlighted fields in Yellow for troubleshooting.)
<?xml version="1.0" encoding="UTF-8"?><saml2p:Response xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" Destination="https://nssp.example.com/cgi/samlauth" ID="_8682a26aecd596e4952b0d2b9a661d6c" InResponseTo="_64330a8ef3900a7fa8cedb1271b2ebe5" IssueInstant="2014-09-23T01:00:14.081Z" Version="2.0" xmlns:xs="http://www.w3.org/2001/XMLSchema"><saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">nssp.example.com</saml2:Issuer><ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:SignedInfo><ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/><ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/><ds:Reference URI="#_8682a26aecd596e4952b0d2b9a661d6c"><ds:Transforms><ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/><ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"><ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="xs"/></ds:Transform></ds:Transforms><ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/><ds:DigestValue>Digest_Value</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>Signature_Value</ds:SignatureValue><ds:KeyInfo><ds:X509Data><ds:X509Certificate>IDP_Certificate (idp-cert.cer, refer to section:2.1.b) </ds:X509Certificate></ds:X509Data></ds:KeyInfo></ds:Signature><saml2p:Status><saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/></saml2p:Status><saml2:Assertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" ID="_57a1b6c685fcae6314ff8a9f41052680" IssueInstant="2014-09-23T01:00:14.081Z" Version="2.0"><saml2:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">nssp.example.com</saml2:Issuer><saml2:Subject><saml2:NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient" NameQualifier="nssp.example.com">_4a5af6cba683cd020f4f484171647d72</saml2:NameID><saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"><saml2:SubjectConfirmationData Address="10.217.28.34" InResponseTo="_64330a8ef3900a7fa8cedb1271b2ebe5" NotOnOrAfter="2014-09-23T01:05:14.081Z" Recipient="https://nssp.example.com/cgi/samlauth"/></saml2:SubjectConfirmation></saml2:Subject><saml2:Conditions NotBefore="2014-09-23T01:00:14.081Z" NotOnOrAfter="2014-09-23T01:05:14.081Z"><saml2:AudienceRestriction><saml2:Audience>nssp.example.com</saml2:Audience></saml2:AudienceRestriction></saml2:Conditions><saml2:AuthnStatement AuthnInstant="2014-09-23T01:00:14.068Z" SessionIndex="3c8492dd7e244b7497d8b0142535f028d6f52ae29621bb36d957f4fda706771b"><saml2:SubjectLocality Address="10.217.28.34"/><saml2:AuthnContext><saml2:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml2:AuthnContextClassRef></saml2:AuthnContext></saml2:AuthnStatement><saml2:AttributeStatement><saml2:Attribute Name="userPrincipalName" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"><saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">User1@example.com</saml2:AttributeValue></saml2:Attribute><saml2:Attribute Name="sAMAccountName" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"><saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">User1</saml2:AttributeValue></saml2:Attribute></saml2:AttributeStatement></saml2:Assertion></saml2p:Response>
Verify if NetScaler creates AAA session for user "user1@example.com", after successful authentication.
Complete the following steps to troubleshoot Shibboleth:
Check idp-access.log.
tail -f /opt/shibboleth-idp/logs/idp-process.log
Restart the Apache service, after making changes to the Shibboleth config.
#/var/lib/apache-tomcat-6.0.33/bin/startup.sh #/var/lib/apache-tomcat-6.0.33/bin/shutdown.sh
Enable syslogparams to loglevel all and use /var/log/ns.log for more debug information.
> set syslogparams –loglevel all # tail -f /var/log/ns.log
Check nsconmsg counters.
# nsconmsg -d statswt0 -g saml
For information about the error counters, see CTX200177 - Configuration and Troubleshooting for NetScaler as SAML IDP and Siteminder as SAML SP.