All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.quarkus.vault.runtime.config.VaultConfigSource Maven / Gradle / Ivy

package io.quarkus.vault.runtime.config;

import static io.quarkus.vault.runtime.config.VaultCacheEntry.tryReturnLastKnownValue;
import static java.util.Collections.emptyMap;
import static java.util.stream.Collectors.toMap;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;

import org.eclipse.microprofile.config.spi.ConfigSource;
import org.jboss.logging.Logger;

import io.quarkus.arc.Arc;
import io.quarkus.vault.VaultKVSecretEngine;

public class VaultConfigSource implements ConfigSource {

    private static final Logger log = Logger.getLogger(VaultConfigSource.class);

    private AtomicReference>> cache = new AtomicReference<>(null);
    private VaultBootstrapConfig vaultBootstrapConfig;

    public VaultConfigSource(VaultBootstrapConfig vaultBootstrapConfig) {
        this.vaultBootstrapConfig = vaultBootstrapConfig;
    }

    @Override
    public String getName() {
        return VaultBootstrapConfig.NAME;
    }

    @Override
    public int getOrdinal() {
        return vaultBootstrapConfig.configOrdinal;
    }

    /**
     * always return an empty map to protect from accidental properties logging
     *
     * @return empty map
     */
    @Override
    public Map getProperties() {
        return emptyMap();
    }

    @Override
    public String getValue(String propertyName) {
        return vaultBootstrapConfig.url.isPresent() ? getSecretConfig().get(propertyName) : null;
    }

    private Map getSecretConfig() {

        VaultCacheEntry> cacheEntry = cache.get();
        if (cacheEntry != null && cacheEntry.youngerThan(vaultBootstrapConfig.secretConfigCachePeriod)) {
            return cacheEntry.getValue();
        }

        Map properties = new HashMap<>();

        try {
            // default kv paths
            vaultBootstrapConfig.secretConfigKvPath.ifPresent(strings -> fetchSecrets(strings, null, properties));

            // prefixed kv paths
            vaultBootstrapConfig.secretConfigKvPathPrefix.forEach((key, value) -> fetchSecrets(value.paths, key, properties));

            log.debug("loaded " + properties.size() + " properties from vault");
        } catch (RuntimeException e) {
            return tryReturnLastKnownValue(e, cacheEntry);
        }

        cache.set(new VaultCacheEntry(properties));
        return properties;

    }

    private void fetchSecrets(List paths, String prefix, Map properties) {
        paths.forEach(path -> properties.putAll(fetchSecrets(path, prefix)));
    }

    private Map fetchSecrets(String path, String prefix) {
        return prefixMap(getVaultKVSecretEngine().readSecret(path), prefix);
    }

    private VaultKVSecretEngine getVaultKVSecretEngine() {
        return Arc.container().instance(VaultKVSecretEngine.class).get();
    }

    private Map prefixMap(Map map, String prefix) {
        return prefix == null
                ? map
                : map.entrySet().stream().collect(toMap(entry -> prefix + "." + entry.getKey(), Map.Entry::getValue));
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy