Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WFLY-14984] Add support for encrypted expressions in the wildfly-config.xml #545

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

PrarthonaPaul
Copy link

Issue: https://issues.redhat.com/browse/WFLY-14984
Considerations based on preliminary discussions:

  • Multiple attributes that could be candidates for supporting encrypted expressions. May be good to add support for encrypted expression for any attribute for forward compatibility.
  • Proposal considers the support for encrypted expression being its own section which can be specified first and other sections can refer to it.

todo before implementation:

  • look into what types of resolution properties are already available for the wildfly client

@PrarthonaPaul PrarthonaPaul force-pushed the WFLY-14984 branch 2 times, most recently from 30b7c1f to 9e83c80 Compare December 4, 2023 18:30

Attribute values for client configuration can include sensitive information. And while credential references can be used for some of them, others still need to be defined using plaintext. As a result, those attributes are still exposed and make the application vulnerable. Additionally, the password for the credential store needs to be defined as clear-text, which is not ideal.

This feature adds support for encrypted expressions for attributes in `wildfly-config.xml` file, which allows users to avoid specifying sensitive information using plaintext. Instead, encrypted expressions can be used to specify these information. A configuration section named `encrypted-expression` would be added, which would reference a `secret-key-credential-store` to extract encrypted expressions. It would also have a resolver, which would be backed by the secret-key-credential-store. The `secret-key-credential-store` can be created either using the `elytron-tool` or using the Elytron subsystem on the WildFly server.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is probably just a copy/paste thing but since wildfly-config.xml is something that's used on the client side, we shouldn't be mentioning the Elytron subsystem here.

Copy link
Author

@PrarthonaPaul PrarthonaPaul Dec 4, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking in case the user is doing some server configuration as well like this blog does: https://wildfly-security.github.io/wildfly-elytron/blog/ejb-over-tls/
In these cases, we can also use the management cli to create the credential store as opposed to using the elytron-tool.
WDYT? Could this be a possible use case?

I can make it more general by saying management cli instead of elytron subsystem.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the linked blog post, it looks like the credential store is created using elytron-tool.sh. I don't see subsystem commands being used to create it.

The management CLI is used for server config so I think mentioning it just makes things a bit confusing since this RFE is about the client side.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed the wording to only mention client configuration.

<protection-parameter-credentials>
<clear-password password="password" />
</protection-parameter-credentials>
</credential-store>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The indentation in this block looks a bit off.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed!


* The `encrypted-expression` configuration can be specified as follows:
```
<encrypted-expression>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be good to add more details here about the specific elements, attributes, etc. that are being introduced. Then the block below could be an example.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed!


** While parsing the xml file, the section for encrypted expression and its resolver would need to be parsed before any other sections that reference it.

* Encrypted expressions can be added to other subsystems in addition to elytron. As a result, the parsing rules and sequences should be configured to be compatible with those subsystems as well.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is client side, the terminology here needs to be updated. It's currently referencing subsystems.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed!


// === Related Issues

// * https://issues.redhat.com/browse/WFCORE[WFCORE-XXXX]
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need an ELY issue for this?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. We can reference your newly created issue here.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added the ELY issue


Attribute values for client configuration can include sensitive information. And while credential references can be used for some of them, others still need to be defined using plaintext. As a result, those attributes are still exposed and make the application vulnerable. Additionally, the password for the credential store needs to be defined as clear-text, which is not ideal.

This feature adds support for encrypted expressions for attributes in `wildfly-config.xml` file, which allows users to avoid specifying sensitive information using plaintext. Instead, encrypted expressions can be used to specify these information. A configuration section named `encrypted-expression` would be added, which would reference a `secret-key-credential-store` to extract encrypted expressions. It would also have a resolver, which would be backed by the secret-key-credential-store. The `secret-key-credential-store` can be created either using the `elytron-tool`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"to extract encrypted expressions" should be reworded. The credential store contains the secret key that is used to encrypt/decrypt encrypted expressions.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"The secret-key-credential-store can be created either using the elytron-tool."

This sentence is incomplete I think.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"It would also have a resolver, which would be backed by the secret-key-credential-store"

Will the resolver be able to reference a credential-store as well in addition to being able to reference a secret-key-credential-store?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Resolvers are backed by aliases from a CredentialStore object. Secret-key-credential-store is an instance of that class with type PropertiesCredentialStore. So, yes, we can use either type.
I will add a note about that. Thanks!


* The ability to specify attribute values as encrypted expressions should be added to wildfly-config.xml.

* The parsing needs to be able to run separately from the application server, as the server may not be running while the client configuration is being set up.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this could be reword to something like:

Parsing for client configuration is separate from parsing server configuration.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed!


* Configurations may not depend on components created for server configuration, such as `resolvers` or `elytron/expression`. The resolver for the encrypted expression should be configured through the client configuration.

* The `encrypted-expression` would be a new configuration block added to the client config under the new schema. The new attributes added include `resolvers`, with attributes called `resolver` under it. Additionally, <credential-stores> attribute would be added to the schema with the <credential-store> attributes added to it. The structures of this attribute would be the same as the one one under the `authentication-client` schema.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a small thing, resolvers and resolver would be elements (as opposed to attributes).

Same with credential-stores and credential-store.

Copy link
Contributor

@fjuma fjuma Jan 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will there be a separate secret-key-credential-store element? (Just noticed that's mentioned in the intro but not in this section)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope, we can just use the credential-store element and specify the type as keystorecredentialstore (which is the default config) or PropertiesCredentialStore.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok thanks. Would be good to update the intro since it currently references a secret-key-credential-store element.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed!
There are still some mentions of a secret-key-credential, but when mentioning the element itself, I am referring to it as a credential-store.
Please let me know if I should change it all to be credential-store

** The configuration for this block can be specified as follows:
```
<encrypted-expression>
<credential-store name="credential-store-name" type="PKCS12" provider="provider-name"/>
Copy link
Contributor

