PingIDM 7.5.0

Secure network connections

This topic explains how to secure incoming connections and ports. As a general precaution in production environments, avoid communication over insecure HTTP.

Use TLS/SSL

Use TLS/SSL to access IDM, ideally with mutual authentication so that only trusted systems can invoke each other. TLS/SSL protects data on the network. Mutual authentication with strong certificates, imported into the truststore and keystore of each application, provides a level of confidence for trusting application access.

Restrict REST access to the HTTPS port

In a production environment, you should restrict REST access to a secure port:

  1. Edit your project’s conf/jetty.xml file:

    Comment out or delete the <Call name="addConnector"> code block that includes the openidm.port.http property.

    Do not delete the <Call name="addConnector"> code blocks that contain the openidm.port.https and openidm.port.mutualauth properties.
  2. Edit resolver/boot.properties :

    • Set the openidm.port.https port number.

    • Set the openidm.port.mutualauth port number.

    • Add the property openidm.https.enabled=true.

Use a certificate to secure REST access over HTTPS. You can use self-signed certificates in a test environment. In production, all certificates should be signed by a certificate authority. The examples in this guide assume a CA-signed certificate named ca-cert.pem.

Protect sensitive REST interface URLs

Anything attached to the router is accessible with the default policy, including the repository. If you do not need such access, deny it in the authorization policy to reduce the attack surface.

In addition, you can deny direct HTTP access to system objects in production, particularly access to action. As a rule of thumb, do not expose anything that is not used in production.

For an example that shows how to protect sensitive URLs, refer to Configure Access Control in access.json.

Enable HTTP Strict-Transport-Security

HTTP Strict-Transport-Security (HSTS) is a web security policy that forces browsers to make secure HTTPS connections to specified web applications. HSTS can protect websites against passive eavesdropper and active man-in-the-middle attacks.

IDM provides an HSTS configuration, but it is disabled by default. To enable HSTS, locate the following excerpt in your conf/jetty.xml file:

<New id="tlsHttpConfig" class="org.eclipse.jetty.server.HttpConfiguration">
    ...
    <Call name="addCustomizer">
        <Arg>
            <New class="org.eclipse.jetty.server.SecureRequestCustomizer">
                <!-- Enable SNI Host Check when true -->
                <Arg name="sniHostCheck" type="boolean">true</Arg>
                <!-- Enable Strict-Transport-Security header and define max-age when >= 0 seconds -->
                <Arg name="stsMaxAgeSeconds" type="long">-1</Arg>
                <!-- If enabled, add includeSubDomains to Strict-Transport-Security header when true -->
                <Arg name="stsIncludeSubdomains" type="boolean">false</Arg>
            </New>
        </Arg>
    </Call>
...

Set the following arguments:

stsMaxAgeSeconds

This parameter sets the length of time, in seconds, that the browser should remember that a site can only be accessed using HTTPS.

For example, the following setting applies the HSTS policy and remains in effect for an hour:

<Arg name="stsMaxAgeSeconds" type="long">3600</Arg>
stsIncludeSubdomains

If this parameter is true, the HSTS policy is applied to the domain of the issuing host as well as its subdomains:

<Arg name="stsIncludeSubdomains" type="boolean">true</Arg>

For more information about HSTS, click here.

Restrict the HTTP payload size

Restricting the size of HTTP payloads can protect the server against large payload HTTP DDoS attacks. IDM includes a servlet filter that limits the size of an incoming HTTP request payload, and returns a 413 Request Entity Too Large response when the maximum payload size is exceeded.

By default, the maximum payload size is 5MB. You can configure the maximum size in your project’s conf/servletfilter-payload.json file. That file has the following structure by default:

{
    "classPathURLs" : [ ],
    "systemProperties" : { },
    "requestAttributes" : { },
    "scriptExtensions" : { },
    "initParams" : {
        "maxRequestSizeInMegabytes" : 5
    },
    "urlPatterns" : [
        "/*"
    ],
    "filterClass" : "org.forgerock.openidm.jetty.LargePayloadServletFilter"
}

