Skip to content

Commit 2013a99

Browse files
authored
Secret type to represent secrets and integrate with the Secret Keys handling (#1232)
1 parent 9c3d0c9 commit 2013a99

18 files changed

Lines changed: 725 additions & 101 deletions

documentation/src/main/docs/config/mappings.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -597,6 +597,28 @@ Map<String, Alias> any = server.aliases.get("prod");
597597
- A mapping can wrap any complex type with an `Optional`
598598
- `Optional` mappings do not require the configuration path and value to be present
599599

600+
## Secrets
601+
602+
- A mapping can mark a member type as a secret with `Secret<T>`:
603+
604+
```java
605+
@ConfigMapping(prefix = "credentials")
606+
public interface Credentials {
607+
String username();
608+
609+
Secret<String> password();
610+
}
611+
```
612+
613+
A `Secret` value modifies the behaviour of the config system by:
614+
615+
- Omitting the name of the secret in `SmallRyeConfig#getPropertyNames()`
616+
- Omitting the name and value of the secret in the mapping `toString` method
617+
- Throwing a `SecurityException` when trying to retrieve the value via `SmallRyeConfig` programmatic API
618+
619+
A Secret can be of any type that can be converted by a registered `org.eclipse.microprofile.config.spi.Converter` of
620+
the same type.
621+
600622
## toString, equals, hashcode
601623

602624
If the config mapping contains a `toString` method declaration, the config mapping instance will include a proper

implementation/src/main/java/io/smallrye/config/ConfigMappingContext.java

Lines changed: 127 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import static io.smallrye.config.ConfigMappingLoader.configMappingProperties;
44
import static io.smallrye.config.ConfigMappingLoader.getConfigMappingClass;
55
import static io.smallrye.config.ConfigValidationException.Problem;
6+
import static io.smallrye.config.Converters.newSecretConverter;
67
import static io.smallrye.config.common.utils.StringUtil.unindexed;
78

89
import java.io.Serial;
@@ -519,8 +520,24 @@ public static <V> V value(
519520
final String propertyName,
520521
final Class<V> valueRawType,
521522
final Class<? extends Converter<V>> valueConvertWith) {
523+
return convertValue(context, propertyName, getConverter(context, valueRawType, valueConvertWith));
524+
}
525+
526+
@SuppressWarnings("unused")
527+
public static <V> Secret<V> secretValue(
528+
final ConfigMappingContext context,
529+
final String propertyName,
530+
final Class<V> valueRawType,
531+
final Class<? extends Converter<V>> valueConvertWith) {
532+
Converter<Secret<V>> valueConverter = newSecretConverter(getConverter(context, valueRawType, valueConvertWith));
533+
return convertValue(context, propertyName, valueConverter);
534+
}
535+
536+
private static <V> V convertValue(
537+
final ConfigMappingContext context,
538+
final String propertyName,
539+
final Converter<V> valueConverter) {
522540
context.usedProperties.add(propertyName);
523-
Converter<V> valueConverter = getConverter(context, valueRawType, valueConvertWith);
524541
return context.config.getValue(propertyName, valueConverter);
525542
}
526543

@@ -543,8 +560,25 @@ public static <V> Optional<V> optionalValue(
543560
final String propertyName,
544561
final Class<V> valueRawType,
545562
final Class<? extends Converter<V>> valueConvertWith) {
563+
return convertOptionalValue(context, propertyName, getConverter(context, valueRawType, valueConvertWith));
564+
}
565+
566+
@SuppressWarnings("unused")
567+
public static <V> Optional<Secret<V>> optionalSecretValue(
568+
final ConfigMappingContext context,
569+
final String propertyName,
570+
final Class<V> valueRawType,
571+
final Class<? extends Converter<V>> valueConvertWith) {
572+
Converter<Optional<Secret<V>>> valueConverter = Converters
573+
.newOptionalConverter(newSecretConverter(getConverter(context, valueRawType, valueConvertWith)));
574+
return convertValue(context, propertyName, valueConverter);
575+
}
576+
577+
private static <V> Optional<V> convertOptionalValue(
578+
final ConfigMappingContext context,
579+
final String propertyName,
580+
final Converter<V> valueConverter) {
546581
context.usedProperties.add(propertyName);
547-
Converter<V> valueConverter = getConverter(context, valueRawType, valueConvertWith);
548582
return context.config.getOptionalValue(propertyName, valueConverter);
549583
}
550584

@@ -568,9 +602,28 @@ public static <V, C extends Collection<V>> C values(
568602
final Class<V> itemRawType,
569603
final Class<? extends Converter<V>> itemConvertWith,
570604
final Class<C> collectionRawType) {
605+
Converter<V> itemConverter = getConverter(context, itemRawType, itemConvertWith);
606+
return convertValues(context, propertyName, itemConverter, collectionRawType);
607+
}
608+
609+
@SuppressWarnings("unused")
610+
public static <V, C extends Collection<Secret<V>>> C secretValues(
611+
final ConfigMappingContext context,
612+
final String propertyName,
613+
final Class<V> itemRawType,
614+
final Class<? extends Converter<V>> itemConvertWith,
615+
final Class<C> collectionRawType) {
616+
Converter<Secret<V>> itemConverter = newSecretConverter(getConverter(context, itemRawType, itemConvertWith));
617+
return convertValues(context, propertyName, itemConverter, collectionRawType);
618+
}
619+
620+
public static <V, C extends Collection<V>> C convertValues(
621+
final ConfigMappingContext context,
622+
final String propertyName,
623+
final Converter<V> itemConverter,
624+
final Class<C> collectionRawType) {
571625
context.usedProperties.add(propertyName);
572626
context.usedProperties.addAll(context.config.getIndexedProperties(propertyName));
573-
Converter<V> itemConverter = getConverter(context, itemRawType, itemConvertWith);
574627
IntFunction<C> collectionFactory = (IntFunction<C>) createCollectionFactory(collectionRawType);
575628
return context.config.getValues(propertyName, itemConverter, collectionFactory);
576629
}
@@ -596,9 +649,28 @@ public static <V, C extends Collection<V>> Optional<C> optionalValues(
596649
final Class<V> itemRawType,
597650
final Class<? extends Converter<V>> itemConvertWith,
598651
final Class<C> collectionRawType) {
652+
Converter<V> itemConverter = getConverter(context, itemRawType, itemConvertWith);
653+
return convertOptionalValues(context, propertyName, itemConverter, collectionRawType);
654+
}
655+
656+
@SuppressWarnings("unused")
657+
public static <V, C extends Collection<Secret<V>>> Optional<C> optionalSecretValues(
658+
final ConfigMappingContext context,
659+
final String propertyName,
660+
final Class<V> itemRawType,
661+
final Class<? extends Converter<V>> itemConvertWith,
662+
final Class<C> collectionRawType) {
663+
Converter<Secret<V>> itemConverter = newSecretConverter(getConverter(context, itemRawType, itemConvertWith));
664+
return convertOptionalValues(context, propertyName, itemConverter, collectionRawType);
665+
}
666+
667+
public static <V, C extends Collection<V>> Optional<C> convertOptionalValues(
668+
final ConfigMappingContext context,
669+
final String propertyName,
670+
final Converter<V> itemConverter,
671+
final Class<C> collectionRawType) {
599672
context.usedProperties.add(propertyName);
600673
context.usedProperties.addAll(context.config.getIndexedProperties(propertyName));
601-
Converter<V> itemConverter = getConverter(context, itemRawType, itemConvertWith);
602674
IntFunction<C> collectionFactory = (IntFunction<C>) createCollectionFactory(collectionRawType);
603675
return context.config.getOptionalValues(propertyName, itemConverter, collectionFactory);
604676
}
@@ -628,9 +700,33 @@ public static <K, V> Map<K, V> values(
628700
final Class<? extends Converter<V>> valueConvertWith,
629701
final Iterable<String> keys,
630702
final String defaultValue) {
631-
632703
Converter<K> keyConverter = getConverter(context, keyRawType, keyConvertWith);
633704
Converter<V> valueConverter = getConverter(context, valueRawType, valueConvertWith);
705+
return convertValues(context, propertyName, keyConverter, valueConverter, keys, defaultValue);
706+
}
707+
708+
@SuppressWarnings("unused")
709+
public static <K, V> Map<K, Secret<V>> secretValues(
710+
final ConfigMappingContext context,
711+
final String propertyName,
712+
final Class<K> keyRawType,
713+
final Class<? extends Converter<K>> keyConvertWith,
714+
final Class<V> valueRawType,
715+
final Class<? extends Converter<V>> valueConvertWith,
716+
final Iterable<String> keys,
717+
final String defaultValue) {
718+
Converter<K> keyConverter = getConverter(context, keyRawType, keyConvertWith);
719+
Converter<Secret<V>> valueConverter = newSecretConverter(getConverter(context, valueRawType, valueConvertWith));
720+
return convertValues(context, propertyName, keyConverter, valueConverter, keys, defaultValue);
721+
}
722+
723+
public static <K, V> Map<K, V> convertValues(
724+
final ConfigMappingContext context,
725+
final String propertyName,
726+
final Converter<K> keyConverter,
727+
final Converter<V> valueConverter,
728+
final Iterable<String> keys,
729+
final String defaultValue) {
634730

635731
Map<String, String> mapKeys = new HashMap<>();
636732
if (keys != null) {
@@ -693,9 +789,34 @@ public static <K, V, C extends Collection<V>> Map<K, C> values(
693789
final Class<C> collectionRawType,
694790
final Iterable<String> keys,
695791
final String defaultValue) {
696-
697792
Converter<K> keyConverter = getConverter(context, keyRawType, keyConvertWith);
698793
Converter<V> valueConverter = getConverter(context, valueRawType, valueConvertWith);
794+
return convertValues(context, propertyName, keyConverter, valueConverter, collectionRawType, keys, defaultValue);
795+
}
796+
797+
public static <K, V, C extends Collection<Secret<V>>> Map<K, C> secretValues(
798+
final ConfigMappingContext context,
799+
final String propertyName,
800+
final Class<K> keyRawType,
801+
final Class<? extends Converter<K>> keyConvertWith,
802+
final Class<V> valueRawType,
803+
final Class<? extends Converter<V>> valueConvertWith,
804+
final Class<C> collectionRawType,
805+
final Iterable<String> keys,
806+
final String defaultValue) {
807+
Converter<K> keyConverter = getConverter(context, keyRawType, keyConvertWith);
808+
Converter<Secret<V>> valueConverter = newSecretConverter(getConverter(context, valueRawType, valueConvertWith));
809+
return convertValues(context, propertyName, keyConverter, valueConverter, collectionRawType, keys, defaultValue);
810+
}
811+
812+
public static <K, V, C extends Collection<V>> Map<K, C> convertValues(
813+
final ConfigMappingContext context,
814+
final String propertyName,
815+
final Converter<K> keyConverter,
816+
final Converter<V> valueConverter,
817+
final Class<C> collectionRawType,
818+
final Iterable<String> keys,
819+
final String defaultValue) {
699820

700821
Map<String, String> mapKeys = new HashMap<>();
701822
if (keys != null) {

0 commit comments

Comments
 (0)