@fjuma fjuma Jan 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should there be a credential-stores element around this?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed!

</protection-parameter-credentials>
</credential-store>
<resolvers>
<resolver name= “resolver-name” credential-store= “credential-store-name key=“key”/>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

credential-store-name is missing the closing quote here and below.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

<resolver name= “resolver-name” credential-store= “credential-store-name key=“key”/>
<resolver name= “resolver-name-2” credential-store= “credential-store-name key=“example”/>
</resolvers>
<default-resolver name=resolver-name>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does default-resolver need to be its own element? Can it be an attribute defined on the expression-resolver like in the server side config? e.g., see the xml config here:

https://wildfly-security.github.io/wildfly-elytron/blog/wildfly-encrypted-expressions/

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if it is not added as a separate element, would we add it as a property for the encrypted expression element?
so like

<encrypted-expression default-resolver="resolver-name">
INSERT CONFIGURATION
</encrypted expression>

If we do go with this, I am not sure if we can ensure that resolver-name is one of the resolvers specified under the elements. I think the parser currently checks to make sure it is.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just looking at the example from the blog post:

<expression-resolver default-resolver="main-resolver">
    <resolver name="initial-resolver" credential-store="initial" secret-key="key"/>
    <resolver name="main-resolver" credential-store="main" secret-key="main-key"/>
</expression-resolver>

Can we make use of this format?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I will update the schema and parser to use this.
Also, would it be better to make the default-resolver a required attribute? or make it optional, but if the user does not specify one, then the first resolver becomes the default resolver?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How is this done on the server side?

Copy link
Author

@PrarthonaPaul PrarthonaPaul Jan 12, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The server does neither.
When adding an expression resource using the following command:

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

defining a value for the default-resolver attribute is optional on the server side.
Now if someone tries to create an expression without defining a resolver, then the output is as follows:

/subsystem=elytron/expression=encryption:create-expression(clear-text=password)
{
    "outcome" => "failed",
    "failure-description" => "WFLYELY01200: The name of the resolver to use was 
not specified and no default-resolver has been defined.",
    "rolled-back" => true
}

On the client, the create-expression part is done using the --encrypt option on the wildfly-elytron tool, which would give you an output like this:

Clear text encrypted to token 'RUxZAUMQQ1PVWZuimKZCpt0s6MONrl7cbqLGPhyBBmm83fXdfZA=' using alias 'key'.

It would be up to the user to convert it to something like {ENC::resolver_name:RUxZAUMQQ1PVWZuimKZCpt0s6MONrl7cbqLGPhyBBmm83fXdfZA=} (where the expression resolver called resolver-name would be used to decrypt)
or they can convert it to {ENC::RUxZAUMQQ1PVWZuimKZCpt0s6MONrl7cbqLGPhyBBmm83fXdfZA=} (where the default expression resolver would be used to decrypt)

There is code in place already in the resolver class to handle cases where the user goes with the second configuration, but there is no default-expression-resolver defined. So, if we do want to do something similar to what the server does, I think it may be possible to throw an exception when trying to resolve the expression. However, since we are using the wildfly-elytron tool to encrypt, we cannot throw the same exception when creating the expression, which is what the server does.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok given that, I think it would be good to have the default-resolver attribute be optional here too.

An encrypted expression provided in wildfly-config should either specify the resolver name or rely on the default being used.

If relying on the default and the default-resolver hasn't been defined, then that's invalid configuration and an exception should occur when attempting to resolve it.

