diff --git a/module/spring-boot-micrometer-metrics/src/main/java/org/springframework/boot/micrometer/metrics/autoconfigure/ssl/SslMeterBinder.java b/module/spring-boot-micrometer-metrics/src/main/java/org/springframework/boot/micrometer/metrics/autoconfigure/ssl/SslMeterBinder.java index 31dc033e494e..8b90fe74da70 100644 --- a/module/spring-boot-micrometer-metrics/src/main/java/org/springframework/boot/micrometer/metrics/autoconfigure/ssl/SslMeterBinder.java +++ b/module/spring-boot-micrometer-metrics/src/main/java/org/springframework/boot/micrometer/metrics/autoconfigure/ssl/SslMeterBinder.java @@ -67,7 +67,10 @@ class SslMeterBinder implements MeterBinder { SslMeterBinder(SslInfo sslInfo, SslBundles sslBundles, Clock clock) { this.clock = clock; this.sslInfo = sslInfo; - sslBundles.addBundleRegisterHandler((bundleName, ignored) -> onBundleChange(bundleName)); + sslBundles.addBundleRegisterHandler((bundleName, ignored) -> { + onBundleChange(bundleName); + sslBundles.addBundleUpdateHandler(bundleName, (ignoredBundle) -> onBundleChange(bundleName)); + }); for (String bundleName : sslBundles.getBundleNames()) { sslBundles.addBundleUpdateHandler(bundleName, (ignored) -> onBundleChange(bundleName)); } diff --git a/module/spring-boot-micrometer-metrics/src/test/java/org/springframework/boot/micrometer/metrics/autoconfigure/ssl/SslMeterBinderTests.java b/module/spring-boot-micrometer-metrics/src/test/java/org/springframework/boot/micrometer/metrics/autoconfigure/ssl/SslMeterBinderTests.java index 7049e0054516..30bbaa19de2f 100644 --- a/module/spring-boot-micrometer-metrics/src/test/java/org/springframework/boot/micrometer/metrics/autoconfigure/ssl/SslMeterBinderTests.java +++ b/module/spring-boot-micrometer-metrics/src/test/java/org/springframework/boot/micrometer/metrics/autoconfigure/ssl/SslMeterBinderTests.java @@ -34,6 +34,12 @@ import org.springframework.boot.ssl.jks.JksSslStoreDetails; import static org.assertj.core.api.Assertions.assertThat; +import java.util.List; + +import static org.mockito.Mockito.atLeast; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; /** * Tests for {@link SslMeterBinder}. @@ -63,6 +69,41 @@ void shouldRegisterChainExpiryMetrics() { .hasDays(36889); } + @Test + void shouldWatchUpdatesForBundlesRegisteredAfterConstruction() { + DefaultSslBundleRegistry sslBundleRegistry = new DefaultSslBundleRegistry(); + SslInfo sslInfo = mock(SslInfo.class); + when(sslInfo.getBundles()).thenReturn(List.of()); + + SslInfo.BundleInfo bundleInfo = mock(SslInfo.BundleInfo.class); + SslInfo.CertificateChainInfo chainInfo = mock(SslInfo.CertificateChainInfo.class); + SslInfo.CertificateInfo certificateInfo = mock(SslInfo.CertificateInfo.class); + SslInfo.CertificateValidityInfo validityInfo = mock(SslInfo.CertificateValidityInfo.class); + + when(sslInfo.getBundle("dynamic")).thenReturn(bundleInfo); + when(bundleInfo.getName()).thenReturn("dynamic"); + when(bundleInfo.getCertificateChains()).thenReturn(List.of(chainInfo)); + when(chainInfo.getAlias()).thenReturn("server"); + when(chainInfo.getCertificates()).thenReturn(List.of(certificateInfo)); + when(certificateInfo.getSerialNumber()).thenReturn("serial"); + + Instant expiry = CLOCK.instant().plus(Duration.ofDays(365)); + when(certificateInfo.getValidityEnds()).thenReturn(expiry); + when(certificateInfo.getValidity()).thenReturn(validityInfo); + when(validityInfo.getStatus()).thenReturn(SslInfo.CertificateValidityInfo.Status.VALID); + when(validityInfo.getMessage()).thenReturn(null); + + SslMeterBinder binder = new SslMeterBinder(sslInfo, sslBundleRegistry, CLOCK); + SimpleMeterRegistry meterRegistry = new SimpleMeterRegistry(); + binder.bindTo(meterRegistry); + + SslBundle bundle = mock(SslBundle.class); + sslBundleRegistry.registerBundle("dynamic", bundle); + sslBundleRegistry.updateBundle("dynamic", bundle); + + verify(sslInfo, atLeast(2)).getBundle("dynamic"); + } + private static long findExpiryGauge(MeterRegistry meterRegistry, String chain, String certificateSerialNumber) { return (long) meterRegistry.get("ssl.chain.expiry") .tag("bundle", "test-0")