home-cert-assistant/src/test/java/de/mlessmann/certassist/TestKeystoreCreation.java

113 lines
4.7 KiB
Java

package de.mlessmann.certassist;
import static org.assertj.core.api.Assertions.assertThat;
import de.mlessmann.certassist.keystore.KeyStoreManager;
import de.mlessmann.certassist.openssl.CertificateProvider;
import de.mlessmann.certassist.openssl.CertificateUsage;
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;
import java.security.SecureRandom;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
public class TestKeystoreCreation {
private static final String STORE_PASSPHRASE = "changeit";
private static final SecureRandom TEST_RANDOM = new SecureRandom();
private final CertificateUsage dummyCert = new CertificateUsage() {
@Override
public String fingerprint() {
return TestOpenSSLService.TEST_CERT_FINGERPRINT;
}
@Override
public Path certificatePath() {
return TestOpenSSLService.TEST_CERT_PATH.resolve("x509forImport.pem");
}
@Override
public Path certificateKeyPath() {
return TestOpenSSLService.TEST_CERT_PATH.resolve("x509forImport.key.pem");
}
@Override
public Path fullchainPath() {
return TestOpenSSLService.TEST_CERT_PATH.resolve("x509forImport.fullchain.pem");
}
};
@Test
void testTruststore() throws Exception {
var passwordProvider = new InMemoryCertificatePasswordProvider();
passwordProvider.setPasswordFor(dummyCert.fingerprint(), TestOpenSSLService.TEST_CERT_PASSPHRASE);
var certificateProvider = Mockito.mock(CertificateProvider.class);
var opensslCertCreator = new OpenSSLService(new ExecutableResolver(), passwordProvider, certificateProvider);
var keyStoreManager = new KeyStoreManager(opensslCertCreator, passwordProvider);
AtomicBoolean serverAccepted = new AtomicBoolean(false);
AtomicBoolean clientAccepted = new AtomicBoolean(false);
try (
var tmpTruststore = keyStoreManager.createTruststore(STORE_PASSPHRASE, dummyCert);
var tmpKeyStore = keyStoreManager.createKeyStore(STORE_PASSPHRASE, dummyCert)
) {
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(
KeyManagerFactory.getDefaultAlgorithm()
);
keyManagerFactory.init(tmpTruststore.readAsKeystore(STORE_PASSPHRASE), STORE_PASSPHRASE.toCharArray());
SSLContext tlsSrvContext = SSLContext.getInstance("TLS");
tlsSrvContext.init(keyManagerFactory.getKeyManagers(), null, TEST_RANDOM);
ServerSocket serverSocket = tlsSrvContext.getServerSocketFactory().createServerSocket(0);
var serverThread = Thread.startVirtualThread(() -> {
try {
var remote = serverSocket.accept();
serverAccepted.set(true);
try {
Thread.sleep(2_000);
} catch (InterruptedException e) {
// nothing
}
remote.close();
} catch (IOException e) {
throw new IllegalStateException("Failed to create server socket!", e);
}
});
var trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(tmpTruststore.readAsKeystore(STORE_PASSPHRASE));
SSLContext tlsContext = SSLContext.getInstance("TLS");
tlsContext.init(null, trustManagerFactory.getTrustManagers(), TEST_RANDOM);
var clientThread = Thread.startVirtualThread(() -> {
try {
var socket = tlsContext.getSocketFactory().createSocket("127.0.0.1", serverSocket.getLocalPort());
clientAccepted.set(true);
socket.close();
} catch (IOException e) {
throw new IllegalStateException("Failed to create client socket!", e);
}
});
serverThread.join();
clientThread.join();
if (!serverSocket.isClosed()) {
serverSocket.close();
}
assertThat(serverAccepted.get()).withFailMessage("Server did not accept connection!").isTrue();
assertThat(clientAccepted.get()).withFailMessage("Client did not accept connection!").isTrue();
}
}
}