io.gravitee.node.secrets.service.keystoreloader.SecretProviderKeyStoreLoader Maven / Gradle / Ivy
package io.gravitee.node.secrets.service.keystoreloader;
import io.gravitee.common.util.KeyStoreUtils;
import io.gravitee.node.api.certificate.KeyStoreEvent;
import io.gravitee.node.api.certificate.KeyStoreLoader;
import io.gravitee.node.api.certificate.KeyStoreLoaderOptions;
import io.gravitee.node.api.secrets.model.Secret;
import io.gravitee.node.api.secrets.model.SecretEvent;
import io.gravitee.node.api.secrets.model.SecretMap;
import io.gravitee.node.api.secrets.model.SecretMount;
import io.gravitee.node.certificates.AbstractKeyStoreLoader;
import io.gravitee.node.secrets.service.conf.GraviteeConfigurationSecretResolverDispatcher;
import io.reactivex.rxjava3.disposables.Disposable;
import java.security.KeyStore;
import lombok.extern.slf4j.Slf4j;
/**
* @author Benoit BORDIGONI (benoit.bordigoni at graviteesource.com)
* @author GraviteeSource Team
*/
@Slf4j
public class SecretProviderKeyStoreLoader extends AbstractKeyStoreLoader {
private final GraviteeConfigurationSecretResolverDispatcher secretResolverDispatcher;
private Disposable watch;
public SecretProviderKeyStoreLoader(
GraviteeConfigurationSecretResolverDispatcher secretResolverDispatcher,
KeyStoreLoaderOptions options
) {
super(options);
this.secretResolverDispatcher = secretResolverDispatcher;
}
@Override
public void start() {
final SecretMount secretMount = secretResolverDispatcher.toSecretMount(options.getSecretLocation());
createBundleAndNotify(secretResolverDispatcher.resolve(secretMount).blockingGet(), secretMount);
if (options.isWatch()) {
this.watch =
secretResolverDispatcher
.watch(secretMount, SecretEvent.Type.UPDATED)
.subscribe(secretMap -> createBundleAndNotify(secretMap, secretMount), ex -> log.error("cannot create keystore", ex));
}
}
private void createBundleAndNotify(SecretMap secretMap, SecretMount secretMount) {
switch (options.getType().toUpperCase()) {
case KeyStoreLoader.CERTIFICATE_FORMAT_PEM -> {
String loaderId = id();
KeyStore keyStore = KeyStoreUtils.initFromPem(
secretMap
.wellKnown(SecretMap.WellKnownSecretKey.CERTIFICATE)
.map(Secret::asString)
.orElseThrow(() ->
new IllegalArgumentException(
"no pem certificate found in secret. If a ?keymap has been set make sure it contains ?keymap=certificate:)"
)
),
secretMap
.wellKnown(SecretMap.WellKnownSecretKey.PRIVATE_KEY)
.map(Secret::asString)
.orElseThrow(() ->
new IllegalArgumentException(
"no pem private key found in secret. If a ?keymap has been set make sure it contains ?keymap=private_key:)"
)
),
this.getPassword(),
options.getDefaultAlias()
);
onEvent(new KeyStoreEvent.LoadEvent(loaderId, keyStore, this.getPassword()));
}
case KeyStoreLoader.CERTIFICATE_FORMAT_JKS, KeyStoreLoader.CERTIFICATE_FORMAT_PKCS12 -> {
String loaderId = id();
KeyStore keyStore = KeyStoreUtils.initFromContent(
options.getType(),
secretMap
.getSecret(secretMount)
.map(Secret::asString)
.orElseThrow(() -> new IllegalArgumentException("no keystore value found for key '%s'".formatted(secretMount.key()))
),
this.getPassword()
);
onEvent(new KeyStoreEvent.LoadEvent(loaderId, keyStore, this.getPassword()));
}
default -> log.warn("some ssl related secrets were changes but not handled");
}
}
@Override
public void stop() {
if (watch != null) {
watch.dispose();
}
}
}