diff --git a/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProvider.java b/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProvider.java index 9087c1ad6..e4bd2702f 100644 --- a/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProvider.java +++ b/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProvider.java @@ -17,9 +17,15 @@ import static java.nio.charset.StandardCharsets.UTF_8; import java.util.Base64; +import java.util.List; import java.util.Map; +import java.util.Collections; +import java.util.stream.Collectors; import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient; +import software.amazon.awssdk.services.secretsmanager.model.Filter; import software.amazon.awssdk.services.secretsmanager.model.GetSecretValueRequest; +import software.amazon.awssdk.services.secretsmanager.model.BatchGetSecretValueRequest; +import software.amazon.awssdk.services.secretsmanager.model.SecretValueEntry; import software.amazon.lambda.powertools.parameters.BaseProvider; import software.amazon.lambda.powertools.parameters.cache.CacheManager; import software.amazon.lambda.powertools.parameters.transform.TransformationManager; @@ -103,9 +109,28 @@ protected String getValue(String key) { */ @Override protected Map getMultipleValues(String path) { - throw new UnsupportedOperationException("Impossible to get multiple values from AWS Secrets Manager"); + throw new UnsupportedOperationException("Impossible to get multiple values from AWS Secrets Manager via path. Use getMultiple(List names) instead."); } + public Map getMultiple(List names){ + BatchGetSecretValueRequest request = BatchGetSecretValueRequest.builder() + .secretIdList(Collections.emptyList()) + .filters(Filter.builder() + .key("name") + .values(names) + .build()) + .build(); + return client.batchGetSecretValue(request).secretValues().stream() + .collect(Collectors.toMap(SecretValueEntry::name, entry -> { + String secretValue = entry.secretString(); + if (secretValue == null) { + secretValue = + new String(Base64.getDecoder().decode(entry.secretBinary().asByteArray()), + UTF_8); + } + return secretValue; + })); + } // For test purpose only SecretsManagerClient getClient() { diff --git a/powertools-parameters/powertools-parameters-secrets/src/test/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProviderTest.java b/powertools-parameters/powertools-parameters-secrets/src/test/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProviderTest.java index a6fbe1c8e..76e0ab6eb 100644 --- a/powertools-parameters/powertools-parameters-secrets/src/test/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProviderTest.java +++ b/powertools-parameters/powertools-parameters-secrets/src/test/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProviderTest.java @@ -23,6 +23,8 @@ import java.time.temporal.ChronoUnit; import java.util.Base64; +import java.util.List; +import java.util.Map; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -34,8 +36,12 @@ import software.amazon.awssdk.core.SdkBytes; import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient; +import software.amazon.awssdk.services.secretsmanager.model.BatchGetSecretValueRequest; +import software.amazon.awssdk.services.secretsmanager.model.BatchGetSecretValueResponse; +import software.amazon.awssdk.services.secretsmanager.model.Filter; import software.amazon.awssdk.services.secretsmanager.model.GetSecretValueRequest; import software.amazon.awssdk.services.secretsmanager.model.GetSecretValueResponse; +import software.amazon.awssdk.services.secretsmanager.model.SecretValueEntry; import software.amazon.lambda.powertools.parameters.cache.CacheManager; import software.amazon.lambda.powertools.parameters.transform.TransformationManager; @@ -51,6 +57,9 @@ class SecretsProviderTest { @Captor ArgumentCaptor paramCaptor; + @Captor + ArgumentCaptor batchCaptor; + CacheManager cacheManager; SecretsProvider provider; @@ -94,7 +103,47 @@ void getValueBase64() { void getMultipleValuesThrowsException() { // Act & Assert assertThatRuntimeException().isThrownBy(() -> provider.getMultipleValues("path")) - .withMessage("Impossible to get multiple values from AWS Secrets Manager"); + .withMessage("Impossible to get multiple values from AWS Secrets Manager via path. Use getMultiple(List names) instead."); + } + @Test + void getMultipleValues() { + List names = List.of("name1", "name2"); + String value1 = "Value1"; + String value2 = "Value2"; + + SecretValueEntry entry1 = + SecretValueEntry.builder() + .name("name1") + .secretString(value1) + .build(); + + byte[] value2b64 = Base64.getEncoder().encode(value2.getBytes()); + SecretValueEntry entry2 = + SecretValueEntry.builder() + .name("name2") + .secretBinary(SdkBytes.fromByteArray(value2b64)) + .build(); + + BatchGetSecretValueResponse response = + BatchGetSecretValueResponse.builder() + .secretValues(entry1, entry2) + .build(); + + Mockito.when(client.batchGetSecretValue(batchCaptor.capture())).thenReturn(response); + + Map result = provider.getMultiple(names); + + assertThat(result).hasSize(2) + .containsEntry("name1", value1) + .containsEntry("name2", value2); + + BatchGetSecretValueRequest captured = batchCaptor.getValue(); + assertThat(captured.secretIdList()).isEmpty(); + assertThat(captured.filters()).hasSize(1); + + Filter filter = captured.filters().get(0); + assertThat(filter.key().toString()).isEqualTo("name"); + assertThat(filter.values()).isEqualTo(names); } @Test