Browse Source

Merge branch 'main' into 4.0.x

pull/45379/head
Phillip Webb 9 months ago
parent
commit
f3c25b21eb
  1. 65
      spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/ssl/SslMeterBinder.java
  2. 9
      spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/ssl/SslMeterBinderTests.java
  3. 8
      spring-boot-project/spring-boot-docs/src/docs/antora/modules/reference/pages/actuator/metrics.adoc

65
spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/ssl/SslMeterBinder.java

@ -23,14 +23,12 @@ import java.time.temporal.ChronoUnit; @@ -23,14 +23,12 @@ import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import io.micrometer.core.instrument.Gauge;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.MultiGauge;
import io.micrometer.core.instrument.MultiGauge.Row;
@ -42,21 +40,16 @@ import org.springframework.boot.info.SslInfo; @@ -42,21 +40,16 @@ import org.springframework.boot.info.SslInfo;
import org.springframework.boot.info.SslInfo.BundleInfo;
import org.springframework.boot.info.SslInfo.CertificateChainInfo;
import org.springframework.boot.info.SslInfo.CertificateInfo;
import org.springframework.boot.info.SslInfo.CertificateValidityInfo;
import org.springframework.boot.info.SslInfo.CertificateValidityInfo.Status;
import org.springframework.boot.ssl.SslBundles;
/**
* {@link MeterBinder} which registers the SSL chain validity (soonest to expire
* certificate in the chain) as a {@link TimeGauge}. Also contributes two {@link Gauge
* gauges} to count the valid and invalid chains.
* {@link MeterBinder} which registers the SSL chain expiry (soonest to expire certificate
* in the chain) as a {@link TimeGauge}.
*
* @author Moritz Halbritter
*/
class SslMeterBinder implements MeterBinder {
private static final String CHAINS_METRIC_NAME = "ssl.chains";
private static final String CHAIN_EXPIRY_METRIC_NAME = "ssl.chain.expiry";
private final Clock clock;
@ -91,18 +84,6 @@ class SslMeterBinder implements MeterBinder { @@ -91,18 +84,6 @@ class SslMeterBinder implements MeterBinder {
for (BundleInfo bundle : this.sslInfo.getBundles()) {
createOrUpdateBundleMetrics(meterRegistry, bundle);
}
Gauge.builder(CHAINS_METRIC_NAME, () -> countChainsByStatus(Status.VALID))
.tag("status", "valid")
.register(meterRegistry);
Gauge.builder(CHAINS_METRIC_NAME, () -> countChainsByStatus(Status.EXPIRED))
.tag("status", "expired")
.register(meterRegistry);
Gauge.builder(CHAINS_METRIC_NAME, () -> countChainsByStatus(Status.NOT_YET_VALID))
.tag("status", "not-yet-valid")
.register(meterRegistry);
Gauge.builder(CHAINS_METRIC_NAME, () -> countChainsByStatus(Status.WILL_EXPIRE_SOON))
.tag("status", "will-expire-soon")
.register(meterRegistry);
}
private void createOrUpdateBundleMetrics(MeterRegistry meterRegistry, BundleInfo bundle) {
@ -130,36 +111,6 @@ class SslMeterBinder implements MeterBinder { @@ -130,36 +111,6 @@ class SslMeterBinder implements MeterBinder {
return Row.of(tags, leastValidCertificate, this::getChainExpiry);
}
private long countChainsByStatus(Status status) {
long count = 0;
for (BundleInfo bundle : this.bundleMetrics.getBundles()) {
for (CertificateChainInfo chain : bundle.getCertificateChains()) {
if (getChainStatus(chain) == status) {
count++;
}
}
}
return count;
}
private Status getChainStatus(CertificateChainInfo chain) {
EnumSet<Status> statuses = EnumSet.noneOf(Status.class);
for (CertificateInfo certificate : chain.getCertificates()) {
CertificateValidityInfo validity = certificate.getValidity();
statuses.add(validity.getStatus());
}
if (statuses.contains(Status.EXPIRED)) {
return Status.EXPIRED;
}
if (statuses.contains(Status.NOT_YET_VALID)) {
return Status.NOT_YET_VALID;
}
if (statuses.contains(Status.WILL_EXPIRE_SOON)) {
return Status.WILL_EXPIRE_SOON;
}
return statuses.isEmpty() ? null : Status.VALID;
}
private long getChainExpiry(CertificateInfo certificate) {
Duration valid = Duration.between(Instant.now(this.clock), certificate.getValidityEnds());
return valid.get(ChronoUnit.SECONDS);
@ -184,18 +135,6 @@ class SslMeterBinder implements MeterBinder { @@ -184,18 +135,6 @@ class SslMeterBinder implements MeterBinder {
return gauges.getGauge(meterRegistry);
}
/**
* Returns all bundles.
* @return all bundles
*/
Collection<BundleInfo> getBundles() {
List<BundleInfo> result = new ArrayList<>();
for (Gauges metrics : this.gauges.values()) {
result.add(metrics.bundle());
}
return result;
}
/**
* Returns all meter registries.
* @return all meter registries

9
spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/ssl/SslMeterBinderTests.java

@ -44,15 +44,6 @@ class SslMeterBinderTests { @@ -44,15 +44,6 @@ class SslMeterBinderTests {
private static final Clock CLOCK = Clock.fixed(Instant.parse("2024-10-21T13:51:40Z"), ZoneId.of("UTC"));
@Test
void shouldRegisterChainMetrics() {
MeterRegistry meterRegistry = bindToRegistry();
assertThat(meterRegistry.get("ssl.chains").tag("status", "valid").gauge().value()).isEqualTo(3.0);
assertThat(meterRegistry.get("ssl.chains").tag("status", "expired").gauge().value()).isEqualTo(1.0);
assertThat(meterRegistry.get("ssl.chains").tag("status", "not-yet-valid").gauge().value()).isEqualTo(1.0);
assertThat(meterRegistry.get("ssl.chains").tag("status", "will-expire-soon").gauge().value()).isEqualTo(0.0);
}
@Test
void shouldRegisterChainExpiryMetrics() {
MeterRegistry meterRegistry = bindToRegistry();

8
spring-boot-project/spring-boot-docs/src/docs/antora/modules/reference/pages/actuator/metrics.adoc

@ -836,13 +836,9 @@ To customize the tags, provide a javadoc:org.springframework.context.annotation. @@ -836,13 +836,9 @@ To customize the tags, provide a javadoc:org.springframework.context.annotation.
[[actuator.metrics.supported.ssl]]
=== SSL bundle metrics
Spring Boot Actuator publishes two metrics about SSL bundles:
The metric `ssl.chains` gauges how many certificate chains have been registered.
The `status` tag can be used to differentiate between valid, not-yet-valid, expired and soon-to-be-expired certificates.
=== SSL Bundle Metrics
Spring Boot Actuator publishes expiry metrics about SSL bundles.
The metric `ssl.chain.expiry` gauges the expiry date of each certificate chain in seconds.
This number will be negative if the chain has already expired.
This metric is tagged with the following information:

Loading…
Cancel
Save