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

Secret Keys Handlers #833

Merged
merged 8 commits into from
Mar 21, 2023
Merged

Secret Keys Handlers #833

merged 8 commits into from
Mar 21, 2023

Conversation

radcortez
Copy link
Member

@radcortez radcortez commented Sep 30, 2022

Replaces #799.

  • We use property expressions to represent a secret key value in the format ${handler_name::encoded_secret}.
  • The SecretKeys API, registers handlers by name via the ServiceLoader.
  • The SecretKeysHandler is executed in the interceptor that deals with secret keys (if there is a match).
  • Any source can contain secrets. It only requires the right handlers to decode/decrypt the value.
  • Also includes a KeyStore source, to demonstrate how it could work with the SecretKeysHandler.

There is still some work to complete:

  • Being able to configure SecretKeysHandler.
  • Certificate support
  • Out of the box handlers

The goal of the current PR is to just agree on the design and then move forward.

@radcortez radcortez marked this pull request as draft September 30, 2022 12:51
@radcortez
Copy link
Member Author

/cc @dmlloyd @sberyozkin

@radcortez radcortez force-pushed the keystore-source branch 2 times, most recently from 0c84602 to b60e9b1 Compare November 4, 2022 18:38
@radcortez radcortez marked this pull request as ready for review November 7, 2022 17:47
@radcortez
Copy link
Member Author

@dmlloyd let me know what you think of the current proposal. Thanks!

@@ -0,0 +1,27 @@
package io.smallrye.config;

