Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,14 @@
import io.grpc.Metadata;
import io.grpc.MethodDescriptor;
import io.grpc.Status;
import io.grpc.netty.shaded.io.grpc.netty.GrpcSslContexts;
import io.grpc.netty.shaded.io.grpc.netty.NettyChannelBuilder;
import io.grpc.netty.shaded.io.netty.handler.ssl.SslContext;
import io.grpc.netty.shaded.io.netty.handler.ssl.SslContextBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
Expand Down Expand Up @@ -404,6 +406,92 @@ public Builder useTransportSecurity(SslContext sslContext) {
return this;
}

/**
Comment thread
abuijze marked this conversation as resolved.
* Configures the use of Transport Layer Security (TLS), verifying the server's certificate against the
* certificates in the given {@code trustedCertificates} file. Use this when Axon Server (or a proxy in front
* of it) uses a certificate that is not signed by a Certificate Authority trusted by the JVM by default.
* <p>
* The given file must be in PEM format and is read once, when the factory is built.
Comment thread
abuijze marked this conversation as resolved.
Outdated
* <p>
* Defaults to not using TLS.
*
* @param trustedCertificates A PEM file containing the CA certificates to verify the server's certificate
* against
* @return this builder for further configuration
* @see #useMutualTransportSecurity(File, File, File)
*/
public Builder useTransportSecurity(File trustedCertificates) {
return useTransportSecurity(buildSslContext(null, null, trustedCertificates));
}

/**
* Configures the use of mutual Transport Layer Security (mTLS), presenting the given client certificate to
* the server during the TLS handshake. The server's certificate is verified using the JVM's default trusted
* Certificate Authorities.
* <p>
* The given files must be in PEM format, with the private key in PKCS#8 format. They are read once, when the
* factory is built.
Comment thread
abuijze marked this conversation as resolved.
Outdated
* <p>
* Defaults to not using TLS.
*
* @param clientCertificateChain A PEM file containing the client's certificate chain
* @param clientPrivateKey A PEM file containing the client's PKCS#8 private key
* @return this builder for further configuration
* @see #useMutualTransportSecurity(File, File, File)
*/
public Builder useMutualTransportSecurity(File clientCertificateChain, File clientPrivateKey) {
return useMutualTransportSecurity(clientCertificateChain, clientPrivateKey, null);
}

/**
* Configures the use of mutual Transport Layer Security (mTLS), presenting the given client certificate to
* the server during the TLS handshake. The server's certificate is verified against the certificates in the
* given {@code trustedCertificates} file, or against the JVM's default trusted Certificate Authorities when
* {@code trustedCertificates} is {@code null}.
* <p>
* The given files must be in PEM format, with the private key in PKCS#8 format. They are read once, when the
* factory is built.
Comment thread
abuijze marked this conversation as resolved.
Outdated
* <p>
* Defaults to not using TLS.
*
* @param clientCertificateChain A PEM file containing the client's certificate chain
* @param clientPrivateKey A PEM file containing the client's PKCS#8 private key
* @param trustedCertificates A PEM file containing the CA certificates to verify the server's certificate
* against, or {@code null} to use the JVM's default trusted Certificate
* Authorities
* @return this builder for further configuration
*/
public Builder useMutualTransportSecurity(File clientCertificateChain,
File clientPrivateKey,
File trustedCertificates) {
if (clientCertificateChain == null) {
Comment thread
abuijze marked this conversation as resolved.
Outdated
throw new IllegalArgumentException("clientCertificateChain may not be null");
}
if (clientPrivateKey == null) {
throw new IllegalArgumentException("clientPrivateKey may not be null");
}
return useTransportSecurity(buildSslContext(clientCertificateChain, clientPrivateKey,
trustedCertificates));
}

