PIV-I Identity Provider: Difference between revisions

From NIEF Wiki
Jump to navigation Jump to search
 
(19 intermediate revisions by 2 users not shown)
Line 1: Line 1:
This guide describes how one can implement a NIEF compliant Identity Provider that authenticates users who possess PIV-I cards that have been cross certified with the Federal Bridge PKI.  
This guide describes how to implement a NIEF SAML Identity Provider (IDP) system that authenticates Personal Identification Verification Interoperable (PIV-I) cardholders using the Federal Bridge PKI Certificate Authority (CA).


== Background ==
== Background ==


Personal Identification Verification Interoperable (PIV-I) cards are smart cards issued by various organizations, typically operating at the state and local government level.  The standard is designed to be aligned/interoperable with the Federal standard for PIV.  Supporting this type of user base with a turnkey Identity Provider capability has tremendous value.
PIV-I is a standard for smart cards issued by various non-federal organizations, typically operating at the state and local government level.  The PIV-I standard is designed to be aligned/interoperable with the federal standard for PIV.  There is tremendous information sharing value in being able to offer a turnkey SAML IDP capability to organizations that play a stakeholder role in the PIV-I cardholder community. This PIV-I IDP Implementation Guide provides detailed technical instructions that these PIV-I stakeholders can use to build such a capability and deploy it within NIEF.
 
This guide is designed around the use of free and open source software, primarily focusing on the use of the following:


This implementation guide is designed around the use of free and open sourced capabilities, primarily focusing on the use of the following:
* [https://www.shibboleth.net/products/identity-provider/ Shibboleth Identity Provider]
* [https://www.shibboleth.net/products/identity-provider/ Shibboleth Identity Provider]
* [https://httpd.apache.org/ Apache HTTP Server]
* [https://httpd.apache.org/ Apache HTTP Server]
Line 12: Line 13:
== Getting Started ==
== Getting Started ==


This guide assumes the user is comfortable deploying a Linux (or equivalent) server with Apache HTTP, Java, and Tomcat.  No specific Shibboleth experience is required to follow this guide.  If a user is not comfortable deploying the prerequisites, they should acquire that experience or collaborate with [mailto:help@nief.org help@nief.org] before attempting to follow this guide. The authors of this guide tested this deploy guide with [https://www.centos.org/ CentOS 7], but any modern Linux distribution that includes packages for the Apache HTTP Server is expected to work. It is likely also possible to do deploy to a Windows or other server environment as long as the deployer is able to adapt the HTTP configuration steps accordingly and that Java 8 is available for running Apache Tomcat and Shibboleth.
This guide assumes the user is comfortable deploying a [https://en.wikipedia.org/wiki/Linux Linux] (or equivalent) server with Apache HTTP Server, [https://en.wikipedia.org/wiki/Java_(software_platform) Java], and Apache Tomcat.  No specific Shibboleth experience is required to follow this guide; however, if you are not comfortable deploying the prerequisites (Linux, Apache, Java, and Tomcat), then you should either acquire that experience or reach out to [mailto:help@nief.org help@nief.org] for assistance before you attempt to follow this guide. We have tested this guide with [https://www.centos.org/ CentOS 7 Linux], but any modern Linux distribution that includes packages for the Apache HTTP Server should work. It is likely also possible to deploy within a Windows environment or other server environment, as long as you are able to adapt the HTTP configuration steps accordingly and as long as Java 8 is available for running Apache Tomcat and Shibboleth.


== Enabling Authentication ==
== Enabling Authentication ==


The following describes how to enable client certificate authentication within the Apache HTTP server.  The server will need a valid server certificate in addition to all of this configuration, but the server certificate does not need to be issued by the same chain (in fact, it rarely should be as the server certificate should come from a well known CA, and the client certificates should come from an organizational CA).  
The following section describes how to enable client certificate authentication (CCA) within the Apache HTTP Server.  The server will need a valid server certificate in addition to all of this configuration, but the server certificate does not need to be issued by the same chain. In fact, it usually should NOT be from the same certificate chain, as the server certificate should come from a well-known CA (e.g., [https://letsencrypt.org/ Let's Encrypt]), and the client certificates should come from an organizational CA.


=== Certificate Authority Specification ===
=== Certificate Authority Specification ===


Apache requires the full certificate chain including an anchor (self signed certificate) to be specified in the HTTP Server configuration.  This is an important thing to understand as typically with PIV-I (and PIV), you are working with cross certified CAs, and if you only include cross certified certs in the CA certificate chain, Apache will fail with errors about chain length being too long (it gets stuck in a loop going through the chain back and forth).   
Apache requires the full certificate chain, including an anchor (self-signed certificate), to be specified in the HTTP Server configuration.  This is an important thing to understand, as typically with PIV-I (and with PIV) you are working with cross certified CAs, and if you only include cross certified certs in the CA certificate chain, Apache will fail with errors about chain length being too long (it gets stuck in a loop going through the chain back and forth).   


Here is a copy of a valid chain (uni-directional chain) from the FTI Test CA to the Federal Test PKI CA: [[File:fti-test-ca-chain.txt]].
Here is a copy of a sample valid chain (uni-directional chain) from the Foundation for Trusted Identity (FTI) Test CA to the Federal Test PKI CA: [[File:fti-test-ca-chain.txt]].


Within the Apache configuration, typically within the file '''ssl.conf''' you specify this CA file like this:
Within the Apache configuration, typically within the file '''ssl.conf''' you specify this CA file like this:
Line 28: Line 29:
     SSLCACertificateFile /etc/httpd/trust/fti-test-ca-chain.pem
     SSLCACertificateFile /etc/httpd/trust/fti-test-ca-chain.pem


For a production deploy the CA chain would be different and will need to be constructed by following the chain and combining the certificates into a single PEM file.
For a production deployment, the CA chain would be different and would need to be constructed by following the chain and combining the certificates into a single PEM file.


=== Certificate Status / Revocation Checking ===
=== Certificate Status / Revocation Checking ===


If OCSP (online certificate status protocol) is available for verifying a certificate is current then it is the simplest option to enable it with a single Apache HTTP Server directive:
If Online Certificate Status Protocol (OCSP) is available for verifying that a certificate is current, then it is the simplest option to enable it with a single Apache HTTP Server directive:


     SSLOCSPEnable On
     SSLOCSPEnable On


In some cases (for example the current test CA chain) OCSP is not fully implemented and it's necessary to instead use CRL (Certificate Revocation List) checking.  This is enabled within the the Apache HTTP Server configuration:
In some cases (for example, in the current test CA chain), OCSP is not fully implemented, and it is necessary to instead use CRL (Certificate Revocation List) checking.  This is enabled within the the Apache HTTP Server configuration:


     SSLCARevocationFile /etc/httpd/trust/fti-crl.pem
     SSLCARevocationFile /etc/httpd/trust/fti-crl.pem


This file has to be updated regularly as it only works if it is current, and by design the file has an expiration date to insure software checking against the CRL is using a current copy of the CRL.  The following script may be useful in configuring this in an automated fashion:
This file must be updated regularly, as it only works if it is current, and by design the file has an expiration date to ensure software checking against the CRL is using a current copy of the CRL.  The following script may be useful in configuring this in an automated fashion:


     #!/bin/bash
     #!/bin/bash
Line 49: Line 50:
     systemctl restart httpd
     systemctl restart httpd


A script such as this can then be configured in a crontab to insure the CRL is up to date.
A script such as this can then be configured in a crontab to ensure the CRL is up to date.


=== Configuring Client Certificate Authentication ===
=== Configuring Client Certificate Authentication (CCA) ===


It is very rare that you will want to require client certificate authentication for the entire server, typically client certificate authentication is constrained to specific URL paths.  At the top level of the HTTP Server SSL configuration you should include this directive:
It is very rare that you will want to require CCA for the entire server. Typically, CCA is constrained to specific URL paths.  At the top level of the HTTP Server SSL configuration, you should include this directive:


     SSLVerifyClient none
     SSLVerifyClient none


Possibly in another configuration file (or in another section of the SSL configuration file) you would enable TLS client certificate authentication like this:
Possibly in another configuration file (or in another section of the SSL configuration file) you would enable TLS CCA like this:


   <Location "/pivi-test">
   <Location "/pivi-test">
Line 65: Line 66:
   </Location>
   </Location>


Putting a simple test page at the location used for testing is a useful way to verify all Apache HTTP Server configuration is correct.  As long as this test page is only viewable after engaging in PIV-I authentication, then you know that the server is configured correctly.
A useful way to verify all Apache HTTP Server configuration is correct is to put a simple test page at the location used for testing.  As long as this test page is only viewable after engaging in PIV-I authentication, you know that the server is configured correctly.


To enable client certificate authentication for use by the Shibboleth IDP, you will need a section like the following (the path could be different if the IDP was installed to a non-standard URL):
To enable CCA for use by the Shibboleth IDP, you will need a section like the following (the path could be different if the IDP was installed to a non-standard URL):


   <Location "/idp/Authn/X509">
   <Location "/idp/Authn/X509">
Line 75: Line 76:
   </Location>
   </Location>


== Installing Shibboleth ==
== Installing Shibboleth ==
 
Prior to installing Shibboleth, Java needs to be available (for most Linux distrubtions java-1.8.0-openjdk is a viable package, java-11-openjdk likely viable as well). 
 
Specify how to run the installer.  Specify how to enable trusted partners.  Specify how to enable X.509 Authn.  Specify how to enable Shibboleth within Apache Tomcat.


Prior to installing Shibboleth, Java must be available. For most Linux distrubtions java-1.8.0-openjdk is a viable package; java-11-openjdk likely viable as well.


=== Getting Shibboleth ===
=== Downloading Shibboleth ===


The latest version of the Shibboleth Identity Provider is available for download here: [https://shibboleth.net/downloads/identity-provider/latest/ https://shibboleth.net/downloads/identity-provider/latest/].  
The latest version of the Shibboleth IDP is available for download here: [https://shibboleth.net/downloads/identity-provider/latest/ https://shibboleth.net/downloads/identity-provider/latest/].  


The [https://wiki.shibboleth.net/confluence/display/IDP30 Shibboleth Wiki] is an absolutely critical resource for understanding components and how to operate a Shibboleth IDP. While some configuration and installation things will be specified in this guide, many subtle things may be overlooked and the content of the [https://wiki.shibboleth.net/confluence/display/IDP30 Shibboleth Wiki] will almost always be more up to date and useful than this guide.
The [https://wiki.shibboleth.net/confluence/display/IDP30 Shibboleth Wiki] is a critical resource for understanding components and how to operate a Shibboleth IDP. While some configuration and installation details are specified in this guide, many other subtle details may be overlooked, and the content of the [https://wiki.shibboleth.net/confluence/display/IDP30 Shibboleth Wiki] is almost always fresher and more useful than this guide.


=== Running Installer ===
=== Running the Shibboleth Installer ===


Once you have downloaded and extracted the installer, you run it as seen below.  You  may need to define JAVA_HOME based on the installed Java package. The values that should populate each question should all be largely self explanatory.   
After you have downloaded and extracted the installer, run it as seen below.  You  may need to define JAVA_HOME based on the installed Java package. The values that should populate each question should all be largely self explanatory.   


     [shibboleth-identity-provider-3.4.3]# bin/install.sh
     [shibboleth-identity-provider-3.4.3]# bin/install.sh
Line 132: Line 130:
All further configuration is handled by editing the installed configuration files in the chosen installation directory's '''conf''' directory.
All further configuration is handled by editing the installed configuration files in the chosen installation directory's '''conf''' directory.


=== Configuring Authentication ===
=== Configuring Shibboleth Authentication ===


To enable X.509 client certificate authentication you must specify it in the '''conf/idp.properties''' file (it defaults to using the Password login flow):  
To enable X.509 CCA, you must specify it in the '''conf/idp.properties''' file (it defaults to using the Password login flow):  


     # Regular expression matching login flows to enable, e.g. IPAddress|Password
     # Regular expression matching login flows to enable, e.g. IPAddress|Password
     idp.authn.flows=X509
     idp.authn.flows=X509


Then you must configure the mechanism for determining the user identity based on the certificate.  There is significant flexibility in how the certificate is parsed and that is configured in '''conf/c14n/x500-subject-c14n-config.xml'''.  Within this file you can parse out certificate fields by OID and/or by Subject Alt Name Types.  The recommended mechanism for production is to be determined, but for the test environment, the best option was to use the email subject alt name type.  Enable this by removing the XML comments around the value:
Then you must configure the mechanism for determining the user identity based on the certificate.  There is significant flexibility in how the certificate is parsed, and that is configured in '''conf/c14n/x500-subject-c14n-config.xml'''.  Within this file you can parse out certificate fields by OID and/or by Subject Alt Name Types.  The recommended mechanism for production is TBD, but in a test environment, the best option is to use the email subject alt name type.  Enable this by removing the XML comments around the value:


     &lt;!-- First priority is given to any subjectAltNames specified (emailAddress is 1) --&gt;
     &lt;!-- First priority is given to any subjectAltNames specified (emailAddress is 1) --&gt;
Line 146: Line 144:
     &lt;/util:list&gt;
     &lt;/util:list&gt;


=== Configuring Trust ===
=== Configuring Shibboleth Trust with Partner Systems ===


There are many ways to enable trusted partners, and much of that can be read about on the [https://wiki.shibboleth.net/confluence/display/IDP30 Shibboleth Wiki], but for our purposes we are simply documenting how to quickly enable trust of the NIEF Testbed or NIEF Production environment.  This configuration is done within the '''conf/metadata-providers.xml''' file.  You will need to enable the Metadata Provider that looks like this (by removing the comments):
There are many ways to enable trusted partners, and you can read about this in detail on the [https://wiki.shibboleth.net/confluence/display/IDP30 Shibboleth Wiki]. But for our purposes, we are simply documenting how to quickly enable trust of the NIEF Testbed or NIEF Production environment.  This configuration is done within the '''conf/metadata-providers.xml''' file.  You need to enable the Metadata Provider that looks like this (by removing the comments):


     <font style="color:red;">&lt;!--</font>
     <font style="color:red;">&lt;!--</font>
Line 164: Line 162:
     <font style="color:red;">--&gt;</font>
     <font style="color:red;">--&gt;</font>


The metadataURL is [http://ref.gfipm.net/gfipm-signed-ref-metadata.xml http://ref.gfipm.net/gfipm-signed-ref-metadata.xml] for the NIEF Testbed and [https://nief.org/trust-fabric/nief-trust-fabric.xml https://nief.org/trust-fabric/nief-trust-fabric.xml] for NIEF in production.  The signing certificates for each are [http://ref.gfipm.net/ref-gfipm-ca.crt http://ref.gfipm.net/ref-gfipm-ca.crt] and [https://nief.org/trust-fabric/nief-ca.crt https://nief.org/trust-fabric/nief-ca.crt] respectively.  You will also need to either bump up the max validity interval for NIEF to 45 days or simply remove it in the case of the NIEF Test Bed which typically allows trust fabric to last for a year or more.  The following is a fully configured one for the NIEF Testbed with inline certificate:
The metadataURL is [http://ref.gfipm.net/gfipm-signed-ref-metadata.xml http://ref.gfipm.net/gfipm-signed-ref-metadata.xml] for the NIEF Testbed and [https://nief.org/trust-fabric/nief-trust-fabric.xml https://nief.org/trust-fabric/nief-trust-fabric.xml] for NIEF in production.  The signing certificates for each are [http://ref.gfipm.net/ref-gfipm-ca.crt http://ref.gfipm.net/ref-gfipm-ca.crt] and [https://nief.org/trust-fabric/nief-ca.crt https://nief.org/trust-fabric/nief-ca.crt] respectively.  You also need to either increase the max validity interval for NIEF to 45 days or simply remove it in the case of the NIEF Testbed which typically allows trust fabric to last for a year or more.  The following is a fully configured example for the NIEF Testbed with inline certificate:


         <MetadataProvider id="nief-testbed"
         <MetadataProvider id="nief-testbed"
Line 192: Line 190:
         </MetadataProvider>
         </MetadataProvider>


And a sample provider for NIEF production:
Here is a sample provider for NIEF production:


     <MetadataProvider id="nief-main"
     <MetadataProvider id="nief-main"
Line 201: Line 199:
                       requireSignedRoot="true">
                       requireSignedRoot="true">
                       <PublicKey>
                       <PublicKey>
                      MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAsTMoQtZ+IHOFO3iWZX/E
                          MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA1fJixy7bY8R6nMXzNVrI
                      0YJ8s/S+xQuAsrQfcg6kZdL7gP1l2tRfe9nilYvN//bZndECw+/t7P/NkZ0apbUw
                          Zu8bfOeu2vSasiNCQafvOcZSYj1n3wYuvS/kuIUFQ8tQyOWJjTsuUE7wEIkUmo6C
                      W/h55KuDyM0sK60PSiBb5KFeHHil8yLoim//cjJkP1RkiWFpA3yDV/e0BwSg4eqh
                          sFh8tO9z0uJFBlicg//mlKRVCrRkXrwR7ScQMli4uVxFCHp6pEFqYLPx0nbENL36
                      gH2lh96dYgUfnUZds4+NFAl6F6AoQgdUPDuVFt68q9KN/Vw7D6Ahhiu2uJsFSn/s
                          kAOebTZpBhs2qPFk/KuVFrGx9VqZ//UiwjICL8aBAuxbi+Orvwe5OfttaSnn6bym
                      8S/7Jtq03TzonWXSI3E3O7t/cHsjpBQ374URQDZE8C2Wuss82TkdP0B3hvSjbJjx
                          Kl95i47wz6m1MfwzYJiWEritSmAodcDbGT49jG64+SItmT4O1YGRx7EtxwvYd9Ug
                      SINVQzThlqAUu8oV6A+/RhQoQjbdEnalf4/Q+iaglsTUDVZIA5JQ24+acse9XwoX
                          94LfOrsd3TgbMW6jpAfXxVuR9DX210haba2l47F14MeB3/VKbGGUqXThvP21Zfsd
                      7gvQlvQlomqKKqx7ICbR0ixjfvxAW24sfTi7vaEY6wTZvBlZpQqS6qZb/AdbOIPz
                          gQmfYPqmcNFQLLX59z+5iVujn6isZ0IUXl7VUVJFo259tph4f2FZeQaAxrYxynoF
                      ww2MmYXp+LDHJl6micpahQbUKcPjreOsOOK7T09d0CfV3p16ppVFZx1u4KsgqhQ6
                          ENCvaDVEXI7XHQjhK0LV096DOK9F4FO3zwoPxa3EWc1ilAdzG4dQpMq7wQkn+K0v
                      hku+AW2g+gTSvALa80kIOEyDETDbYSdp5DkVL1yBY0Q5DyLmlpMjAqznK6ehRIEY
                          6VL0rwSzz12aLS4/TIrPDcs8zTUz8QDbo1qcdCx2ABk2S0e01cQXCqaeqB8PZOmb
                      nD1BYw7q75xnr7FMIlYKB+WlMhVhI71/QkZXkWh8szkN0EzrKqTU2mXNrWfiZA76
                          gIK35Bdoh7g+4M9/V2agl9ohb+HDNktowESbJn2yrG3rizcuhR++t/IZ36PG0LVv
                      53ABqsoA5nyBjurxWFljFqVSLtN+kslf6a/904FvdUrhQFupPoZZVJq2sBLRAJku
                          3yL4/UikxcLNkQSQktou6D27OFVdGT7XGZtByuFZCg78PtbChZGZfTUJYZOq7E+A
                      o9lfBUOGVkpZQ1MsENaBjusCAwEAAQ==
                          EQSq3FyoF7lJ6RYXNqEl7F0CAwEAAQ==
                       </PublicKey>
                       </PublicKey>
               </MetadataFilter>
               </MetadataFilter>
Line 221: Line 219:
       </MetadataProvider>
       </MetadataProvider>


=== Running ===
=== Running Shibboleth ===


The Shibboleth IDP can likely run in any supported servlet container. For simplicity sake, these instructions assume the use of [https://tomcat.apache.org/download-80.cgi Apache Tomcat 8]. The simplest and quickest way to enable the IDP within Tomcat is to create a file callsed '''idp.xml''' in the '''[TOMCAT_HOME]/conf/Catalina/localhost''' directory.  The contents of this file will specify the war file like this (the path specified in docBase will likely need to be updated to the installation path of Shibboleth):
The Shibboleth IDP can likely run in any supported servlet container. For simplicity's sake, these instructions assume the use of [https://tomcat.apache.org/download-80.cgi Apache Tomcat 8]. The simplest and quickest way to enable the IDP within Tomcat is to create a file named '''idp.xml''' in the '''[TOMCAT_HOME]/conf/Catalina/localhost''' directory.  The contents of this file specify the war file like this (the path specified in docBase will likely need to be updated to the installation path of Shibboleth):


     <Context docBase="/opt/idp/war/idp.war"
     <Context docBase="/opt/idp/war/idp.war"
Line 230: Line 228:
         swallowOutput="true" />
         swallowOutput="true" />


As Tomcat is more frequently installed directly as opposed to via a package manager, it may be useful to have a Linux startup script. One can be downloaded [File:tomcat.txt here].
Since it is more common to install Tomcat directly rather than via a package manager, it may be useful to have a Linux startup script. One can be downloaded here: [[File:tomcat.sh]].
 
=== Proxying Shibboleth ===
 
Assuming Apache httpd was used from the earlier section as the web server, you will need to configure it to proxy the application server that runs the IDP.  This is typically done with a small snippet of proxy configuration within Apache configuration files:
 
  <Location /idp>
    ProxyPass ajp://localhost:8009/idp
  </Location>


== Configuring NIEF Attributes ==
== Configuring NIEF Attributes ==


TBDExplain how attribute resolution worksExplain how attribute filtering worksPointers to existing connectors on github.  Pointers to documentation on the Shibboleth wiki.
Shibboleth supports a rich XML configured and API driven capability for attribute resolutionAttributes can be filtered by relying party, by user, or conditionally based on various logic.  The attribute values can be sourced from nearly anywhere, as long as code can be written to interact with the source (e.g., databases, web services, directories, programmatic derivation, etc.)
 
=== Attribute Filtering ===
 
Within the configuration file '''conf/attribute-filter.xml''' you can specify attribute release policies.  The simplest such policy is to release all configured attributes to all trusted partnersA slightly more sophisticated example, that filters based on test user accounts and assumes a specific test attribute set, is available for download here: [[File:attribute-filter.xml]].
 
=== Attribute Resolution ===
 
Within the configuration file '''conf/attribute-resolver.xml''' you specify attributes and how to resolve their values.  This is one of the most complex and flexible configuration points for Shibboleth, and detailed documentation is available on the [https://wiki.shibboleth.net/confluence/display/IDP30/AttributeResolverConfiguration Shibboleth Wiki].  The flexibility is nearly endless, given the ability to write scripts and custom data connectors.  Two samples are available here:
 
# This sample is an extremely simple sample that sends the UserName and a couple of statically defined attributes: [[File:minimum-resolver.xml]].
# This complicated sample configuration file sources attributes from a SQL database, statically for the organization, and from the filesystem in user files is available for download here: [[File:attribute-resolver.xml]].
 
=== Data Connectors ===
 
Shibboleth supports the development of new data connectors using their integration APIsGTRI has developed many such data connectors over the years, and they are available for download on github:
 
* [https://github.com/gtkrug/txdps-shib3 Texas DPS Data Connectors] - This project consists of three data connectors developed for Texas DPS and supports querying two different web services, one external and one internal, as well as a copy of the GTRI local file system data connector, useful for testing.
* [https://github.com/gtkrug/gfipm-shib3-test-dc GTRI Test Data Connector] - This is a simple test data connector, but also offers a convenient reference for implementing additional web services, as it is a simple sample of the API.
* [https://github.com/gtkrug/bae-shib3 BAE Data Connector] - This data connector functions as a Backend Attribute Exchange (BAE) clientIt is rather outdated and has really only ever been tested with the retired BAE service from IIR.  <font color="red">NOT recommended for use</font>.
* [[Shibboleth HTTP Dataconnector]] - This is a capability of Shibboleth to use a combination of Javascript and templates to call webservices to retrieve attributes.  The link will lead to a sample GTRI created for using the IIR 28 CFR service.


== Testing ==
== Testing ==


Just link to the NIEF Testbed part of the wiki.
It is always a good idea to test and validate a new IDP deployment within a test environment. The [[NIEF Testbed]] is intended for exactly this purpose.

Latest revision as of 19:35, 24 September 2019

This guide describes how to implement a NIEF SAML Identity Provider (IDP) system that authenticates Personal Identification Verification Interoperable (PIV-I) cardholders using the Federal Bridge PKI Certificate Authority (CA).

Background

PIV-I is a standard for smart cards issued by various non-federal organizations, typically operating at the state and local government level. The PIV-I standard is designed to be aligned/interoperable with the federal standard for PIV. There is tremendous information sharing value in being able to offer a turnkey SAML IDP capability to organizations that play a stakeholder role in the PIV-I cardholder community. This PIV-I IDP Implementation Guide provides detailed technical instructions that these PIV-I stakeholders can use to build such a capability and deploy it within NIEF.

This guide is designed around the use of free and open source software, primarily focusing on the use of the following:

Getting Started

This guide assumes the user is comfortable deploying a Linux (or equivalent) server with Apache HTTP Server, Java, and Apache Tomcat. No specific Shibboleth experience is required to follow this guide; however, if you are not comfortable deploying the prerequisites (Linux, Apache, Java, and Tomcat), then you should either acquire that experience or reach out to help@nief.org for assistance before you attempt to follow this guide. We have tested this guide with CentOS 7 Linux, but any modern Linux distribution that includes packages for the Apache HTTP Server should work. It is likely also possible to deploy within a Windows environment or other server environment, as long as you are able to adapt the HTTP configuration steps accordingly and as long as Java 8 is available for running Apache Tomcat and Shibboleth.

Enabling Authentication

The following section describes how to enable client certificate authentication (CCA) within the Apache HTTP Server. The server will need a valid server certificate in addition to all of this configuration, but the server certificate does not need to be issued by the same chain. In fact, it usually should NOT be from the same certificate chain, as the server certificate should come from a well-known CA (e.g., Let's Encrypt), and the client certificates should come from an organizational CA.

Certificate Authority Specification

Apache requires the full certificate chain, including an anchor (self-signed certificate), to be specified in the HTTP Server configuration. This is an important thing to understand, as typically with PIV-I (and with PIV) you are working with cross certified CAs, and if you only include cross certified certs in the CA certificate chain, Apache will fail with errors about chain length being too long (it gets stuck in a loop going through the chain back and forth).

Here is a copy of a sample valid chain (uni-directional chain) from the Foundation for Trusted Identity (FTI) Test CA to the Federal Test PKI CA: File:Fti-test-ca-chain.txt.

Within the Apache configuration, typically within the file ssl.conf you specify this CA file like this:

    SSLCACertificateFile /etc/httpd/trust/fti-test-ca-chain.pem

For a production deployment, the CA chain would be different and would need to be constructed by following the chain and combining the certificates into a single PEM file.

Certificate Status / Revocation Checking

If Online Certificate Status Protocol (OCSP) is available for verifying that a certificate is current, then it is the simplest option to enable it with a single Apache HTTP Server directive:

   SSLOCSPEnable On

In some cases (for example, in the current test CA chain), OCSP is not fully implemented, and it is necessary to instead use CRL (Certificate Revocation List) checking. This is enabled within the the Apache HTTP Server configuration:

   SSLCARevocationFile /etc/httpd/trust/fti-crl.pem

This file must be updated regularly, as it only works if it is current, and by design the file has an expiration date to ensure software checking against the CRL is using a current copy of the CRL. The following script may be useful in configuring this in an automated fashion:

   #!/bin/bash
   cd /etc/httpd/trust
   if [ -f FTITestCA.crl ]; then rm FTITestCA.crl; fi
   wget --quiet http://pki.fti.org/fti_ca/crl/FTITestCA.crl
   openssl crl -in FTITestCA.crl -inform DER -out fti-crl.pem
   systemctl restart httpd

A script such as this can then be configured in a crontab to ensure the CRL is up to date.

Configuring Client Certificate Authentication (CCA)

It is very rare that you will want to require CCA for the entire server. Typically, CCA is constrained to specific URL paths. At the top level of the HTTP Server SSL configuration, you should include this directive:

   SSLVerifyClient none

Possibly in another configuration file (or in another section of the SSL configuration file) you would enable TLS CCA like this:

  <Location "/pivi-test">
     SSLOptions +StdEnvVars +ExportCertData
     SSLVerifyClient require
     SSLVerifyDepth 4
  </Location>

A useful way to verify all Apache HTTP Server configuration is correct is to put a simple test page at the location used for testing. As long as this test page is only viewable after engaging in PIV-I authentication, you know that the server is configured correctly.

To enable CCA for use by the Shibboleth IDP, you will need a section like the following (the path could be different if the IDP was installed to a non-standard URL):

  <Location "/idp/Authn/X509">
     SSLOptions +StdEnvVars +ExportCertData
     SSLVerifyClient require
     SSLVerifyDepth 4
  </Location>

Installing Shibboleth

Prior to installing Shibboleth, Java must be available. For most Linux distrubtions java-1.8.0-openjdk is a viable package; java-11-openjdk likely viable as well.

Downloading Shibboleth

The latest version of the Shibboleth IDP is available for download here: https://shibboleth.net/downloads/identity-provider/latest/.

The Shibboleth Wiki is a critical resource for understanding components and how to operate a Shibboleth IDP. While some configuration and installation details are specified in this guide, many other subtle details may be overlooked, and the content of the Shibboleth Wiki is almost always fresher and more useful than this guide.

Running the Shibboleth Installer

After you have downloaded and extracted the installer, run it as seen below. You may need to define JAVA_HOME based on the installed Java package. The values that should populate each question should all be largely self explanatory.

   [shibboleth-identity-provider-3.4.3]# bin/install.sh
   Error: JAVA_HOME is not defined correctly.
     We cannot execute java
   shibboleth-identity-provider-3.4.3]# export JAVA_HOME=/etc/alternatives/jre_1.8.0/
   [shibboleth-identity-provider-3.4.3]# bin/install.sh
   Source (Distribution) Directory (press <enter> to accept default): [/home/krug/src/idp-install/shibboleth-identity-provider-3.4.3]
    
   Installation Directory: [/opt/shibboleth-idp]
    
   Hostname: [new.nief.org]
   piv.nief.org
   SAML EntityID: https://piv.nief.org/idp/shibboleth
    
   Attribute Scope: [nief.org]
   nief.org
   Backchannel PKCS12 Password:
   Re-enter password:
   Cookie Encryption Key Password:
   Re-enter password:
   Warning: /opt/shibboleth-idp/bin does not exist.
   Warning: /opt/shibboleth-idp/edit-webapp does not exist.
   Warning: /opt/shibboleth-idp/dist does not exist.
   Warning: /opt/shibboleth-idp/doc does not exist.
   Warning: /opt/shibboleth-idp/system does not exist.
   Generating Signing Key, CN = piv.nief.org URI = https://piv.nief.org/idp/shibboleth ...
   ...done
   Creating Encryption Key, CN = piv.nief.org URI = https://piv.nief.org/idp/shibboleth ...
   ...done
   Creating Backchannel keystore, CN = piv.nief.org URI = https://piv.nief.org/idp/shibboleth ...
   ...done
   Creating cookie encryption key files...
   ...done
   Rebuilding /opt/shibboleth-idp/war/idp.war ...
   ...done
    
   BUILD SUCCESSFUL
   Total time: 2 minutes 18 seconds

All further configuration is handled by editing the installed configuration files in the chosen installation directory's conf directory.

Configuring Shibboleth Authentication

To enable X.509 CCA, you must specify it in the conf/idp.properties file (it defaults to using the Password login flow):

   # Regular expression matching login flows to enable, e.g. IPAddress|Password
   idp.authn.flows=X509

Then you must configure the mechanism for determining the user identity based on the certificate. There is significant flexibility in how the certificate is parsed, and that is configured in conf/c14n/x500-subject-c14n-config.xml. Within this file you can parse out certificate fields by OID and/or by Subject Alt Name Types. The recommended mechanism for production is TBD, but in a test environment, the best option is to use the email subject alt name type. Enable this by removing the XML comments around the value:

   <!-- First priority is given to any subjectAltNames specified (emailAddress is 1) -->
   <util:list id="shibboleth.c14n.x500.SubjectAltNameTypes">
       <!-- <value>1</value> -->
   </util:list>

Configuring Shibboleth Trust with Partner Systems

There are many ways to enable trusted partners, and you can read about this in detail on the Shibboleth Wiki. But for our purposes, we are simply documenting how to quickly enable trust of the NIEF Testbed or NIEF Production environment. This configuration is done within the conf/metadata-providers.xml file. You need to enable the Metadata Provider that looks like this (by removing the comments):

   <!--
   <MetadataProvider id="HTTPMetadata"
                     xsi:type="FileBackedHTTPMetadataProvider"
                     backingFile="%{idp.home}/metadata/localCopyFromXYZHTTP.xml"
                     metadataURL="http://WHATEVER">
    
       <MetadataFilter xsi:type="SignatureValidation" certificateFile="%{idp.home}/credentials/metaroot.pem" />
       <MetadataFilter xsi:type="RequiredValidUntil" maxValidityInterval="P30D"/>
       <MetadataFilter xsi:type="EntityRoleWhiteList">
           <RetainedRole>md:SPSSODescriptor</RetainedRole>
       </MetadataFilter>
   </MetadataProvider>
   -->

The metadataURL is http://ref.gfipm.net/gfipm-signed-ref-metadata.xml for the NIEF Testbed and https://nief.org/trust-fabric/nief-trust-fabric.xml for NIEF in production. The signing certificates for each are http://ref.gfipm.net/ref-gfipm-ca.crt and https://nief.org/trust-fabric/nief-ca.crt respectively. You also need to either increase the max validity interval for NIEF to 45 days or simply remove it in the case of the NIEF Testbed which typically allows trust fabric to last for a year or more. The following is a fully configured example for the NIEF Testbed with inline certificate:

       <MetadataProvider id="nief-testbed"
                         xsi:type="FileBackedHTTPMetadataProvider"
                     backingFile="%{idp.home}/metadata/gfipm-ref-cache.xml"
                     metadataURL="https://ref.gfipm.net/gfipm-signed-ref-metadata.xml">
               <MetadataFilter xsi:type="SignatureValidation"
                       requireSignedRoot="true">
                       <PublicKey>
                       MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0j7Etpn++n6z/NPs5752
                       gdisHr9GwjFouKC12GIxK6bOwgMdNLvTfMp+34fwRGeKTkwM65zmNob6WXxDMZJE
                       KoaGg2UBYwaYsW/lc1ZPJpyEACTSgIxIJB4HNJuJYUm7uO5jebUevLVt091IE/6H
                       OpxuRQNKE753JJQprxTT5O/Kb8wXBTHNWMNtdpSgC38uv9Yt+vAnDYOkrZanr2de
                       jRFjxf3ZzkD4vihGCucEcjzt51IicDI/T/kjPLj9qvlb0z0NUxS/rikSahB0G6Qr
                       xw6DSutxq7vovfU3o3dFs2e6GQ19uB4ZjTF/6uXYD+BdKlaUgjwihZBb+mPv43sc
                       r9JWW2aShWs7ua9WihYfSCkbfj9zDPss25sCFdrVxpGYxdyYsF3FP2aWZJ9PaiaW
                       y6lFZ+Gkk5OT4DWT2vhFQBymSxHs4Id5tz/3jGepFwZf+Q7IhaluHaFWooOw4cHa
                       dfhx4oaMDrHe8N7OnVVrHJ5ChaGyYBA1Nk0xJZeBhF8HK9sNYdeYTYiqGYg6xkuu
                       a82lDtbqwMmt2FMHQn2glZorxpcKiJf9G6ucwbN7gdAAEeRkoUnF/rf0DZWyb5NF
                       GDJFqbx8mOtlFujT05NGq8l3oC5M3VKcnvlcuI6Ie9McentSGW+X0TrRbnoDn+lA
                       VJvBhHNjfJcC6UuwECkRvmUCAwEAAQ==
                       </PublicKey>
               </MetadataFilter>
               <MetadataFilter xsi:type="EntityRoleWhiteList">
                       <RetainedRole>md:SPSSODescriptor</RetainedRole>
               </MetadataFilter>
       </MetadataProvider>

Here is a sample provider for NIEF production:

    <MetadataProvider id="nief-main"
                        xsi:type="FileBackedHTTPMetadataProvider"
                    backingFile="%{idp.home}/metadata/nief-cache.xml"
                    metadataURL="https://nief.org/trust-fabric/nief-trust-fabric.xml">
              <MetadataFilter xsi:type="SignatureValidation"
                      requireSignedRoot="true">
                      <PublicKey>
                         MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA1fJixy7bY8R6nMXzNVrI
                         Zu8bfOeu2vSasiNCQafvOcZSYj1n3wYuvS/kuIUFQ8tQyOWJjTsuUE7wEIkUmo6C
                         sFh8tO9z0uJFBlicg//mlKRVCrRkXrwR7ScQMli4uVxFCHp6pEFqYLPx0nbENL36
                         kAOebTZpBhs2qPFk/KuVFrGx9VqZ//UiwjICL8aBAuxbi+Orvwe5OfttaSnn6bym
                         Kl95i47wz6m1MfwzYJiWEritSmAodcDbGT49jG64+SItmT4O1YGRx7EtxwvYd9Ug
                         94LfOrsd3TgbMW6jpAfXxVuR9DX210haba2l47F14MeB3/VKbGGUqXThvP21Zfsd
                         gQmfYPqmcNFQLLX59z+5iVujn6isZ0IUXl7VUVJFo259tph4f2FZeQaAxrYxynoF
                         ENCvaDVEXI7XHQjhK0LV096DOK9F4FO3zwoPxa3EWc1ilAdzG4dQpMq7wQkn+K0v
                         6VL0rwSzz12aLS4/TIrPDcs8zTUz8QDbo1qcdCx2ABk2S0e01cQXCqaeqB8PZOmb
                         gIK35Bdoh7g+4M9/V2agl9ohb+HDNktowESbJn2yrG3rizcuhR++t/IZ36PG0LVv
                         3yL4/UikxcLNkQSQktou6D27OFVdGT7XGZtByuFZCg78PtbChZGZfTUJYZOq7E+A
                         EQSq3FyoF7lJ6RYXNqEl7F0CAwEAAQ==
                      </PublicKey>
              </MetadataFilter>
              <MetadataFilter xsi:type="RequiredValidUntil" maxValidityInterval="P45D"/>
              <MetadataFilter xsi:type="EntityRoleWhiteList">
                      <RetainedRole>md:SPSSODescriptor</RetainedRole>
              </MetadataFilter>
      </MetadataProvider>

Running Shibboleth

The Shibboleth IDP can likely run in any supported servlet container. For simplicity's sake, these instructions assume the use of Apache Tomcat 8. The simplest and quickest way to enable the IDP within Tomcat is to create a file named idp.xml in the [TOMCAT_HOME]/conf/Catalina/localhost directory. The contents of this file specify the war file like this (the path specified in docBase will likely need to be updated to the installation path of Shibboleth):

   <Context docBase="/opt/idp/war/idp.war"
        privileged="true"
        antiResourceLocking="false"
        swallowOutput="true" />

Since it is more common to install Tomcat directly rather than via a package manager, it may be useful to have a Linux startup script. One can be downloaded here: File:Tomcat.sh.

Proxying Shibboleth

Assuming Apache httpd was used from the earlier section as the web server, you will need to configure it to proxy the application server that runs the IDP. This is typically done with a small snippet of proxy configuration within Apache configuration files:

  <Location /idp>
    ProxyPass ajp://localhost:8009/idp
  </Location>

Configuring NIEF Attributes

Shibboleth supports a rich XML configured and API driven capability for attribute resolution. Attributes can be filtered by relying party, by user, or conditionally based on various logic. The attribute values can be sourced from nearly anywhere, as long as code can be written to interact with the source (e.g., databases, web services, directories, programmatic derivation, etc.)

Attribute Filtering

Within the configuration file conf/attribute-filter.xml you can specify attribute release policies. The simplest such policy is to release all configured attributes to all trusted partners. A slightly more sophisticated example, that filters based on test user accounts and assumes a specific test attribute set, is available for download here: File:Attribute-filter.xml.

Attribute Resolution

Within the configuration file conf/attribute-resolver.xml you specify attributes and how to resolve their values. This is one of the most complex and flexible configuration points for Shibboleth, and detailed documentation is available on the Shibboleth Wiki. The flexibility is nearly endless, given the ability to write scripts and custom data connectors. Two samples are available here:

  1. This sample is an extremely simple sample that sends the UserName and a couple of statically defined attributes: File:Minimum-resolver.xml.
  2. This complicated sample configuration file sources attributes from a SQL database, statically for the organization, and from the filesystem in user files is available for download here: File:Attribute-resolver.xml.

Data Connectors

Shibboleth supports the development of new data connectors using their integration APIs. GTRI has developed many such data connectors over the years, and they are available for download on github:

  • Texas DPS Data Connectors - This project consists of three data connectors developed for Texas DPS and supports querying two different web services, one external and one internal, as well as a copy of the GTRI local file system data connector, useful for testing.
  • GTRI Test Data Connector - This is a simple test data connector, but also offers a convenient reference for implementing additional web services, as it is a simple sample of the API.
  • BAE Data Connector - This data connector functions as a Backend Attribute Exchange (BAE) client. It is rather outdated and has really only ever been tested with the retired BAE service from IIR. NOT recommended for use.
  • Shibboleth HTTP Dataconnector - This is a capability of Shibboleth to use a combination of Javascript and templates to call webservices to retrieve attributes. The link will lead to a sample GTRI created for using the IIR 28 CFR service.

Testing

It is always a good idea to test and validate a new IDP deployment within a test environment. The NIEF Testbed is intended for exactly this purpose.