From fc4ea17cf3d85311c6ece4ff2234ab61a0d63663 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Magnus=20Le=C3=9Fmann=20=28=40MarkL4YG=29?= Date: Sat, 23 Nov 2024 20:52:15 +0100 Subject: [PATCH] chore: Rename certificate information to be more versatile to use --- .../CertificateInfo.java} | 20 +++--- .../CertificateInfoExtension.java} | 12 ++-- .../CertificateInfoSubject.java} | 8 ++- .../certassist/openssl/OpenSSLService.java | 66 ++++++++++--------- .../service/CertificateCreationService.java | 44 ++++++------- .../certassist/CertificateServiceTest.java | 14 ++-- .../certassist/TestOpenSSLService.java | 19 +++--- 7 files changed, 93 insertions(+), 90 deletions(-) rename src/main/java/de/mlessmann/certassist/{openssl/CertificateRequest.java => models/CertificateInfo.java} (50%) rename src/main/java/de/mlessmann/certassist/{openssl/CertificateRequestExtension.java => models/CertificateInfoExtension.java} (64%) rename src/main/java/de/mlessmann/certassist/{openssl/CertificateSubject.java => models/CertificateInfoSubject.java} (56%) diff --git a/src/main/java/de/mlessmann/certassist/openssl/CertificateRequest.java b/src/main/java/de/mlessmann/certassist/models/CertificateInfo.java similarity index 50% rename from src/main/java/de/mlessmann/certassist/openssl/CertificateRequest.java rename to src/main/java/de/mlessmann/certassist/models/CertificateInfo.java index 4b519d1..a870b27 100644 --- a/src/main/java/de/mlessmann/certassist/openssl/CertificateRequest.java +++ b/src/main/java/de/mlessmann/certassist/models/CertificateInfo.java @@ -1,11 +1,11 @@ -package de.mlessmann.certassist.openssl; +package de.mlessmann.certassist.models; import lombok.Builder; import lombok.Data; @Data @Builder -public class CertificateRequest { +public class CertificateInfo { private RequestType type; private String trustingAuthority; @@ -16,9 +16,9 @@ public class CertificateRequest { @Builder.Default private int requestedValidityDays = 365; - private CertificateSubject subject; - private CertificateSubject issuer; - private CertificateRequestExtension extension; + private CertificateInfoSubject subject; + private CertificateInfoSubject issuer; + private CertificateInfoExtension extension; public enum RequestType { ROOT_AUTHORITY, @@ -26,21 +26,19 @@ public class CertificateRequest { NORMAL_CERTIFICATE, } - public static class CertificateRequestBuilder { + public static class CertificateInfoBuilder { - public CertificateRequestBuilder subject(CertificateSubject.CertificateSubjectBuilder builder) { + public CertificateInfoBuilder subject(CertificateInfoSubject.CertificateInfoSubjectBuilder builder) { this.subject = builder.build(); return this; } - public CertificateRequestBuilder issuer(CertificateSubject.CertificateSubjectBuilder builder) { + public CertificateInfoBuilder issuer(CertificateInfoSubject.CertificateInfoSubjectBuilder builder) { this.issuer = builder.build(); return this; } - public CertificateRequestBuilder extension( - CertificateRequestExtension.CertificateRequestExtensionBuilder builder - ) { + public CertificateInfoBuilder extension(CertificateInfoExtension.CertificateInfoExtensionBuilder builder) { this.extension = builder.build(); return this; } diff --git a/src/main/java/de/mlessmann/certassist/openssl/CertificateRequestExtension.java b/src/main/java/de/mlessmann/certassist/models/CertificateInfoExtension.java similarity index 64% rename from src/main/java/de/mlessmann/certassist/openssl/CertificateRequestExtension.java rename to src/main/java/de/mlessmann/certassist/models/CertificateInfoExtension.java index 853dbeb..d90f27b 100644 --- a/src/main/java/de/mlessmann/certassist/openssl/CertificateRequestExtension.java +++ b/src/main/java/de/mlessmann/certassist/models/CertificateInfoExtension.java @@ -1,4 +1,4 @@ -package de.mlessmann.certassist.openssl; +package de.mlessmann.certassist.models; import java.util.List; import java.util.Objects; @@ -8,15 +8,15 @@ import lombok.Getter; @Getter @Builder -public class CertificateRequestExtension { +public class CertificateInfoExtension { - private List alternativeNames; + private List alternativeDnsNames; - public static class CertificateRequestExtensionBuilder { + public static class CertificateInfoExtensionBuilder { - public CertificateRequestExtensionBuilder alternativeNames(String... altNames) { + public CertificateInfoExtensionBuilder alternativeDnsNames(String... altNames) { Objects.requireNonNull(altNames, "Alternative names must not be null (but can be empty)"); - this.alternativeNames = + this.alternativeDnsNames = Stream .of(altNames) .filter(Objects::nonNull) diff --git a/src/main/java/de/mlessmann/certassist/openssl/CertificateSubject.java b/src/main/java/de/mlessmann/certassist/models/CertificateInfoSubject.java similarity index 56% rename from src/main/java/de/mlessmann/certassist/openssl/CertificateSubject.java rename to src/main/java/de/mlessmann/certassist/models/CertificateInfoSubject.java index 4d5f302..48ec520 100644 --- a/src/main/java/de/mlessmann/certassist/openssl/CertificateSubject.java +++ b/src/main/java/de/mlessmann/certassist/models/CertificateInfoSubject.java @@ -1,11 +1,11 @@ -package de.mlessmann.certassist.openssl; +package de.mlessmann.certassist.models; import lombok.Builder; import lombok.Getter; @Getter @Builder -public class CertificateSubject { +public class CertificateInfoSubject { private String commonName; private String emailAddress; @@ -15,5 +15,7 @@ public class CertificateSubject { private String state; private String locality; - public static class CertificateSubjectBuilder {} + public static class CertificateInfoSubjectBuilder { + // Class only exists to allow the builder to be statically imported. + } } diff --git a/src/main/java/de/mlessmann/certassist/openssl/OpenSSLService.java b/src/main/java/de/mlessmann/certassist/openssl/OpenSSLService.java index 2e3530c..5286e35 100644 --- a/src/main/java/de/mlessmann/certassist/openssl/OpenSSLService.java +++ b/src/main/java/de/mlessmann/certassist/openssl/OpenSSLService.java @@ -1,15 +1,26 @@ package de.mlessmann.certassist.openssl; -import static de.mlessmann.certassist.Constants.CERTASSIST_TMP_PREFIX; -import static java.util.concurrent.TimeUnit.*; -import static org.slf4j.LoggerFactory.getLogger; - import de.mlessmann.certassist.DeleteRecursiveFileVisitor; import de.mlessmann.certassist.except.CommandLineOperationException; import de.mlessmann.certassist.except.UnresolvableCLIDependency; -import de.mlessmann.certassist.openssl.CertificateRequest.RequestType; -import de.mlessmann.certassist.openssl.CertificateSubject.CertificateSubjectBuilder; +import de.mlessmann.certassist.models.CertificateInfo; +import de.mlessmann.certassist.models.CertificateInfo.RequestType; +import de.mlessmann.certassist.models.CertificateInfoExtension; +import de.mlessmann.certassist.models.CertificateInfoSubject; +import de.mlessmann.certassist.models.CertificateInfoSubject.CertificateInfoSubjectBuilder; import de.mlessmann.certassist.service.ExecutableResolver; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.springframework.lang.NonNull; +import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; +import org.zeroturnaround.exec.ProcessExecutor; +import org.zeroturnaround.exec.ProcessResult; +import org.zeroturnaround.exec.StartedProcess; +import org.zeroturnaround.exec.stream.slf4j.Slf4jStream; + import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; @@ -25,17 +36,10 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.springframework.lang.NonNull; -import org.springframework.stereotype.Service; -import org.springframework.util.CollectionUtils; -import org.zeroturnaround.exec.ProcessExecutor; -import org.zeroturnaround.exec.ProcessResult; -import org.zeroturnaround.exec.StartedProcess; -import org.zeroturnaround.exec.stream.slf4j.Slf4jStream; + +import static de.mlessmann.certassist.Constants.CERTASSIST_TMP_PREFIX; +import static java.util.concurrent.TimeUnit.*; +import static org.slf4j.LoggerFactory.getLogger; @Service @RequiredArgsConstructor @@ -65,7 +69,7 @@ public class OpenSSLService { private final CertificatePasswordProvider passwordProvider; private final CertificateProvider certificateProvider; - private static String buildSubjectArg(CertificateRequest request) { + private static String buildSubjectArg(CertificateInfo request) { String certSubject = OPENSSL_CERT_SUBJECT_TEMPLATE .replace("ISO-COUNTRY", request.getSubject().getCountry()) .replace("STATE", request.getSubject().getState()) @@ -103,7 +107,7 @@ public class OpenSSLService { } @NonNull - public OpenSSLCertificateResult createCertificate(CertificateRequest request) throws CommandLineOperationException { + public OpenSSLCertificateResult createCertificate(CertificateInfo request) throws CommandLineOperationException { Path tmpDir; try { tmpDir = Files.createTempDirectory(CERTASSIST_TMP_PREFIX); @@ -150,7 +154,7 @@ public class OpenSSLService { } } - private Path createKeyfile(CertificateRequest request, Path outFile, String filePassword) + private Path createKeyfile(CertificateInfo request, Path outFile, String filePassword) throws CommandLineOperationException { Path keyFile = outFile.toAbsolutePath(); log.debug("Writing new certificate key to {}", keyFile); @@ -182,7 +186,7 @@ public class OpenSSLService { return keyFile; } - private Path createCertificate(CertificateRequest request, Path keyFile, Path outFile, String keyPassphrase) + private Path createCertificate(CertificateInfo request, Path keyFile, Path outFile, String keyPassphrase) throws CommandLineOperationException { log.debug("Writing new certificate file {}", outFile); @@ -222,7 +226,7 @@ public class OpenSSLService { return outFile; } - private Path createSigningRequest(CertificateRequest request, Path keyFile, Path outFile, String certPassword) + private Path createSigningRequest(CertificateInfo request, Path keyFile, Path outFile, String certPassword) throws CommandLineOperationException { log.atDebug().log("Writing new certificate signing request file {}", outFile); @@ -363,7 +367,7 @@ public class OpenSSLService { } private Path signCertificate( - CertificateRequest request, + CertificateInfo request, Path caCert, Path caKey, String caKeyPassphrase, @@ -377,7 +381,7 @@ public class OpenSSLService { String extContent = CSR_EXT_TEMPLATE; List altNames = Optional .ofNullable(request.getExtension()) - .map(CertificateRequestExtension::getAlternativeNames) + .map(CertificateInfoExtension::getAlternativeDnsNames) .orElse(List.of()); if (!altNames.isEmpty()) { AtomicInteger counter = new AtomicInteger(1); @@ -489,7 +493,7 @@ public class OpenSSLService { } } - public CertificateRequest getCertificateInfo(Path path) throws CommandLineOperationException { + public CertificateInfo getCertificateInfo(Path path) throws CommandLineOperationException { StartedProcess infoProc = null; try { infoProc = @@ -563,14 +567,14 @@ public class OpenSSLService { } } - private CertificateRequest getCertificateInfo(String[] lines) { - var builder = CertificateRequest.builder(); + private CertificateInfo getCertificateInfo(String[] lines) { + var builder = CertificateInfo.builder(); boolean hasIssuer = false; for (int i = 0; i < lines.length; i++) { String line = lines[i]; if (line.startsWith("subject=")) { - CertificateSubjectBuilder subjectBuilder = CertificateSubject.builder(); + var subjectBuilder = CertificateInfoSubject.builder(); line = lines[++i]; while (line.startsWith(" ")) { @@ -580,7 +584,7 @@ public class OpenSSLService { builder = builder.subject(subjectBuilder); } else if (line.startsWith("issuer=")) { hasIssuer = true; - CertificateSubjectBuilder issuerBuilder = CertificateSubject.builder(); + var issuerBuilder = CertificateInfoSubject.builder(); line = lines[++i]; while (line.startsWith(" ")) { @@ -591,7 +595,7 @@ public class OpenSSLService { builder = builder.issuer(issuerBuilder); } else if (line.startsWith("X509v3 Subject Alternative Name")) { String[] altNames = lines[++i].split(","); - builder = builder.extension(CertificateRequestExtension.builder().alternativeNames(altNames)); + builder = builder.extension(CertificateInfoExtension.builder().alternativeDnsNames(altNames)); } } @@ -599,7 +603,7 @@ public class OpenSSLService { return builder.build(); } - private CertificateSubjectBuilder readSubjectInfo(String line, CertificateSubjectBuilder builder) { + private CertificateInfoSubjectBuilder readSubjectInfo(String line, CertificateInfoSubjectBuilder builder) { String[] parts = line.split("=", 2); if (parts.length != 2) { return builder; diff --git a/src/main/java/de/mlessmann/certassist/service/CertificateCreationService.java b/src/main/java/de/mlessmann/certassist/service/CertificateCreationService.java index 7f42002..a9e37c4 100644 --- a/src/main/java/de/mlessmann/certassist/service/CertificateCreationService.java +++ b/src/main/java/de/mlessmann/certassist/service/CertificateCreationService.java @@ -1,9 +1,7 @@ package de.mlessmann.certassist.service; import de.mlessmann.certassist.except.CommandLineOperationException; -import de.mlessmann.certassist.models.Certificate; -import de.mlessmann.certassist.models.CertificateExtension; -import de.mlessmann.certassist.models.CertificateType; +import de.mlessmann.certassist.models.*; import de.mlessmann.certassist.openssl.*; import de.mlessmann.certassist.repositories.CertificateRepository; import java.io.IOException; @@ -22,12 +20,10 @@ public class CertificateCreationService { private final OpenSSLService openSSLService; private final PassphraseService passphraseService; - public Certificate createCertificate(final CertificateRequest certificateRequest) { - final Certificate certificate = createEntityFromRequest(certificateRequest); + public Certificate createCertificate(final CertificateInfo certificateInfo) { + final Certificate certificate = createEntityFromRequest(certificateInfo); - try ( - OpenSSLCertificateResult certificateCreatorResult = openSSLService.createCertificate(certificateRequest); - ) { + try (OpenSSLCertificateResult certificateCreatorResult = openSSLService.createCertificate(certificateInfo);) { certificate.setPrivateKey(Files.readAllBytes(certificateCreatorResult.certificateKeyPath())); certificate.setCert(Files.readAllBytes(certificateCreatorResult.certificatePath())); } catch (CommandLineOperationException | IOException e) { @@ -38,26 +34,26 @@ public class CertificateCreationService { return certificate; } - private Certificate createEntityFromRequest(CertificateRequest certificateRequest) { + private Certificate createEntityFromRequest(CertificateInfo certificateInfo) { final Certificate certificate = new Certificate(); - certificate.setType(mapCertificateRequestType(certificateRequest.getType())); - certificate.setSubjectCommonName(certificateRequest.getSubject().getCommonName()); - certificate.setTrustingAuthority(certificateRequest.getTrustingAuthority()); - certificate.setRequestedKeyLength(certificateRequest.getRequestedKeyLength()); - certificate.setRequestedValidityDays(certificateRequest.getRequestedValidityDays()); - final CertificateSubject certificateSubject = certificateRequest.getSubject(); - certificate.setSubjectEmailAddress(certificateSubject.getEmailAddress()); - certificate.setSubjectOrganization(certificateSubject.getOrganization()); - certificate.setSubjectOrganizationalUnit(certificateSubject.getOrganizationalUnit()); - certificate.setSubjectCountry(certificateSubject.getCountry()); - certificate.setSubjectState(certificateSubject.getState()); - certificate.setSubjectLocality(certificateSubject.getLocality()); + certificate.setType(mapCertificateRequestType(certificateInfo.getType())); + certificate.setSubjectCommonName(certificateInfo.getSubject().getCommonName()); + certificate.setTrustingAuthority(certificateInfo.getTrustingAuthority()); + certificate.setRequestedKeyLength(certificateInfo.getRequestedKeyLength()); + certificate.setRequestedValidityDays(certificateInfo.getRequestedValidityDays()); + final CertificateInfoSubject subjectInfo = certificateInfo.getSubject(); + certificate.setSubjectEmailAddress(subjectInfo.getEmailAddress()); + certificate.setSubjectOrganization(subjectInfo.getOrganization()); + certificate.setSubjectOrganizationalUnit(subjectInfo.getOrganizationalUnit()); + certificate.setSubjectCountry(subjectInfo.getCountry()); + certificate.setSubjectState(subjectInfo.getState()); + certificate.setSubjectLocality(subjectInfo.getLocality()); - final CertificateRequestExtension extension = certificateRequest.getExtension(); + final CertificateInfoExtension extension = certificateInfo.getExtension(); if (extension != null) { final CertificateExtension certificateExtension = new CertificateExtension(); certificateExtension.setIdentifier("alternativeNames"); - certificateExtension.setValue(String.join(",", extension.getAlternativeNames())); + certificateExtension.setValue(String.join(",", extension.getAlternativeDnsNames())); certificate.setCertificateExtension(List.of(certificateExtension)); } return certificate; @@ -79,7 +75,7 @@ public class CertificateCreationService { } } - private CertificateType mapCertificateRequestType(CertificateRequest.RequestType requestType) { + private CertificateType mapCertificateRequestType(CertificateInfo.RequestType requestType) { return switch (requestType) { case ROOT_AUTHORITY -> CertificateType.ROOT_CA; case STANDALONE_CERTIFICATE -> CertificateType.STANDALONE_CERT; diff --git a/src/test/java/de/mlessmann/certassist/CertificateServiceTest.java b/src/test/java/de/mlessmann/certassist/CertificateServiceTest.java index 563d451..38f00f0 100644 --- a/src/test/java/de/mlessmann/certassist/CertificateServiceTest.java +++ b/src/test/java/de/mlessmann/certassist/CertificateServiceTest.java @@ -2,9 +2,9 @@ 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.models.CertificateInfo; +import de.mlessmann.certassist.models.CertificateInfoExtension; +import de.mlessmann.certassist.models.CertificateInfoSubject; import de.mlessmann.certassist.service.CertificateCreationService; import java.nio.file.Path; import org.junit.jupiter.api.Test; @@ -19,11 +19,11 @@ public class CertificateServiceTest { @Test void testCanCreateCertificate() { - var request = CertificateRequest + var request = CertificateInfo .builder() - .type(CertificateRequest.RequestType.STANDALONE_CERTIFICATE) + .type(CertificateInfo.RequestType.STANDALONE_CERTIFICATE) .subject( - CertificateSubject + CertificateInfoSubject .builder() .commonName("cert.creation") .country("DE") @@ -31,7 +31,7 @@ public class CertificateServiceTest { .locality("HH") .organization("Crazy-Cats") ) - .extension(CertificateRequestExtension.builder().alternativeNames("test2.home", "test3.home")) + .extension(CertificateInfoExtension.builder().alternativeDnsNames("test2.home", "test3.home")) .build(); var cert = certificateService.createCertificate(request); assertThat(cert).isNotNull(); diff --git a/src/test/java/de/mlessmann/certassist/TestOpenSSLService.java b/src/test/java/de/mlessmann/certassist/TestOpenSSLService.java index ae3133f..2055b4f 100644 --- a/src/test/java/de/mlessmann/certassist/TestOpenSSLService.java +++ b/src/test/java/de/mlessmann/certassist/TestOpenSSLService.java @@ -3,8 +3,11 @@ package de.mlessmann.certassist; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.*; +import de.mlessmann.certassist.models.CertificateInfo; +import de.mlessmann.certassist.models.CertificateInfo.RequestType; +import de.mlessmann.certassist.models.CertificateInfoExtension; +import de.mlessmann.certassist.models.CertificateInfoSubject; import de.mlessmann.certassist.openssl.*; -import de.mlessmann.certassist.openssl.CertificateRequest.RequestType; import de.mlessmann.certassist.service.ExecutableResolver; import java.nio.file.Path; import java.util.Objects; @@ -38,11 +41,11 @@ class TestOpenSSLService { ExecutableResolver executableResolver = new ExecutableResolver(); var certificateCreator = new OpenSSLService(executableResolver, passwordProvider, certificateProvider); - CertificateRequest certRequest = CertificateRequest + CertificateInfo certRequest = CertificateInfo .builder() .type(RequestType.STANDALONE_CERTIFICATE) .subject( - CertificateSubject + CertificateInfoSubject .builder() .commonName("test.home") .country("DE") @@ -50,7 +53,7 @@ class TestOpenSSLService { .locality("HH") .organization("Crazy-Cats") ) - .extension(CertificateRequestExtension.builder().alternativeNames("test2.home", "test3.home")) + .extension(CertificateInfoExtension.builder().alternativeDnsNames("test2.home", "test3.home")) .build(); try (var cert = certificateCreator.createCertificate(certRequest)) { @@ -61,12 +64,12 @@ class TestOpenSSLService { .withFailMessage(ERR_NOT_ENCRYPTED) .isTrue(); - CertificateRequest childRequest = CertificateRequest + CertificateInfo childRequest = CertificateInfo .builder() .type(RequestType.NORMAL_CERTIFICATE) .trustingAuthority(cert.fingerprint()) .subject( - CertificateSubject + CertificateInfoSubject .builder() .commonName("test.local") .country("DE") @@ -74,7 +77,7 @@ class TestOpenSSLService { .locality("HH") .organization("Crazy-Cats") ) - .extension(CertificateRequestExtension.builder().alternativeNames("test2.local", "test3.local")) + .extension(CertificateInfoExtension.builder().alternativeDnsNames("test2.local", "test3.local")) .build(); var spiedCert = spy(cert); @@ -116,6 +119,6 @@ class TestOpenSSLService { assertThat(request.getSubject().getState()).isEqualTo("SH"); assertThat(request.getSubject().getLocality()).isEqualTo("HH"); assertThat(request.getSubject().getOrganization()).isEqualTo("Crazy-Cats"); - assertThat(request.getExtension().getAlternativeNames()).containsExactly("test2.local", "test3.local"); + assertThat(request.getExtension().getAlternativeDnsNames()).containsExactly("test2.local", "test3.local"); } }