private static SslContext buildSslContext(File clientCertificateChain,
File clientPrivateKey,
File trustedCertificates) {
SslContextBuilder sslContextBuilder = GrpcSslContexts.forClient();
if (clientCertificateChain != null) {
sslContextBuilder.keyManager(clientCertificateChain, clientPrivateKey);
}
if (trustedCertificates != null) {
sslContextBuilder.trustManager(trustedCertificates);
}
try {
return sslContextBuilder.build();
} catch (Exception e) {
throw new IllegalArgumentException("Could not create an SSL context from the given certificate files",
e);
}
}

/**
* Indicates whether the connector should always reconnect via the Routing Servers. When {@code true} (default),
* the connector will contact the Routing Servers for a new destination each time a connection is dropped. When
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
package io.axoniq.axonserver.connector;
Comment thread
abuijze marked this conversation as resolved.

import io.axoniq.axonserver.connector.impl.ServerAddress;
import io.axoniq.axonserver.grpc.control.ClientIdentification;
import io.axoniq.axonserver.grpc.control.PlatformInboundInstruction;
import io.axoniq.axonserver.grpc.control.PlatformInfo;
import io.axoniq.axonserver.grpc.control.PlatformOutboundInstruction;
import io.axoniq.axonserver.grpc.control.PlatformServiceGrpc;
import io.grpc.Server;
import io.grpc.TlsServerCredentials;
import io.grpc.netty.shaded.io.grpc.netty.NettyServerBuilder;
import io.grpc.stub.StreamObserver;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;

import java.io.File;
import java.io.IOException;
import java.net.ServerSocket;
import java.util.concurrent.TimeUnit;
import java.util.function.UnaryOperator;

import static io.axoniq.axonserver.connector.testutils.AssertUtils.assertWithin;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;

/**
* Test class validating the (mutual) TLS configuration options of the {@link AxonServerConnectionFactory}, against a
* stub PlatformService endpoint secured with TLS.
*
* @author Allard Buijze
*/
class MutualTlsConnectionTest {

private Server server;
private int serverPort;
private AxonServerConnectionFactory connectionFactory;

@AfterEach
void tearDown() {
if (connectionFactory != null) {
connectionFactory.shutdown();
}
if (server != null) {
server.shutdownNow();
}
}

@Test
void connectsWithClientCertificateWhenServerRequiresClientAuth() throws Exception {
startServer(TlsServerCredentials.ClientAuth.REQUIRE);

AxonServerConnection connection = connect(
factory -> factory.useMutualTransportSecurity(tlsFile("client.crt"),
tlsFile("client.key"),
tlsFile("ca.crt"))
);

assertWithin(10, TimeUnit.SECONDS, () -> assertTrue(connection.isConnected()));
}

@Test
void failsToConnectWithoutClientCertificateWhenServerRequiresClientAuth() throws Exception {
startServer(TlsServerCredentials.ClientAuth.REQUIRE);

AxonServerConnection connection = connect(
factory -> factory.useTransportSecurity(tlsFile("ca.crt"))
);

assertWithin(10, TimeUnit.SECONDS, () -> assertTrue(connection.isConnectionFailed()));
assertFalse(connection.isConnected());
}

@Test
void connectsWithTrustedCertificatesOnlyWhenServerDoesNotRequireClientAuth() throws Exception {
startServer(TlsServerCredentials.ClientAuth.NONE);

AxonServerConnection connection = connect(
factory -> factory.useTransportSecurity(tlsFile("ca.crt"))
);

assertWithin(10, TimeUnit.SECONDS, () -> assertTrue(connection.isConnected()));
}

@Test
void mutualTransportSecurityRejectsMissingCertificateOrKey() {
AxonServerConnectionFactory.Builder builder = AxonServerConnectionFactory.forClient("mtls-test");

assertThrows(IllegalArgumentException.class,

Check warning on line 89 in src/test/java/io/axoniq/axonserver/connector/MutualTlsConnectionTest.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Refactor the code of the lambda to have only one invocation possibly throwing a runtime exception.

See more on https://sonarcloud.io/project/issues?id=AxonIQ_axonserver-connector-java&issues=AZ9gQuVxxi9ITgheSRqJ&open=AZ9gQuVxxi9ITgheSRqJ&pullRequest=501
() -> builder.useMutualTransportSecurity(null, tlsFile("client.key")));
assertThrows(IllegalArgumentException.class,

Check warning on line 91 in src/test/java/io/axoniq/axonserver/connector/MutualTlsConnectionTest.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Refactor the code of the lambda to have only one invocation possibly throwing a runtime exception.

See more on https://sonarcloud.io/project/issues?id=AxonIQ_axonserver-connector-java&issues=AZ9gQuVxxi9ITgheSRqK&open=AZ9gQuVxxi9ITgheSRqK&pullRequest=501
() -> builder.useMutualTransportSecurity(tlsFile("client.crt"), null));
assertThrows(IllegalArgumentException.class,

Check warning on line 93 in src/test/java/io/axoniq/axonserver/connector/MutualTlsConnectionTest.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Refactor the code of the lambda to have only one invocation possibly throwing a runtime exception.

See more on https://sonarcloud.io/project/issues?id=AxonIQ_axonserver-connector-java&issues=AZ9gQuVxxi9ITgheSRqL&open=AZ9gQuVxxi9ITgheSRqL&pullRequest=501
() -> builder.useMutualTransportSecurity(new File("does-not-exist.crt"),
new File("does-not-exist.key")));
}

private void startServer(TlsServerCredentials.ClientAuth clientAuth) throws Exception {
TlsServerCredentials.Builder credentials = TlsServerCredentials.newBuilder()
.keyManager(tlsFile("server.crt"),
tlsFile("server.key"))
.clientAuth(clientAuth);
if (clientAuth != TlsServerCredentials.ClientAuth.NONE) {
credentials.trustManager(tlsFile("ca.crt"));
}
server = NettyServerBuilder.forPort(freePort(), credentials.build())
.addService(new StubPlatformService())
.build()
.start();
}

private AxonServerConnection connect(UnaryOperator<AxonServerConnectionFactory.Builder> tlsConfig) {
connectionFactory = tlsConfig.apply(AxonServerConnectionFactory.forClient("mtls-test")
.routingServers(new ServerAddress("localhost",
serverPort)))
.build();
return connectionFactory.connect("default");
}

private int freePort() throws IOException {
try (ServerSocket socket = new ServerSocket(0)) {
serverPort = socket.getLocalPort();
return serverPort;
}
}

private File tlsFile(String name) {
try {
return new File(getClass().getResource("/tls/" + name).toURI());
} catch (Exception e) {
throw new IllegalStateException("Could not locate test resource /tls/" + name, e);
}
}

private static class StubPlatformService extends PlatformServiceGrpc.PlatformServiceImplBase {

@Override
public void getPlatformServer(ClientIdentification request, StreamObserver<PlatformInfo> responseObserver) {
responseObserver.onNext(PlatformInfo.newBuilder().setSameConnection(true).build());
responseObserver.onCompleted();
}

@Override
public StreamObserver<PlatformInboundInstruction> openStream(
StreamObserver<PlatformOutboundInstruction> responseObserver) {
return new StreamObserver<PlatformInboundInstruction>() {
@Override
public void onNext(PlatformInboundInstruction value) {
// no-op: the stub only needs to keep the stream open
}

@Override
public void onError(Throwable t) {
// no-op
}

@Override
public void onCompleted() {
responseObserver.onCompleted();
}
};
}
}
}
19 changes: 19 additions & 0 deletions src/test/resources/tls/ca.crt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
-----BEGIN CERTIFICATE-----
MIIDFzCCAf+gAwIBAgIULHat2vB2ieUzjtCWRdRkIXXWe00wDQYJKoZIhvcNAQEL
BQAwGjEYMBYGA1UEAwwPVGVzdCBUcnVzdGVkIENBMCAXDTI2MDcxNDA4MzU1M1oY
DzIxMjYwNjIwMDgzNTUzWjAaMRgwFgYDVQQDDA9UZXN0IFRydXN0ZWQgQ0EwggEi
MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCo3ODm78QSpgh4Sy5S/USAbMqT
M6XaNe41+jGwoHrBaFaeCEXADtSSE8O/oFHrrbWnbFxpdMSrXHVCicnl2kPJxQzV
ezo5NuPDEdjKSfjA3Y3uCo71EBP3iUmUZdk9um2gX+t99dIIIq+A0stZs10IWdpr
NTPPelO5qtqO2m/3/aUjKDj9f47UfTaxi6aNseAlrll7ccNI2Csz9x+2zpftsq5y
kCI/AD2ZOkX+1dqi44sVGU6+x/QsFQB3QVRKsdgXIBp8CVzpt4PkzPzlKNq0WiEt
cAcv5kxkDe/e4ZBBnf5l+V4TxHF/z8LPwp8Mr47OpYtGCma25q+jPtK+quUxAgMB
AAGjUzBRMB0GA1UdDgQWBBQHS4hLKOqr4vBgRc8WoyJSVKLiBDAfBgNVHSMEGDAW
gBQHS4hLKOqr4vBgRc8WoyJSVKLiBDAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3
DQEBCwUAA4IBAQBTkMW0nxZM5+12JyzEbXdLW+Az9LGc9YdlLz/0YAaGYXremQXy
pVun2qx730vwkS8nTvat0WPPXfIR8QzO6WTf/BNB4drWN9znqYW58KY78tnSUjNb
uf707QeHCbICH1z+tErQf48JU6HeOLPvXvyvxc4RZAm4kavWbzsKDr8IJfMSh9RC
Aiv0zE/RUHL1wmd6w6UQqmzbzjqi3mv+h0GdRPrTlpus7GngTN8R5Bu0s05ONtSy
fqMTqdQthxdt1jWlnacPrn/LZ/ldAamqecazgBXuKNzqfjfvAOzCgtVl4KWmqjKT
xwyCT49G9g5taftkgR+9NTFKf/UWYbUUY6YQ
-----END CERTIFICATE-----
28 changes: 28 additions & 0 deletions src/test/resources/tls/ca.key
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCo3ODm78QSpgh4
Sy5S/USAbMqTM6XaNe41+jGwoHrBaFaeCEXADtSSE8O/oFHrrbWnbFxpdMSrXHVC
icnl2kPJxQzVezo5NuPDEdjKSfjA3Y3uCo71EBP3iUmUZdk9um2gX+t99dIIIq+A
0stZs10IWdprNTPPelO5qtqO2m/3/aUjKDj9f47UfTaxi6aNseAlrll7ccNI2Csz
9x+2zpftsq5ykCI/AD2ZOkX+1dqi44sVGU6+x/QsFQB3QVRKsdgXIBp8CVzpt4Pk
zPzlKNq0WiEtcAcv5kxkDe/e4ZBBnf5l+V4TxHF/z8LPwp8Mr47OpYtGCma25q+j
PtK+quUxAgMBAAECggEAHuunMRJpbGLDvUdC+cZPo1aId5DnB0CF2JNyQt337G9v
IOvx3bu5d/AvkWjJZ2b9EuW4PEU5+Ajrnd3+Pt0LOaif831niW+AIEml0VDfQG2x
XgvH5p7lkReuBgLqVy/KgCngRMXdCklTqrquqsO5vtw5LxVkYdML/r0G3U6pXxbi
V0aHp/8FCZEUbIte0JeZgIUjnCHg1O80JDCMHtYhyIy3VOauTbeAVfcYGBPBOVpo
YwxOhZpBzaoDYZze0e9+6Jtcu01uId85HvAULRoMDoUmNQOBD2I96ke3sRhB1Ac+
6quwq3K+dzjla9zqjpLnP8W6AUyhAwQhQxICK05fOwKBgQDWLTNQ67w04G9RyS7A
2JZQw2KnES0sswvL1HcjNkZ8PiFG5GWAN9YBNE7XiDj9EIOJdniEumav/9BCC4Td
JmSH2/s+Xp8fxIZonz27BIpHJaxWzsY8PXrnZx3NsAKZptX2bJq13hb57UDv7aZl
pgziYNMF4HEw09yHUTgDOpuJuwKBgQDJ1mtd9mv7z7j9wd90cZIqnhvd5/rzC0EH
BC6xQ9idPpofELBXHw0CZFsYTEVlZKVoBC1TZmWGLVxDCr4sZaWvtn45kZ66jWHv
yDdwnOqJsIzm1Z5+43WCpnxHEiXdAqBKPAVMglviCx8EcZMMMptA7lnQ8faN/J0/
20NbjoBYAwKBgDj9uBz9TYyIeDa8IQvB1mXRSAwKvwmY7zei5rzg8WqYIcS6e+Pd
d73ETIJ/xiJY5ZeLhdBTxYVpveIFLKqoT7HzMGzNQuxyIA3w6b09HQqHlM9YoFlh
RrYSs1SLVHXMdjznc1eXrGd+4Xu2skN0JxOKDj0PFy+WAKWlUBFT5BWHAoGABL+8
yvsvUz9x9NaI8W5yp/oMYc5Bg1Jydz3L83PLNvfwHGcCHyql3baKximVQGt70NS4
VEwGe3+5ugIYs2a43UeH9MbOW0lUUpX9Z/LpOdAjoJLKJeYoL6jHJ8zvgyG6r8R1
w3UVwF3OnwYlFZZjPMXe6yGmUXTuJkB8dz0FHA0CgYEAzzbTyQpTAX9aMb1/Ij0W
1hwc2eafCXmy4e5VkKf5YcVKDZMcSvkicC4VAlUxWOSQ/ZwXmv4mTamnlbXS2oW2
Rdan6oD2FAUG5aI8LXyG1bfuJcp3dWjgfrfJB0cS134jXk+XKMdNvsi4WsV60hJa
Ksmu2ROmTUXC2meV+93V3Eg=
-----END PRIVATE KEY-----
17 changes: 17 additions & 0 deletions src/test/resources/tls/client.crt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
-----BEGIN CERTIFICATE-----
MIICuTCCAaECFGQlQgq3PBbtJnTpsXCsSIiYtvhYMA0GCSqGSIb3DQEBCwUAMBox
GDAWBgNVBAMMD1Rlc3QgVHJ1c3RlZCBDQTAgFw0yNjA3MTQwODM1NTRaGA8yMTI2
MDYyMDA4MzU1NFowFjEUMBIGA1UEAwwLdGVzdC1jbGllbnQwggEiMA0GCSqGSIb3
DQEBAQUAA4IBDwAwggEKAoIBAQCVBtGyAy86lzCzmhqyZlmECQJZVHgPlT2Y4cRG
MUupbFCH1QOjqsV7nuMoW7EQYPU3Xs9aBrabij3BsbRCfxcZHNGVxjEAYdjPyqi1
uMGcLvNrbj4XM6CD/kV4QZpj6wHX2yCO1onTvGK6f40MfoTbuFAqPS6RngO6fmH9
ODuXawTH6o4bpYMKwUeK9HFpOtJvFQW+MePTmU4J7ZPhPs/8WZW8DmLV5TVZzZ6Y
dpYHLr15UHN7E6O4BRoHF8oLXPOoNBTq+xx1UFFY3XrJP4Xr9VVQQVQnO3V4Kv3I
mAPTrS/h9tn6QFQbxkYT8uUt/m6D5zgqvQCjSMWc/A4P2QXVAgMBAAEwDQYJKoZI
hvcNAQELBQADggEBAH9HhGR+SDDHknn9kkV4BEl4uWZIHW18ppfEfzBPllhA55Y+
ZqboPvuzoRbuYntGFL/P9Ws3svmoIDUfVQPDMmjm4Kujnjb1jDyY5bmDdQs2RjDH
HJnXPqxA0+mlNXrpbsstqqZdFa1WxeT+lqTgALrNT9teBnA4cBczoQFGHwH+ltRs
ZYaycFa4blgclOL75oScbiQigB1fWPY7QGMnEwQLGN2I6HhKYyy/dFua6wTLGIeG
3ifbYec4T/lwLOeT+kVQz8iDTN3fn75YnUortUdkZ0j5mVFxsx5oOKXj7RYdF0GA
I223lYDUCxGRnV+euTCPYTWFYOsERXIUt3iM+sk=
-----END CERTIFICATE-----
28 changes: 28 additions & 0 deletions src/test/resources/tls/client.key
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCVBtGyAy86lzCz
mhqyZlmECQJZVHgPlT2Y4cRGMUupbFCH1QOjqsV7nuMoW7EQYPU3Xs9aBrabij3B
sbRCfxcZHNGVxjEAYdjPyqi1uMGcLvNrbj4XM6CD/kV4QZpj6wHX2yCO1onTvGK6
f40MfoTbuFAqPS6RngO6fmH9ODuXawTH6o4bpYMKwUeK9HFpOtJvFQW+MePTmU4J
7ZPhPs/8WZW8DmLV5TVZzZ6YdpYHLr15UHN7E6O4BRoHF8oLXPOoNBTq+xx1UFFY
3XrJP4Xr9VVQQVQnO3V4Kv3ImAPTrS/h9tn6QFQbxkYT8uUt/m6D5zgqvQCjSMWc
/A4P2QXVAgMBAAECggEAAWnSF84PBtwTuDeKlmB0a8iASloYrs2NMVokyyVt1wXB
6F17qxpakWu5ZX+j7BvLTF+v3j+PJrL9MNoI85Kyfju6fIeBNyrczEqBZpw06kPW
VBGOPhiW5pTFBZkaFOWcu+my9mY8/BilJA+QUvFcb7Wg1wG2o4CcGIrymxAk0PCm
1WeKctnS9U8W6HWSxn7cWudP2kjSBw8QjAUCocMdOUAvixuXM7EGLgdjHJ5cUPQA
8IDiicYuZrYhYx0s3iHNL8M2dR5jW1ElphOL3nmhm78Ix406JC/s1OhFerFVLW6V
nk5NbWhklthN8NsFEBUdvz+0k8Z8T0AUUJH7Ib3AIQKBgQDN//00KBpXfboAecC3
Ah91RuJSONvXWrGTcCEEODpnO1bkqLui6v5XamTRtlE7Iu5C2USckTLBlF6mzV7J
yEZyMJkrqm4i/AtyFkQ+4/IO9Matq/lKOMxn/1pChhMl2cMg8HQ+t5I+Ef4BHLkb
nCJWaZLgEg6IMA7iUZdjCgYU4QKBgQC5MryLB40ks0BQqhObuyKCd4SUQtmob85V
ovCO7iGYphH0O/DIFH2FgTSj8NcwDRS4cchmDnclHOctNZQFt2ShZvc5blUNXXdM
r3AsDOItrpJrrcBz8RVmi/yfRGif9m3WUJUlz33BAwz/EREBHCepKJRMHmwAFfuG
JkO86NXbdQKBgF92yT15dDOldSQxSCjHWBK+RbW62c5kHjToWrSc5hve+PbAZywp
4LJcANrataxFFMtv6obwFuh0vKRqOgoiwNq8QM9mjOGzkg5N2VSXyB48OzJSpxVJ
Wxi60nZPseHxl6bVJ9nEsoYHSoHzcKkl4xfOlx014Pwl4U/qZdCk3YqhAoGAbjg/
9g58dgcok9lk6h4pn7Q593MBzzkbd+QNf0NCQ3My5ER4PNvVCIupJJjFuRdP6aXu
Oq8JQdE91K46dlx7S4PYRxnfDKE/yyfufoj8Y2uuQN+b1mT485sEslUoX2tuW0qC
OYqPsTt7lKI3mI2FHSvFdrf0Vui+VUyYq+l2vbECgYEAxVPi1MdZTQqxqspKC+io
rD0E9klYnlTvtx1D8Of3v5ZgUfDndbwMSnm+eB0eDZToJol2xibT9Z9JVVXGo4cq
9yjQknrMOoe1uz4q2QB5d+t9+WxuXPSIy3hpx6YkR0ZBiOtmMu1IpuVC41i4gHJp
1M4ZQJG7uuAmcvTVpbGvxCQ=
-----END PRIVATE KEY-----
19 changes: 19 additions & 0 deletions src/test/resources/tls/server.crt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
-----BEGIN CERTIFICATE-----
MIIDHDCCAgSgAwIBAgIUZCVCCrc8Fu0mdOmxcKxIiJi2+FcwDQYJKoZIhvcNAQEL
BQAwGjEYMBYGA1UEAwwPVGVzdCBUcnVzdGVkIENBMCAXDTI2MDcxNDA4MzU1M1oY
DzIxMjYwNjIwMDgzNTUzWjAUMRIwEAYDVQQDDAlsb2NhbGhvc3QwggEiMA0GCSqG
SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDBXA8g/LiGaI7WfMOAYW7q1t801MfoCe30
pegYXVYFyeoUyVbuCo4sffa6/y56bw4aP152eCJjPIpcI5263HmQMrGFGhnpHOJo
WSpL0lVKCKCAoiQcPKSkTJQjzFZEWxSJJRgFy+766a7k4OBw9NXwnnaqzlv/A2SR
e8u0dZAgnVs1xmtcN5qfLm7eqFO2raXx8yPwrJruvcKUDktfx8YYNVQCylcZ7z1/
Asv+W2oku423QE0x6V0u/k9iOyJAjXXQgFhE3PHUT2m+8hYsfoAfBV/3y+4SW/N1
vmmxNo8hcCZ0U7g8MW+nSweOpLhVINk5Xn3kLnuh4KEKB1jch9vnAgMBAAGjXjBc
MBoGA1UdEQQTMBGCCWxvY2FsaG9zdIcEfwAAATAdBgNVHQ4EFgQUFD7KcrbNUPRK
pHQBBqChuRfX4FgwHwYDVR0jBBgwFoAUB0uISyjqq+LwYEXPFqMiUlSi4gQwDQYJ
KoZIhvcNAQELBQADggEBAFA1d2kLDTuPxPfHsd7EtY3bExysFqm1Wmjw5KhjEGdf
xq3cX6m3E/txRg1gcI0N4ZSIw+r1AyOD2+z781oeleVlG8RaZ68H5HL6XwCiVZtf
r/I/jCRjx4wWb1tQtH487MfYypWFq/bwMZy5wlgQ565dLAebN/J1EYeUXNFBLJDa
YlArnK8XpEqxwOYrzZeKoKSvPAkMBxxESSfa0VC9b7/2wVPN4fUXB7KV+gfIDXWQ
sNg4V3EXMLb1UnYnEV9M8En0mGDpeJlUndOxxFMDcQma9i+SECieUAAGt7q7kqxx
l05bNVBJPMr7LnbDMvbLFtpPwIORnYKeNtwBLUrxHvw=
-----END CERTIFICATE-----
Loading