Throughout this post, we’re going to look at how AWS Secrets (other secret stores can be used) are pulled into Kubernetes as secrets there and then used within a ForgeRock AM authentication tree. A use case for this is when part of the ForgeRock AM authentication tree needs to communicate with an API. The API requires an API key which isn't stored in ForgeRock, the API keys are secured in AWS Secrets Manager. Use Kubernetes External Secrets to pull the secrets from AWS into the Kubernetes cluster.
At the time of writing ForgeRock AM version 7.0 doesn't support referencing environment variables from scripted decision nodes, therefore a custom Java node is required to retrieve the secret and store it in the shared state of the authentication tree. The secret can then be used by a scripted decision node to set the API key in a request header and call the API.
It is possible to call System.getenv() in a scripted decision node but the java.lang.System class will require whitelisting which will open the possibility of the script writer using System.exit(int) which would terminate the JVM. Therefore, it is not an ideal solution.
In ForgeRock AM 7.1, it will be possible to reference Kubernetes secrets from within scripted decision nodes using the ‘secrets’ binding as follows:
A different option to look at on the secret management side is the ForgeRock Secret Agent which can be used to manage different types of secrets and back them up in the cloud.
The following steps are concerned with setting up Kubernetes External Secrets to pull in AWS Secrets and how they can be used as environment variables within ForgeRock AM (7.0) nodes.
For ForgeRock to pick this secret up it needs to be referenced in the deployment.yaml for AM, this is located under <path-to-forgeops>/kustomize/base/am. Under spec.template.spec.containers.env in the YAML you can add the environment variable and reference the secret.
Create a custom node in a small maven project. The process method below is executed when the tree reaches the custom node, it retrieves the environment variable. It makes a copy of the sharedState and adds the environment variable value to the sharedState. The method then tells ForgeRock to go to the next node replacing the sharedState with the new one from this method.
The environment variable is retrieved using the sharedState.get() function, a request is then constructed setting the API key as one of the headers, the request is then sent and the response is logged.
The next step is to configure the tree where these nodes are going to be used, go to realms/<selected-realms>/authentication/trees and either create a new tree or select an existing one to amend.
The custom node and “Scripted Decision” nodes can be dragged onto the tree. Edit the "Scripted Decision" node, select the script created earlier in the dropdown menu. Add the outcomes of the script, usually true and false but there can be other outcomes. Adjust the nodes outgoing points to the relevant nodes and save the tree.
To test the tree, go to the URL for the tree - the registration one I used for example was <domain>/am/XUI/ realm=/&authIndexType=service&authIndexValue=Registration
Follow the node executions in the AM pod logs, it should also highlight any errors with the code.
With a successful tree execution the cloud secrets have been used within ForgeRock enabling APIs to be called as part of an authentication tree.