Friday, July 25, 2014

How to build ADFS (SAML 2.0) to KCD "proxy" using Citrix NetScaler - Part 1

Story behind this post

Some time ago I got request from customer project that they need give for customer Excel access to SQL Analysis Services which is located on our Cloud environment and customer will connect to it from they network over the internet.

First tricky part here was that this connection should be single-sign-on from user point of view.

Using SharePoint's Excel Services it is possible create Excel sheet which is located on SharePoint and Excel Services will connect to back-end service. Because data on SQL Analysis Services would be also different depending who connecting to Analysis Services, Kerberos delegation was only possible way to continue.

SharePoint contains native support for ADFS federation to it, but another tricky part was that if you enable ADFS federation to SharePoint it will authorize users to it without authenticating them. Because users are not authenticated you can't get Kerberos tickets to them so connection SQL Analysis Services autetication is not working any more. More info about that on here: http://blogs.msdn.com/b/andrasg/archive/2010/05/04/setting-up-sharepoint-2010-excel-services-to-get-external-data.aspx


How Citrix NetScaler can help with this situation?

Unlike SharePoint, NetScaler supports extracting user information from ADFS (SAML 2.0) claims and retrieve Kerberos ticket for them. That concept is called for Kerberos constrained delegation (KCD). With that Kerberos ticket NetScaler can forward user's session to any web service which supports Kerberos authentication.

When I say any web service, it really means that. So what actually happened was that I found solution which actually can provide SAML 2.0 federation support to any application which are using IIS native authentication without coding that manually to every application and because it uses Kerberos authentication to back-end services, double or even triple hop are not problem any more.

Which basically means that you can example have web page which gets data from another web server which gets data from SQL server and still use integrated authentication on SQL server side.

How authentication process works on this concept

This picture show how authentication process works on this concept.
What is missing from picture is communication with Claims Provider which actually gives SAML claims for user.

If you want get this working like federation to Office 365 you also need these:
  • ADFS server to customer's network where user actually can be authenticated using they own domain's accounts.
    • On picture above that means that after Step 3, ADFS would redirect user's browser first to customer's ADFS server and wait that it comes back with correct ADFS claim from there.
  • Because we want use Kerberos delegation to back-end service(s) you need have users created to Cloud environment's Active Directory with same identifier field (best practice is use UPN) than them are on customer's domain.
    • Important notes is that these are standard based solutions. Which means that you can use any SAML 2.0 product (ADFS, Shibboleth,etc) on you or customer's side and you can mix them if needed. And on customer's side can be any directory (Active Directory, OpenLDAP, SQL, etc) where you can get authentication information. 

Configuring

Next I will explain for you step by step how configure this concept to lab environment. I will use one empty IIS server on this example

I used totally empty Netscaler for building this lab so all needed steps should be on this guide. I used Netscaler's 10.1 version but all configurations are done from command line so them should works at least on all 10.x versions.

On this example Domain Controller, IIS server and Netscaler are all part of same Active Directory domain (yes, we will join Netscaler to domain :) )

Basic configs

Because Netscaler need get Kerberos tickets from domain controllers it need to have working DNS settings. And because on Active Directory domain Kerberos tickets are only valid for five minutes (default setting) Netscaler's clock must be on same time with domain.

You can configure both of these things using following commands:
add dns nameServer 192.168.100.11
add dns suffix contoso.com
add ntp server 192.168.100.11

We also need create virtual server front of real IIS server using Netscaler.
You can create this using normal procedure but there is two important things what you should remember.
  1. You must create server record to Netscaler instead of using destination server's IP addresses directly on service.
  2. You must user server's real hostname on server record.
    1. That mean that you can't use example "srv_" prefix on server records.
    2. This is important because Netscaler will request Kerberos tickets for that hostname so if it isn't exactly same than server's real name, them domain controller will reject that request.



I created *.contoso.com certificate to Netscaler and imported it using wildcard keypair name and all servers Trusted Root Certificatest. That solved all certificate problems what I was on this lab.

Easiest way what I know is generate self-signed certificate using following PowerShell command (PowerShell 4.0 is needed):
New-SelfSignedCertificate -DnsName *.contoso.com -CertStoreLocation cert:\LocalMachine\My
Then you can export certificate on PFX format and import that to Netscaler accordance with this instruction: http://support.citrix.com/article/CTX136444


