diff --git a/zookeeper-server/src/main/java/org/apache/zookeeper/util/PemReader.java b/zookeeper-server/src/main/java/org/apache/zookeeper/util/PemReader.java index dd5a1576401..a3f20061b4c 100644 --- a/zookeeper-server/src/main/java/org/apache/zookeeper/util/PemReader.java +++ b/zookeeper-server/src/main/java/org/apache/zookeeper/util/PemReader.java @@ -92,9 +92,10 @@ public static KeyStore loadTrustStore(File certificateChainFile) throws IOExcept keyStore.load(null, null); List certificateChain = readCertificateChain(certificateChainFile); + int i = 1; for (X509Certificate certificate : certificateChain) { X500Principal principal = certificate.getSubjectX500Principal(); - keyStore.setCertificateEntry(principal.getName("RFC2253"), certificate); + keyStore.setCertificateEntry(principal.getName("RFC2253") + "-" + i++, certificate); } return keyStore; } diff --git a/zookeeper-server/src/test/java/org/apache/zookeeper/common/PEMFileLoaderTest.java b/zookeeper-server/src/test/java/org/apache/zookeeper/common/PEMFileLoaderTest.java index ee9a68eb7ad..c179192623b 100644 --- a/zookeeper-server/src/test/java/org/apache/zookeeper/common/PEMFileLoaderTest.java +++ b/zookeeper-server/src/test/java/org/apache/zookeeper/common/PEMFileLoaderTest.java @@ -108,7 +108,7 @@ public void testLoadKeyStoreWithWrongFileType( @ParameterizedTest @MethodSource("data") - public void testLoadTrustStore( + public void testLoadTrustStoreFromPemBundle( X509KeyType caKeyType, X509KeyType certKeyType, String keyPassword, Integer paramIndex) throws Exception { init(caKeyType, certKeyType, keyPassword, paramIndex); @@ -118,7 +118,7 @@ public void testLoadTrustStore( .setTrustStorePassword(x509TestContext.getTrustStorePassword()) .build() .loadTrustStore(); - assertEquals(1, ts.size()); + assertEquals(2, ts.size()); } @ParameterizedTest diff --git a/zookeeper-server/src/test/java/org/apache/zookeeper/common/X509TestContext.java b/zookeeper-server/src/test/java/org/apache/zookeeper/common/X509TestContext.java index 2bb759e639f..0acd4181c7c 100644 --- a/zookeeper-server/src/test/java/org/apache/zookeeper/common/X509TestContext.java +++ b/zookeeper-server/src/test/java/org/apache/zookeeper/common/X509TestContext.java @@ -29,6 +29,7 @@ import java.security.Security; import java.security.cert.X509Certificate; import java.util.Arrays; +import java.util.List; import org.apache.commons.io.FileUtils; import org.bouncycastle.asn1.x500.X500NameBuilder; import org.bouncycastle.asn1.x500.style.BCStyle; @@ -48,7 +49,7 @@ public class X509TestContext { private final X509KeyType trustStoreKeyType; private final KeyPair trustStoreKeyPair; private final long trustStoreCertExpirationMillis; - private final X509Certificate trustStoreCertificate; + private final List trustStoreCertificates; private final String trustStorePassword; private File trustStoreJksFile; private File trustStorePemFile; @@ -99,11 +100,18 @@ private X509TestContext(File tempDir, KeyPair trustStoreKeyPair, long trustStore X500NameBuilder caNameBuilder = new X500NameBuilder(BCStyle.INSTANCE); caNameBuilder.addRDN(BCStyle.CN, MethodHandles.lookup().lookupClass().getCanonicalName() + " Root CA"); - trustStoreCertificate = X509TestHelpers.newSelfSignedCACert(caNameBuilder.build(), trustStoreKeyPair, trustStoreCertExpirationMillis); + // Create two CA certs to test multiple certs in PEM bundles. + // Use same subject name to simulate multiple CA certs from the same CA and to test reg + trustStoreCertificates = Arrays.asList( + X509TestHelpers.newSelfSignedCACert(caNameBuilder.build(), trustStoreKeyPair, + trustStoreCertExpirationMillis), + X509TestHelpers.newSelfSignedCACert(caNameBuilder.build(), trustStoreKeyPair, + trustStoreCertExpirationMillis) + ); X500NameBuilder nameBuilder = new X500NameBuilder(BCStyle.INSTANCE); nameBuilder.addRDN(BCStyle.CN, MethodHandles.lookup().lookupClass().getCanonicalName() + " Zookeeper Test"); - keyStoreCertificate = X509TestHelpers.newCert(trustStoreCertificate, trustStoreKeyPair, nameBuilder.build(), keyStoreKeyPair.getPublic(), keyStoreCertExpirationMillis); + keyStoreCertificate = X509TestHelpers.newCert(trustStoreCertificates.get(0), trustStoreKeyPair, nameBuilder.build(), keyStoreKeyPair.getPublic(), keyStoreCertExpirationMillis); trustStorePkcs12File = trustStorePemFile = trustStoreJksFile = null; keyStorePkcs12File = keyStorePemFile = keyStoreJksFile = null; @@ -139,8 +147,8 @@ public long getTrustStoreCertExpirationMillis() { return trustStoreCertExpirationMillis; } - public X509Certificate getTrustStoreCertificate() { - return trustStoreCertificate; + public X509Certificate getTrustStoreCertificates() { + return trustStoreCertificates.get(0); } public String getTrustStorePassword() { @@ -159,7 +167,7 @@ public File getTrustStoreFile(KeyStoreFileType storeFileType) throws IOException case JKS: return getTrustStoreJksFile(); case PEM: - return getTrustStorePemFile(); + return getTrustStorePemBundleFile(); case PKCS12: return getTrustStorePkcs12File(); case BCFKS: @@ -177,7 +185,7 @@ private File getTrustStoreJksFile() throws IOException { File trustStoreJksFile = File.createTempFile(TRUST_STORE_PREFIX, KeyStoreFileType.JKS.getDefaultFileExtension(), tempDir); trustStoreJksFile.deleteOnExit(); try (final FileOutputStream trustStoreOutputStream = new FileOutputStream(trustStoreJksFile)) { - byte[] bytes = X509TestHelpers.certToJavaTrustStoreBytes(trustStoreCertificate, trustStorePassword); + byte[] bytes = X509TestHelpers.certToJavaTrustStoreBytes(trustStoreCertificates.get(0), trustStorePassword); trustStoreOutputStream.write(bytes); trustStoreOutputStream.flush(); } catch (GeneralSecurityException e) { @@ -188,11 +196,13 @@ private File getTrustStoreJksFile() throws IOException { return trustStoreJksFile; } - private File getTrustStorePemFile() throws IOException { + private File getTrustStorePemBundleFile() throws IOException { if (trustStorePemFile == null) { File trustStorePemFile = File.createTempFile(TRUST_STORE_PREFIX, KeyStoreFileType.PEM.getDefaultFileExtension(), tempDir); trustStorePemFile.deleteOnExit(); - FileUtils.writeStringToFile(trustStorePemFile, X509TestHelpers.pemEncodeX509Certificate(trustStoreCertificate), StandardCharsets.US_ASCII, false); + for (X509Certificate cert : trustStoreCertificates) { + FileUtils.writeStringToFile(trustStorePemFile, X509TestHelpers.pemEncodeX509Certificate(cert), StandardCharsets.US_ASCII, true); + } this.trustStorePemFile = trustStorePemFile; } return trustStorePemFile; @@ -203,7 +213,7 @@ private File getTrustStorePkcs12File() throws IOException { File trustStorePkcs12File = File.createTempFile(TRUST_STORE_PREFIX, KeyStoreFileType.PKCS12.getDefaultFileExtension(), tempDir); trustStorePkcs12File.deleteOnExit(); try (final FileOutputStream trustStoreOutputStream = new FileOutputStream(trustStorePkcs12File)) { - byte[] bytes = X509TestHelpers.certToPKCS12TrustStoreBytes(trustStoreCertificate, trustStorePassword); + byte[] bytes = X509TestHelpers.certToPKCS12TrustStoreBytes(trustStoreCertificates.get(0), trustStorePassword); trustStoreOutputStream.write(bytes); trustStoreOutputStream.flush(); } catch (GeneralSecurityException e) { @@ -220,7 +230,7 @@ private File getTrustStoreBcfksFile() throws IOException { TRUST_STORE_PREFIX, KeyStoreFileType.BCFKS.getDefaultFileExtension(), tempDir); trustStoreBcfksFile.deleteOnExit(); try (final FileOutputStream trustStoreOutputStream = new FileOutputStream(trustStoreBcfksFile)) { - byte[] bytes = X509TestHelpers.certToBCFKSTrustStoreBytes(trustStoreCertificate, trustStorePassword); + byte[] bytes = X509TestHelpers.certToBCFKSTrustStoreBytes(trustStoreCertificates.get(0), trustStorePassword); trustStoreOutputStream.write(bytes); trustStoreOutputStream.flush(); } catch (GeneralSecurityException e) { diff --git a/zookeeper-server/src/test/java/org/apache/zookeeper/util/PemReaderTest.java b/zookeeper-server/src/test/java/org/apache/zookeeper/util/PemReaderTest.java index d584c28da9d..29bf18c0828 100644 --- a/zookeeper-server/src/test/java/org/apache/zookeeper/util/PemReaderTest.java +++ b/zookeeper-server/src/test/java/org/apache/zookeeper/util/PemReaderTest.java @@ -135,8 +135,8 @@ public void testLoadCertificateFromTrustStore( throws Exception { init(caKeyType, certKeyType, keyPassword, paramIndex); List certs = PemReader.readCertificateChain(x509TestContext.getTrustStoreFile(KeyStoreFileType.PEM)); - assertEquals(1, certs.size()); - assertEquals(x509TestContext.getTrustStoreCertificate(), certs.get(0)); + assertEquals(2, certs.size()); + assertEquals(x509TestContext.getTrustStoreCertificates(), certs.get(0)); } }