[fix] ssl_cert monitor: skip hostname check when verify is off (#4324)

Co-authored-by: aias00 <liuhongyu@apache.org>
This commit is contained in:
NekoPunch
2026-08-18 13:27:45 +08:00
committed by GitHub
co-authored by aias00
parent 038ed5dea8
commit 589741d068
2 changed files with 86 additions and 7 deletions
@@ -92,6 +92,7 @@ public class SslCertificateCollectImpl extends AbstractCollect {
if (!verifySsl){
SSLContext ignoreSslContext = createIgnoreVerifySslContext();
urlConnection.setSSLSocketFactory(ignoreSslContext.getSocketFactory());
urlConnection.setHostnameVerifier((hostname, session) -> true);
}
urlConnection.connect();
@@ -17,23 +17,101 @@
package org.apache.hertzbeat.collector.collect.http;
import org.junit.jupiter.api.BeforeEach;
import com.sun.net.httpserver.HttpsConfigurator;
import com.sun.net.httpserver.HttpsServer;
import java.io.FileInputStream;
import java.net.InetSocketAddress;
import java.nio.file.Files;
import java.nio.file.Path;
import java.security.KeyStore;
import java.util.List;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import org.apache.hertzbeat.common.entity.job.Metrics;
import org.apache.hertzbeat.common.entity.job.protocol.HttpProtocol;
import org.apache.hertzbeat.common.entity.message.CollectRep;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
/**
* Test case for {@link SslCertificateCollectImpl}
* Test case for {@link SslCertificateCollectImpl}: real TLS handshake against a local
* HTTPS server using a self-signed cert whose CN/SAN does not match the target address.
*/
class SslCertificateCollectImplTest {
@BeforeEach
void setUp() {
private static HttpsServer server;
private static Path keystore;
@BeforeAll
static void startServer() throws Exception {
keystore = genSelfSignedKeystore();
KeyStore ks = KeyStore.getInstance("PKCS12");
try (FileInputStream in = new FileInputStream(keystore.toFile())) {
ks.load(in, "changeit".toCharArray());
}
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(ks, "changeit".toCharArray());
SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(kmf.getKeyManagers(), null, null);
server = HttpsServer.create(new InetSocketAddress("127.0.0.1", 0), 0);
server.setHttpsConfigurator(new HttpsConfigurator(ctx));
server.createContext("/", exchange -> {
exchange.sendResponseHeaders(200, -1);
exchange.close();
});
server.start();
}
@AfterAll
static void stopServer() throws Exception {
if (server != null) {
server.stop(0);
}
if (keystore != null) {
Files.deleteIfExists(keystore);
}
}
private static Path genSelfSignedKeystore() throws Exception {
Path ks = Files.createTempFile("ssl-collect-test", ".p12");
Files.delete(ks);
String keytool = Path.of(System.getProperty("java.home"), "bin", "keytool").toString();
int exit = new ProcessBuilder(keytool, "-genkeypair", "-alias", "test",
"-keyalg", "RSA", "-keysize", "2048", "-storetype", "PKCS12",
"-keystore", ks.toString(), "-storepass", "changeit",
"-dname", "CN=test", "-ext", "SAN=dns:not-this-host", "-validity", "1")
.inheritIO().start().waitFor();
Assertions.assertEquals(0, exit, "keytool failed to generate test keystore");
return ks;
}
private CollectRep.MetricsData.Builder collect(boolean verify) {
HttpProtocol http = new HttpProtocol();
http.setHost("127.0.0.1");
http.setPort(String.valueOf(server.getAddress().getPort()));
http.setSsl(String.valueOf(verify));
Metrics metrics = Metrics.builder()
.http(http)
.aliasFields(List.of("subject", "expired", "end_timestamp"))
.build();
CollectRep.MetricsData.Builder builder = CollectRep.MetricsData.newBuilder();
new SslCertificateCollectImpl().collect(builder, metrics);
return builder;
}
@Test
void getInstance() {
void verifyOnFailsForUntrustedCert() {
CollectRep.MetricsData.Builder builder = collect(true);
Assertions.assertEquals(CollectRep.Code.UN_CONNECTABLE, builder.getCode(), builder.getMsg());
Assertions.assertEquals(0, builder.getValuesCount());
}
@Test
void collect() {
void verifyOffCollectsUntrustedMismatchedCert() {
CollectRep.MetricsData.Builder builder = collect(false);
Assertions.assertTrue(builder.getValuesCount() > 0, "expected cert rows, got: " + builder.getMsg());
Assertions.assertEquals("CN=test", builder.getValues(0).getColumns(0));
}
}
}