You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by ad...@apache.org on 2021/06/25 12:28:33 UTC

[jackrabbit-oak] branch trunk updated: OAK-9473 - Cold Standby: configure decryption password for SSL key in OSGi

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

adulceanu pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/jackrabbit-oak.git


The following commit(s) were added to refs/heads/trunk by this push:
     new cb14ad4  OAK-9473 - Cold Standby: configure decryption password for SSL key in OSGi
cb14ad4 is described below

commit cb14ad47d4c0570fead4c082da9b6bec54130c15
Author: Axel Hanikel <ah...@adobe.com>
AuthorDate: Thu Jun 24 17:41:12 2021 +0200

    OAK-9473 - Cold Standby: configure decryption password for SSL key in OSGi
---
 .../oak/segment/standby/client/StandbyClient.java  |  18 ++--
 .../segment/standby/client/StandbyClientSync.java  |  22 +++--
 .../oak/segment/standby/server/StandbyServer.java  |  20 ++--
 .../segment/standby/server/StandbyServerSync.java  |  36 +++++---
 .../segment/standby/store/StandbyStoreService.java |  33 ++++---
 .../oak/segment/standby/StandbyTestIT.java         | 101 ++++++++++++++++++++-
 .../jackrabbit/oak/segment/standby/TestBase.java   |  95 +++++++++++++++++++
 7 files changed, 277 insertions(+), 48 deletions(-)

