From d271be988f8bc7832d65cf0bcb1541ed12dfb656 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Magnus=20Le=C3=9Fmann=20=28=40MarkL4YG=29?= Date: Fri, 22 Nov 2024 20:27:50 +0100 Subject: [PATCH] chore: Add version logging for OpenSSL --- .../openssl/CertificateRequestExtension.java | 13 +++--- .../openssl/OpenSSLCertificateCreator.java | 27 ++++++++++++- .../certassist/CertificateServiceTest.java | 40 ++++++++++--------- .../TestOpenSSLCertificateCreator.java | 11 ++--- 4 files changed, 58 insertions(+), 33 deletions(-) diff --git a/src/main/java/de/mlessmann/certassist/openssl/CertificateRequestExtension.java b/src/main/java/de/mlessmann/certassist/openssl/CertificateRequestExtension.java index 9bdf9c9..853dbeb 100644 --- a/src/main/java/de/mlessmann/certassist/openssl/CertificateRequestExtension.java +++ b/src/main/java/de/mlessmann/certassist/openssl/CertificateRequestExtension.java @@ -3,7 +3,6 @@ package de.mlessmann.certassist.openssl; import java.util.List; import java.util.Objects; import java.util.stream.Stream; - import lombok.Builder; import lombok.Getter; @@ -17,11 +16,13 @@ public class CertificateRequestExtension { public CertificateRequestExtensionBuilder alternativeNames(String... altNames) { Objects.requireNonNull(altNames, "Alternative names must not be null (but can be empty)"); - this.alternativeNames = Stream.of(altNames) - .filter(Objects::nonNull) - .map(String::trim) - .map(name -> name.replaceAll("^DNS:", "")) - .toList(); + this.alternativeNames = + Stream + .of(altNames) + .filter(Objects::nonNull) + .map(String::trim) + .map(name -> name.replaceAll("^DNS:", "")) + .toList(); return this; } } diff --git a/src/main/java/de/mlessmann/certassist/openssl/OpenSSLCertificateCreator.java b/src/main/java/de/mlessmann/certassist/openssl/OpenSSLCertificateCreator.java index 1d53d2f..8b8b6e8 100644 --- a/src/main/java/de/mlessmann/certassist/openssl/OpenSSLCertificateCreator.java +++ b/src/main/java/de/mlessmann/certassist/openssl/OpenSSLCertificateCreator.java @@ -16,6 +16,7 @@ import java.nio.file.StandardOpenOption; import java.util.List; import java.util.Optional; import java.util.concurrent.ExecutionException; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -49,6 +50,7 @@ public class OpenSSLCertificateCreator { private static final Pattern FINGERPRINT_EXTRACTOR = Pattern.compile( "^(?[0-9a-zA-Z]+) (?i)Fingerprint(?-i)=(?[a-z:A-Z0-9]+)" ); + private final AtomicBoolean versionLogged = new AtomicBoolean(false); private final ExecutableResolver executableResolver; private final CertificatePasswordProvider passwordProvider; @@ -426,7 +428,7 @@ public class OpenSSLCertificateCreator { if (infoResult.getExitValue() != 0) { log.debug("Certificate info command output:\n{}", output); throw new CommandLineOperationException( - "Failed to get info of path. Exit code: %d".formatted(infoResult.getExitValue()) + "Failed to get info of path. Exit code: %d".formatted(infoResult.getExitValue()) ); } return getCertificateInfo(output.lines().toArray(String[]::new)); @@ -437,7 +439,28 @@ public class OpenSSLCertificateCreator { private String resolveOpenSSL() throws CommandLineOperationException { try { - return executableResolver.getOpenSSLPath(); + String path = executableResolver.getOpenSSLPath(); + if (!versionLogged.get()) { + try { + StartedProcess versionProc = new ProcessExecutor() + .command(path, "version") + .readOutput(true) + .redirectError(Slf4jStream.ofCaller().asError()) + .start(); + var versionResult = versionProc.getFuture().get(); + if (versionResult.getExitValue() != 0) { + throw new CommandLineOperationException( + "Failed to get OpenSSL version. Exit code: " + versionResult.getExitValue() + ); + } + + log.info("Using OpenSSL version: {}", versionResult.getOutput().getUTF8()); + versionLogged.set(true); + } catch (IOException | InterruptedException | ExecutionException e) { + throw new CommandLineOperationException("Failed to get OpenSSL version", e); + } + } + return path; } catch (UnresolvableCLIDependency e) { throw new CommandLineOperationException(e); } diff --git a/src/test/java/de/mlessmann/certassist/CertificateServiceTest.java b/src/test/java/de/mlessmann/certassist/CertificateServiceTest.java index 1199766..4c95ded 100644 --- a/src/test/java/de/mlessmann/certassist/CertificateServiceTest.java +++ b/src/test/java/de/mlessmann/certassist/CertificateServiceTest.java @@ -1,17 +1,16 @@ package de.mlessmann.certassist; +import static org.assertj.core.api.Assertions.assertThat; + import de.mlessmann.certassist.openssl.CertificateRequest; import de.mlessmann.certassist.openssl.CertificateRequestExtension; import de.mlessmann.certassist.openssl.CertificateSubject; import de.mlessmann.certassist.service.CertificateCreationService; +import java.nio.file.Path; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -import java.nio.file.Path; - -import static org.assertj.core.api.Assertions.assertThat; - @SpringBootTest public class CertificateServiceTest { @@ -20,18 +19,20 @@ public class CertificateServiceTest { @Test void testCanCreateCertificate() { - var request = CertificateRequest.builder() - .type(CertificateRequest.RequestType.STANDALONE_CERTIFICATE) - .subject( - CertificateSubject.builder() - .commonName("cert.creation") - .country("DE") - .state("SH") - .locality("HH") - .organization("Crazy-Cats") - ) - .extension(CertificateRequestExtension.builder().alternativeNames("test2.home", "test3.home")) - .build(); + var request = CertificateRequest + .builder() + .type(CertificateRequest.RequestType.STANDALONE_CERTIFICATE) + .subject( + CertificateSubject + .builder() + .commonName("cert.creation") + .country("DE") + .state("SH") + .locality("HH") + .organization("Crazy-Cats") + ) + .extension(CertificateRequestExtension.builder().alternativeNames("test2.home", "test3.home")) + .build(); var cert = certificateService.createCertificate(request); assertThat(cert).isNotNull(); assertThat(cert.getId()).isGreaterThan("0"); @@ -40,8 +41,11 @@ public class CertificateServiceTest { @Test void testCanImportCertificate() { Path certDir = TestOpenSSLCertificateCreator.TEST_CERT_PATH; - var importedCert = certificateService.importCertificate(certDir.resolve("x509forImport.pem"), - certDir.resolve("x509forImport.key.pem"), TestOpenSSLCertificateCreator.TEST_CERT_PASSPHRASE); + var importedCert = certificateService.importCertificate( + certDir.resolve("x509forImport.pem"), + certDir.resolve("x509forImport.key.pem"), + TestOpenSSLCertificateCreator.TEST_CERT_PASSPHRASE + ); assertThat(importedCert).isNotNull(); assertThat(importedCert.getId()).isGreaterThan("0"); } diff --git a/src/test/java/de/mlessmann/certassist/TestOpenSSLCertificateCreator.java b/src/test/java/de/mlessmann/certassist/TestOpenSSLCertificateCreator.java index 21c6988..bf5de81 100644 --- a/src/test/java/de/mlessmann/certassist/TestOpenSSLCertificateCreator.java +++ b/src/test/java/de/mlessmann/certassist/TestOpenSSLCertificateCreator.java @@ -66,10 +66,7 @@ class TestOpenSSLCertificateCreator { .locality("HH") .organization("Crazy-Cats") ) - .extension( - CertificateRequestExtension.builder() - .alternativeNames("test2.local", "test3.local") - ) + .extension(CertificateRequestExtension.builder().alternativeNames("test2.local", "test3.local")) .build(); var spiedCert = spy(cert); @@ -91,9 +88,9 @@ class TestOpenSSLCertificateCreator { CertificateProvider certificateProvider = mock(CertificateProvider.class); ExecutableResolver executableResolver = new ExecutableResolver(); var certificateCreator = new OpenSSLCertificateCreator( - executableResolver, - passwordProvider, - certificateProvider + executableResolver, + passwordProvider, + certificateProvider ); var request = certificateCreator.getCertificateInfo(TEST_CERT_PATH.resolve("x509forImportCA.pem"));