This is an automated email from the ASF dual-hosted git repository.

exceptionfactory pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/nifi.git


The following commit(s) were added to refs/heads/main by this push:
     new c55be0dcd1 NIFI-15556 Add support for Parameter Tags to AWS Secrets 
Manager Parameter Provider (#10859)
c55be0dcd1 is described below

commit c55be0dcd1a0b765af8d261fd4e38c8096b734cf
Author: Pierre Villard <[email protected]>
AuthorDate: Thu Feb 5 22:47:01 2026 +0100

    NIFI-15556 Add support for Parameter Tags to AWS Secrets Manager Parameter 
Provider (#10859)
    
    Signed-off-by: David Handermann <[email protected]>
---
 .../aws/AwsSecretsManagerParameterProvider.java    |  78 +++++--
 .../TestAwsSecretsManagerParameterProvider.java    | 237 +++++++++++++++++----
 2 files changed, 266 insertions(+), 49 deletions(-)

diff --git 
a/nifi-extension-bundles/nifi-aws-bundle/nifi-aws-parameter-providers/src/main/java/org/apache/nifi/parameter/aws/AwsSecretsManagerParameterProvider.java
 
b/nifi-extension-bundles/nifi-aws-bundle/nifi-aws-parameter-providers/src/main/java/org/apache/nifi/parameter/aws/AwsSecretsManagerParameterProvider.java
index f5afd3536f..c962ca511d 100644
--- 
a/nifi-extension-bundles/nifi-aws-bundle/nifi-aws-parameter-providers/src/main/java/org/apache/nifi/parameter/aws/AwsSecretsManagerParameterProvider.java
+++ 
b/nifi-extension-bundles/nifi-aws-bundle/nifi-aws-parameter-providers/src/main/java/org/apache/nifi/parameter/aws/AwsSecretsManagerParameterProvider.java
@@ -31,6 +31,7 @@ import org.apache.nifi.logging.ComponentLog;
 import org.apache.nifi.parameter.AbstractParameterProvider;
 import org.apache.nifi.parameter.Parameter;
 import org.apache.nifi.parameter.ParameterGroup;
+import org.apache.nifi.parameter.ParameterTag;
 import org.apache.nifi.parameter.VerifiableParameterProvider;
 import org.apache.nifi.processor.util.StandardValidators;
 import 
org.apache.nifi.processors.aws.credentials.provider.AwsCredentialsProviderService;
@@ -45,6 +46,8 @@ import software.amazon.awssdk.http.apache.ApacheHttpClient;
 import software.amazon.awssdk.regions.Region;
 import software.amazon.awssdk.retries.DefaultRetryStrategy;
 import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient;
+import 
software.amazon.awssdk.services.secretsmanager.model.DescribeSecretRequest;
+import 
software.amazon.awssdk.services.secretsmanager.model.DescribeSecretResponse;
 import 
software.amazon.awssdk.services.secretsmanager.model.GetSecretValueRequest;
 import 
software.amazon.awssdk.services.secretsmanager.model.GetSecretValueResponse;
 import software.amazon.awssdk.services.secretsmanager.model.ListSecretsRequest;
@@ -52,16 +55,15 @@ import 
software.amazon.awssdk.services.secretsmanager.model.ListSecretsResponse;
 import 
software.amazon.awssdk.services.secretsmanager.model.ResourceNotFoundException;
 import software.amazon.awssdk.services.secretsmanager.model.SecretListEntry;
 import 
software.amazon.awssdk.services.secretsmanager.model.SecretsManagerException;
+import software.amazon.awssdk.services.secretsmanager.model.Tag;
 
 import java.time.Duration;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Comparator;
-import java.util.HashSet;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
-import java.util.Set;
 import java.util.regex.Pattern;
 import javax.net.ssl.KeyManager;
 import javax.net.ssl.TrustManager;
@@ -77,7 +79,7 @@ import javax.net.ssl.X509TrustManager;
         "key/value pairs in the secret mapping to Parameters in the group.")
 public class AwsSecretsManagerParameterProvider extends 
AbstractParameterProvider implements VerifiableParameterProvider {
     enum ListingStrategy implements DescribedValue {
-        ENUMERATION("Enumerate Secret Names", "Requires a set of secret names 
to fetch. AWS actions required: GetSecretValue."),
+        ENUMERATION("Enumerate Secret Names", "Requires a set of secret names 
to fetch. AWS actions required: DescribeSecret and GetSecretValue."),
 
         PATTERN("Match Pattern", "Requires a regular expression pattern to 
match secret names. AWS actions required: ListSecrets and GetSecretValue.");
 
@@ -196,10 +198,16 @@ public class AwsSecretsManagerParameterProvider extends 
AbstractParameterProvide
 
         // Fetch either by pattern or by enumerated list. See description of 
SECRET_LISTING_STRATEGY for more details.
         final ListingStrategy listingStrategy = 
context.getProperty(SECRET_LISTING_STRATEGY).asAllowableValue(ListingStrategy.class);
-        final Set<String> fetchSecretNames = new HashSet<>();
+        final Map<String, List<Tag>> secretNameToTags = new HashMap<>();
+
         if (listingStrategy == ListingStrategy.ENUMERATION) {
             final String secretNames = 
context.getProperty(SECRET_NAMES).getValue();
-            fetchSecretNames.addAll(Arrays.asList(secretNames.split(",")));
+            for (final String secretName : secretNames.split(",")) {
+                final String trimmedName = secretName.trim();
+                // For enumeration strategy, we need to call DescribeSecret to 
get tags
+                final List<Tag> tags = describeSecretTags(secretsManager, 
trimmedName);
+                secretNameToTags.put(trimmedName, tags);
+            }
         } else {
             final Pattern secretNamePattern = 
Pattern.compile(context.getProperty(SECRET_NAME_PATTERN).getValue());
 
@@ -212,7 +220,9 @@ public class AwsSecretsManagerParameterProvider extends 
AbstractParameterProvide
                         getLogger().debug("Secret [{}] does not match the 
secret name pattern {}", secretName, secretNamePattern);
                         continue;
                     }
-                    fetchSecretNames.add(secretName);
+                    // ListSecrets response includes tags, so we can use them 
directly
+                    final List<Tag> tags = entry.hasTags() ? entry.tags() : 
List.of();
+                    secretNameToTags.put(secretName, tags);
                 }
                 final String nextToken = listSecretsResponse.nextToken();
                 if (nextToken == null) {
@@ -223,8 +233,10 @@ public class AwsSecretsManagerParameterProvider extends 
AbstractParameterProvide
             }
         }
 
-        for (final String secretName : fetchSecretNames) {
-            final List<ParameterGroup> secretParameterGroups = 
fetchSecret(secretsManager, secretName);
+        for (final Map.Entry<String, List<Tag>> entry : 
secretNameToTags.entrySet()) {
+            final String secretName = entry.getKey();
+            final List<ParameterTag> parameterTags = 
convertTags(entry.getValue());
+            final List<ParameterGroup> secretParameterGroups = 
fetchSecret(secretsManager, secretName, parameterTags);
             groups.addAll(secretParameterGroups);
         }
         return groups;
@@ -257,7 +269,8 @@ public class AwsSecretsManagerParameterProvider extends 
AbstractParameterProvide
         return results;
     }
 
-    private List<ParameterGroup> fetchSecret(final SecretsManagerClient 
secretsManager, final String secretName) {
+    private List<ParameterGroup> fetchSecret(final SecretsManagerClient 
secretsManager, final String secretName,
+                                              final List<ParameterTag> tags) {
         final List<ParameterGroup> groups = new ArrayList<>();
 
         final List<Parameter> parameters = new ArrayList<>();
@@ -289,7 +302,7 @@ public class AwsSecretsManagerParameterProvider extends 
AbstractParameterProvide
                 }
                 final String parameterValue = valueNode.asText();
 
-                parameters.add(createParameter(parameterName, parameterValue));
+                parameters.add(createParameter(parameterName, parameterValue, 
tags));
             }
 
             groups.add(new ParameterGroup(secretName, parameters));
@@ -302,14 +315,55 @@ public class AwsSecretsManagerParameterProvider extends 
AbstractParameterProvide
         }
     }
 
-    private Parameter createParameter(final String parameterName, final String 
parameterValue) {
+    private Parameter createParameter(final String parameterName, final String 
parameterValue,
+                                       final List<ParameterTag> tags) {
         return new Parameter.Builder()
                 .name(parameterName)
                 .value(parameterValue)
                 .provided(true)
+                .tags(tags)
                 .build();
     }
 
+    /**
+     * Retrieves tags for a secret using DescribeSecret API.
+     * This is needed for the ENUMERATION strategy since GetSecretValue does 
not return tags.
+     *
+     * @param secretsManager the Secrets Manager client
+     * @param secretName the name of the secret
+     * @return list of tags associated with the secret
+     */
+    private List<Tag> describeSecretTags(final SecretsManagerClient 
secretsManager, final String secretName) {
+        try {
+            final DescribeSecretRequest describeRequest = 
DescribeSecretRequest.builder()
+                    .secretId(secretName)
+                    .build();
+            final DescribeSecretResponse describeResponse = 
secretsManager.describeSecret(describeRequest);
+            return describeResponse.hasTags() ? describeResponse.tags() : 
List.of();
+        } catch (final ResourceNotFoundException e) {
+            getLogger().debug("Secret [{}] not found when describing for 
tags", secretName);
+            return List.of();
+        } catch (final SecretsManagerException e) {
+            getLogger().warn("Error describing secret [{}] for tags: {}", 
secretName, e.getMessage());
+            return List.of();
+        }
+    }
+
+    /**
+     * Converts AWS Secrets Manager Tags to NiFi ParameterTags.
+     *
+     * @param awsTags the AWS tags to convert
+     * @return list of NiFi ParameterTag objects
+     */
+    private List<ParameterTag> convertTags(final List<Tag> awsTags) {
+        if (awsTags == null || awsTags.isEmpty()) {
+            return List.of();
+        }
+        return awsTags.stream()
+                .map(tag -> new ParameterTag(tag.key(), tag.value()))
+                .toList();
+    }
+
     private ClientOverrideConfiguration createConfiguration() {
         return ClientOverrideConfiguration.builder()
                 .retryStrategy(DefaultRetryStrategy.doNotRetry())
diff --git 
a/nifi-extension-bundles/nifi-aws-bundle/nifi-aws-parameter-providers/src/test/java/org/apache/nifi/parameter/aws/TestAwsSecretsManagerParameterProvider.java
 
b/nifi-extension-bundles/nifi-aws-bundle/nifi-aws-parameter-providers/src/test/java/org/apache/nifi/parameter/aws/TestAwsSecretsManagerParameterProvider.java
index da913ffcf9..ab1e22c3af 100644
--- 
a/nifi-extension-bundles/nifi-aws-bundle/nifi-aws-parameter-providers/src/test/java/org/apache/nifi/parameter/aws/TestAwsSecretsManagerParameterProvider.java
+++ 
b/nifi-extension-bundles/nifi-aws-bundle/nifi-aws-parameter-providers/src/test/java/org/apache/nifi/parameter/aws/TestAwsSecretsManagerParameterProvider.java
@@ -22,6 +22,7 @@ import org.apache.nifi.components.ConfigVerificationResult;
 import org.apache.nifi.components.PropertyDescriptor;
 import org.apache.nifi.parameter.Parameter;
 import org.apache.nifi.parameter.ParameterGroup;
+import org.apache.nifi.parameter.ParameterTag;
 import org.apache.nifi.parameter.VerifiableParameterProvider;
 import org.apache.nifi.reporting.InitializationException;
 import org.apache.nifi.util.MockComponentLog;
@@ -33,6 +34,8 @@ import org.mockito.ArgumentMatcher;
 import org.mockito.Mock;
 import org.mockito.junit.jupiter.MockitoExtension;
 import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient;
+import 
software.amazon.awssdk.services.secretsmanager.model.DescribeSecretRequest;
+import 
software.amazon.awssdk.services.secretsmanager.model.DescribeSecretResponse;
 import 
software.amazon.awssdk.services.secretsmanager.model.GetSecretValueRequest;
 import 
software.amazon.awssdk.services.secretsmanager.model.GetSecretValueResponse;
 import software.amazon.awssdk.services.secretsmanager.model.ListSecretsRequest;
@@ -40,6 +43,7 @@ import 
software.amazon.awssdk.services.secretsmanager.model.ListSecretsResponse;
 import 
software.amazon.awssdk.services.secretsmanager.model.ResourceNotFoundException;
 import software.amazon.awssdk.services.secretsmanager.model.SecretListEntry;
 import 
software.amazon.awssdk.services.secretsmanager.model.SecretsManagerException;
+import software.amazon.awssdk.services.secretsmanager.model.Tag;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -90,12 +94,12 @@ public class TestAwsSecretsManagerParameterProvider {
     @Test
     public void testFetchParametersWithNoSecrets() throws 
InitializationException {
         final List<ParameterGroup> expectedGroups = 
Collections.singletonList(new ParameterGroup("MySecret", 
Collections.emptyList()));
-        runProviderTest(mockSecretsManager(expectedGroups), 0, 
ConfigVerificationResult.Outcome.SUCCESSFUL, "PATTERN", null);
+        runProviderTest(mockSecretsManagerWithTags(expectedGroups, 
Collections.emptyMap()), 0, ConfigVerificationResult.Outcome.SUCCESSFUL, 
"PATTERN", null);
     }
 
     @Test
     public void testFetchParameters() throws InitializationException {
-        runProviderTest(mockSecretsManager(mockParameterGroups), 8, 
ConfigVerificationResult.Outcome.SUCCESSFUL, "PATTERN", null);
+        runProviderTest(mockSecretsManagerWithTags(mockParameterGroups, 
Collections.emptyMap()), 8, ConfigVerificationResult.Outcome.SUCCESSFUL, 
"PATTERN", null);
     }
 
     @Test
@@ -110,7 +114,8 @@ public class TestAwsSecretsManagerParameterProvider {
 
     @Test
     public void testFetchNonExistentSecret() throws InitializationException {
-        
when(defaultSecretsManager.getSecretValue(argThat(matchesGetSecretValueRequest("MySecretDoesNotExist")))).thenThrow(ResourceNotFoundException.builder().message("Fake
 exception").build());
+        
when(defaultSecretsManager.describeSecret(argThat(matchesDescribeSecretRequest("BadSecret")))).thenThrow(ResourceNotFoundException.builder().message("Fake
 exception").build());
+        
when(defaultSecretsManager.getSecretValue(argThat(matchesGetSecretValueRequest("BadSecret")))).thenThrow(ResourceNotFoundException.builder().message("Fake
 exception").build());
         runProviderTest(defaultSecretsManager, 0, 
ConfigVerificationResult.Outcome.FAILED, "ENUMERATION", "BadSecret");
     }
 
@@ -142,6 +147,12 @@ public class TestAwsSecretsManagerParameterProvider {
                 .build();
         
when(secretsManager.getSecretValue(argThat(matchesGetSecretValueRequest("MixedSecret")))).thenReturn(response);
 
+        // Mock DescribeSecret for tags (returns empty tags)
+        final DescribeSecretResponse describeResponse = 
DescribeSecretResponse.builder()
+                .name("MixedSecret")
+                .build();
+        
when(secretsManager.describeSecret(argThat(matchesDescribeSecretRequest("MixedSecret")))).thenReturn(describeResponse);
+
         final List<ParameterGroup> parameterGroups = 
runProviderTest(secretsManager, 3, ConfigVerificationResult.Outcome.SUCCESSFUL, 
"ENUMERATION", "MixedSecret");
 
         assertEquals(1, parameterGroups.size());
@@ -170,6 +181,12 @@ public class TestAwsSecretsManagerParameterProvider {
                 .build();
         
when(secretsManager.getSecretValue(argThat(matchesGetSecretValueRequest("NestedSecret")))).thenReturn(response);
 
+        // Mock DescribeSecret for tags (returns empty tags)
+        final DescribeSecretResponse describeResponse = 
DescribeSecretResponse.builder()
+                .name("NestedSecret")
+                .build();
+        
when(secretsManager.describeSecret(argThat(matchesDescribeSecretRequest("NestedSecret")))).thenReturn(describeResponse);
+
         final List<ParameterGroup> parameterGroups = 
runProviderTest(secretsManager, 1, ConfigVerificationResult.Outcome.SUCCESSFUL, 
"ENUMERATION", "NestedSecret");
 
         assertEquals(1, parameterGroups.size());
@@ -183,6 +200,116 @@ public class TestAwsSecretsManagerParameterProvider {
         assertEquals("validValue", parameterValues.get("validParam"));
     }
 
+    @Test
+    public void testFetchParametersWithTagsPatternStrategy() throws 
InitializationException {
+        final List<Tag> secretTags = List.of(
+                Tag.builder().key("environment").value("production").build(),
+                Tag.builder().key("team").value("data-platform").build()
+        );
+
+        final SecretsManagerClient secretsManager = mockSecretsManagerWithTags(
+                List.of(new ParameterGroup("TaggedSecret", 
List.of(parameter("param1", "value1")))),
+                Map.of("TaggedSecret", secretTags)
+        );
+
+        final List<ParameterGroup> parameterGroups = 
runProviderTest(secretsManager, 1,
+                ConfigVerificationResult.Outcome.SUCCESSFUL, "PATTERN", null);
+
+        assertEquals(1, parameterGroups.size());
+        final ParameterGroup group = parameterGroups.get(0);
+        assertEquals("TaggedSecret", group.getGroupName());
+        assertEquals(1, group.getParameters().size());
+
+        final Parameter parameter = group.getParameters().get(0);
+        assertEquals("param1", parameter.getDescriptor().getName());
+        assertEquals("value1", parameter.getValue());
+
+        // Verify tags are present
+        final List<ParameterTag> tags = parameter.getTags();
+        assertEquals(2, tags.size());
+        assertEquals("environment", tags.get(0).getKey());
+        assertEquals("production", tags.get(0).getValue());
+        assertEquals("team", tags.get(1).getKey());
+        assertEquals("data-platform", tags.get(1).getValue());
+    }
+
+    @Test
+    public void testFetchParametersWithTagsEnumerationStrategy() throws 
InitializationException {
+        final List<Tag> secretTags = List.of(
+                Tag.builder().key("cost-center").value("12345").build()
+        );
+
+        final SecretsManagerClient secretsManager = 
mock(SecretsManagerClient.class);
+
+        // Mock GetSecretValue
+        final String secretString = "{ \"dbPassword\": \"secret123\" }";
+        final GetSecretValueResponse response = 
GetSecretValueResponse.builder()
+                .name("EnumeratedSecret")
+                .secretString(secretString)
+                .build();
+        
when(secretsManager.getSecretValue(argThat(matchesGetSecretValueRequest("EnumeratedSecret")))).thenReturn(response);
+
+        // Mock DescribeSecret to return tags
+        final DescribeSecretResponse describeResponse = 
DescribeSecretResponse.builder()
+                .name("EnumeratedSecret")
+                .tags(secretTags)
+                .build();
+        
when(secretsManager.describeSecret(argThat(matchesDescribeSecretRequest("EnumeratedSecret")))).thenReturn(describeResponse);
+
+        final List<ParameterGroup> parameterGroups = 
runProviderTest(secretsManager, 1,
+                ConfigVerificationResult.Outcome.SUCCESSFUL, "ENUMERATION", 
"EnumeratedSecret");
+
+        assertEquals(1, parameterGroups.size());
+        final Parameter parameter = 
parameterGroups.get(0).getParameters().get(0);
+        assertEquals("dbPassword", parameter.getDescriptor().getName());
+
+        // Verify tags are present
+        final List<ParameterTag> tags = parameter.getTags();
+        assertEquals(1, tags.size());
+        assertEquals("cost-center", tags.get(0).getKey());
+        assertEquals("12345", tags.get(0).getValue());
+    }
+
+    @Test
+    public void testFetchParametersWithMultipleSecretsAndTags() throws 
InitializationException {
+        final Map<String, List<Tag>> secretTagsMap = Map.of(
+                "Secret1", 
List.of(Tag.builder().key("app").value("app1").build()),
+                "Secret2", 
List.of(Tag.builder().key("app").value("app2").build(), 
Tag.builder().key("env").value("dev").build())
+        );
+
+        final List<ParameterGroup> mockGroups = List.of(
+                new ParameterGroup("Secret1", List.of(parameter("key1", 
"val1"))),
+                new ParameterGroup("Secret2", List.of(parameter("key2", 
"val2"), parameter("key3", "val3")))
+        );
+
+        final SecretsManagerClient secretsManager = 
mockSecretsManagerWithTags(mockGroups, secretTagsMap);
+
+        final List<ParameterGroup> parameterGroups = 
runProviderTest(secretsManager, 3,
+                ConfigVerificationResult.Outcome.SUCCESSFUL, "PATTERN", null);
+
+        assertEquals(2, parameterGroups.size());
+
+        // Find Secret1 group
+        final ParameterGroup secret1Group = parameterGroups.stream()
+                .filter(g -> "Secret1".equals(g.getGroupName()))
+                .findFirst()
+                .orElseThrow();
+        assertEquals(1, secret1Group.getParameters().size());
+        assertEquals(1, secret1Group.getParameters().get(0).getTags().size());
+        assertEquals("app1", 
secret1Group.getParameters().get(0).getTags().get(0).getValue());
+
+        // Find Secret2 group
+        final ParameterGroup secret2Group = parameterGroups.stream()
+                .filter(g -> "Secret2".equals(g.getGroupName()))
+                .findFirst()
+                .orElseThrow();
+        assertEquals(2, secret2Group.getParameters().size());
+        // Both parameters in Secret2 should have the same tags
+        for (final Parameter param : secret2Group.getParameters()) {
+            assertEquals(2, param.getTags().size());
+        }
+    }
+
     private AwsSecretsManagerParameterProvider getParameterProvider() {
         return spy(new AwsSecretsManagerParameterProvider());
     }
@@ -203,6 +330,13 @@ public class TestAwsSecretsManagerParameterProvider {
                         final GetSecretValueResponse response = 
GetSecretValueResponse.builder().name(groupName).secretString(secretString).build();
                         
when(secretsManager.getSecretValue(argThat(matchesGetSecretValueRequest(groupName))))
                                 .thenReturn(response);
+
+                        // Mock DescribeSecret for tags (returns empty tags)
+                        final DescribeSecretResponse describeResponse = 
DescribeSecretResponse.builder()
+                                .name(groupName)
+                                .build();
+                        
when(secretsManager.describeSecret(argThat(matchesDescribeSecretRequest(groupName))))
+                                .thenReturn(describeResponse);
                     } catch (final JsonProcessingException e) {
                         throw new IllegalStateException(e);
                     }
@@ -211,40 +345,6 @@ public class TestAwsSecretsManagerParameterProvider {
         });
         return secretsManager;
     }
-    private SecretsManagerClient mockSecretsManager(final List<ParameterGroup> 
mockParameterGroups) {
-        final SecretsManagerClient secretsManager = 
mock(SecretsManagerClient.class);
-        
when(emptyListSecretsResponse.secretList()).thenReturn(Collections.emptyList());
-
-        String currentToken = null;
-        for (int i = 0; i < mockParameterGroups.size(); i++) {
-            final ParameterGroup group = mockParameterGroups.get(i);
-            final List<SecretListEntry> secretList = 
Collections.singletonList(SecretListEntry.builder().name(group.getGroupName()).build());
-            final ListSecretsResponse listSecretsResponse = 
mock(ListSecretsResponse.class);
-            when(listSecretsResponse.secretList()).thenReturn(secretList);
-            
when(secretsManager.listSecrets(argThat(ListSecretsRequestMatcher.hasToken(currentToken)))).thenReturn(listSecretsResponse);
-
-            currentToken = "token-" + i;
-            when(listSecretsResponse.nextToken()).thenReturn(currentToken);
-        }
-        
when(secretsManager.listSecrets(argThat(ListSecretsRequestMatcher.hasToken(currentToken)))).thenReturn(emptyListSecretsResponse);
-
-        mockParameterGroups.forEach(group -> {
-            final String groupName = group.getGroupName();
-            final Map<String, String> keyValues = 
group.getParameters().stream().collect(Collectors.toMap(
-                    param -> param.getDescriptor().getName(),
-                    Parameter::getValue));
-            final String secretString;
-            try {
-                secretString = objectMapper.writeValueAsString(keyValues);
-                final GetSecretValueResponse response = 
GetSecretValueResponse.builder().name(groupName).secretString(secretString).build();
-                
when(secretsManager.getSecretValue(argThat(matchesGetSecretValueRequest(groupName))))
-                        .thenReturn(response);
-            } catch (final JsonProcessingException e) {
-                throw new IllegalStateException(e);
-            }
-        });
-        return secretsManager;
-    }
 
     private List<ParameterGroup> runProviderTest(final SecretsManagerClient 
secretsManager,
                                                  final int expectedCount,
@@ -287,6 +387,51 @@ public class TestAwsSecretsManagerParameterProvider {
         return parameterGroups;
     }
 
+    private SecretsManagerClient mockSecretsManagerWithTags(final 
List<ParameterGroup> mockParameterGroups,
+                                                            final Map<String, 
List<Tag>> secretTags) {
+        final SecretsManagerClient secretsManager = 
mock(SecretsManagerClient.class);
+        
when(emptyListSecretsResponse.secretList()).thenReturn(Collections.emptyList());
+
+        String currentToken = null;
+        for (int i = 0; i < mockParameterGroups.size(); i++) {
+            final ParameterGroup group = mockParameterGroups.get(i);
+            final String groupName = group.getGroupName();
+            final List<Tag> tags = secretTags.getOrDefault(groupName, 
Collections.emptyList());
+
+            // Build SecretListEntry with tags
+            final SecretListEntry.Builder entryBuilder = 
SecretListEntry.builder().name(groupName);
+            if (!tags.isEmpty()) {
+                entryBuilder.tags(tags);
+            }
+            final List<SecretListEntry> secretList = 
Collections.singletonList(entryBuilder.build());
+
+            final ListSecretsResponse listSecretsResponse = 
mock(ListSecretsResponse.class);
+            when(listSecretsResponse.secretList()).thenReturn(secretList);
+            
when(secretsManager.listSecrets(argThat(ListSecretsRequestMatcher.hasToken(currentToken)))).thenReturn(listSecretsResponse);
+
+            currentToken = "token-" + i;
+            when(listSecretsResponse.nextToken()).thenReturn(currentToken);
+        }
+        
when(secretsManager.listSecrets(argThat(ListSecretsRequestMatcher.hasToken(currentToken)))).thenReturn(emptyListSecretsResponse);
+
+        mockParameterGroups.forEach(group -> {
+            final String groupName = group.getGroupName();
+            final Map<String, String> keyValues = 
group.getParameters().stream().collect(Collectors.toMap(
+                    param -> param.getDescriptor().getName(),
+                    Parameter::getValue));
+            final String secretString;
+            try {
+                secretString = objectMapper.writeValueAsString(keyValues);
+                final GetSecretValueResponse response = 
GetSecretValueResponse.builder().name(groupName).secretString(secretString).build();
+                
when(secretsManager.getSecretValue(argThat(matchesGetSecretValueRequest(groupName))))
+                        .thenReturn(response);
+            } catch (final JsonProcessingException e) {
+                throw new IllegalStateException(e);
+            }
+        });
+        return secretsManager;
+    }
+
     private static Parameter parameter(final String name, final String value) {
         return new Parameter.Builder()
             .name(name)
@@ -298,6 +443,10 @@ public class TestAwsSecretsManagerParameterProvider {
         return new GetSecretValueRequestMatcher(groupName);
     }
 
+    private static ArgumentMatcher<DescribeSecretRequest> 
matchesDescribeSecretRequest(final String secretId) {
+        return new DescribeSecretRequestMatcher(secretId);
+    }
+
     private static class GetSecretValueRequestMatcher implements 
ArgumentMatcher<GetSecretValueRequest> {
 
         private final String secretId;
@@ -329,4 +478,18 @@ public class TestAwsSecretsManagerParameterProvider {
             return argument != null && Objects.equals(argument.nextToken(), 
token);
         }
     }
+
+    private static class DescribeSecretRequestMatcher implements 
ArgumentMatcher<DescribeSecretRequest> {
+
+        private final String secretId;
+
+        private DescribeSecretRequestMatcher(final String secretId) {
+            this.secretId = secretId;
+        }
+
+        @Override
+        public boolean matches(final DescribeSecretRequest argument) {
+            return argument != null && argument.secretId().equals(secretId);
+        }
+    }
 }

Reply via email to