Skip to content
This repository has been archived by the owner on Jul 1, 2024. It is now read-only.

Kms module #47

Merged
merged 17 commits into from
Aug 23, 2022
Merged

Kms module #47

merged 17 commits into from
Aug 23, 2022

Conversation

chris-giblin
Copy link
Contributor

In this PR:

  • all kms functionality resides in separate submodules to facilitate drop-in kms plugins
  • generic kms classes moved into submodule, kms
  • a first kms implmentation, the test kms, is in submodule, kms-test
  • refactoring of import statements, class names, and pom dependencies due to the above changes

Issues addressed in this PR:

Copy link
Member

@tombentley tombentley left a comment

Choose a reason for hiding this comment

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

Thanks @chris-giblin, this is going to be a nice!

A couple of questions in addition to a few line comments:

  1. Why are the value and keyprotect modules not in the root pom.xml as modules?
  2. And they're also missing the service loader manifests in META-INF, right?

Thanks!

*
* @return
*/
String getName();
Copy link
Member

Choose a reason for hiding this comment

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

With this being an instance method an implementation might not return a constant value, which would foil the dplicate detection in the manager. So perhaps we should use an annotation on the implementation class to provide that name. That way the name would have to be a compile-time constant.

We should probably specify the legal syntax of these names a little more tightly too. We want to avoid collisions between names, so perhaps establishing a convention where a DNS name is used as a prefix, and requiring the rest of the name to be a DNS label. Thus the KMS implementations we provided would be strimzi.io/vault, strimzi.io/key-protect and strimzi.io/test, which would allow someone else to implement example.com/vault if they wanted to have their own Vault KMS impl.

I also wonder about whether we should call this name, given that the json seems to refer to it as type (maybe simplest to change the json typefactoryName)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

For the name syntax, I have created issue #48
I agree type and name should be consistent. I propose going with factoryName.

if (INSTANCE.dups.size() > 1) {
throw new KmsException(
"Invalid KMS provider configuration, duplicate short names: "
+ INSTANCE.dups.toString());
Copy link
Member

Choose a reason for hiding this comment

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

Can the message give a hint about how to fix the problem? ("Remove one of the KMS provider jars from the classpath, or rename one of them and rebuild the jar).

Also, no need for the toString (the compiler will add it for you).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Committed a fix. Please have a look

*
* @return
*/
private List<String> getDuplicateNames() {
Copy link
Member

Choose a reason for hiding this comment

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

Perhaps this method should just return a String, being an error message for whatever errors are encountered during initialization. That way we can also validate the factory names here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I like returning a List (actually it should be a Set). The caller can use easily convert to String if needed. I might be missing your point though.

Copy link
Member

Choose a reason for hiding this comment

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

My point was that:

  1. The raising of an exception happens at the call to getInstance, not at class initialization time.
  2. If we're going to validate the name of each factory then that's a 2nd kind of error, which would require another field to convey from the initialisation-time to the getInstance time. Nor can we discount the possibility of other kinds of error in the future.
  3. So it just seems more frugal to me to use a String error message, and convert the set to a message here, since from the users PoV there is no difference in behaviour: They still see an exception with an error message.

Iterator<KmsFactory> it = loader.iterator();
while (it.hasNext()) {
KmsFactory factory = it.next();
String name = factory.getName().toLowerCase();
Copy link
Member

Choose a reason for hiding this comment

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

Need a Locale to avoid locale-dependent behaviour.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

Iterator<KmsFactory> it = loader.iterator();
while (it.hasNext()) {
KmsFactory factory = it.next();
if (factory.getName().equalsIgnoreCase(type)) {
Copy link
Member

Choose a reason for hiding this comment

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

I think this will be locale-dependent, which we want to avoid.

(IIRC checkstyle and/or findbugs catches this sort of thing. We're using it in the strimzi-kafka-operator repo if you wanted to copy the config, but that's for another PR).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Created issue #49

Comment on lines 78 to 79
while (it.hasNext()) {
KmsFactory factory = it.next();
Copy link
Member

Choose a reason for hiding this comment

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

ServiceLoader is Iterable, so we could write this as for (KmsFactory factory : loader) {

Copy link
Contributor Author

Choose a reason for hiding this comment

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

nice, done

Copy link
Member

Choose a reason for hiding this comment

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

@chris-giblin do you have some unpushed commits, because while you say "done" this code doesn't seem to have changed.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@tombentley indeed, there was an unpushed commit. Apologies. The commit has now been added to this PR. Please review when you get the chance. Thanks.

Comment on lines 99 to 102
Integer num = nameMap.get(name);
if (num == null) {
num = Integer.valueOf(0);
}
Copy link
Member

Choose a reason for hiding this comment

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

Integer num = getOrDefault(name, Integer.valueOf(0))

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks, done

package io.strimzi.kafka.topicenc.kms;

/**
* Interface to a KMS factory.
Copy link
Member

Choose a reason for hiding this comment

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

We should mention that implementations are discovered via KmsFactoryManager using the service loader mechanism.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

@chris-giblin
Copy link
Contributor Author

1. Why are the value and keyprotect modules not in the root pom.xml as modules?

2. And they're also missing the service loader manifests in META-INF, right?

The idea of this PR is to introduce kms submodule and one implementation, kms-test. Once approved and merged, there will then be each a PR for kms-vault and kms-keyprotect

Copy link
Member

@tombentley tombentley left a comment

Choose a reason for hiding this comment

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

Thanks!

Map<String, KmsDefinition> validKmsDefs,
Map<String, KeyMgtSystem> kmsPool) {

String kmsName = createKey(policy.getKmsName(), Locale.getDefault());
Copy link
Member

Choose a reason for hiding this comment

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

The default locale will depend on the runtime machine. You need to use a constant locale, like Locale.ROOT or Locale.ENGLISH to have consistent behaviour.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I have created issue #50 for how Local is consistently managed and specified.

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

Successfully merging this pull request may close these issues.

2 participants