Skip to content

Commit 1b4979c

Browse files
authored
Add metrics in SecretsRefreshJob for SecretsManager exceptions (#6252)
* Add metrics for SecretsManager ResourceNotFound and LimitExceeded exception
1 parent a60b076 commit 1b4979c

File tree

2 files changed

+105
-0
lines changed

2 files changed

+105
-0
lines changed

data-prepper-plugins/aws-plugin/src/main/java/org/opensearch/dataprepper/plugins/aws/SecretsRefreshJob.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,18 @@
1111
import org.opensearch.dataprepper.model.plugin.PluginConfigPublisher;
1212
import org.slf4j.Logger;
1313
import org.slf4j.LoggerFactory;
14+
import software.amazon.awssdk.services.secretsmanager.model.SecretsManagerException;
15+
import software.amazon.awssdk.services.secretsmanager.model.ResourceNotFoundException;
16+
import software.amazon.awssdk.services.secretsmanager.model.LimitExceededException;
1417

1518
public class SecretsRefreshJob implements Runnable {
1619
private static final Logger LOG = LoggerFactory.getLogger(SecretsRefreshJob.class);
1720
static final String SECRETS_REFRESH_SUCCESS = "secretsRefreshSuccess";
1821
static final String SECRETS_REFRESH_FAILURE = "secretsRefreshFailure";
1922
static final String SECRETS_REFRESH_DURATION = "secretsRefreshDuration";
23+
static final String SECRETS_SECRET_NOT_FOUND = "secretsSecretNotFound";
24+
static final String SECRETS_LIMIT_EXCEEDED = "secretsLimitExceeded";
25+
static final String SECRETS_ACCESS_DENIED = "secretsAccessDenied";
2026
static final String SECRET_CONFIG_ID_TAG = "secretConfigId";
2127
private final String secretConfigId;
2228
private final SecretsSupplier secretsSupplier;
@@ -25,6 +31,9 @@ public class SecretsRefreshJob implements Runnable {
2531
private final Counter secretsRefreshSuccessCounter;
2632
private final Counter secretsRefreshFailureCounter;
2733
private final Timer secretsRefreshTimer;
34+
private final Counter secretsSecretNotFoundCounter;
35+
private final Counter secretsLimitExceededCounter;
36+
private final Counter secretsAccessDeniedCounter;
2837

2938
public SecretsRefreshJob(final String secretConfigId,
3039
final SecretsSupplier secretsSupplier,
@@ -40,6 +49,12 @@ public SecretsRefreshJob(final String secretConfigId,
4049
SECRETS_REFRESH_FAILURE, SECRET_CONFIG_ID_TAG, secretConfigId);
4150
this.secretsRefreshTimer = pluginMetrics.timerWithTags(
4251
SECRETS_REFRESH_DURATION, SECRET_CONFIG_ID_TAG, secretConfigId);
52+
this.secretsSecretNotFoundCounter = pluginMetrics.counterWithTags(
53+
SECRETS_SECRET_NOT_FOUND, SECRET_CONFIG_ID_TAG, secretConfigId);
54+
this.secretsLimitExceededCounter = pluginMetrics.counterWithTags(
55+
SECRETS_LIMIT_EXCEEDED, SECRET_CONFIG_ID_TAG, secretConfigId);
56+
this.secretsAccessDeniedCounter = pluginMetrics.counterWithTags(
57+
SECRETS_ACCESS_DENIED, SECRET_CONFIG_ID_TAG, secretConfigId);
4358
}
4459

4560
@Override
@@ -50,6 +65,17 @@ public void run() {
5065
secretsRefreshSuccessCounter.increment();
5166
pluginConfigPublisher.notifyAllPluginConfigObservable();
5267
} catch(Exception e) {
68+
if (e instanceof SecretsManagerException) {
69+
SecretsManagerException sme = (SecretsManagerException) e;
70+
if (sme instanceof ResourceNotFoundException) {
71+
secretsSecretNotFoundCounter.increment();
72+
} else if (sme instanceof LimitExceededException) {
73+
secretsLimitExceededCounter.increment();
74+
} else if (sme.awsErrorDetails() != null &&
75+
"AccessDeniedException".equals(sme.awsErrorDetails().errorCode())) {
76+
secretsAccessDeniedCounter.increment();
77+
}
78+
}
5379
LOG.error("Failed to refresh secrets in aws:secrets:{}.", secretConfigId, e);
5480
secretsRefreshFailureCounter.increment();
5581
}

data-prepper-plugins/aws-plugin/src/test/java/org/opensearch/dataprepper/plugins/aws/SecretsRefreshJobTest.java

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@
1414
import org.mockito.junit.jupiter.MockitoExtension;
1515
import org.opensearch.dataprepper.metrics.PluginMetrics;
1616
import org.opensearch.dataprepper.model.plugin.PluginConfigPublisher;
17+
import software.amazon.awssdk.awscore.exception.AwsErrorDetails;
18+
import software.amazon.awssdk.services.secretsmanager.model.ResourceNotFoundException;
19+
import software.amazon.awssdk.services.secretsmanager.model.LimitExceededException;
20+
import software.amazon.awssdk.services.secretsmanager.model.InvalidRequestException;
1721

1822
import static org.mockito.ArgumentMatchers.any;
1923
import static org.mockito.ArgumentMatchers.eq;
@@ -25,6 +29,9 @@
2529
import static org.opensearch.dataprepper.plugins.aws.SecretsRefreshJob.SECRETS_REFRESH_DURATION;
2630
import static org.opensearch.dataprepper.plugins.aws.SecretsRefreshJob.SECRETS_REFRESH_FAILURE;
2731
import static org.opensearch.dataprepper.plugins.aws.SecretsRefreshJob.SECRETS_REFRESH_SUCCESS;
32+
import static org.opensearch.dataprepper.plugins.aws.SecretsRefreshJob.SECRETS_SECRET_NOT_FOUND;
33+
import static org.opensearch.dataprepper.plugins.aws.SecretsRefreshJob.SECRETS_LIMIT_EXCEEDED;
34+
import static org.opensearch.dataprepper.plugins.aws.SecretsRefreshJob.SECRETS_ACCESS_DENIED;
2835
import static org.opensearch.dataprepper.plugins.aws.SecretsRefreshJob.SECRET_CONFIG_ID_TAG;
2936

3037
@ExtendWith(MockitoExtension.class)
@@ -48,6 +55,15 @@ class SecretsRefreshJobTest {
4855
@Mock
4956
private Timer secretsRefreshTimer;
5057

58+
@Mock
59+
private Counter secretsSecretNotFoundCounter;
60+
61+
@Mock
62+
private Counter secretsLimitExceededCounter;
63+
64+
@Mock
65+
private Counter secretsAccessDeniedCounter;
66+
5167
private SecretsRefreshJob objectUnderTest;
5268

5369
@BeforeEach
@@ -65,6 +81,15 @@ void setUp() {
6581
when(pluginMetrics.timerWithTags(
6682
eq(SECRETS_REFRESH_DURATION), eq(SECRET_CONFIG_ID_TAG), eq(TEST_SECRET_CONFIG_ID)))
6783
.thenReturn(secretsRefreshTimer);
84+
when(pluginMetrics.counterWithTags(
85+
eq(SECRETS_SECRET_NOT_FOUND), eq(SECRET_CONFIG_ID_TAG), eq(TEST_SECRET_CONFIG_ID)))
86+
.thenReturn(secretsSecretNotFoundCounter);
87+
when(pluginMetrics.counterWithTags(
88+
eq(SECRETS_LIMIT_EXCEEDED), eq(SECRET_CONFIG_ID_TAG), eq(TEST_SECRET_CONFIG_ID)))
89+
.thenReturn(secretsLimitExceededCounter);
90+
when(pluginMetrics.counterWithTags(
91+
eq(SECRETS_ACCESS_DENIED), eq(SECRET_CONFIG_ID_TAG), eq(TEST_SECRET_CONFIG_ID)))
92+
.thenReturn(secretsAccessDeniedCounter);
6893
objectUnderTest = new SecretsRefreshJob(
6994
TEST_SECRET_CONFIG_ID, secretsSupplier, pluginConfigPublisher, pluginMetrics);
7095
}
@@ -90,5 +115,59 @@ void testRunWithRefreshFailure() {
90115
verifyNoInteractions(pluginConfigPublisher);
91116
verifyNoInteractions(secretsRefreshSuccessCounter);
92117
verify(secretsRefreshFailureCounter).increment();
118+
verifyNoInteractions(secretsSecretNotFoundCounter);
119+
verifyNoInteractions(secretsLimitExceededCounter);
120+
verifyNoInteractions(secretsAccessDeniedCounter);
121+
}
122+
123+
@Test
124+
void testRunWithResourceNotFoundException() {
125+
doThrow(ResourceNotFoundException.class).when(secretsSupplier).refresh(eq(TEST_SECRET_CONFIG_ID));
126+
objectUnderTest.run();
127+
128+
verify(secretsRefreshTimer).record(any(Runnable.class));
129+
verify(secretsSupplier).refresh(TEST_SECRET_CONFIG_ID);
130+
verifyNoInteractions(pluginConfigPublisher);
131+
verifyNoInteractions(secretsRefreshSuccessCounter);
132+
verify(secretsRefreshFailureCounter).increment();
133+
verify(secretsSecretNotFoundCounter).increment();
134+
verifyNoInteractions(secretsLimitExceededCounter);
135+
verifyNoInteractions(secretsAccessDeniedCounter);
136+
}
137+
138+
@Test
139+
void testRunWithLimitExceededException() {
140+
doThrow(LimitExceededException.class).when(secretsSupplier).refresh(eq(TEST_SECRET_CONFIG_ID));
141+
objectUnderTest.run();
142+
143+
verify(secretsRefreshTimer).record(any(Runnable.class));
144+
verify(secretsSupplier).refresh(TEST_SECRET_CONFIG_ID);
145+
verifyNoInteractions(pluginConfigPublisher);
146+
verifyNoInteractions(secretsRefreshSuccessCounter);
147+
verify(secretsRefreshFailureCounter).increment();
148+
verify(secretsLimitExceededCounter).increment();
149+
verifyNoInteractions(secretsSecretNotFoundCounter);
150+
verifyNoInteractions(secretsAccessDeniedCounter);
151+
}
152+
153+
@Test
154+
void testRunWithAccessDeniedException() {
155+
final InvalidRequestException accessDeniedException = InvalidRequestException.builder()
156+
.awsErrorDetails(AwsErrorDetails.builder()
157+
.errorCode("AccessDeniedException")
158+
.build())
159+
.build();
160+
doThrow(accessDeniedException).when(secretsSupplier).refresh(eq(TEST_SECRET_CONFIG_ID));
161+
162+
objectUnderTest.run();
163+
164+
verify(secretsRefreshTimer).record(any(Runnable.class));
165+
verify(secretsSupplier).refresh(TEST_SECRET_CONFIG_ID);
166+
verifyNoInteractions(pluginConfigPublisher);
167+
verifyNoInteractions(secretsRefreshSuccessCounter);
168+
verify(secretsRefreshFailureCounter).increment();
169+
verify(secretsAccessDeniedCounter).increment();
170+
verifyNoInteractions(secretsSecretNotFoundCounter);
171+
verifyNoInteractions(secretsLimitExceededCounter);
93172
}
94173
}

0 commit comments

Comments
 (0)