Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow loading secret keys in mappings #775

Merged
merged 1 commit into from
Jul 5, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -790,7 +790,7 @@ void mapConfiguration(SmallRyeConfig config) throws ConfigValidationException {
}

config.addPropertyNames(additionalMappedProperties(new HashSet<>(getProperties().keySet()), config));
mapConfiguration(config, config.getConfigMappings());
SecretKeys.doUnlocked(() -> mapConfiguration(config, config.getConfigMappings()));
}

private void mapConfiguration(SmallRyeConfig config, ConfigMappings mappings) throws ConfigValidationException {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package io.smallrye.config;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import javax.annotation.Priority;
Expand All @@ -22,6 +24,38 @@ public ConfigValue getValue(final ConfigSourceInterceptorContext context, final
return context.proceed(name);
}

@Override
public Iterator<String> iterateNames(final ConfigSourceInterceptorContext context) {
if (SecretKeys.isLocked()) {
Set<String> names = new HashSet<>();
Iterator<String> namesIterator = context.iterateNames();
while (namesIterator.hasNext()) {
String name = namesIterator.next();
if (!secrets.contains(name)) {
names.add(name);
}
}
return names.iterator();
}
return context.iterateNames();
}

@Override
public Iterator<ConfigValue> iterateValues(final ConfigSourceInterceptorContext context) {
if (SecretKeys.isLocked()) {
Set<ConfigValue> values = new HashSet<>();
Iterator<ConfigValue> valuesIterator = context.iterateValues();
while (valuesIterator.hasNext()) {
ConfigValue value = valuesIterator.next();
if (!secrets.contains(value.getName())) {
values.add(value);
}
}
return values.iterator();
}
return context.iterateValues();
}

private boolean isSecret(final String name) {
return secrets.contains(name);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,35 +1,50 @@
package io.smallrye.config;

import static java.util.stream.Collectors.toSet;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.util.Set;
import java.util.stream.StreamSupport;

import org.eclipse.microprofile.config.Config;
import org.junit.jupiter.api.Test;

class SecretKeysTest {
@Test
void lock() {
final Config config = buildConfig("secret", "12345678", "not.secret", "value");
Config config = buildConfig("secret", "12345678", "not.secret", "value");

assertThrows(SecurityException.class, () -> config.getValue("secret", String.class),
"Not allowed to access secret key secret");
assertEquals("value", config.getValue("not.secret", String.class));

Set<String> properties = StreamSupport.stream(config.getPropertyNames().spliterator(), false).collect(toSet());
assertFalse(properties.contains("secret"));
assertTrue(properties.contains("not.secret"));
}

@Test
void unlock() {
final Config config = buildConfig("secret", "12345678", "not.secret", "value");
Config config = buildConfig("secret", "12345678", "not.secret", "value");

SecretKeys.doUnlocked(() -> assertEquals("12345678", config.getValue("secret", String.class)));
assertEquals("12345678", SecretKeys.doUnlocked(() -> config.getValue("secret", String.class)));

assertThrows(SecurityException.class, () -> config.getValue("secret", String.class),
"Not allowed to access secret key secret");

Set<String> properties = SecretKeys
.doUnlocked(() -> StreamSupport.stream(config.getPropertyNames().spliterator(), false).collect(toSet()));
assertTrue(properties.contains("secret"));
assertTrue(properties.contains("not.secret"));
}

@Test
void unlockAndLock() {
final Config config = buildConfig("secret", "12345678", "not.secret", "value");
Config config = buildConfig("secret", "12345678", "not.secret", "value");

SecretKeys.doUnlocked(() -> {
assertEquals("12345678", config.getValue("secret", String.class));
Expand All @@ -45,7 +60,7 @@ void unlockAndLock() {

@Test
void lockAndUnlock() {
final Config config = buildConfig("secret", "12345678", "not.secret", "value");
Config config = buildConfig("secret", "12345678", "not.secret", "value");

SecretKeys.doLocked(() -> {
assertThrows(SecurityException.class, () -> config.getValue("secret", String.class),
Expand All @@ -55,6 +70,26 @@ void lockAndUnlock() {
});
}

@ConfigMapping(prefix = "mapping")
interface MappingSecret {
String secret();
}

@Test
void mapping() {
SmallRyeConfig config = new SmallRyeConfigBuilder()
.addDefaultInterceptors()
.withMapping(MappingSecret.class)
.withSources(KeyValuesConfigSource.config("mapping.secret", "secret"))
.withSecretKeys("mapping.secret")
.build();

MappingSecret mapping = config.getConfigMapping(MappingSecret.class);
assertEquals("secret", mapping.secret());
assertThrows(SecurityException.class, () -> config.getRawValue("mapping.secret"),
"Not allowed to access secret key mapping.secret");
}

private static Config buildConfig(String... keyValues) {
return new SmallRyeConfigBuilder()
.addDefaultSources()
Expand Down