PingGateway 2024.6

Secure connections

PingGateway is often deployed to replay credentials or other security information. In a real world deployment, this information must be communicated over a secure connection using HTTPS, meaning HTTP over encrypted Transport Layer Security (TLS). Never send real credentials, bearer tokens, or other security information unprotected over HTTP.

Learn about how to use well-known CA-signed certificates from the documentation for the Java Virtual Machine (JVM).

After installing certificates for client-server trust, consider which cipher suites to use. PingGateway inherits the list of cipher suites from the underlying Java environment.

PingGateway uses the JSSE to secure connections. You can set security and system properties to configure the JSSE. For a list of properties to customize the JSSE in Oracle Java, refer to the Customization section of the JSSE Reference guide.

Configure PingGateway for TLS (client-side)

When PingGateway sends requests over HTTP to a proxied application, or requests services from a third-party application, PingGateway is acting as a client of the application, and the application is acting as a server. PingGateway is client-side.

When PingGateway sends requests securely over HTTPS, PingGateway must be able to trust the server. By default, PingGateway uses the Java environment truststore to trust server certificates. The Java environment truststore includes public key signing certificates from many well-known Certificate Authorities (CAs).

When servers present certificates signed by trusted CAs, then PingGateway can send requests over HTTPS to those servers, without any configuration to set up the HTTPS client connection. When server certificates are self-signed or signed by a CA whose certificate is not automatically trusted, the following objects can be required to configure the connection:

  • KeyStoreSecretStore, to manage a secret store for cryptographic keys and certificates, based on a standard Java keystore.

  • SecretsTrustManager, to manage trust material that verifies the credentials presented by a peer.

  • (Optional) SecretsKeyManager, to manage keys that authenticate a TLS connection to a peer.

  • ClientHandler and ReverseProxyHandler reference to ClientTlsOptions, for connecting to TLS-protected endpoints.

The following procedure describes how to set up PingGateway for HTTPS (client-side), when server certificates are self-signed or signed by untrusted CAs.

Set up PingGateway for HTTPS (client-side) for untrusted servers
  1. Locate or set up the following directories:

    • Directory containing the sample application .jar: sampleapp_install_dir

    • Directory to store the sample application certificate and PingGateway keystore: /path/to/secrets

  2. Extract the public certificate from the sample application:

    $ cd /path/to/secrets
    $ jar --verbose --extract \
    --file sampleapp_install_dir/PingGateway-sample-application-2024.6.0-jar-with-dependencies.jar tls/sampleapp-cert.pem
    
    inflated: tls/sampleapp-cert.pem

    The file /path/to/secrets/tls/sampleapp-cert.pem is created.

  3. Import the certificate into the PingGateway keystore, and answer yes to trust the certificate:

    $ keytool -importcert \
    -alias ig-sampleapp \
    -file tls/sampleapp-cert.pem \
    -keystore reverseproxy-truststore.p12 \
    -storetype pkcs12 \
    -storepass password
    
    ...
    Trust this certificate? [no]: yes
    
    Certificate was added to keystore
    Because keytool converts all characters in its key aliases to lowercase, use only lowercase in alias definitions of a keystore.
  4. List the keys in the PingGateway keystore to make sure that a key with the alias ig-sampleapp is present:

    $ keytool -list \
    -v \
    -keystore /path/to/secrets/reverseproxy-truststore.p12 \
    -storetype pkcs12 \
    -storepass password
    
    Keystore type: PKCS12
    Keystore provider: SUN
    Your keystore contains 1 entry
    Alias name: ig-sampleapp
    ...
  5. Add the following route to PingGateway to serve the sample application .css and other static resources:

    • Linux

    • Windows

    $HOME/.openig/config/routes/00-static-resources.json
    appdata\OpenIG\config\routes\00-static-resources.json
    {
      "name" : "00-static-resources",
      "baseURI" : "http://app.example.com:8081",
      "condition": "${find(request.uri.path,'^/css') or matchesWithRegex(request.uri.path, '^/.*\\\\.ico$') or matchesWithRegex(request.uri.path, '^/.*\\\\.gif$')}",
      "handler": "ReverseProxyHandler"
    }
  6. Add the following route to PingGateway:

    • Linux

    • Windows

    $HOME/.openig/config/routes/client-side-https.json
    appdata\OpenIG\config\routes\client-side-https.json
    {
      "name": "client-side-https",
      "condition": "${find(request.uri.path, '/home/client-side-https')}",
      "baseURI": "https://app.example.com:8444",
      "heap": [
        {
          "name": "Base64EncodedSecretStore-1",
          "type": "Base64EncodedSecretStore",
          "config": {
            "secrets": {
              "keystore.secret.id": "cGFzc3dvcmQ="
            }
          }
        },
        {
          "name": "KeyStoreSecretStore-1",
          "type": "KeyStoreSecretStore",
          "config": {
            "file": "/path/to/secrets/reverseproxy-truststore.p12",
            "storeType": "PKCS12",
            "storePasswordSecretId": "keystore.secret.id",
            "secretsProvider": "Base64EncodedSecretStore-1",
            "mappings": [
              {
                "secretId": "trust.manager.secret.id",
                "aliases": [ "ig-sampleapp" ]
              }
            ]
          }
        },
        {
          "name": "SecretsTrustManager-1",
          "type": "SecretsTrustManager",
          "config": {
            "verificationSecretId": "trust.manager.secret.id",
            "secretsProvider":"KeyStoreSecretStore-1"
          }
        },
        {
          "name": "ReverseProxyHandler-1",
          "type": "ReverseProxyHandler",
          "config": {
            "tls": {
              "type": "ClientTlsOptions",
              "config": {
                "trustManager": "SecretsTrustManager-1"
              }
            },
            "hostnameVerifier": "ALLOW_ALL"
          },
          "capture": "all"
        }
      ],
      "handler": "ReverseProxyHandler-1"
    }

    Notice the following features of the route:

    • The route matches requests to /home/client-side-https.

    • The baseURI changes the request URI to point to the HTTPS port for the sample application.

    • The Base64EncodedSecretStore provides the keystore password.

    • The SecretsTrustManager points to the secret bound to the sample application certificate, coming from the KeyStoreSecretStore.

    • The KeyStoreSecretStore contains the sample application certificate to validate the TLS connection. The password to access the keystore is provided by the SystemAndEnvSecretStore.

    • The ReverseProxyHandler uses the SecretsTrustManager for the connection to TLS-protected endpoints. All hostnames are allowed.

  7. Test the setup:

    1. Start the sample application

      $ java -jar sampleapp_install_dir/PingGateway-sample-application-2024.6.0-jar-with-dependencies.jar
    2. Go to http://ig.example.com:8080/home/client-side-https.

      The request is proxied transparently to the sample application, on the TLS port 8444.

    3. Check the route log for a line like this:

      GET https://app.example.com:8444/home/client-side-https

Configure PingGateway for TLS (server-side)

When PingGateway is server-side, applications send requests to PingGateway or request services from PingGateway. PingGateway is acting as a server of the application, and the application is acting as a client.

To run PingGateway as a server over TLS:

  • In the admin.json heap, add a SecretsKeyManager to authenticate PingGateway to the client. Key material is a private key and its certificate for PingGateway.

  • In admin.json, update the connectors list to include a connector for the HTTPS port. The connector tls property must refer to a ServerTlsOptions.

  • The ServerTlsOptions must configure keyManager to refer to the SecretsKeyManager.

The following example connector includes a ServerTlsOptions that refers to a SecretsKeyManager in the heap:

"connectors": [
  {
    "port": 8443,
    "tls": {
      "type": "ServerTlsOptions",
      "config": {
        "keyManager": "SecretsKeyManager-1"
      }
    }
  }
]

Learn more from About keys and certificates.

Serve one certificate for TLS connections to all server names

This example uses PEM files and a PKCS#12 keystore for self-signed certificates, but you can adapt it to use official (non self-signed) keys and certificates.