public class SecretKeysHandlerConfigSourceInterceptor implements ConfigSourceInterceptor {
Copy link
Contributor

Choose a reason for hiding this comment

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

This makes sense to me. We can look up secret values separately from extracting them from an expression, which also allows specialized config sources that might encode them in an idiomatic way. 👍

public class KeyStoreConfigSourceFactory implements ConfigSourceFactory {
@Override
public Iterable<ConfigSource> getConfigSources(final ConfigSourceContext context) {
SmallRyeConfig config = new SmallRyeConfigBuilder()
Copy link
Contributor

Choose a reason for hiding this comment

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

So this config source requires a full config in order to work? If so, this gets away from the single-config methodology twice, once by requiring a config for the config and once for the key store itself.

Copy link
Member Author

Choose a reason for hiding this comment

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

Not exactly. This is just a trick to be able to use a mapping to configure a ConfigSource.

For instance, consider the mapping:
https://github.com/radcortez/smallrye-config/blob/b2bf955328cf8e4382c364f898173477d80d77a3/sources/keystore/src/main/java/io/smallrye/config/source/keystore/KeyStoreConfig.java#L11

How can we create this mapping? Remember, we use SmallRyeConfig to call certain API to populate the mapping instance. Ideally, we should decouple that, so we don't need to use the trick.

We create an empty SmallRyeConfig instance, just with the mapping class and a ConfigSource that delegates to the ConfigSourceContext:

https://github.com/radcortez/smallrye-config/blob/b2bf955328cf8e4382c364f898173477d80d77a3/sources/keystore/src/main/java/io/smallrye/config/source/keystore/KeyStoreConfigSourceFactory.java#L38-L41

https://github.com/radcortez/smallrye-config/blob/b2bf955328cf8e4382c364f898173477d80d77a3/sources/keystore/src/main/java/io/smallrye/config/source/keystore/KeyStoreConfigSourceFactory.java#L70-L97

So we can get an instance of the mapping class, by wrapping all of that, but still use the original config context being build.

@UXabre
Copy link

UXabre commented Feb 14, 2023

preface: the following could be very dumb as I'm not acquainted with this project in particular, but seeing that other parts seem to support dynamic loading of config changes, e.g. the following PR https://github.com/smallrye/smallrye-config/pull/152/files#diff-60faeb32cc934956c4bbc5ac22b81c35f9c9fc6e8073e83779bb1cfbe00d7cb9 ...

Also, I'm sorry I'm discussing it here but I couldn't find a related issue on the matter.

I'm curious to learn if it shouldn't also be possible to load changes of these secrets as well? For instance, a file containing a password file should probably trigger an event if it is changed so that a consuming application could simply reload. However, as mentioned, it seems some part of this project support it but I'm finding it hard to understand if this PR builds on that or not?
To be more specific: will a change of a secretvalue lead to an event being fired

To give an example: will a change of a secretvalue lead to an event being fired that can be caught by, let's say, KeyCloak (which uses quarkus) which would be able to restart a connection to a backend resource?

@radcortez
Copy link
Member Author

Also, I'm sorry I'm discussing it here but I couldn't find a related issue on the matter.

You don't need to apologize :)

I'm curious to learn if it shouldn't also be possible to load changes of these secrets as well? For instance, a file containing a password file should probably trigger an event if it is changed so that a consuming application could simply reload. However, as mentioned, it seems some part of this project support it but I'm finding it hard to understand if this PR builds on that or not? To be more specific: will a change of a secretvalue lead to an event being fired

No, we don't build on that. What determines how a configuration is read (and if it is reloadable), is the ConfigSource. This PR, only adds the ability to interpret values as secrets and handle them. It is certainly possible with the events extension to provide a ConfigSource that triggers the CDI event on a config change or reload.

To give an example: will a change of a secretvalue lead to an event being fired that can be caught by, let's say, KeyCloak (which uses quarkus) which would be able to restart a connection to a backend resource?

Our stance with Quarkus is that we don't support reloadable configuration (at least the configuration on the quarkus namespace). Everyone else is free to do what they want :) The big issue is that is hard to manage user expectations about a configuration reload. Certain configurations will always require a server restart, while others we could get away without, so we prefer to be consistent and always require a restart if you change the Quarkus configuration.

@UXabre
Copy link

UXabre commented Feb 14, 2023

Thanks for your elaborate reply on the matter, really appreciate it and I understand it fully :-) Happy coding!

@Pepo48
Copy link

Pepo48 commented Feb 16, 2023

Hey @radcortez, as I'm continuing with the spike around this PR, I encountered another issue (hopefully this time it's not something already known 😊) .

It seems that when you work with the Keystore Config Source and addProfileConfigSource method tries to load the optional profile resource (for example in my case it was keystore-prod, which doesn't have to exist), a runtime exception thrown here:

} catch (KeyStoreException | CertificateException | IOException | NoSuchAlgorithmException
| UnrecoverableKeyException e) {
throw new RuntimeException(e);
}

is not handled properly. In my scenario, where single property file is shared among multiple tests, it affected all of them.

I tried a quick fix, where I caught the exception here:


So now the line looks like this:

catch (FileNotFoundException | NoSuchFileException | RuntimeException e) {

and it helped. But you may find a more elegant solution, for sure 😊.
If it will be needed I can share a reproducer as well.

Thanks!

@radcortez
Copy link
Member Author

Thanks! Let me have a look!

@Pepo48
Copy link

Pepo48 commented Feb 23, 2023

Thanks! Let me have a look!

@radcortez I just wanted to ask whether there is a progress regarding this?

On top of that, what secret handlers are planned to be present in the final implementation? I tried the jasypt one and it seems to cover our needs for now.

Is this still aimed for the Quarkus 3 release?

Thanks!

@radcortez
Copy link
Member Author

Hey. I'm sorry, I was on PTO the last few days so I couldn't look into it, but it is on my plans to look as soon as possible. I still need to do the final move to Jakarta (including other SR Projects), and then we should be ready to go with new features.

Yes, the jasypt one is planned to be included and still aimed at Quarkus 3.

The idea is to add handlers as required, so if you need a specific one, feel free to add it.

@radcortez radcortez force-pushed the keystore-source branch 2 times, most recently from 4d6a7af to 3ef8368 Compare March 8, 2023 14:51
@radcortez
Copy link
Member Author

@Pepo48

I have fixed some of the issues and added some of the missing pieces (namely, supporting a way to configure the secret handlers).

Can you take a final look? Thanks :)

@radcortez radcortez changed the title Prototype to secure secret keys Secret Keys Handlers Mar 10, 2023
@radcortez radcortez force-pushed the keystore-source branch 3 times, most recently from b9baa8d to cfb1742 Compare March 17, 2023 13:22
@michalvavrik
Copy link

michalvavrik commented Mar 20, 2023

Hey @radcortez ,

do you think it is possible for you to release SmallRye Config and bump the version in Quarkus once this gets merged? I'd like to do QE test development for this - https://issues.redhat.com/browse/QUARKUS-2727. I hope release won't eat too much of your time.

Thank you

@radcortez
Copy link
Member Author

I'm currently working on the Quarkus integration bits and I believe it should be completed in the next few days. Thanks!

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.

5 participants