Using Elytron Credential Stores in WildFly

The elytron subsystem allows using Credential Stores as secure storage for your credentials. Using a credential store is a replacement of the standard password vault mechanism to store passwords and other sensitive strings. Credential stores allow for easier credential management within WildFly, without having to use an external tool. It is however still possible to use an external script named elytron-tool.sh to manage entirely from the shell the storage of your passwords.

The default credential store implementation uses a Java Cryptography Extension (JCEKS) keystore file to store credentials. When creating a new credential store, the default implementation also allows you to reference an existing keystore file or have WildFly automatically create one for you. Currently, the default implementation only allows you to store clear text passwords.

Example: Securing your Datasource password

In this example, we will show how to secure the password used to connect a sample MySql datasource. First of all, we will start a MySql instance, for the sake of simplicity we will just start it with Docker:

$ docker run -d --name mysql -e MYSQL_USER=mysql -e MYSQL_PASSWORD=secret -e MYSQL_DATABASE=demodb -e MYSQL_ROOT_PASSWORD=s3cr3t mysql

Next, we will create a Credential Store. This can be done either using a shell script (elytron-tool.sh) or enterely with WildFly CLI:

/subsystem=elytron/credential-store=my_store:add(location="credentials/csstore.jceks", relative-to=jboss.server.data.dir,  credential-reference={clear-text=mypassword},create=true)

The above command has created a Credential Store named “csstore.jceks” in the “jboss.server.data.dir/credentials” using a clear text password named “mypassword”.

Then, we will add an alias into the credential store to reference the password (“secret”) of mysql user:

/subsystem=elytron/credential-store=my_store:add-alias(alias=database-pw, secret-value="secret")

Let’s check that our alias has been correctly included:

/subsystem=elytron/credential-store=my_store:read-aliases
{
    "outcome" => "success",
    "result" => ["database-pw"]
}

Perfect. Now just create a datasource without specifying the “password” as datasource’s property but rather include a “credential-reference” which points to your alias:

data-source add --name=mysqlDS --jndi-name=java:/MySQLDS --driver-name=mysql-connector-java-5.1.15.jar --connection-url=jdbc:mysql://172.17.0.2:3306/demodb --user-name=mysql --credential-reference={store=my_store, alias=database-pw}

Finally, let’s check that our connection with the Database is ok:

/subsystem=datasources/data-source=mysqlDS:test-connection-in-pool()
{
    "outcome" => "success",
    "result" => [true]
}

So we managed to replace correctly the password with a Credential Store reference.

Create and Modify Credential Stores Offline using the Command Line Tool

As we have anticipated, we can use as well the WildFly Elytron tool, which which is available in $JBOSS_HOME/bin, to create and modify a credential store for an offline, or stopped, WildFly server.

Here is, for example, how to create a Credential store using the elytron-tool.sh:

$ elytron-tool.sh credential-store --create --location "../credentials/csstore.jceks" --password mypassword

Once created, then you can start adding entries to your store:

$ elytron-tool.sh credential-store --location "../credentials/csstore.jceks" --password mypassword --add database-pw --secret secret

Using encrypted passwords in your Credential Store

In our example, we have used clear text passwords in our Credential Stores. This is not optimal in any sensitive environment. To encrypt strings stored in your Credential Stores, Elytron uses Resolvers.

Each Resolver references a secret key in a Credential Store which it will use to decrypt the expressions. Encrypted expressions are typically formatted in this way.

ENC::initial-resolver:RUxZAUMQ+bO1tTNnE61Dz1PYSnHZQ8HaWDna6YHQi5KBKPnrXJ4=

Let’s see how to create Resolvers with a practical example.

Firstly, we will define the Credential Store which uses a dynamically Secret Key and stored under the alias key:

/subsystem=elytron/secret-key-credential-store=my_store_secret:add(relative-to=jboss.server.config.dir, path=my_store_secret.cs)

Then, let’s generate the Secret Key:

/subsystem=elytron/secret-key-credential-store=my_store_secret:export-secret-key(alias=key)
{
    "outcome" => "success",
    "result" => {"key" => "RUxZAUukKKN19cxlAng6ae1K8psaSDvoFG24ZHfMWzXZ684flA=="}
}

Next, we can activate support for encrypted expressions by adding a Resolver:

/subsystem=elytron/expression=encryption:add(resolvers=[{name=initial-resolver, credential-store=my_store_secret, secret-key=key}])

Finally, and we can now encrypt a any clear text value. For example to encrypt the “secret” password:

 /subsystem=elytron/expression=encryption:create-expression(resolver=initial-resolver, clear-text=secret)
{
    "outcome" => "success",
    "result" => {"expression" => "${ENC::initial-resolver:RUxZAUMQ+bO1tTNnE61Dz1PYSnHZQ8HaWDna6YHQi5KBKPnrXJ4=}"}
}

The encrypted expression can be used as replacement of clear text passwords in your configuration. Before setting the encrypted password, check that the configuration attribute has the expressions-allowed set to true. For example, for the Datasource’s password:

/subsystem=datasources/data-source=ExampleDS:read-resource-description
. . .
            "password" => {
                "type" => STRING,
                "description" => "Specifies the password used when creating a new connection",
                "expressions-allowed" => true,
                "required" => false,
                "nillable" => true,
                "alternatives" => ["credential-reference"],
                "requires" => ["user-name"],
                "min-length" => 1L,
                "max-length" => 2147483647L,
                "access-constraints" => {"sensitive" => {
                    "credential" => {"type" => "core"},
                    "data-source-security" => {"type" => "datasources"}
                }},

Encrypting data using the Command Line Tool

Once you have added the Secret Key in a Credential Store, the credential-store argument of the elytron-tool can also be used to create encrypted strings. Example:

bin/elytron-tool.sh credential-store --location standalone/configuration/my_store_secret.cs --type PropertiesCredentialStore --encrypt key
Clear text value:
Confirm clear text value:
Clear text encrypted to token 'RUxZAUMQvGzk6Vaadp2cahhZ6rlPhHOZcWyjXALlAthrENvRTvQ=' using alias 'key'

That’s all! enjoy using Credential Stores on WildFly!

Found the article helpful? if so please follow us on Socials