FileSystemSecretStore
Manage a store of secrets held in files in a specified directory. Each file must contain only one secret, in the format
declared in the configuration. Secrets are read lazily from the filesystem, and are cached indefinitely.
Secrets from FileSystemSecretStore never expire.
For a description of how secrets are managed, see About Secrets.
Usage
{ "name": string, "type": "FileSystemSecretStore", "config": { "directory": configuration expression<string>, "format": configuration expression<enumeration>, "suffix": configuration expression<string>, "mappings": [ configuration object, ... ] } }
Properties
"directory"
: configuration expression<string>, requiredFile path to a directory containing secret files. This object checks the specified directory, but not its subdirectories.
"format"
: configuration expression<enumeration>, optionalFormat in which the secret is stored. Use one of the following values:
BASE64
: Base64-encodedPLAIN
: Plain text
Default:
BASE64
"suffix"
: configuration expression<string>, optionalFile suffix.
When set, the FileSystemSecretStore will append that suffix to the secret ID and try to find a file with the mapped name.
Default: None
"mappings"
: array of objects, optionalOne or more mappings to define a secret:
secretId
: configuration expression<secret-id>, requiredThe ID of the secret used in your configuration.
For information about supported formats for
secret-id
, see secret-id.format
: SecretKeyPropertyFormat reference, requiredThe SecretKeyPropertyFormat object that defines the format and algorithm used for the secret.
For more information, see "SecretKeyPropertyFormat". For an example that uses SecretKeyPropertyFormat, see "Packing Data Into a JWT Signed With a Symmetric Key".
Log Level
To facilitate debugging secrets for the FileSystemSecretStore, in logback.xml
add a logger defined by the fully qualified package name of the property resolver. The following line in logback.xml
sets the log level to ALL
:
<logger name="org.forgerock.secrets.propertyresolver" level="ALL">
Example
In the following example, an AmService is configured to communicate WebSocket notifications from AM to IG, using the IG agent in AM. IG uses the FileSystemSecretStore to retrieve the password from a file in the specified directory. When the route is deployed, a WebSocket notification is written to the IG log.
Before you start this tutorial:
Prepare IG as described in Getting Started Guide.
Install and configure AM on http://openam.example.com:8088/openam, with the default configuration. If you use a different configuration, substitute in the tutorial accordingly.
Set up AM:
(For AM 6.5.x and earlier versions) Select Identities > demo, and set the demo user password to
Ch4ng31t
.(For AM 6.5.3 and later versions) Select Services > Add a Service, and add a Validation Service with the following Valid goto URL Resources:
http://openig.example.com:8080/*
http://openig.example.com:8080/*?*
Select Applications > Agents > Identity Gateway, add an agent with the following values:
Agent ID:
ig_agent
Password:
password
Leave all other values as default.
For AM 6.5.x and earlier versions, set up an agent as described in "Set Up an IG Agent in AM 6.5 and Earlier".
Select Applications > Agents > Java (or J2EE).
Add an agent with the following values:
Agent ID:
ig_agent
Agent URL:
http://openig.example.com:8080/agentapp
Server URL:
http://openam.example.com:8088/openam
Password:
password
On the Global tab, deselect Agent Configuration Change Notification.
This option stops IG from being notified about agent configuration changes in AM, because they are not required by IG.
Set up IG:
Add a file called
agent.secret.id
to the secret store directory, and add the IG agent password to the file:$
echo cGFzc3dvcmQ= > /path/to/secrets/agent.secret.id
The value is the base64-encoded value of
password
, which is the password of the IG agent.Add the following route to IG, to serve .css and other static resources for the sample application:
$HOME/.openig/config/routes/static-resources.json
%appdata%\OpenIG\config\routes\static-resources.json
{ "name" : "sampleapp_resources", "baseURI" : "http://app.example.com:8081", "condition": "${matches(request.uri.path,'^/css')}", "handler": "ReverseProxyHandler" }
Add the following route to IG:
$HOME/.openig/config/routes/filesystemsecret.json
%appdata%\OpenIG\config\routes\filesystemsecret.json
{ "heap":[ { "name": "FileSystemSecretStore-1", "type": "FileSystemSecretStore", "config": { "format": "BASE64", "directory": "/path/to/secrets" } }, { "name": "AmService-1", "type": "AmService", "config": { "url": "http://openam.example.com:8088/openam", "agent": { "username": "ig_agent", "passwordSecretId": "agent.secret.id" }, "secretsProvider": "FileSystemSecretStore-1", "version": "7", "notifications": { "enabled": true } } } ], "handler": { "type": "Chain", "config": { "filters": [ { "type": "SingleSignOnFilter", "config": { "amService": "AmService-1" } } ], "handler": "ReverseProxyHandler" } }, "condition": "${matches(request.uri.path, '/home/filesystemsecret')}", "baseURI": "http://app.example.com:8081" }
Notice the following features of the route:
The route matches requests to
/filesystemsecret
.The agent password for AmService is provided by the FileSystemSecretStore in the heap.
The SingleSignOnFilter manages redirects to AM for authentication, using the IG agent in
AmService-1
.
Test the setup:
If you are logged in to AM, log out.
Go to http://openig.example.com:8080/home/filesystemsecret.
The SingleSignOnFilter redirects the request to AM for authentication.
Log in to AM as user
demo
, passwordCh4ng31t
.When you have authenticated, the SingleSignOnFilter passes the request to the sample app, which returns the profile page.
In the following example, the FileSystemSecretStore is configured to look for suffixed secrets in a secrets/
directory.
{ "directory": "&{my.instance.dir}/secrets", "suffix": ".base64", "format": "BASE64" }
Given that the directory contains both keystore.pass
and keystore.pass.base64
, when the keystore.pass
secret is trying to be resolved, the secret stored in keystore.pass.base64
will be returned.