diff --git a/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/standby/client/StandbyClient.java b/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/standby/client/StandbyClient.java
index 2105df0..3e92a73 100644
--- a/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/standby/client/StandbyClient.java
+++ b/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/standby/client/StandbyClient.java
@@ -73,8 +73,9 @@ class StandbyClient implements AutoCloseable {
         private int readTimeoutMs;
         private File spoolFolder;
         private String sslKeyFile;
+        private String sslKeyPassword;
         private String sslChainFile;
-        public String sslServerSubjectPattern;
+        public String sslSubjectPattern;
 
         private Builder() {}
 
@@ -118,13 +119,18 @@ class StandbyClient implements AutoCloseable {
             return this;
         }
 
+        public Builder withSSLKeyPassword(String sslKeyPassword) {
+            this.sslKeyPassword = sslKeyPassword;
+            return this;
+        }
+
         public Builder withSSLChainFile(String sslChainFile) {
             this.sslChainFile = sslChainFile;
             return this;
         }
 
-        public Builder withSSLServerSubjectPattern(String sslServerSubjectPattern) {
-            this.sslServerSubjectPattern = sslServerSubjectPattern;
+        public Builder withSSLSubjectPattern(String sslServerSubjectPattern) {
+            this.sslSubjectPattern = sslServerSubjectPattern;
             return this;
         }
 
@@ -169,14 +175,14 @@ class StandbyClient implements AutoCloseable {
                     if (builder.secure) {
                         SslContext sslContext;
                         if (builder.sslKeyFile != null && !"".equals(builder.sslKeyFile)) {
-                            sslContext = SslContextBuilder.forClient().keyManager(new File(builder.sslChainFile), new File(builder.sslKeyFile)).build();
+                            sslContext = SslContextBuilder.forClient().keyManager(new File(builder.sslChainFile), new File(builder.sslKeyFile), builder.sslKeyPassword).build();
                         } else {
                             sslContext = SslContextBuilder.forClient().trustManager(InsecureTrustManagerFactory.INSTANCE).build();
                         }
                         p.addLast("ssl", sslContext.newHandler(ch.alloc()));
 
-                        if (builder.sslServerSubjectPattern != null) {
-                            p.addLast(new SSLSubjectMatcher(builder.sslServerSubjectPattern));
+                        if (builder.sslSubjectPattern != null) {
+                            p.addLast(new SSLSubjectMatcher(builder.sslSubjectPattern));
                         }
                     }
 
diff --git a/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/standby/client/StandbyClientSync.java b/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/standby/client/StandbyClientSync.java
index 6af99db..ebca61d 100644
--- a/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/standby/client/StandbyClientSync.java
+++ b/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/standby/client/StandbyClientSync.java
@@ -59,8 +59,9 @@ public final class StandbyClientSync implements ClientStandbyStatusMBean, Runnab
         private boolean autoClean;
         private File spoolFolder;
         private String sslKeyFile;
+        private String sslKeyPassword;
         private String sslChainFile;
-        private String sslServerSubjectPattern;
+        private String sslSubjectPattern;
 
         private Builder() {}
 
@@ -104,13 +105,18 @@ public final class StandbyClientSync implements ClientStandbyStatusMBean, Runnab
             return this;
         }
 
+        public Builder withSSLKeyPassword(String sslKeyPassword) {
+            this.sslKeyPassword = sslKeyPassword;
+            return this;
+        }
+
         public Builder withSSLChainFile(String sslChainFile) {
             this.sslChainFile = sslChainFile;
             return this;
         }
 
-        public Builder withSSLServerSubjectPattern(String sslServerSubjectPattern) {
-            this.sslServerSubjectPattern = sslServerSubjectPattern;
+        public Builder withSSLSubjectPattern(String sslSubjectPattern) {
+            this.sslSubjectPattern = sslSubjectPattern;
             return this;
         }
 
@@ -149,9 +155,11 @@ public final class StandbyClientSync implements ClientStandbyStatusMBean, Runnab
 
     private final String sslKeyFile;
 
+    private final String sslKeyPassword;
+
     private final String sslChainFile;
 
-    private final String sslServerSubjectPattern;
+    private final String sslSubjectPattern;
 
     private int failedRequests;
 
@@ -192,8 +200,9 @@ public final class StandbyClientSync implements ClientStandbyStatusMBean, Runnab
         this.execution = new StandbyClientSyncExecution(fileStore, () -> running);
         this.spoolFolder = builder.spoolFolder;
         this.sslKeyFile = builder.sslKeyFile;
+        this.sslKeyPassword = builder.sslKeyPassword;
         this.sslChainFile = builder.sslChainFile;
-        this.sslServerSubjectPattern = builder.sslServerSubjectPattern;
+        this.sslSubjectPattern = builder.sslSubjectPattern;
         try {
             ManagementFactory.getPlatformMBeanServer().registerMBean(new StandardMBean(this, ClientStandbyStatusMBean.class), new ObjectName(this.getMBeanName()));
         } catch (Exception e) {
@@ -253,8 +262,9 @@ public final class StandbyClientSync implements ClientStandbyStatusMBean, Runnab
                      .withReadTimeoutMs(readTimeoutMs)
                      .withSpoolFolder(spoolFolder)
                      .withSSLKeyFile(sslKeyFile)
+                     .withSSLKeyPassword(sslKeyPassword)
                      .withSSLChainFile(sslChainFile)
-                     .withSSLServerSubjectPattern(sslServerSubjectPattern).build()) {
+                     .withSSLSubjectPattern(sslSubjectPattern).build()) {
                     execution.execute(client);
                 }
 
diff --git a/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/standby/server/StandbyServer.java b/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/standby/server/StandbyServer.java
index b1e2d66..29adcba 100644
--- a/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/standby/server/StandbyServer.java
+++ b/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/standby/server/StandbyServer.java
@@ -109,11 +109,13 @@ class StandbyServer implements AutoCloseable {
 
         private String sslKeyFile;
 
+        private String sslKeyPassword;
+
         private String sslChainFile;
 
         private boolean sslClientValidation;
 
-        public String sslClientSubjectPattern;
+        private String sslSubjectPattern;
 
         private Builder(final int port, final StoreProvider storeProvider, final int blobChunkSize) {
             this.port = port;
@@ -166,6 +168,11 @@ class StandbyServer implements AutoCloseable {
             return this;
         }
 
+        Builder withSSLKeyPassword(String sslKeyPassword) {
+            this.sslKeyPassword = sslKeyPassword;
+            return this;
+        }
+
         Builder withSSLChainFile(String sslChainFile) {
             this.sslChainFile = sslChainFile;
             return this;
@@ -176,8 +183,8 @@ class StandbyServer implements AutoCloseable {
             return this;
         }
 
-        Builder withSSLClientSubjectPattern(String sslClientSubjectPattern) {
-            this.sslClientSubjectPattern = sslClientSubjectPattern;
+        Builder withSSLSubjectPattern(String sslSubjectPattern) {
+            this.sslSubjectPattern = sslSubjectPattern;
             return this;
         }
 
@@ -204,7 +211,6 @@ class StandbyServer implements AutoCloseable {
 
             return new StandbyServer(this);
         }
-
     }
 
     private StandbyServer(final Builder builder) throws CertificateException, SSLException {
@@ -212,7 +218,7 @@ class StandbyServer implements AutoCloseable {
 
         if (builder.secure) {
             if (builder.sslKeyFile != null && !"".equals(builder.sslKeyFile)) {
-                sslContext = SslContextBuilder.forServer(new File(builder.sslChainFile), new File(builder.sslKeyFile)).build();
+                sslContext = SslContextBuilder.forServer(new File(builder.sslChainFile), new File(builder.sslKeyFile), builder.sslKeyPassword).build();
             } else {
                 SelfSignedCertificate ssc = new SelfSignedCertificate();
                 sslContext = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey()).build();
@@ -244,8 +250,8 @@ class StandbyServer implements AutoCloseable {
                     handler.engine().setNeedClientAuth(builder.sslClientValidation);
                     p.addLast("ssl", handler);
 
-                    if (builder.sslClientSubjectPattern != null) {
-                        p.addLast(new SSLSubjectMatcher(builder.sslClientSubjectPattern));
+                    if (builder.sslSubjectPattern != null) {
+                        p.addLast(new SSLSubjectMatcher(builder.sslSubjectPattern));
                     }
                 }
 
diff --git a/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/standby/server/StandbyServerSync.java b/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/standby/server/StandbyServerSync.java
index d547973..5917d5e 100644
--- a/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/standby/server/StandbyServerSync.java
+++ b/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/standby/server/StandbyServerSync.java
@@ -69,7 +69,9 @@ public class StandbyServerSync implements StandbyStatusMBean, StateConsumer, Sto
 
         private boolean sslValidateClient;
 
-        public String sslClientSubjectPattern;
+        private String sslKeyPassword;
+
+        private String sslSubjectPattern;
 
         private Builder() {
             // Prevent external instantiation
@@ -132,6 +134,11 @@ public class StandbyServerSync implements StandbyStatusMBean, StateConsumer, Sto
             return this;
         }
 
+        public Builder withSSLKeyPassword(String sslKeyPassword) {
+            this.sslKeyPassword = sslKeyPassword;
+            return this;
+        }
+
         public Builder withSSLChainFile(String sslChainFile) {
             this.sslChainFile = sslChainFile;
             return this;
@@ -142,8 +149,8 @@ public class StandbyServerSync implements StandbyStatusMBean, StateConsumer, Sto
             return this;
         }
 
-        public Builder withSSLClientSubjectPattern(String sslClientSubjectPattern) {
-            this.sslClientSubjectPattern = sslClientSubjectPattern;
+        public Builder withSSLSubjectPattern(String sslSubjectPattern) {
+            this.sslSubjectPattern = sslSubjectPattern;
             return this;
         }
 
@@ -153,7 +160,6 @@ public class StandbyServerSync implements StandbyStatusMBean, StateConsumer, Sto
             checkArgument(blobChunkSize > 0);
             return new StandbyServerSync(this);
         }
-
     }
 
     private static final Logger log = LoggerFactory.getLogger(StandbyServer.class);
@@ -184,13 +190,15 @@ public class StandbyServerSync implements StandbyStatusMBean, StateConsumer, Sto
 
     private StandbyServer server;
 
-    private final String sslCertificate;
+    private final String sslKeyFile;
+
+    private final String sslKeyPassword;
 
-    private final String sslChain;
+    private final String sslChainFile;
 
     private final boolean sslValidateClient;
 
-    private final String sslClientSubjectPattern;
+    private final String sslSubjectPattern;
 
     private StandbyServerSync(Builder builder) {
         this.port = builder.port;
@@ -202,10 +210,11 @@ public class StandbyServerSync implements StandbyStatusMBean, StateConsumer, Sto
         this.standbyHeadReader = builder.standbyHeadReader;
         this.standbyReferencesReader = builder.standbyReferencesReader;
         this.standbySegmentReader = builder.standbySegmentReader;
-        this.sslCertificate = builder.sslKeyFile;
-        this.sslChain = builder.sslChainFile;
+        this.sslKeyFile = builder.sslKeyFile;
+        this.sslKeyPassword = builder.sslKeyPassword;
+        this.sslChainFile = builder.sslChainFile;
         this.sslValidateClient = builder.sslValidateClient;
-        this.sslClientSubjectPattern = builder.sslClientSubjectPattern;
+        this.sslSubjectPattern = builder.sslSubjectPattern;
         this.observer = new CommunicationObserver("primary");
 
         final MBeanServer jmxServer = ManagementFactory.getPlatformMBeanServer();
@@ -245,10 +254,11 @@ public class StandbyServerSync implements StandbyStatusMBean, StateConsumer, Sto
                 .withStandbyHeadReader(standbyHeadReader)
                 .withStandbyReferencesReader(standbyReferencesReader)
                 .withStandbySegmentReader(standbySegmentReader)
-                .withSSLKeyFile(sslCertificate)
-                .withSSLChainFile(sslChain)
+                .withSSLKeyFile(sslKeyFile)
+                .withSSLKeyPassword(sslKeyPassword)
+                .withSSLChainFile(sslChainFile)
                 .withSSLClientValidation(sslValidateClient)
-                .withSSLClientSubjectPattern(sslClientSubjectPattern);
+                .withSSLSubjectPattern(sslSubjectPattern);
 
             server = builder.build();
             server.start();
diff --git a/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/standby/store/StandbyStoreService.java b/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/standby/store/StandbyStoreService.java
index deeb6a1..8efbb9e 100644
--- a/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/standby/store/StandbyStoreService.java
+++ b/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/standby/store/StandbyStoreService.java
@@ -39,6 +39,7 @@ import org.osgi.service.component.annotations.ConfigurationPolicy;
 import org.osgi.service.component.annotations.Deactivate;
 import org.osgi.service.component.annotations.Reference;
 import org.osgi.service.metatype.annotations.AttributeDefinition;
+import org.osgi.service.metatype.annotations.AttributeType;
 import org.osgi.service.metatype.annotations.Designate;
 import org.osgi.service.metatype.annotations.ObjectClassDefinition;
 import org.osgi.service.metatype.annotations.Option;
@@ -124,6 +125,12 @@ public class StandbyStoreService {
         String sslKeyFile();
 
         @AttributeDefinition(
+            name = "SSL Key Password",
+            description = "Password for the SSL key. If this is empty, an unencrypted key is expected.",
+            type = AttributeType.PASSWORD)
+        String sslKeyPassword() default "";
+
+        @AttributeDefinition(
                 name = "SSL Certificate Chain File",
                 description = "The file name which contains the SSL certificate chain."
         )
@@ -136,16 +143,10 @@ public class StandbyStoreService {
         boolean sslValidateClient() default false;
 
         @AttributeDefinition(
-            name = "SSL Server Certificate Subject Pattern",
-            description = "The server certificate subject must match this pattern in order to be accepted by the client."
-        )
-        String sslServerSubjectPattern();
-
-        @AttributeDefinition(
-            name = "SSL Client Certificate Subject Pattern",
-            description = "The client certificate subject must match this pattern in order to be accepted by the server."
+            name = "SSL Certificate Subject Pattern",
+            description = "The peer certificate's subject must match this pattern in order to be accepted."
         )
-        String sslClientSubjectPattern();
+        String sslSubjectPattern();
     }
 
     @Reference(policy = STATIC, policyOption = GREEDY)
@@ -190,7 +191,7 @@ public class StandbyStoreService {
         String sslKeyFile = config.sslKeyFile();
         String sslChainFile = config.sslChainFile();
         boolean sslValidateClient = config.sslValidateClient();
-        String sslClientSubjectPattern = config.sslClientSubjectPattern();
+        String sslSubjectPattern = config.sslSubjectPattern();
 
         StandbyServerSync.Builder builder = StandbyServerSync.builder()
             .withPort(port)
@@ -201,7 +202,11 @@ public class StandbyStoreService {
             .withSSLKeyFile(sslKeyFile)
             .withSSLChainFile(sslChainFile)
             .withSSLClientValidation(sslValidateClient)
-            .withSSLClientSubjectPattern(sslClientSubjectPattern);
+            .withSSLSubjectPattern(sslSubjectPattern);
+
+        if (!"".equals(config.sslKeyPassword())) {
+            builder.withSSLKeyPassword(config.sslKeyPassword());
+        }
 
         StandbyServerSync standbyServerSync = builder.build();
 
@@ -224,7 +229,11 @@ public class StandbyStoreService {
             .withSecureConnection(config.secure())
             .withSSLKeyFile(config.sslKeyFile())
             .withSSLChainFile(config.sslChainFile())
-            .withSSLServerSubjectPattern(config.sslClientSubjectPattern());
+            .withSSLSubjectPattern(config.sslSubjectPattern());
+
+        if (!"".equals(config.sslKeyPassword())) {
+            builder.withSSLKeyPassword(config.sslKeyPassword());
+        }
 
         StandbyClientSync standbyClientSync = builder.build();
         closer.register(standbyClientSync);
diff --git a/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/standby/StandbyTestIT.java b/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/standby/StandbyTestIT.java
index 8908891..b437b98 100644
--- a/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/standby/StandbyTestIT.java
+++ b/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/standby/StandbyTestIT.java
@@ -345,6 +345,99 @@ public class StandbyTestIT extends TestBase {
      * This test syncs a few segments over an encrypted connection.
      * The server has a configured certificate which can be validated with the truststore.
      * The server validates the client certificate.
+     * The client has a configured certificate which can be validated with the truststore.
+     * All the keys are encrypted.
+     */
+    @Test
+    @Ignore("This test takes ~2s and is therefore disabled by default")
+    public void testSyncSSLValidClientEncryptedKeys() throws Exception {
+        int blobSize = 5 * MB;
+        FileStore primary = serverFileStore.fileStore();
+        FileStore secondary = clientFileStore.fileStore();
+
+        FileOutputStream fos;
+
+        File serverKeyFile = folder.newFile();
+        fos = new FileOutputStream(serverKeyFile);
+        IOUtils.writeString(fos, encryptedServerKey);
+        fos.close();
+
+        File clientKeyFile = folder.newFile();
+        fos = new FileOutputStream(clientKeyFile);
+        IOUtils.writeString(fos, encryptedClientKey);
+        fos.close();
+
+        File serverCertFile = folder.newFile();
+        fos = new FileOutputStream(serverCertFile);
+        IOUtils.writeString(fos, serverCert);
+        fos.close();
+
+        File clientCertFile = folder.newFile();
+        fos = new FileOutputStream(clientCertFile);
+        IOUtils.writeString(fos, clientCert);
+        fos.close();
+
+        File keyStoreFile = folder.newFile();
+        KeyStore keyStore = KeyStore.getInstance("JKS");
+        keyStore.load(null, "changeit".toCharArray());
+        Certificate c = CertificateFactory.getInstance("X.509").generateCertificate(new ByteArrayInputStream(caCert.getBytes()));
+        keyStore.setCertificateEntry("the-ca-cert", c);
+        keyStore.store(new FileOutputStream(keyStoreFile), "changeit".toCharArray());
+        System.setProperty("javax.net.ssl.trustStore", keyStoreFile.getAbsolutePath());
+
+        NodeStore store = SegmentNodeStoreBuilders.builder(primary).build();
+        try (
+            StandbyServerSync serverSync = StandbyServerSync.builder()
+                .withPort(serverPort.getPort())
+                .withFileStore(primary)
+                .withBlobChunkSize(MB)
+                .withSecureConnection(true)
+                .withSSLKeyFile(serverKeyFile.getAbsolutePath())
+                .withSSLKeyPassword(secretPassword)
+                .withSSLChainFile(serverCertFile.getAbsolutePath())
+                .withSSLClientValidation(true)
+                .build();
+            StandbyClientSync clientSync = StandbyClientSync.builder()
+                .withHost(getServerHost())
+                .withPort(serverPort.getPort())
+                .withFileStore(secondary)
+                .withSecureConnection(true)
+                .withReadTimeoutMs(getClientTimeout())
+                .withAutoClean(false)
+                .withSpoolFolder(folder.newFolder())
+                .withSSLKeyFile(clientKeyFile.getAbsolutePath())
+                .withSSLKeyPassword(secretPassword)
+                .withSSLChainFile(clientCertFile.getAbsolutePath())
+                .build()
+        ) {
+            serverSync.start();
+            byte[] data = addTestContent(store, "server", blobSize, 1);
+            primary.flush();
+
+            clientSync.run();
+
+            assertEquals(primary.getHead(), secondary.getHead());
+
+            assertTrue(primary.getStats().getApproximateSize() > blobSize);
+            assertTrue(secondary.getStats().getApproximateSize() > blobSize);
+
+            PropertyState ps = secondary.getHead().getChildNode("root")
+                .getChildNode("server").getProperty("testBlob");
+            assertNotNull(ps);
+            assertEquals(Type.BINARY.tag(), ps.getType().tag());
+            Blob b = ps.getValue(Type.BINARY);
+            assertEquals(blobSize, b.length());
+
+            byte[] testData = new byte[blobSize];
+            ByteStreams.readFully(b.getNewStream(), testData);
+            assertArrayEquals(data, testData);
+        }
+    }
+
+    /**
+     * This test syncs a few segments over an encrypted connection.
+     * The server has a configured certificate which can be validated with the truststore.
+     * The server validates the client certificate.
      * The client has a configured certificate which cannot be validated with the truststore.
      * The SSL connection is expected to fail.
      */
@@ -550,7 +643,7 @@ public class StandbyTestIT extends TestBase {
                 .withSSLKeyFile(serverKeyFile.getAbsolutePath())
                 .withSSLChainFile(serverCertFile.getAbsolutePath())
                 .withSSLClientValidation(true)
-                .withSSLClientSubjectPattern("foobar")
+                .withSSLSubjectPattern("foobar")
                 .build();
             StandbyClientSync clientSync = StandbyClientSync.builder()
                 .withHost(getServerHost())
@@ -628,7 +721,7 @@ public class StandbyTestIT extends TestBase {
                 .withSSLKeyFile(serverKeyFile.getAbsolutePath())
                 .withSSLChainFile(serverCertFile.getAbsolutePath())
                 .withSSLClientValidation(true)
-                .withSSLClientSubjectPattern(".*.esting.*")
+                .withSSLSubjectPattern(".*.esting.*")
                 .build();
             StandbyClientSync clientSync = StandbyClientSync.builder()
                 .withHost(getServerHost())
@@ -718,7 +811,7 @@ public class StandbyTestIT extends TestBase {
                 .withSpoolFolder(folder.newFolder())
                 .withSSLKeyFile(clientKeyFile.getAbsolutePath())
                 .withSSLChainFile(clientCertFile.getAbsolutePath())
-                .withSSLServerSubjectPattern("foobar")
+                .withSSLSubjectPattern("foobar")
                 .build()
         ) {
             serverSync.start();
@@ -796,7 +889,7 @@ public class StandbyTestIT extends TestBase {
                 .withSpoolFolder(folder.newFolder())
                 .withSSLKeyFile(clientKeyFile.getAbsolutePath())
                 .withSSLChainFile(clientCertFile.getAbsolutePath())
-                .withSSLServerSubjectPattern(".*.esting.*")
+                .withSSLSubjectPattern(".*.esting.*")
                 .build()
         ) {
             serverSync.start();
diff --git a/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/standby/TestBase.java b/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/standby/TestBase.java
index 7a83709..e89e374 100644
--- a/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/standby/TestBase.java
+++ b/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/standby/TestBase.java
@@ -241,4 +241,99 @@ public class TestBase {
             "pKHE9hkL/dxsEBXkVdaRHzrfxCBxsP3b3EmOJ4xdl1phGhedUk/+RUWGY8VSnyaq\n" +
             "uVMy1feUqV+AebfUSPzPVubV\n" +
         "-----END PRIVATE KEY-----\n";
+
+    static final String encryptedClientKey =
+        "-----BEGIN ENCRYPTED PRIVATE KEY-----\n" +
+            "MIIE6TAbBgkqhkiG9w0BBQMwDgQIZuy9oMDzt8wCAggABIIEyH7Rbg5VcLV/ZDqp\n" +
+            "AJ6tzPqMlnLVtspB/qk5nZRz2/n42yaqgO2eO7DJ5qNbBGZ6KzLosC6DHd1aXA7E\n" +
+            "8l5RTWQj0u16ANeKsjJ86o5/MRJkeUMh2tPLdVcG0e5nifgbWzXYpS6LuwKQpGEL\n" +
+            "ufSAWhF9BY1hMe58qzCFBsFjrd0tB232sDOnhopaLiO5tQ6h3iMvwK/EPXJGPKHX\n" +
+            "5++DlV/QNaENb/EsCvPlrRgpSWn6dAJ1kemKcvLbnHzTwK88B1n3GUr1B3Z+0jSV\n" +
+            "9IGNeIRVz97KGxW0v33SD1Kw4QpPH+PHH/HhmJ48Vv/mf1rINwA/yRE0iS89glhW\n" +
+            "NPh5O7HD2l2qZZDq74RUfvSzaW738/108ppck/uo+nOvEHnl346XJ7Etbp+fRYj1\n" +
+            "y/irfT7yZ1ZMUkms39M+yBwCp/AqdhvJemOLCAgSJcWWWsNnNqlQlJJsuvkcRPBr\n" +
+            "foYAsPWnZRcowZLyQ80gG5ZKoTa8Kyf/V2CuULHwYv16MLf0koLpGAEjd4QDLrun\n" +
+            "ybsRisrAFupgxNBLovyh6I4b97n0Qeotf/iIfmBOH7azYqpmvgJxNB6hNVwz2LAM\n" +
+            "JgnirRgY+FEdAyTd44/qPQpwXoz4ac3wrdGEU0oLwKk/J2bX1Eqh3tfziPycCO6v\n" +
+            "2IC3WGP59/ty3T1xA/LI0TqInAkUD+0Rkp1HhmPL4xEL/bGLL5FViFkybjO6pgoK\n" +
+            "xjq/dqTbrnmjyhVIjfdCbl2MFEsqUgemH/5J5o75P6mS0HOBaK6ERI9tM6dHz5Wk\n" +
+            "2AbwUUvEebLA6zR5+57dFKSQXhOOekRCQ9w8gDhPHMxyYp3YAdiFitweY/5Xhokt\n" +
+            "l3OXtLPNiqONcYp/Xkz5/CgsjoIHDGgQGy4sWYUQYCdAFXP8/ogR4zVpsUBP0Hjv\n" +
+            "9isg5MlXEEj+YOFYQr/HbON9zxP4LhzuYUWynvVJDfPxY1x7JI+aequHZRPj9Qct\n" +
+            "X6Va5c+G8q87fj/qCJCplGslhJsxBidTQw88+wNeVAVPd+456bszwIE5ey7glvTb\n" +
+            "gwmU4mXDm75T+PW3Y7Gz1HZ9ZCMuUBelBEKxVSOOXCxkO4zzfI9PVxVzkqfurVOO\n" +
+            "9R9i3gV3J6rQj98XtbvBTSrq9nylnzRiFSP2T0aRNLVRmGBahm9YIK+kll/VM2uL\n" +
+            "VzUYPJv22Q/cXR2lkwNFbScOGNzJ3UXiuWOM1CkBgadoHpKhmD4IypvMpA/B0tTL\n" +
+            "l4kL0z7Cg50kXYY77pl6cxorRnPs9fTpPWTPymqWp8Se+pfn/Fxqz11xD0P45Rlo\n" +
+            "0CHLS3536c2zX3/1Uh4ZIGTAwoWeiCfizTnaS7GbIniqJ1/KVx9L5gIu/uWHGSnY\n" +
+            "sU/gOHQw+HxkYGXYI5AqWUp79CZUEnKsNVZDAexKWraG3TBJSydZcyl3OcEfez+f\n" +
+            "ISw//WpK5Wc+Zc+KabT8eWGwN1bIV/5HP1hSx6kggtQBs6BSkEDirzzzvQeIvdol\n" +
+            "ddjGSudEjO2EBE25utg+5omiR8uCQwwInNNOr2otMikmWRgQ3AuIuqxYAF0qH1+f\n" +
+            "n6ePw/b30oy4xIKWz8Kxrn8oPLYgs1Dl3lF6LjRwq1urC2leYb6ZPaX5QjdarMJp\n" +
+            "sxOT5nOmsaG0vinlsQ==\n" +
+        "-----END ENCRYPTED PRIVATE KEY-----";
+
+    static final String encryptedServerKey =
+        "-----BEGIN ENCRYPTED PRIVATE KEY-----\n" +
+            "MIIE6TAbBgkqhkiG9w0BBQMwDgQIto3hFjULIx0CAggABIIEyNWG0f8x6yY3XeE+\n" +
+            "WZjuFYe5WG4ftC8hvKgYCY1NhkFSH3R4FIkAdRanuskUI9rU6tzXEEVKpnsMNTf5\n" +
+            "AhQz/bI4fdu57vyz/ujwmdBMtP9m5hBjyfcJq6w/g1bECC6garbeTYvXgUljyV1n\n" +
+            "h8WQ4rClFhAZ1Qrujc6DTd63BGVoGxY+Jxe6FA2mZj2Z1bCsiWFGU0ShnU+QDF/O\n" +
+            "2SPcHHy37uckIdSrSFAuY8+iwQ5fL5mRH3Gw1CopQY07R8RKyRKpuZV56zJDXmGv\n" +
+            "j0NfJul26EmqXJSTLJyMlYdIP+xSPo50qTWqOl7w37fRcAw7duVP2jIlHJEJD9Y1\n" +
+            "UJe4ypihLp402Amw19wnsaxwk9PDDUd7kN1xFQMJ/eVF5k2hEL3m+2g6PbuFoSHt\n" +
+            "FVQEMDGqeAIPvrUr9FwO0qU7x0hJ1ce/v6IyYhJwbuVDzUFP0nHalTSVM/lXOshO\n" +
+            "dUqY97hOMh+q9drNUCQM08gq3XD/HQP/zA6LYH+X9Ts9Y0R+cocOXwbxc2jKAimo\n" +
+            "MwmP9bSD9MPabGGTv4ZeTVK9JTq4uetCk3ehqNEpS7d69bq0pJ3F6xvGaL7GjiQA\n" +
+            "8YyEUFtbyaBDgg4iwIiPsy/jo7h6Gj1Io/TjcDnp38h1YMTrER2nljB8lSm3t7DA\n" +
+            "5KOzLKHvvB8gUfMiM3OzbIcXtBJIWWidELToqEljAVHWt054yaI4oX1laHOa3zPG\n" +
+            "yriTUARkp5lA2llrm9E1AevlOxpUz3cr94ohvSI40QZgehcvraHJ7FCP7SUi54uY\n" +
+            "o7MRDe27zLsjYRoSLD6saSFL1XigjCa4dpOu3yN8q/R0NyjmBySxOlPbglyl/OmD\n" +
+            "czWFvUQcHcuSsPosbp30nsDD5SIGY6p+XR8tqJdKrCh+vgFlQPb1OkvGcXD7uzjI\n" +
+            "0jYVc23pUwrM3oynAjll2uEBlMfHsdYTB5ehv/sp7tqnc3/VbPhW9WOercbQvVnq\n" +
+            "Gb13aL4ra94glERJFH5LitvmjkylD6tjOttDONYg9ow1dA5g2q/A7WD0UV4TrW2w\n" +
+            "LRze30kKG2p94DE1if54VMA91QLhU3YwntDSk8jZ6bO7rG91d98npwHWZfMzJI6J\n" +
+            "blHM5gaAmHCTvwX6/Px/tS+8HmG5l8BBBqz70gh24uYjMgsTWsfRsjfypBmXzEFt\n" +
+            "JiFJIBwGQ0uHDM2JXqIdCf1em875eK3XR6qvrQDPiA5HVXFaGdRGbx0aK7lzDHrn\n" +
+            "7cn02kNLb4/kbZnpj04p7/j6dpfGLMnkSH7Pxx4f0cfirfDvcZQwjpl/n4bHnIxT\n" +
+            "Qv6XWq67dQObvbiCZF14CayEEqNU6Q9wq+EBji2739FhAAbZ0P1Uj792wk50tOgg\n" +
+            "+EqXzCGaqSRn7RrMEiQQTGBson9L6aBlNxyBRH6LMLAsvcKzlYB5zMQHwObd/eaU\n" +
+            "43WdwOly9CLeJbTpPNvZoeDGT7jdin3XiuauMnDa4W1wwKHKgpbD543ScZfIkNm1\n" +
+            "Wcibp27rE4/5eIsNyQnxkDRN7f3x0a9iwhlgrToXGabileLsonx3Jdf/YXgiqiQY\n" +
+            "4lLGr4EIVjKg8YbJvpnrEZQNeTHwPr8/N5N51VZvoVePBq/ZnBi9EK/aCL+f+0Dx\n" +
+            "yZio9eDGsuOXwR7iOg==\n" +
+        "-----END ENCRYPTED PRIVATE KEY-----";
+
+    static final String encryptedArbitraryKey =
+        "-----BEGIN ENCRYPTED PRIVATE KEY-----\n" +
+            "MIIE6TAbBgkqhkiG9w0BBQMwDgQIT+Z6cmw0caMCAggABIIEyCCZWzPzrAGr7nsi\n" +
+            "ifNxQbX0GO6wYb3ND7yinc/0Yw+d38l0S5LTLg+5GD7SbXfoMmC44rUxSGnBV5Bj\n" +
+            "/bUW30B/s0+I3Ya1pXXyVP98vjy71Pspw/sHH3tYU73fPdqzh538Jf9qEgqgaJej\n" +
+            "MRdiQfQmXexmkyeWAYQutbONrwfuH8NqLGxuPjrc21WjKkijnv9X8CuUk6M1MCPc\n" +
+            "jN2iPhTsYiOkgKkyjF817792jDBYJHtoOuG5OmhSAdw6I3Tm5TRqAO/6IGPuDqWb\n" +
+            "7ho3ZyLBxBaLHTOawQkGm842lhwn5fACCCYNGsQhVGdbZN4KVgSYzJwvGw8vaawE\n" +
+            "VhD+zcDzhAydlhMXwFxDMgoZD5qRZujuDoBLgBYrDFDDEUfDNoUJSmWPpHXVc2tq\n" +
+            "RBiP3xb152lWiqRcXLZVHfXfxT79qZAxvlRBUgYEA/u2ud3p2/7R9UBvRzE6P6IA\n" +
+            "9ZuO6CgJgGvHXY2u721/MvvhY/75X1c1t0VJsdU2H6+E34QDtSqmQD08zBlZw5TK\n" +
+            "qltQpxgjMO1jtdEuHWPbR5Aoa5smOL9qBleptSGsm0I5zET+hv4y3f5AHIx3X3xy\n" +
+            "UH6Nw30oQtSbbZzPX4sqZuzA66W9Z4yW3Pn1EYcpuacypty/gvRZrvnwb6gYNB+h\n" +
+            "XTTaikNiGebcAZhSukcKmL3mjlpbUZC3Bjbz5AstZJyd0tMSaw0E4C8VQQHYyX5X\n" +
+            "lteW1O2TvHyGdeb0LNwsXzIMqsqmgsuNsms12Xx7KurxhPGk3Za2SdXQUASSryWX\n" +
+            "XPlKxlQDDM9DvSQsRw6BCUoUKZ/2YiXnnL/zrY1+xegXumwolgT8Dsu6CFxvzT7E\n" +
+            "16/4FeaVDB0/A5nmR71gkwm/b/JJL/Qj0H+E0rhCyZJeW9ddg4IWolEFTvCrVmHG\n" +
+            "gZ8DQIHJHSPilG8gdjzJ8cs89pctswnjuLMI2wT2/jqtM76Ibr9d0eIB6CzT17dh\n" +
+            "ASchmnUUXgjY/djAO8M3LuMUgu6OTCpIwAjfz7DOaakI42Dvrz0sTCkBwjD3XY7v\n" +
+            "1EyxoxCPoxTlHE1BLNgT5OD0B9SPC9aQLt+DOcDXVh8vQvIGtqMbxthIoi61XTeo\n" +
+            "sm35wkdiC0wSCgqPKIiz/LcyaWcOwbK2F7Q1dKluBT29L6X35FLqbp8RNZLJSX18\n" +
+            "53gJJLH4Hd7XcAn2Sat+vyuY3Z3vNiFMmx+vbho3ZgGL5KTNdmpN1fM7EqpGOUfp\n" +
+            "easRPOw3P1KuVqTVCvm/osf4VniV3xCvgwffJ/kOlHChnIrHGZpeBFmiV4xk7ucb\n" +
+            "7PSVt8BLV2+krXSTijFepeuVckitj3Kf4o++WePE6wlPi0rPYG47IE10xHojSKgr\n" +
+            "xdEonxiGL07/MEdI9+9PHLg5+ZakymRmMnEcJdpd7+WxaFy8jhvCCZ+7ppZBpYQC\n" +
+            "azdkciNz9d/YZRQH5M6VGk1VqqkQbenasUuZpXAxDOraLPlq801JyYyPqeROAgb8\n" +
+            "hTQXseAe+7lHWpmUGKuN0Y9EcV/3fiAP+PeMt/QXeGF5jcRVGWLs6nDVOaBQ/SB3\n" +
+            "syFXwJR6WtajR5OC7dEGZPTxaNfiu4GFuE73i3cVEJH2MH7+c/yB/40RJQdJ4kd6\n" +
+            "7KJYwr8P4TrNulM60Q==\n" +
+        "-----END ENCRYPTED PRIVATE KEY-----\n";
+
+    static final String secretPassword = "secret";
 }