Skip to content

Commit

Permalink
ENH: allow disable secret refreshment (#3990)
Browse files Browse the repository at this point in the history
* ENH: allow disable secret refreshment

Signed-off-by: George Chen <[email protected]>
  • Loading branch information
chenqi0805 committed Jan 31, 2024
1 parent 96007d6 commit 04ed41c
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,13 @@ public class AwsSecretManagerConfiguration {
private String awsStsRoleArn;

@JsonProperty("refresh_interval")
@NotNull(message = "refresh_interval must not be null")
@DurationMin(hours = 1L, message = "Refresh interval must be at least 1 hour.")
private Duration refreshInterval = Duration.ofHours(1L);

@JsonProperty("disable_refresh")
private boolean disableRefresh = false;

public String getAwsSecretId() {
return awsSecretId;
}
Expand All @@ -57,6 +61,10 @@ public Duration getRefreshInterval() {
return refreshInterval;
}

public boolean isDisableRefresh() {
return disableRefresh;
}

public SecretsManagerClient createSecretManagerClient() {
return SecretsManagerClient.builder()
.credentialsProvider(authenticateAwsConfiguration())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,14 @@ public void apply(final ExtensionPoints extensionPoints) {
private void submitSecretsRefreshJobs(final AwsSecretPluginConfig awsSecretPluginConfig,
final SecretsSupplier secretsSupplier) {
awsSecretPluginConfig.getAwsSecretManagerConfigurationMap().forEach((key, value) -> {
final SecretsRefreshJob secretsRefreshJob = new SecretsRefreshJob(
key, secretsSupplier, pluginConfigPublisher, pluginMetrics);
final long period = value.getRefreshInterval().toSeconds();
final long jitterDelay = ThreadLocalRandom.current().nextLong(60L);
scheduledExecutorService.scheduleAtFixedRate(secretsRefreshJob, period + jitterDelay,
period, TimeUnit.SECONDS);
if (!value.isDisableRefresh()) {
final SecretsRefreshJob secretsRefreshJob = new SecretsRefreshJob(
key, secretsSupplier, pluginConfigPublisher, pluginMetrics);
final long period = value.getRefreshInterval().toSeconds();
final long jitterDelay = ThreadLocalRandom.current().nextLong(60L);
scheduledExecutorService.scheduleAtFixedRate(secretsRefreshJob, period + jitterDelay,
period, TimeUnit.SECONDS);
}
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ void testAwsSecretManagerConfigurationDefault() throws IOException {
assertThat(awsSecretManagerConfiguration.getAwsSecretId(), equalTo("test-secret"));
assertThat(awsSecretManagerConfiguration.getAwsRegion(), equalTo(Region.US_EAST_1));
assertThat(awsSecretManagerConfiguration.getRefreshInterval(), equalTo(Duration.ofHours(1)));
assertThat(awsSecretManagerConfiguration.isDisableRefresh(), is(false));
}

@Test
Expand All @@ -100,6 +101,19 @@ void testAwsSecretManagerConfigurationInvalidRefreshInterval() throws IOExceptio
assertThat(violation.getMessage(), equalTo("Refresh interval must be at least 1 hour."));
}

@Test
void testAwsSecretManagerConfigurationNullRefreshInterval() throws IOException {
final InputStream inputStream = AwsSecretPluginConfigTest.class.getResourceAsStream(
"/test-aws-secret-manager-configuration-null-refresh-interval.yaml");
final AwsSecretManagerConfiguration awsSecretManagerConfiguration = objectMapper.readValue(
inputStream, AwsSecretManagerConfiguration.class);
final Set<ConstraintViolation<AwsSecretManagerConfiguration>> violations = VALIDATOR.validate(
awsSecretManagerConfiguration);
assertThat(violations.size(), equalTo(1));
final ConstraintViolation<AwsSecretManagerConfiguration> violation = violations.stream().findFirst().get();
assertThat(violation.getMessage(), equalTo("refresh_interval must not be null"));
}

@Test
void testCreateGetSecretValueRequest() throws IOException {
when(getSecretValueRequestBuilder.secretId(anyString())).thenReturn(getSecretValueRequestBuilder);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,41 @@ void testInitializationWithNonNullConfig() {
verify(runtime).addShutdownHook(any());
}

@Test
void testInitializationWithDisableRefresh() {
when(awsSecretPluginConfig.getAwsSecretManagerConfigurationMap()).thenReturn(
Map.of(TEST_SECRET_CONFIG_ID, awsSecretManagerConfiguration));
when(awsSecretManagerConfiguration.isDisableRefresh()).thenReturn(true);
when(awsSecretManagerConfiguration.createSecretManagerClient()).thenReturn(secretsManagerClient);
when(awsSecretManagerConfiguration.createGetSecretValueRequest()).thenReturn(getSecretValueRequest);
when(secretsManagerClient.getSecretValue(eq(getSecretValueRequest))).thenReturn(getSecretValueResponse);
when(getSecretValueResponse.secretString()).thenReturn(UUID.randomUUID().toString());
try (final MockedStatic<Executors> executorsMockedStatic = mockStatic(Executors.class);
final MockedStatic<Runtime> runtimeMockedStatic = mockStatic(Runtime.class)
) {
executorsMockedStatic.when(Executors::newSingleThreadScheduledExecutor)
.thenReturn(scheduledExecutorService);
runtimeMockedStatic.when(Runtime::getRuntime).thenReturn(runtime);
objectUnderTest = new AwsSecretPlugin(awsSecretPluginConfig);
objectUnderTest.apply(extensionPoints);
}
final ArgumentCaptor<ExtensionProvider> extensionProviderArgumentCaptor =
ArgumentCaptor.forClass(ExtensionProvider.class);
verify(extensionPoints, times(2)).addExtensionProvider(extensionProviderArgumentCaptor.capture());
final List<ExtensionProvider> actualExtensionProviders = extensionProviderArgumentCaptor.getAllValues();
assertThat(actualExtensionProviders.get(0), instanceOf(AwsSecretsPluginConfigValueTranslatorExtensionProvider.class));
final Optional<PluginConfigValueTranslator> optionalPluginConfigValueTranslator =
actualExtensionProviders.get(0).provideInstance(context);
assertThat(optionalPluginConfigValueTranslator.isPresent(), is(true));
assertThat(optionalPluginConfigValueTranslator.get(), instanceOf(AwsSecretsPluginConfigValueTranslator.class));
assertThat(actualExtensionProviders.get(1), instanceOf(AwsSecretsPluginConfigPublisherExtensionProvider.class));
final Optional<PluginConfigPublisher> optionalPluginConfigPublisher =
actualExtensionProviders.get(1).provideInstance(context);
assertThat(optionalPluginConfigPublisher.isPresent(), is(true));
verifyNoInteractions(scheduledExecutorService);
verify(runtime).addShutdownHook(any());
}

@Test
void testInitializationWithNullConfig() {
objectUnderTest = new AwsSecretPlugin(null);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
secret_id: test-secret
refresh_interval: null

0 comments on commit 04ed41c

Please sign in to comment.