PIV-I Identity Provider

From NIEF Wiki
Revision as of 17:23, 4 February 2019 by Jeff.Krug (talk | contribs) (→‎Testing)
Jump to navigation Jump to search

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.

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.

This implementation guide is designed around the use of free and open sourced capabilities, 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, 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 help@nief.org before attempting to follow this guide. The authors of this guide tested this deploy guide with 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.

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).

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).

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.

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 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.

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:

   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:

   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:

   #!/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 insure the CRL is up to date.

Configuring Client Certificate Authentication

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:

   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:

  <Location "/pivi-test">
     SSLOptions +StdEnvVars +ExportCertData
     SSLVerifyClient require
     SSLVerifyDepth 4
  </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.

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):

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

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).

Getting Shibboleth

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

The 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 Shibboleth Wiki will almost always be more up to date and useful than this guide.

Running 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.

   [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 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):

   # 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 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:

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

Configuring Trust

There are many ways to enable trusted partners, and much of that can be read about 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 will 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 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:

       <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>

And 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>
                      MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAsTMoQtZ+IHOFO3iWZX/E
                      0YJ8s/S+xQuAsrQfcg6kZdL7gP1l2tRfe9nilYvN//bZndECw+/t7P/NkZ0apbUw
                      W/h55KuDyM0sK60PSiBb5KFeHHil8yLoim//cjJkP1RkiWFpA3yDV/e0BwSg4eqh
                      gH2lh96dYgUfnUZds4+NFAl6F6AoQgdUPDuVFt68q9KN/Vw7D6Ahhiu2uJsFSn/s
                      8S/7Jtq03TzonWXSI3E3O7t/cHsjpBQ374URQDZE8C2Wuss82TkdP0B3hvSjbJjx
                      SINVQzThlqAUu8oV6A+/RhQoQjbdEnalf4/Q+iaglsTUDVZIA5JQ24+acse9XwoX
                      7gvQlvQlomqKKqx7ICbR0ixjfvxAW24sfTi7vaEY6wTZvBlZpQqS6qZb/AdbOIPz
                      ww2MmYXp+LDHJl6micpahQbUKcPjreOsOOK7T09d0CfV3p16ppVFZx1u4KsgqhQ6
                      hku+AW2g+gTSvALa80kIOEyDETDbYSdp5DkVL1yBY0Q5DyLmlpMjAqznK6ehRIEY
                      nD1BYw7q75xnr7FMIlYKB+WlMhVhI71/QkZXkWh8szkN0EzrKqTU2mXNrWfiZA76
                      53ABqsoA5nyBjurxWFljFqVSLtN+kslf6a/904FvdUrhQFupPoZZVJq2sBLRAJku
                      o9lfBUOGVkpZQ1MsENaBjusCAwEAAQ==
                      </PublicKey>
              </MetadataFilter>
              <MetadataFilter xsi:type="RequiredValidUntil" maxValidityInterval="P45D"/>
              <MetadataFilter xsi:type="EntityRoleWhiteList">
                      <RetainedRole>md:SPSSODescriptor</RetainedRole>
              </MetadataFilter>
      </MetadataProvider>

Running

The Shibboleth IDP can likely run in any supported servlet container. For simplicity 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 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):

   <Context docBase="/opt/idp/war/idp.war"
        privileged="true"
        antiResourceLocking="false"
        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 here: File:Tomcat.sh.

Configuring NIEF Attributes

Shibboleth supports a rich XML configured and API driven capability for engaging in 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 anything as long as code can be written to interact with the source (databases, web services, directories, programmatically derived, etc.).

Attribute Filtering

Within the configuration file conf/attribute-filter.xml you specify attribute release policies. The simplest version of such a policy would simply release all configured attributes to all trusted partners. A slightly more sophisticated example that filters based on test user accounts and 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. A sample configuration file that sources attributes from a SQL database, statically for the organization, and from the filesystem is available for download here: File:Attribute-resolver.xml.

Data Connectors

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

  • Texas DPS Dataconnectors - 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 Dataconnector - 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 Dataconnector - This data connector functions as a BAE client. It is rather out dated and has really only ever been tested with the retired BAE service from IIR. NOT recommended for use.

Testing

It is always a good idea to test and validate a new identity provider deploy within a test environment. The NIEF Testbed is meant for just this purpose.