Add smoke tests to verify Couchbase SSL connections

See gh-34811
pull/35333/head
Scott Frederick 2 years ago
parent d4107a8185
commit 1143396531

@ -120,8 +120,7 @@ public class CouchbaseAutoConfiguration {
builder.ioConfig((config) -> config.maxHttpConnections(io.getMaxEndpoints())
.numKvConnections(io.getMinEndpoints())
.idleHttpConnectionTimeout(io.getIdleHttpConnectionTimeout()));
if ((connectionDetails instanceof PropertiesCouchbaseConnectionDetails)
&& this.properties.getEnv().getSsl().getEnabled()) {
if (this.properties.getEnv().getSsl().getEnabled()) {
configureSsl(builder, sslBundles);
}
return builder;

@ -32,7 +32,7 @@ public final class DockerImageNames {
private static final String CASSANDRA_VERSION = "3.11.10";
private static final String COUCHBASE_VERSION = "6.5.1";
private static final String COUCHBASE_VERSION = "7.1.4";
private static final String ELASTICSEARCH_VERSION = "7.17.5";

@ -0,0 +1,25 @@
plugins {
id "java"
id "org.springframework.boot.conventions"
}
description = "Spring Boot Data Couchbase smoke test"
dependencies {
implementation(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-data-couchbase"))
implementation(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-data-couchbase-reactive"))
testImplementation(project(":spring-boot-project:spring-boot-test"))
testImplementation(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-test"))
testImplementation(project(":spring-boot-project:spring-boot-tools:spring-boot-test-support"))
testImplementation(project(":spring-boot-project:spring-boot-testcontainers"))
testImplementation("com.squareup.okhttp3:okhttp")
testImplementation("io.projectreactor:reactor-core")
testImplementation("io.projectreactor:reactor-test")
testImplementation("org.junit.jupiter:junit-jupiter")
testImplementation("org.junit.platform:junit-platform-engine")
testImplementation("org.junit.platform:junit-platform-launcher")
testImplementation("org.testcontainers:junit-jupiter")
testImplementation("org.testcontainers:testcontainers")
testImplementation("org.testcontainers:couchbase")
}

@ -0,0 +1,24 @@
/*
* Copyright 2012-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package smoketest.data.couchbase;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SampleCouchbaseApplication {
}

@ -0,0 +1,49 @@
/*
* Copyright 2012-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package smoketest.data.couchbase;
import org.springframework.data.annotation.Id;
import org.springframework.data.couchbase.core.mapping.Document;
import org.springframework.data.couchbase.core.mapping.id.GeneratedValue;
import org.springframework.data.couchbase.core.mapping.id.GenerationStrategy;
@Document
public class SampleDocument {
@Id
@GeneratedValue(strategy = GenerationStrategy.UNIQUE)
private String id;
private String text;
public String getId() {
return this.id;
}
public void setId(String id) {
this.id = id;
}
public String getText() {
return this.text;
}
public void setText(String text) {
this.text = text;
}
}

@ -0,0 +1,23 @@
/*
* Copyright 2012-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package smoketest.data.couchbase;
import org.springframework.data.couchbase.repository.ReactiveCouchbaseRepository;
interface SampleReactiveRepository extends ReactiveCouchbaseRepository<SampleDocument, String> {
}

@ -0,0 +1,23 @@
/*
* Copyright 2012-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package smoketest.data.couchbase;
import org.springframework.data.couchbase.repository.CouchbaseRepository;
interface SampleRepository extends CouchbaseRepository<SampleDocument, String> {
}

@ -0,0 +1,35 @@
/*
* Copyright 2012-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package smoketest.data.couchbase;
import org.springframework.data.couchbase.core.CouchbaseTemplate;
import org.springframework.stereotype.Service;
@Service
public class SampleService {
private final CouchbaseTemplate couchbaseTemplate;
public SampleService(CouchbaseTemplate couchbaseTemplate) {
this.couchbaseTemplate = couchbaseTemplate;
}
public SampleDocument findById(String id) {
return this.couchbaseTemplate.findById(SampleDocument.class).one(id);
}
}

@ -0,0 +1,69 @@
/*
* Copyright 2012-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package smoketest.data.couchbase;
import java.time.Duration;
import org.junit.jupiter.api.Test;
import org.testcontainers.couchbase.BucketDefinition;
import org.testcontainers.couchbase.CouchbaseContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.springframework.data.couchbase.core.ReactiveCouchbaseTemplate;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Smoke tests for Couchbase using reactive repositories with SSL.
*
* @author Scott Frederick
*/
@Testcontainers(disabledWithoutDocker = true)
@SpringBootTest(properties = { "spring.couchbase.env.ssl.bundle=client", "spring.data.couchbase.bucket-name=cbbucket",
"spring.ssl.bundle.pem.client.keystore.certificate=classpath:ssl/test-client.crt",
"spring.ssl.bundle.pem.client.keystore.private-key=classpath:ssl/test-client.key",
"spring.ssl.bundle.pem.client.truststore.certificate=classpath:ssl/test-ca.crt" })
class SampleCouchbaseApplicationReactiveSslTests {
private static final String BUCKET_NAME = "cbbucket";
@Container
@ServiceConnection
static final CouchbaseContainer couchbase = new SecureCouchbaseContainer()
.withBucket(new BucketDefinition(BUCKET_NAME));
@Autowired
private ReactiveCouchbaseTemplate couchbaseTemplate;
@Autowired
private SampleReactiveRepository repository;
@Test
void testRepository() {
SampleDocument document = new SampleDocument();
document.setText("Look, new @DataCouchbaseTest!");
document = this.repository.save(document).block(Duration.ofSeconds(30));
assertThat(document.getId()).isNotNull();
assertThat(this.couchbaseTemplate.getBucketName()).isEqualTo(BUCKET_NAME);
this.repository.deleteAll();
}
}

@ -0,0 +1,68 @@
/*
* Copyright 2012-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package smoketest.data.couchbase;
import org.junit.jupiter.api.Test;
import org.testcontainers.couchbase.BucketDefinition;
import org.testcontainers.couchbase.CouchbaseContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.springframework.data.couchbase.core.CouchbaseTemplate;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Smoke tests for Couchbase with SSL.
*
* @author Scott Frederick
*/
@Testcontainers(disabledWithoutDocker = true)
@SpringBootTest(properties = { "spring.couchbase.env.ssl.bundle=client", "spring.couchbase.env.timeouts.connect=2m",
"spring.data.couchbase.bucket-name=cbbucket",
"spring.ssl.bundle.pem.client.keystore.certificate=classpath:ssl/test-client.crt",
"spring.ssl.bundle.pem.client.keystore.private-key=classpath:ssl/test-client.key",
"spring.ssl.bundle.pem.client.truststore.certificate=classpath:ssl/test-ca.crt" })
class SampleCouchbaseApplicationSslTests {
private static final String BUCKET_NAME = "cbbucket";
@Container
@ServiceConnection
static final CouchbaseContainer couchbase = new SecureCouchbaseContainer()
.withBucket(new BucketDefinition(BUCKET_NAME));
@Autowired
private CouchbaseTemplate couchbaseTemplate;
@Autowired
private SampleRepository repository;
@Test
void testRepository() {
SampleDocument document = new SampleDocument();
document.setText("Look, new @DataCouchbaseTest!");
document = this.repository.save(document);
assertThat(document.getId()).isNotNull();
assertThat(this.couchbaseTemplate.getBucketName()).isEqualTo(BUCKET_NAME);
this.repository.deleteAll();
}
}

@ -0,0 +1,88 @@
/*
* Copyright 2012-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package smoketest.data.couchbase;
import java.time.Duration;
import com.github.dockerjava.api.command.InspectContainerResponse;
import okhttp3.Credentials;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import org.testcontainers.couchbase.CouchbaseContainer;
import org.testcontainers.utility.MountableFile;
import org.springframework.boot.testsupport.testcontainers.DockerImageNames;
/**
* A {@link CouchbaseContainer} for Couchbase with SSL configuration.
*
* @author Scott Frederick
*/
public class SecureCouchbaseContainer extends CouchbaseContainer {
private static final int MANAGEMENT_PORT = 8091;
private static final int KV_SSL_PORT = 11207;
private static final String ADMIN_USER = "Administrator";
private static final String ADMIN_PASSWORD = "password";
public SecureCouchbaseContainer() {
super(DockerImageNames.couchbase());
withStartupAttempts(5);
withStartupTimeout(Duration.ofMinutes(10));
withCopyFileToContainer(MountableFile.forClasspathResource("/ssl/test-server.crt"),
"/opt/couchbase/var/lib/couchbase/inbox/chain.pem");
withCopyFileToContainer(MountableFile.forClasspathResource("/ssl/test-server.key"),
"/opt/couchbase/var/lib/couchbase/inbox/pkey.key");
withCopyFileToContainer(MountableFile.forClasspathResource("/ssl/test-ca.crt"),
"/opt/couchbase/var/lib/couchbase/inbox/CA/ca.pem");
}
@Override
public String getConnectionString() {
return "couchbase://%s:%d".formatted(getHost(), getMappedPort(KV_SSL_PORT));
}
@Override
protected void containerIsStarting(InspectContainerResponse containerInfo) {
super.containerIsStarting(containerInfo);
doHttpRequest("node/controller/loadTrustedCAs");
doHttpRequest("node/controller/reloadCertificate");
}
private void doHttpRequest(String path) {
Response response;
try {
String url = "http://%s:%d/%s".formatted(getHost(), getMappedPort(MANAGEMENT_PORT), path);
Request.Builder requestBuilder = new Request.Builder().url(url)
.header("Authorization", Credentials.basic(ADMIN_USER, ADMIN_PASSWORD))
.post(RequestBody.create("".getBytes()));
response = new OkHttpClient().newCall(requestBuilder.build()).execute();
}
catch (Exception ex) {
throw new IllegalStateException("Error calling Couchbase HTTP endpoint", ex);
}
if (!response.isSuccessful()) {
throw new IllegalStateException("Error calling Couchbase HTTP endpoint: " + response);
}
}
}

@ -0,0 +1,32 @@
-----BEGIN CERTIFICATE-----
MIIFhjCCA26gAwIBAgIUERZP46qinK0dKmJzlCsoD/k1nWYwDQYJKoZIhvcNAQEL
BQAwOzEZMBcGA1UECgwQU3ByaW5nIEJvb3QgVGVzdDEeMBwGA1UEAwwVQ2VydGlm
aWNhdGUgQXV0aG9yaXR5MB4XDTIzMDUwMTIwNDkxMFoXDTMzMDQyODIwNDkxMFow
OzEZMBcGA1UECgwQU3ByaW5nIEJvb3QgVGVzdDEeMBwGA1UEAwwVQ2VydGlmaWNh
dGUgQXV0aG9yaXR5MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEApWYo
UQjDY98oVOO5HOjheWeBN+C6gozg4aPY0VdRDTKmZ5SzNjuYtX6jsd8e5UF+ceeL
Aw9E3FAKG80F/81c6mtFhFUNUaBCbK2/+igs+Ae6r42i6iLImvgYLbZ0rGpPwszT
KGlwyobsI8n1bRFrVRdtGWVfn3Dfc5k/+dnZ03kOpViv/gd/xNWMcMOlj64F1s8L
6Nx9bfeJvOcsX+5qMiy/B6dZS0lkvXZISJbFhvX/+5Tb/vkP41AnrYff8hO8OBs+
G2srr2xNAIcgNBSjedDVUaRO+a2WHdX/1fHOlNqz335XMo79FOqRWDCZET3YW36A
hqiSPPiDq8AA7hmVxnq7vxWo/qclaqVuk5Dxp+ZD7d8deSGehTPajeCZCDtNhw6C
jtlU8v/LdwMRhqZp5/fjDlOEkutFh6B/aMjq3ZPYQad4MtQixDifgEs4iwnIMoVS
Wqpn24qn0qddfP0Y00U1F79UuJ2cJpyqdjtMRvbdNv6udWhD0rtrjdLvGFDOryzD
W7xQD2NLWW0IC9YNuXR0FzrJFFqWBW+lfF1u1PdW7ITFtUhj8RcIZZgUS/w1Yh8/
d6ja18UROEgiJ/Isgvl8sNTe2oNQK9HM6XtyEif5G5J7cv5FAH3si98My5h+rKq9
AMGfQLtDOM+Ivg7D63iiuxB57Rq91xCsKCC2QNECAwEAAaOBgTB/MB0GA1UdDgQW
BBQuNq1dmybivJy6XnHIFBYqEfqtMDAfBgNVHSMEGDAWgBQuNq1dmybivJy6XnHI
FBYqEfqtMDAPBgNVHRMBAf8EBTADAQH/MCwGA1UdEQQlMCOCC2V4YW1wbGUuY29t
gglsb2NhbGhvc3SCCTEyNy4wLjAuMTANBgkqhkiG9w0BAQsFAAOCAgEAJFpeqQB9
pJLn4idrp7M1lSCrBJu2tu2UsOVcKTGZ3uqgKgKa+bn0kw9yN1CMISLSOV9B1Zt5
/+2U24/9iC1nGIzEpk2uQ2GwGaxFsy38gP6FF+UFltEvLbhfHWZ/j8gWQhTRQ/sT
TMd0L0CysmDswoEHcuNgdX+V4WVchPqdHTxp5qLM3GRas5JCuNcVi+vFEWCQsYRh
iTpsCEVfRsVJKUvPKVLR8PSEjSt8S+SQjIuTVWSmdG358uRVxpBzAzMwz9sQw4G6
Rv3S4LaQpWXUyHVYM1OxQz0fhEug5qgSR75GTFwG1oVd5rdk7iK/J3WbRJZ9FcKx
ipZ3jdl5mmI6p87OjgQVtUInv8KK88AhJmypBXaHE64nn8+YUsh/ud6+Vr8vyMPK
TZJivCtVKoX+nd3Zb3qX2YGORKQmn4GPX551FCk1CFOa+qlGfXtfqV2Z9LEQmqx3
ygqVnmSf34oTz04sSMdK7m3ULqLyv3RFJJ4F+VsHHAEdJYO+v/GdGz/0FA7ZZ4t+
7r1qY7uK4NSMRBn+DGlUL9oVp26uss/Qvi1WTI0g9W1YImxYSlaR0tm9jZQckirm
KMLMDyGJFvHqR8LRa3DU6L5pU99LxZSHRxBAY6oexKSYWt7BSE1kwaL3Exjg/RG/
ap5/GNJS1STNnbgq5TtWUbvZcXuhuBe8ClI=
-----END CERTIFICATE-----

@ -0,0 +1,51 @@
-----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY-----

@ -0,0 +1,24 @@
-----BEGIN CERTIFICATE-----
MIIEGjCCAgKgAwIBAgIUCNvMLf/1EZcO6R9L/PQVWN8agbkwDQYJKoZIhvcNAQEL
BQAwOzEZMBcGA1UECgwQU3ByaW5nIEJvb3QgVGVzdDEeMBwGA1UEAwwVQ2VydGlm
aWNhdGUgQXV0aG9yaXR5MB4XDTIzMDUwMTIwNDkxMFoXDTI0MDQzMDIwNDkxMFow
LzEZMBcGA1UECgwQU3ByaW5nIEJvb3QgVGVzdDESMBAGA1UEAwwJbG9jYWxob3N0
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzP5NGFAhk6hAVr3YshRJ
YGxS2IGphFaq/c99QZQ62JbcSwceFo0p8Px9JiaT38n7NejEy6t6U0PQP2B9r3pJ
p0RwplvITLd1lp96DdMQeGXKa2rqJ62u9//u/XxFboVU6QYC90Pnqi6sRWejKEI8
Yowg6erjNMCQiIAKqhWPfdsJOxf79102gdahuTT8A89p551u7a84oTRtX4fLksP2
x0BVFb0/Dirz5ngwm6YHpN+8z7BYIyj4dLzzFjaqU1gptxtGygap1GtD1X9fJ61l
k6K8vMww4+/zYOoGratUTNeKHOvvXf9SnjoqyMTvJFyTX+5snkyL81q3+XgXJOYL
ZQIDAQABoyIwIDALBgNVHQ8EBAMCBaAwEQYJYIZIAYb4QgEBBAQDAgeAMA0GCSqG
SIb3DQEBCwUAA4ICAQAq5Em7EVkGhPgIMDmxhm398Kv8OivFxX6x5aGnJ+m8+mZV
+wrkjRvpqN/+CtTsid2q4+qYdlov8hJ2oxwVhfnrF5b7Xj7caC2FJifPXPiaMogT
5VI4uCABBuVQR0kDtnPF8bRiTWCKC3DC84GqMp0cUs3Qyf1dLcjhcc9dSROn00y8
/qmIz8roJ2esnqG12rTGdIAaWSgBCMKFjrV8YmxLf+z72VHSx6uC5CARG+UYa5Mu
vga0Q77QmwSstKBvGUBtvzQoML3/UFCikdfOxDgvJbr8Q0yEEw8hK7vGZLaj00zB
U4B5+DfV285RW09ihp2YMxuz3mL2tM5++RYJphB9/VTN3/f+geKt2pPA3Rkk11Ug
LP3NdpT5ZnQL9ehtmIExk2NVBi+RmGCcP7KcMtlq44FdyRF7p6qdg/Eq5n/sOMxQ
DnamgWDQltm6cuZ49haCXLZIbfqM2cHARIw/Sv3Dgd9SSDL2pooWI2U82fQ9A71q
u/hUlNDZm0v51IfgzJcbAtlAYd2OVlgCkkkFtbgdOaQUShIkcCKcpxtgQzpynNMO
DJoO41VXpMzBN7/ppVi0JrF7RkaXGeoNsqfvcmjQEuXUOluge2q8kHDf7gEUddKa
ijPHtkFQF2ujCGr/AVYjCMSlOk5WhRh8ZVxN0KbiWZJUN8akX4gU4KIpTe1big==
-----END CERTIFICATE-----

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAzP5NGFAhk6hAVr3YshRJYGxS2IGphFaq/c99QZQ62JbcSwce
Fo0p8Px9JiaT38n7NejEy6t6U0PQP2B9r3pJp0RwplvITLd1lp96DdMQeGXKa2rq
J62u9//u/XxFboVU6QYC90Pnqi6sRWejKEI8Yowg6erjNMCQiIAKqhWPfdsJOxf7
9102gdahuTT8A89p551u7a84oTRtX4fLksP2x0BVFb0/Dirz5ngwm6YHpN+8z7BY
Iyj4dLzzFjaqU1gptxtGygap1GtD1X9fJ61lk6K8vMww4+/zYOoGratUTNeKHOvv
Xf9SnjoqyMTvJFyTX+5snkyL81q3+XgXJOYLZQIDAQABAoIBAFNG/Arkgr95mqmi
dmXh1+1UFFPgWP1qOAzkPf5mOYHDx7qzKYX/0woTiMP26BwB8gv0g/45q3goFHGq
wWSISWOqahkrMDP6U8rc/rifBhHjSFhbFsUHygz17CEOWyaLA/OmfY32CCcazuFj
OOUiA2YFh1mAEs1bbVwGqE5wc9qsZtBlJxudSWtSZoJuFECDNqLfQXkJ39KnKhp4
D337nOR/xww81202mlfF/vvhRMfUIUS2Ij9USndp9huBHFSxf1mYjD1ljjx6U7el
new8TPf76J7nuy/6SxZ9wF6P2dk/eQcN5AnIcDGq0WzS3VcJc/KG/+maflCvH0dB
SLfx4AECgYEA7e+5/UhWZ62BfF1/Nat95+t+bh8UYN8gPEUos7oS/cUrme7YAPQT
MTWNulpmgGCRDxeXU9XBaPGyF7cU5bx28sK64ZUe8D1ySgGpVeSEQtjCLFEf6eat
801TQVNaH2WlDZTm+Onfr7ppFN1pLrBY+83m9TDJd6v4qHsvtNkcx38CgYEA3I5U
OvvoTEj8+Xc0U296NU+aWJLNrkDH6lFtdXsLyoumxh0DDbKSw8ia28Z5+8tz0mdB
33sIsnnsQ+83YoiXyopM9GFZdZH3luKrXgOGH8QFygJI8xGqqcLjeWNkW0b0KCkv
AoiedqOOmCdRMUfy3v5irH+4O90ZmW6VxNKbfxsCgYEAtjjFOQwAWHCR3TwBo4nN
6CL7dbzJr5LSLjZNAK/9wWoShVZdCQXj+OjpvRFktOa/0U4g7+yhrgyEdxMYpwUa
F7s4wnCg/B4i/Difhg93l3ZH5wbOKSUojU/n9fyu5aLDsE4cQf9i90MNHRSgbEhU
Law4OAmAEe2bhvSoyZkJKGMCgYBgW25BNr0OVvTuqD2cFh/2Goj8GWbysiqlHF4N
7WwBWXHLK/Ghklq8XnAJhHTWpNQ9IA+Pa1kpYErwgxpXWgW23yUvvzguPU9GBFGK
CVAXoLRGxSjJyPYepJ5s8hduKVmSEiwPl1Bj1KD/qG24cg6RjeHeKw56WOZOOhoE
m16D8QKBgBHXU31OJ2KMDnwjsMW2SlpYKoIQlJyTg3qvN7gu+ZGo5B7hviqh5wN1
y577N/NT9No8qGNEGTZl35hkyw8DmB4RAZp7G1qbVCGszUBt/vS6Guv82/EgMVo2
ZgiQBkI1kEOtj5LMVBfOKTRBEpyAm5fSZ+eQtSIc5LCbQ8aEvio4
-----END RSA PRIVATE KEY-----

@ -0,0 +1,24 @@
-----BEGIN CERTIFICATE-----
MIIEGjCCAgKgAwIBAgIUCNvMLf/1EZcO6R9L/PQVWN8agbgwDQYJKoZIhvcNAQEL
BQAwOzEZMBcGA1UECgwQU3ByaW5nIEJvb3QgVGVzdDEeMBwGA1UEAwwVQ2VydGlm
aWNhdGUgQXV0aG9yaXR5MB4XDTIzMDUwMTIwNDkxMFoXDTI0MDQzMDIwNDkxMFow
LzEZMBcGA1UECgwQU3ByaW5nIEJvb3QgVGVzdDESMBAGA1UEAwwJbG9jYWxob3N0
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqgji6StU0UkWfYmZumQO
L7SnFg7/xBM5ubMtXJsBOS0RaRWJ0WwIsQ2ksDOf2ybDyXiePplbtR/4GsnXPyNp
H1vgY/Mt/PeiP/lHw9dDTdSx6YMMxGVoILsHkblaeHwh8yVGCg2gdoRROscgjS+e
j7gTr4H2UBlepHsjZBKc+hamDrIC3vK42iQUyzbClJ8lpY+KbL4R4KhsuhTb2jRL
wye3m2w+YU1jvE+IioQfozlZTAw0SX7whcCw0B3hLVQg6hsdSeSYkCUZiZY72ySR
fI+mDcnJVcetH2ShK1zVFBpDs9qkJSA9YumO1ZKVDdDseeuHHsEUG2/pszQ2cHH6
EwIDAQABoyIwIDALBgNVHQ8EBAMCBaAwEQYJYIZIAYb4QgEBBAQDAgZAMA0GCSqG
SIb3DQEBCwUAA4ICAQACFGGWNTEDCvkfEuZZT84zT8JQ9O5wDzgYDX/xRSXbB1Jv
fd9QQfwlVFXg3jewIgWZG0TgQt/7yF6RYOtU+GRP6meJhSm9/11KnYYLNlHQU1QE
7imreHAnsJiueHXPmpe9EL4jv2mQt7GSccABMf1pfBQ+C0dETnUoH68oO3LttU16
f43H1royvOm3G6LnJb83rLYVe07P1PTjk/37gaFCf54J1eDfqntVDiSq8H6fV+nL
9ZvsVuC4BcREnB3oY7vsJFBhGeK/3+QFX4Zr3DTwLxiWe2pqSQfUbn4+d6+uwIY7
pixgNorpebKQn0vX/G4llVjOmBNjlgSzDyVTYObBz316GojF7yRk3oBbxK//3w/t
XVhLwrPpqB5Jehh2HsKKZrdfnjB1Gn+pDpSEMVDrCbWxzAJz4WOu2ihCYYsF3Gts
lzI1ZzD+UpFyeHG/1wQHzyQwADBiaYfh1oAnpNcOvJhT1S6IVGImcOBNa8u14aVG
NjvnJWVn3v3dcvAVO1ZUwX9TdHP11oIpn7fGYZzSxCDrhGaFeW0tscxddHRrXdwk
IHyHZ3o2RgivhaSc4C04nuZEX00ohTgtKo2rpK1SP+gn64Yh+u+O6AH8r+q7cZy2
gZNscwHAmkEalP78D5vnOFRUYEVrNc/X2f+rwFoQD7B8GNGa/visAkD7myg7JQ==
-----END CERTIFICATE-----

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAqgji6StU0UkWfYmZumQOL7SnFg7/xBM5ubMtXJsBOS0RaRWJ
0WwIsQ2ksDOf2ybDyXiePplbtR/4GsnXPyNpH1vgY/Mt/PeiP/lHw9dDTdSx6YMM
xGVoILsHkblaeHwh8yVGCg2gdoRROscgjS+ej7gTr4H2UBlepHsjZBKc+hamDrIC
3vK42iQUyzbClJ8lpY+KbL4R4KhsuhTb2jRLwye3m2w+YU1jvE+IioQfozlZTAw0
SX7whcCw0B3hLVQg6hsdSeSYkCUZiZY72ySRfI+mDcnJVcetH2ShK1zVFBpDs9qk
JSA9YumO1ZKVDdDseeuHHsEUG2/pszQ2cHH6EwIDAQABAoIBAQCLTuiJ3OSK63Sv
udLncR5mW34hhnxqas36pSBfJOflrlT7YZgeqoKcfO8XJdSsup/iKx6Lbx5B0UV2
vTPLGPoBpUa83PoqrcCS5Wu0umL8G20AQkxthB/B4TocXF4RJLK0AS/XAL8dGt9q
Zsb2pbMlUM1gF/x0N7Tg0bp3PQC7rAgYe7JFvArxRrmDP38FE9Cg5EIAVMN8Fw2b
dxKZxJ+mqj1t1bU4/bsrYBs9QpNrBjQc0KTFOamwkvWI7FhHXQtIZfJvvBj8mN7z
He7B5j/JcfGC5LN1UpL4tziOrKwMGGIvpAnpbVEv29SWxOG5Vbccb4ghBN+VJqSH
6WON791hAoGBAN7Q5nuCk+L/8BQh29WHZuP6dbLyMMjWMyuDm2xEYD0fjjacvU7r
KIQDcQY3E7bXu6OXKQmxARFY7HuZUyGg8R4QBeAEVfDPjRKzGZgA1+gF325eQwAQ
giXqg0paE2ePfbawi21NfQPCMMhb4n3QzpYd4eEsFFwMvt4oZCPkHubJAoGBAMNb
pGajPKW19dFWP5OsKc1U6itej78RQRjO7zpQ3JWvNuMa/SZzEa2blFuks585u6M2
XdVPhhspc0TwS+asizNEMDYaPpAjmg9X9LY87hcYTC0FXT0Axx+7A/JtmMAVF3Pn
4lvhfdB5XSV5jo/BtUJ3vDx5FSFIHQbbj1agGpv7AoGAdv6pmJyLzldRJ+9NMCQ3
1tkTspWVaCy89yg6AQAjRYFsuc3LbDI6WQZdfiw74xIjq6I20G4vW8xZv0iLFRKW
sq9r889c9lZhyPLNYFhS9h7szEybC5XFa+pqY3Lnmg8P3Fk8nQsdELzMwLQRqY+y
RImA8HhSBzbnWE3J7UEPH8ECgYAXyNGEOX2Jw1SRTwnghcZ1HFCCRToFDim5xn/z
vqKMis+I6OFHTB0r4NQ4MB46VYIVxem4rbzrE6nYC9WB2SH9dODVxW42iE8abR/7
DAIEx82Gca+/XJfhshgx7Mv7HtZDI0k43IQ/3HbNuDX2JKRX2lINnsRG0AvQqOyT
pFx4/wKBgQCXU0LGSCgNwuqdhXHoaFEzAzzspDjCI+9KDuchkvoYWfCWElX035O9
TbEybMjCuv08eAqeJv++a1jnTmJwf+w+WhBG+DpYcro1JXmo8Lu9KAbiq0lJGQP6
tX9gr0XY3IC+L5ndOANuFH6mjGlnp7Z+J8i7HFFoSa+MI2JkoQ5yVA==
-----END RSA PRIVATE KEY-----
Loading…
Cancel
Save