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

Use Java ServiceLoader framework to create KMS instances #46

Closed
chris-giblin opened this issue Aug 4, 2022 · 3 comments
Closed

Use Java ServiceLoader framework to create KMS instances #46

chris-giblin opened this issue Aug 4, 2022 · 3 comments
Assignees

Comments

@chris-giblin
Copy link
Contributor

Initial plan was to specify classname of KMS implementation as a field within the KMS config such as:

[
  {
    "name"         : "vault-test",
    "kmsClassname" : "io.strimzi.kafka.topicenc.kms.vault.VaultKms",
    "uri"          : "http://127.0.0.1:8200/v1/secret/data/test",
    "credential"   : "<vault token>"
  },
  {
    "name"         : "test",
    "kmsClassname" : "io.strimzi.kafka.topicenc.kms.test.TestKms"
  },
  {
    "name"         : "cloud",
    "kmsClassname" : "io.strimzi.kafka.topicenc.kms.keyprotect.KeyProtectKms",
    "uri"          : "http://sfsffs.ibm.com/abc",
    "instanceId"   : "shdjkjahkjahd",
    "credential"   : "<apikey>"
  }

I have prototyped this and it works well, however there are shortcomings:

  • Brittleness: Refactoring of fully qualified class name requires update to config file
  • Security: using classname for configuration requires knowledge of and exposes class structure. I also have concerns this mechanism could be abused to load arbitrary classes.

This is reinforced by a recent post by Gunnar Morling:
https://twitter.com/gunnarmorling/status/1547253835911122945

Example of using Java ServiceLoader with short names by Gunnar:
https://github.com/kroxylicious/kproxy/blob/main/kroxylicious/src/main/java/io/kroxylicious/proxy/internal/filter/FilterContributorManager.java

ServiceLoader Javadoc:
https://docs.oracle.com/javase/10/docs/api/java/util/ServiceLoader.html

@chris-giblin chris-giblin self-assigned this Aug 4, 2022
@chris-giblin
Copy link
Contributor Author

chris-giblin commented Aug 4, 2022

@tombentley I have evaluated using ServiceLoader to load KMS implementations. This looks great with one important exception: the service implementation loaded is a single instance per kms type (e.g., vault, key-protect, etc.) however we may have multiple different KMS configs for the same KMS type.

Take for example, three configurations for keys on the same and different vault instances:

[
  {
    "name"      : "vault-test-1",
    "type"       : "vault",
    "uri"          : "http://127.0.0.1:8200/v1/secret/data/test1",
    "credential"   : "<vault token 1>"
  },
  {
    "name"      : "vault-test-2",
    "type"       : "vault",
    "uri"          : "http://127.0.0.1:8200/v1/secret/data/test2",
    "credential"   : "<vault token 2>"
  },
  {
    "name"      : "vault-test-3",
    "type"       : "vault",
    "uri"          : "http://127.0.0.1:6200/v1/secret/data/test3",
    "credential"   : "<vault token 3>"
  }
]

The polymorphic call to retrieve a key is very simple when a KMS instance is created for each configuration. We just need to retrieve by key ID:

 SecretKey key = kms.getKey(keyRef);

By contrast, in the case of ServiceLoader creating a KMS instance for each KMS type, the caller must pass the kms config as well in order to inform the KMS provider from which KMS of that type to retrieve the the key:

 SecretKey key = kms.getKey(keyRef, kmsDef);

The KMS provider must manage all the kms systems and configurations of its respective type. This complicates the provider implementation somewhat.

@chris-giblin
Copy link
Contributor Author

To merge the two concepts of service providers and kms config instances, the instances created by the service loader would be factories which in turn create type and config-specific kms instances. This would allow for any type-specific initialization/config.

This was referenced Aug 5, 2022
@chris-giblin
Copy link
Contributor Author

Java ServiceLoader implemented in PR #47

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

No branches or pull requests

1 participant