Change the value of the maxRequestSizeInMegabytes property to set a different maximum HTTP payload size.

The remaining properties in this file are described in Register Additional Servlet Filters.

Deploy securely behind a load balancer

IDM prevents URL-hijacking, with the following code block in the conf/jetty.xml file:

<Call name="addCustomizer">
  <Arg>
    <New class="org.eclipse.jetty.server.SecureRequestCustomizer">
      <!-- Enable SNI Host Check when true -->
      <Arg name="sniHostCheck" type="boolean">true</Arg>
      <!-- Enable Strict-Transport-Security header and define max-age when >= 0 seconds -->
      <Arg name="stsMaxAgeSeconds" type="long">-1</Arg>
      <!-- If enabled, add includeSubDomains to Strict-Transport-Security header when true -->
      <Arg name="stsIncludeSubdomains" type="boolean">false</Arg>
    </New>
  </Arg>
</Call>

If you are deploying IDM behind a system such as a load balancer, firewall, or a reverse proxy, you must uncomment the next section in jetty.xml , so that Jetty honors X-Forwarded-Host headers:

 <Call name="addCustomizer">
    <Arg>
        <New class="org.eclipse.jetty.server.ForwardedRequestCustomizer">
            <Set name="forcedHost">
                <Call class="org.forgerock.openidm.jetty.Param" name="getProperty">
                    <Arg>openidm.host</Arg>
                </Call>:<Call class="org.forgerock.openidm.jetty.Param" name="getProperty">
                    <Arg>openidm.port.https</Arg>
                </Call>
            </Set>
        </New>
    </Arg>
</Call>

Connect to IDM through a proxy server

  1. Add the following JVM parameters to the value of OPENIDM_OPTS in your startup script (startup.sh or startup.bat ):

    -Dhttps.proxyHost

    Hostname or IP address of the proxy server; for example, proxy.example.com or 192.168.0.1.

    -Dhttps.proxyPort

    Port number used by IDM; for example, 8443 or 9443.

    Example
    # Only set OPENIDM_OPTS if not already set
    [ -z "$OPENIDM_OPTS" ] && OPENIDM_OPTS="-Xmx2048m -Xms2048m -Dhttps.proxyHost=localhost -Dhttps.proxyPort=8443"
  2. Enable the ForwardedRequestCustomizer class so that Jetty honors X-Forwarded- headers.

    To enable the class, uncomment the following excerpt in your conf/jetty.xml file:

    <Call name="addCustomizer">
        <Arg>
            <New class="org.eclipse.jetty.server.ForwardedRequestCustomizer">
                <Set name="forcedHost">
                    <Call class="org.forgerock.openidm.jetty.Param" name="getProperty">
                        <Arg>openidm.host</Arg>
                    </Call>:
                    <Call class="org.forgerock.openidm.jetty.Param" name="getProperty">
                        <Arg>openidm.port.https</Arg>
                    </Call>
                </Set>
            </New>
        </Arg>
    </Call>

    For more information on this class, refer to the Jetty documentation.

Protect against Cross-Site Request Forgery

IDM provides a filter to protect against Cross-Site Request Forgery (CSRF). The filter is disabled by default. To enable it, set the following property in resolver/boot.properties:

openidm.csrfFilter.enabled=true

The filter requires the client to send a CSRF cookie (X-CSRF-Token) on every request. By default, this cookie is the JWT session cookie (session-jwt), obtained on authentication. If your client uses a different cookie for authentication, set the name of that cookie in the following property in resolver/boot.properties:

openidm.csrfFilter.authCookieName=session-jwt

If there are HTTP request paths that the CSRF filter should always allow, set these paths as comma-separated values of the openidm.csrfFilter.pathWhitelistCSV property in resolver/boot.properties. For example:

openidm.csrfFilter.pathWhitelistCSV=/openidm/example,/openidm/my-project