io.axual.utilities.config.providers.VaultConfigProvider Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of vault-config-provider Show documentation
Show all versions of vault-config-provider Show documentation
The ConfigProvider is a means for Kafka Applications to retrieve secret configuration options and provide them to the implementations without showing the contents in the output.
The Configuration Provider for HashiCorp Vault can connect to a HashiCorp Vault installation and retrieve one or more keys and secrets stored.
The newest version!
package io.axual.utilities.config.providers;
/*-
* ========================LICENSE_START=================================
* Configuration Provider for HashiCorp Vault
* %%
* Copyright (C) 2020 Axual B.V.
* %%
* 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.
* =========================LICENSE_END==================================
*/
import com.bettercloud.vault.response.LogicalResponse;
import org.apache.kafka.common.config.ConfigData;
import org.apache.kafka.common.config.provider.ConfigProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import io.axual.utilities.config.providers.exceptions.VaultConfigurationException;
import io.axual.utilities.config.providers.exceptions.VaultConfigurationRetrieveException;
/**
* The VaultConfigProvider is used to retrieve secrets stored in a HashiCorp Vault.
* It can get all variables stored in the path, or only the specified keys from a path.
*/
public class VaultConfigProvider implements ConfigProvider {
public static final Logger LOG = LoggerFactory.getLogger(VaultConfigProvider.class);
protected Optional vaultHelper;
/**
* Constructor used for injecting custom VaultHelper
*
* @param vaultHelper the vaultHelper to use
*/
VaultConfigProvider(VaultHelper vaultHelper) {
this.vaultHelper = Optional.ofNullable(vaultHelper);
}
/**
* A default constructor is required for the ConfigProvider initialization.
*/
public VaultConfigProvider() {
vaultHelper = Optional.empty();
}
/**
* Creates the VaultHelperConfig used for Vault communication and tests the
* connection if a test path is set in the configuration.
*
* If configure is called multiple times the previous configuration is removed
*
* @param configs A map containing the configuration parameters for the provider
* @see VaultHelperConfig
*/
public void configure(Map configs) {
LOG.debug("Configuring provider");
if (vaultHelper.isPresent()) {
LOG.error("Previous configuration found, will not configure provider");
} else {
VaultHelperConfig config = new VaultHelperConfig(configs, true);
vaultHelper = Optional.ofNullable(createVaultHelper(config));
vaultHelper.ifPresent(VaultHelper::testConnection);
}
}
/**
* Retrieves all key/value pairs from the supplied Vault Path
*
* @param path The Path to the Vault Key Value pairs
* @return The configuration key and values retrieved from Vault
*/
public ConfigData get(String path) {
LOG.info("Get vault data from {}", path);
return get(path, Collections.emptySet());
}
/**
* Retrieves the specified key/value pairs from the supplied Vault Path.
*
* @param path The Path to the Vault Key Value pairs
* @param providedKeys The specific keys to retrieve, or all keys when empty
* @return The configuration key and values retrieved from Vault
*/
public ConfigData get(String path, Set providedKeys) {
VaultHelper helper = this.vaultHelper.orElseThrow(() -> new VaultConfigurationException("Provider is not yet configured"));
Set keys = providedKeys.stream()
.filter(key -> (key != null && !key.trim().isEmpty()))
.collect(Collectors.toSet());
LOG.info("Get vault data from {} with keys {}", path, keys);
LogicalResponse response = helper.getData(path);
Map retrieved = response.getData();
Map result = new HashMap<>();
if (keys.isEmpty()) {
result.putAll(retrieved);
} else {
for (String wanted : keys) {
if (retrieved.containsKey(wanted)) {
result.put(wanted, retrieved.get(wanted));
} else {
throw new VaultConfigurationRetrieveException("Did not find required key: " + wanted);
}
}
}
return new ConfigData(result);
}
/**
* Constructs the VaultHelper, build as utility method to enable spying during tests
*
* @param config The configuration to use when constructing the VaultHelper
* @return a new VaultHelper instance.
*/
VaultHelper createVaultHelper(VaultHelperConfig config) {
return new VaultHelper(config, LOG);
}
/**
* Closing the provider will remove the created vaultHelper.
*/
@Override
public void close() {
LOG.debug("Closing provider");
vaultHelper = Optional.empty();
}
}