From 627a2a928394fb4cd68eab0050a32edf39370307 Mon Sep 17 00:00:00 2001 From: charlesk40 Date: Thu, 6 Dec 2018 14:49:57 -0800 Subject: [PATCH] Import all certificates to single entry when adding to the keystore (#608) --- .../src/main/java/com/oath/auth/Utils.java | 28 +++++++++--- .../test/java/com/oath/auth/KeyStoreTest.java | 38 +++++++++++++++- .../test/resources/rsa_public_x510_empty.cert | 0 .../rsa_public_x510_w_intermediate.cert | 45 +++++++++++++++++++ 4 files changed, 103 insertions(+), 8 deletions(-) create mode 100644 libs/java/cert_refresher/src/test/resources/rsa_public_x510_empty.cert create mode 100644 libs/java/cert_refresher/src/test/resources/rsa_public_x510_w_intermediate.cert diff --git a/libs/java/cert_refresher/src/main/java/com/oath/auth/Utils.java b/libs/java/cert_refresher/src/main/java/com/oath/auth/Utils.java index 1dd5a7c5df1..4cbcbc8e3a5 100644 --- a/libs/java/cert_refresher/src/main/java/com/oath/auth/Utils.java +++ b/libs/java/cert_refresher/src/main/java/com/oath/auth/Utils.java @@ -20,6 +20,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.net.URL; import java.nio.file.Paths; import java.security.GeneralSecurityException; import java.security.KeyStore; @@ -27,6 +28,7 @@ import java.security.cert.Certificate; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; +import java.util.List; import java.util.concurrent.TimeUnit; import javax.net.ssl.KeyManager; @@ -194,7 +196,7 @@ public static SSLContext buildSSLContext(KeyManagerProxy keyManagerProxy, */ public static KeyStore createKeyStore(final String athenzPublicCert, final String athenzPrivateKey) throws Exception { - X509Certificate certificate; + List certificates; PrivateKey privateKey; KeyStore keyStore; File certFile; @@ -214,8 +216,13 @@ public static KeyStore createKeyStore(final String athenzPublicCert, final Strin Thread.sleep(1000); } } else { - certFile = new File(Utils.class.getClassLoader().getResource(athenzPublicCert).getFile()); - keyFile = new File(Utils.class.getClassLoader().getResource(athenzPrivateKey).getFile()); + URL certURL = Utils.class.getClassLoader().getResource(athenzPublicCert); + URL keyURL = Utils.class.getClassLoader().getResource(athenzPrivateKey); + if (null == certURL || null == keyURL) { + throw new IllegalArgumentException("Certificate or private key file is empty."); + } + certFile = new File(certURL.getFile()); + keyFile = new File(keyURL.getFile()); } } catch (Throwable t) { throw new IllegalArgumentException(t); @@ -237,12 +244,19 @@ public static KeyStore createKeyStore(final String athenzPublicCert, final Strin } else { throw new IllegalStateException("Unknown object type: " + key.getClass().getName()); } - - certificate = (X509Certificate) cf.generateCertificate(publicCertStream); + + certificates = (List) cf.generateCertificates(publicCertStream); + if (certificates.isEmpty()) { + throw new IllegalArgumentException("Certificate file contains empty certificate or an invalid certificate."); + } + //We are going to assume that the first one is the main certificate which will be used for the alias + String alias = ((X509Certificate) certificates.get(0)).getSubjectX500Principal().getName(); + if (LOG.isDebugEnabled()) { + LOG.debug("{} number of certificates found. Using {} alias to create the keystore", certificates.size(), alias); + } keyStore = KeyStore.getInstance("JKS"); - String alias = certificate.getSubjectX500Principal().getName(); keyStore.load(null); - keyStore.setKeyEntry(alias, privateKey, KEYSTORE_PASSWORD, new X509Certificate[]{certificate}); + keyStore.setKeyEntry(alias, privateKey, KEYSTORE_PASSWORD, certificates.toArray(new X509Certificate[certificates.size()])); } catch (IOException e) { throw new IllegalArgumentException(e); diff --git a/libs/java/cert_refresher/src/test/java/com/oath/auth/KeyStoreTest.java b/libs/java/cert_refresher/src/test/java/com/oath/auth/KeyStoreTest.java index acdb9d0eb21..8dbbe2153ed 100644 --- a/libs/java/cert_refresher/src/test/java/com/oath/auth/KeyStoreTest.java +++ b/libs/java/cert_refresher/src/test/java/com/oath/auth/KeyStoreTest.java @@ -15,14 +15,21 @@ */ package com.oath.auth; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.security.KeyStore; +import java.security.cert.X509Certificate; +import java.util.Enumeration; + import org.junit.Test; public class KeyStoreTest { + static final String ALIAS_NAME = "cn=athenz.syncer,o=my test company,l=sunnyvale,st=ca,c=us"; + @Test public void testGetKeyStore() throws Exception { @@ -37,10 +44,39 @@ public void testGetKeyStore() throws Exception { } catch (Exception ignored) { } } - + + @Test public void testCreateKeyStore() throws Exception { KeyStore keyStore = Utils.createKeyStore("rsa_public_x509.cert", "rsa_private.key"); assertNotNull(keyStore); + String alias = null; + for (Enumeration e = keyStore.aliases(); e.hasMoreElements(); ) { + alias = (String)e.nextElement(); + assertEquals(ALIAS_NAME, alias); + } + X509Certificate[] chain = (X509Certificate[]) keyStore.getCertificateChain(alias); + assertNotNull(chain); + assertTrue(chain.length == 1); + } + + @Test + public void testCreateKeyStoreChain() throws Exception { + KeyStore keyStore = Utils.createKeyStore("rsa_public_x510_w_intermediate.cert", "rsa_private.key"); + assertNotNull(keyStore); + String alias = null; + for (Enumeration e = keyStore.aliases(); e.hasMoreElements(); ) { + alias = (String)e.nextElement(); + assertEquals(ALIAS_NAME, alias); + } + + X509Certificate[] chain = (X509Certificate[]) keyStore.getCertificateChain(alias); + assertNotNull(chain); + assertTrue(chain.length == 2); + } + + @Test (expected = IllegalArgumentException.class) + public void testCreateKeyStoreEmpty() throws Exception { + Utils.createKeyStore("rsa_public_x510_empty.cert", "rsa_private.key"); } } diff --git a/libs/java/cert_refresher/src/test/resources/rsa_public_x510_empty.cert b/libs/java/cert_refresher/src/test/resources/rsa_public_x510_empty.cert new file mode 100644 index 00000000000..e69de29bb2d diff --git a/libs/java/cert_refresher/src/test/resources/rsa_public_x510_w_intermediate.cert b/libs/java/cert_refresher/src/test/resources/rsa_public_x510_w_intermediate.cert new file mode 100644 index 00000000000..eef370299ca --- /dev/null +++ b/libs/java/cert_refresher/src/test/resources/rsa_public_x510_w_intermediate.cert @@ -0,0 +1,45 @@ +-----BEGIN CERTIFICATE----- +MIICfzCCAimgAwIBAgIJAMIRugkwe7mwMA0GCSqGSIb3DQEBBQUAMGAxCzAJBgNV +BAYTAlVTMQswCQYDVQQIEwJDQTESMBAGA1UEBxMJU3Vubnl2YWxlMRgwFgYDVQQK +Ew9NeSBUZXN0IENvbXBhbnkxFjAUBgNVBAMTDWF0aGVuei5zeW5jZXIwHhcNMTYx +MjA5MjE1NDQ2WhcNMTcxMjA5MjE1NDQ2WjBgMQswCQYDVQQGEwJVUzELMAkGA1UE +CBMCQ0ExEjAQBgNVBAcTCVN1bm55dmFsZTEYMBYGA1UEChMPTXkgVGVzdCBDb21w +YW55MRYwFAYDVQQDEw1hdGhlbnouc3luY2VyMFwwDQYJKoZIhvcNAQEBBQADSwAw +SAJBANImoEeD7LU+x6x5dAnNRFtrbab2yxrDXFXdwKQxlIs2PWfLeo3Xq0e2bOU6 +kQDgFz/IkMN3tEyDgQ/Nv0eAbckCAwEAAaOBxTCBwjAdBgNVHQ4EFgQUBi0msMNX +iC2XLpKjXPz1DMf9PoEwgZIGA1UdIwSBijCBh4AUBi0msMNXiC2XLpKjXPz1DMf9 +PoGhZKRiMGAxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTESMBAGA1UEBxMJU3Vu +bnl2YWxlMRgwFgYDVQQKEw9NeSBUZXN0IENvbXBhbnkxFjAUBgNVBAMTDWF0aGVu +ei5zeW5jZXKCCQDCEboJMHu5sDAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUA +A0EAPnVkUdicQzk1809lHNyhSqb6p+kxjC52RfI8bZ+kACOppLLCpNu3nuuh+9yT +J1U2YLjE774n48u74k7EEmvJ3A== +-----END CERTIFICATE----- + +-----BEGIN CERTIFICATE----- +MIIEsTCCA5mgAwIBAgIQBOHnpNxc8vNtwCtCuF0VnzANBgkqhkiG9w0BAQsFADBs +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j +ZSBFViBSb290IENBMB4XDTEzMTAyMjEyMDAwMFoXDTI4MTAyMjEyMDAwMFowcDEL +MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3 +LmRpZ2ljZXJ0LmNvbTEvMC0GA1UEAxMmRGlnaUNlcnQgU0hBMiBIaWdoIEFzc3Vy +YW5jZSBTZXJ2ZXIgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC2 +4C/CJAbIbQRf1+8KZAayfSImZRauQkCbztyfn3YHPsMwVYcZuU+UDlqUH1VWtMIC +Kq/QmO4LQNfE0DtyyBSe75CxEamu0si4QzrZCwvV1ZX1QK/IHe1NnF9Xt4ZQaJn1 +itrSxwUfqJfJ3KSxgoQtxq2lnMcZgqaFD15EWCo3j/018QsIJzJa9buLnqS9UdAn +4t07QjOjBSjEuyjMmqwrIw14xnvmXnG3Sj4I+4G3FhahnSMSTeXXkgisdaScus0X +sh5ENWV/UyU50RwKmmMbGZJ0aAo3wsJSSMs5WqK24V3B3aAguCGikyZvFEohQcft +bZvySC/zA/WiaJJTL17jAgMBAAGjggFJMIIBRTASBgNVHRMBAf8ECDAGAQH/AgEA +MA4GA1UdDwEB/wQEAwIBhjAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIw +NAYIKwYBBQUHAQEEKDAmMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2Vy +dC5jb20wSwYDVR0fBEQwQjBAoD6gPIY6aHR0cDovL2NybDQuZGlnaWNlcnQuY29t +L0RpZ2lDZXJ0SGlnaEFzc3VyYW5jZUVWUm9vdENBLmNybDA9BgNVHSAENjA0MDIG +BFUdIAAwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQuY29tL0NQ +UzAdBgNVHQ4EFgQUUWj/kK8CB3U8zNllZGKiErhZcjswHwYDVR0jBBgwFoAUsT7D +aQP4v0cB1JgmGggC72NkK8MwDQYJKoZIhvcNAQELBQADggEBABiKlYkD5m3fXPwd +aOpKj4PWUS+Na0QWnqxj9dJubISZi6qBcYRb7TROsLd5kinMLYBq8I4g4Xmk/gNH +E+r1hspZcX30BJZr01lYPf7TMSVcGDiEo+afgv2MW5gxTs14nhr9hctJqvIni5ly +/D6q1UEL2tU2ob8cbkdJf17ZSHwD2f2LSaCYJkJA69aSEaRkCldUxPUd1gJea6zu +xICaEnL6VpPX/78whQYwvwt/Tv9XBZ0k7YXDK/umdaisLRbvfXknsuvCnQsH6qqF +0wGjIChBWUMo0oHjqvbsezt3tkBigAVBRQHvFwY+3sAzm2fTYS5yh+Rp/BIAV0Ae +cPUeybQ= +-----END CERTIFICATE-----