-
Notifications
You must be signed in to change notification settings - Fork 119
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Secret type to represent secrets and integrate with the secrets handling
- Loading branch information
Showing
8 changed files
with
212 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
53 changes: 53 additions & 0 deletions
53
implementation/src/main/java/io/smallrye/config/Secret.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
package io.smallrye.config; | ||
|
||
import java.util.Arrays; | ||
|
||
import javax.security.auth.Destroyable; | ||
|
||
import org.eclipse.microprofile.config.spi.Converter; | ||
|
||
public interface Secret extends Destroyable { | ||
|
||
char[] get(); | ||
|
||
// TODO - Does it make sense to have a method like this? | ||
default char[] getAndDestroy() { | ||
throw new UnsupportedOperationException(); | ||
} | ||
|
||
class PlainSecret implements Secret { | ||
private char[] secret; | ||
|
||
public PlainSecret(final char[] secret) { | ||
this.secret = secret; | ||
} | ||
|
||
@Override | ||
public char[] get() { | ||
return secret.clone(); | ||
} | ||
|
||
@Override | ||
public void destroy() { | ||
final char[] secret = this.secret; | ||
this.secret = null; | ||
if (secret != null) { | ||
Arrays.fill(secret, '\0'); | ||
} | ||
} | ||
|
||
@Override | ||
public boolean isDestroyed() { | ||
return secret == null; | ||
} | ||
} | ||
|
||
final class SecretConverter implements Converter<Secret> { | ||
private static final long serialVersionUID = 3586679829566742841L; | ||
|
||
@Override | ||
public Secret convert(final String value) throws IllegalArgumentException, NullPointerException { | ||
return new PlainSecret(value.toCharArray()); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
74 changes: 74 additions & 0 deletions
74
implementation/src/test/java/io/smallrye/config/ConfigMappingSecretsTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
package io.smallrye.config; | ||
|
||
import static io.smallrye.config.KeyValuesConfigSource.config; | ||
import static java.util.stream.Collectors.toSet; | ||
import static java.util.stream.StreamSupport.stream; | ||
import static org.junit.jupiter.api.Assertions.assertArrayEquals; | ||
import static org.junit.jupiter.api.Assertions.assertFalse; | ||
import static org.junit.jupiter.api.Assertions.assertThrows; | ||
|
||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.Set; | ||
|
||
import org.eclipse.microprofile.config.spi.Converter; | ||
import org.junit.jupiter.api.Test; | ||
|
||
import io.smallrye.config.Secret.PlainSecret; | ||
|
||
class ConfigMappingSecretsTest { | ||
@Test | ||
void secrets() throws Exception { | ||
SmallRyeConfig config = new SmallRyeConfigBuilder() | ||
.addDefaultInterceptors() | ||
// TODO - Converter must be available by default | ||
.withConverter(Secret.class, 100, Converters.newEmptyValueConverter(new Secret.SecretConverter())) | ||
.withConverter(PlainSecret.class, 100, Converters.newEmptyValueConverter(new Converter<>() { | ||
final Secret.SecretConverter secretConverter = new PlainSecret.SecretConverter(); | ||
|
||
@Override | ||
public PlainSecret convert(final String value) throws IllegalArgumentException, NullPointerException { | ||
return (PlainSecret) secretConverter.convert(value); | ||
} | ||
})) | ||
.withMapping(MappingSecrets.class) | ||
.withSources(config( | ||
"secrets.secret", "secret", | ||
"secrets.plain-secret", "plain", | ||
"secrets.secrets[0]", "secret", | ||
"secrets.secret-map.key", "secret")) | ||
.withSecretKeys() | ||
.build(); | ||
|
||
MappingSecrets mapping = config.getConfigMapping(MappingSecrets.class); | ||
assertArrayEquals("secret".toCharArray(), mapping.secret().get()); | ||
assertArrayEquals("plain".toCharArray(), mapping.plainSecret().get()); | ||
assertArrayEquals("secret".toCharArray(), mapping.secrets().get(0).get()); | ||
assertArrayEquals("secret".toCharArray(), mapping.secretMap().get("key").get()); | ||
|
||
assertThrows(SecurityException.class, () -> config.getRawValue("secrets.secret")); | ||
assertThrows(SecurityException.class, () -> config.getRawValue("secrets.plain-secret")); | ||
assertThrows(SecurityException.class, () -> config.getRawValue("secrets.secrets[0]")); | ||
assertThrows(SecurityException.class, () -> config.getRawValue("secrets.secret-map.key")); | ||
|
||
// TODO - getPropertyNames is cached and is first accessed by mappings with secrets to populate. We may have to clear the cache after mapping is done | ||
Set<String> properties = stream(config.getPropertyNames().spliterator(), false).collect(toSet()); | ||
|
||
properties = stream(config.getLatestPropertyNames().spliterator(), false).collect(toSet()); | ||
assertFalse(properties.contains("secrets.secret")); | ||
assertFalse(properties.contains("secrets.plain-secret")); | ||
assertFalse(properties.contains("secrets.secrets[0]")); | ||
assertFalse(properties.contains("secrets.secret-map.key")); | ||
} | ||
|
||
@ConfigMapping(prefix = "secrets") | ||
interface MappingSecrets { | ||
Secret secret(); | ||
|
||
PlainSecret plainSecret(); | ||
|
||
List<Secret> secrets(); | ||
|
||
Map<String, Secret> secretMap(); | ||
} | ||
} |