io.helidon.integrations.oci.secrets.configsource.AbstractSecretBundleConfigSource Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of helidon-integrations-oci-secrets-config-source Show documentation
Show all versions of helidon-integrations-oci-secrets-config-source Show documentation
OCI Secrets Retrieval API ConfigSourceProvider Implementation
/*
* Copyright (c) 2023, 2024 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.helidon.integrations.oci.secrets.configsource;
import java.lang.System.Logger;
import java.util.Base64;
import java.util.Objects;
import java.util.function.Predicate;
import java.util.function.Supplier;
import io.helidon.common.LazyValue;
import io.helidon.config.AbstractConfigSource;
import io.helidon.config.AbstractConfigSourceBuilder;
import io.helidon.config.Config;
import io.helidon.config.ConfigException;
import io.helidon.config.spi.ConfigNode.ValueNode;
import io.helidon.service.registry.GlobalServiceRegistry;
import com.oracle.bmc.auth.AbstractAuthenticationDetailsProvider;
import com.oracle.bmc.secrets.Secrets;
import com.oracle.bmc.secrets.SecretsClient;
import static java.lang.System.Logger.Level.WARNING;
import static java.nio.charset.StandardCharsets.UTF_8;
/**
* An {@link AbstractConfigSource} that encapsulates functionality common to both {@link SecretBundleLazyConfigSource}
* and {@link SecretBundleNodeConfigSource}.
*
* @param the type of {@link AbstractConfigSourceBuilder} subclass used to build instances of this class
* @see SecretBundleLazyConfigSource
* @see SecretBundleNodeConfigSource
*/
abstract sealed class AbstractSecretBundleConfigSource>
extends AbstractConfigSource
permits SecretBundleLazyConfigSource, SecretBundleNodeConfigSource {
static final String VAULT_OCID_PROPERTY_NAME = "vault-ocid";
private static final Logger LOGGER = System.getLogger(AbstractSecretBundleConfigSource.class.getName());
/**
* Creates a new {@link AbstractSecretBundleConfigSource}.
*
* @param b a builder
*/
protected AbstractSecretBundleConfigSource(B b) {
super(b);
}
static ValueNode valueNode(String base64EncodedContent, Base64.Decoder base64Decoder) {
String decodedContent = new String(base64Decoder.decode(base64EncodedContent), UTF_8);
return ValueNode.create(decodedContent.intern());
}
/**
* An {@link AbstractConfigSourceBuilder} used to build instances of {@link AbstractSecretBundleConfigSource}.
*
* @param the builder subclass
*/
public abstract static sealed class Builder>
extends AbstractConfigSourceBuilder
permits SecretBundleLazyConfigSource.Builder, SecretBundleNodeConfigSource.Builder {
private Supplier extends Secrets> secretsSupplier;
private String vaultOcid;
/**
* Creates a new {@link Builder}.
*/
protected Builder() {
super();
SecretsClient.Builder scb = SecretsClient.builder();
this.secretsSupplier = () -> scb.build(adpSupplier().get());
}
static LazyValue extends AbstractAuthenticationDetailsProvider> adpSupplier() {
return LazyValue.create(() -> GlobalServiceRegistry.registry()
.get(AbstractAuthenticationDetailsProvider.class));
}
/**
* Configures this {@link Builder} from the supplied meta-configuration.
*
* @param metaConfig the meta-configuration; must not be {@code null}
* @return this {@link Builder}
* @throws NullPointerException if {@code metaConfig} is {@code null}
*/
@Override // AbstractConfigSourceBuilder
public B config(Config metaConfig) {
metaConfig.get("change-watcher")
.asNode()
.ifPresent(n -> {
throw new ConfigException("Invalid meta-configuration key: change-watcher: "
+ "Change watching is not supported by "
+ this.getClass().getName() + " instances");
});
metaConfig.get("vault-ocid")
.asString()
.filter(Predicate.not(String::isBlank))
.ifPresentOrElse(this::vaultOcid,
() -> {
if (LOGGER.isLoggable(WARNING)) {
LOGGER.log(WARNING,
"No meta-configuration value supplied for "
+ metaConfig.key().toString() + "." + VAULT_OCID_PROPERTY_NAME
+ "); resulting ConfigSource will be empty");
}
});
return super.config(metaConfig);
}
/**
* Sets the (required) OCID of the OCI vault from which an {@link AbstractSecretBundleConfigSource} will
* retrieve values.
*
* @param vaultOcid a valid OCID identifying an OCI vault; must not be {@code null}
* @return this {@link Builder}
* @throws NullPointerException if {@code vaultId} is {@code null}
*/
@SuppressWarnings("unchecked")
public B vaultOcid(String vaultOcid) {
this.vaultOcid = Objects.requireNonNull(vaultOcid, "vaultOcid");
return (B) this;
}
/**
* Uses the supplied {@link Supplier} of {@link Secrets} instances, instead of the default one, for
* communicating with the OCI Secrets Retrieval API.
*
* @param secretsSupplier the non-default {@link Supplier} to use; must not be {@code null}
* @return this {@link Builder}
* @throws NullPointerException if {@code secretsSupplier} is {@code null}
*/
@SuppressWarnings("unchecked")
public B secretsSupplier(Supplier extends Secrets> secretsSupplier) {
this.secretsSupplier = Objects.requireNonNull(secretsSupplier, "secretsSupplier");
return (B) this;
}
String vaultOcid() {
return this.vaultOcid;
}
Supplier extends Secrets> secretsSupplier() {
return this.secretsSupplier;
}
}
}