-
Notifications
You must be signed in to change notification settings - Fork 35
RFC: Allow any kind of keystore in vert.x core
Currently in vert.x core there are several ways to work with java security keystores. The 2 mostly used types are:
io.vertx.core.net.JksOptions
io.vertx.core.net.PfxOptions
This abstraction allows the configuration of a key store using from a polyglot perspective or using a JSON configuration. Although this has been working for a long time it does have a few limitations.
This type assumes that the configured keystore is of type "JKS" and the provider is the JDK (libSUNJSSE) setting the type or provider is not possible.
This type assumes that the configured keystore is of type "PKCS12" and the provider is the JDK (libSUNJSSE) setting the type or provider is not possible.
Both these classes extend a base class KeystoreOptions
which currently allows setting the type of the keystore. One of the reasons for this was the request to support PKCS11
(hardware stores), however the base class is NOT used in any public API, this means that the end user is only aware of the 2 sub classes listed above.
For secure and certified application there is a requirement to support FIPS
, among other items, this enforces strong rules on passwords and secret storage which translate in key store formats. In order to support this the vert.x end user must be able to configure the keystore type and in some cases specify the provider as generic OpenJDK does not ship with FIPS
support enabled out of the box.
The solution should be to add getters and setters to both type
and provider
to KeystoreOptions, but this isn't enough. Although the sub classes would be able to inherit these, currently JksOptions
hard codes the type to JKS
and disallows mutating it, and PfxOptions
does the same with type
as PKCS12
.
API wise, if this restriction would be removed, from a technical PoV, there would be no real difference between the 2 sub classes as types could be changed, so it would bring confusion to the end user. This would mean that "KeystoreOptions" would become "THE" way to load keystores, regardless of type and/or provider.
Having a closer look, this will require a deprecation/breaking change to many data objects, e.g.:
- net.NetClientOptions
- net.NetServerOptions
- net.TCPSSLOptions
- http.HttpClientOptions
- eventbus.EventBusOptions
Which currently have APIs like:
@Override
public NetClientOptions setTrustStoreOptions(JksOptions options) {
super.setTrustStoreOptions(options);
return this;
}
@Override
public NetClientOptions setPfxTrustOptions(PfxOptions options) {
return (NetClientOptions) super.setPfxTrustOptions(options);
}
Both setters "seem" to attempt to achieve the same result, but for the sake of type safety need to be declared as 2 independent setters. The proposed fix (with least breakage) would be in the following style:
@Override
public NetClientOptions setTrustStoreOptions(KeystoreOptions options) {
super.setTrustStoreOptions(options);
return this;
}
/**
* @deprecated Use {@link #setTrustStoreOptions(KeystoreOptions)} instead.
*/
@Override
@Deprecated
public NetClientOptions setPfxTrustOptions(PfxOptions options) {
return this.setTrustStoreOptions((KeystoreOptions) options);
}
However this will bring compilation issues as now the compiler will not be able to distinct between KeystoreOptions
and PfxOptions
so user code will require manual enforced casts e.g.: (KeystoreOptions) options
.
A more drastic change would be to really remove the [set|get]PfxXYZOptions()
which may require code changes to the user but probably less than the forced casting.
@Override
public NetClientOptions setTrustStoreOptions(KeystoreOptions options) {
super.setTrustStoreOptions(options);
return this;
}
At a higher level this can become more tricky as most of the configurations in core and other sub modules (amqp as an example) do rely on these types too.
A requested (downstream) feature is to handle password specific support for each key instead of relying on the store password itself. This will not solve it and it currently addressed on vertx-auth-common
.