Installing and configuring IG/OpenIG

This book provides information on installing and configuring IG/OpenIG including frequently asked questions.


What versions of IG/OpenIG are compatible with AM/OpenAM?

The purpose of this article is to provide compatibility information between IG/OpenIG and AM/OpenAM versions. Also included is the supported Java® versions for each combination.

IG/OpenIG and AM/OpenAM compatibility

The following matrix indicates compatibility between AM/OpenAM and IG/OpenIG versions:

  IG 6.5.1 IG 6.5 IG 6, 6.1 IG 5.5.x IG 5 OpenIG 4.x
AM 6.5.1 Yes Yes Yes -- -- --
AM 6.5 All features except mTLS Yes Yes -- -- --
AM 6 All features except mTLS Yes Yes -- -- --
AM 5.5 All features except mTLS Yes Yes Yes -- --
AM 5, 5.1.x Partly * (most features) Partly * (most features) Partly * (most features) Yes Yes --
OpenAM 13.5.x Partly * (limited features) Partly * (limited features) Partly * (limited features) Partly * (most features) Yes Yes
OpenAM 13 -- -- -- -- -- Yes

* For details of the specific features supported in these versions, please refer to the relevant IG release notes:

Note

It is strongly recommended that you always upgrade to the latest maintenance releases for whichever versions of AM/OpenAM and IG/OpenIG you have deployed.

Java Compatability

Java 11

  • AM 6.5 and later.
  • IG 6.5 and later (OpenJDK only).

Java 8

  • AM 5 and later; OpenAM 13.x
  • IG 5 and later; OpenIG 4.x

Java 7

  • AM 5 and 5.1.x; OpenAM 13.x
  • IG 5 and OpenIG 4.x

Software and Hardware requirements

AM/OpenAM

IG/OpenIG

See Also

What operating systems are ForgeRock products supported on?

Checking your product versions are supported

FAQ: Installing AM/OpenAM

FAQ: Upgrading AM/OpenAM

FAQ: Installing and configuring IG/OpenIG

Installing and configuring AM/OpenAM

Installing and configuring IG/OpenIG


What Java versions are ForgeRock products supported on?

The purpose of this article is to provide information on the supported Java® versions across the ForgeRock platform (AM/OpenAM, DS/OpenDJ, IDM/OpenIDM and IG/OpenIG).

Oracle® JDK

Note

End of Public Updates for Oracle JDK 8

Since January 2019, Oracle no longer posts updates of Java SE 8 to its public download sites for commercial use. If you need continued access to critical bug fixes and security fixes, as well as general maintenance for Java SE 8 or previous versions, you can get long term support through Oracle Java SE Subscription or Oracle Java Desktop Subscription. For more information and details on how to receive longer term support for Oracle JDK 8, please see the Oracle Java SE Support Roadmap.

Platform 5 and later

  Platform 6.5 Platform 6 Platform 5.5 Platform 5
Access Management 8, 11 8 8 7, 8
Directory Services 8, 11 8, 9 8 7, 8
Identity Management 8, 11 8 8 7, 8
Identity Gateway 8 8 8 7, 8

Pre-Platform 5

  Oracle JDK 8 Oracle JDK 7
OpenAM 13.x Yes Yes
OpenDJ 3.x Yes Yes
OpenIDM 4.x Yes Yes
OpenIG 4.x Yes Yes

Java Agents

  Oracle JDK 11 Oracle JDK 8 Oracle JDK 7
Java Agent 5.6 Yes Yes --
Java Agent 5.5 -- Yes --
Java Agent 5 -- Yes --
JEE agents 3.5.x -- Yes Yes

* Web Agents 4 and later do not have any Java dependencies. Earlier versions did require Java in order to run the installer.

OpenJDK

Platform 5 and later

  Platform 6.5 Platform 6 Platform 5.5 Platform 5
Access Management 8, 11 8 8 8
Directory Services 8, 11 8, 9 8 7, 8
Identity Management 8, 11 8 8 7, 8
Identity Gateway 8, 11 8 8 8

Pre-Platform 5

  OpenJDK 8 OpenJDK 7
OpenAM 13.x -- --
OpenDJ 3.x Yes Yes
OpenIDM 4.x Yes Yes
OpenIG 4.x Yes Yes

Java Agents

  OpenJDK 11 OpenJDK 8
Java Agent 5.6 Yes Yes
Java Agent 5.5 -- Yes
Java Agent 5 -- Yes
JEE agents 3.5.x -- --

* Web Agents 4 and later do not have any Java dependencies. Earlier versions did require Java in order to run the installer.

IBM® SDK (Websphere® only)

Note

Only AM/OpenAM and Java Agents have been validated with the IBM SDK.

AM/OpenAM

  IBM SDK 8 IBM SDK 7
AM 6.x Yes --
AM 5.5 Yes --
AM 5 -- Yes
OpenAM 13.x -- Yes

Java Agents

  IBM SDK 8 IBM SDK 7
Java Agent 5.6 Yes --
Java Agent 5.5 Yes --
Java Agent 5 Yes --
JEE agents 3.5.x Yes Yes

See Also

What operating systems are ForgeRock products supported on?

Platform compatibility

AM Release Notes › Java Requirements

DS Release Notes › Preparing the Java Environment

IDM Release Notes › Preparing the Java Environment

IG Release Notes › Java Requirements


How do I quickly test IG/OpenIG configurations (All versions) with Jetty?

The purpose of this article is to provide some hints around getting IG/OpenIG up and running quickly using the Jetty® web container and the command line.

Using jetty-runner

Prerequisites

  • Java® 7 or Java 8: An installation of Java that matches the supported version of IG/OpenIG you want to run; see the release notes of the version you are working with.
  • jetty-runner: A copy of the jetty-runner.jar that matches the supported version of IG/OpenIG you want to run; see the release notes of the version you are working with.
  • openig.war: A copy of the IG/OpenIG war file that you want to use with jetty-runner. You can download the war file from BackStage.
  • IG/OpenIG base configuration directory: An appropriate directory structure that holds the IG/OpenIG configuration files.

Running

  • Enter the following command to start up the Jetty container to host IG/OpenIG:
    $ java -Dopenig.base=[ig-configuration-directory] -jar [jetty-runner.jar] --path / [openig.war]
    replacing [ig-configuration-directory], [jetty-runner.jar] and [openig.war] with appropriate values.

Testing

  • Browse to the appropriate IG/OpenIG URL to match the configuration used when starting up IG/OpenIG.
Note

The default http listening port used by Jetty is 8080; use the jetty-runner --port parameter to change this as required, for example: --path / --port 7070 [openig.war]

Using the IG/OpenIG source code and Maven

Caution

You must authenticate to the ForgeRock protected Maven repositories using your BackStage credentials in order to build IG/OpenIG releases from source. See How do I access the ForgeRock protected Maven repositories? for further information. Source code for IG 5 and later is only available on request. See FAQ: Source code in IG/OpenIG (Q. How do I request access to the source code for IG 5 and later?) for further information.

Prerequisites

  • Java 7 or Java 8: An installation of Java that matches the supported version of IG/OpenIG you want to run; see the release notes of the version you are working with.
  • Apache Maven™ 3.x: An installation of at least Maven v3.3.9.
  • IG/OpenIG source code: A clone of the IG/OpenIG source code. See FAQ: Source code in IG/OpenIG for further information on obtaining the source code.
  • IG/OpenIG base configuration directory: An appropriate directory structure that holds the IG/OpenIG configuration files.

Building

  • Change into the directory where you have cloned a copy of the IG/OpenIG source code.
  • Checkout appropriate version of IG/OpenIG, for example, if you want to run a copy of IG 5:
    $ git checkout 5.0
  • Build the IG/OpenIG project to generate the war file:
    $ mvn clean install

See How do I build AM, DS, IDM and IG (All versions) from source? for further information on building IG.

Running

  • Enter the following to start the Maven Jetty plugin from the source directory where you have successfully built a copy of the IG/OpenIG version you want to run:
    $ mvn -pl openig-war jetty:run -Dopenig.base=[ig-configuration-directory]
    replacing [ig-configuration-directory] with an appropriate value.

Testing

  • Browse to the appropriate IG/OpenIG URL to match the configuration used when starting up IG/OpenIG.
Note

The default http listening port used by Jetty is 8080; use the java -Djetty.port parameter to change this as required, for example: jetty:run -Djetty.port=7070

See Also

Gateway Guide › Configuration Directories and Files

IG 6 Release Notes

IG 5.5 Release Notes

IG 5 Release Notes

OpenIG 4.5 Release Notes

OpenIG 4 Release Notes

jetty-runner documentation

jetty-runner downloads

Apache Maven downloads


How do I configure IG (All versions) to load properties from multiple configuration files?

The purpose of this article is to provide information on configuring IG to load properties from multiple JSON configuration files.

Configuring IG to load properties from multiple files

You can update the config.json file (located in the $HOME/.openig/config/ directory) to point to multiple configuration files using the $location property introduced in IG 5, for example:

  • IG 6.5 and later:
    {
      "properties" : {
        "constants": {
          "$location": "file:${IG_INSTANCE_DIR}/resources/ig-consts.json"
        },
        "variables": {
          "$location": "file:${IG_INSTANCE_DIR}/resources/ig-vars.json"
        }
      }
    }
    
  • Pre-IG 6.5:
    {
      "properties" : {
        "constants": {
          "$location": "file:${OPENIG_BASE}/resources/ig-consts.json"
        },
        "variables": {
          "$location": "file:${OPENIG_BASE}/resources/ig-vars.json"
        }
      }
    }
    

Based on this example, you can then access properties using the following format, depending on which file they derive from:

Format File
constants.propertyName /path/to/ig/resources/ig-consts.json
variables.propertyName /path/to/ig/resources/ig-vars.json

Where you replace propertyName with the actual property name.  

See Also

FAQ: Installing and configuring IG/OpenIG

Installing and configuring IG/OpenIG

Configuration Reference › Properties

Getting Started Guide › Trying IG With a Simple Configuration

Gateway Guide › Changing the Default Location of the Configuration Folders

Release Notes › Deprecated Functionality

Related Training

N/A

Related Issue Tracker IDs

OPENIG-1814 ( request to have $location support a list of files rather than a single entry for config.json)


How do I connect to LDAPS from within an IG (All versions) Groovy script using the LdapClient class?

The purpose of this article is to provide information on connecting to LDAPS from within an IG Groovy script using the LdapClient class.

Connecting to LDAPS

As of IG 6, the documentation provides scripts that can be used in a ScriptableFilter for both LDAP and LDAPS authentication: Gateway Guide › Scripting Authentication to LDAP and LDAPS-enabled Servers. You can use this information in IG 5.x as well.

Alternatively, the following script provides a simple example using the LdapClient class to connect to LDAPS using ldapOptions; again this script can be used in a ScriptableFilter for authentication:

import org.forgerock.opendj.ldap.*
import org.forgerock.openam.ldap.LDAPUtils
import org.forgerock.opendj.security.SslContextBuilder
import org.forgerock.opendj.security.*

.....

ldapOptions = ldap.defaultOptions(context)
if (ssl) {
 SslContextBuilder builder = new SslContextBuilder();
 builder.trustManager(TrustManagers.trustAll());
 SslOptions sslOptions = SslOptions.newSslOptions(builder.build()).enabledProtocols(LDAPUtils.LDAP_SECURE_PROTOCOLS);
 ldapOptions = ldapOptions.set(CommonLdapOptions.SSL_OPTIONS, sslOptions);
}

.....

client = ldap.connect(host, port as Integer, ldapOptions)

You should be aware of the following with this script example:

  • The SslContextBuilder class has been removed in IG 6.5. See Release Notes › Important Changes to Existing Functionality (DS API Change for Secure LDAP Connection) for further information on how this changes affects this example script.
  • This script assumes SSL is passed in a boolean flag; if you know you will always be doing SSL, you can leave the if block out.
  • The script also calls builder.trustManager(TrustManagers.trustAll()); which makes initial setup simpler in terms of importing certificates and keystores etc, but may not be appropriate in a production setup.
Note

You should ensure your LDAPS clients are configured correctly; see How do I configure LDAPS clients in DS/OpenDJ (All versions)? for further information.

See Also

API Javadoc › Class LdapClient

Related Training

N/A

Related Issue Tracker IDs

N/A


How do I connect to IDM (All versions) with mutual SSL authentication from IG (All versions)?

The purpose of this article is to provide information on connecting to IDM with mutual SSL authentication from IG using the client certificate module (CLIENT_CERT).

Connecting to IDM with mutual SSL authentication

The following process guides you through connecting to IDM with mutual SSL authentication from IG, where IDM is the server and IG is the client:

  1. Configure the CLIENT_CERT module in IDM per Integrator's Guide › Configuring Client Certificate Authentication ensuring you update your authentication.json file (located in the /path/to/idm/conf directory) to include the module.
  2. Create a keystore for IG that contains the IG private key and certificate. See Gateway Guide › Configuring IG For HTTPS (Client-Side) for further information.
  3. Import the IG certificate into the IDM truststore to allow IDM to trust IG. See Integrator's Guide › Demonstrating the CLIENT_CERT Module for an example. 
  4. Import the IDM server certificate (openidm-localhost) into the IG truststore to allow IG to trust IDM.
  5. Create a custom endpoint for mutual SSL authentication purposes. See Integrator's Guide › Creating Custom Endpoints to Launch Scripts for further information on custom endpoints.
  6. Update the access.js script (located in the /path/to/idm/script directory) to allow the internal/role/openidm-cert role to access the custom endpoint you created. The internal/role/openidm-cert role is the default role for any user authenticated with mutual SSL authentication. For example, if your custom endpoint is endpoint/echo, the addition needed in the access.js file would be similar to this: 
    {
     "pattern" : "endpoint/echo",
     "roles" : "internal/role/openidm-cert",
     "methods" : "*",
     "actions" : "*"
    },
    
    In pre-IDM 6.5, you do not need to include the full path; you can just refer to the role name, for example, openidm-cert.
  7. Create a route in IG that includes a TlsOptions (IG 6.5 and later) or a keyManager (pre-IG 6.5) for the ClientHandler that is configured with the IG keystore. For example, your route may look similar to this with a TlsOptions object:
    {
      "handler": {
        "type": "Chain",
        "config": {
          "filters" : [
            {
                "name": "OpenIDMuserName",
                "type": "HeaderFilter",
                "config": {
                        "messageType": "REQUEST",
                        "remove": ["X-OpenIDM-Username"],
                "add" : {
                  "X-OpenIDM-Username": [ "anonymous" ]
                }
              }
            },
            {
                "name": "OpenIDMpassword",
                "type": "HeaderFilter",
                "config": {
                  "messageType": "REQUEST",
                  "remove": ["X-OpenIDM-Password"],
                  "add" : {
                    "X-OpenIDM-Password": [ "anonymous" ]
                  }
                }
            }
          ],
          "handler": {
            "type" : "ClientHandler",
            "config": {
              "hostnameVerifier": "STRICT",
              "tls": {
                "type": "TlsOptions",
                "config": {
                  "sslContextAlgorithm": "TLSv1.2",
                  "keyManager": {
                    "type": "KeyManager",
                    "config": {
                      "keystore": {
                        "type": "KeyStore",
                        "config": {
                          "url": "file://${env['HOME']}/keystore.jks",
                          "passwordSecretId": "keymanager.keystore.secret.id"
                        }
                      },
                      "passwordSecretId": "keymanager.secret.id"
                    }
                  }
                }
              }
            }
          },
          "capture" : "all"
        }
      },
      "condition": "${matches(request.uri.path, '^/openidm/endpoint/echo')}",
      "baseURI": "https://idm.example.com:18444",
      "capture" : "all",
      "timer" : true
    }
    
    See Gateway Guide › Configuring Routes for further information.
  8. Update the openidm.auth.clientauthonlyport property in the boot.properties file (located in install-dir/resolver/ (IDM 6 and later) or /path/to/idm/conf/boot/ (pre-IDM 6)) to include the IG port (and ports for any other clients that are authorized to perform authentication). You can have a list of ports, for example:
    openidm.auth.clientauthonlyports=18444,9090 
  9. Restart IDM.

Header host filter

As an alternative to specifying authorized ports in step 8, you can add a filter to the IG route to replace the header host with the IDM host and port, for example:

{ 
  "name": "HostFilter", 
  "type": "HeaderFilter", 
  "config": { 
    "messageType": "REQUEST", 
    "remove": "host", 
    "add": { 
      "host": "idm.example.com:18444" 
    } 
} 

It is up to you whether you choose to make the configuration change in IDM or IG.

See Also

How do I customize authorization rules for http requests in IDM/OpenIDM (All versions)?

Related Training

N/A

Related Issue Tracker IDs

N/A


How do I configure IG/OpenIG (All versions) to pass the client IP address to downstream applications when proxying requests?

The purpose of this article is to provide information on configuring IG/OpenIG to pass the client IP address to downstream applications (such as AM/OpenAM) when proxying requests. Typically proxies use the X-Forwarded-For header to pass this information; the downstream application must also be configured to make use of this header.

Overview

IG/OpenIG can be configured to pass the original IP address of the client by using the X-Forwarded-For HTTP header field. The downstream application must also be configured to consume the header and make use of this information, which is outside the scope of this article.

Note

If the downstream application is AM/OpenAM, you can set the com.sun.identity.authentication.client.ipAddressHeader advanced configuration property to X-Forwarded-For to achieve this. See Installation Guide › Handling HTTP Request Headers for further information.

Example scenario

The following example demonstrates a use case where IG/OpenIG would need to pass the client IP address when proxying requests:

  • All incoming requests are handled by IG/OpenIG and proxied to AM/OpenAM.
  • AM/OpenAM has been configured to use different authentication methods depending on the client IP address.

The following section explains how you can configure IG/OpenIG to pass the client IP address.

Configuring IG/OpenIG to pass the client IP address

The ClientContext can be used to supply information about the client sending a request. When IG/OpenIG receives a request, it injects information about the client sending the request into this context.

You can configure this context as follows:

  1. Update the config.json file (located in the $HOME/.openig/config/ directory) to add this context. The following example proxies all the requests and captures the headers of the request being made:
      "heap": [
        {
          "name": "ClientIPHeaderHandler",
          "type": "Chain",
          "config": {
            "filters": [
              {
                "type": "HeaderFilter",
                "config": {
                  "messageType": "REQUEST",
                  "add": {
                    "X-Forwarded-For": [
                      "${contexts.client.remoteAddress}"
                    ]
                  }
                }
              }
            ],
            "handler": {
              "name": "CaptureClientHandler",
              "type": "ClientHandler",
              "capture": "all"
            }
          }
        }
      ]
    }
    
  2. Update the relevant route (for example, 99-default.json) to use the handler specified in step 1. For example:
    {
        "handler": "ClientIPHeaderHandler",
        "capture": "all"
    }
    