Before you start, install PingGateway, as described in the Install.

  1. Locate a directory for the secrets, for example, /path/to/secrets.

  2. Create self-signed keys in one of the following ways. If you have your own keys, use them and skip this step.

    Use your own keys

    If you have your own keys, use them and skip this step.

    Set up a self-signed certificate in a (PKCS#12) keystore
    1. Create the keystore, replacing /path/to/secrets with your path:

      $ keytool \
      -genkey \
      -alias https-connector-key \
      -keyalg RSA \
      -keystore /path/to/secrets/keystore.pkcs12 \
      -storepass password \
      -keypass password \
      -dname "CN=ig.example.com,O=Example Corp,C=FR"
      Because keytool converts all characters in its key aliases to lowercase, use only lowercase in alias definitions of a keystore.
    2. In the secrets directory, add a file called keystore.pass, containing the keystore password password:

      $ cd /path/to/secrets/
      $ echo -n 'password' > keystore.pass

      Make sure the password file contains only the password, with no trailing spaces or carriage returns.

    Set up self-signed certificate stored in PEM file
    1. Locate a directory for secrets, and go to it:

      $ cd /path/to/secrets
    2. Create the following secret key and certificate pair as PEM files:

      $ openssl req \
      -newkey rsa:2048 \
      -new \
      -nodes \
      -x509 \
      -days 3650 \
      -subj "/CN=ig.example.com/OU=example/O=com/L=fr/ST=fr/C=fr" \
      -keyout ig.example.com-key.pem \
      -out ig.example.com-certificate.pem

      Two PEM files are created, one for the secret key, and another for the associated certificate.

    3. Map the key and certificate to the same secret ID in PingGateway:

      $ cat ig.example.com-key.pem ig.example.com-certificate.pem > key.manager.secret.id.pem
  3. Set up TLS on PingGateway in one of the following ways:

    Keys stored in a (PKCS#12) keystore

    Add the following file to PingGateway, replacing /path/to/secrets with your path:

    • Linux

    • Windows

    $HOME/.openig/config/admin.json
    appdata\OpenIG\config\admin.json
    {
      "connectors": [
        {
          "port": 8080
        },
        {
          "port": 8443,
          "tls": "ServerTlsOptions-1"
        }
      ],
      "heap": [
        {
          "name": "ServerTlsOptions-1",
          "type": "ServerTlsOptions",
          "config": {
            "keyManager": {
              "type": "SecretsKeyManager",
              "config": {
                "signingSecretId": "key.manager.secret.id",
                "secretsProvider": "ServerIdentityStore"
              }
            }
          }
        },
        {
          "type": "FileSystemSecretStore",
          "name": "SecretsPasswords",
          "config": {
            "directory": "/path/to/secrets",
            "format": "PLAIN"
          }
        },
        {
          "name": "ServerIdentityStore",
          "type": "KeyStoreSecretStore",
          "config": {
            "file": "/path/to/secrets/IG-keystore",
            "storePasswordSecretId": "keystore.pass",
            "secretsProvider": "SecretsPasswords",
            "mappings": [
              {
                "secretId": "key.manager.secret.id",
                "aliases": ["https-connector-key"]
              }
            ]
          }
        }
      ]
    }

    Notice the following features of the file:

    • PingGateway starts on port 8080, and on 8443 over TLS.

    • PingGateway’s private keys for TLS are managed by the SecretsKeyManager, whose ServerIdentityStore references a KeyStoreSecretStore.

    • The KeyStoreSecretStore maps the keystore alias to the secret ID for retrieving the server keys (private key + certificate).

    • The password of the KeyStoreSecretStore is provided by the FileSystemSecretStore.

    Keys stored in PEM file

    Add the following file to PingGateway, replacing /path/to/secrets with your path:

    • Linux

    • Windows

    $HOME/.openig/config/admin.json
    appdata\OpenIG\config\admin.json
    {
      "connectors": [
        {
          "port": 8080
        },
        {
          "port": 8443,
          "tls": "ServerTlsOptions-1"
        }
      ],
      "heap": [
        {
          "name": "ServerTlsOptions-1",
          "type": "ServerTlsOptions",
          "config": {
            "keyManager": {
              "type": "SecretsKeyManager",
              "config": {
                "signingSecretId": "key.manager.secret.id",
                "secretsProvider": "ServerIdentityStore"
              }
            }
          }
        },
        {
          "name": "ServerIdentityStore",
          "type": "FileSystemSecretStore",
          "config": {
            "format": "PLAIN",
            "directory": "/path/to/secrets",
            "suffix": ".pem",
            "mappings": [{
              "secretId": "key.manager.secret.id",
              "format": {
                "type": "PemPropertyFormat"
              }
            }]
          }
        }
      ]
    }

    Notice how this file differs to that for the keystore-based approach:

    • The ServerIdentityStore is a FileSystemSecretStore.

    • The FileSystemSecretStore reads the keys that are stored as file in the PEM standard format.

  4. Start PingGateway:

    • Linux

    • Windows

    $ /path/to/PingGateway-2024.6.0/bin/start.sh
    
    ...
    ... started in 1234ms on ports : [8080 8443]
    C:\path\to\identity-gateway-2024.6.0\bin\start.bat

    By default, PingGateway configuration files are located under $HOME/.openig (on Windows appdata\OpenIG). For information about how to use a different location, refer to Configuration location.

  5. Test the connection in one of the following ways:

    • Ping PingGateway and make sure an HTTP 200 is returned:

      $ curl -v --cacert /path/to/secrets/ig.example.com-certificate.pem \
      https://ig.example.com:8443/openig/ping
    • Display the product version and build information:

      $ curl --cacert /path/to/secrets/ig.example.com-certificate.pem \
      https://ig.example.com:8443/openig/api/info

Use Server Name Indication (SNI) to serve different certificates for TLS connections to different server names

This example uses PEM files for self-signed certificates, but you can adapt it to use official (non self-signed) keys and certificates.

Before you start, install PingGateway, as described in the Install.

  1. Locate a directory for secrets, for example, /path/to/secrets, and go to it.

    $ cd /path/to/secrets
  2. Create the following secret key and certificate pair as PEM files:

    1. For ig.example.com:

      1. Create a key and certificate:

        $ openssl req \
        -newkey rsa:2048 \
        -new \
        -nodes \
        -x509 \
        -days 3650 \
        -subj "/CN=ig.example.com/OU=example/O=com/L=fr/ST=fr/C=fr" \
        -keyout ig.example.com-key.pem \
        -out ig.example.com-certificate.pem

        Two PEM files are created, one for the secret key, and another for the associated certificate.

      2. Map the key and certificate to the same secret ID in PingGateway:

        $ cat ig.example.com-key.pem ig.example.com-certificate.pem > key.manager.secret.id.pem
    2. For servers grouped by a wildcard:

      1. Create a key and certificate:

        $ openssl req \
        -newkey rsa:2048 \
        -new \
        -nodes \
        -x509 \
        -days 3650 \
        -subj "/CN=*.example.com/OU=example/O=com/L=fr/ST=fr/C=fr" \
        -keyout wildcard.example.com-key.pem \
        -out wildcard.example.com-certificate.pem
      2. Map the key and certificate to the same secret ID in PingGateway:

        $ cat wildcard.example.com-key.pem wildcard.example.com-certificate.pem > wildcard.secret.id.pem
    3. For other, unmapped servers

      1. Create a key and certificate:

        $ openssl req \
        -newkey rsa:2048 \
        -new \
        -nodes \
        -x509 \
        -days 3650 \
        -subj "/CN=un.mapped.com/OU=example/O=com/L=fr/ST=fr/C=fr" \
        -keyout default.example.com-key.pem \
        -out default.example.com-certificate.pem
      2. Map the key and certificate to the same secret ID in PingGateway:

        $ cat default.example.com-key.pem default.example.com-certificate.pem > default.secret.id.pem
  3. Add the following file to PingGateway, replacing /path/to/secrets with your path, and then restart PingGateway:

    • Linux

    • Windows

    $HOME/.openig/config/admin.json
    appdata\OpenIG\config\admin.json
    {
      "connectors": [
        {
          "port": 8080
        },
        {
          "port": 8443,
          "tls": "ServerTlsOptions-1"
        }
      ],
      "heap": [
        {
          "name": "ServerTlsOptions-1",
          "type": "ServerTlsOptions",
          "config": {
            "sni": {
              "serverNames": {
                "ig.example.com": "key.manager.secret.id",
                "*.example.com": "wildcard.secret.id"
              },
              "defaultSecretId" : "default.secret.id",
              "secretsProvider": "ServerIdentityStore"
            }
          }
        },
        {
          "name": "ServerIdentityStore",
          "type": "FileSystemSecretStore",
          "config": {
            "format": "PLAIN",
            "directory": "path/to/secrets",
            "suffix": ".pem",
            "mappings": [
              {
                "secretId": "key.manager.secret.id",
                "format": {
                  "type": "PemPropertyFormat"
                }
              },
              {
                "secretId": "wildcard.secret.id",
                "format": {
                  "type": "PemPropertyFormat"
                }
              },
              {
                "secretId": "default.secret.id",
                "format": {
                  "type": "PemPropertyFormat"
                }
              }
            ]
          }
        }
      ]
    }

    Notice the following features of the file:

    • The ServerTlsOptions object maps two servers to secret IDs, and includes a default secret ID

    • The secret IDs correspond to the secret IDs in the FileSystemSecretStore, and the PEM files generated in an earlier step.

  4. Run the following commands to request TLS connections to different servers, using different certificates:

    1. Connect to ig.example.com, and note that the certificate subject corresponds to the certificate created for ig.example.com:

      $ openssl s_client -connect localhost:8443 -servername ig.example.com
      
      ...
      Server certificate
      -----BEGIN CERTIFICATE-----
      MII...dZC
      -----END CERTIFICATE-----
      subject=/CN=ig.example.com/OU=example/O=com/L=fr/ST=fr/C=fr
      issuer=/CN=ig.example.com/OU=example/O=com/L=fr/ST=fr/C=fr
    2. Connect to other.example.com, and note that the certificate subject corresponds to the certificate created with the wildcard, *.example.com:

      $ openssl s_client -connect localhost:8443 -servername other.example.com
      
      ...
      Server certificate
      -----BEGIN CERTIFICATE-----
      MII...fY=
      -----END CERTIFICATE-----
      subject=/CN=*.example.com/OU=example/O=com/L=fr/ST=fr/C=fr
      issuer=/CN=*.example.com/OU=example/O=com/L=fr/ST=fr/C=fr
    3. Connect to unmapped.site.com, and note that the certificate subject corresponds to the certificate created for the default secret ID:

      $ openssl s_client -connect localhost:8443 -servername unmapped.site.com
      
      ...
      Server certificate
      -----BEGIN CERTIFICATE-----
      MII..rON
      -----END CERTIFICATE-----
      subject=/CN=un.mapped.com/OU=example/O=com/L=fr/ST=fr/C=fr
      issuer=/CN=un.mapped.com/OU=example/O=com/L=fr/ST=fr/C=fr

Configure PingGateway for mutual TLS (server-side)

When PingGateway is server-side, applications send requests to PingGateway or request services from PingGateway. PingGateway is acting as a server of the application, and the application is acting as a client.

To run PingGateway as a server for mutual TLS:

  • Using information from Configure PingGateway for TLS (server-side), configure PingGateway for TLS connections.

  • In admin.json, add a SecretsTrustManager to verify the credentials presented by the client:

    • The trust material is a public key certificate for a client or certificate authority.

    • The SecretsTrustManager must refer to a secret in a secrets store, where the secret is mapped to the certificate.

    • ServerTlsOptions must configure trustManager to refer to that SecretsTrustManager and clientAuth to require or request the client to authenticate.

    • Linux

    • Windows

    $HOME/.openig/config/admin.json
    appdata\OpenIG\config\admin.json
    {
      "mode": "DEVELOPMENT",
      "properties": {
        "ig_keystore_directory": "/path/to/ig/secrets",
        "oauth2_client_keystore_directory": "/path/to/client/secrets"
      },
      "connectors": [
        {
          "port": 8080
        },
        {
          "port": 8443,
          "tls": {
            "type": "ServerTlsOptions",
            "config": {
              "alpn": {
                "enabled": true
              },
              "clientAuth": "REQUEST",
              "keyManager": "SecretsKeyManager-1",
              "trustManager": "SecretsTrustManager-1"
            }
          }
        }
      ],
      "heap": [
        {
          "name": "SecretsPasswords",
          "type": "FileSystemSecretStore",
          "config": {
            "directory": "&{ig_keystore_directory}",
            "format": "PLAIN"
          }
        },
        {
          "name": "SecretsKeyManager-1",
          "type": "SecretsKeyManager",
          "config": {
            "signingSecretId": "key.manager.secret.id",
            "secretsProvider": "ServerIdentityStore"
          }
        },
        {
          "name": "SecretsTrustManager-1",
          "type": "SecretsTrustManager",
          "config": {
            "verificationSecretId": "trust.manager.secret.id",
            "secretsProvider": {
              "type": "KeyStoreSecretStore",
              "config": {
                "file": "&{oauth2_client_keystore_directory}/cacerts.p12",
                "storePasswordSecretId": "keystore.pass",
                "secretsProvider": "SecretsPasswords",
                "mappings": [
                  {
                    "secretId": "trust.manager.secret.id",
                    "aliases": ["client-cert"]
                  }
                ]
              }
            }
          }
        },
        {
          "name": "ServerIdentityStore",
          "type": "FileSystemSecretStore",
          "config": {
            "format": "PLAIN",
            "directory": "&{ig_keystore_directory}",
            "suffix": ".pem",
            "mappings": [{
              "secretId": "key.manager.secret.id",
              "format": {
                "type": "PemPropertyFormat"
              }
            }]
          }
        }
      ]
    }
Copyright © 2010-2024 ForgeRock, all rights reserved.