Remove SSL status tag from metrics
Update `SslMeterBinder` to the status tag is no longer included in the reported metrics. Instead the expiry date should be used directly by the monitoring system. Closes gh-45602
This commit is contained in:
@@ -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;
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user