chore: Refactor packages/classes a little to update the PoC architecture a bit #18
15 changed files with 179 additions and 117 deletions
12
.github/workflows/build.yml
vendored
12
.github/workflows/build.yml
vendored
|
@ -20,6 +20,18 @@ jobs:
|
|||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: 21
|
||||
- name: Update environment variables based on PR labels
|
||||
id: pr-env
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const labels = context.payload.pull_request.labels.map(label => label.name);
|
||||
console.log('PR labels:', labels);
|
||||
const springDebug = labels.includes('pr-debug');
|
||||
return { SPRING_DEBUG: '' + springDebug };
|
||||
result-encoding: json
|
||||
- uses: gradle/actions/setup-gradle@v4
|
||||
- name: Build gradle project
|
||||
run: ./gradlew build
|
||||
env:
|
||||
ORG_GRADLE_PROJECT_SPRING_DEBUG: ${{ fromJSON(steps.pr-env.outputs.result).SPRING_DEBUG }}
|
|
@ -7,6 +7,7 @@ plugins {
|
|||
|
||||
group = "io.github.markl4yg.hca"
|
||||
version = "0.0.1-SNAPSHOT"
|
||||
val springDebugLogging = providers.gradleProperty("SPRING_DEBUG").orNull == "true"
|
||||
|
||||
apply(
|
||||
from = file("./gradle/spotless.gradle")
|
||||
|
@ -57,6 +58,13 @@ dependencies {
|
|||
|
||||
tasks.withType<Test> {
|
||||
useJUnitPlatform()
|
||||
if (springDebugLogging) {
|
||||
// Additional Hibernate logging
|
||||
jvmArgs("-Dlogging.level.org.sqlite=DEBUG")
|
||||
jvmArgs("-Dlogging.level.org.hibernate=DEBUG")
|
||||
jvmArgs("-Dhibernate.show_sql=true")
|
||||
jvmArgs("-Dhibernate.format_sql=true")
|
||||
}
|
||||
|
||||
systemProperty("spring.profiles.active", "test")
|
||||
jvmArgs("-XX:+EnableDynamicAgentLoading") // DynamicAgentLoading for byteBuddy within Mockito
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
package de.mlessmann.certassist.keystore;
|
||||
|
||||
import de.mlessmann.certassist.openssl.CertificatePasswordProvider;
|
||||
import de.mlessmann.certassist.openssl.OpenSSLService;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class AutoBootKeyStoreManagement {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(KeyStoreManager.class)
|
||||
public KeyStoreManager keystoreProvider(
|
||||
OpenSSLService certificateCreator,
|
||||
CertificatePasswordProvider passwordProvider
|
||||
) {
|
||||
return new KeyStoreManager(certificateCreator, passwordProvider);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(TruststoreManager.class)
|
||||
public TruststoreManager truststoreProvider() {
|
||||
return new TruststoreManager();
|
||||
}
|
||||
}
|
|
@ -3,7 +3,7 @@ package de.mlessmann.certassist.keystore;
|
|||
import de.mlessmann.certassist.except.JavaSecurityException;
|
||||
import de.mlessmann.certassist.openssl.CertificatePasswordProvider;
|
||||
import de.mlessmann.certassist.openssl.CertificateUsage;
|
||||
import de.mlessmann.certassist.openssl.OpenSSLCertificateCreator;
|
||||
import de.mlessmann.certassist.openssl.OpenSSLService;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.OpenOption;
|
||||
|
@ -27,7 +27,7 @@ public class KeyStoreManager {
|
|||
StandardOpenOption.CREATE,
|
||||
StandardOpenOption.TRUNCATE_EXISTING,
|
||||
};
|
||||
private final OpenSSLCertificateCreator certificateCreator;
|
||||
private final OpenSSLService certificateCreator;
|
||||
private final CertificatePasswordProvider passwordProvider;
|
||||
|
||||
public KeystoreUsage createKeyStore(String keyStorePassphrase, CertificateUsage... serverCerts)
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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<String> alternativeNames;
|
||||
private List<String> 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)
|
|
@ -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.
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package de.mlessmann.certassist.openssl;
|
||||
|
||||
import de.mlessmann.certassist.service.ExecutableResolver;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class AutoBootOpenSSL {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(CertificatePasswordProvider.class)
|
||||
public CertificatePasswordProvider usageProvider() {
|
||||
return new InMemoryCertificatePasswordProvider();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(CertificatePasswordProvider.class)
|
||||
public OpenSSLService openSSLProvider(
|
||||
ExecutableResolver executableResolver,
|
||||
CertificatePasswordProvider passwordProvider,
|
||||
CertificateProvider usageProvider
|
||||
) {
|
||||
return new OpenSSLService(executableResolver, passwordProvider, usageProvider);
|
||||
}
|
||||
}
|
|
@ -1,15 +1,13 @@
|
|||
package de.mlessmann.certassist.service;
|
||||
package de.mlessmann.certassist.openssl;
|
||||
|
||||
import de.mlessmann.certassist.openssl.CertificatePasswordProvider;
|
||||
import de.mlessmann.certassist.service.PassphraseService;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.stereotype.Service;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Service
|
||||
@ConditionalOnMissingBean(CertificatePasswordProvider.class)
|
||||
@Slf4j
|
||||
public class InMemoryCertificatePasswordProvider implements CertificatePasswordProvider {
|
||||
|
||||
private final Map<String, String> passwords = new ConcurrentHashMap<>();
|
||||
|
@ -22,11 +20,13 @@ public class InMemoryCertificatePasswordProvider implements CertificatePasswordP
|
|||
|
||||
@Override
|
||||
public String getPasswordFor(String certificateFingerprint) {
|
||||
log.trace("Getting password for certificate fingerprint: {}", certificateFingerprint);
|
||||
return Optional.ofNullable(passwords.get(certificateFingerprint)).orElseThrow();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPasswordFor(String certificateFingerprint, String password) {
|
||||
log.trace("Setting password for certificate fingerprint: {}", certificateFingerprint);
|
||||
Objects.requireNonNull(certificateFingerprint);
|
||||
Objects.requireNonNull(password);
|
||||
passwords.put(certificateFingerprint, password);
|
|
@ -5,11 +5,14 @@ import static java.util.concurrent.TimeUnit.*;
|
|||
import static org.slf4j.LoggerFactory.getLogger;
|
||||
|
||||
import de.mlessmann.certassist.DeleteRecursiveFileVisitor;
|
||||
import de.mlessmann.certassist.ExecutableResolver;
|
||||
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 java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
|
@ -40,7 +43,7 @@ import org.zeroturnaround.exec.stream.slf4j.Slf4jStream;
|
|||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
public class OpenSSLCertificateCreator {
|
||||
public class OpenSSLService {
|
||||
|
||||
private static final Logger openSSLLogger = getLogger("OpenSSL-Logger");
|
||||
public static final String OPENSSL_CERT_SUBJECT_TEMPLATE =
|
||||
|
@ -65,7 +68,7 @@ public class OpenSSLCertificateCreator {
|
|||
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 +106,7 @@ public class OpenSSLCertificateCreator {
|
|||
}
|
||||
|
||||
@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 +153,7 @@ public class OpenSSLCertificateCreator {
|
|||
}
|
||||
}
|
||||
|
||||
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 +185,7 @@ public class OpenSSLCertificateCreator {
|
|||
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 +225,7 @@ public class OpenSSLCertificateCreator {
|
|||
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 +366,7 @@ public class OpenSSLCertificateCreator {
|
|||
}
|
||||
|
||||
private Path signCertificate(
|
||||
CertificateRequest request,
|
||||
CertificateInfo request,
|
||||
Path caCert,
|
||||
Path caKey,
|
||||
String caKeyPassphrase,
|
||||
|
@ -377,7 +380,7 @@ public class OpenSSLCertificateCreator {
|
|||
String extContent = CSR_EXT_TEMPLATE;
|
||||
List<String> altNames = Optional
|
||||
.ofNullable(request.getExtension())
|
||||
.map(CertificateRequestExtension::getAlternativeNames)
|
||||
.map(CertificateInfoExtension::getAlternativeDnsNames)
|
||||
.orElse(List.of());
|
||||
if (!altNames.isEmpty()) {
|
||||
AtomicInteger counter = new AtomicInteger(1);
|
||||
|
@ -489,7 +492,7 @@ public class OpenSSLCertificateCreator {
|
|||
}
|
||||
}
|
||||
|
||||
public CertificateRequest getCertificateInfo(Path path) throws CommandLineOperationException {
|
||||
public CertificateInfo getCertificateInfo(Path path) throws CommandLineOperationException {
|
||||
StartedProcess infoProc = null;
|
||||
try {
|
||||
infoProc =
|
||||
|
@ -563,14 +566,14 @@ public class OpenSSLCertificateCreator {
|
|||
}
|
||||
}
|
||||
|
||||
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 +583,7 @@ public class OpenSSLCertificateCreator {
|
|||
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 +594,7 @@ public class OpenSSLCertificateCreator {
|
|||
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 +602,7 @@ public class OpenSSLCertificateCreator {
|
|||
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;
|
|
@ -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;
|
||||
|
@ -19,17 +17,13 @@ import org.springframework.stereotype.Service;
|
|||
public class CertificateCreationService {
|
||||
|
||||
private final CertificateRepository certificateRepository;
|
||||
private final OpenSSLCertificateCreator openSSLCertificateCreator;
|
||||
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 = openSSLCertificateCreator.createCertificate(
|
||||
certificateRequest
|
||||
);
|
||||
) {
|
||||
try (OpenSSLCertificateResult certificateCreatorResult = openSSLService.createCertificate(certificateInfo);) {
|
||||
certificate.setPrivateKey(Files.readAllBytes(certificateCreatorResult.certificateKeyPath()));
|
||||
certificate.setCert(Files.readAllBytes(certificateCreatorResult.certificatePath()));
|
||||
} catch (CommandLineOperationException | IOException e) {
|
||||
|
@ -40,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;
|
||||
|
@ -67,8 +61,8 @@ public class CertificateCreationService {
|
|||
|
||||
public Certificate importCertificate(Path certificate, Path keyFile, String passphrase) {
|
||||
try {
|
||||
String fingerprint = openSSLCertificateCreator.getCertificateFingerprint(certificate);
|
||||
var generatedRequest = openSSLCertificateCreator.getCertificateInfo(certificate);
|
||||
String fingerprint = openSSLService.getCertificateFingerprint(certificate);
|
||||
var generatedRequest = openSSLService.getCertificateInfo(certificate);
|
||||
Certificate entity = createEntityFromRequest(generatedRequest);
|
||||
entity.setCert(Files.readAllBytes(certificate));
|
||||
entity.setPrivateKey(Files.readAllBytes(keyFile));
|
||||
|
@ -81,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;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package de.mlessmann.certassist;
|
||||
package de.mlessmann.certassist.service;
|
||||
|
||||
import de.mlessmann.certassist.except.UnresolvableCLIDependency;
|
||||
import java.io.File;
|
|
@ -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();
|
||||
|
@ -40,11 +40,11 @@ public class CertificateServiceTest {
|
|||
|
||||
@Test
|
||||
void testCanImportCertificate() {
|
||||
Path certDir = TestOpenSSLCertificateCreator.TEST_CERT_PATH;
|
||||
Path certDir = TestOpenSSLService.TEST_CERT_PATH;
|
||||
var importedCert = certificateService.importCertificate(
|
||||
certDir.resolve("x509forImport.pem"),
|
||||
certDir.resolve("x509forImport.key.pem"),
|
||||
TestOpenSSLCertificateCreator.TEST_CERT_PASSPHRASE
|
||||
TestOpenSSLService.TEST_CERT_PASSPHRASE
|
||||
);
|
||||
assertThat(importedCert).isNotNull();
|
||||
assertThat(importedCert.getId()).isGreaterThan("0");
|
||||
|
|
|
@ -6,8 +6,9 @@ import de.mlessmann.certassist.keystore.KeyStoreManager;
|
|||
import de.mlessmann.certassist.keystore.TruststoreManager;
|
||||
import de.mlessmann.certassist.openssl.CertificateProvider;
|
||||
import de.mlessmann.certassist.openssl.CertificateUsage;
|
||||
import de.mlessmann.certassist.openssl.OpenSSLCertificateCreator;
|
||||
import de.mlessmann.certassist.service.InMemoryCertificatePasswordProvider;
|
||||
import de.mlessmann.certassist.openssl.InMemoryCertificatePasswordProvider;
|
||||
import de.mlessmann.certassist.openssl.OpenSSLService;
|
||||
import de.mlessmann.certassist.service.ExecutableResolver;
|
||||
import java.io.IOException;
|
||||
import java.net.ServerSocket;
|
||||
import java.nio.file.Path;
|
||||
|
@ -26,36 +27,32 @@ public class TestKeystoreCreation {
|
|||
private final CertificateUsage dummyCert = new CertificateUsage() {
|
||||
@Override
|
||||
public String fingerprint() {
|
||||
return TestOpenSSLCertificateCreator.TEST_CERT_FINGERPRINT;
|
||||
return TestOpenSSLService.TEST_CERT_FINGERPRINT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path certificatePath() {
|
||||
return TestOpenSSLCertificateCreator.TEST_CERT_PATH.resolve("x509forImport.pem");
|
||||
return TestOpenSSLService.TEST_CERT_PATH.resolve("x509forImport.pem");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path certificateKeyPath() {
|
||||
return TestOpenSSLCertificateCreator.TEST_CERT_PATH.resolve("x509forImport.key.pem");
|
||||
return TestOpenSSLService.TEST_CERT_PATH.resolve("x509forImport.key.pem");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path fullchainPath() {
|
||||
return TestOpenSSLCertificateCreator.TEST_CERT_PATH.resolve("x509forImport.fullchain.pem");
|
||||
return TestOpenSSLService.TEST_CERT_PATH.resolve("x509forImport.fullchain.pem");
|
||||
}
|
||||
};
|
||||
|
||||
@Test
|
||||
void testTruststore() throws Exception {
|
||||
var passwordProvider = new InMemoryCertificatePasswordProvider();
|
||||
passwordProvider.setPasswordFor(dummyCert.fingerprint(), TestOpenSSLCertificateCreator.TEST_CERT_PASSPHRASE);
|
||||
passwordProvider.setPasswordFor(dummyCert.fingerprint(), TestOpenSSLService.TEST_CERT_PASSPHRASE);
|
||||
|
||||
var certificateProvider = Mockito.mock(CertificateProvider.class);
|
||||
var opensslCertCreator = new OpenSSLCertificateCreator(
|
||||
new ExecutableResolver(),
|
||||
passwordProvider,
|
||||
certificateProvider
|
||||
);
|
||||
var opensslCertCreator = new OpenSSLService(new ExecutableResolver(), passwordProvider, certificateProvider);
|
||||
var truststoreManager = new TruststoreManager();
|
||||
var keyStoreManager = new KeyStoreManager(opensslCertCreator, passwordProvider);
|
||||
AtomicBoolean serverAccepted = new AtomicBoolean(false);
|
||||
|
|
|
@ -3,8 +3,12 @@ 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;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
|
@ -13,7 +17,7 @@ import org.springframework.boot.test.context.SpringBootTest;
|
|||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
|
||||
@SpringBootTest
|
||||
class TestOpenSSLCertificateCreator {
|
||||
class TestOpenSSLService {
|
||||
|
||||
public static final String TEST_CERT_PASSPHRASE = "ABC-123";
|
||||
public static final Path TEST_CERT_PATH = Path.of("src/test/resources/openssl");
|
||||
|
@ -35,17 +39,13 @@ class TestOpenSSLCertificateCreator {
|
|||
void testCertificateCreation() throws Exception {
|
||||
CertificateProvider certificateProvider = mock(CertificateProvider.class);
|
||||
ExecutableResolver executableResolver = new ExecutableResolver();
|
||||
var certificateCreator = new OpenSSLCertificateCreator(
|
||||
executableResolver,
|
||||
passwordProvider,
|
||||
certificateProvider
|
||||
);
|
||||
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")
|
||||
|
@ -53,7 +53,7 @@ class TestOpenSSLCertificateCreator {
|
|||
.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)) {
|
||||
|
@ -64,12 +64,12 @@ class TestOpenSSLCertificateCreator {
|
|||
.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")
|
||||
|
@ -77,7 +77,7 @@ class TestOpenSSLCertificateCreator {
|
|||
.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);
|
||||
|
@ -101,11 +101,7 @@ class TestOpenSSLCertificateCreator {
|
|||
void testCertificateImport() throws Exception {
|
||||
CertificateProvider certificateProvider = mock(CertificateProvider.class);
|
||||
ExecutableResolver executableResolver = new ExecutableResolver();
|
||||
var certificateCreator = new OpenSSLCertificateCreator(
|
||||
executableResolver,
|
||||
passwordProvider,
|
||||
certificateProvider
|
||||
);
|
||||
var certificateCreator = new OpenSSLService(executableResolver, passwordProvider, certificateProvider);
|
||||
|
||||
var request = certificateCreator.getCertificateInfo(TEST_CERT_PATH.resolve("x509forImportCA.pem"));
|
||||
assertThat(request).isNotNull();
|
||||
|
@ -123,6 +119,6 @@ class TestOpenSSLCertificateCreator {
|
|||
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");
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue