PIV/CAC/Smart cards

Login to Keeper Connection Manager with a PIV/CAC device

KCM allows authentication with the web application using the DoD's Common Access Cards (CAC), as well as with any smart card supported by the browser for SSL client auth such as Personal Identity Verification (PIV).

This feature allows users to authenticate to Keeper Connection Manager using CAC, this does not allow pass-through of CAC to the remote desktop.

This support depends on an SSL termination instance providing SSL/TLS authentication, a capability that was added to KCM version 2.12.0.

A typical configuration for PIV/CAC would be the following:

  1. An SSL termination instance configured with two hostnames: one for normal access (such as kcm.example.net) and another just for handling SSL client auth, which should ideally be a wildcard domain (such as *.login.kcm.example.net). The SSL client auth configuration would include the certificate of the CA providing the PIV/CAC cards.

  2. PIV/CAC support installed and configured to authenticate users against *.login.kcm.example.net and redirect them back to kcm.example.net once ready.

  3. Database backend configured to automatically create user accounts for users coming from SSO.

  4. User creation workflow configured to require approval for users that SSO from PIV/CAC.

Configuration Options for PIV/CAC

Support for PIV/CAC is configured using Keeper's new support for SSL/TLS client authentication. This support is provided by the “guacamole-auth-sso-ssl” extension, which we package as kcm-guacamole-auth-sso-ssl. Setting any SSL_* variable will implicitly include the kcm-guacamole-auth-sso-ssl package.

The following options will need to be set in the keeper/guacamole Docker container definition (or in guacamole.properties for linux distributions):

PropertyEnvironment VariableDescription

ssl-client-auth-uri

SSL_CLIENT_AUTH_URI

REQUIRED. A wildcard URI that points to this Guacamole instance and requests SSL/TLS client authentication.

ssl-primary-uri

SSL_PRIMARY_URI

REQUIRED. A non-wildcard URI that points to this Guacamole instance and DOES NOT request SSL/TLS client authentication.

ssl-subject-base-dn

SSL_SUBJECT_BASE_DN

The base DN containing all valid subject DNs. If specified, only certificates asserting subject DNs beneath this base DN will be accepted.

By default, all DNs are accepted.

ssl-subject-username-attribute

SSL_SUBJECT_USERNAME_ATTRIBUTE

The LDAP attribute or attributes that may be used to represent a username within the subject DN of a user's X.509 certificate. If the least-significant attribute of the subject DN is not one of these attributes, the certificate will be rejected.

By default, any attribute is accepted.

The following options are also available, though it would be unusual to need to set them:

PropertyEnvironment VariableDescriptionDefault Value

ssl-client-certificate-header

SSL_CLIENT_CERTIFICATE_HEADER

The name of the header to use to retrieve the URL-encoded client certificate from an HTTP request received from an SSL termination service providing SSL/TLS client authentication.

This should not normally need to be set, as the defaults of the keeper/guacamole-ssl-nginx image match the default value of this option.

X-Client-Certificate

ssl-client-verified-header

SSL_CLIENT_VERIFIED_HEADER

The name of the header to use to retrieve the verification status of the certificate an HTTP request received from an SSL termination service providing SSL/TLS client authentication. This value of this header must be "SUCCESS" (all uppercase) if the certificate was successfully verified.

This should not normally need to be set, as the defaults of the keeper/guacamole-ssl-nginx image match the default value of this option.

X-Client-Verified

ssl-max-domain-validity

SSL_MAX_DOMAIN_VALIDITY

The amount of time that the temporary, unique subdomain generated for SSL/TLS authentication may remain valid, in minutes.

This subdomain is used to ensure each SSL/TLS authentication attempt is fresh and does not potentially reuse a previous authentication attempt that was cached by the browser or OS. This interval must be long enough to allow for network delays in authenticating the user with the SSL termination service that enforces SSL/TLS client authentication, but short enough that an unused domain does not consume unnecessary server resources and cannot potentially be guessed while that subdomain is still valid. These subdomains are 128-bit secure random values.

This should not normally need to be set, though it’s conceivable that an administrator may wish to reduce this value.

5

ssl-max-token-validity

SSL_MAX_TOKEN_VALIDITY

The amount of time that a temporary authentication token for SSL/TLS authentication may remain valid, in minutes.

This token is used to represent the user's asserted identity after it has been verified by the SSL termination service. This interval must be long enough to allow for network delays in receiving the token, but short enough that unused tokens do not consume unnecessary server resources and cannot potentially be guessed while the token is still valid. These tokens are 256-bit secure random values.

This should not normally need to be set, though it’s conceivable that an administrator may wish to reduce this value.

5

SSL (NGINX) Configuration Options for PIV/CAC

Authenticating with PIV/CAC (or any smart card) via the browser is using SSL/TLS client authentication. This capability was further enhanced for PIV/CAC by adding convenient configuration options for testing whether certificates have been revoked via OCSP or a CRL. For reference, the following are all options related to SSL/TLS client authentication currently supported by the keeper/guacamole-ssl-nginx Docker image:

Environmental VariableDescriptionDefault Value

ADDITIONAL_PROXY_CONFIG

Arbitrary, additional NGINX configuration statements that should be included within the location block that configures NGINX to proxy Guacamole.

CLIENT_CERTIFICATE_FILE

The certificate that NGINX should use to verify the certificate presented by the SSL/TLS client.

CLIENT_CRL_FILE

Controls the certificate revocation list (CRL) file that NGINX should use to check whether a client’s certificate has been revoked, as provided by NGINX ssl_crl directive. This file must be in PEM format and may contain multiple CRLs. If omitted, no CRL file will be used.

This variable will be ignored unless CLIENT_CERTIFICATE_FILE is specified.

If available, OCSP is often preferable to using a CRL file.

CLIENT_OCSP

Controls whether NGINX will use OCSP to check whether a client’s certificate has been revoked, as provided by NGINX ssl_ocsp directive. Setting this variable to on will use OCSP to check client certificates.

This variable will be ignored unless CLIENT_CERTIFICATE_FILE is specified.

If enabled, RESOLVER must also be specified.

off

RESOLVER

The DNS server that NGINX should use to resolve domain names. This is only required if OCSP is enabled.

SSL_VERIFY_CLIENT

Controls how and whether NGINX requires and verifies the certificate presented by the client (browser), as provided by NGINX ssl_verify_client directive.

on

SSL_VERIFY_DEPTH

Controls how deep NGINX will follow through the client’s certificate chain when attempting to validate their certificate, as provided by NGINX ssl_verify_depth directive.

1

Example PIV/CAC Configuration

The example docker-compose.yml below uses the following placeholders:

Placeholder

Description

PasswordForPostgresAdmin

Some reasonable password to assign to PostgreSQL’s postgres user - the typical root user of a PostgreSQL database. This account is used only if an administrator needs to manually connect to the database using a tool like psql.

guacamole_db

The name of the Guacamole database within PostgreSQL. This value is used automatically by kcm-setup.run and is documented as a reasonable value both within Keeper’s docs and upstream, so it is uncommon to use any other value here.

guacamole_user

The limited-privilege PostgreSQL user that Guacamole should use to execute queries against its database. This value is used automatically by kcm-setup.run and is documented as a reasonable value both within Keeper’s docs and upstream, so it is uncommon to use any other value here.

PasswordForGuacamole

Some reasonable password to assign to the PostgreSQL user that Guacamole will use to authenticate with the database as the limited-privilege account guacamole_user and execute queries.

ou=test department,o=u.s. government,c=us

The base DN of the subject DNs that should be accepted when presented via SSL/TLS client authentication (smart card authentication via browser).

kcm.example.net

The domain that users will visit with their browsers to use KCM.

/path/to/pki

The path on the Docker host containing the certificates and private keys used for SSL, including for client authentication.

/pki

The path within the Docker container that /path/to/pki should be mounted to, so that its files may be accessed by NGINX.

cac-certificate.pem

The filename of the PEM-format certificate that NGINX should use to validate the certificates it receives from users when they attempt to authenticate with smart cards.

In practice, these values will vary, as will whether the user chooses to use MySQL or PostgreSQL. The example below was written using PostgreSQL.

version: "3"
services:

    guacamole:
        image: keeper/guacamole:2
        restart: unless-stopped
        environment:
            ACCEPT_EULA: "Y"
            GUACD_HOSTNAME: "guacd"
            POSTGRES_HOSTNAME: "db"
            POSTGRES_DATABASE: "guacamole_db"
            POSTGRES_USERNAME: "guacamole_user"
            POSTGRES_PASSWORD: "PasswordForGuacamole"
            SSL_PRIMARY_URI: "https://kcm.example.net"
            SSL_CLIENT_AUTH_URI: "https://*.kcm.example.net"
            SSL_SUBJECT_BASE_DN: "ou=test department,o=u.s. government,c=us"
            POSTGRESQL_AUTO_CREATE_ACCOUNTS: "true"
            REQUIRE_ACCOUNT_APPROVAL: "ssl"
        volumes:
            - "common-storage:/var/lib/guacamole:rw"

    db:
        image: keeper/guacamole-db-postgres:2
        restart: unless-stopped
        environment:
            ACCEPT_EULA: "Y"
            GUACAMOLE_DATABASE: "guacamole_db"
            GUACAMOLE_USERNAME: "guacamole_user"
            GUACAMOLE_PASSWORD: "PasswordForGuacamole"
            GUACAMOLE_ADMIN_PASSWORD: "guacadmin"
            POSTGRES_PASSWORD: "PasswordForPostgresAdmin"

    guacd:
        image: keeper/guacd:2
        restart: unless-stopped
        environment:
            ACCEPT_EULA: "Y"
        volumes:
            - "common-storage:/var/lib/guacamole:rw"

    ssl:
        image: keeper/guacamole-ssl-nginx:2
        restart: unless-stopped
        ports:
            - "80:80"
            - "443:443"
        volumes:
            - "/path/to/pki:/pki:ro"
        environment:

            ACCEPT_EULA: "Y"
            GUACAMOLE_HOSTNAME: "guacamole"

            SERVERS: |

              # Main hostname, referenced by SSL_PRIMARY_URI
              - SSL_HOSTNAME: "kcm.example.net"
                CERTIFICATE_FILE: "/pki/kcm.example.net.crt"
                PRIVATE_KEY_FILE: "/pki/kcm.example.net.key"

                # The default CSP must be overridden for the main URI to allow
                # it to issue requests to its SSL/TLS-authenticating
                # counterpart. The only change from the default CSP here is to
                # add an the wildcard URI (including https://) to connect-src.
                CONTENT_SECURITY_POLICY: "default-src 'none'; script-src 'self' 'unsafe-eval'; connect-src 'self' wss://kcm.example.net https://*.kcm.example.net; object-src 'self'; frame-src 'self' https:; img-src 'self' data: blob:; style-src 'self' 'unsafe-inline'; font-src 'self' data:; form-action 'self'; base-uri 'self'; frame-ancestors 'self';"

              # Hostname requiring client auth, referenced by SSL_CLIENT_AUTH_URI
              - SSL_HOSTNAME: "*.kcm.example.net"
                CERTIFICATE_FILE: "/pki/_.kcm.example.net.crt"
                PRIVATE_KEY_FILE: "/pki/_.kcm.example.net.key"
                CLIENT_CERTIFICATE_FILE: "/pki/cac-certificate.pem"
                SSL_VERIFY_CLIENT: "optional" # This is necessary to allow the webapp to receive
                                              # verification failures. Without this, Nginx would
                                              # respond directly to any verification failures and
                                              # will not include the CORS headers necessary to
                                              # allow the webapp to actually see that failure. This
                                              # also allows the webapp to see the nature of the
                                              # failure by investigating the headers Nginx sends.
                                              # There are no such headers (and no such request) if
                                              # this is set to "required" and Nginx aborts
                                              # processing due to an invalid certificate.

volumes:
    common-storage:

Configuring the KCM user creation workflow

Prior to configuring the user workflow, make sure to set the REQUIRE_ACCOUNT_APPROVAL key to the appropriate authentication method.

For PIV/CAC, you would set it to ssl:

 guacamole:
        image: keeper/guacamole:2
        restart: unless-stopped
        environment:
            ACCEPT_EULA: "Y"
            GUACD_HOSTNAME: "guacd"
            SSL_PRIMARY_URI: "https://kcm.example.net"
            SSL_CLIENT_AUTH_URI: "https://*.kcm.example.net"
            SSL_SUBJECT_BASE_DN: "ou=test department,o=u.s. government,c=us"
            POSTGRESQL_AUTO_CREATE_ACCOUNTS: "true"
            REQUIRE_ACCOUNT_APPROVAL: "ssl"

Once you have successfully configured, there will be a new "Use Certificate or Smart Card" link on the login screen of the application as seen below:

For additional details on user creation workflow, visit this page.

Installing CA Authority

For each end-user client device that will need access to Keeper Connection Manager, you may need to install the internal CA as a trusted authority into the user's browser. The installation of CA trusted authority varies by platform.

Last updated