Chapter 2. Providing an initial key to JBoss EAP to unlock secured resources

2.1. Encrypted expressions in Elytron

To maintain the secrecy of your sensitive strings, you can use encrypted expressions instead of the sensitive strings in the server configuration file.

An encrypted expression is one that results from encrypting a string with a SecretKeyCredential, then combining it with its encoding prefix and resolver name. The encoding prefix tells Elytron that the expression is an encrypted expression. The resolver maps the encrypted expression to its corresponding SecretKeyCredential in a credential store.

The expression=encryption resource in Elytron uses an encrypted expression to decode the encrypted string inside it at run time. By using an encrypted expression instead of the sensitive string itself in the configuration file, you protect the secrecy of the string. An encrypted expression takes the following format:

Syntax when using a specific resolver

${ENC::RESOLVER_NAME:ENCRYPTED_STRING}

ENC is the prefix that denotes an encrypted expression.

RESOLVER_NAME is the resolver Elytron uses to decrypt the encrypted string.

Example

${ENC::initialresolver:RUxZAUMQE+L5zx9LmCRLyh5fjdfl1WM7lhfthKjeoEU+x+RMi6s=}

If you create an encrypted expression with a default resolver, it looks like this:

Syntax when using the default resolver

${ENC::ENCRYPTED_STRING}

Example

${ENC::RUxZAUMQE+L5zx9LmCRLyh5fjdfl1WM7lhfthKjeoEU+x+RMi6s=}

In this case, Elytron uses the default resolver you defined in the expression=encryption resource to decrypt an expression. You can use an encrypted expression on any resource attribute that supports it. To find out whether an attribute supports encrypted expression, use the read-resource-description operation, for example:

Example read-resource-description on mail/mail-session

/subsystem=mail/mail-session=*/:read-resource-description(recursive=true,access-control=none)
{
  "outcome"=>"success",
  "result"=>[{
  ...
    "from"=>{
      ...
      "expression-allowed"=>true,
      ...
   }]
}

In this example, the attribute from supports encrypted expressions. This means that you can hide your email address in the from field by encrypting it and then using the encrypted expression instead.

2.2. Creating an encrypted expression in Elytron

Create an encrypted expression from a sensitive string and a SecretKeyCredential. Use this encrypted expression instead of the sensitive string in the management model - the server configuration file, to maintain the secrecy of the sensitive string.

Prerequisites

Procedure

  1. Create a resolver that references the alias of an existing SecretKeyCredential in a credential store using the following management CLI command:

    Syntax

    /subsystem=elytron/expression=encryption:add(resolvers=[{name=<name_of_the_resolver>, credential-store=<name_of_credential_store>, secret-key=<secret_key_alias>}])

    Example

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

    If an error message about a duplicate resource displays, use the list-add operation instead of add, as follows:

    Syntax

    /subsystem=elytron/expression=encryption:list-add(name=resolvers, value={name=<name_of_the_resolver>, credential-store=<name_of_credential_store>, secret-key=<secret_key_alias>})

    Example

    /subsystem=elytron/expression=encryption:list-add(name=resolvers,value={name=exampleResolver, credential-store=examplePropertiesCredentialStore, secret-key=key})
    {
        "outcome" => "success",
        "response-headers" => {
            "operation-requires-reload" => true,
            "process-state" => "reload-required"
        }
    }

  2. Reload the server.

    reload
  3. Disable caching of commands in the management CLI:

    Important

    If you do not disable caching, the secret key is visible to anyone who can access the management CLI history file.

    history --disable
  4. Create an encrypted expression using the following management CLI command:

    Syntax

    /subsystem=elytron/expression=encryption:create-expression(resolver=<existing_resolver>, clear-text=<sensitive_string_to_protect>)

    Example

    /subsystem=elytron/expression=encryption:create-expression(resolver=exampleResolver, clear-text=TestPassword)
    {
        "outcome" => "success",
        "result" => {"expression" => "${ENC::exampleResolver:RUxZAUMQgtpG7oFlHR2j1Gkn3GKIHff+HR8GcMX1QXHvx2uGurI=}"}
    }

    ${ENC::exampleResolver:RUxZAUMQgtpG7oFlHR2j1Gkn3GKIHff+HR8GcMX1QXHvx2uGurI=} is the encrypted expression you use instead of TestPassword in the management model.

    If you use the same plain text in different locations, repeat this command each time before you use the encrypted expression instead of the plain text in that location. When you repeat the same command for the same plain text, you get a different result for the same key because Elytron uses a unique initialization vector for each call.

    By using different encrypted expressions you make sure that, if one encrypted expression on a string is somehow compromised, users cannot discover that any other encrypted expressions might also contain the same string.

  5. Re-enable the command caching using the following management CLI command:

    history --enable

2.3. Using an encrypted expression to secure a KeyStoreCredentialStore/credential-store

You can use an encrypted expression to secure a KeyStoreCredentialStore.

Prerequisites

Procedure

  • Create a KeyStoreCredentialStore that uses an encrypted expression as the clear-text:

    Syntax

    /subsystem=elytron/credential-store=<name_of_credential_store>:add(path=<path_to_the_credential_store>, create=true, modifiable=true, credential-reference={clear-text=<encrypted_expression>})

    Example

    /subsystem=elytron/credential-store=secureKeyStoreCredentialStore:add(path="secureKeyStoreCredentialStore.jceks", relative-to=jboss.server.data.dir, create=true, modifiable=true, credential-reference={clear-text=${ENC::exampleResolver:RUxZAUMQgtpG7oFlHR2j1Gkn3GKIHff+HR8GcMX1QXHvx2uGurI=}})
    {"outcome" => "success"}

After you have secured a KeyStoreCredentialStore with an encrypted expression, you can generate a SecretKeyCredential in the KeyStoreCredentialStore and use the secret key to create another encrypted expression. You can then use this new encrypted expression instead of a sensitive string in the management model - the server configuration file. You can create an entire chain of credential stores for security. Such a chain makes it harder to guess the sensitive string because the string is protected as follows:

  • The first encrypted expression secures a KeyStoreCredentialStore.
  • Another encrypted expression secures a sensitive string.
  • To decode the sensitive string, you would need to decrypt both the encrypted expressions.

As the chain of encrypted expressions becomes longer, it gets harder to decrypt the sensitive string.