Capture log

You can trace the flow in the capture log. Based on the above example, you can see the request coming in from the browser and then the request being made by IG/OpenIG to the proxied application with the additional header: 

[qtp96639997-17] INFO  o.f.o.d.c.C.c.top-level-handler - 
--- (request) id:23a32cc8-3452-44a1-af64-867b2371dfaa-14 --->

GET http://localhost:8080/examples/ HTTP/1.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: en-GB;q=1,en-US;q=0.9,en;q=0.8
Cache-Control: max-age=0
Connection: keep-alive
Host: app.example.com:7070
If-Modified-Since: Thu, 10 Jan 2013 09:54:32 GMT
If-None-Match: W/"1209-1357811672000"
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36

[qtp96639997-17] INFO  o.f.o.d.c.C.c.CaptureClientHandler - 

--- (request) id:23a32cc8-3452-44a1-af64-867b2371dfaa-14 --->

GET http://localhost:8080/examples/ HTTP/1.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: en-GB;q=1,en-US;q=0.9,en;q=0.8
Cache-Control: max-age=0
Connection: keep-alive
Host: app.example.com:7070
If-Modified-Since: Thu, 10 Jan 2013 09:54:32 GMT
If-None-Match: W/"1209-1357811672000"
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36
X-Forwarded-For: 192.0.2.0

[I/O dispatcher 9] INFO  o.f.o.d.c.C.c.CaptureClientHandler - 

<--- (response) id:23a32cc8-3452-44a1-af64-867b2371dfaa-14 ---

HTTP/1.1 304 Not Modified
Date: Wed, 14 Nov 2018 18:24:19 GMT
ETag: W/"1209-1357811672000"
Server: Apache-Coyote/1.1

[I/O dispatcher 9] INFO  o.f.o.d.c.C.c.top-level-handler - 

<--- (response) id:23a32cc8-3452-44a1-af64-867b2371dfaa-14 ---

HTTP/1.1 304 Not Modified
Date: Wed, 14 Nov 2018 18:24:19 GMT
ETag: W/"1209-1357811672000"
Server: Apache-Coyote/1.1

[qtp96639997-15] INFO  o.f.o.d.c.C.c.top-level-handler - 

See Also

How do I configure IG/OpenIG (All versions) to retrieve the user certificate and pass it to AM/OpenAM in the HTTP header?

Installing and configuring IG/OpenIG

Configuration Reference › Chain

Configuration Reference › Route

Related Training

N/A

Related Issue Tracker IDs

N/A


How do I configure IG/OpenIG (All versions) to retrieve the user certificate and pass it to AM/OpenAM in the HTTP header?

The purpose of this article is to provide information on configuring IG/OpenIG to retrieve the user (X.509) certificate from the web container and pass it to AM/OpenAM in the HTTP header. This setup can be used if you are using IG/OpenIG as a reverse proxy for AM/OpenAM and are using the Certificate Authentication module in AM/OpenAM to authenticate users.

Overview

Note

If SSL is terminated by a reverse-proxy or load balancer in front of IG/OpenIG that has been configured to pass on user certificates, IG/OpenIG will pass the HTTP header containing the user certificate (providing IG/OpenIG has not been configured to explicitly remove headers as part of a Filter configuration). Therefore, you will not need to configure IG/OpenIG in this scenario.

You should ensure AM/OpenAM has been configured to check the HTTP header for the user certificate. See How do I configure AM/OpenAM (All versions) to check the HTTP header for the user certificate? for further information.

If you are using IG/OpenIG as the reverse proxy, you can configure IG/OpenIG to retrieve the user certificate from the web container and pass it to AM/OpenAM via the HTTP header. The approach you take depends on version:

  • IG / OpenIG 4.x - as of OpenIG 4.x, there are no additional coding steps required as the certificate(s) contained in client.certificates (certificates is a list that is never null but can be empty) are already in the form required by AM/OpenAM and can just be passed on in a header as is. See Configuration Reference › Client for further information.
  • OpenIG 3.1.x - you can use ClientInfo to retrieve the certificate and then include it in a Filter. See Configuring OpenIG 3.1.x for further information.
  • OpenIG 3.0 - you need to create a custom Filter to achieve this as you cannot access the attributes of the request in this version of OpenIG. See Configuring OpenIG 3.0 for further information.

Web container

You should ensure the web container in which AM/OpenAM and IG/OpenIG are deployed handles user certificates correctly. For example, for Apache Tomcat™, you should set clientAuth to "want" in the server.xml file.

See Gateway Guide › Configuring Deployment Containers for further information on configuring the web container. In particular, Gateway Guide › Configuring Tomcat For HTTPS (Server-Side) for information on getting Tomcat up quickly on an SSL port.

Configuring OpenIG 3.1.x

In OpenIG 3.1.x, you can access the client certificates through exchange.clientInfo.certificates (certificates is a list, never null but can be empty) so the example code is a little simpler than in OpenIG 3.0:

import java.io.IOException;
import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;
import javax.xml.bind.DatatypeConverter;
import org.forgerock.openig.filter.GenericFilter;
import org.forgerock.openig.handler.Handler;
import org.forgerock.openig.handler.HandlerException;
import org.forgerock.openig.http.Exchange;
import org.forgerock.openig.log.LogTimer;

public class CertFilter3x extends GenericFilter {

    @Override
    public void filter(Exchange exchange, Handler next) throws HandlerException, IOException {

        LogTimer timer = logger.getTimer().start();
        for (X509Certificate cert : exchange.clientInfo.getCertificates()) {
            // Add certificate to headers here
            exchange.request.getHeaders().add("CertHeaderName", getPemCert(cert));
        }
        next.handle(exchange);
        timer.stop();
    }

    private String getPemCert(X509Certificate x509cert) {

        StringBuilder pemCert = new StringBuilder();
        try {
            pemCert.append("-----BEGIN CERTIFICATE-----");
            pemCert.append(DatatypeConverter.printBase64Binary(x509cert.getEncoded()));
            pemCert.append("-----END CERTIFICATE-----");
        } catch (CertificateEncodingException e) {
            // Handle exception
        }

        return pemCert.toString();
    }
}

Configuring OpenIG 3.0

In OpenIG 3.0, you need to create a custom Filter to access the user certificate. An example to get you started is:

import java.io.IOException;
import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;
import javax.servlet.http.HttpServletRequest;
import javax.xml.bind.DatatypeConverter;
import org.forgerock.openig.filter.GenericFilter;
import org.forgerock.openig.handler.Handler;
import org.forgerock.openig.handler.HandlerException;
import org.forgerock.openig.http.Exchange;
import org.forgerock.openig.log.LogTimer;

public class CertFilter21 extends GenericFilter {

    @Override
    public void filter(Exchange exchange, Handler next) throws HandlerException, IOException {

        LogTimer timer = logger.getTimer().start();
        HttpServletRequest request = (HttpServletRequest)exchange.get("javax.servlet.http.HttpServletRequest");
        if (request != null) {
            X509Certificate[] certs = (X509Certificate[])request.getAttribute("javax.servlet.request.X509Certificate");
            if (certs != null) {
                for (X509Certificate cert : certs) {
                    exchange.request.getHeaders().add("CertHeaderName", getPemCert(cert));
                }
            }
        }
        next.handle(exchange);
        timer.stop();
    }
    
    private String getPemCert(X509Certificate x509cert) {

        StringBuilder pemCert = new StringBuilder();
        try {
            pemCert.append("-----BEGIN CERTIFICATE-----");
            pemCert.append(DatatypeConverter.printBase64Binary(x509cert.getEncoded()));
            pemCert.append("-----END CERTIFICATE-----");
        } catch (CertificateEncodingException e) {
            // Handle exception
        }

        return pemCert.toString();
    }
}

See Also

How do I configure AM/OpenAM (All versions) to check the HTTP header for the user certificate?

Authentication and Single Sign-On Guide › Implementing Authentication › Certificate Authentication Module

Gateway Guide › Extending the ForgeRock Identity Gateway › Key Extension Points

Related Training

N/A

Related Issue Tracker IDs

N/A


How do I configure an idle timeout in IG/OpenIG (All versions)?

The purpose of this article is to provide information on configuring IG/OpenIG to automatically expire sessions after a set period of time.

Configuring idle timeout

You have two options for setting idle timeout in IG/OpenIG depending on your requirements:

  • JwtSession - if you use this object to store sessions, you can specify how long they are valid for. This is not strictly an idle timeout, but may be sufficient for your needs.
  • HTTP session - if you require true idle timeout functionality, then you must specify session timeout settings in the web application container.

JwtSession 

If you are using the JwtSession object to store sessions, then you can use the sessionTimeout property to specify how long sessions are valid for:

  • In IG 5 and later, there is a persistentCookie property - this must be set to true to create persistent cookies and then you should set sessionTimeout to the period of time for which the JWT session is valid. Once this time period is exceeded, the cookie will expire.
  • In OpenIG 4, cookies are always persistent, which means you just need to set the sessionTimeout property.

See Configuration Reference › JwtSession for further information including valid duration settings for the sessionTimeout property.

HTTP session

If you want true session idle timeout, you need to set the <session-timeout> property in either the web application container configuration file (global setting) or in the web.xml file (located in the WEB-INF directory) for the IG/OpenIG web application; this setting overrides the global setting.

For example, to set the timeout to 60 minutes:

    <session-config>
        <session-timeout>60</session-timeout>
    </session-config>

