From cf8af6d6ce0be3dd565b1f7a14f0648d482b3e42 Mon Sep 17 00:00:00 2001 From: Bjørn Christian Seime Date: Thu, 14 May 2020 16:58:07 +0200 Subject: Expose underlying certificate and private key from SiaIdentityProvider Extend ServiceIdentityProvider interface with new methods. Add class that bundles certificate with private key. Use Path instead of File for better compatibility with mocked file system in unit tests. --- .../com/yahoo/security/X509CertificateWithKey.java | 33 ++++++++++++++++++++++ .../security/tls/AutoReloadingX509KeyManager.java | 10 ++++++- 2 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 security-utils/src/main/java/com/yahoo/security/X509CertificateWithKey.java (limited to 'security-utils/src') diff --git a/security-utils/src/main/java/com/yahoo/security/X509CertificateWithKey.java b/security-utils/src/main/java/com/yahoo/security/X509CertificateWithKey.java new file mode 100644 index 00000000000..4772de5c1fb --- /dev/null +++ b/security-utils/src/main/java/com/yahoo/security/X509CertificateWithKey.java @@ -0,0 +1,33 @@ +// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.security; + +import java.security.PrivateKey; +import java.security.cert.X509Certificate; +import java.util.Collections; +import java.util.List; + +/** + * Wraps a {@link java.security.cert.X509Certificate} with its {@link java.security.PrivateKey}. + * Primary motivation is APIs where the callee must correctly observe an atomic update of both certificate and key. + * + * @author bjorncs + */ +public class X509CertificateWithKey { + + private final List certificate; + private final PrivateKey privateKey; + + public X509CertificateWithKey(X509Certificate certificate, PrivateKey privateKey) { + this(Collections.singletonList(certificate), privateKey); + } + + public X509CertificateWithKey(List certificate, PrivateKey privateKey) { + if (certificate.isEmpty()) throw new IllegalArgumentException(); + this.certificate = certificate; + this.privateKey = privateKey; + } + + public X509Certificate certificate() { return certificate.get(0); } + public List certificateWithIntermediates() { return certificate; } + public PrivateKey privateKey() { return privateKey; } +} diff --git a/security-utils/src/main/java/com/yahoo/security/tls/AutoReloadingX509KeyManager.java b/security-utils/src/main/java/com/yahoo/security/tls/AutoReloadingX509KeyManager.java index 18764f51dc5..d4e74e22e40 100644 --- a/security-utils/src/main/java/com/yahoo/security/tls/AutoReloadingX509KeyManager.java +++ b/security-utils/src/main/java/com/yahoo/security/tls/AutoReloadingX509KeyManager.java @@ -5,19 +5,20 @@ import com.yahoo.security.KeyStoreBuilder; import com.yahoo.security.KeyStoreType; import com.yahoo.security.KeyUtils; import com.yahoo.security.X509CertificateUtils; +import com.yahoo.security.X509CertificateWithKey; import javax.net.ssl.SSLEngine; import javax.net.ssl.X509ExtendedKeyManager; import java.io.IOException; import java.io.UncheckedIOException; import java.net.Socket; -import java.nio.file.Files; import java.nio.file.Path; import java.security.KeyStore; import java.security.Principal; import java.security.PrivateKey; import java.security.cert.X509Certificate; import java.time.Duration; +import java.util.Arrays; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; @@ -59,6 +60,13 @@ public class AutoReloadingX509KeyManager extends X509ExtendedKeyManager implemen return new AutoReloadingX509KeyManager(privateKeyFile, certificatesFile); } + public X509CertificateWithKey getCurrentCertificateWithKey() { + X509ExtendedKeyManager manager = mutableX509KeyManager.currentManager(); + X509Certificate[] certificateChain = manager.getCertificateChain(CERTIFICATE_ALIAS); + PrivateKey privateKey = manager.getPrivateKey(CERTIFICATE_ALIAS); + return new X509CertificateWithKey(Arrays.asList(certificateChain), privateKey); + } + private static KeyStore createKeystore(Path privateKey, Path certificateChain) { try { return KeyStoreBuilder.withType(KeyStoreType.PKCS12) -- cgit v1.2.3