Skip to content

Commit c691742

Browse files
equanzsrinath-ctds
authored andcommitted
[fix][client] Fixed an issue where a cert chain could not be used in TLS authentication (apache#23644)
(cherry picked from commit e236d61) (cherry picked from commit e0e1956)
1 parent 89d241e commit c691742

File tree

2 files changed

+61
-9
lines changed

2 files changed

+61
-9
lines changed

pulsar-common/src/main/java/org/apache/pulsar/common/util/KeyManagerProxy.java

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,14 @@
3030
import java.security.Principal;
3131
import java.security.PrivateKey;
3232
import java.security.UnrecoverableKeyException;
33+
import java.security.cert.Certificate;
3334
import java.security.cert.CertificateException;
3435
import java.security.cert.CertificateFactory;
3536
import java.security.cert.X509Certificate;
37+
import java.util.List;
3638
import java.util.concurrent.ScheduledExecutorService;
3739
import java.util.concurrent.TimeUnit;
40+
import java.util.stream.Collectors;
3841
import javax.net.ssl.KeyManagerFactory;
3942
import javax.net.ssl.SSLEngine;
4043
import javax.net.ssl.X509ExtendedKeyManager;
@@ -88,18 +91,16 @@ private void updateKeyManager()
8891
return;
8992
}
9093

91-
X509Certificate certificate;
92-
PrivateKey privateKey = null;
93-
KeyStore keyStore;
94-
try (InputStream publicCertStream = new FileInputStream(certFile.getFileName());
95-
InputStream privateKeyStream = new FileInputStream(keyFile.getFileName())) {
94+
final KeyStore keyStore;
95+
try (InputStream publicCertStream = new FileInputStream(certFile.getFileName())) {
9696
final CertificateFactory cf = CertificateFactory.getInstance("X.509");
97-
certificate = (X509Certificate) cf.generateCertificate(publicCertStream);
97+
final List<X509Certificate> certificateList = cf.generateCertificates(publicCertStream)
98+
.stream().map(o -> (X509Certificate) o).collect(Collectors.toList());
9899
keyStore = KeyStore.getInstance("JKS");
99-
String alias = certificate.getSubjectX500Principal().getName();
100-
privateKey = SecurityUtility.loadPrivateKeyFromPemFile(keyFile.getFileName());
100+
final String alias = certificateList.get(0).getSubjectX500Principal().getName();
101+
final PrivateKey privateKey = SecurityUtility.loadPrivateKeyFromPemFile(keyFile.getFileName());
101102
keyStore.load(null);
102-
keyStore.setKeyEntry(alias, privateKey, KEYSTORE_PASSWORD, new X509Certificate[] { certificate });
103+
keyStore.setKeyEntry(alias, privateKey, KEYSTORE_PASSWORD, certificateList.toArray(new Certificate[0]));
103104
} catch (IOException | KeyManagementException e) {
104105
throw new IllegalArgumentException(e);
105106
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.apache.pulsar.common.util;
21+
22+
import static org.testng.Assert.assertEquals;
23+
import com.google.common.io.Resources;
24+
import java.util.concurrent.Executors;
25+
import java.util.concurrent.ScheduledExecutorService;
26+
import lombok.Cleanup;
27+
import org.testng.annotations.DataProvider;
28+
import org.testng.annotations.Test;
29+
30+
public class KeyManagerProxyTest {
31+
32+
@DataProvider(name = "certDataProvider")
33+
public static Object[][] caDataProvider() {
34+
return new Object[][]{
35+
{"ca/multiple-ca.pem", 2},
36+
{"ca/single-ca.pem", 1}
37+
};
38+
}
39+
40+
@Test(dataProvider = "certDataProvider")
41+
public void testLoadCert(String path, int certCount) {
42+
final String certFilePath = Resources.getResource(path).getPath();
43+
// This key is not paired with certs, but this is not a problem as the key is not used in this test
44+
final String keyFilePath = Resources.getResource("ssl/my-ca/client-key.pem").getPath();
45+
@Cleanup("shutdownNow")
46+
final ScheduledExecutorService scheduledExecutor = Executors.newSingleThreadScheduledExecutor();
47+
48+
final KeyManagerProxy keyManager = new KeyManagerProxy(certFilePath, keyFilePath, 60, scheduledExecutor);
49+
assertEquals(keyManager.getCertificateChain("cn=test1").length, certCount);
50+
}
51+
}

0 commit comments

Comments
 (0)