You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pulsar.apache.org by pe...@apache.org on 2022/07/25 02:10:57 UTC

[pulsar] branch branch-2.10 updated: [improve][security] Add load multiple certificates support in TrustManagerProxy (#14798)

This is an automated email from the ASF dual-hosted git repository.

penghui pushed a commit to branch branch-2.10
in repository https://gitbox.apache.org/repos/asf/pulsar.git


The following commit(s) were added to refs/heads/branch-2.10 by this push:
     new 3f946c79806 [improve][security] Add load multiple certificates support in TrustManagerProxy (#14798)
3f946c79806 is described below

commit 3f946c798069c5704c6eaeef0119fe33d3e13a68
Author: Zixuan Liu <no...@gmail.com>
AuthorDate: Wed Jul 13 16:47:09 2022 +0800

    [improve][security] Add load multiple certificates support in TrustManagerProxy (#14798)
    
    Signed-off-by: Zixuan Liu <no...@gmail.com>
    (cherry picked from commit 35037cdebd602980d7eb79f6a5f29ecf62e6dd88)
---
 .../pulsar/common/util/TrustManagerProxy.java      | 28 +++++------
 .../pulsar/common/util/TrustManagerProxyTest.java  | 55 ++++++++++++++++++++++
 .../src/test/resources/ca/multiple-ca.pem          | 36 ++++++++++++++
 pulsar-common/src/test/resources/ca/single-ca.pem  | 19 ++++++++
 4 files changed, 122 insertions(+), 16 deletions(-)

diff --git a/pulsar-common/src/main/java/org/apache/pulsar/common/util/TrustManagerProxy.java b/pulsar-common/src/main/java/org/apache/pulsar/common/util/TrustManagerProxy.java
index 089efcae23d..120e9d17a67 100644
--- a/pulsar-common/src/main/java/org/apache/pulsar/common/util/TrustManagerProxy.java
+++ b/pulsar-common/src/main/java/org/apache/pulsar/common/util/TrustManagerProxy.java
@@ -19,16 +19,13 @@
 package org.apache.pulsar.common.util;
 
 import io.netty.handler.ssl.SslContext;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
 import java.io.IOException;
-import java.io.InputStream;
 import java.net.Socket;
+import java.security.KeyManagementException;
 import java.security.KeyStore;
 import java.security.KeyStoreException;
 import java.security.NoSuchAlgorithmException;
 import java.security.cert.CertificateException;
-import java.security.cert.CertificateFactory;
 import java.security.cert.X509Certificate;
 import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.TimeUnit;
@@ -45,13 +42,13 @@ import lombok.extern.slf4j.Slf4j;
 public class TrustManagerProxy extends X509ExtendedTrustManager {
 
     private volatile X509ExtendedTrustManager trustManager;
-    private FileModifiedTimeUpdater certFile;
+    private final FileModifiedTimeUpdater certFile;
 
     public TrustManagerProxy(String caCertFile, int refreshDurationSec, ScheduledExecutorService executor) {
         this.certFile = new FileModifiedTimeUpdater(caCertFile);
         try {
             updateTrustManager();
-        } catch (IOException | CertificateException e) {
+        } catch (KeyManagementException | IOException | CertificateException e) {
             log.warn("Failed to load cert {}, {}", certFile, e.getMessage());
             throw new IllegalArgumentException(e);
         } catch (NoSuchAlgorithmException | KeyStoreException e) {
@@ -71,19 +68,18 @@ public class TrustManagerProxy extends X509ExtendedTrustManager {
     }
 
     private void updateTrustManager() throws CertificateException, KeyStoreException, NoSuchAlgorithmException,
-            FileNotFoundException, IOException {
-        CertificateFactory factory = CertificateFactory.getInstance("X.509");
-        try (InputStream inputStream = new FileInputStream(certFile.getFileName())) {
-            X509Certificate certificate = (X509Certificate) factory.generateCertificate(inputStream);
+            IOException, KeyManagementException {
+        KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
+        keyStore.load(null);
+        X509Certificate[] certificates = SecurityUtility.loadCertificatesFromPemFile(certFile.getFileName());
+        for (X509Certificate certificate : certificates) {
             String alias = certificate.getSubjectX500Principal().getName();
-            KeyStore keyStore = KeyStore.getInstance("JKS");
-            keyStore.load(null);
             keyStore.setCertificateEntry(alias, certificate);
-            final TrustManagerFactory trustManagerFactory = TrustManagerFactory
-                    .getInstance(TrustManagerFactory.getDefaultAlgorithm());
-            trustManagerFactory.init(keyStore);
-            trustManager = (X509ExtendedTrustManager) trustManagerFactory.getTrustManagers()[0];
         }
+        final TrustManagerFactory trustManagerFactory = TrustManagerFactory
+                .getInstance(TrustManagerFactory.getDefaultAlgorithm());
+        trustManagerFactory.init(keyStore);
+        trustManager = (X509ExtendedTrustManager) trustManagerFactory.getTrustManagers()[0];
     }
 
     @Override
diff --git a/pulsar-common/src/test/java/org/apache/pulsar/common/util/TrustManagerProxyTest.java b/pulsar-common/src/test/java/org/apache/pulsar/common/util/TrustManagerProxyTest.java
new file mode 100644
index 00000000000..33163f6e6a5
--- /dev/null
+++ b/pulsar-common/src/test/java/org/apache/pulsar/common/util/TrustManagerProxyTest.java
@@ -0,0 +1,55 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.pulsar.common.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import com.google.common.io.Resources;
+import java.security.cert.X509Certificate;
+import java.util.Arrays;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+public class TrustManagerProxyTest {
+    @DataProvider(name = "caDataProvider")
+    public static Object[][] caDataProvider() {
+        return new Object[][]{
+                {"ca/multiple-ca.pem", 2},
+                {"ca/single-ca.pem", 1}
+        };
+    }
+
+    @Test(dataProvider = "caDataProvider")
+    public void testLoadCA(String path, int count) {
+        String caPath = Resources.getResource(path).getPath();
+
+        ScheduledExecutorService scheduledExecutor = Executors.newSingleThreadScheduledExecutor();
+        try {
+            TrustManagerProxy trustManagerProxy =
+                    new TrustManagerProxy(caPath, 120, scheduledExecutor);
+            X509Certificate[] x509Certificates = trustManagerProxy.getAcceptedIssuers();
+            assertNotNull(x509Certificates);
+            assertEquals(Arrays.stream(x509Certificates).count(), count);
+        } finally {
+            scheduledExecutor.shutdown();
+        }
+    }
+}
diff --git a/pulsar-common/src/test/resources/ca/multiple-ca.pem b/pulsar-common/src/test/resources/ca/multiple-ca.pem
new file mode 100644
index 00000000000..15f136a6953
--- /dev/null
+++ b/pulsar-common/src/test/resources/ca/multiple-ca.pem
@@ -0,0 +1,36 @@
+-----BEGIN CERTIFICATE-----
+MIIC8jCCAdqgAwIBAgIUPnoDe05/dkrbpa2vpmnp45e6/4UwDQYJKoZIhvcNAQEL
+BQAwEDEOMAwGA1UEAxMFdGVzdDEwIBcNMjIwMzIyMDkxOTAwWhgPMjEyMjAzMjQw
+OTE5MDBaMBAxDjAMBgNVBAMTBXRlc3QxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
+MIIBCgKCAQEAvbd4hZAwrgShqrA6g7QKyXQw/4TvskSBT411XCu9+ZIvG4tEafUJ
+CjuHv6AEAt8XN9DSNzVB64q/cOczskaOMa/MQd6Qe+peAiqUsFyu6vucQyCWOLz6
+iuvjPyhuIL5ZYbh17CtXNZOn50BYzq95K4vcAvNUxq/HAGnAm2HegSujq4IMaVpU
+gBE3OinUf6patbGqDDuPRUy/gw3I/+xkQcP9RxZqmbsvc6tw6ZpejBdCunCF9hxH
+p1V70AqNlxUo7H2w7O7gSDU17gzq8kYoyyiJSLS4Wh1nDscpCQykcxYtS+Agb4VZ
+GOYxWMyIBvhRHXLfPVSaYRKw5t5cVy4GjQIDAQABo0IwQDAOBgNVHQ8BAf8EBAMC
+AQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQULlE62PqE/wu4x4BmUmnE5Xfw
+8rowDQYJKoZIhvcNAQELBQADggEBAEVd7o4Gdm9jpsIFuq8879q3XTmdVvLFL5/6
+g/AddloVeyznd6J1vP4n/4fcIskJ084SD1g8FXG21hOb4vQR06E1qWYhxgJJs7fz
+kY3nInbmEWba4Sg7dHXL1KnKOCkhq25UlFF2sMI5BSyKwwAi1R7PKdbTFXZuwFL+
+bKJIvegh+jawlFi1LbSjYYRTy4GgSE8f8/T0xVjqNjdxBnExEkV/dklUJgxck1b1
+K7fRAeoB65tpO/jvYeoQGu1kJkUNmbJu8k1TbBJQm9AxR6OaE+ZKFCf3U5wqH3Ff
+hvrO1utY5yvTUnZ2EMTBytH5cGQ+8zW9tm00AB8eimCb4360l/8=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIC+jCCAeKgAwIBAgIUEyTKRqhwRp7VqaWPm50zo+CWrt0wDQYJKoZIhvcNAQEL
+BQAwFDESMBAGA1UEAxMJbG9jYWxob3N0MCAXDTIyMDMyMTA5NTkwMFoYDzIxMjIw
+MzIzMDk1OTAwWjAUMRIwEAYDVQQDEwlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEB
+AQUAA4IBDwAwggEKAoIBAQDrVbbVOJwhdFzi5hueWKwqHQ8OKtWup8lsOIQXbpc0
+T3/FPclF7Qo481SFBUH9Kg+kXJvxYS/sy/9VnoCq/UaUpaOZ6DQTM09bS9b1LOLM
+EjXv9sMJ82ipQiwG/MOCGtuDHV++Hmf1lMej0pULL6WpBUhbIYWauiUWLlgLzc1u
+v4JZcO/AuBl+tli49Af1ODGWQ4kJYESv27IDU0Jv+/HyE4fmm82vJEqAwjnjxmek
+vsFpBvVK6dPUpTJ4hmG4pRrs4MzyxWBGi4PlWhka0LoT8pJ7gcykABToj3gt4Dmz
+vVS1LoPq5ph5XgqE+8OHlIMaYIrG6fSxzFXQTyzp27pNAgMBAAGjQjBAMA4GA1Ud
+DwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR26y6V2jSvt5Dh
+n2yaI0YW/nK2aTANBgkqhkiG9w0BAQsFAAOCAQEAxThI6kyDeKajNcnYP6urFO/d
+7j/Yvhm1m/xsbg3Ou0iwJqygiJ+IC+jsVzA/tZE1TSX/Yn2KkGdc6vtZVTqESkSi
+Gjxp36M1mhLKr/s4pspzSB+8pIOnhOBO2hcZ31DuWASv4AGpIT6XnuoK0KWaJvo8
+Dwbv1D89m5E2WickT4G/QLtbd05Ens/5BrrWW9Lt3f1IxffRWuTBdM7D7a/fF3zF
+PpMWCAwmDeDwB9fbyBMtXo+Hd+R1YoeO5X5f0F4HO6VcVo+AkUNxs7FETYAiAQXn
+yUYS/bCWHY6eeb67siCLtt4FprkYHt4SQHwKU1V4YmoEE7O/YN9IBEEvKVJZSg==
+-----END CERTIFICATE-----
diff --git a/pulsar-common/src/test/resources/ca/single-ca.pem b/pulsar-common/src/test/resources/ca/single-ca.pem
new file mode 100644
index 00000000000..2cf2d06f97a
--- /dev/null
+++ b/pulsar-common/src/test/resources/ca/single-ca.pem
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIC8jCCAdqgAwIBAgIUPnoDe05/dkrbpa2vpmnp45e6/4UwDQYJKoZIhvcNAQEL
+BQAwEDEOMAwGA1UEAxMFdGVzdDEwIBcNMjIwMzIyMDkxOTAwWhgPMjEyMjAzMjQw
+OTE5MDBaMBAxDjAMBgNVBAMTBXRlc3QxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
+MIIBCgKCAQEAvbd4hZAwrgShqrA6g7QKyXQw/4TvskSBT411XCu9+ZIvG4tEafUJ
+CjuHv6AEAt8XN9DSNzVB64q/cOczskaOMa/MQd6Qe+peAiqUsFyu6vucQyCWOLz6
+iuvjPyhuIL5ZYbh17CtXNZOn50BYzq95K4vcAvNUxq/HAGnAm2HegSujq4IMaVpU
+gBE3OinUf6patbGqDDuPRUy/gw3I/+xkQcP9RxZqmbsvc6tw6ZpejBdCunCF9hxH
+p1V70AqNlxUo7H2w7O7gSDU17gzq8kYoyyiJSLS4Wh1nDscpCQykcxYtS+Agb4VZ
+GOYxWMyIBvhRHXLfPVSaYRKw5t5cVy4GjQIDAQABo0IwQDAOBgNVHQ8BAf8EBAMC
+AQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQULlE62PqE/wu4x4BmUmnE5Xfw
+8rowDQYJKoZIhvcNAQELBQADggEBAEVd7o4Gdm9jpsIFuq8879q3XTmdVvLFL5/6
+g/AddloVeyznd6J1vP4n/4fcIskJ084SD1g8FXG21hOb4vQR06E1qWYhxgJJs7fz
+kY3nInbmEWba4Sg7dHXL1KnKOCkhq25UlFF2sMI5BSyKwwAi1R7PKdbTFXZuwFL+
+bKJIvegh+jawlFi1LbSjYYRTy4GgSE8f8/T0xVjqNjdxBnExEkV/dklUJgxck1b1
+K7fRAeoB65tpO/jvYeoQGu1kJkUNmbJu8k1TbBJQm9AxR6OaE+ZKFCf3U5wqH3Ff
+hvrO1utY5yvTUnZ2EMTBytH5cGQ+8zW9tm00AB8eimCb4360l/8=
+-----END CERTIFICATE-----
+