feat: Implement way of retrieving CAs in signing process

This commit is contained in:
Magnus Leßmann (@MarkL4YG) 2024-11-19 23:02:27 +01:00
parent ef141568b7
commit cc33015674
Signed by: Mark.TwoFive
GPG key ID: 5B5EBCBE331F1E6F
4 changed files with 53 additions and 17 deletions

View file

@ -0,0 +1,11 @@
package de.mlessmann.certassist.openssl;
/**
* Accessor interface to the certificate storage.
*/
public interface CertificateProvider {
/**
* A stored certificate is needed (e.g. for command line operations when signing sub certificates).
*/
CertificateUsage requestCertificateUsage(String fingerprint);
}

View file

@ -0,0 +1,17 @@
package de.mlessmann.certassist.openssl;
import java.nio.file.Path;
/**
* Instance of a certificate that is temporarily stored on disk to be available for use in command line calls.
* The instance implements AutoCloseable to enable cleanup after the stored files are no longer needed.
* @implSpec The files should be removed from disk when the instance is closed, UNLESS the provided paths are the permanent storage location for the certificate files.
*/
public interface CertificateUsage extends AutoCloseable {
Path certificatePath();
Path certificateKeyPath();
String fingerprint();
@Override
void close();
}

View file

@ -47,6 +47,7 @@ public class OpenSSLCertificateCreator {
private final ExecutableResolver executableResolver;
private final CertPasswordProvider passwordProvider;
private final CertificateProvider certificateProvider;
private static String buildSubjectArg(CertificateRequest request) {
String certSubject = OPENSSL_CERT_SUBJECT_TEMPLATE
@ -77,21 +78,23 @@ public class OpenSSLCertificateCreator {
}
String certPassword = passwordProvider.generateNewPassword();
Path keyFile = createKeyfile(request, tmpDir.resolve("root.key"), certPassword);
Path rootCert = createCertificate(request, keyFile, tmpDir.resolve("root.crt"), certPassword);
Path keyFile = createKeyfile(request, tmpDir.resolve("certificate.key"), certPassword);
if (
request.getType() == RequestType.ROOT_AUTHORITY || request.getType() == RequestType.STANDALONE_CERTIFICATE
) {
String fingerprint = getCertificateFingerprint(rootCert);
return new OpenSSLCertificateResult(tmpDir, rootCert, keyFile, fingerprint);
Path certificate = createCertificate(request, keyFile, tmpDir.resolve("certificate.crt"), certPassword);
String fingerprint = getCertificateFingerprint(certificate);
passwordProvider.setPasswordFor(fingerprint, certPassword);
return new OpenSSLCertificateResult(tmpDir, certificate, keyFile, fingerprint);
}
Path childKey = createKeyfile(request, tmpDir.resolve("child.key"), certPassword);
Path unsignedCert = createSigningRequest(request, childKey, tmpDir.resolve("child.csr"), certPassword);
Path signedCert = signCertificate(request, rootCert, keyFile, unsignedCert, certPassword);
String fingerPrint = getCertificateFingerprint(signedCert);
passwordProvider.setPasswordFor(fingerPrint, certPassword);
return new OpenSSLCertificateResult(tmpDir, signedCert, childKey, fingerPrint);
try (var certAuthority = certificateProvider.requestCertificateUsage(request.getTrustingAuthority())) {
Path unsignedCert = createSigningRequest(request, keyFile, tmpDir.resolve("child.csr"), certPassword);
Path signedCert = signCertificate(request, certAuthority.certificatePath(), certAuthority.certificateKeyPath(), unsignedCert, certPassword);
String fingerprint = getCertificateFingerprint(signedCert);
passwordProvider.setPasswordFor(fingerprint, certPassword);
return new OpenSSLCertificateResult(tmpDir, signedCert, keyFile, fingerprint);
}
}
private Path createKeyfile(CertificateRequest request, Path outFile, String filePassword)

View file

@ -11,19 +11,24 @@ import org.junit.jupiter.api.Test;
class TestOpenSSLCertificateCreator {
private OpenSSLCertificateCreator openSSLCertificateCreator;
private CertPasswordProvider passwordProvider;
@BeforeEach
void setUp() {
CertPasswordProvider passwordProvider = mock(CertPasswordProvider.class);
passwordProvider = mock(CertPasswordProvider.class);
when(passwordProvider.generateNewPassword()).thenReturn("ABC-123");
ExecutableResolver executableResolver = new ExecutableResolver();
openSSLCertificateCreator = new OpenSSLCertificateCreator(executableResolver, passwordProvider);
}
@Test
void testCertificateCreation() throws Exception {
CertificateProvider certificateProvider = mock(CertificateProvider.class);
ExecutableResolver executableResolver = new ExecutableResolver();
var certificateCreator = new OpenSSLCertificateCreator(
executableResolver,
passwordProvider,
certificateProvider
);
CertificateRequest certRequest = CertificateRequest
.builder()
.commonName("test.home")
@ -32,8 +37,8 @@ class TestOpenSSLCertificateCreator {
.extension(CertificateRequestExtension.builder().alternativeNames("test2.home", "test3.home"))
.build();
try (var cert = openSSLCertificateCreator.createCertificate(certRequest)) {
assertThat(openSSLCertificateCreator.verifyCertificate(cert.getCertificatePath())).isEqualTo(true);
try (var cert = certificateCreator.createCertificate(certRequest)) {
assertThat(certificateCreator.verifyCertificate(cert.getCertificatePath())).isEqualTo(true);
System.out.println("Certificate created: " + cert);
}
}