I used following commands for configure IIS service load balancing (and enabling LB feature).
enable feature LB
enable feature SSL
enable feature AAA

add server IIS 192.168.100.21
add service svc_IIS IIS HTTP 80
add lb vserver vsrv_IIS SSL 192.168.100.20 443 -persistenceType NONE
bind lb vserver vsrv_IIS svc_IIS 
bind service svc_IIS -monitorName http
set ssl vserver vsrv_IIS -tls11 DISABLED -tls12 DISABLED
bind ssl vserver vsrv_IIS -certkeyName wildcard
On this point is good idea create DNS record for your web page and check that you can connect to it. I'm using url https://iis.contoso.com on this example.

Creating authentication vserver

We need authentication vserver on this concept so I created that one next.
I configured it firstly to use LDAP authentication because it is must easier configure than SAML so I was able to test that auth vserver works.

There is good guide for this part on here so I don't explain this part more but my commands are below: http://support.citrix.com/article/CTX126852

add authentication vserver auth_vsrv SSL 192.168.100.30 443 -AuthenticationDomain contoso.com
bind ssl vserver auth_vsrv -certkeyName wildcard

add authentication ldapAction auth_ldap_srv -serverIP 192.168.100.11 -ldapBase "dc=contoso,dc=local" -ldapBindDn ns@contoso.local -ldapBindDnPassword Password1 -ldapLoginName samAccountName
add authentication ldapPolicy auth_ldap_policy ns_true auth_ldap_srv
bind authentication vserver auth_vsrv -policy auth_ldap_policy -priority 100

add tm sessionAction sessionLDAPSSO -SSO ON -ssoCredential PRIMARY -ssoDomain contoso.local
add tm sessionPolicy sessionLDAPSSO ns_true sessionLDAPSSO
bind authentication vserver auth_vsrv -policy sessionLDAPSSO -priority 1

When authentication vserver was ready I enabled it to my IIS page using following command and tested that authentication using username and password works.
set lb vserver vsrv_IIS -AuthenticationHost auth.contoso.com -Authentication ON -authnVsName auth_vsrv

Configuring SAML support to Netscaler

Here is guide how configure SAML support to Netscaler: http://support.citrix.com/article/CTX133919

You can follow that guide but there is one important note "Metadata file is not created by default. NetScaler administrator has to create the metadata file".

That guide also contains example about metadata file but it is on screenshot format and guide actually doesn't explain very well what that file should contain. So if you are not familiar with SAML protocol it can be hard get it done.


That why I will provide for you my Netscaler's metadata file from my lab and try explain all relevant part from it.

First of all, you need give some DNS name for your Netscaler SAML IDP. You can use same IDP for multiple URLs as long all of them can use same ADFS (or any SAML provider) policies.


I used DNS name nsidp.contoso.com on this example. You don't need configure that name to DNS but it will be included to SAML signing certificate. SAML certificate can be self-signed because only other SAML providers (ADFS on this example) need to be trust it and it will be included to metadata xml. I used same method than earlier for generating this certificate.

After that I exported nsidp.contoso.com certificate again from server but now only public key and saved it on base64 encoded format.

Then I opened that .cer file on notepad, removed all end of line marks from it and copied certificate without headers to metadata XML.


Whole my metadata file is visible on here:
Important settings on that file are:
  • entityID
    • This is your Netscaler IDPs unique identity. That will be send to ADFS on all requests so it know which policy it should use.
  • ds:X509SubjectName
    • Your IDPs name.
  • ds:X509Certificate
    • Your IDPs public certificate.
  • md:AssertionConsumerService
    • This is url where ADFS will redirect user session after successfully authentication. Netscaler will send this url to ADFS on all requests but ADFS reject them if url are not configured to it.
    • URL will be automatically generated to all sites where you are using  SAML authentication.
    • You must add new url to metadata every time when you add new vserver to use SAML authentication. Each url must have unique index.
When metadata file is ready you can import it to relaying party trusts on ADFS console and follow the guide about all other steps.

Because Netscaler's certificate is self-signed, I also disabled it's CRL check using following PowerShell command on ADFS server:
Set-AdfsRelyingPartyTrust -SigningCertificateRevocationCheck None -TargetName nsidp.training.lab


ADFS server's signing certicate I uploaded to Netscaler and configured ADFS server to Netscaler's claims provider trust using following commands:
add ssl certKey adfs-signing -cert adfs-signing.cer 
add authentication samlAction auth_saml -samlIdPCertName adfs-signing -samlSigningCertName nsidp -samlRedirectUrl "https://adfs.contoso.com/adfs/ls/" -samlUserField "Name ID" -samlIssuerName auth.contoso.com


Change authentication vserver to use SAML authentication

On this point I created new authentication policy which are using SAML and changed authentication vserver to use it.
unbind authentication vserver auth_vsrv -policy auth_ldap_policy

add authentication samlPolicy auth_saml_policy ns_true auth_saml
bind authentication vserver auth_vsrv -policy auth_saml_policy

Now you should be able to connect your web page using ADFS federation. If it works you probably need test that using some browser which not do automatic login to ADFS server. Other way you can't see was ADFS used or not.


Next steps are join Netscaler to domain and generate needed Kerberos configurations.
I will write this guides part 2 about them later.

13 comments:

  1. Hi Ollie

    Please tell me you have written part 2!!! This is exactly what I need now! Does the NS have to become a IDP or can it just be a SP for ADFS?

    Great post

    ReplyDelete
    Replies
    1. Hi Mark,

      Nice to see that you have found my blog and think that there is usefull information :)
      Second part is almost done. Hopefully I can release it on this week.

      I found one problem what I needed escalate to Citrix support but it is now resolved.


      Actually on this schenario ADFS is IDP and Netscaler is SP.

      Delete
  2. That's great news! I look forward to reading part 2.

    ReplyDelete
  3. Olli , are you using 10.5.x or 10.1.x version of the netscaler? We have found 10.5.50.10 does not with this solution. 10.1.124.1308 version works a charm.

    ReplyDelete
    Replies
    1. First I used 10.1.x (I don't remember exact number) version and when there was problems with session handling I upgraded to 10.5.50.10 version.

      I started from scratch when I finalized second part so configuration here should works with 10.5.50.10.

      Which kind problems you have with that 10.5.x version?

      Delete
  4. Thanks Olli. its was my SPNs that I had wrong. All working great now.

    ReplyDelete
  5. Hi Olli,
    Great post! :-)
    I have one question: You are using only one domain: contoso.com. Would your setup also work for multiple domains? Would SSO work not only for contoso.com but also for other domains that belong to my organization?
    Thanks
    Henk

    ReplyDelete
    Replies
    1. Hi

      You have two options:
      1. If you have child domains like corp.contoso.com they some work using same configuration.
      2. If you have separated domains then you need configure all of them to Netscaler.

      You also need DNS server which can resolve names from all domains and then use that one on Netscaler.

      Delete
  6. Hi Ollie,
    We have a similar requirement for an app that does not support saml. I am a little unclear from above if the adfs domain can be external to an organisation that is hosting the non-saml all. ie need need NetScaler to auth a user against external domain using saml, and the allow that user access to the internal hosted app. From above will this work if upn is the same on external directory and an account exists with same upn on internal directory.
    ps did you ever publish 2nd part

    ReplyDelete
    Replies
    1. Hi Robert,
      Sorry about late answer.

      I would say that you need to have application server (IIS) and Netscaler part of same domain. But Netscaler and ADFS (etc) can be part of different domains as long usernames are on same format.

      You can find part 2 from here: http://olli.problem.fi/2014/10/how-to-build-adfs-saml-20-to-kcd-proxy.html

      Delete
  7. This comment has been removed by the author.

    ReplyDelete
  8. This comment has been removed by the author.

    ReplyDelete
  9. Hi Olli,

    It was very informative and thanks for the great effort! we are trying to configure a similar set up where liferay portal acts as a IDP and Netscaler acts a SP and Share point as a service.

    The share point service is hosted on Azure, so we are configures the Azure LB IP as a service on the Netscaler, instead of the direct share point servers. The other configurations are the same, but the target page pops up for credentials(no SSO). Can you update if the kerberos delegation would happen properly for the Azure LB as well. Any suggestions to achieve SSO on this setup is welcome.

    Looking forward for your reply! Thanks in Advance!

    ReplyDelete