The required global configuration file varies according to which container you use:

  • Apache Tomcat™ - web.xml (located in the /path/to/tomcat/conf/ directory).
  • Jetty® - webdefault.xml (located in the /path/to/jetty/etc/ directory).
  • JBoss® - web.xml (located in the server/<profile>/deploy/jboss-web.deployer/conf/ directory).

Automatic logout

There are no session expired triggers in IG/OpenIG that can automatically log you out of an associated application once the session expires. One possible solution would be to call the logout endpoint on the other application every time a user arrives at IG/OpenIG without a valid session; however, if this requires tokens or other values that IG/OpenIG won't have access to (because the user's session has expired or does not exist) then this will not be possible.

See Also

Installing and configuring IG/OpenIG

Java Session Timeout

Related Training

N/A

Related Issue Tracker IDs

N/A


How do I filter information included in logs in IG (All versions) and OpenIG 4.5?

The purpose of this article is to provide information on filtering the IG/OpenIG logs to determine what information is logged. Filtering allows you to hide sensitive information in the logs such as passwords and session tokens. This information applies to capture logs for routes and audit logs.

Background Information

Capture logs

IG/OpenIG logs everything contained in the entity by default, which means filtering is required if you have requests or responses that contain sensitive information such as passwords.

OpenIG 4.5 introduced a new logger based on SLF4J, which provides a lot of flexibility around logging; this includes a regex pattern swapping function: replace(p){r, t}, which can be used to mask information in the logs: Logback Layouts › Replace.

Note

Using the replace(p){r, t} function will increase the logging overhead as IG/OpenIG will have to parse the entire message; you should only apply it to selective routes where you need this feature rather than to all routes.

Audit logs

You can use a filter policy in your AuditService configuration to exclude sensitive data from log files.

Filtering information in the capture logs

You can include the replace(p){r, t} function in the pattern section of the logback.xml file in the IG/OpenIG configuration directory, which by default is $HOME/.openig/config/.

The following example demonstrates using this function to replace passwords (this example is based on the default ConsoleAppender in the logback.xml file):

  <encoder>
   <pattern>%nopex[%thread] %highlight(%-5level) %boldWhite(%logger{35}) - %replace(%message){'"X-OpenIDM-Password": ".*"', '"X-OpenIDM-Password": "xxx"'} %n%highlight(%rootException{short})
   </pattern>
  </encoder>

You can also nest replace calls, for example:

%replace(%replace(%message){'regex1', 'replacement1'}){'regex2', 'replacement2'}

You can use websites such as Online Regex Tester to test your regular expressions for any other replacement changes you want to include.

Filtering information in the audit logs

You can include a filter policy in your AuditService configuration to exclude sensitive information. See Configuration Reference › AuditService for a suggested list of filters you should include. You can include as many or as few of these as required, plus any additional ones you need. The important thing is to ensure you include the path to the header, for example: /access/http/request/headers/.

The following example demonstrates using the filter policy to exclude the X-OpenAM-Password header from the audit logs:

    "auditService": {
        "type": "AuditService",
        "config": {
            "config": {
                "filterPolicies" : {
                    "field" : {
                        "excludeIf" : [
                            "/access/http/request/headers/X-OpenAM-Password"
                        ]
                    }
                }
            },
            "event-handlers": [{
                "class": "org.forgerock.audit.handlers.json.JsonAuditEventHandler",
                "config": {
                    "name": "json",
                    "logDirectory": "/tmp/logs",
                    "topics": [
                        "access"
                    ]
                }
            }]
        }
    },

See Also

How do I collect debug logs in IG/OpenIG (All versions) for troubleshooting?

How do I generate more detailed logs to diagnose an issue in IG (All versions)?

OpenIG 4.5 Release Notes › New Features

IG 5 Release Notes › Important Changes to Existing Functionality

Gateway Guide › Logging Events

Gateway Guide › Reference Logback Configuration

Related Training

N/A

Related Issue Tracker IDs

N/A


How do I create a custom error page in IG/OpenIG (All versions)?

The purpose of this article is to provide information on creating custom error pages in IG/OpenIG for standard response codes.

Creating a custom error page

You can use the StaticResponseHandler for custom error pages. This handler checks for error codes coming from the backend application and can be used to replace a standard error message with a custom response.

This article includes two examples to get you started:

Multiple error codes

You can also check for a range of error codes rather than just a single code by using a condition such as:

"condition": "${response.status.code >= 500 and response.status.code <= 504}",

Custom text

The examples show custom text being specified in the entity field; if you would prefer to include the custom text in a file, replace the text in the entity field using the read(), Function for example:

"entity": "${read('/home/user/customError.html')}"

Where customError.html is the file that contains your custom text.

403 error page

Here's a simple example that checks for response code 403 and replaces the standard response with the text defined in the entity field:

          "handler": {
            "name": "MyChain",
            "type": "Chain",
            "config": {
              "filters": [
                {
                  "name": "Switch",
                  "type": "SwitchFilter",
                  "config": {
                    "onResponse": [
                      {
                        "condition": "${response.status.code == 403}",
                        "handler": {
                          "type": "StaticResponseHandler",
                          "config": {
                            "status": 403,
                            "reason": "ACCESS DENIED",
                            "entity": "<html>403: Access Denied: You do not have permission to view this page.</html>"
                          }
                        }
                      }
                    ]
                  }
                }
              ],
              "handler": {
                "type": "ClientHandler",
                "comment": "Log the request, pass it to the protected application, and then log the response",
                "capture": "all",
                "baseURI": "https://example.com"
              }
            }
          }

500 error page

In this example, by being ahead of the PolicyEnforcementFilter, the StaticResponseHandler will intercept 500 error codes returned by AM/OpenAM’s policy engine and replace them with the text defined in the entity field:

        {
            "name": "Switch",
            "type": "SwitchFilter",
            "config": {
              "onResponse": [
                {
                  "condition": "${response.status.code == 500}",
                  "handler": {
                    "type": "StaticResponseHandler",
                    "config": {
                      "status": 500,
                      "reason": "ERROR",
                      "entity": "<html>500: Custom error page.</html>"
                    }
                  }
                }
              ]
            }
          },
        {
         "type": "PolicyEnforcementFilter",
          "name": "PolicyEnforcementFilter-1",
          "config": {
            "amService": "AmService",
            "pepRealm": "/",
            "application": "PEP policy set",
            "ssoTokenSubject": "${contexts.ssoToken.value}"
          }
        }
      ],
      "handler": "ClientHandler"
    }
  }
}

The amService property shown in the example above is used in IG 6 and later; it replaces the following removed properties: openamUrl, pepUsername, pepPassword and realm as detailed in Release Notes › Removed Functionality.

See Also

FAQ: Installing and configuring IG/OpenIG

Installing and configuring IG/OpenIG

Configuration Reference › PolicyEnforcementFilter

Related Training

N/A

Related Issue Tracker IDs

N/A


How do I migrate OpenIG 4 scripts from using blocking APIs to non-blocking APIs?

The purpose of this article is to provide information on migrating existing OpenIG 4 scripts from using blocking APIs to non-blocking APIs. Moving to non-blocking APIs guarantees an efficient use of resources and can prevent deadlock situations. You should also migrate your scripts if you have upgraded to OpenIG 4.5 or later, or are planning to upgrade in the future; otherwise you will likely encounter a "Cannot execute script" error when trying to run an existing script.

Overview

There is a known issue where existing scriptable filters and handlers stop working after upgrading to OpenIG 4.5 or later. This issue is caused by a class version conflict in the CatalogManager class, which is used by the xml-resolver-1.2.jar and is required by the HTTPBuilder API. This issue affects all scripts that use the CatalogManager class or libraries that depend on it, for example, the Groovy http-builder library. You can resolve this issue by migrating to CHF supported APIs.

You will see an error similar to the following in your logs when you encounter this issue:

TUE MAY 02 17:02:59 CET 2017 WARNING {ScriptableFilter}/handler/config/filters/0 --- Cannot execute script
TUE MAY 02 17:02:59 CET 2017 WARNING {ScriptableFilter}/handler/config/filters/0 --- java.lang.Exception: java.lang.NoSuchMethodError: org.apache.xml.resolver.CatalogManager.setIgnoreMissingProperties(Z)V 
javax.script.ScriptException: java.lang.Exception: java.lang.NoSuchMethodError: org.apache.xml.resolver.CatalogManager.setIgnoreMissingProperties(Z)V
   at org.forgerock.openig.script.Script$GroovyImpl.run(Script.java:62)
   at org.forgerock.openig.script.Script.run(Script.java:245) 
Caused by: java.lang.Exception: java.lang.NoSuchMethodError: org.apache.xml.resolver.CatalogManager.setIgnoreMissingProperties(Z)V
   ... 42 more
Caused by: java.lang.NoSuchMethodError: org.apache.xml.resolver.CatalogManager.setIgnoreMissingProperties(Z)V
   at groovyx.net.http.ParserRegistry.<clinit>(ParserRegistry.java:111)
   at groovyx.net.http.HTTPBuilder.<init>(HTTPBuilder.java:194)
   at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
   at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
   ... 41 more

It is strongly recommended that you migrate to CHF supported APIs and use documented variables even if you are not experiencing issues with your scripts. CHF non-blocking APIs guarantee an efficient use of resources and can prevent deadlock situations; they also ensure you can upgrade to OpenIG 4.5 and later without encountering this issue.

This article details the following two step migration process:

  1. Migrate http-builder APIs to CHF blocking APIs (they are simple to understand and starting using).
  2. Migrate to CHF asynchronous APIs.

Example script

The following example script to log a user out of AM/OpenAM uses the Groovy http-builder library; it fails in OpenIG 4.5 and later because there is a class version conflict on CatalogManager, which is provided by both the AM/OpenAM SAML Fedlet library and the Groovy http-builder library:

@Grab('org.codehaus.groovy.modules.http-builder:http-builder:0.7.1')
import groovyx.net.http.RESTClient

def openAMRESTClient = new RESTClient(openamUrl)

// Check if OpenAM session cookie is present
if (null != request.cookies['iPlanetDirectoryPro']) {
   String openAMCookieValue = request.cookies['iPlanetDirectoryPro'][0].value

   // Perform logout
   logger.info("iPlanetDirectoryPro cookie found, performing logout")
   def response = openAMRESTClient.post(path: 'sessions/',
                                        query: ['_action': 'logout'],
                                        headers: ['iplanetDirectoryPro': openAMCookieValue])
   def result = response.getData().get("result")
   logger.info("OpenAM logout response: " + result)
}

return next.handle(context, request)

The logic in this script is quite simple:

  1. If there is a session token in the request, get it.
  2. Call a dedicated AM/OpenAM REST endpoint to revoke the token (which logs the user out).
  3. Continue the execution of the chain (after the response has been received).

Migrating to CHF blocking APIs

This step details removing the dependency on the http-builder library and using the built-in CHF APIs instead. The migrated example script below demonstrates the basics of the CHF API: request creation, obtaining a response and reading its content as JSON (without forgetting to release resources).

Background

In each script’s execution context there is an HTTP binding (Client interface) that provides you with a way to perform HTTP requests from within your script.

From the Client API:

class Client {
   Promise<Response, NeverThrowsException> send(Request request);
   Promise<Response, NeverThrowsException> send(Context context, Request request);
}

There is only one thing that you can obviously do with this interface, that is, send an HTTP request. You do not get back the response directly, but you have the promise of a response. This is comparable to a Future on which you would attach listeners that get notified when the response has been fully received (or an error has happened).

This part of the migration uses the Promise as a Future (blocking on a .get()). In essence, this migration step is all about creating and populating a CHF Request object.

Migrated example script

The following shows the above example script after it has been migrated to use the built-in CHF APIs:

// Check if OpenAM session cookie is present
if (null != request.cookies[ 'iPlanetDirectoryPro' ]) {
   String openAMCookieValue = request.cookies[ 'iPlanetDirectoryPro' ][ 0 ].value

   logger.info("iPlanetDirectoryPro cookie found, performing logout")

   def logout = new Request()
   logout.method = "POST"
   logout.uri = "${openamUrl}/sessions"
   logout.uri.query = "_action=logout"
   logout.headers['iPlanetDirectoryPro'] = openAMCookieValue

   // Block for at most 20 seconds before using the response
   def logoutResponse = http.send(logout)
                            .get(20, SECONDS)

   def result = logoutResponse.entity.json.result
   logger.info("OpenAM logout response: " + result)

   // Don’t forget to release resources associated with the response
   logoutResponse.close()
}

return next.handle(context, request)

The logic in this script is as follows:

  1. Request initialization: the following snippet of this script creates a POST request to the AM/OpenAM sessions endpoint (using Groovy String substitution). It specifies the logout action in the query URL component and places the current request’s SSO Token (the iPlanetDirectoryPro cookie) in a header (as this is where the sessions endpoint expects it):
    def logout = new Request()
    logout.method = "POST"
    logout.uri = "${openamUrl}/sessions"
    logout.uri.query = "_action=logout"
    logout.headers['iPlanetDirectoryPro'] = openAMCookieValue
    
  2. Perform the request and wait for the response: the following snippet of this script uses the get() method. The returned promise can never throw an exception, which means you do not need to use the getOrThrow() variant of the get() method; if something goes wrong when making the request, you will receive a 502 Bad Gateway response. This example also includes a timeout to prevent deadlocks if there is no response. When the timeout is reached, a RuntimeException is returned; ideally the timeout should be configurable and IG/OpenIG provides the args configuration point in the script configuration, which can be used for this purpose:
    // Block for at most 20 seconds before using the response
    def logoutResponse = http.send(logout)
                             .get(20, SECONDS)
    
  3. Read the response's content using the CHF's native JSON support: the following snippet of this script calls logoutResponse.entity.json, which provides the JSON-parsed content of the message, with a focus on the result JSON attribute. The message is then closed to release resources:
    def result = logoutResponse.entity.json.result
    
    // Don’t forget to release resources associated with the response
    logoutResponse.close()
    
    
  4. Call the next element of the chain and continue the request processing:
    return next.handle(context, request)
    

Migrate to CHF asynchronous APIs

This step details moving away from synchronous programming (where we spend valuable CPU time waiting for things to happen) to asynchronous programming (where we register callbacks to notify us when things are ready and act when that happens rather than waiting for something; this allows our valuable CPU time to do other things). It also introduces the http.send() returned Promise object, where it’s the promise of a response that may or may not have been received yet. Put simply, we want to read the response content after it has been received, log the result and then continue the chain execution.

This step demonstrates adding an asynchronous function that calls the next element in the chain, after the response processing has been done.

Migrated example script

The following shows the example script after it has been migrated to use the CHF asynchronous APIs:

// Check if OpenAM session cookie is present
if (null != request.cookies[ 'iPlanetDirectoryPro' ]) {
   String openAMCookieValue = request.cookies[ 'iPlanetDirectoryPro' ][ 0 ].value

   logger.info("iPlanetDirectoryPro cookie found, performing logout")

   def logout = new Request()
   logout.method = "POST"
   logout.uri = "${openamUrl}/sessions"
   logout.uri.query = "_action=logout"
   logout.headers['iPlanetDirectoryPro'] = openAMCookieValue

   // Return the "promise" of a result => non-blocking
   // Processing will happen when a response from AM will be received
   return http.send(logout)
              .then { response ->
                   def result = response.entity.json.result
                   logger.info("OpenAM logout response: " + result)
                   response.close()
                   return response
              }
              .thenAsync({
                   next.handle(context, request)
              } as AsyncFunction)
}

logger.info("iPlanetDirectoryPro cookie not found, continue and ignore logout action")
return next.handle(context, request)

As you can see, most of the changes have occurred towards the end of the script, with the response being processed using callbacks. Additionally, since we no longer block, we do not need a timeout to prevent deadlocks.

The logic in this script is as follows:

  1. Process the response when it’s ready: the following snippet of this script introduces a then(Function) method to process this response. The callback Function provided in this then() method accepts the result of the invocation as a parameter, which can be processed as required; this example reuses the response processing logic from before to return the response (a result is expected from Function callbacks):
    return http.send(logout)
               .then { response ->
                    def result = response.entity.json.result
                    logger.info("OpenAM logout response: " + result)
                    response.close()
                    return response
               }
    
    
    You must include the first return in this section of the script to ensure the promise that is configured with the response processing function is returned when the logout action is triggered. If you exclude the return, for example, the first line is simply:
    http.send(logout)
    
    The script will execute, do an HTTP call, register a callback on the promise and then just continue. This means the logout action will get missed when there is an iPlanetDirectoryPro cookie, which is not the desired behavior of this script.
  2. Continue the execution of the chain after triggering the logout action: the following snippet of this script calls the next element of the chain by performing the call in a then-able fashion (chaining different then() methods together). You can use this approach because you will just see the response of the logout action when a request with an iPlanetDirectoryPro cookie enters the filter, rather than the usual response sent back from the protected application:
               .thenAsync({
                   next.handle(context, request)
               } as AsyncFunction)
    

Groovy specific points

  •  There is no return statement, because Groovy considers the last evaluated expression of a method to be the returned value.
  • The as AsyncFunction is only required for asynchronous functions (ResultHandler, ExceptionHandler and Function don’t need it). The Groovy compiler doesn’t handle all the generic types of AsyncFunction very well.

Further information on the Promise object

There are a number of then-able methods offered by the Promise API that you can try, which will make your code simpler and avoid 'callback hell'. These methods fall into the following categories:

thenOn****(****Handler) These methods are pure notification functions (on successful result, on error). You can’t return anything from within these methods, they are here as a side-effect-free type of handler. No exceptions should be thrown in theses callbacks.
then(Function), with 1, 2 or 3 Function arguments These methods are designed for when you need to return something different to the next handler in the Promise chain (a transformation). They could be parsing an input string and return a JSON, or modifying the result. Throwing exceptions is accepted here and they will be propagated to the next functions in the Promise chain.
thenAsync(AsyncFunction), with 1, 2 or 3 AsyncFunction arguments These methods are quite similar to those in then(Function). The real difference is that they have to return a promise of their result instead of the actual result. These methods are an ideal fit when you need to call another method that itself returns a promise (like returning the result of the filter’s chain).
then***(), the rest of the then-able methods (thenAlways(), thenFinally(), thenCatch(), ...) These methods are really syntactic sugar to make the promise more fluent to read.

Now you can understand why our first then() can be turned into a thenOnResult() instead, which saves the last return statement as the received parameter is returned:

return http.send(logout)
           .thenOnResult { response ->
               def result = response.entity.json.result
               logger.info("OpenAM logout response: " + result)
               response.close()
           }
           .thenAsync({
               next.handle(context, request)
           } as AsyncFunction)

See Also

N/A

Related Training

N/A

Related Issue Tracker IDs

OPENIG-910 (ScriptableFilter : Get error `Cannot execute script` with groovy scripts previously working)


Frequently Asked Questions


FAQ: Installing and configuring IG/OpenIG

The purpose of this FAQ is to provide answers to commonly asked questions regarding installing and configuring IG/OpenIG.

Frequently asked questions

Q. Is IG/OpenIG compatible with Oracle Java Development Kit (JDK) 11?

A. No, Oracle JDK 11 is not supported, however, IG 6.5 does support OpenJDK 11. You should only use supported versions to prevent compatibility issues.

Q. Can IG/OpenIG be used with OpenJDK?

A. Yes. IG 5.x and 6.x have been tested with OpenJDK 1.8; OpenJDK has not been tested with with earlier versions of OpenIG, but OpenJDK is a compliant JDK and is fully compatible. However, as it has not been tested, there may be incompatibility issues with other third-party products.

Note

If you are using IG on Tomcat with SSL enabled, use OpenJDK 1.8.0_121 or later versions to prevent mismatch between client side ciphers and server side ciphers.

Q. Can I run multiple IG/OpenIG instances on the same server?

A. Yes you can but you must adhere to the following guidelines:

  • Run each IG/OpenIG instance in its own web application container instance since IG/OpenIG must be run as the root context web application (for example, ROOT.war in Apache Tomcat™).
  • Use different ports for each web application container instance.
  • Use different base configuration directories for each instance. By default, configuration files are stored in the $HOME/.openig directory, so you would want to change this, for example, $HOME/.openig1$HOME/.openig2 etc. See Gateway Guide › Changing the Default Location of the Configuration Folders for further information.
  • Rename the cookie used for JwtSession if instances run under the same hostname but you do not want to share the stateless session across instances. You do not need to rename this cookie if you want the stateless session to be shared across all IG/OpenIG instances running in a cluster. In this scenario you need to ensure that the keys/certificates are also the same. See Configuration Reference › JwtSession for further information.

Q. Can I run IG/OpenIG in the same web application container instance as AM/OpenAM?

A. No, you should run IG/OpenIG and AM/OpenAM in separate web application containers to avoid property file / classloading issues.

Q. Do AM/OpenAM and IG/OpenIG need to be running on the same web application container version?

A. No, there is no dependency between the AM/OpenAM and IG/OpenIG web application container versions.

Q. Can I install IG/OpenIG and AM/OpenAM on the same VM instance?

A. You can for testing purposes provided they listen to different ports for HTTP/HTTPS. However, this setup is not recommended in production.

Q. Can I terminate SSL at the load balancer?

A. Yes, you can set up IG/OpenIG servers behind a load balancer and offload SSL at the load balancer (for example, the F5). 

Q. Why does IG/OpenIG have to be installed as the root application?

A. If the intention is to use IG/OpenIG as a reverse proxy for all requests, there shouldn't really be a scenario where you would want to deploy it as anything other than root. If it is not in the root context, you would be restricting applications that can be proxied to since they need to be in the same context. 

There is also code within IG/OpenIG that implicitly assumes it is deployed in the root context.

Q. What throttling algorithm does IG/OpenIG use and how does it work?

A. The throttling algorithm used in IG/OpenIG is the Token bucket algorithm. This is the only supported algorithm in IG/OpenIG and allows a more regulated flow under load; however, since this algorithm does not prevent traffic bursts, the throttling rate may occasionally deviate from the defined limit.

This algorithm throttles and smooths the traffic once the incoming rate of requests is higher than the declared throttling rate. Initially the bucket is filled with tokens (requests) without any rate limit (seen as a traffic burst). Once the bucket is full, the rate limit is applied:

  • Before the bucket is full: IG/OpenIG keeps accepting requests.
  • Once the bucket is full and IG/OpenIG receives more requests than the configured throttling rate (for example, 6 requests every 60 seconds), the algorithm allows the bucket to push one token out every duration/requests seconds (in this example, 60/6, which  is every 10 seconds). As tokens are pushed out, additional tokens can be accepted.

In your log, you will see HTTP/1.1 200 responses when tokens are accepted and HTTP/1.1 429 responses when the bucket is full. Among the HTTP/1.1 429 responses will be HTTP/1.1 200 responses when a token has been pushed out, thus allowing another token to be accepted. For example, you will see something similar to this in your log:

[.559s] HTTP/1.1 200 
[.663s] HTTP/1.1 200 
[.747s] HTTP/1.1 200 
[.837s] HTTP/1.1 200 
[.925s] HTTP/1.1 200 
[1.007s] HTTP/1.1 200 
[1.093s] HTTP/1.1 429 
[1.167s] HTTP/1.1 429 
[1.260s] HTTP/1.1 429 
[1.350s] HTTP/1.1 429 
[1.440s] HTTP/1.1 429 
[1.518s] HTTP/1.1 429 
[1.602s] HTTP/1.1 429 
[1.688s] HTTP/1.1 429 
[1.761s] HTTP/1.1 429 
[1.846s] HTTP/1.1 429 
[1.920s] HTTP/1.1 429 
[1.998s] HTTP/1.1 429 
[2.083s] HTTP/1.1 200 
[2.161s] HTTP/1.1 429 
...

Q. How do I configure IG/OpenIG to not enforce URI authorization for certain file types?

A. You can use route conditions to control which requests are handled by IG/OpenIG as detailed in Gateway Guide › Setting Route Conditions.

If you want similar functionality to the URI Not Enforced list used by the Policy Agents, you can craft a condition using regular expressions to explicitly exclude file types (such as graphics, images and CSS files) which may not require authorization for your deployment.

For example, the following condition would not enforce authorization on a request where the URI contains .css .svg, and .png file types:

"condition": "${matches(request.uri.path, '^/login') and matches(request.uri.path,'(\\\\.css|\\\\.svg|\\\\.png)$')}",
Note

Customizing or building expressions for IG/OpenIG is outside the scope of ForgeRock support; if you want more tailored advice, consider engaging Deployment Support Services.

Q. Does IG/OpenIG support URI rewriting?

A. No, IG/OpenIG does not currently support URI rewriting, it does just rebase the host:port of the base URL. There is an RFE raised to include this functionality in a future release: OPENIG-1664 (Provide support for basic URI path rewriting).

If you need to rewrite URLs, you can use a ScriptableFilter as detailed in Configuration Reference › ScriptableFilter. Unfortunately, we do not provide an example ScriptableFilter for this purpose as there are many different use cases and it can be error prone working with the regular expressions needed to rewrite links in HTML pages.

See Also

FAQ: Source code in IG/OpenIG

FAQ: IG/OpenIG compatibility with third-party products

Installing and configuring IG/OpenIG

LocationHeaderFilter - rewrites Location headers

Release Notes

Gateway Guide › Installation in Detail


FAQ: IG/OpenIG compatibility with third-party products

The purpose of this FAQ is to provide answers to commonly asked questions regarding IG/OpenIG compatibility with third-party products.

Frequently asked questions

Q. Is IG/OpenIG FIPS 140-2 compliant?

A. ForgeRock conforms to FIPS 140-2 for encryption and hashing ciphers for both inflight messaging, protocol tunnels and credential storage. In addition, the ForgeRock solution has been certified in deployments against rigorous DoD STIG requirements and is in process at FedRAMP certification. All of these certifications require proper FIPS 140-2 compliance. The solution allows deployments to choose ciphers; the most common ones used in deployments tend to be SHA-256 and AES-256, however we support stronger key lengths on both of these. A common trend for mobility is support for elliptical curve cryptography due to its high security yet low process power nature and of course is also recommended by NIST as part of FIPS 140-2.

Regarding FIPS 140-2 certification, ForgeRock does not write its own crypto modules, but our software can utilize underlying crypto modules (usually those associated with Java®) which have options to be executed in FIPS-compliant mode.

See Also

FAQ: Installing and configuring IG/OpenIG


Known Issues


502 Bad Gateway or SocketTimeoutException when using IG (All versions)

The purpose of this article is to provide assistance if you encounter a 502 Bad Gateway response when routing from IG to a custom endpoint, or an endpoint in IDM or AM using a ClientHandler. This response is accompanied by a "java.net.SocketTimeoutException: null" error.

Symptoms

An error similar to one of the following is shown in the web application container log (for example, catalina.out for Apache Tomcat™) when the endpoint is called from IG (this may be an intermittent error):

--- (response) id:aa167dcf-461d-513b-a942-9272bad726fb-736 ---

HTTP/1.1 502 Bad Gateway
Context's content :
attributes:
     org.apache.tomcat.util.net.secure_protocol_version: "TLSv1.2"

[I/O dispatcher 11] INFO mo.f.o.d.t.T.timer.top-level-handler - Elapsed time: 10025 ms 
[I/O dispatcher 11] WARN mo.f.o.f.LogAttachedExceptionFilter - Response [Status: 502 Bad Gateway] to 'https://idm.example.com:8444/openidm/endpoint/test' carries an exception [txId:aa167dcf-503b-461d-a745-9285bad726fb-735] 
java.net.SocketTimeoutException: null    
   at org.apache.http.nio.protocol.HttpAsyncRequestExecutor.timeout(HttpAsyncRequestExecutor.java:375)
[http-bio-198.51.100.0-8443-exec-2] ERROR mo.f.o.handler.router.RouterHandler - no handler to dispatch to 
[http-bio-198.51.100.0-8443-exec-1] INFO mo.f.o.d.c.C.c.myClientHandler
--- (response) id:aa167dcf-461d-513b-a942-9272bad726fb-736 ---

HTTP/1.1 502 Bad Gateway 
Context's content : 
attributes: 
     org.apache.tomcat.util.net.secure_protocol_version: "TLSv1.2"

[I/O dispatcher 12] WARN o.f.openig.handler.ClientHandler - An error occurred while processing the request 
java.net.SocketTimeoutException: null 
   at org.apache.http.nio.protocol.HttpAsyncRequestExecutor.timeout(HttpAsyncRequestExecutor.java:375) 
[I/O dispatcher 12] INFO o.f.o.d.c.C.c.TlsClientHandler -

Recent Changes

N/A

Causes

The connection from IG to the backend is timing out before a response has been received by the client application. By default, the timeouts for the IG ClientHandler are set to 10 seconds.

Solution

This issue can be resolved by increasing the timeouts (connectionTimeout and soTimeout) for the ClientHandler in the IG route. For example, the configuration in the route would look similar to this with a 30 second timeout:

 "handler": { 
   "name": "myClientHandler", 
   "type": "ClientHandler", 
   "config": {
      "connectionTimeout": "30 seconds", 
      "soTimeout": "30 seconds" 
   }
}

If you prefer to set these timeouts globally in config.json (located in the $HOME/.openig/config/ directory), you should ensure you define the ClientHandler correctly in the route, for example:

"handler": "myClientHandler",

See Also

Troubleshooting IG/OpenIG

Installing and configuring IG/OpenIG

Gateway Guide › Configuring Routes

Configuration Reference › ClientHandler

Related Training

N/A

Related Issue Tracker IDs

N/A


config.json not readable error in IG/OpenIG (All versions)

The purpose of this article is to provide assistance if you encounter a "/root/.openig/config/config.json" not readable error in IG/OpenIG.

Symptoms

Accessing a standard page using the hard-coded credentials in the 01-static.json file fails (for example, if you are trying the installation per Getting Started Guide › Trying IG With a Simple Configuration). The 01-static.json file is located in the $HOME/.openig/config/routes/ directory.

The following error is shown in the stdout: 

2016-11-23 09:27:19.195:INFO:oeja.AnnotationConfiguration:main: Scanning elapsed time=3253ms
[main] [34mINFO [0;39m [1;37mo.f.o.http.GatewayHttpApplication[0;39m - OpenIG base directory : /root/.openig
[34m[0;39m[main] [34mINFO [0;39m [1;37mo.f.o.http.GatewayHttpApplication[0;39m - /root/.openig/config/config.json not readable, using OpenIG default configuration

Log file location for stdout depends upon your http container, see  How do I collect debug logs in IG/OpenIG (All versions) for troubleshooting? for further information.

Recent Changes

Installed or configured IG/OpenIG as user Root.

Causes

You are running IG/OpenIG's web application container as a user other than Root, meaning you cannot access the configuration since IG/OpenIG's configuration is in a directory owned by Root.

Solution

This issue can be resolved by moving the IG/OpenIG configuration into a directory owned by the user who actually runs the web application container. For example, if the Jetty user runs the web application container, the 01-static.json file should be located in the Jetty user's directory instead:

/jetty/.openig/config/routes/01-static.json

See Also

FAQ: Installing and configuring IG/OpenIG

Installing and configuring IG/OpenIG

Related Training

N/A

Related Issue Tracker IDs

N/A


An illegal reflective access operation has occurred when using Java 11 with ForgeRock products

The purpose of this article is to provide assistance if you encounter "An illegal reflective access operation has occurred" warning when using ForgeRock products with Java® 11. This issue affects AM 6.5.x, DS 6.5.x, IDM 6.5.x, IG 6.5.x and Java Agent 5.6.x.

Symptoms

You will see An illegal reflective access operation has occurred warning when installing and using AM (including Amster and ssoadm tools), Java Agents, DS, IDM and IG. The subsequent two lines following this warning vary depending on which product you are using and what you were doing at the time it occurred.

Here are some examples of the types of error you will see by product:

  • AM:
    WARNING: An illegal reflective access operation has occurred
    WARNING: Illegal reflective access by org.codehaus.groovy.vmplugin.v7.Java7$1 (file:/path/to/tomcat/webapps/openam/WEB-INF/lib/groovy-2.4.6.jar (about:blank)) to constructor java.lang.invoke.MethodHandles$Lookup(java.lang.Class,int)
    WARNING: Please consider reporting this to the maintainers of org.codehaus.groovy.vmplugin.v7.Java7$1
    WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
    WARNING: All illegal access operations will be denied in a future release
    
  • Java Agent:
    WARNING: An illegal reflective access operation has occurred
    WARNING: Illegal reflective access by org.forgerock.openam.sdk.com.google.inject.internal.cglib.core.$ReflectUtils$1 (file:/tmp/5.6.0/java/java_agents/tomcat_agent/lib/jee-agents-installtools-5.6.0.jar) to method java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain)
    WARNING: Please consider reporting this to the maintainers of org.forgerock.openam.sdk.com.google.inject.internal.cglib.core.$ReflectUtils$1
    WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
    WARNING: All illegal access operations will be denied in a future release
    
  • DS:
    WARNING: An illegal reflective access operation has occurred
    WARNING: Illegal reflective access by org.opends.server.util.Platform$PlatformIMPL (file:/path/to/ds/lib/opendj.jar) to constructor sun.security.tools.keytool.CertAndKeyGen(java.lang.String,java.lang.String)
    WARNING: Please consider reporting this to the maintainers of org.opends.server.util.Platform$PlatformIMPL
    WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
    WARNING: All illegal access operations will be denied in a future release
    
  • IDM:
    WARNING: An illegal reflective access operation has occurred
    WARNING: Illegal reflective access by org.apache.felix.framework.ext.ClassPathExtenderFactory$DefaultClassLoaderExtender (file:/path/to/idm/bin/felix.jar) to method java.net.URLClassLoader.addURL(java.net.URL)
    WARNING: Please consider reporting this to the maintainers of org.apache.felix.framework.ext.ClassPathExtenderFactory$DefaultClassLoaderExtender
    WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
    WARNING: All illegal access operations will be denied in a future release
    

Recent Changes

Upgraded to Java 11.

Installed AM 6.5.x, DS 6.5.x, IDM 6.5.x or IG 6.5.x with Java 11.

Installed Java Agent 5.6.x with Java 11.

Causes

These warnings occur when using Groovy with Java 11. For reference, these known issues are:

Whenever you use functionality that accesses Groovy scripting, you will see these warnings.  

Additionally, there is a similar compatibility issue with Felix: FELIX-5765 (An illegal reflective access operation has occurred).

Solution

These messages can be safely ignored because they do not impact the use or functionality of ForgeRock products. However, if you do not want to see them, you can downgrade Java to JDK 1.8 or whitelist these warnings.

See Also

SSLHandshakeException or ClassCastException when using an HSM and Java 11 with ForgeRock products

Federation related pages do not display in the console with a java.lang.NoClassDefFoundError: sun/misc/CharacterEncoder error in AM 6.5.x

How do I disable TLS 1.3 when running DS 6.5 with Java 11?

Cannot install or use ssoadm in AM 5.x, 6.0.0.x, 6.5.0, 6.5.0.1 and OpenAM 13.x after restricting configuration store (DS/OpenDJ) cipher suites or Java upgrade

AM 5.x and 6.0.0.x, IDM 6.x and Rest2LDAP cannot connect to DS 5.x or 6 after restricting DS cipher suites or Java upgrade

Related Training

N/A

Related Issue Tracker IDs

OPENAM-14478 (AM on JDK11 shows warning when Groovy access with "Illegal reflective access by org.codehaus.groovy.vmplugin.v7.Java7$1")

OPENIDM-11765 (Warnings on startup when using embedded DS repo with Java 11)

OPENDJ-5664 (JDK 11: illegal reflective access warning during import-ldif)

OPENDJ-5663 (JDK 11: illegal reflective access warning on setup (without profile))

OPENDJ-5660 (JDK 11: illegal reflective access warning on setup (with profile))

AMAGENTS-2616 (Java agent installer makes warning messages when JDK 11 is used)


SSLHandshakeException or ClassCastException when using an HSM and Java 11 with ForgeRock products

The purpose of this article is to provide assistance if you encounter an SSLHandshakeException or ClassCastException when using a hardware security module (HSM) via the PKCS11 module with Java® 11. This issue affects all ForgeRock products that are compatible with Java 11 (AM, DS, IDM and IG 6.5 and later).

Symptoms

In DS/OpenDJ, you will see the following in the logs:

Unable to connect to the server: 91 (Connect Error) Additional Information: The LDAP connection has failed because an error occurred during the SSL handshake: java.io.EOFException

If you enable SSL debug logging, you will see one of the following errors depending on whether you are using TLS 1.3 or storing EC keys:

  • Using TLS 1.3 with Java 11:
    javax.net.ssl.SSLHandshakeException: Cannot produce CertificateVerify signature 
       at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:128) 
       at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:321) 
       at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:264) 
       at java.base/sun.security.ssl.CertificateVerify$T13CertificateVerifyMessage.<init>(CertificateVerify.java:905) 
       at java.base/sun.security.ssl.CertificateVerify$T13CertificateVerifyProducer.onProduceCertificateVerify(CertificateVerify.java:1077)
       at java.base/sun.security.ssl.CertificateVerify$T13CertificateVerifyProducer.produce(CertificateVerify.java:1070) 
       at java.base/sun.security.ssl.SSLHandshake.produce(SSLHandshake.java:436) 
       at java.base/sun.security.ssl.ClientHello$T13ClientHelloConsumer.goServerHello(ClientHello.java:1224) 
       at java.base/sun.security.ssl.ClientHello$T13ClientHelloConsumer.consume(ClientHello.java:1160) 
       at java.base/sun.security.ssl.ClientHello$ClientHelloConsumer.onClientHello(ClientHello.java:849) 
       at java.base/sun.security.ssl.ClientHello$ClientHelloConsumer.consume(ClientHello.java:810) 
       at java.base/sun.security.ssl.SSLHandshake.consume(SSLHandshake.java:392) 
       at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:444) 
       at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:421) 
       at java.base/sun.security.ssl.TransportContext.dispatch(TransportContext.java:178) 
       at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:164) 
       at java.base/sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1152) 
       at java.base/sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1063) 
       at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:402) 
       at TLSServer$ServerThread.run(TLSServer.java:92) 
    Caused by: java.security.InvalidKeyException: No installed provider supports this key: sun.security.pkcs11.P11Key$P11PrivateKey 
       at java.base/java.security.Signature$Delegate.chooseProvider(Signature.java:1163) 
       at java.base/java.security.Signature$Delegate.engineInitSign(Signature.java:1204) 
       at java.base/java.security.Signature.initSign(Signature.java:546) 
       at java.base/sun.security.ssl.SignatureScheme.getSignature(SignatureScheme.java:473) 
       at java.base/sun.security.ssl.CertificateVerify$T13CertificateVerifyMessage.<init>(CertificateVerify.java:895) 
    
  • Storing EC keys in the PKCS11 module and using Java 11:
    java.lang.ClassCastException: class sun.security.pkcs11.P11Key$P11PrivateKey cannot be cast to class java.security.interfaces.ECPrivateKey (sun.security.pkcs11.P11Key$P11PrivateKey is in module jdk.crypto.cryptoki of loader 'platform'; java.security.interfaces.ECPrivateKey is in module java.base of loader 'bootstrap') 
       at java.base/sun.security.ssl.SignatureScheme.getPreferableAlgorithm(SignatureScheme.java:436) 
       at java.base/sun.security.ssl.CertificateVerify$T13CertificateVerifyMessage.<init>(CertificateVerify.java:867) 
       at java.base/sun.security.ssl.CertificateVerify$T13CertificateVerifyProducer.onProduceCertificateVerify(CertificateVerify.java:1077)
       at java.base/sun.security.ssl.CertificateVerify$T13CertificateVerifyProducer.produce(CertificateVerify.java:1070) 
       at java.base/sun.security.ssl.SSLHandshake.produce(SSLHandshake.java:436) 
       at java.base/sun.security.ssl.ClientHello$T13ClientHelloConsumer.goServerHello(ClientHello.java:1224) 
       at java.base/sun.security.ssl.ClientHello$T13ClientHelloConsumer.consume(ClientHello.java:1160) 
       at java.base/sun.security.ssl.ClientHello$ClientHelloConsumer.onClientHello(ClientHello.java:849) 
       at java.base/sun.security.ssl.ClientHello$ClientHelloConsumer.consume(ClientHello.java:810) 
    

You can enable SSL debugging as indicated in the following articles depending on your product:

Recent Changes

Upgraded to Java 11.

Implemented an HSM via the PKCS11 module and kept the default protocol (TLS 1.3 is the default protocol used for a PKCS11 HSM).

Used EC keys stored in PKCS11.

Causes

There are two JDK bugs that are causing these issues:

These errors are a result of bugs in the JDK rather than being issues with ForgeRock products.

Solution

Until the JDK bugs are fixed, you can workaround these issues as follows:

  • SSLHandshakeException error - you can either use TLS 1.2 or you can downgrade Java to JDK 1.8.
  • ClassCastException error - the only workaround for this issue is to downgrade Java to JDK 1.8.

See Also

Security Guide › Using a Hardware Security Module

Integrator's Guide › Configuring IDM For a Hardware Security Module (HSM) Device

How do I configure AM/OpenAM (All versions) to use a Hardware Security Module (HSM) for signing SAML assertions?

Federation related pages do not display in the console with a java.lang.NoClassDefFoundError: sun/misc/CharacterEncoder error in AM 6.5.x

Related Training

N/A

Related Issue Tracker IDs

OPENDJ-5761 (java.security.InvalidKeyException during SSL Handshake with keys in SoftHSM)


Patches


How do I check what patches are installed for ForgeRock products?

The purpose of this article is to provide details for checking what patches are installed for AM/OpenAM, DS/OpenDJ, IDM/OpenIDM and IG/OpenIG.

Overview

This article provides details for checking what patches are installed by product:

You can also use the patchinfo utility in AM/OpenAM and IG/OpenIG as detailed in How do I use the patchinfo utility to check what patches are installed for AM/OpenAM (All versions) or IG/OpenIG (All versions)? 

Checking for patches in AM/OpenAM

Providing you have unzipped your patches directly in the openam directory as recommended, you can check what patches are installed as follows:

$ cd /path/to/tomcat/webapps/openam/WEB-INF
$ ls README.*

README.1.12345    README.201608

Where each README represents a set of installed patches. READMEs are named to indicate either the ticket number where the patch was given (README.1.12345) or the security advisory ID (README.201608).

Embedded DS/OpenDJ

You can check what patches are installed using the status -V command as follows:

$ cd $HOME/[am_instance]/opends/bin
$ ./status -V

Wed Nov 29 11:27:09 MST 2017
ForgeRock Directory Services 5.5.0+OPENDJ-1234,OPENDJ-5678
Build 20171019141329

Any installed patches will be listed after the product name and version as an issue tracker ID (JIRA).

Checking for patches in Policy Agents

You can check the debug log to see what patch version you have installed, for example:

######################################################
 # OpenAM Web Agent                                   #
 # Version: 4.1.0-27                                  #
 # Revision: 39e5be3                                  #
 # Container: IIS 7.5, 8.x WINNT 32/64bit/WINNT       #
 # Build date: Nov  2 2017 13:42:43                   #
 ######################################################

For Web policy agents 4.x, you can also check the version using the agentadmin --v command as follows:

$ ./agentadmin --v

OpenAM Web Agent for Apache Server 2.2.x 64bit 
Version: 4.1.0-25 
Revision: 42ff535 
Build machine: delacroix 
Build date: Sep 15 2017 16:44:11

Checking for patches in DS/OpenDJ

You can check what patches are installed using the status -V command as follows:

$ cd /path/to/ds/bin
$ ./status -V

Wed Nov 29 11:27:09 MST 2017
ForgeRock Directory Services 5.5.0+OPENDJ-1234,OPENDJ-5678
Build 20171019141329

Any installed patches will be listed after the product name and version as an issue tracker ID (JIRA).

Checking for patches in IDM/OpenIDM

You can check what patches are installed using the PS command when running IDM/OpenIDM interactively, for example:

ps
START LEVEL 12
   ID   State         Level  Name
[   0] [Active     ] [    0] System Bundle (4.2.1)
[   1] [Resolved   ] [    1] javax.transaction API v.1.1 (3.1.1)
[   2] [Active     ] [    1] OpenIDM System Bundle (4.5.0)
...
[ 135] [Active     ] [   10] OpenIDM Core Bundle (4.5.0.OPENIDM-1234-5678)
...

Any installed patches will be listed after a product bundle as an issue tracker ID (JIRA). Patches only apply to a bundle (not the whole product), so you will need to check all bundles for patches, focusing on any that start OpenIDM, ForgeRock or OpenICF. You can search for version.JIRA_prefix to easily find the patched bundles, for example:

(4.5.0.OPENIDM
(4.5.0.OPENICF
(4.5.0.CREST

Checking for patches in IG/OpenIG

Providing you have unzipped your patches directly in the top-level IG/OpenIG WAR directory as recommended, you can check what patches are installed as follows:

$ cd /path/to/jetty/webapps/root/WEB-INF
$ ls README.*

README.1.12345    README.201606

Where each README represents a set of installed patches. READMEs are named to indicate either the ticket number where the patch was given (README.1.12345) or the security advisory ID (README.201606).

See Also

How do I install an AM/OpenAM patch (All versions) supplied by ForgeRock support?

FAQ: Patches in AM/OpenAM

How do I install a DS/OpenDJ patch (All versions) supplied by ForgeRock support?

How do I install an IDM/OpenIDM patch (All versions) supplied by ForgeRock support?

How do I install an IG/OpenIG patch (All versions) supplied by ForgeRock support?

Related Training

N/A

Related Issue Tracker IDs

OPENAM-2651 (Formalized patching mechanism)


How do I install an IG/OpenIG patch (All versions) supplied by ForgeRock support?

The purpose of this article is to provide information on installing an IG/OpenIG patch that has been supplied by ForgeRock support.

Installing a patch

Note

You should test the patch in a development or test environment before deploying to production.

You can install an IG/OpenIG patch as follows:

  1. Back up your existing IG/OpenIG WAR file 
  2. Extract the patch zip into the top-level IG/OpenIG WAR directory (for example, ROOT if you are using Apache Tomcat™).
  3. Restart the web application container in which IG/OpenIG runs.

See Also

Maintenance and Patch availability policy

Related Training

N/A

Related Issue Tracker IDs

N/A


Copyright and TrademarksCopyright © 2018 - 2019 ForgeRock, all rights reserved.

This content has been optimized for printing.

Loading...