From caefe964b1950bf5b4d7f774da30e478499efa2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Magnus=20Le=C3=9Fmann=20=28=40MarkL4YG=29?= Date: Sun, 17 Nov 2024 20:20:58 +0100 Subject: [PATCH] chore: Run spotless --- .../DeleteRecursiveFileVisitor.java | 7 +- .../certassist/ExecutableResolver.java | 19 +-- .../except/UnresolvableCLIDependency.java | 7 +- .../openssl/CertificateRequest.java | 13 +- .../openssl/CertificateRequestExtension.java | 4 +- .../openssl/OpenSSLCertificateCreator.java | 138 ++++++++++++++---- .../openssl/OpenSSLCertificateResult.java | 7 +- .../TestOpenSSLCertificateCreator.java | 8 +- 8 files changed, 146 insertions(+), 57 deletions(-) diff --git a/src/main/java/de/mlessmann/certassist/DeleteRecursiveFileVisitor.java b/src/main/java/de/mlessmann/certassist/DeleteRecursiveFileVisitor.java index f8c501e..8310eca 100644 --- a/src/main/java/de/mlessmann/certassist/DeleteRecursiveFileVisitor.java +++ b/src/main/java/de/mlessmann/certassist/DeleteRecursiveFileVisitor.java @@ -1,7 +1,6 @@ package de.mlessmann.certassist; -import org.slf4j.Logger; -import org.springframework.lang.NonNull; +import static org.slf4j.LoggerFactory.getLogger; import java.io.IOException; import java.nio.file.FileVisitResult; @@ -9,8 +8,8 @@ import java.nio.file.FileVisitor; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.attribute.BasicFileAttributes; - -import static org.slf4j.LoggerFactory.getLogger; +import org.slf4j.Logger; +import org.springframework.lang.NonNull; public class DeleteRecursiveFileVisitor implements FileVisitor { diff --git a/src/main/java/de/mlessmann/certassist/ExecutableResolver.java b/src/main/java/de/mlessmann/certassist/ExecutableResolver.java index e2a10b6..8ae0cd0 100644 --- a/src/main/java/de/mlessmann/certassist/ExecutableResolver.java +++ b/src/main/java/de/mlessmann/certassist/ExecutableResolver.java @@ -1,20 +1,18 @@ package de.mlessmann.certassist; -import de.mlessmann.certassist.except.UnresolvableCLIDependency; -import lombok.Setter; -import org.apache.commons.lang3.SystemUtils; -import org.slf4j.Logger; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Service; +import static org.slf4j.LoggerFactory.getLogger; +import de.mlessmann.certassist.except.UnresolvableCLIDependency; import java.io.File; import java.nio.file.Files; import java.nio.file.Path; import java.util.List; import java.util.Objects; import java.util.Optional; - -import static org.slf4j.LoggerFactory.getLogger; +import org.apache.commons.lang3.SystemUtils; +import org.slf4j.Logger; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; @Service public class ExecutableResolver { @@ -53,7 +51,10 @@ public class ExecutableResolver { } } - LOGGER.error("Could not find executable '{}' in PATH. Make sure that it exists on the of the directory and is executable.", executableName); + LOGGER.error( + "Could not find executable '{}' in PATH. Make sure that it exists on the of the directory and is executable.", + executableName + ); return Optional.empty(); } diff --git a/src/main/java/de/mlessmann/certassist/except/UnresolvableCLIDependency.java b/src/main/java/de/mlessmann/certassist/except/UnresolvableCLIDependency.java index 908823f..08d106d 100644 --- a/src/main/java/de/mlessmann/certassist/except/UnresolvableCLIDependency.java +++ b/src/main/java/de/mlessmann/certassist/except/UnresolvableCLIDependency.java @@ -9,7 +9,12 @@ public class UnresolvableCLIDependency extends Exception { private final String propertyName; public UnresolvableCLIDependency(String executableName, String propertyName) { - super("Could not resolve executable for '%s'. (Use property '%s' to point the application directly to the executable.)".formatted(executableName, propertyName)); + super( + "Could not resolve executable for '%s'. (Use property '%s' to point the application directly to the executable.)".formatted( + executableName, + propertyName + ) + ); this.executableName = executableName; this.propertyName = propertyName; } diff --git a/src/main/java/de/mlessmann/certassist/openssl/CertificateRequest.java b/src/main/java/de/mlessmann/certassist/openssl/CertificateRequest.java index d6aa45b..4d6ab9d 100644 --- a/src/main/java/de/mlessmann/certassist/openssl/CertificateRequest.java +++ b/src/main/java/de/mlessmann/certassist/openssl/CertificateRequest.java @@ -1,10 +1,9 @@ package de.mlessmann.certassist.openssl; +import java.util.UUID; import lombok.Builder; import lombok.Data; -import java.util.UUID; - @Data @Builder public class CertificateRequest { @@ -15,26 +14,32 @@ public class CertificateRequest { private RequestType type; private String commonName; private String trustingAuthority; + @Builder.Default private int requestedKeyLength = 4096; + @Builder.Default private int requestedValidityDays = 365; + private CertificateSubject subject; private CertificateRequestExtension extension; public enum RequestType { ROOT_AUTHORITY, STANDALONE_CERTIFICATE, - NORMAL_CERTIFICATE + NORMAL_CERTIFICATE, } public static class CertificateRequestBuilder { + public CertificateRequestBuilder subject(CertificateSubject.CertificateSubjectBuilder builder) { this.subject = builder.build(); return this; } - public CertificateRequestBuilder extension(CertificateRequestExtension.CertificateRequestExtensionBuilder builder) { + public CertificateRequestBuilder extension( + CertificateRequestExtension.CertificateRequestExtensionBuilder 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/openssl/CertificateRequestExtension.java index f28e94e..4350717 100644 --- a/src/main/java/de/mlessmann/certassist/openssl/CertificateRequestExtension.java +++ b/src/main/java/de/mlessmann/certassist/openssl/CertificateRequestExtension.java @@ -1,10 +1,9 @@ package de.mlessmann.certassist.openssl; +import java.util.List; import lombok.Builder; import lombok.Getter; -import java.util.List; - @Getter @Builder public class CertificateRequestExtension { @@ -12,6 +11,7 @@ public class CertificateRequestExtension { private List alternativeNames; public static class CertificateRequestExtensionBuilder { + public CertificateRequestExtensionBuilder alternativeNames(String... altNames) { this.alternativeNames = List.of(altNames); 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 c571ae5..1649335 100644 --- a/src/main/java/de/mlessmann/certassist/openssl/OpenSSLCertificateCreator.java +++ b/src/main/java/de/mlessmann/certassist/openssl/OpenSSLCertificateCreator.java @@ -1,8 +1,18 @@ package de.mlessmann.certassist.openssl; +import static org.slf4j.LoggerFactory.getLogger; + import de.mlessmann.certassist.ExecutableResolver; import de.mlessmann.certassist.except.CommandLineOperationException; import de.mlessmann.certassist.except.UnresolvableCLIDependency; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardOpenOption; +import java.util.List; +import java.util.Optional; +import java.util.concurrent.ExecutionException; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.springframework.beans.factory.annotation.Autowired; @@ -12,30 +22,21 @@ import org.zeroturnaround.exec.ProcessExecutor; 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; -import java.nio.file.Path; -import java.nio.file.StandardOpenOption; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.ExecutionException; - -import static org.slf4j.LoggerFactory.getLogger; - @Service public class OpenSSLCertificateCreator { - public static final String OPENSSL_CERT_SUBJECT_TEMPLATE = "/C=ISO-COUNTRY/ST=STATE/L=LOCALITY/O=ORGANIZATION/CN=COMMON-NAME"; + public static final String OPENSSL_CERT_SUBJECT_TEMPLATE = + "/C=ISO-COUNTRY/ST=STATE/L=LOCALITY/O=ORGANIZATION/CN=COMMON-NAME"; private static final Logger LOGGER = getLogger(OpenSSLCertificateCreator.class); - private static final String CSR_EXT_TEMPLATE = """ - authorityKeyIdentifier=keyid,issuer - basicConstraints=CA:FALSE - keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment - subjectAltName = @alt_names - - [alt_names] - """; + private static final String CSR_EXT_TEMPLATE = + """ + authorityKeyIdentifier=keyid,issuer + basicConstraints=CA:FALSE + keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment + subjectAltName = @alt_names + + [alt_names] + """; private final ExecutableResolver executableResolver; @@ -45,7 +46,12 @@ public class OpenSSLCertificateCreator { } private static String buildSubjectArg(CertificateRequest request) { - String certSubject = OPENSSL_CERT_SUBJECT_TEMPLATE.replace("ISO-COUNTRY", request.getSubject().getCountry()).replace("STATE", request.getSubject().getState()).replace("LOCALITY", request.getSubject().getLocality()).replace("ORGANIZATION", request.getSubject().getOrganization()).replace("COMMON-NAME", request.getCommonName()); + String certSubject = OPENSSL_CERT_SUBJECT_TEMPLATE + .replace("ISO-COUNTRY", request.getSubject().getCountry()) + .replace("STATE", request.getSubject().getState()) + .replace("LOCALITY", request.getSubject().getLocality()) + .replace("ORGANIZATION", request.getSubject().getOrganization()) + .replace("COMMON-NAME", request.getCommonName()); if (StringUtils.isNotBlank(request.getSubject().getOrganizationalUnit())) { certSubject += "/OU=" + request.getSubject().getOrganizationalUnit(); @@ -58,7 +64,8 @@ public class OpenSSLCertificateCreator { } @Nullable - public OpenSSLCertificateResult createCertificate(CertificateRequest request) throws CommandLineOperationException, InterruptedException { + public OpenSSLCertificateResult createCertificate(CertificateRequest request) + throws CommandLineOperationException, InterruptedException { Path tmpDir; try { tmpDir = Files.createTempDirectory("certassist"); @@ -75,12 +82,26 @@ public class OpenSSLCertificateCreator { return new OpenSSLCertificateResult(tmpDir); } - private Path createKeyfile(CertificateRequest request, Path outFile) throws CommandLineOperationException, InterruptedException { + private Path createKeyfile(CertificateRequest request, Path outFile) + throws CommandLineOperationException, InterruptedException { Path keyFile = outFile.toAbsolutePath(); LOGGER.atDebug().log("Writing new certificate key to {}", keyFile); try { - StartedProcess keygenProc = new ProcessExecutor().command(resolveOpenSSL(), "genrsa", "-out", keyFile.toString(), "-passout", "env:KEY_PASS", Integer.toString(request.getRequestedKeyLength())).environment("KEY_PASS", request.getOid()).redirectOutput(Slf4jStream.ofCaller().asDebug()).redirectError(Slf4jStream.ofCaller().asError()).start(); + StartedProcess keygenProc = new ProcessExecutor() + .command( + resolveOpenSSL(), + "genrsa", + "-out", + keyFile.toString(), + "-passout", + "env:KEY_PASS", + Integer.toString(request.getRequestedKeyLength()) + ) + .environment("KEY_PASS", request.getOid()) + .redirectOutput(Slf4jStream.ofCaller().asDebug()) + .redirectError(Slf4jStream.ofCaller().asError()) + .start(); keygenProc.getFuture().get(); } catch (IOException e) { throw new CommandLineOperationException("Failure running OpenSSL keygen command.", e); @@ -90,12 +111,36 @@ public class OpenSSLCertificateCreator { return keyFile; } - private Path createCertificate(CertificateRequest request, Path keyFile, Path outFile) throws CommandLineOperationException, InterruptedException { + private Path createCertificate(CertificateRequest request, Path keyFile, Path outFile) + throws CommandLineOperationException, InterruptedException { LOGGER.atDebug().log("Writing new certificate file {}", outFile); String certSubject = buildSubjectArg(request); try { - StartedProcess certGenProc = new ProcessExecutor().command(resolveOpenSSL(), "req", "-new", "-passin", "env:KEY_PASS", "-key", keyFile.toString(), "-sha256", "-days", Integer.toString(request.getRequestedValidityDays()), "-out", outFile.toString(), "-passout", "env:KEY_PASS", "-utf8", "-subj", certSubject).environment("KEY_PASS", request.getOid()).redirectOutput(Slf4jStream.ofCaller().asDebug()).redirectError(Slf4jStream.ofCaller().asError()).start(); + StartedProcess certGenProc = new ProcessExecutor() + .command( + resolveOpenSSL(), + "req", + "-new", + "-passin", + "env:KEY_PASS", + "-key", + keyFile.toString(), + "-sha256", + "-days", + Integer.toString(request.getRequestedValidityDays()), + "-out", + outFile.toString(), + "-passout", + "env:KEY_PASS", + "-utf8", + "-subj", + certSubject + ) + .environment("KEY_PASS", request.getOid()) + .redirectOutput(Slf4jStream.ofCaller().asDebug()) + .redirectError(Slf4jStream.ofCaller().asError()) + .start(); certGenProc.getFuture().get(); } catch (IOException e) { throw new CommandLineOperationException("Failure running OpenSSL req command.", e); @@ -105,16 +150,18 @@ public class OpenSSLCertificateCreator { return outFile; } - private Path signCertificate(CertificateRequest request, Path caCert, Path caKey, Path csrFile) throws CommandLineOperationException, InterruptedException { + private Path signCertificate(CertificateRequest request, Path caCert, Path caKey, Path csrFile) + throws CommandLineOperationException, InterruptedException { Path outFile = csrFile.resolveSibling(csrFile.getFileName().toString().replace(".csr", ".crt")); LOGGER.atDebug().log("Writing new signed certificate file {}", outFile); Path extFile = csrFile.resolveSibling(csrFile.getFileName().toString().replace(".csr", ".ext")); try { String extContent = CSR_EXT_TEMPLATE; - List altNames = Optional.ofNullable(request.getExtension()) - .map(CertificateRequestExtension::getAlternativeNames) - .orElse(List.of()); + List altNames = Optional + .ofNullable(request.getExtension()) + .map(CertificateRequestExtension::getAlternativeNames) + .orElse(List.of()); if (!altNames.isEmpty()) { String altNamesContent = String.join("\n", altNames); extContent = extContent.replaceAll("\\[alt_names]\n?, ", "[alt_names]\n" + altNamesContent); @@ -124,13 +171,40 @@ public class OpenSSLCertificateCreator { } LOGGER.debug("Writing extension file content: \n {}", extContent); - Files.writeString(extFile, extContent, StandardCharsets.UTF_8, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING); + Files.writeString( + extFile, + extContent, + StandardCharsets.UTF_8, + StandardOpenOption.CREATE, + StandardOpenOption.TRUNCATE_EXISTING + ); } catch (IOException e) { throw new RuntimeException(e); } try { - StartedProcess certGenProc = new ProcessExecutor().command(resolveOpenSSL(), "x509", "-req", "-days", Integer.toString(request.getRequestedValidityDays()), "-in", csrFile.toString(), "-CA", caCert.toString(), "-CAkey", caKey.toString(), "-CAcreateserial", "-out", outFile.toString(), "-extfile", extFile.toString()).redirectOutput(Slf4jStream.ofCaller().asDebug()).redirectError(Slf4jStream.ofCaller().asError()).start(); + StartedProcess certGenProc = new ProcessExecutor() + .command( + resolveOpenSSL(), + "x509", + "-req", + "-days", + Integer.toString(request.getRequestedValidityDays()), + "-in", + csrFile.toString(), + "-CA", + caCert.toString(), + "-CAkey", + caKey.toString(), + "-CAcreateserial", + "-out", + outFile.toString(), + "-extfile", + extFile.toString() + ) + .redirectOutput(Slf4jStream.ofCaller().asDebug()) + .redirectError(Slf4jStream.ofCaller().asError()) + .start(); certGenProc.getFuture().get(); } catch (IOException e) { throw new CommandLineOperationException("Failure running OpenSSL x509 command.", e); diff --git a/src/main/java/de/mlessmann/certassist/openssl/OpenSSLCertificateResult.java b/src/main/java/de/mlessmann/certassist/openssl/OpenSSLCertificateResult.java index a5de8e9..82d4860 100644 --- a/src/main/java/de/mlessmann/certassist/openssl/OpenSSLCertificateResult.java +++ b/src/main/java/de/mlessmann/certassist/openssl/OpenSSLCertificateResult.java @@ -1,14 +1,13 @@ package de.mlessmann.certassist.openssl; -import de.mlessmann.certassist.DeleteRecursiveFileVisitor; -import org.slf4j.Logger; +import static org.slf4j.LoggerFactory.getLogger; +import de.mlessmann.certassist.DeleteRecursiveFileVisitor; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.util.Set; - -import static org.slf4j.LoggerFactory.getLogger; +import org.slf4j.Logger; public class OpenSSLCertificateResult implements AutoCloseable { diff --git a/src/test/java/de/mlessmann/certassist/TestOpenSSLCertificateCreator.java b/src/test/java/de/mlessmann/certassist/TestOpenSSLCertificateCreator.java index 9423509..be4fd7a 100644 --- a/src/test/java/de/mlessmann/certassist/TestOpenSSLCertificateCreator.java +++ b/src/test/java/de/mlessmann/certassist/TestOpenSSLCertificateCreator.java @@ -20,7 +20,13 @@ public class TestOpenSSLCertificateCreator { @Test void testCertificateCreation() throws Exception { - CertificateRequest certRequest = CertificateRequest.builder().commonName("test.home").type(RequestType.STANDALONE_CERTIFICATE).subject(CertificateSubject.builder().country("DE").state("SH").locality("HH").organization("Crazy-Cats")).extension(CertificateRequestExtension.builder().alternativeNames("test2.home", "test3.home")).build(); + CertificateRequest certRequest = CertificateRequest + .builder() + .commonName("test.home") + .type(RequestType.STANDALONE_CERTIFICATE) + .subject(CertificateSubject.builder().country("DE").state("SH").locality("HH").organization("Crazy-Cats")) + .extension(CertificateRequestExtension.builder().alternativeNames("test2.home", "test3.home")) + .build(); try (var cert = openSSLCertificateCreator.createCertificate(certRequest)) { System.out.println("Certificate created: " + cert);