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..d00afdfe6470 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 @@ -20,6 +20,8 @@ import java.time.Duration; import java.time.Instant; import java.time.ZoneId; +import java.util.Collections; +import java.util.List; import io.micrometer.core.instrument.MeterRegistry; import io.micrometer.core.instrument.simple.SimpleMeterRegistry; @@ -34,6 +36,10 @@ import org.springframework.boot.ssl.jks.JksSslStoreDetails; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.BDDMockito.given; +import static org.mockito.BDDMockito.then; +import static org.mockito.Mockito.atLeast; +import static org.mockito.Mockito.mock; /** * Tests for {@link SslMeterBinder}. @@ -63,6 +69,41 @@ void shouldRegisterChainExpiryMetrics() { .hasDays(36889); } + @Test + void shouldWatchUpdatesForBundlesRegisteredAfterConstruction() { + DefaultSslBundleRegistry sslBundleRegistry = new DefaultSslBundleRegistry(); + SslInfo sslInfo = mock(SslInfo.class); + given(sslInfo.getBundles()).willReturn(Collections.emptyList()); + + 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); + + given(sslInfo.getBundle("dynamic")).willReturn(bundleInfo); + given(bundleInfo.getName()).willReturn("dynamic"); + given(bundleInfo.getCertificateChains()).willReturn(List.of(chainInfo)); + given(chainInfo.getAlias()).willReturn("server"); + given(chainInfo.getCertificates()).willReturn(List.of(certificateInfo)); + given(certificateInfo.getSerialNumber()).willReturn("serial"); + + Instant expiry = CLOCK.instant().plus(Duration.ofDays(365)); + given(certificateInfo.getValidityEnds()).willReturn(expiry); + given(certificateInfo.getValidity()).willReturn(validityInfo); + given(validityInfo.getStatus()).willReturn(SslInfo.CertificateValidityInfo.Status.VALID); + given(validityInfo.getMessage()).willReturn(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); + + then(sslInfo).should(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")