From 34626a739582380c8930df7365939f24d57883bf Mon Sep 17 00:00:00 2001 From: Klay Date: Wed, 13 Oct 2021 08:39:45 -0700 Subject: [PATCH] add ssl support for graph daemon (#364) --- client/pom.xml | 6 + .../facebook/thrift/transport/TSocket.java | 31 +++ .../nebula/client/graph/NebulaPoolConfig.java | 24 ++ .../client/graph/data/CASignedSSLParam.java | 32 +++ .../nebula/client/graph/data/SSLParam.java | 25 ++ .../client/graph/data/SelfSignedSSLParam.java | 32 +++ .../client/graph/net/ConnObjectPool.java | 12 +- .../nebula/client/graph/net/Connection.java | 4 + .../nebula/client/graph/net/NebulaPool.java | 4 +- .../graph/net/RoundRobinLoadBalancer.java | 15 +- .../client/graph/net/SyncConnection.java | 50 +++- .../java/com/vesoft/nebula/util/SslUtil.java | 213 ++++++++++++++++++ .../client/graph/data/TestDataFromServer.java | 80 +++++++ .../resources/docker-compose-casigned.yaml | 135 +++++++++++ .../resources/docker-compose-selfsigned.yaml | 135 +++++++++++ client/src/test/resources/ssl/casigned.crt | 16 ++ client/src/test/resources/ssl/casigned.key | 27 +++ client/src/test/resources/ssl/casigned.pem | 24 ++ client/src/test/resources/ssl/selfsigned.key | 30 +++ .../test/resources/ssl/selfsigned.password | 1 + client/src/test/resources/ssl/selfsigned.pem | 24 ++ client/src/test/resources/ssl/test.ca.key | 30 +++ .../src/test/resources/ssl/test.ca.password | 1 + client/src/test/resources/ssl/test.ca.pem | 24 ++ client/src/test/resources/ssl/test.ca.srl | 1 + client/src/test/resources/ssl/test.derive.crt | 23 ++ client/src/test/resources/ssl/test.derive.csr | 19 ++ client/src/test/resources/ssl/test.derive.key | 27 +++ .../nebula/examples/GraphClientExample.java | 63 +++++- examples/src/main/resources/ssl/casigned.crt | 16 ++ examples/src/main/resources/ssl/casigned.key | 27 +++ examples/src/main/resources/ssl/casigned.pem | 24 ++ .../src/main/resources/ssl/selfsigned.key | 30 +++ .../main/resources/ssl/selfsigned.password | 1 + .../src/main/resources/ssl/selfsigned.pem | 24 ++ 35 files changed, 1214 insertions(+), 16 deletions(-) create mode 100644 client/src/main/java/com/vesoft/nebula/client/graph/data/CASignedSSLParam.java create mode 100644 client/src/main/java/com/vesoft/nebula/client/graph/data/SSLParam.java create mode 100644 client/src/main/java/com/vesoft/nebula/client/graph/data/SelfSignedSSLParam.java create mode 100644 client/src/main/java/com/vesoft/nebula/util/SslUtil.java create mode 100644 client/src/test/resources/docker-compose-casigned.yaml create mode 100644 client/src/test/resources/docker-compose-selfsigned.yaml create mode 100644 client/src/test/resources/ssl/casigned.crt create mode 100644 client/src/test/resources/ssl/casigned.key create mode 100644 client/src/test/resources/ssl/casigned.pem create mode 100644 client/src/test/resources/ssl/selfsigned.key create mode 100644 client/src/test/resources/ssl/selfsigned.password create mode 100644 client/src/test/resources/ssl/selfsigned.pem create mode 100644 client/src/test/resources/ssl/test.ca.key create mode 100644 client/src/test/resources/ssl/test.ca.password create mode 100644 client/src/test/resources/ssl/test.ca.pem create mode 100644 client/src/test/resources/ssl/test.ca.srl create mode 100644 client/src/test/resources/ssl/test.derive.crt create mode 100644 client/src/test/resources/ssl/test.derive.csr create mode 100644 client/src/test/resources/ssl/test.derive.key create mode 100644 examples/src/main/resources/ssl/casigned.crt create mode 100644 examples/src/main/resources/ssl/casigned.key create mode 100644 examples/src/main/resources/ssl/casigned.pem create mode 100644 examples/src/main/resources/ssl/selfsigned.key create mode 100644 examples/src/main/resources/ssl/selfsigned.password create mode 100644 examples/src/main/resources/ssl/selfsigned.pem diff --git a/client/pom.xml b/client/pom.xml index 8e056ac68..a17bc85f7 100644 --- a/client/pom.xml +++ b/client/pom.xml @@ -22,6 +22,7 @@ 2.2 3.0.1 1.2.78 + 1.69 @@ -239,5 +240,10 @@ fastjson ${fastjson.version} + + org.bouncycastle + bcpkix-jdk15on + ${bouncycastle.version} + diff --git a/client/src/main/fbthrift/com/facebook/thrift/transport/TSocket.java b/client/src/main/fbthrift/com/facebook/thrift/transport/TSocket.java index 47160f930..e95168876 100644 --- a/client/src/main/fbthrift/com/facebook/thrift/transport/TSocket.java +++ b/client/src/main/fbthrift/com/facebook/thrift/transport/TSocket.java @@ -70,6 +70,37 @@ public TSocket(Socket socket) throws TTransportException { } } + /** + * Constructor that takes an already created socket that comes alone with timeout + * and connectionTimeout. + * + * @param socket Already created socket object + * @param timeout Socket timeout + * @param connectionTimeout Socket connection timeout + * @throws TTransportException if there is an error setting up the streams + */ + public TSocket(Socket socket, int timeout, int connectionTimeout) throws TTransportException { + socket_ = socket; + try { + socket_.setSoLinger(false, 0); + socket_.setTcpNoDelay(true); + socket_.setSoTimeout(timeout); + connectionTimeout_ = connectionTimeout; + } catch (SocketException sx) { + LOGGER.warn("Could not configure socket.", sx); + } + + if (isOpen()) { + try { + inputStream_ = new BufferedInputStream(socket_.getInputStream()); + outputStream_ = new BufferedOutputStream(socket_.getOutputStream()); + } catch (IOException iox) { + close(); + throw new TTransportException(TTransportException.NOT_OPEN, iox); + } + } + } + /** * Creates a new unconnected socket that will connect to the given host on the given port. * diff --git a/client/src/main/java/com/vesoft/nebula/client/graph/NebulaPoolConfig.java b/client/src/main/java/com/vesoft/nebula/client/graph/NebulaPoolConfig.java index 3e1f70110..60bba75ea 100644 --- a/client/src/main/java/com/vesoft/nebula/client/graph/NebulaPoolConfig.java +++ b/client/src/main/java/com/vesoft/nebula/client/graph/NebulaPoolConfig.java @@ -6,6 +6,8 @@ package com.vesoft.nebula.client.graph; +import com.vesoft.nebula.client.graph.data.SSLParam; + public class NebulaPoolConfig { // The min connections in pool for all addresses private int minConnsSize = 0; @@ -27,6 +29,28 @@ public class NebulaPoolConfig { // the wait time to get idle connection, unit ms private int waitTime = 0; + // set to true to turn on ssl encrypted traffic + private boolean enableSsl = false; + + // ssl param is required if ssl is turned on + private SSLParam sslParam = null; + + public boolean isEnableSsl() { + return enableSsl; + } + + public void setEnableSsl(boolean enableSsl) { + this.enableSsl = enableSsl; + } + + public SSLParam getSslParam() { + return sslParam; + } + + public void setSslParam(SSLParam sslParam) { + this.sslParam = sslParam; + } + public int getMinConnSize() { return minConnsSize; } diff --git a/client/src/main/java/com/vesoft/nebula/client/graph/data/CASignedSSLParam.java b/client/src/main/java/com/vesoft/nebula/client/graph/data/CASignedSSLParam.java new file mode 100644 index 000000000..9667c70f9 --- /dev/null +++ b/client/src/main/java/com/vesoft/nebula/client/graph/data/CASignedSSLParam.java @@ -0,0 +1,32 @@ +/* Copyright (c) 2021 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.client.graph.data; + +public class CASignedSSLParam extends SSLParam { + private String caCrtFilePath; + private String crtFilePath; + private String keyFilePath; + + public CASignedSSLParam(String caCrtFilePath, String crtFilePath, String keyFilePath) { + super(SignMode.CA_SIGNED); + this.caCrtFilePath = caCrtFilePath; + this.crtFilePath = crtFilePath; + this.keyFilePath = keyFilePath; + } + + public String getCaCrtFilePath() { + return caCrtFilePath; + } + + public String getCrtFilePath() { + return crtFilePath; + } + + public String getKeyFilePath() { + return keyFilePath; + } +} diff --git a/client/src/main/java/com/vesoft/nebula/client/graph/data/SSLParam.java b/client/src/main/java/com/vesoft/nebula/client/graph/data/SSLParam.java new file mode 100644 index 000000000..1a19ec48d --- /dev/null +++ b/client/src/main/java/com/vesoft/nebula/client/graph/data/SSLParam.java @@ -0,0 +1,25 @@ +/* Copyright (c) 2021 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.client.graph.data; + +public abstract class SSLParam { + public enum SignMode { + NONE, + SELF_SIGNED, + CA_SIGNED + } + + private SignMode signMode; + + public SSLParam(SignMode signMode) { + this.signMode = signMode; + } + + public SignMode getSignMode() { + return signMode; + } +} diff --git a/client/src/main/java/com/vesoft/nebula/client/graph/data/SelfSignedSSLParam.java b/client/src/main/java/com/vesoft/nebula/client/graph/data/SelfSignedSSLParam.java new file mode 100644 index 000000000..d10046a6d --- /dev/null +++ b/client/src/main/java/com/vesoft/nebula/client/graph/data/SelfSignedSSLParam.java @@ -0,0 +1,32 @@ +/* Copyright (c) 2021 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.client.graph.data; + +public class SelfSignedSSLParam extends SSLParam { + private String crtFilePath; + private String keyFilePath; + private String password; + + public SelfSignedSSLParam(String crtFilePath, String keyFilePath, String password) { + super(SignMode.SELF_SIGNED); + this.crtFilePath = crtFilePath; + this.keyFilePath = keyFilePath; + this.password = password; + } + + public String getCrtFilePath() { + return crtFilePath; + } + + public String getKeyFilePath() { + return keyFilePath; + } + + public String getPassword() { + return password; + } +} diff --git a/client/src/main/java/com/vesoft/nebula/client/graph/net/ConnObjectPool.java b/client/src/main/java/com/vesoft/nebula/client/graph/net/ConnObjectPool.java index ac043fa2d..9e2ebd4ab 100644 --- a/client/src/main/java/com/vesoft/nebula/client/graph/net/ConnObjectPool.java +++ b/client/src/main/java/com/vesoft/nebula/client/graph/net/ConnObjectPool.java @@ -9,7 +9,7 @@ public class ConnObjectPool extends BasePooledObjectFactory { private final NebulaPoolConfig config; - private LoadBalancer loadBalancer; + private final LoadBalancer loadBalancer; private static final int retryTime = 3; public ConnObjectPool(LoadBalancer loadBalancer, NebulaPoolConfig config) { @@ -28,7 +28,15 @@ public SyncConnection create() throws IOErrorException { SyncConnection conn = new SyncConnection(); while (retry-- > 0) { try { - conn.open(address, config.getTimeout()); + if (config.isEnableSsl()) { + if (config.getSslParam() == null) { + throw new IllegalArgumentException("SSL Param is required when enableSsl " + + "is set to true"); + } + conn.open(address, config.getTimeout(), config.getSslParam()); + } else { + conn.open(address, config.getTimeout()); + } return conn; } catch (IOErrorException e) { if (retry == 0) { diff --git a/client/src/main/java/com/vesoft/nebula/client/graph/net/Connection.java b/client/src/main/java/com/vesoft/nebula/client/graph/net/Connection.java index 1cbd1ba3e..5f94f1c84 100644 --- a/client/src/main/java/com/vesoft/nebula/client/graph/net/Connection.java +++ b/client/src/main/java/com/vesoft/nebula/client/graph/net/Connection.java @@ -1,6 +1,7 @@ package com.vesoft.nebula.client.graph.net; import com.vesoft.nebula.client.graph.data.HostAddress; +import com.vesoft.nebula.client.graph.data.SSLParam; import com.vesoft.nebula.client.graph.exception.IOErrorException; public abstract class Connection { @@ -10,6 +11,9 @@ public HostAddress getServerAddress() { return this.serverAddr; } + public abstract void open(HostAddress address, int timeout, SSLParam sslParam) + throws IOErrorException; + public abstract void open(HostAddress address, int timeout) throws IOErrorException; public abstract void reopen() throws IOErrorException; diff --git a/client/src/main/java/com/vesoft/nebula/client/graph/net/NebulaPool.java b/client/src/main/java/com/vesoft/nebula/client/graph/net/NebulaPool.java index b5c6cd567..6fe80a2ba 100644 --- a/client/src/main/java/com/vesoft/nebula/client/graph/net/NebulaPool.java +++ b/client/src/main/java/com/vesoft/nebula/client/graph/net/NebulaPool.java @@ -85,7 +85,9 @@ public boolean init(List addresses, NebulaPoolConfig config) checkConfig(config); this.waitTime = config.getWaitTime(); List newAddrs = hostToIp(addresses); - this.loadBalancer = new RoundRobinLoadBalancer(newAddrs, config.getTimeout()); + this.loadBalancer = config.isEnableSsl() + ? new RoundRobinLoadBalancer(newAddrs, config.getTimeout(), config.getSslParam()) + : new RoundRobinLoadBalancer(newAddrs, config.getTimeout()); ConnObjectPool objectPool = new ConnObjectPool(this.loadBalancer, config); this.objectPool = new GenericObjectPool<>(objectPool); GenericObjectPoolConfig objConfig = new GenericObjectPoolConfig(); diff --git a/client/src/main/java/com/vesoft/nebula/client/graph/net/RoundRobinLoadBalancer.java b/client/src/main/java/com/vesoft/nebula/client/graph/net/RoundRobinLoadBalancer.java index 661dcaa80..9e7c9402a 100644 --- a/client/src/main/java/com/vesoft/nebula/client/graph/net/RoundRobinLoadBalancer.java +++ b/client/src/main/java/com/vesoft/nebula/client/graph/net/RoundRobinLoadBalancer.java @@ -1,6 +1,7 @@ package com.vesoft.nebula.client.graph.net; import com.vesoft.nebula.client.graph.data.HostAddress; +import com.vesoft.nebula.client.graph.data.SSLParam; import com.vesoft.nebula.client.graph.exception.IOErrorException; import java.util.ArrayList; import java.util.HashMap; @@ -21,6 +22,8 @@ public class RoundRobinLoadBalancer implements LoadBalancer { private final AtomicInteger pos = new AtomicInteger(0); private final int delayTime = 60; // unit seconds private final ScheduledExecutorService schedule = Executors.newScheduledThreadPool(1); + private SSLParam sslParam; + private boolean enabledSsl; public RoundRobinLoadBalancer(List addresses, int timeout) { this.timeout = timeout; @@ -31,6 +34,12 @@ public RoundRobinLoadBalancer(List addresses, int timeout) { schedule.scheduleAtFixedRate(this::scheduleTask, 0, delayTime, TimeUnit.SECONDS); } + public RoundRobinLoadBalancer(List addresses, int timeout, SSLParam sslParam) { + this(addresses,timeout); + this.sslParam = sslParam; + this.enabledSsl = true; + } + public void close() { schedule.shutdownNow(); } @@ -63,7 +72,11 @@ public void updateServersStatus() { public boolean ping(HostAddress addr) { try { Connection connection = new SyncConnection(); - connection.open(addr, this.timeout); + if (enabledSsl) { + connection.open(addr, this.timeout, sslParam); + } else { + connection.open(addr, this.timeout); + } connection.close(); return true; } catch (IOErrorException e) { diff --git a/client/src/main/java/com/vesoft/nebula/client/graph/net/SyncConnection.java b/client/src/main/java/com/vesoft/nebula/client/graph/net/SyncConnection.java index 08a5e0a3b..4e6a77161 100644 --- a/client/src/main/java/com/vesoft/nebula/client/graph/net/SyncConnection.java +++ b/client/src/main/java/com/vesoft/nebula/client/graph/net/SyncConnection.java @@ -15,23 +15,64 @@ import com.facebook.thrift.transport.TTransportException; import com.facebook.thrift.utils.StandardCharsets; import com.vesoft.nebula.ErrorCode; +import com.vesoft.nebula.client.graph.data.CASignedSSLParam; import com.vesoft.nebula.client.graph.data.HostAddress; +import com.vesoft.nebula.client.graph.data.SSLParam; +import com.vesoft.nebula.client.graph.data.SelfSignedSSLParam; import com.vesoft.nebula.client.graph.exception.AuthFailedException; import com.vesoft.nebula.client.graph.exception.IOErrorException; import com.vesoft.nebula.graph.AuthResponse; import com.vesoft.nebula.graph.ExecutionResponse; import com.vesoft.nebula.graph.GraphService; +import com.vesoft.nebula.util.SslUtil; +import java.io.IOException; +import javax.net.ssl.SSLSocketFactory; public class SyncConnection extends Connection { protected TTransport transport = null; protected TProtocol protocol = null; private GraphService.Client client = null; private int timeout = 0; + private SSLParam sslParam = null; + private boolean enabledSsl = false; + + @Override + public void open(HostAddress address, int timeout, SSLParam sslParam) throws IOErrorException { + try { + SSLSocketFactory sslSocketFactory; + + this.serverAddr = address; + this.timeout = timeout <= 0 ? Integer.MAX_VALUE : timeout; + this.enabledSsl = true; + this.sslParam = sslParam; + if (sslParam.getSignMode() == SSLParam.SignMode.CA_SIGNED) { + sslSocketFactory = + SslUtil.getSSLSocketFactoryWithCA((CASignedSSLParam) sslParam); + } else { + sslSocketFactory = + SslUtil.getSSLSocketFactoryWithoutCA((SelfSignedSSLParam) sslParam); + } + if (sslSocketFactory == null) { + throw new IOErrorException(IOErrorException.E_UNKNOWN, + "SSL Socket Factory Creation failed"); + } + this.transport = new TSocket( + sslSocketFactory.createSocket(address.getHost(), + address.getPort()), this.timeout, this.timeout); + this.protocol = new TCompactProtocol(transport); + client = new GraphService.Client(protocol); + } catch (TException e) { + throw new IOErrorException(IOErrorException.E_UNKNOWN, e.getMessage()); + } catch (IOException e) { + e.printStackTrace(); + } + } @Override public void open(HostAddress address, int timeout) throws IOErrorException { - this.serverAddr = address; try { + this.enabledSsl = false; + this.serverAddr = address; this.timeout = timeout <= 0 ? Integer.MAX_VALUE : timeout; this.transport = new TSocket( address.getHost(), address.getPort(), this.timeout, this.timeout); @@ -56,7 +97,11 @@ public void open(HostAddress address, int timeout) throws IOErrorException { @Override public void reopen() throws IOErrorException { close(); - open(serverAddr, timeout); + if (enabledSsl) { + open(serverAddr, timeout, sslParam); + } else { + open(serverAddr, timeout); + } } public AuthResult authenticate(String user, String password) @@ -143,6 +188,7 @@ public boolean ping() { execute(0, "YIELD 1;"); return true; } catch (IOErrorException e) { + e.printStackTrace(); return false; } } diff --git a/client/src/main/java/com/vesoft/nebula/util/SslUtil.java b/client/src/main/java/com/vesoft/nebula/util/SslUtil.java new file mode 100644 index 000000000..e75087e10 --- /dev/null +++ b/client/src/main/java/com/vesoft/nebula/util/SslUtil.java @@ -0,0 +1,213 @@ +/* Copyright (c) 2021 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.util; + +import com.vesoft.nebula.client.graph.data.CASignedSSLParam; +import com.vesoft.nebula.client.graph.data.SelfSignedSSLParam; +import java.io.FileReader; +import java.security.KeyPair; +import java.security.KeyStore; +import java.security.Security; +import java.security.cert.Certificate; +import java.security.cert.X509Certificate; +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSocketFactory; +import javax.net.ssl.TrustManagerFactory; +import org.bouncycastle.cert.X509CertificateHolder; +import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.openssl.PEMDecryptorProvider; +import org.bouncycastle.openssl.PEMEncryptedKeyPair; +import org.bouncycastle.openssl.PEMKeyPair; +import org.bouncycastle.openssl.PEMParser; +import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter; +import org.bouncycastle.openssl.jcajce.JcePEMDecryptorProviderBuilder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class SslUtil { + private static final Logger LOGGER = LoggerFactory.getLogger(SslUtil.class); + + public static SSLSocketFactory getSSLSocketFactoryWithCA(CASignedSSLParam param) { + final String caCrtFile = param.getCaCrtFilePath(); + final String crtFile = param.getCrtFilePath(); + final String keyFile = param.getKeyFilePath(); + final String password = ""; + try { + //Add BouncyCastle as a Security Provider + Security.addProvider(new BouncyCastleProvider()); + + // Load client private key + PEMParser reader = null; + Object keyObject; + try { + reader = new PEMParser(new FileReader(keyFile)); + keyObject = reader.readObject(); + } finally { + if (reader != null) { + reader.close(); + } + } + + PEMDecryptorProvider provider = + new JcePEMDecryptorProviderBuilder().build(password.toCharArray()); + JcaPEMKeyConverter keyConverter = new JcaPEMKeyConverter().setProvider("BC"); + + KeyPair key; + + if (keyObject instanceof PEMEncryptedKeyPair) { + key = keyConverter.getKeyPair(((PEMEncryptedKeyPair) keyObject) + .decryptKeyPair(provider)); + } else { + key = keyConverter.getKeyPair((PEMKeyPair) keyObject); + } + + // Load Certificate Authority (CA) certificate + X509CertificateHolder caCertHolder; + try { + reader = new PEMParser(new FileReader(caCrtFile)); + caCertHolder = (X509CertificateHolder) reader.readObject(); + } finally { + if (reader != null) { + reader.close(); + } + } + + // CA certificate is used to authenticate server + JcaX509CertificateConverter certificateConverter = + new JcaX509CertificateConverter().setProvider("BC"); + KeyStore caKeyStore = KeyStore.getInstance(KeyStore.getDefaultType()); + X509Certificate caCert = certificateConverter.getCertificate(caCertHolder); + caKeyStore.load(null, null); + caKeyStore.setCertificateEntry("ca-certificate", caCert); + + TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance( + TrustManagerFactory.getDefaultAlgorithm()); + trustManagerFactory.init(caKeyStore); + + // Load client certificate + X509CertificateHolder certHolder; + try { + reader = new PEMParser(new FileReader(crtFile)); + certHolder = (X509CertificateHolder) reader.readObject(); + } finally { + if (reader != null) { + reader.close(); + } + } + + // Client key and certificates are sent to server so it can authenticate the client + KeyStore clientKeyStore = KeyStore.getInstance(KeyStore.getDefaultType()); + X509Certificate cert = certificateConverter.getCertificate(certHolder); + clientKeyStore.load(null, null); + clientKeyStore.setCertificateEntry("certificate", cert); + clientKeyStore.setKeyEntry("private-key", key.getPrivate(), password.toCharArray(), + new Certificate[]{cert}); + + KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance( + KeyManagerFactory.getDefaultAlgorithm()); + keyManagerFactory.init(clientKeyStore, password.toCharArray()); + + // Create SSL socket factory + SSLContext context = SSLContext.getInstance("TLSv1.3"); + context.init(keyManagerFactory.getKeyManagers(), + trustManagerFactory.getTrustManagers(), null); + + // Return the newly created socket factory object + return context.getSocketFactory(); + + } catch (Exception e) { + LOGGER.error(e.getMessage()); + } + + return null; + } + + public static SSLSocketFactory getSSLSocketFactoryWithoutCA(SelfSignedSSLParam param) { + final String crtFile = param.getCrtFilePath(); + final String keyFile = param.getKeyFilePath(); + final String password = param.getPassword(); + try { + // Add BouncyCastle as a Security Provider + Security.addProvider(new BouncyCastleProvider()); + + // Load client private key + PEMParser reader = null; + Object keyObject; + try { + reader = new PEMParser(new FileReader(keyFile)); + keyObject = reader.readObject(); + } finally { + if (reader != null) { + reader.close(); + } + } + + PEMDecryptorProvider provider = + new JcePEMDecryptorProviderBuilder().build(password.toCharArray()); + JcaPEMKeyConverter keyConverter = new JcaPEMKeyConverter().setProvider("BC"); + + KeyPair key; + + if (keyObject instanceof PEMEncryptedKeyPair) { + key = keyConverter.getKeyPair(((PEMEncryptedKeyPair) keyObject) + .decryptKeyPair(provider)); + } else { + key = keyConverter.getKeyPair((PEMKeyPair) keyObject); + } + + // certificate is used to authenticate server + JcaX509CertificateConverter certificateConverter = + new JcaX509CertificateConverter().setProvider("BC"); + + // Load client certificate + X509CertificateHolder certHolder; + try { + reader = new PEMParser(new FileReader(crtFile)); + certHolder = (X509CertificateHolder) reader.readObject(); + } finally { + if (reader != null) { + reader.close(); + } + } + + X509Certificate cert = certificateConverter.getCertificate(certHolder); + // certificate is used to authenticate server + KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); + keyStore.load(null, null); + keyStore.setCertificateEntry("certificate", cert); + + TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance( + TrustManagerFactory.getDefaultAlgorithm()); + trustManagerFactory.init(keyStore); + + // Client key and certificates are sent to server so it can authenticate the client + KeyStore clientKeyStore = KeyStore.getInstance(KeyStore.getDefaultType()); + clientKeyStore.load(null, null); + clientKeyStore.setCertificateEntry("certificate", cert); + clientKeyStore.setKeyEntry("private-key", key.getPrivate(), password.toCharArray(), + new Certificate[]{cert}); + + KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance( + KeyManagerFactory.getDefaultAlgorithm()); + keyManagerFactory.init(clientKeyStore, password.toCharArray()); + + // Create SSL socket factory + SSLContext context = SSLContext.getInstance("TLSv1.3"); + context.init(keyManagerFactory.getKeyManagers(), + trustManagerFactory.getTrustManagers(), null); + + // Return the newly created socket factory object + return context.getSocketFactory(); + } catch (Exception e) { + LOGGER.error(e.getMessage()); + } + + return null; + } +} diff --git a/client/src/test/java/com/vesoft/nebula/client/graph/data/TestDataFromServer.java b/client/src/test/java/com/vesoft/nebula/client/graph/data/TestDataFromServer.java index aebb7ef88..d71442857 100644 --- a/client/src/test/java/com/vesoft/nebula/client/graph/data/TestDataFromServer.java +++ b/client/src/test/java/com/vesoft/nebula/client/graph/data/TestDataFromServer.java @@ -451,4 +451,84 @@ public void testErrorForJson() { assert false; } } + + @Test + public void testSelfSignedSsl() { + Session sslSession = null; + NebulaPool sslPool = new NebulaPool(); + try { + Runtime runtime = Runtime.getRuntime(); + runtime.exec("docker-compose -f src/test/resources/docker-compose" + + "-selfsigned.yaml up -d").waitFor(20,TimeUnit.SECONDS); + + NebulaPoolConfig nebulaSslPoolConfig = new NebulaPoolConfig(); + nebulaSslPoolConfig.setMaxConnSize(100); + nebulaSslPoolConfig.setEnableSsl(true); + nebulaSslPoolConfig.setSslParam(new SelfSignedSSLParam( + "src/test/resources/ssl/selfsigned.pem", + "src/test/resources/ssl/selfsigned.key", + "vesoft")); + Assert.assertTrue(sslPool.init(Arrays.asList(new HostAddress("127.0.0.1", 8669)), + nebulaSslPoolConfig)); + sslSession = sslPool.getSession("root", "nebula", true); + + String ngql = "YIELD 1"; + JSONObject resp = JSON.parseObject(sslSession.executeJson(ngql)); + String rowData = resp.getJSONArray("results").getJSONObject(0).getJSONArray("data") + .getJSONObject(0).getJSONArray("row").toJSONString(); + String exp = "[1]"; + Assert.assertEquals(rowData, exp); + + runtime.exec("docker-compose -f src/test/resources/docker-compose" + + "-selfsigned.yaml down").waitFor(60,TimeUnit.SECONDS); + } catch (Exception e) { + e.printStackTrace(); + assert false; + } finally { + if (sslSession != null) { + sslSession.release(); + } + sslPool.close(); + } + } + + @Test + public void testCASignedSsl() { + Session sslSession = null; + NebulaPool sslPool = new NebulaPool(); + try { + Runtime runtime = Runtime.getRuntime(); + runtime.exec("docker-compose -f src/test/resources/docker-compose" + + "-casigned.yaml up -d").waitFor(20,TimeUnit.SECONDS); + + NebulaPoolConfig nebulaSslPoolConfig = new NebulaPoolConfig(); + nebulaSslPoolConfig.setMaxConnSize(100); + nebulaSslPoolConfig.setEnableSsl(true); + nebulaSslPoolConfig.setSslParam(new CASignedSSLParam( + "src/test/resources/ssl/casigned.pem", + "src/test/resources/ssl/casigned.crt", + "src/test/resources/ssl/casigned.key")); + Assert.assertTrue(sslPool.init(Arrays.asList(new HostAddress("127.0.0.1", 8669)), + nebulaSslPoolConfig)); + sslSession = sslPool.getSession("root", "nebula", true); + + String ngql = "YIELD 1"; + JSONObject resp = JSON.parseObject(sslSession.executeJson(ngql)); + String rowData = resp.getJSONArray("results").getJSONObject(0).getJSONArray("data") + .getJSONObject(0).getJSONArray("row").toJSONString(); + String exp = "[1]"; + Assert.assertEquals(rowData, exp); + + runtime.exec("docker-compose -f src/test/resources/docker-compose" + + "-casigned.yaml down").waitFor(60,TimeUnit.SECONDS); + } catch (Exception e) { + e.printStackTrace(); + assert false; + } finally { + if (sslSession != null) { + sslSession.release(); + } + sslPool.close(); + } + } } diff --git a/client/src/test/resources/docker-compose-casigned.yaml b/client/src/test/resources/docker-compose-casigned.yaml new file mode 100644 index 000000000..bfdd1b96d --- /dev/null +++ b/client/src/test/resources/docker-compose-casigned.yaml @@ -0,0 +1,135 @@ +version: '3.4' +services: + metad-casigned: + image: vesoft/nebula-metad:nightly + environment: + USER: root + TZ: "${TZ}" + command: + - --meta_server_addrs=172.29.1.1:8559 + - --local_ip=172.29.1.1 + - --ws_ip=172.29.1.1 + - --port=8559 + - --data_path=/data/meta + - --log_dir=/logs + - --v=0 + - --minloglevel=0 + - --heartbeat_interval_secs=2 + - --expired_time_factor=2 + - --ws_h2_port=11000 + - --cert_path=/share/resources/test.derive.crt + - --key_path=/share/resources/test.derive.key + - --password_path=/share/resources/test.ca.password + - --enable_ssl=true + healthcheck: + test: ["CMD", "curl", "-f", "http://172.29.1.1:11000/status"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 20s + ports: + - "8559:8559" + - 11000 + - 11002 + volumes: + - ./data/meta:/data/meta:Z + - ./logs/meta:/logs:Z + - ./ssl:/share/resources:Z + networks: + nebula-net-casigned: + ipv4_address: 172.29.1.1 + restart: on-failure + cap_add: + - SYS_PTRACE + + storaged-casigned: + image: vesoft/nebula-storaged:nightly + environment: + USER: root + TZ: "${TZ}" + command: + - --meta_server_addrs=172.29.1.1:8559 + - --local_ip=172.29.2.1 + - --ws_ip=172.29.2.1 + - --port=8779 + - --data_path=/data/storage + - --log_dir=/logs + - --v=0 + - --minloglevel=0 + - --heartbeat_interval_secs=2 + - --timezone_name=+08:00:00 + - --ws_h2_port=12000 + - --cert_path=/share/resources/test.derive.crt + - --key_path=/share/resources/test.derive.key + - --password_path=/share/resources/test.ca.password + - --enable_ssl=true + depends_on: + - metad-casigned + healthcheck: + test: ["CMD", "curl", "-f", "http://172.29.2.1:12000/status"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 20s + ports: + - "8779:8779" + - 12000 + - 12002 + volumes: + - ./data/storage:/data/storage:Z + - ./logs/storage:/logs:Z + - ./ssl:/share/resources:Z + networks: + nebula-net-casigned: + ipv4_address: 172.29.2.1 + restart: on-failure + cap_add: + - SYS_PTRACE + + graphd-casigned: + image: vesoft/nebula-graphd:nightly + environment: + USER: root + TZ: "${TZ}" + command: + - --meta_server_addrs=172.29.1.1:8559 + - --port=8669 + - --ws_ip=172.29.3.1 + - --log_dir=/logs + - --v=0 + - --minloglevel=0 + - --heartbeat_interval_secs=2 + - --timezone_name=+08:00:00 + - --ws_h2_port=13000 + - --cert_path=/share/resources/test.derive.crt + - --key_path=/share/resources/test.derive.key + - --password_path=/share/resources/test.ca.password + - --enable_ssl=true + depends_on: + - metad-casigned + healthcheck: + test: ["CMD", "curl", "-f", "http://172.29.3.1:13000/status"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 20s + ports: + - "8669:8669" + - 13000 + - 13002 + volumes: + - ./logs/graph:/logs:Z + - ./ssl:/share/resources:Z + networks: + nebula-net-casigned: + ipv4_address: 172.29.3.1 + restart: on-failure + cap_add: + - SYS_PTRACE + +networks: + nebula-net-casigned: + ipam: + driver: default + config: + - subnet: 172.29.0.0/16 diff --git a/client/src/test/resources/docker-compose-selfsigned.yaml b/client/src/test/resources/docker-compose-selfsigned.yaml new file mode 100644 index 000000000..aeac1a60a --- /dev/null +++ b/client/src/test/resources/docker-compose-selfsigned.yaml @@ -0,0 +1,135 @@ +version: '3.4' +services: + metad-selfsigned: + image: vesoft/nebula-metad:nightly + environment: + USER: root + TZ: "${TZ}" + command: + - --meta_server_addrs=172.29.1.1:8559 + - --local_ip=172.29.1.1 + - --ws_ip=172.29.1.1 + - --port=8559 + - --data_path=/data/meta + - --log_dir=/logs + - --v=0 + - --minloglevel=0 + - --heartbeat_interval_secs=2 + - --expired_time_factor=2 + - --ws_h2_port=11000 + - --cert_path=/share/resources/test.derive.crt + - --key_path=/share/resources/test.derive.key + - --password_path=/share/resources/test.ca.password + - --enable_ssl=true + healthcheck: + test: ["CMD", "curl", "-f", "http://172.29.1.1:11000/status"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 20s + ports: + - "8559:8559" + - 11000 + - 11002 + volumes: + - ./data/meta:/data/meta:Z + - ./logs/meta:/logs:Z + - ./ssl:/share/resources:Z + networks: + nebula-net-selfsigned: + ipv4_address: 172.29.1.1 + restart: on-failure + cap_add: + - SYS_PTRACE + + storaged-selfsigned: + image: vesoft/nebula-storaged:nightly + environment: + USER: root + TZ: "${TZ}" + command: + - --meta_server_addrs=172.29.1.1:8559 + - --local_ip=172.29.2.1 + - --ws_ip=172.29.2.1 + - --port=8779 + - --data_path=/data/storage + - --log_dir=/logs + - --v=0 + - --minloglevel=0 + - --heartbeat_interval_secs=2 + - --timezone_name=+08:00:00 + - --ws_h2_port=12000 + - --cert_path=/share/resources/test.derive.crt + - --key_path=/share/resources/test.derive.key + - --password_path=/share/resources/test.ca.password + - --enable_ssl=true + depends_on: + - metad-selfsigned + healthcheck: + test: ["CMD", "curl", "-f", "http://172.29.2.1:12000/status"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 20s + ports: + - "8779:8779" + - 12000 + - 12002 + volumes: + - ./data/storage:/data/storage:Z + - ./logs/storage:/logs:Z + - ./ssl:/share/resources:Z + networks: + nebula-net-selfsigned: + ipv4_address: 172.29.2.1 + restart: on-failure + cap_add: + - SYS_PTRACE + + graphd-selfsigned: + image: vesoft/nebula-graphd:nightly + environment: + USER: root + TZ: "${TZ}" + command: + - --meta_server_addrs=172.29.1.1:8559 + - --port=8669 + - --ws_ip=172.29.3.1 + - --log_dir=/logs + - --v=0 + - --minloglevel=0 + - --heartbeat_interval_secs=2 + - --timezone_name=+08:00:00 + - --ws_h2_port=13000 + - --cert_path=/share/resources/test.derive.crt + - --key_path=/share/resources/test.derive.key + - --password_path=/share/resources/test.ca.password + - --enable_ssl=true + depends_on: + - metad-selfsigned + healthcheck: + test: ["CMD", "curl", "-f", "http://172.29.3.1:13000/status"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 20s + ports: + - "8669:8669" + - 13000 + - 13002 + volumes: + - ./logs/graph:/logs:Z + - ./ssl:/share/resources:Z + networks: + nebula-net-selfsigned: + ipv4_address: 172.29.3.1 + restart: on-failure + cap_add: + - SYS_PTRACE + +networks: + nebula-net-selfsigned: + ipam: + driver: default + config: + - subnet: 172.29.0.0/16 diff --git a/client/src/test/resources/ssl/casigned.crt b/client/src/test/resources/ssl/casigned.crt new file mode 100644 index 000000000..fe1add667 --- /dev/null +++ b/client/src/test/resources/ssl/casigned.crt @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE----- +MIICljCCAX4CCQC9uuUY+ah8qzANBgkqhkiG9w0BAQsFADANMQswCQYDVQQGEwJD +TjAeFw0yMTA5MjkwNzM4MDRaFw0yNDAxMDIwNzM4MDRaMA0xCzAJBgNVBAYTAkNO +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuo7hKpcs+VQKbGRq0fUL ++GcSfPfJ8mARtIeI8WfU0j1vI5KNujI//G2olOGEueDCw4OO0UbdjnsFpgj2awAo +rj4ga2W6adQHK8qHY6q/Rdqv0oDCrcePMtQ8IwbFjNWOXC4bn7GcV7mzOkigdcj8 +UPkSeaqI9XxBRm3OoDX+T8h6cDLrm+ncKB8KKe/QApKH4frV3HYDqGtN49zuRs6F +iurFbXDGVAZEdFEJl38IQJdmE2ASOzEHZbxWKzO/DZr/Z2+L1CuycZIwuITcnddx +b2Byx/opwX4HlyODeUBbyDp+hd+GkasmIcpOlIDw9OXIvrcajKvzLEbqGt2ThsxX +QwIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQAxzxtbYBQ2WgBGrpzOX4TxsuSaigqo +YJ5zbVEHtwbsbBTZ7UJvRc9IyhrOL5Ui4PJI85chh1GpGqOmMoYSaWdddaIroilQ +56bn5haB8ezAMnLXbPuf97UENO0RIkyzt63XPIUkDnwlzOukIq50qgsYEDuiioM/ +wpCqSbMJ4iK/SlSSUWw3cKuAHvFfLv7hkC6AhvT7yfaCNDs29xEQUCD12XlIdFGH +FjMgVMcvcIePQq5ZcmSfVMge9jPjPx/Nj9SVauF5z5pil9qHG4jyXPGThiiJ3CE4 +GU5d/Qfe7OeiYI3LaoVufZ5pZnR9nMnpzqU46w9gY7vgi6bAhNwsCDr3 +-----END CERTIFICATE----- diff --git a/client/src/test/resources/ssl/casigned.key b/client/src/test/resources/ssl/casigned.key new file mode 100644 index 000000000..3561e7ab8 --- /dev/null +++ b/client/src/test/resources/ssl/casigned.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAuo7hKpcs+VQKbGRq0fUL+GcSfPfJ8mARtIeI8WfU0j1vI5KN +ujI//G2olOGEueDCw4OO0UbdjnsFpgj2awAorj4ga2W6adQHK8qHY6q/Rdqv0oDC +rcePMtQ8IwbFjNWOXC4bn7GcV7mzOkigdcj8UPkSeaqI9XxBRm3OoDX+T8h6cDLr +m+ncKB8KKe/QApKH4frV3HYDqGtN49zuRs6FiurFbXDGVAZEdFEJl38IQJdmE2AS +OzEHZbxWKzO/DZr/Z2+L1CuycZIwuITcnddxb2Byx/opwX4HlyODeUBbyDp+hd+G +kasmIcpOlIDw9OXIvrcajKvzLEbqGt2ThsxXQwIDAQABAoIBAH4SEBe4EaxsHp8h +PQ6linFTNis9SDuCsHRPIzv/7tIksfZYE27Ahn0Pndz+ibMTMIrvXJQQT6j5ede6 +NswYT2Vwlnf9Rvw9TJtLQjMYMCoEnsyiNu047oxq4DjLWrTRnGKuxfwlCoI9++Bn +NAhkyh3uM44EsIk0bugpTHj4A+PlbUPe7xdEI/6XpaZrRN9oiejJ4VxZAPgFGiTm +uNF5qg16+0900Pfj5Y/M4vXmn+gq39PO/y0FlTpaoEuYZiZZS3xHGmSVhlt8LIgI +8MdMRaKTfNeNITaqgOWh9pAW4xmK48/KfLgNPQgtDHjMJpgM0BbcBOayOY8Eio0x +Z66G2AECgYEA9vj/8Fm3CKn/ogNOO81y9kIs0iPcbjasMnQ3UXeOdD0z0+7TM86F +Xj3GK/z2ecvY7skWtO5ZUbbxp4aB7omW8Ke9+q8XPzMEmUuAOTzxQkAOxdr++HXP +TILy0hNX2cmiLQT1U60KoZHzPZ5o5hNIQPMt7hN12ERWcIfR/MUZa5UCgYEAwWCP +6Y7Zso1QxQR/qfjuILET3/xU+ZmqSRDvzJPEiGI3oeWNG4L6cKR+XTe0FWZBAmVk +Qq/1qXmdBnf5S7azffoJe2+H/m3kHJSprIiAAWlBN2e+kFlNfBhtkgia5NvsrjRw +al6mf/+weRD1FiPoZY3e1wBKoqro7aI8fE5gwXcCgYEAnEI05OROeyvb8qy2vf2i +JA8AfsBzwkPTNWT0bxX+yqrCdO/hLyEWnubk0IYPiEYibgpK1JUNbDcctErVQJBL +MN5gxBAt3C2yVi8/5HcbijgvYJ3LvnYDf7xGWAYnCkOZ2XQOqC+Oz2UhijYE1rUS +fQ2fXMdxQzERo8c7Y/tstvUCgYBuixy5jwezokUB20h/ieXWmmOaL00EQmutyRjM +AczfigXzbp3zlDRGIEJ8V1OCyClxjTR7SstMTlENWZgRSCfjZAP3pBJBx+AW1oUI +NB+4rsqxOYUeT26T+gLo8DJbkb0C+Mcqh2D22tuu2ZrBRVWceDVjAq+nvbvZ3Fxn +UwbMkQKBgQCxL3aA6ART6laIxT/ZqMhV0ZcaoDJogjF+4I4bhlO4ivWGWJ4RpEDn +ziFb6+M/4pe4vCou9yuAof6WTKM8JG4rok0yxhN3V6QGP49TjtrfkkrEPCtB2LSI +N1+YRSTrS5VDcl8h8JH7fpghRnXHONEyIqasYVqsbxKzNyLV/z2rkw== +-----END RSA PRIVATE KEY----- diff --git a/client/src/test/resources/ssl/casigned.pem b/client/src/test/resources/ssl/casigned.pem new file mode 100644 index 000000000..412ba3161 --- /dev/null +++ b/client/src/test/resources/ssl/casigned.pem @@ -0,0 +1,24 @@ +-----BEGIN CERTIFICATE----- +MIIEGzCCAwOgAwIBAgIUDcmZFpL4PcdCXfLRBK8bR2vb39cwDQYJKoZIhvcNAQEL +BQAwgZwxCzAJBgNVBAYTAkNOMREwDwYDVQQIDAhaaGVqaWFuZzERMA8GA1UEBwwI +SGFuZ3pob3UxFDASBgNVBAoMC1Zlc29mdCBJbmMuMRAwDgYDVQQLDAdzZWN0aW9u +MRYwFAYDVQQDDA1zaHlsb2NrIGh1YW5nMScwJQYJKoZIhvcNAQkBFhhzaHlsb2Nr +Lmh1YW5nQHZlc29mdC5jb20wHhcNMjEwODE5MDkyNDQ3WhcNMjUwODE4MDkyNDQ3 +WjCBnDELMAkGA1UEBhMCQ04xETAPBgNVBAgMCFpoZWppYW5nMREwDwYDVQQHDAhI +YW5nemhvdTEUMBIGA1UECgwLVmVzb2Z0IEluYy4xEDAOBgNVBAsMB3NlY3Rpb24x +FjAUBgNVBAMMDXNoeWxvY2sgaHVhbmcxJzAlBgkqhkiG9w0BCQEWGHNoeWxvY2su +aHVhbmdAdmVzb2Z0LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AMEAgpamCQHl+8JnUHI6/VmJHjDLYJLTliN/CwpFrhMqIVjJ8wG57WYLpXpn91Lz +eHu52LkVzcikybIJ2a+LOTvnhNFdbmTbqDtrb+s6wM/sO+nF6tU2Av4e5zhyKoeR +LL+rHMk3nymohbdN4djySFmOOU5A1O/4b0bZz4Ylu995kUawdiaEo13BzxxOC7Ik +Gge5RyDcm0uLXZqTAPy5Sjv/zpOyj0AqL1CJUH7XBN9OMRhVU0ZX9nHWl1vgLRld +J6XT17Y9QbbHhCNEdAmFE5kEFgCvZc+MungUYABlkvoj86TLmC/FMV6fWdxQssyd +hS+ssfJFLaTDaEFz5a/Tr48CAwEAAaNTMFEwHQYDVR0OBBYEFK0GVrQx+wX1GCHy +e+6fl4X+prmYMB8GA1UdIwQYMBaAFK0GVrQx+wX1GCHye+6fl4X+prmYMA8GA1Ud +EwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAHqP8P+ZUHmngviHLSSN1ln5 +Mx4BCkVeFRUaFx0yFXytV/iLXcG2HpFg3A9rAFoYgCDwi1xpsERnBZ/ShTv/eFOc +IxBY5yggx3/lGi8tAgvUdarhd7mQO67UJ0V4YU3hAkbnZ8grHHXj+4hfgUpY4ok6 +yaed6HXwknBb9W8N1jZI8ginhkhjaeRCHdMiF+fBvNCtmeR1bCml1Uz7ailrpcaT +Mf84+5VYuFEnaRZYWFNsWNCOBlJ/6/b3V10vMXzMmYHqz3xgAq0M3fVTFTzopnAX +DLSzorL/dYVdqEDCQi5XI9YAlgWN4VeGzJI+glkLOCNzHxRNP6Qev+YI+7Uxz6I= +-----END CERTIFICATE----- diff --git a/client/src/test/resources/ssl/selfsigned.key b/client/src/test/resources/ssl/selfsigned.key new file mode 100644 index 000000000..6006d0f27 --- /dev/null +++ b/client/src/test/resources/ssl/selfsigned.key @@ -0,0 +1,30 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,6D12ED8559E80FA3 + +tv9epnwlt4dP6Q5ee0dACOyFA5BTwYTdoMykQRJrKGwfaNeXUXn+sQ/U/oFHp1Wx +O8VZE+z2aHpiFSTw+Eh6MPt86X5yVG3tpeVO6dErvr8Kd+NpuI8zn7rNoOFRh8wD +33EFcQMLQPneDl10O18hooIoi0qwp1pd63hYZPwEhB3eOrM5Mnv9OVJs65bzYfyf +Wku33YWYxeqlDvMCsou8PZnv/M2wYsr7+QoTcNmGKP45igMthMDBzwgF+q0p9ZZU +N11c6ojAs01kfuqFf3vKfHNYe6zsBiNhnUuEy8enXSxD5E7tR/OI8aEzPLdk7fmN +/UsMK2LE0Yd5iS3O1x/1ZjSBxJ+M/UzzCO692GTAiD6Hc13iJOavq/vt1mEPjfCD +neF38Bhb5DfFi+UAHrz6EHMreamGCzP82us2maIs7mSTq7nXDZfbBc7mBDLAUUnT +J6tlrTyc+DQXzkJa6jmbxJhcsWm6XvjIBEzSXVHxEDPLnZICQk3VXODjCXTD75Rg +0WaS78Ven7DW8wn07q3VzWAFDKaet3VI+TVTv7EfIavlfiA6LSshaENdFLeHahNE +s/V/j5K3Pg6+WQcZRgOsfqIwUCSQxY13R6TTdaaCkLay5BggF5iiAO3pkqsJiadf +w843Ak4USBptymJxoZgJyFtQHpQyNiFfsAbs9BaYbg2evvE7/VQhLk0gQ7HgQMeJ +wgxEQqZQKDCCSugSzY1YEGXKnrZYCKyipzyyH936mE15zNwhYp/Pi2020+gmtP3h +CDfcPs1yeLI2/1JuimafbuKsv9xchWa6ASU8p8Q7wTLtUj9ylLKyA4A/75pK0DXG +Hv/q0O+UfhAMD438SoPBle7RSvIsDU1VjUqstlNybBglBZxGIME7/18+Ms7U32wh +4xFkZwxT2nqFgyk37tXMdMz9UBh12/AXR9NU4XY37C3Ao2TDT7/0DvU6KdJhsDpv +rGcaC2zzhko+0CPrLlk52KbqP003JXiWvOSI+FylyPPDB/YGitmndJUuQblf3u/E +l+tGi9MeSBQeWKV6D3AVnO05AZjfTUzSK0vw4DgNh5YPNJvLy31B7kDAS88vyGI1 +t6MBwjW4/tz/nS/p1Go3mSzBhPkIsCrZE+ar7lH8p8JqkLl4fXIMaVKIfyfJdzyS +lkh3K7bOGDPegxxxaWdb+EnC7k+1R3EOU7uJFW61HyrGI3q6Y7kOl5aYSJ5Ge1Uv +PycFWHWVTHq/R7HRE6HIJzGe/PnLIbStXLDFeivjfcYq1YaSaF8Vl+xg+0u3ULOl +P6IuPTph6dlcgttRZVl3ETcF0T+2wfbUwgjf0ZiguCJfR2jLGhPl1KBg0Kd9cTSY +zI3YMMd2G8hApt/QFlm4Ry8CqaJUmDcjDNIJT3M+RldUgfz37NsX05cA5e9+I1AL +2406F/v5U9gWsYx7HuwJtQrDzYYDbl1GD4H+qHFJE5JYhPP4AyWYxJ1NR5dqyvrt ++3r5+xlwZrS76c10RsBWL7th8ZEzRxOZxbtLwbf4bG/tIGfQP2sTnWwA+qym6b2S +sRduqOTP+xwnhOq/ZKn8lfsDfhT8CPnKHBsd09kM9y/UWuxFe0upLydRLE/Wsb9s +-----END RSA PRIVATE KEY----- diff --git a/client/src/test/resources/ssl/selfsigned.password b/client/src/test/resources/ssl/selfsigned.password new file mode 100644 index 000000000..143be9ab9 --- /dev/null +++ b/client/src/test/resources/ssl/selfsigned.password @@ -0,0 +1 @@ +vesoft diff --git a/client/src/test/resources/ssl/selfsigned.pem b/client/src/test/resources/ssl/selfsigned.pem new file mode 100644 index 000000000..412ba3161 --- /dev/null +++ b/client/src/test/resources/ssl/selfsigned.pem @@ -0,0 +1,24 @@ +-----BEGIN CERTIFICATE----- +MIIEGzCCAwOgAwIBAgIUDcmZFpL4PcdCXfLRBK8bR2vb39cwDQYJKoZIhvcNAQEL +BQAwgZwxCzAJBgNVBAYTAkNOMREwDwYDVQQIDAhaaGVqaWFuZzERMA8GA1UEBwwI +SGFuZ3pob3UxFDASBgNVBAoMC1Zlc29mdCBJbmMuMRAwDgYDVQQLDAdzZWN0aW9u +MRYwFAYDVQQDDA1zaHlsb2NrIGh1YW5nMScwJQYJKoZIhvcNAQkBFhhzaHlsb2Nr +Lmh1YW5nQHZlc29mdC5jb20wHhcNMjEwODE5MDkyNDQ3WhcNMjUwODE4MDkyNDQ3 +WjCBnDELMAkGA1UEBhMCQ04xETAPBgNVBAgMCFpoZWppYW5nMREwDwYDVQQHDAhI +YW5nemhvdTEUMBIGA1UECgwLVmVzb2Z0IEluYy4xEDAOBgNVBAsMB3NlY3Rpb24x +FjAUBgNVBAMMDXNoeWxvY2sgaHVhbmcxJzAlBgkqhkiG9w0BCQEWGHNoeWxvY2su +aHVhbmdAdmVzb2Z0LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AMEAgpamCQHl+8JnUHI6/VmJHjDLYJLTliN/CwpFrhMqIVjJ8wG57WYLpXpn91Lz +eHu52LkVzcikybIJ2a+LOTvnhNFdbmTbqDtrb+s6wM/sO+nF6tU2Av4e5zhyKoeR +LL+rHMk3nymohbdN4djySFmOOU5A1O/4b0bZz4Ylu995kUawdiaEo13BzxxOC7Ik +Gge5RyDcm0uLXZqTAPy5Sjv/zpOyj0AqL1CJUH7XBN9OMRhVU0ZX9nHWl1vgLRld +J6XT17Y9QbbHhCNEdAmFE5kEFgCvZc+MungUYABlkvoj86TLmC/FMV6fWdxQssyd +hS+ssfJFLaTDaEFz5a/Tr48CAwEAAaNTMFEwHQYDVR0OBBYEFK0GVrQx+wX1GCHy +e+6fl4X+prmYMB8GA1UdIwQYMBaAFK0GVrQx+wX1GCHye+6fl4X+prmYMA8GA1Ud +EwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAHqP8P+ZUHmngviHLSSN1ln5 +Mx4BCkVeFRUaFx0yFXytV/iLXcG2HpFg3A9rAFoYgCDwi1xpsERnBZ/ShTv/eFOc +IxBY5yggx3/lGi8tAgvUdarhd7mQO67UJ0V4YU3hAkbnZ8grHHXj+4hfgUpY4ok6 +yaed6HXwknBb9W8N1jZI8ginhkhjaeRCHdMiF+fBvNCtmeR1bCml1Uz7ailrpcaT +Mf84+5VYuFEnaRZYWFNsWNCOBlJ/6/b3V10vMXzMmYHqz3xgAq0M3fVTFTzopnAX +DLSzorL/dYVdqEDCQi5XI9YAlgWN4VeGzJI+glkLOCNzHxRNP6Qev+YI+7Uxz6I= +-----END CERTIFICATE----- diff --git a/client/src/test/resources/ssl/test.ca.key b/client/src/test/resources/ssl/test.ca.key new file mode 100644 index 000000000..6006d0f27 --- /dev/null +++ b/client/src/test/resources/ssl/test.ca.key @@ -0,0 +1,30 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,6D12ED8559E80FA3 + +tv9epnwlt4dP6Q5ee0dACOyFA5BTwYTdoMykQRJrKGwfaNeXUXn+sQ/U/oFHp1Wx +O8VZE+z2aHpiFSTw+Eh6MPt86X5yVG3tpeVO6dErvr8Kd+NpuI8zn7rNoOFRh8wD +33EFcQMLQPneDl10O18hooIoi0qwp1pd63hYZPwEhB3eOrM5Mnv9OVJs65bzYfyf +Wku33YWYxeqlDvMCsou8PZnv/M2wYsr7+QoTcNmGKP45igMthMDBzwgF+q0p9ZZU +N11c6ojAs01kfuqFf3vKfHNYe6zsBiNhnUuEy8enXSxD5E7tR/OI8aEzPLdk7fmN +/UsMK2LE0Yd5iS3O1x/1ZjSBxJ+M/UzzCO692GTAiD6Hc13iJOavq/vt1mEPjfCD +neF38Bhb5DfFi+UAHrz6EHMreamGCzP82us2maIs7mSTq7nXDZfbBc7mBDLAUUnT +J6tlrTyc+DQXzkJa6jmbxJhcsWm6XvjIBEzSXVHxEDPLnZICQk3VXODjCXTD75Rg +0WaS78Ven7DW8wn07q3VzWAFDKaet3VI+TVTv7EfIavlfiA6LSshaENdFLeHahNE +s/V/j5K3Pg6+WQcZRgOsfqIwUCSQxY13R6TTdaaCkLay5BggF5iiAO3pkqsJiadf +w843Ak4USBptymJxoZgJyFtQHpQyNiFfsAbs9BaYbg2evvE7/VQhLk0gQ7HgQMeJ +wgxEQqZQKDCCSugSzY1YEGXKnrZYCKyipzyyH936mE15zNwhYp/Pi2020+gmtP3h +CDfcPs1yeLI2/1JuimafbuKsv9xchWa6ASU8p8Q7wTLtUj9ylLKyA4A/75pK0DXG +Hv/q0O+UfhAMD438SoPBle7RSvIsDU1VjUqstlNybBglBZxGIME7/18+Ms7U32wh +4xFkZwxT2nqFgyk37tXMdMz9UBh12/AXR9NU4XY37C3Ao2TDT7/0DvU6KdJhsDpv +rGcaC2zzhko+0CPrLlk52KbqP003JXiWvOSI+FylyPPDB/YGitmndJUuQblf3u/E +l+tGi9MeSBQeWKV6D3AVnO05AZjfTUzSK0vw4DgNh5YPNJvLy31B7kDAS88vyGI1 +t6MBwjW4/tz/nS/p1Go3mSzBhPkIsCrZE+ar7lH8p8JqkLl4fXIMaVKIfyfJdzyS +lkh3K7bOGDPegxxxaWdb+EnC7k+1R3EOU7uJFW61HyrGI3q6Y7kOl5aYSJ5Ge1Uv +PycFWHWVTHq/R7HRE6HIJzGe/PnLIbStXLDFeivjfcYq1YaSaF8Vl+xg+0u3ULOl +P6IuPTph6dlcgttRZVl3ETcF0T+2wfbUwgjf0ZiguCJfR2jLGhPl1KBg0Kd9cTSY +zI3YMMd2G8hApt/QFlm4Ry8CqaJUmDcjDNIJT3M+RldUgfz37NsX05cA5e9+I1AL +2406F/v5U9gWsYx7HuwJtQrDzYYDbl1GD4H+qHFJE5JYhPP4AyWYxJ1NR5dqyvrt ++3r5+xlwZrS76c10RsBWL7th8ZEzRxOZxbtLwbf4bG/tIGfQP2sTnWwA+qym6b2S +sRduqOTP+xwnhOq/ZKn8lfsDfhT8CPnKHBsd09kM9y/UWuxFe0upLydRLE/Wsb9s +-----END RSA PRIVATE KEY----- diff --git a/client/src/test/resources/ssl/test.ca.password b/client/src/test/resources/ssl/test.ca.password new file mode 100644 index 000000000..143be9ab9 --- /dev/null +++ b/client/src/test/resources/ssl/test.ca.password @@ -0,0 +1 @@ +vesoft diff --git a/client/src/test/resources/ssl/test.ca.pem b/client/src/test/resources/ssl/test.ca.pem new file mode 100644 index 000000000..412ba3161 --- /dev/null +++ b/client/src/test/resources/ssl/test.ca.pem @@ -0,0 +1,24 @@ +-----BEGIN CERTIFICATE----- +MIIEGzCCAwOgAwIBAgIUDcmZFpL4PcdCXfLRBK8bR2vb39cwDQYJKoZIhvcNAQEL +BQAwgZwxCzAJBgNVBAYTAkNOMREwDwYDVQQIDAhaaGVqaWFuZzERMA8GA1UEBwwI +SGFuZ3pob3UxFDASBgNVBAoMC1Zlc29mdCBJbmMuMRAwDgYDVQQLDAdzZWN0aW9u +MRYwFAYDVQQDDA1zaHlsb2NrIGh1YW5nMScwJQYJKoZIhvcNAQkBFhhzaHlsb2Nr +Lmh1YW5nQHZlc29mdC5jb20wHhcNMjEwODE5MDkyNDQ3WhcNMjUwODE4MDkyNDQ3 +WjCBnDELMAkGA1UEBhMCQ04xETAPBgNVBAgMCFpoZWppYW5nMREwDwYDVQQHDAhI +YW5nemhvdTEUMBIGA1UECgwLVmVzb2Z0IEluYy4xEDAOBgNVBAsMB3NlY3Rpb24x +FjAUBgNVBAMMDXNoeWxvY2sgaHVhbmcxJzAlBgkqhkiG9w0BCQEWGHNoeWxvY2su +aHVhbmdAdmVzb2Z0LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AMEAgpamCQHl+8JnUHI6/VmJHjDLYJLTliN/CwpFrhMqIVjJ8wG57WYLpXpn91Lz +eHu52LkVzcikybIJ2a+LOTvnhNFdbmTbqDtrb+s6wM/sO+nF6tU2Av4e5zhyKoeR +LL+rHMk3nymohbdN4djySFmOOU5A1O/4b0bZz4Ylu995kUawdiaEo13BzxxOC7Ik +Gge5RyDcm0uLXZqTAPy5Sjv/zpOyj0AqL1CJUH7XBN9OMRhVU0ZX9nHWl1vgLRld +J6XT17Y9QbbHhCNEdAmFE5kEFgCvZc+MungUYABlkvoj86TLmC/FMV6fWdxQssyd +hS+ssfJFLaTDaEFz5a/Tr48CAwEAAaNTMFEwHQYDVR0OBBYEFK0GVrQx+wX1GCHy +e+6fl4X+prmYMB8GA1UdIwQYMBaAFK0GVrQx+wX1GCHye+6fl4X+prmYMA8GA1Ud +EwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAHqP8P+ZUHmngviHLSSN1ln5 +Mx4BCkVeFRUaFx0yFXytV/iLXcG2HpFg3A9rAFoYgCDwi1xpsERnBZ/ShTv/eFOc +IxBY5yggx3/lGi8tAgvUdarhd7mQO67UJ0V4YU3hAkbnZ8grHHXj+4hfgUpY4ok6 +yaed6HXwknBb9W8N1jZI8ginhkhjaeRCHdMiF+fBvNCtmeR1bCml1Uz7ailrpcaT +Mf84+5VYuFEnaRZYWFNsWNCOBlJ/6/b3V10vMXzMmYHqz3xgAq0M3fVTFTzopnAX +DLSzorL/dYVdqEDCQi5XI9YAlgWN4VeGzJI+glkLOCNzHxRNP6Qev+YI+7Uxz6I= +-----END CERTIFICATE----- diff --git a/client/src/test/resources/ssl/test.ca.srl b/client/src/test/resources/ssl/test.ca.srl new file mode 100644 index 000000000..877d296b7 --- /dev/null +++ b/client/src/test/resources/ssl/test.ca.srl @@ -0,0 +1 @@ +4AF2EBB941EA7EE8358ECC7E51C2F1A38EE18873 diff --git a/client/src/test/resources/ssl/test.derive.crt b/client/src/test/resources/ssl/test.derive.crt new file mode 100644 index 000000000..8f03073e2 --- /dev/null +++ b/client/src/test/resources/ssl/test.derive.crt @@ -0,0 +1,23 @@ +-----BEGIN CERTIFICATE----- +MIIDvjCCAqYCFEry67lB6n7oNY7MflHC8aOO4YhzMA0GCSqGSIb3DQEBCwUAMIGc +MQswCQYDVQQGEwJDTjERMA8GA1UECAwIWmhlamlhbmcxETAPBgNVBAcMCEhhbmd6 +aG91MRQwEgYDVQQKDAtWZXNvZnQgSW5jLjEQMA4GA1UECwwHc2VjdGlvbjEWMBQG +A1UEAwwNc2h5bG9jayBodWFuZzEnMCUGCSqGSIb3DQEJARYYc2h5bG9jay5odWFu +Z0B2ZXNvZnQuY29tMB4XDTIxMDgyNDEwNTExMloXDTIzMTEyNzEwNTExMlowgZkx +CzAJBgNVBAYTAkNOMREwDwYDVQQIDAhaaGVqaWFuZzERMA8GA1UEBwwISGFuZ3po +b3UxFDASBgNVBAoMC1Zlc29mdCBJbmMuMRAwDgYDVQQLDAdzZWN0aW9uMRMwEQYD +VQQDDApTaHlsb2NrIEhnMScwJQYJKoZIhvcNAQkBFhhzaHlsb2NrLmh1YW5nQHZl +c29mdC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDHk1PQtaCG +S31nvxKuT6pzVQuOsA2hEIDzBZuoBK3blezBB16fjUWG2wHG/r9Oss5YzOly4viL +1oFLsNdYg27EFH7pcGfdSUmZa6LHILegJTmLa1aB4lRG9EsvPIxNuo637CW2z6EW +ElVKXn2N1G1vW3fpKGxJ+d1ovaFfBliO0sK+myW+vYdKrNg70WqKKCoCIlIjEWw3 +vQdrmvhuhIBbG1bXkXbJwIepBdb4wGSx8qsgs93I6/je/K/iJaPJIqdH8loo6fSo +DBUiNA87ZsQdtbBeuk7QuF71SxD5+E8wCMtFMwRGmL0vYMPwkaurKxwEs49e8eTz +RvIrNtyYgVo7AgMBAAEwDQYJKoZIhvcNAQELBQADggEBAGBpm5OLXn02kWr1ENU5 +FOOVryD41SCmPy8hLwQ2MCXd446UfTXc5TTlllksaePn373ZANLUe78vUCoVPjOh +dU5GxyOKtubXovI+yuvMS11u00KtgiAd5qa+IhX3c/P60bh4+fdKZ9ViyLsG+IpQ ++XDYT2uekLyjXXJU6h1raW7M1VY9FcDC63moXz0WgWJ/9tJgB0ZQkVcL+2UpveoZ +Whf9P0xAzCmNSrR7CMhdeRN2vBQQaHXk/64wkHncdkz/NglVl00rh4MtBKZ6Cqze +uZvgrxOJNzB4aXBMHO7sWzw1VSfS79CZm4H39hBWGiVEkr3yZYQbboDRY6F5dQyc +BZc= +-----END CERTIFICATE----- diff --git a/client/src/test/resources/ssl/test.derive.csr b/client/src/test/resources/ssl/test.derive.csr new file mode 100644 index 000000000..89b26237e --- /dev/null +++ b/client/src/test/resources/ssl/test.derive.csr @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIDEjCCAfoCAQAwgZkxCzAJBgNVBAYTAkNOMREwDwYDVQQIDAhaaGVqaWFuZzER +MA8GA1UEBwwISGFuZ3pob3UxFDASBgNVBAoMC1Zlc29mdCBJbmMuMRAwDgYDVQQL +DAdzZWN0aW9uMRMwEQYDVQQDDApTaHlsb2NrIEhnMScwJQYJKoZIhvcNAQkBFhhz +aHlsb2NrLmh1YW5nQHZlc29mdC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw +ggEKAoIBAQDHk1PQtaCGS31nvxKuT6pzVQuOsA2hEIDzBZuoBK3blezBB16fjUWG +2wHG/r9Oss5YzOly4viL1oFLsNdYg27EFH7pcGfdSUmZa6LHILegJTmLa1aB4lRG +9EsvPIxNuo637CW2z6EWElVKXn2N1G1vW3fpKGxJ+d1ovaFfBliO0sK+myW+vYdK +rNg70WqKKCoCIlIjEWw3vQdrmvhuhIBbG1bXkXbJwIepBdb4wGSx8qsgs93I6/je +/K/iJaPJIqdH8loo6fSoDBUiNA87ZsQdtbBeuk7QuF71SxD5+E8wCMtFMwRGmL0v +YMPwkaurKxwEs49e8eTzRvIrNtyYgVo7AgMBAAGgMzAVBgkqhkiG9w0BCQcxCAwG +dmVzb2Z0MBoGCSqGSIb3DQEJAjENDAtWZXNvZnQgSW5jLjANBgkqhkiG9w0BAQsF +AAOCAQEAjmyCyxziJMR8NILRAwmfYcBB90CbTFMMEyWy402KxoXcyVZBGO2eukIq +gaF2ywuh6yuTPtGsdVMVTWDQ4RLYpoQoR5Blu+M8Or8rhZSfMYXi79Ne3abSF28E +eWjBmh2Ys0GtaThlufJBWE+vWPH2iEGrSRTg1fvBLBzAW6nXU2svoTrKfDcEoY5z +xB0CKhBoewoIZ2FPBmBAnIWHfXR/vQ76QIoNdfQ4nT8iXuLRoNjRlvVU4AUDwKtu +keRDrnmJ7A5eqTlleCMzra2MAp9Na9gojXlGQP9q9V8nFtSvbjYAoH0ezWpdWj4+ +Rtu9EK4JkDymmmZcneFapExZrRLt0A== +-----END CERTIFICATE REQUEST----- diff --git a/client/src/test/resources/ssl/test.derive.key b/client/src/test/resources/ssl/test.derive.key new file mode 100644 index 000000000..a011917b3 --- /dev/null +++ b/client/src/test/resources/ssl/test.derive.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAx5NT0LWghkt9Z78Srk+qc1ULjrANoRCA8wWbqASt25XswQde +n41FhtsBxv6/TrLOWMzpcuL4i9aBS7DXWINuxBR+6XBn3UlJmWuixyC3oCU5i2tW +geJURvRLLzyMTbqOt+wlts+hFhJVSl59jdRtb1t36ShsSfndaL2hXwZYjtLCvpsl +vr2HSqzYO9FqiigqAiJSIxFsN70Ha5r4boSAWxtW15F2ycCHqQXW+MBksfKrILPd +yOv43vyv4iWjySKnR/JaKOn0qAwVIjQPO2bEHbWwXrpO0Lhe9UsQ+fhPMAjLRTME +Rpi9L2DD8JGrqyscBLOPXvHk80byKzbcmIFaOwIDAQABAoIBAEZ50URHjzs9VziW +sdsaSN/XbXBi3T0+Xbr0BQatOFPtuqBjoNeJBL9dgWArP5Vj8RhMrDekzQ5cnmYD +OdiI+UmGz1ZSGmt7YOErsFzPQejsnEiOjArryMURqacxo34jXhi27I6E/aaUrMfJ +XF8EX+zOCSct3ie1c6l0JZMv43/zbzP2vMFEdfnVfZA2Kxo5l3I4rjuxHUEWHzrb +EgM4a2+y7LQrut75zP9zWEZAqim/VEIEj24Gqj+Vocb6cHlc31KzKaEz7Ra5ha2J +kN2CQRKCzoMupVL5E6dWMiDVjUyUXdUgjSCIW2H+E1ONgvxA78jJx7+Dzj+/bWxH +h/vr3dkCgYEA9Aev7PGoGF0eapZY3crehvtCn1v4YLheh0dk4EpbpbEx0rQaG3h7 +YYCf7euxMvoTsKPETHAUG/s/RZV1DNOjxs8GKgEIVaRYEf1VZeDXudtnyKBwCMAL +5CKHRBvfmNG9n+PpQQlrIAZGej7HU+/IzEVsrD2A5DeH9IVpMNvrX10CgYEA0V1r +aydbBP+Ma/fiG5UDa8l4GdLzvAoW2cY6ZhQX4NiLTK91MwA/QOQcVMvJAN2KpPHC +kGDRT7IhMs66cMxl0ImIJ2QSnv8HRNmBBSdUtJx1S6nV2u0VfgP61oNT/YbLR/Jk +CAIl1qe7Q8IsrMbPxCbt8g+D8Wr9C3pdYYqFvncCgYEAicGdKmDwx3Apr3nYCLxx +CjnkzhkZCWCK3EsNQyA2xD5XJd7NrhxBajU2ExUuHtzVKK4KLixG7dTTTvCj9u2y +UpSjoiqbDd2MaftcrfpTTXPyDmujUw02qT5kpaomexpLtWrvTeuHMbjZKEEwPM3r +yISYaFL/49UFRp/ZVd+P63ECgYAX1B0ctf77A6bUxwK6Buy7wNNlhQful+tf39rX +sWPCWIMKOFILevS4Cv5afFMlQRG9kjKFwi8wdeKnaLX5jpnr8StI6G/iHr6SDHtN +vds7Ly9+bBcF8sPmcseC0LGngkbyqljOPIhX9QEwRhJVm88b0R511WQ7/uRMASJN +rrloIwKBgCxYlu1xvvEuQNoIux/yKAEJ1h4Ta2zc5upjw0uDKMi0UNIbNhgdFOvj +LuVbxTRU8WktrLNk3T0rsopKsTbEZVg6Yuv8ZLkEiNYTzhUbn2Y5yM3bnoVwyOns +pTtqmBtvDZxaRCYdIQG3b09IvrewDk26AOtNHdeKw883G2muP/vA +-----END RSA PRIVATE KEY----- diff --git a/examples/src/main/java/com/vesoft/nebula/examples/GraphClientExample.java b/examples/src/main/java/com/vesoft/nebula/examples/GraphClientExample.java index 6b78cbb80..f9e0c1ce7 100644 --- a/examples/src/main/java/com/vesoft/nebula/examples/GraphClientExample.java +++ b/examples/src/main/java/com/vesoft/nebula/examples/GraphClientExample.java @@ -8,9 +8,12 @@ import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; +import com.vesoft.nebula.ErrorCode; import com.vesoft.nebula.client.graph.NebulaPoolConfig; +import com.vesoft.nebula.client.graph.data.CASignedSSLParam; import com.vesoft.nebula.client.graph.data.HostAddress; import com.vesoft.nebula.client.graph.data.ResultSet; +import com.vesoft.nebula.client.graph.data.SelfSignedSSLParam; import com.vesoft.nebula.client.graph.data.ValueWrapper; import com.vesoft.nebula.client.graph.net.NebulaPool; import com.vesoft.nebula.client.graph.net.Session; @@ -79,7 +82,7 @@ private static void printResult(ResultSet resultSet) throws UnsupportedEncodingE public static void main(String[] args) { NebulaPool pool = new NebulaPool(); - Session session = null; + Session session; try { NebulaPoolConfig nebulaPoolConfig = new NebulaPoolConfig(); nebulaPoolConfig.setMaxConnSize(100); @@ -146,22 +149,62 @@ public static void main(String[] args) { { String queryForJson = "YIELD 1"; String resp = session.executeJson(queryForJson); - JSONObject errors = JSON.parseObject(resp).getJSONArray("result").getJSONObject(0) - .getJSONObject("errors"); - if (!errors.getString("errorCode").equals("0")) { + JSONObject errors = JSON.parseObject(resp).getJSONArray("errors").getJSONObject(0); + if (errors.getInteger("code") != 0) { log.error(String.format("Execute: `%s', failed: %s", - queryForJson, errors.getString("errorMsg"))); + queryForJson, errors.getString("message"))); + System.exit(1); + } + System.out.println(resp); + } + + { + NebulaPoolConfig nebulaSslPoolConfig = new NebulaPoolConfig(); + nebulaSslPoolConfig.setMaxConnSize(100); + nebulaSslPoolConfig.setEnableSsl(true); + nebulaSslPoolConfig.setSslParam(new CASignedSSLParam( + "examples/src/main/resources/ssl/casigned.pem", + "examples/src/main/resources/ssl/casigned.crt", + "examples/src/main/resources/ssl/casigned.key")); + NebulaPool sslPool = new NebulaPool(); + sslPool.init(Arrays.asList(new HostAddress("192.168.8.123", 9669)), + nebulaSslPoolConfig); + String queryForJson = "YIELD 1"; + Session sslSession = sslPool.getSession("root", "nebula", false); + String resp = sslSession.executeJson(queryForJson); + JSONObject errors = JSON.parseObject(resp).getJSONArray("errors").getJSONObject(0); + if (errors.getInteger("code") != ErrorCode.SUCCEEDED.getValue()) { + log.error(String.format("Execute: `%s', failed: %s", + queryForJson, errors.getString("message"))); + System.exit(1); + } + System.out.println(resp); + } + + { + NebulaPoolConfig nebulaSslPoolConfig = new NebulaPoolConfig(); + nebulaSslPoolConfig.setMaxConnSize(100); + nebulaSslPoolConfig.setEnableSsl(true); + nebulaSslPoolConfig.setSslParam(new SelfSignedSSLParam( + "examples/src/main/resources/ssl/selfsigned.pem", + "examples/src/main/resources/ssl/selfsigned.key", + "vesoft")); + NebulaPool sslPool = new NebulaPool(); + sslPool.init(Arrays.asList(new HostAddress("192.168.8.123", 9669)), + nebulaSslPoolConfig); + String queryForJson = "YIELD 1"; + Session sslSession = sslPool.getSession("root", "nebula", false); + String resp = sslSession.executeJson(queryForJson); + JSONObject errors = JSON.parseObject(resp).getJSONArray("errors").getJSONObject(0); + if (errors.getInteger("code") != ErrorCode.SUCCEEDED.getValue()) { + log.error(String.format("Execute: `%s', failed: %s", + queryForJson, errors.getString("message"))); System.exit(1); } System.out.println(resp); } } catch (Exception e) { e.printStackTrace(); - } finally { - if (session != null) { - session.release(); - } - pool.close(); } } } diff --git a/examples/src/main/resources/ssl/casigned.crt b/examples/src/main/resources/ssl/casigned.crt new file mode 100644 index 000000000..fe1add667 --- /dev/null +++ b/examples/src/main/resources/ssl/casigned.crt @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE----- +MIICljCCAX4CCQC9uuUY+ah8qzANBgkqhkiG9w0BAQsFADANMQswCQYDVQQGEwJD +TjAeFw0yMTA5MjkwNzM4MDRaFw0yNDAxMDIwNzM4MDRaMA0xCzAJBgNVBAYTAkNO +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuo7hKpcs+VQKbGRq0fUL ++GcSfPfJ8mARtIeI8WfU0j1vI5KNujI//G2olOGEueDCw4OO0UbdjnsFpgj2awAo +rj4ga2W6adQHK8qHY6q/Rdqv0oDCrcePMtQ8IwbFjNWOXC4bn7GcV7mzOkigdcj8 +UPkSeaqI9XxBRm3OoDX+T8h6cDLrm+ncKB8KKe/QApKH4frV3HYDqGtN49zuRs6F +iurFbXDGVAZEdFEJl38IQJdmE2ASOzEHZbxWKzO/DZr/Z2+L1CuycZIwuITcnddx +b2Byx/opwX4HlyODeUBbyDp+hd+GkasmIcpOlIDw9OXIvrcajKvzLEbqGt2ThsxX +QwIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQAxzxtbYBQ2WgBGrpzOX4TxsuSaigqo +YJ5zbVEHtwbsbBTZ7UJvRc9IyhrOL5Ui4PJI85chh1GpGqOmMoYSaWdddaIroilQ +56bn5haB8ezAMnLXbPuf97UENO0RIkyzt63XPIUkDnwlzOukIq50qgsYEDuiioM/ +wpCqSbMJ4iK/SlSSUWw3cKuAHvFfLv7hkC6AhvT7yfaCNDs29xEQUCD12XlIdFGH +FjMgVMcvcIePQq5ZcmSfVMge9jPjPx/Nj9SVauF5z5pil9qHG4jyXPGThiiJ3CE4 +GU5d/Qfe7OeiYI3LaoVufZ5pZnR9nMnpzqU46w9gY7vgi6bAhNwsCDr3 +-----END CERTIFICATE----- diff --git a/examples/src/main/resources/ssl/casigned.key b/examples/src/main/resources/ssl/casigned.key new file mode 100644 index 000000000..3561e7ab8 --- /dev/null +++ b/examples/src/main/resources/ssl/casigned.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAuo7hKpcs+VQKbGRq0fUL+GcSfPfJ8mARtIeI8WfU0j1vI5KN +ujI//G2olOGEueDCw4OO0UbdjnsFpgj2awAorj4ga2W6adQHK8qHY6q/Rdqv0oDC +rcePMtQ8IwbFjNWOXC4bn7GcV7mzOkigdcj8UPkSeaqI9XxBRm3OoDX+T8h6cDLr +m+ncKB8KKe/QApKH4frV3HYDqGtN49zuRs6FiurFbXDGVAZEdFEJl38IQJdmE2AS +OzEHZbxWKzO/DZr/Z2+L1CuycZIwuITcnddxb2Byx/opwX4HlyODeUBbyDp+hd+G +kasmIcpOlIDw9OXIvrcajKvzLEbqGt2ThsxXQwIDAQABAoIBAH4SEBe4EaxsHp8h +PQ6linFTNis9SDuCsHRPIzv/7tIksfZYE27Ahn0Pndz+ibMTMIrvXJQQT6j5ede6 +NswYT2Vwlnf9Rvw9TJtLQjMYMCoEnsyiNu047oxq4DjLWrTRnGKuxfwlCoI9++Bn +NAhkyh3uM44EsIk0bugpTHj4A+PlbUPe7xdEI/6XpaZrRN9oiejJ4VxZAPgFGiTm +uNF5qg16+0900Pfj5Y/M4vXmn+gq39PO/y0FlTpaoEuYZiZZS3xHGmSVhlt8LIgI +8MdMRaKTfNeNITaqgOWh9pAW4xmK48/KfLgNPQgtDHjMJpgM0BbcBOayOY8Eio0x +Z66G2AECgYEA9vj/8Fm3CKn/ogNOO81y9kIs0iPcbjasMnQ3UXeOdD0z0+7TM86F +Xj3GK/z2ecvY7skWtO5ZUbbxp4aB7omW8Ke9+q8XPzMEmUuAOTzxQkAOxdr++HXP +TILy0hNX2cmiLQT1U60KoZHzPZ5o5hNIQPMt7hN12ERWcIfR/MUZa5UCgYEAwWCP +6Y7Zso1QxQR/qfjuILET3/xU+ZmqSRDvzJPEiGI3oeWNG4L6cKR+XTe0FWZBAmVk +Qq/1qXmdBnf5S7azffoJe2+H/m3kHJSprIiAAWlBN2e+kFlNfBhtkgia5NvsrjRw +al6mf/+weRD1FiPoZY3e1wBKoqro7aI8fE5gwXcCgYEAnEI05OROeyvb8qy2vf2i +JA8AfsBzwkPTNWT0bxX+yqrCdO/hLyEWnubk0IYPiEYibgpK1JUNbDcctErVQJBL +MN5gxBAt3C2yVi8/5HcbijgvYJ3LvnYDf7xGWAYnCkOZ2XQOqC+Oz2UhijYE1rUS +fQ2fXMdxQzERo8c7Y/tstvUCgYBuixy5jwezokUB20h/ieXWmmOaL00EQmutyRjM +AczfigXzbp3zlDRGIEJ8V1OCyClxjTR7SstMTlENWZgRSCfjZAP3pBJBx+AW1oUI +NB+4rsqxOYUeT26T+gLo8DJbkb0C+Mcqh2D22tuu2ZrBRVWceDVjAq+nvbvZ3Fxn +UwbMkQKBgQCxL3aA6ART6laIxT/ZqMhV0ZcaoDJogjF+4I4bhlO4ivWGWJ4RpEDn +ziFb6+M/4pe4vCou9yuAof6WTKM8JG4rok0yxhN3V6QGP49TjtrfkkrEPCtB2LSI +N1+YRSTrS5VDcl8h8JH7fpghRnXHONEyIqasYVqsbxKzNyLV/z2rkw== +-----END RSA PRIVATE KEY----- diff --git a/examples/src/main/resources/ssl/casigned.pem b/examples/src/main/resources/ssl/casigned.pem new file mode 100644 index 000000000..412ba3161 --- /dev/null +++ b/examples/src/main/resources/ssl/casigned.pem @@ -0,0 +1,24 @@ +-----BEGIN CERTIFICATE----- +MIIEGzCCAwOgAwIBAgIUDcmZFpL4PcdCXfLRBK8bR2vb39cwDQYJKoZIhvcNAQEL +BQAwgZwxCzAJBgNVBAYTAkNOMREwDwYDVQQIDAhaaGVqaWFuZzERMA8GA1UEBwwI +SGFuZ3pob3UxFDASBgNVBAoMC1Zlc29mdCBJbmMuMRAwDgYDVQQLDAdzZWN0aW9u +MRYwFAYDVQQDDA1zaHlsb2NrIGh1YW5nMScwJQYJKoZIhvcNAQkBFhhzaHlsb2Nr +Lmh1YW5nQHZlc29mdC5jb20wHhcNMjEwODE5MDkyNDQ3WhcNMjUwODE4MDkyNDQ3 +WjCBnDELMAkGA1UEBhMCQ04xETAPBgNVBAgMCFpoZWppYW5nMREwDwYDVQQHDAhI +YW5nemhvdTEUMBIGA1UECgwLVmVzb2Z0IEluYy4xEDAOBgNVBAsMB3NlY3Rpb24x +FjAUBgNVBAMMDXNoeWxvY2sgaHVhbmcxJzAlBgkqhkiG9w0BCQEWGHNoeWxvY2su +aHVhbmdAdmVzb2Z0LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AMEAgpamCQHl+8JnUHI6/VmJHjDLYJLTliN/CwpFrhMqIVjJ8wG57WYLpXpn91Lz +eHu52LkVzcikybIJ2a+LOTvnhNFdbmTbqDtrb+s6wM/sO+nF6tU2Av4e5zhyKoeR +LL+rHMk3nymohbdN4djySFmOOU5A1O/4b0bZz4Ylu995kUawdiaEo13BzxxOC7Ik +Gge5RyDcm0uLXZqTAPy5Sjv/zpOyj0AqL1CJUH7XBN9OMRhVU0ZX9nHWl1vgLRld +J6XT17Y9QbbHhCNEdAmFE5kEFgCvZc+MungUYABlkvoj86TLmC/FMV6fWdxQssyd +hS+ssfJFLaTDaEFz5a/Tr48CAwEAAaNTMFEwHQYDVR0OBBYEFK0GVrQx+wX1GCHy +e+6fl4X+prmYMB8GA1UdIwQYMBaAFK0GVrQx+wX1GCHye+6fl4X+prmYMA8GA1Ud +EwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAHqP8P+ZUHmngviHLSSN1ln5 +Mx4BCkVeFRUaFx0yFXytV/iLXcG2HpFg3A9rAFoYgCDwi1xpsERnBZ/ShTv/eFOc +IxBY5yggx3/lGi8tAgvUdarhd7mQO67UJ0V4YU3hAkbnZ8grHHXj+4hfgUpY4ok6 +yaed6HXwknBb9W8N1jZI8ginhkhjaeRCHdMiF+fBvNCtmeR1bCml1Uz7ailrpcaT +Mf84+5VYuFEnaRZYWFNsWNCOBlJ/6/b3V10vMXzMmYHqz3xgAq0M3fVTFTzopnAX +DLSzorL/dYVdqEDCQi5XI9YAlgWN4VeGzJI+glkLOCNzHxRNP6Qev+YI+7Uxz6I= +-----END CERTIFICATE----- diff --git a/examples/src/main/resources/ssl/selfsigned.key b/examples/src/main/resources/ssl/selfsigned.key new file mode 100644 index 000000000..6006d0f27 --- /dev/null +++ b/examples/src/main/resources/ssl/selfsigned.key @@ -0,0 +1,30 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,6D12ED8559E80FA3 + +tv9epnwlt4dP6Q5ee0dACOyFA5BTwYTdoMykQRJrKGwfaNeXUXn+sQ/U/oFHp1Wx +O8VZE+z2aHpiFSTw+Eh6MPt86X5yVG3tpeVO6dErvr8Kd+NpuI8zn7rNoOFRh8wD +33EFcQMLQPneDl10O18hooIoi0qwp1pd63hYZPwEhB3eOrM5Mnv9OVJs65bzYfyf +Wku33YWYxeqlDvMCsou8PZnv/M2wYsr7+QoTcNmGKP45igMthMDBzwgF+q0p9ZZU +N11c6ojAs01kfuqFf3vKfHNYe6zsBiNhnUuEy8enXSxD5E7tR/OI8aEzPLdk7fmN +/UsMK2LE0Yd5iS3O1x/1ZjSBxJ+M/UzzCO692GTAiD6Hc13iJOavq/vt1mEPjfCD +neF38Bhb5DfFi+UAHrz6EHMreamGCzP82us2maIs7mSTq7nXDZfbBc7mBDLAUUnT +J6tlrTyc+DQXzkJa6jmbxJhcsWm6XvjIBEzSXVHxEDPLnZICQk3VXODjCXTD75Rg +0WaS78Ven7DW8wn07q3VzWAFDKaet3VI+TVTv7EfIavlfiA6LSshaENdFLeHahNE +s/V/j5K3Pg6+WQcZRgOsfqIwUCSQxY13R6TTdaaCkLay5BggF5iiAO3pkqsJiadf +w843Ak4USBptymJxoZgJyFtQHpQyNiFfsAbs9BaYbg2evvE7/VQhLk0gQ7HgQMeJ +wgxEQqZQKDCCSugSzY1YEGXKnrZYCKyipzyyH936mE15zNwhYp/Pi2020+gmtP3h +CDfcPs1yeLI2/1JuimafbuKsv9xchWa6ASU8p8Q7wTLtUj9ylLKyA4A/75pK0DXG +Hv/q0O+UfhAMD438SoPBle7RSvIsDU1VjUqstlNybBglBZxGIME7/18+Ms7U32wh +4xFkZwxT2nqFgyk37tXMdMz9UBh12/AXR9NU4XY37C3Ao2TDT7/0DvU6KdJhsDpv +rGcaC2zzhko+0CPrLlk52KbqP003JXiWvOSI+FylyPPDB/YGitmndJUuQblf3u/E +l+tGi9MeSBQeWKV6D3AVnO05AZjfTUzSK0vw4DgNh5YPNJvLy31B7kDAS88vyGI1 +t6MBwjW4/tz/nS/p1Go3mSzBhPkIsCrZE+ar7lH8p8JqkLl4fXIMaVKIfyfJdzyS +lkh3K7bOGDPegxxxaWdb+EnC7k+1R3EOU7uJFW61HyrGI3q6Y7kOl5aYSJ5Ge1Uv +PycFWHWVTHq/R7HRE6HIJzGe/PnLIbStXLDFeivjfcYq1YaSaF8Vl+xg+0u3ULOl +P6IuPTph6dlcgttRZVl3ETcF0T+2wfbUwgjf0ZiguCJfR2jLGhPl1KBg0Kd9cTSY +zI3YMMd2G8hApt/QFlm4Ry8CqaJUmDcjDNIJT3M+RldUgfz37NsX05cA5e9+I1AL +2406F/v5U9gWsYx7HuwJtQrDzYYDbl1GD4H+qHFJE5JYhPP4AyWYxJ1NR5dqyvrt ++3r5+xlwZrS76c10RsBWL7th8ZEzRxOZxbtLwbf4bG/tIGfQP2sTnWwA+qym6b2S +sRduqOTP+xwnhOq/ZKn8lfsDfhT8CPnKHBsd09kM9y/UWuxFe0upLydRLE/Wsb9s +-----END RSA PRIVATE KEY----- diff --git a/examples/src/main/resources/ssl/selfsigned.password b/examples/src/main/resources/ssl/selfsigned.password new file mode 100644 index 000000000..143be9ab9 --- /dev/null +++ b/examples/src/main/resources/ssl/selfsigned.password @@ -0,0 +1 @@ +vesoft diff --git a/examples/src/main/resources/ssl/selfsigned.pem b/examples/src/main/resources/ssl/selfsigned.pem new file mode 100644 index 000000000..412ba3161 --- /dev/null +++ b/examples/src/main/resources/ssl/selfsigned.pem @@ -0,0 +1,24 @@ +-----BEGIN CERTIFICATE----- +MIIEGzCCAwOgAwIBAgIUDcmZFpL4PcdCXfLRBK8bR2vb39cwDQYJKoZIhvcNAQEL +BQAwgZwxCzAJBgNVBAYTAkNOMREwDwYDVQQIDAhaaGVqaWFuZzERMA8GA1UEBwwI +SGFuZ3pob3UxFDASBgNVBAoMC1Zlc29mdCBJbmMuMRAwDgYDVQQLDAdzZWN0aW9u +MRYwFAYDVQQDDA1zaHlsb2NrIGh1YW5nMScwJQYJKoZIhvcNAQkBFhhzaHlsb2Nr +Lmh1YW5nQHZlc29mdC5jb20wHhcNMjEwODE5MDkyNDQ3WhcNMjUwODE4MDkyNDQ3 +WjCBnDELMAkGA1UEBhMCQ04xETAPBgNVBAgMCFpoZWppYW5nMREwDwYDVQQHDAhI +YW5nemhvdTEUMBIGA1UECgwLVmVzb2Z0IEluYy4xEDAOBgNVBAsMB3NlY3Rpb24x +FjAUBgNVBAMMDXNoeWxvY2sgaHVhbmcxJzAlBgkqhkiG9w0BCQEWGHNoeWxvY2su +aHVhbmdAdmVzb2Z0LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AMEAgpamCQHl+8JnUHI6/VmJHjDLYJLTliN/CwpFrhMqIVjJ8wG57WYLpXpn91Lz +eHu52LkVzcikybIJ2a+LOTvnhNFdbmTbqDtrb+s6wM/sO+nF6tU2Av4e5zhyKoeR +LL+rHMk3nymohbdN4djySFmOOU5A1O/4b0bZz4Ylu995kUawdiaEo13BzxxOC7Ik +Gge5RyDcm0uLXZqTAPy5Sjv/zpOyj0AqL1CJUH7XBN9OMRhVU0ZX9nHWl1vgLRld +J6XT17Y9QbbHhCNEdAmFE5kEFgCvZc+MungUYABlkvoj86TLmC/FMV6fWdxQssyd +hS+ssfJFLaTDaEFz5a/Tr48CAwEAAaNTMFEwHQYDVR0OBBYEFK0GVrQx+wX1GCHy +e+6fl4X+prmYMB8GA1UdIwQYMBaAFK0GVrQx+wX1GCHye+6fl4X+prmYMA8GA1Ud +EwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAHqP8P+ZUHmngviHLSSN1ln5 +Mx4BCkVeFRUaFx0yFXytV/iLXcG2HpFg3A9rAFoYgCDwi1xpsERnBZ/ShTv/eFOc +IxBY5yggx3/lGi8tAgvUdarhd7mQO67UJ0V4YU3hAkbnZ8grHHXj+4hfgUpY4ok6 +yaed6HXwknBb9W8N1jZI8ginhkhjaeRCHdMiF+fBvNCtmeR1bCml1Uz7ailrpcaT +Mf84+5VYuFEnaRZYWFNsWNCOBlJ/6/b3V10vMXzMmYHqz3xgAq0M3fVTFTzopnAX +DLSzorL/dYVdqEDCQi5XI9YAlgWN4VeGzJI+glkLOCNzHxRNP6Qev+YI+7Uxz6I= +-----END CERTIFICATE-----