From fe8263404bd40d0e605853d10c9a20e91471a205 Mon Sep 17 00:00:00 2001 From: Bjørn Christian Seime Date: Mon, 11 Feb 2019 13:25:23 +0100 Subject: Add x509 key manager that regularly updates cert chain from PEM files --- .../tls/AutoReloadingX509KeyManagerTest.java | 84 ++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 security-utils/src/test/java/com/yahoo/security/tls/AutoReloadingX509KeyManagerTest.java (limited to 'security-utils/src/test/java') diff --git a/security-utils/src/test/java/com/yahoo/security/tls/AutoReloadingX509KeyManagerTest.java b/security-utils/src/test/java/com/yahoo/security/tls/AutoReloadingX509KeyManagerTest.java new file mode 100644 index 00000000000..139d5313074 --- /dev/null +++ b/security-utils/src/test/java/com/yahoo/security/tls/AutoReloadingX509KeyManagerTest.java @@ -0,0 +1,84 @@ +// Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.security.tls; + +import com.yahoo.security.KeyAlgorithm; +import com.yahoo.security.KeyUtils; +import com.yahoo.security.SignatureAlgorithm; +import com.yahoo.security.X509CertificateBuilder; +import com.yahoo.security.X509CertificateUtils; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import org.mockito.ArgumentCaptor; +import org.mockito.Mockito; + +import javax.security.auth.x500.X500Principal; +import java.io.IOException; +import java.math.BigInteger; +import java.nio.file.Files; +import java.nio.file.Path; +import java.security.KeyPair; +import java.security.Principal; +import java.security.cert.X509Certificate; +import java.time.Instant; +import java.util.concurrent.ScheduledExecutorService; + +import static java.time.temporal.ChronoUnit.DAYS; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyLong; +import static org.mockito.Mockito.verify; + +/** + * @author bjorncs + */ +public class AutoReloadingX509KeyManagerTest { + private static final X500Principal SUBJECT = new X500Principal("CN=dummy"); + + @Rule + public TemporaryFolder tempDirectory = new TemporaryFolder(); + + @Test + public void crypto_material_is_reloaded_when_scheduler_task_is_executed() throws IOException { + KeyPair keyPair = KeyUtils.generateKeypair(KeyAlgorithm.EC); + Path privateKeyFile = tempDirectory.newFile().toPath(); + Files.writeString(privateKeyFile, KeyUtils.toPem(keyPair.getPrivate())); + + Path certificateFile = tempDirectory.newFile().toPath(); + BigInteger serialNumberInitialCertificate = BigInteger.ONE; + X509Certificate initialCertificate = generateCertificate(keyPair, serialNumberInitialCertificate); + Files.writeString(certificateFile, X509CertificateUtils.toPem(initialCertificate)); + + ScheduledExecutorService scheduler = Mockito.mock(ScheduledExecutorService.class); + ArgumentCaptor updaterTaskCaptor = ArgumentCaptor.forClass(Runnable.class); + + AutoReloadingX509KeyManager keyManager = new AutoReloadingX509KeyManager(privateKeyFile, certificateFile, scheduler); + verify(scheduler).scheduleAtFixedRate(updaterTaskCaptor.capture(), anyLong(), anyLong(), any()); + + String[] initialAliases = keyManager.getClientAliases(keyPair.getPublic().getAlgorithm(), new Principal[]{SUBJECT}); + X509Certificate[] certChain = keyManager.getCertificateChain(initialAliases[0]); + assertThat(certChain).hasSize(1); + assertThat(certChain[0].getSerialNumber()).isEqualTo(serialNumberInitialCertificate); + + BigInteger serialNumberUpdatedCertificate = BigInteger.TWO; + X509Certificate updatedCertificate = generateCertificate(keyPair, serialNumberUpdatedCertificate); + Files.writeString(certificateFile, X509CertificateUtils.toPem(updatedCertificate)); + + updaterTaskCaptor.getValue().run(); // run update task in ReloadingX509KeyManager + + String[] updatedAliases = keyManager.getClientAliases(keyPair.getPublic().getAlgorithm(), new Principal[]{SUBJECT}); + X509Certificate[] updatedCertChain = keyManager.getCertificateChain(updatedAliases[0]); + assertThat(updatedCertChain).hasSize(1); + assertThat(updatedCertChain[0].getSerialNumber()).isEqualTo(serialNumberUpdatedCertificate); + } + + private static X509Certificate generateCertificate(KeyPair keyPair, BigInteger serialNumber) { + return X509CertificateBuilder.fromKeypair(keyPair, + SUBJECT, + Instant.EPOCH, + Instant.EPOCH.plus(1, DAYS), + SignatureAlgorithm.SHA256_WITH_ECDSA, + serialNumber) + .build(); + } +} \ No newline at end of file -- cgit v1.2.3