The Forgerock Java Remote Connector Server (RCS) can be deployed within a Docker container.
Contents
- RCS Parent Image
- Customizing the Parent RCS Image
- Pushing RCS Image to a Docker Repository
- Registering RCS
- Configuring RCS
- Running RCS
- Developing Scripted Connectors with Docker
RCS Parent Image
Currently, RCS images could be pulled from the gcr.io/forgerock-io/rcs image repository in the public ForgeRock Container Registry (you will need a Google account to see it in a browser).
A public RCS image provides the default installation of the ForgeRock Open Identity Connector Framework (ICF).
Customizing the Parent RCS Image
If you need to extend the parent image functionality, you can customize it by copying additional files to the ICF installation folder in the final image, which is located at /opt/openicf
. The additional files could include complete connector packages, scripts, drivers, etc.
The easiest and the most readable way to capture your RCS image customizations is to save them in a custom docker image using a custom Dockerfile.
For example:
# 1. Accept build arguments in the FROM instruction.
# @example
ARG FROM_TAG=1.5.20.15
FROM gcr.io/forgerock-io/rcs:$FROM_TAG
# 2. Merge your custom files with the RCS installation.
# @example
COPY openicf/conf conf
COPY openicf/connectors connectors
COPY openicf/lib lib
COPY openicf/scripts scripts
# 3. Use root user for operations that escalate permissions.
# @example
# USER root
# 4. Add untrusted public TLS certificate(s) to RCS' `truststore` to allow for communications with unrecognized hosts.
# Run `docker build` with the `--progress plain` option to check the outcome of the RUN instruction.
# @example
# COPY openicf/security/BadSSL-Untrusted-Root-Certificate-Authority.cer /opt/openicf/security
# RUN keytool -keystore $JAVA_HOME/lib/security/cacerts -storepass changeit -trustcacerts -import -file /opt/openicf/security/BadSSL-Untrusted-Root-Certificate-Authority.cer -alias badssl-com-untrusted-root-ca -noprompt
# 5. Switch back to a non-root user.
# @example
# USER 11111
-
During the docker build phase, you can use the –build-arg flag, where you can specify the parent image tag against which you want to build your RCS image. Doing so will allow to choose a particular version of the parent image available at the gcr.io/forgerock-io/rcs repository.
For example:
docker build --build-arg FROM_TAG=1.5.20.15 -t rcs .
-
You can copy your local files into the
/opt/openicf
location in the parent RCS image to extend and/or modify its functionality. You can replicate theopenicf
installation folder structure locally and copy everything at once, or use separateCOPY
instructions for individual folders and files, doing which could help with caching respective layers in the final image.NOTE that the RCS parent image Dockerfile specifies a working directory:
[ . . . ] WORKDIR /opt/openicf [ . . . ]
This means that in the
COPY
instruction destination, you need to use an absolute path or a path relative to theWORKDIR
location.-
openicf/conf
Provide your custom version of the
openicf/conf/ConnectorServer.properties
file, in which you can specify all or some of the RCS configuration properties as described in the Configure a remote connector server RCS doc. -
openicf/connectors
Add your custom/downloaded connectors packaged in JAR files into this sub-folder.
-
openicf/lib
-
Add any additional JARs used by your connectors into this sub-folder.
For example, you can supply database driver(s) that your connectors use.
-
Provide your customized version of the
openicf/lib/framework/logback.xml
file to overwrite the default one; and thus, adjust the detail of the logs produced by the RCS, as described in the Connector development > Connector troubleshooting doc and in the How do I enable debug logging and log rotation for the Java Remote Connector Server (RCS)? Knowledge Base article.The resulting log files could be found in a running container under the
/opt/openicf/logs
folder, will be printed out in the standard output by the container in the (default) attached mode, or could be explicitly requested from the container with the docker logs command.
-
-
openicf/scripts
Add Groovy scripts used by your scripted connectors to this folder.
-
-
By default, a Docker container runs as a root user.
It is generally recommended to run a Docker container as a non-root user, which is addressed in the RCS parent image Dockerfile:
[ . . . ] USER 11111 [ . . . ]
For some instructions, however, you might need elevated permissions. For example, for adding an untrusted certificate to the Java truststore, you will need the root user privileges.
-
You can copy any other content that your connectors might use to any other accessible location within the connector server image.
In the provided example, a public certificate is added to the Java
truststore
to allow for RCS communications with an otherwise untrusted host; for example, a third-party API. The destination of theCOPY
instruction in this case could be any accessible location within the image, because the change is not applied by the ICF, but with a command provided in theRUN
instruction.Currently, RCS does not have its own
truststore
, and by default is using its Java Virtual Machine (JVM)truststore
.The Identity Cloud certificates are signed by a trusted CA and do NOT need to be added to the
truststore
. -
After any specific instructions that require elevated permissions have been performed, you should switch back to the non-root user using the USER instruction.
During the development phase, you might choose to continue as a root user. For example, root user privileges are required for enabling file sync when using a Docker image in the Skaffold dev mode.
In this case, you can specify the user in the docker run command with the –user , -u flag.
Pushing RCS Image to a Docker Repository
To share your RCS image and make it available for orchestration tools, you can push it to a Docker repository.
If your Docker repository is served from a private Docker registry, make sure you have configured Docker to have appropriate privileges to push to this repository. Your Docker registry provider can provide specific instructions on setting up authentication for Docker.
For example, Set up authentication for Docker describes how to use gcloud credential helper for configuring Docker with the Google Cloud CLI session credentials, which you can use while developing your RCS images and pushing them to a Google Cloud Artifact Registry.
You will need to tag your image before you push it to a repository. You can also tag your image with the reference to your repository in the docker build command using the -t, --tag flag.
For example:
$ docker build --build-arg FROM_TAG=1.5.20.15 -t gcr.io/<organization>/<username>/rcs .
$ docker push gcr.io/<organization>/<username>/rcs
Registering RCS
You need to configure your RCS in client mode in order to be able to connect it to a managed environment such as ForgeRock Identity Cloud (Identity Cloud).
In the client mode, you must provide the connectorserver.connectorServerName
property in your RCS configuration, which must match the name under which your connector server is registered in IDM.
In Identity Cloud, you can register a connector server using the ForgeRock Identity Platform (Platform) admin UI, as described in the Sync identities with an external resource > Register a remote server doc. In the UI, the Name
input for a connector server accepts a ^[a-z0-9_-]+$
value, which can then be used in the connectorServerName
property in your connector server configuration.
Eventually, the
Name
value is saved as thename
property of aremoteConnectorClients
entry in theprovisioner.openicf.connectorinfoprovider.json
file in IDM.
Configuring RCS
To configure your RCS in the client mode, you will need to define the following RCS configuration properties:
connectorserver.url
connectorserver.connectorServerName
In order to connect to an Identity Cloud tenant, you will also need to specify the following:
connectorserver.tokenEndpoint
connectorserver.clientId
connectorserver.clientSecret
connectorserver.scope
To enable more controlled debug output, you should also specify the RCS logger class:
connectorserver.loggerClass
The static connector server properties could be provided via instructions included in the openicf/conf/ConnectorServer.properties
file.
As an example, a ConnectorServer.properties
file could contain the following instructions for setting the properties that are not likely to change and carry no sensitive data; hence, could be embedded into the image:
openicf/conf/ConnectorServer.properties
# Set connectorserver properties.
# @see {@link https://backstage.forgerock.com/docs/openicf/latest/connector-reference/configure-server.html#rcs-properties}
# Set static properties.
connectorserver.scope=fr:idm:*
connectorserver.loggerClass=org.forgerock.openicf.common.logging.slf4j.SLF4JLog
To provide dynamic values in the connector server configuration, which could be the preferred approach for secrets and environment specifics, you can define JVM’s system properties via the OPENICF_OPTS
environment variable, which needs to be exported into the JVM’s environment before the connector server starts. This information should be provided at the time when the container runs, so that it is not embedded into the image.
Running RCS
You can create an RCS container and run it with the docker run command.
In a standalone Docker container, environment variables can be set with one of the -e, --env, --env-file flags.
For example:
.env file
OPENICF_OPTS=-Dconnectorserver.url=wss://openam-dx-kl04.forgeblocks.com/openicf/0 -Dconnectorserver.tokenEndpoint=https://openam-dx-kl04.forgeblocks.com/am/oauth2/realms/root/realms/alpha/access_token -Dconnectorserver.connectorServerName=rcs-docker-1 -Dconnectorserver.clientId=RCSClient -Dconnectorserver.clientSecret=YA...H?
$ docker run --env-file .env rcs
A Docker environment file is limited to one-line variable definitions and might not be easy to read. An alternative approach could be defining the environment variable on the host machine and then using the
-e, --env
flag.For example:
.env
OPENICF_OPTS="-Dconnectorserver.url=wss://openam-dx-kl04.forgeblocks.com/openicf/0 \ -Dconnectorserver.tokenEndpoint=https://openam-dx-kl04.forgeblocks.com/am/oauth2/realms/root/realms/alpha/access_token \ -Dconnectorserver.connectorServerName=rcs-docker-1 \ -Dconnectorserver.clientId=RCSClient \ -Dconnectorserver.clientSecret=YA...H?"
$ set -a; source .env; set +a; $ docker run -e OPENICF_OPTS rcs
This way, the sensitive and dynamic properties will not have to be embedded into the image.
In turn, every value used in the OPENICF_OPTS
variable could be substituted dynamically to address different environments and/or different connector server names registered in IDM. For example, you might be interested in running multiple containers referring to different connector server names registered in a server cluster.
Developing Scripted Connectors with Docker
The parent RCS image does not ship with any (Groovy) scripts. This means that while developing scripted connectors, you can use docker run (-v, --volume) flag as a convenient way of dynamically providing content of your scripts to the running RCS container.
For example:
docker run --rm --env-file .env -v ./openicf/scripts:/opt/openicf/scripts rcs
Now, any updates to the scripts made in the ./openicf/scripts
folder on the host machine will become immediately available to the RCS running in the container.
While developing your scripts, you can also benefit from attaching a debugger to your RCS process, as described in the Attaching Debugger to RCS within Docker Container chapter of a developing scripted connectors article on the ForgeRock Community site.