<clear-password password="password" />
</protection-parameter-credentials>
</credential-store>
<resolvers>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the server config, I think we use , right (would be good to double check what's used there)? Any reason to use "resolvers" here instead of "expression-resolvers"?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated to and . I will update the code to reflect this change as well.

```
Note that the initial password for the secret-key-credential-store used for the resolver would need to be specified in clear-text.

Once parsing is done, the resolver would need to be created programmatically (if not created by the server already) and be connected with the secret-key-credential-store.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you explain this some more? The client side config is unrelated to the server side config so not quite following the reference to the server side here.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"(if not created by the server already)" should not be there since this is entirely on the client side.
I have fixed it.

</credential-store>
```

* The encrypted expression would be created using the `--generate-secret-key` command and can be read using the `--export-secret-key` command.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be good to get some examples added here.

Copy link
Author

@PrarthonaPaul PrarthonaPaul Jan 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added example commands for both generating secret key and encrypting with it.
Thanks @fjuma I have addresses the comments on this PR!

</credential-store>
</credential-stores>
<expression-resolvers default-resolver="expression-resolver-name">
<expression-resolver name= “expression-resolver-name” credential-store= “credential-store-name" alias=“key”/>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just looking at the server configuration and noticed that we use "secret-key" instead of "alias" there. Any reason to use "alias" here? Just wondering if we should use "secret-key" instead just to make it more similar to the configuration on the server side.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No particular reason. I assumed alias is more unambiguous than secret-key. But it should be easy to change it to secret-key if we decide to go with that.

Clear text encrypted to token 'RUxZAUMQvGzk6Vaadp2cahhZ6rlPhHOZcWyjXALlAthrENvRTvQ=' using alias 'key'.
```

* expression-resolvers should be backed by an entry from a credential-store of type KeyStoreCredentialStore. However, when using a KeyStoreCredentialStore type credential store, the protection parameter, which is the password, needs to be specified in clear-text inside the <encrypted-expressions> tag.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expression-resolvers can reference any type of credential-store right? Here, KeyStoreCredentialStore is mentioned specifically.

Copy link
Author

@PrarthonaPaul PrarthonaPaul Feb 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed it to "However, when using other types of credential stores that are protected by a protection parameter, such as a password, that needs to be specified in clear-text inside the tag. "


* expression-resolvers should be backed by an entry from a credential-store of type KeyStoreCredentialStore. However, when using a KeyStoreCredentialStore type credential store, the protection parameter, which is the password, needs to be specified in clear-text inside the <encrypted-expressions> tag.

* Attribute value resolvers inside the wildfly-client-config project should be updated with the ability to parse encrypted expressions and resolve them to extract the clear-text sensitive information. In order to avoid circular dependencies, service loader would be used by the wildfly-client-config project to use an EncryptedExpressionResolver class to decrypt an encrypted expression.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be good to provide some more details on the Service Loader approach if possible.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added!


=== Nice-to-Have Requirements

* The parsing of the encrypted expression should be added at the top of the xml file and must be parsed before any other class that uses encrypted expressions.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this still relevant?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed this point since it is no longer relevant.


** The configuration for this block can be specified as follows:
```
<encrypted-expressions>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just noticed encrypted-expressions is used here but encrypted-expression is used in the blog post wildfly-security/wildfly-elytron#2088.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed it on the blog!
Thanks, @fjuma for reviewing the proposal!

@PrarthonaPaul PrarthonaPaul force-pushed the WFLY-14984 branch 2 times, most recently from e1669ea to 254280b Compare February 6, 2024 14:46

Attribute values for client configuration can include sensitive information. And while credential references can be used for some of them, others still need to be defined using plaintext. As a result, those elements are still exposed and make the application vulnerable. Additionally, the password for the credential store needs to be defined as clear-text, which is not ideal.

This feature adds support for encrypted expressions for elements in `wildfly-config.xml` file, which allows users to avoid specifying sensitive information using plaintext. Instead, encrypted expressions can be used to specify these information. A configuration section named `encrypted-expressions` would be added, which would reference a `secret-key-credential-store` to convert plaintext to encrypted expressions and vice versa. The secret-key-credential-store would be indicated by the `credential-store` tag with the `type` being `PropertiesCredentialStore`. It would also have a expression-resolver, which would be backed by one of the secret key aliases from the the secret-key-credential-store. The `credential-store` can be created using the wildfly-elytron tool using the `credential-store` command and the `--create` option.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change, "these information." to "this information."

It might be helpful to future readers to reference this doc about wildfly-elytron tool,
https://github.com/wildfly/wildfly/blob/main/docs/src/main/asciidoc/_elytron/Credential_Store.adoc

Clear text encrypted to token 'RUxZAUMQvGzk6Vaadp2cahhZ6rlPhHOZcWyjXALlAthrENvRTvQ=' using alias 'key'.
```

* expression-resolvers should be backed by an entry from a credential-store of type KeyStoreCredentialStore. However, when using other types of credential stores that are protected by a protection parameter, such as a password, that needs to be specified in clear-text inside the <encrypted-expressions> tag.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change, "that needs to be specified" to "it needs to be specified".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants