Skip to content

Commit

Permalink
Merge pull request #167 from scalecube/vault-miltiple-path
Browse files Browse the repository at this point in the history
Vault miltiple path
  • Loading branch information
snripa authored May 21, 2020
2 parents 24fee4f + 6670df2 commit 30e36c3
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
import io.scalecube.config.ConfigSourceNotAvailableException;
import io.scalecube.config.source.ConfigSource;
import io.scalecube.config.source.LoadedConfigProperty;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
Expand All @@ -27,31 +31,35 @@ public class VaultConfigSource implements ConfigSource {
private static final String VAULT_SECRETS_PATH = "VAULT_SECRETS_PATH";

private final VaultInvoker vault;
private final String secretsPath;
private final List<String> secretsPath;

/**
* Create a new {@link VaultConfigSource}.
*
* @param vault vault invoker.
* @param secretsPath secret path.
* @param vault vault invoker.
* @param secretsPaths secret path-s.
*/
private VaultConfigSource(VaultInvoker vault, String secretsPath) {
private VaultConfigSource(VaultInvoker vault, List<String> secretsPaths) {
this.vault = vault;
this.secretsPath = secretsPath;
this.secretsPath = secretsPaths;
}

@Override
public Map<String, ConfigProperty> loadConfig() {
try {
LogicalResponse response = vault.invoke(vault -> vault.logical().read(secretsPath));
return response.getData().entrySet().stream()
.map(LoadedConfigProperty::withNameAndValue)
.map(LoadedConfigProperty.Builder::build)
.collect(Collectors.toMap(LoadedConfigProperty::name, Function.identity()));
} catch (Exception ex) {
LOGGER.warn("unable to load config properties", ex);
throw new ConfigSourceNotAvailableException(ex);
Map<String, ConfigProperty> result = new HashMap<>();
for (String path : secretsPath) {
try {
LogicalResponse response = vault.invoke(vault -> vault.logical().read(path));
final Map<String, LoadedConfigProperty> pathProps = response.getData().entrySet().stream()
.map(LoadedConfigProperty::withNameAndValue)
.map(LoadedConfigProperty.Builder::build)
.collect(Collectors.toMap(LoadedConfigProperty::name, Function.identity()));
result.putAll(pathProps);
} catch (Exception ex) {
LOGGER.warn("unable to load config properties from {}",path, ex);
throw new ConfigSourceNotAvailableException(ex);
}
}
return result;
}

/**
Expand Down Expand Up @@ -87,12 +95,12 @@ public static final class Builder {
private Function<VaultInvoker.Builder, VaultInvoker.Builder> vault = Function.identity();
private VaultInvoker invoker;
private EnvironmentLoader environmentLoader = VaultInvoker.Builder.ENVIRONMENT_LOADER;
private String secretsPath;
private List<String> secretsPaths = new ArrayList<>();

private Builder() {}

public Builder secretsPath(String secretsPath) {
this.secretsPath = secretsPath;
this.secretsPaths.add(secretsPath);
return this;
}

Expand Down Expand Up @@ -126,13 +134,13 @@ public VaultConfigSource build() {
invoker != null
? invoker
: vault.apply(new VaultInvoker.Builder(environmentLoader)).build();
secretsPath =
Objects.requireNonNull(
secretsPath != null
? secretsPath
: environmentLoader.loadVariable(VAULT_SECRETS_PATH),
"Missing secretsPath");
return new VaultConfigSource(vaultInvoker, secretsPath);
if (secretsPaths.isEmpty()) {
String envSecretPath = Objects
.requireNonNull(environmentLoader.loadVariable(VAULT_SECRETS_PATH),
"Missing secretsPath");
secretsPaths = Arrays.asList(envSecretPath.split(":"));
}
return new VaultConfigSource(vaultInvoker, secretsPaths);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@ class VaultConfigSourceTest {
static void beforeAll() {
VaultInstance vaultInstance = vaultContainerExtension.vaultInstance();
vaultInstance.putSecrets(
VAULT_SECRETS_PATH1, "top_secret=password1", "db_password=dbpassword1");
VAULT_SECRETS_PATH1, "top_secret=password1", "db_password=dbpassword1", "only_first=pss1");
vaultInstance.putSecrets(
VAULT_SECRETS_PATH2, "top_secret=password2", "db_password=dbpassword2");
VAULT_SECRETS_PATH2, "top_secret=password2", "db_password=dbpassword2", "only_second=pss2");
vaultInstance.putSecrets(VAULT_SECRETS_PATH3, "secret=password", "password=dbpassword");
}

Expand Down Expand Up @@ -88,6 +88,31 @@ void testSecondTenant() {
assertThat(actual.valueAsString(""), equalTo("password2"));
}

@Test
void testMultiplePathsEnv() {
String commonPath = VAULT_SECRETS_PATH1 + ":" + VAULT_SECRETS_PATH2;
EnvironmentLoader multiLoader =
new MockEnvironmentLoader(baseLoader).put(VAULT_SECRETS_PATH, commonPath);
VaultConfigSource vaultConfigSource = VaultConfigSource.builder(multiLoader).build();
Map<String, ConfigProperty> loadConfig = vaultConfigSource.loadConfig();

ConfigProperty commonSecret = loadConfig.get("top_secret");
assertThat(commonSecret, notNullValue());
assertThat(commonSecret.name(), equalTo("top_secret"));
assertThat("Second path should override the first one", commonSecret.valueAsString(""),
equalTo("password2"));

ConfigProperty fromFirstPath = loadConfig.get("only_first");
assertThat(fromFirstPath.name(), equalTo("only_first"));
assertThat("Secret defined only in first path expected", fromFirstPath.valueAsString(""),
equalTo("pss1"));

ConfigProperty fromSecondPath = loadConfig.get("only_second");
assertThat(fromSecondPath.name(), equalTo("only_second"));
assertThat("Secret defined only in second path expected", fromSecondPath.valueAsString(""),
equalTo("pss2"));
}

@Test
void testMissingProperty() {
VaultConfigSource vaultConfigSource = VaultConfigSource.builder(loader3).build();
Expand Down

0 comments on commit 30e36c3

Please sign in to comment.