Skip to content

Commit 18cc0ef

Browse files
committed
Add test for HTTP and Transport TLS on basic license
This adds a new security/qa test for TLS on a basic license. It starts a 2 node cluster with a basic license, and TLS enabled on both HTTP and Transport, and verifies the license type, x-pack SSL usage and SSL certificates API. It also upgrades the cluster to a trial license and performs that same set of checks (to ensure that clusters with basic license and TLS enabled can be upgraded to a higher feature license) Backport of: elastic#40714
1 parent d5fcbf2 commit 18cc0ef

File tree

12 files changed

+400
-0
lines changed

12 files changed

+400
-0
lines changed

x-pack/plugin/security/build.gradle

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,3 +298,13 @@ unitTest {
298298
// installing them as individual plugins for integ tests doesn't make sense,
299299
// so we disable integ tests
300300
integTest.enabled = false
301+
302+
// add all sub-projects of the qa sub-project
303+
gradle.projectsEvaluated {
304+
project.subprojects
305+
.find { it.path == project.path + ":qa" }
306+
.subprojects
307+
.findAll { it.path.startsWith(project.path + ":qa") }
308+
.each { check.dependsOn it.check }
309+
}
310+
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import org.elasticsearch.gradle.test.RestIntegTestTask
2+
3+
apply plugin: 'elasticsearch.build'
4+
unitTest.enabled = false
5+
6+
dependencies {
7+
compile project(':test:framework')
8+
}
9+
10+
subprojects {
11+
project.tasks.withType(RestIntegTestTask) {
12+
final File xPackResources = new File(xpackProject('plugin').projectDir, 'src/test/resources')
13+
project.copyRestSpec.from(xPackResources) {
14+
include 'rest-api-spec/api/**'
15+
}
16+
}
17+
}
18+
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import org.elasticsearch.gradle.http.WaitForHttpResource
2+
3+
apply plugin: 'elasticsearch.standalone-rest-test'
4+
apply plugin: 'elasticsearch.rest-test'
5+
6+
dependencies {
7+
// "org.elasticsearch.plugin:x-pack-core:${version}" doesn't work with idea because the testArtifacts are also here
8+
testCompile project(path: xpackModule('core'), configuration: 'default')
9+
testCompile project(path: xpackModule('security'), configuration: 'testArtifacts')
10+
testCompile project(path: xpackModule('core'), configuration: 'testArtifacts')
11+
}
12+
13+
forbiddenPatterns {
14+
exclude '**/*.key'
15+
exclude '**/*.p12'
16+
}
17+
18+
File caFile = project.file('src/test/resources/ssl/ca.crt')
19+
20+
integTestCluster {
21+
numNodes=2
22+
23+
extraConfigFile 'http.key', project.projectDir.toPath().resolve('src/test/resources/ssl/http.key')
24+
extraConfigFile 'http.crt', project.projectDir.toPath().resolve('src/test/resources/ssl/http.crt')
25+
extraConfigFile 'transport.key', project.projectDir.toPath().resolve('src/test/resources/ssl/transport.key')
26+
extraConfigFile 'transport.crt', project.projectDir.toPath().resolve('src/test/resources/ssl/transport.crt')
27+
extraConfigFile 'ca.crt', caFile
28+
29+
setting 'xpack.ilm.enabled', 'false'
30+
setting 'xpack.ml.enabled', 'false'
31+
setting 'xpack.license.self_generated.type', 'basic'
32+
setting 'xpack.security.http.ssl.enabled', 'true'
33+
setting 'xpack.security.http.ssl.certificate', 'http.crt'
34+
setting 'xpack.security.http.ssl.key', 'http.key'
35+
setting 'xpack.security.http.ssl.key_passphrase', 'http-password'
36+
setting 'xpack.security.transport.ssl.enabled', 'true'
37+
setting 'xpack.security.transport.ssl.certificate', 'transport.crt'
38+
setting 'xpack.security.transport.ssl.key', 'transport.key'
39+
setting 'xpack.security.transport.ssl.key_passphrase', 'transport-password'
40+
setting 'xpack.security.transport.ssl.certificate_authorities', 'ca.crt'
41+
42+
waitCondition = { node, ant ->
43+
WaitForHttpResource http = new WaitForHttpResource("https", node.httpUri(), numNodes)
44+
http.setCertificateAuthorities(caFile)
45+
return http.wait(5000)
46+
}
47+
}
48+
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
package org.elasticsearch.xpack.security;
7+
8+
import org.elasticsearch.client.Request;
9+
import org.elasticsearch.client.Response;
10+
import org.elasticsearch.common.io.PathUtils;
11+
import org.elasticsearch.common.settings.Settings;
12+
import org.elasticsearch.test.rest.ESRestTestCase;
13+
import org.elasticsearch.test.rest.yaml.ObjectPath;
14+
import org.junit.AfterClass;
15+
import org.junit.BeforeClass;
16+
17+
import java.io.FileNotFoundException;
18+
import java.io.IOException;
19+
import java.net.URL;
20+
import java.nio.file.Path;
21+
import java.util.ArrayList;
22+
import java.util.List;
23+
import java.util.Map;
24+
import java.util.stream.Collectors;
25+
26+
import static org.hamcrest.Matchers.containsInAnyOrder;
27+
import static org.hamcrest.Matchers.equalTo;
28+
import static org.hamcrest.Matchers.instanceOf;
29+
import static org.hamcrest.Matchers.iterableWithSize;
30+
import static org.hamcrest.Matchers.notNullValue;
31+
32+
public class TlsWithBasicLicenseIT extends ESRestTestCase {
33+
private static Path httpTrustStore;
34+
35+
@BeforeClass
36+
public static void findTrustStore() throws Exception {
37+
final URL resource = TlsWithBasicLicenseIT.class.getResource("/ssl/ca.p12");
38+
if (resource == null) {
39+
throw new FileNotFoundException("Cannot find classpath resource /ssl/ca.p12");
40+
}
41+
httpTrustStore = PathUtils.get(resource.toURI());
42+
}
43+
44+
@AfterClass
45+
public static void cleanupStatics() {
46+
httpTrustStore = null;
47+
}
48+
49+
@Override
50+
protected String getProtocol() {
51+
return "https";
52+
}
53+
54+
@Override
55+
protected Settings restClientSettings() {
56+
return Settings.builder()
57+
.put(TRUSTSTORE_PATH, httpTrustStore)
58+
.put(TRUSTSTORE_PASSWORD, "password")
59+
.build();
60+
}
61+
62+
public void testWithBasicLicense() throws Exception {
63+
checkLicenseType("basic");
64+
checkSSLEnabled();
65+
checkCertificateAPI();
66+
}
67+
68+
public void testWithTrialLicense() throws Exception {
69+
startTrial();
70+
try {
71+
checkLicenseType("trial");
72+
checkSSLEnabled();
73+
checkCertificateAPI();
74+
} finally {
75+
revertTrial();
76+
}
77+
}
78+
79+
private void startTrial() throws IOException {
80+
Response response = client().performRequest(new Request("POST", "/_license/start_trial?acknowledge=true"));
81+
assertOK(response);
82+
}
83+
84+
private void revertTrial() throws IOException {
85+
client().performRequest(new Request("POST", "/_license/start_basic?acknowledge=true"));
86+
}
87+
88+
private void checkLicenseType(String type) throws IOException {
89+
Map<String, Object> license = getAsMap("/_license");
90+
assertThat(license, notNullValue());
91+
assertThat(ObjectPath.evaluate(license, "license.type"), equalTo(type));
92+
}
93+
94+
private void checkSSLEnabled() throws IOException {
95+
Map<String, Object> usage = getAsMap("/_xpack/usage");
96+
assertThat(usage, notNullValue());
97+
assertThat(ObjectPath.evaluate(usage, "security.ssl.http.enabled"), equalTo(true));
98+
assertThat(ObjectPath.evaluate(usage, "security.ssl.transport.enabled"), equalTo(true));
99+
}
100+
101+
private void checkCertificateAPI() throws IOException {
102+
Response response = client().performRequest(new Request("GET", "/_ssl/certificates"));
103+
ObjectPath path = ObjectPath.createFromResponse(response);
104+
final Object body = path.evaluate("");
105+
assertThat(body, instanceOf(List.class));
106+
final List<?> certs = (List<?>) body;
107+
assertThat(certs, iterableWithSize(3));
108+
final List<Map<String, Object>> certInfo = new ArrayList<>();
109+
for (int i = 0; i < certs.size(); i++) {
110+
final Object element = certs.get(i);
111+
assertThat(element, instanceOf(Map.class));
112+
final Map<String, Object> map = (Map<String, Object>) element;
113+
certInfo.add(map);
114+
assertThat(map.get("format"), equalTo("PEM"));
115+
}
116+
List<String> paths = certInfo.stream().map(m -> String.valueOf(m.get("path"))).collect(Collectors.toList());
117+
assertThat(paths, containsInAnyOrder("http.crt", "transport.crt", "ca.crt"));
118+
}
119+
120+
121+
}
122+
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
= Keystore Details
2+
This document details the steps used to create the certificate and keystore files in this directory.
3+
4+
== Instructions on generating certificates
5+
The certificates in this directory have been generated using elasticsearch-certutil (7.0.0 SNAPSHOT)
6+
7+
[source,shell]
8+
-----------------------------------------------------------------------------------------------------------
9+
elasticsearch-certutil ca --pem --out=ca.zip --pass="ca-password" --days=3500
10+
unzip ca.zip
11+
mv ca/ca.* ./
12+
13+
rm ca.zip
14+
rmdir ca
15+
-----------------------------------------------------------------------------------------------------------
16+
17+
[source,shell]
18+
-----------------------------------------------------------------------------------------------------------
19+
elasticsearch-certutil cert --pem --name=http --out=http.zip --pass="http-password" --days=3500 \
20+
--ca-cert=ca.crt --ca-key=ca.key --ca-pass="ca-password" \
21+
--dns=localhost --dns=localhost.localdomain --dns=localhost4 --dns=localhost4.localdomain4 --dns=localhost6 --dns=localhost6.localdomain6 \
22+
--ip=127.0.0.1 --ip=0:0:0:0:0:0:0:1
23+
24+
unzip http.zip
25+
mv http/http.* ./
26+
27+
rm http.zip
28+
rmdir http
29+
-----------------------------------------------------------------------------------------------------------
30+
31+
[source,shell]
32+
-----------------------------------------------------------------------------------------------------------
33+
elasticsearch-certutil cert --pem --name=transport --out=transport.zip --pass="transport-password" --days=3500 \
34+
--ca-cert=ca.crt --ca-key=ca.key --ca-pass="ca-password" \
35+
--dns=localhost --dns=localhost.localdomain --dns=localhost4 --dns=localhost4.localdomain4 --dns=localhost6 --dns=localhost6.localdomain6 \
36+
--ip=127.0.0.1 --ip=0:0:0:0:0:0:0:1
37+
38+
unzip transport.zip
39+
mv transport/transport.* ./
40+
41+
rm transport.zip
42+
rmdir transport
43+
-----------------------------------------------------------------------------------------------------------
44+
45+
[source,shell]
46+
-----------------------------------------------------------------------------------------------------------
47+
keytool -importcert -file ca.crt -keystore ca.p12 -storetype PKCS12 -storepass "password" -alias ca
48+
-----------------------------------------------------------------------------------------------------------
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
-----BEGIN CERTIFICATE-----
2+
MIIDSTCCAjGgAwIBAgIUNsCMQBpQB3zJAC1iERdc7yADVw0wDQYJKoZIhvcNAQEL
3+
BQAwNDEyMDAGA1UEAxMpRWxhc3RpYyBDZXJ0aWZpY2F0ZSBUb29sIEF1dG9nZW5l
4+
cmF0ZWQgQ0EwHhcNMTkwMzI5MDUxMjEyWhcNMjgxMDI3MDUxMjEyWjA0MTIwMAYD
5+
VQQDEylFbGFzdGljIENlcnRpZmljYXRlIFRvb2wgQXV0b2dlbmVyYXRlZCBDQTCC
6+
ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMJL4SrJJsQpKFuHsNnWwzM9
7+
2Cnmsc7WzGEskV0ncSUloMxUZaZ8CJ2iuubN6KPe75ke8SS9vlNG3MEWRBVSPY4H
8+
EJNcyiiI1w9c/yom6Kfvep1RvvRHlp+k/bDPzzuj4B8Dyg66TVYKRm+9uRWAUvZr
9+
djhFB3cawbM1jD9ZaBLM4Qbdg0AlMqXWpkLPVtkD8lREPkAIhYxKx7TYqB1SbMg5
10+
ejfoRGF5qfl4luegWRlQKkOBCcJPZamcccNjDq9eXQm3vrp0/QEp0ODG14wU3B9R
11+
G+2/yhh5KP3WWK/uksAmEv8YzG7UaCLNJRk/FuPz8uoSGLPM1e+2HWXsR9OnlF8C
12+
AwEAAaNTMFEwHQYDVR0OBBYEFL+GbWzP3nPfx+OqvW5CYCqHN8ZlMB8GA1UdIwQY
13+
MBaAFL+GbWzP3nPfx+OqvW5CYCqHN8ZlMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZI
14+
hvcNAQELBQADggEBAHZeLZ7yCvqQOJbQ3yoixYLVR33dSx/T/W5WQQGYcQ7TUZ4N
15+
gXkV9kGD+9I/8NWgkttx4TTieWctyNPrhAqqWGuGvhCQ+WL8m67EPRiVdw7EY+61
16+
qlUbAdK39adDqbDeUI07dzd+wKlhwnHtd2dTcJEGluwLaU4ftuLA8DQNwzWxZVAW
17+
EWzfTUgdc1SYTysE5C0d1Q9CbI+o0Na+CaW4DRqGh1OGyH7Fyck9WQp1nOAEQhD9
18+
sn4FOC4w+T92t/Ekpfcm5HHkYjGWK1EsCkRCj1m8QtyqBgByeXHCidH2pfKIuVdl
19+
ZnaOfIkCQx49gLARjzzGp/OC/UfKVCWzpLHn7dY=
20+
-----END CERTIFICATE-----
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
-----BEGIN RSA PRIVATE KEY-----
2+
Proc-Type: 4,ENCRYPTED
3+
DEK-Info: DES-EDE3-CBC,67376A5606FB27E9
4+
5+
v4OAjurrB7Tc2mVswSeaaYAiFomvSQmre8DlC5VNvavzT6Hlx5hIyEVIttcNeTeD
6+
Hj4d+JOp5OO5Ew5cWgo0jtR2QIjGbrQe8t8oedJwhEiYC0IfX0rItJv1iaz4WO+8
7+
hz4J1lwAI9wFabmXIeHx0q3ZqqIfSOoAepO8W2SqIj0KSz3tKRoYaX7AzZ27muLN
8+
K2Mej1EX/ftgZZNgfU62gJzGGsdQecLc+UZBDVTPZL3PLZmQV0r1sBXaq56Qk78t
9+
DsUyYwA4zvPBIPkfydTxobylt1pSeZ7Yyni+iQk4X7T4jj3Q6wKrwjPNJ6p8Xcwn
10+
4BN37DIYPPBEp56EUCbxl+iMkfRoCjZdaqhycw4LjKB0wloY2Zko6FaYTd0qPZ/m
11+
2GM8MvIQ9bc4t9Bef2VAXhb8IUXJ+ro+sB7vlQRSLQ1JwHPAPiIFyRmilezAaupA
12+
2DNLBIlmgMzh5Lh6vIcyHQVxsCoJesmVQCyyBy4lFPU9afcYLWjzgnBhW2SikTpW
13+
/lC3VDloUjIYfC3qYhbHIomsUMCGk3xHIwLw1cNFnf7c/RX1q5bBZrJ8q6GVh/Rb
14+
ulHcuCm5g/Jvt8TM8c2WIE5mzwkoFIe/XVY33Lyk237qCsPlVWwFpxa0UtWVpDnk
15+
uuubgI0cb+zehN2f5sgHtdbphNNTflZyW+Uk0lCbYGNakXBILePFmURsThW3gQ44
16+
g+zPaiGkbB1qwE/TS3Vz17j8DkgWRsEJP7IBsZ/ljaUcs3zujH6EKN9YtwyIeoHo
17+
VHBuF4RGew2Ps0NoLGYanpvu01ZUUr2C0ZbDjXLBy8ajOc5zgyMCBead19T+piFw
18+
iGvA8D7eILz1xzbAcX7dry06Mc9o/CbFcRMIis3LVvdSuZDoRk/cv0mKo6rq/1MS
19+
VeYgPjJ8QWuhulIYkmNipTRdzMsXEafEdsp+GruKnNri0u/lirfhYAXDGp2GAttJ
20+
zKnbPkHSJRt1xWgtimU+CnnpEOp+qd2yFNgT/Nn2yjrsPqLqTkEdzbh2DoCYGPHe
21+
HoAcs+MePKfqBh+W2MEJ/ZdDVz93lKoDTuk2cjaVVe+7YBdHW0gQzfW5ArscadUV
22+
+mSzhUm9AIhM/Gk6t7rgVoWyO6PvkTgENKFmUUQkHnJWaaDIzji2xFR114Huw5rN
23+
gHPn8HOKPIhVu1UV2N/MFLrjjvn8bft/vLkSxZ3c7AgYkPr8Mmd0b8ufTOlk5a+W
24+
hkR4D7WZ7Hgkj1NIvRbjxCXTHFbHZqKJHeTTNCpCUygIH5g8h7RGVPS0XKylpbr1
25+
2kZU/AwlPcAPba+UcTKXOvy02NmiV5Bg6qYc8rcxv6aXKPOrxeW3Iop/ZesF7Nnu
26+
ccR+rI78cQIGD1gAo3xLJ10/p0Rb9R/pWfHUY499Oymc926qWaj3mEl+xOJXxWOr
27+
3Uf4yMg8mrfcm3JW7clWy3l+/++CSWBS/zqUpXKy5CbVdR8XQNS5Pg0fDgwkrcbv
28+
7TviQ+vYD7aEI0w6mviljPkYVTXNpnRHyF7VfaEYff8032GxW99D3zeK7dd6yP4k
29+
W/oN5IwXCvnfrteNtqSOIPOWw9gAp4x4EzmCin77s8SgMHOGsPcEhA==
30+
-----END RSA PRIVATE KEY-----
Binary file not shown.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
-----BEGIN CERTIFICATE-----
2+
MIIDszCCApugAwIBAgIVAJX8GTm+AWIicokE5npzZ2B3qad3MA0GCSqGSIb3DQEB
3+
CwUAMDQxMjAwBgNVBAMTKUVsYXN0aWMgQ2VydGlmaWNhdGUgVG9vbCBBdXRvZ2Vu
4+
ZXJhdGVkIENBMB4XDTE5MDMyOTA1MTIyNVoXDTI4MTAyNzA1MTIyNVowDzENMAsG
5+
A1UEAxMEaHR0cDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMGvsPmg
6+
4lKfd1ie6TZQLdCxfXy6MooLHac1wUxyvHcUxlbuSchj+A2gVPBk6VaCV8OO4X7T
7+
MslTJKw5877m28Xzw+CmUgDsXAJJy2IvM8X0IP/xktkJQ3uSUReSW2650TFj9Zcm
8+
Z3AtMblo+cNnZMNWJBW1G1QMHHKMY5kukaB7Ia6CBec60k2HrkS6xmsMgwQPBa/k
9+
VlbHkI7RzbmxohVJFHL34EFhifEL0qkYU5MnZ8PjH8U749VoZOYcY1MKb2sw9iYn
10+
JTOv1gIFhd4Sw37occxDVaqZU/1X90ijZyvB/AugxRfmpLb83ZRMdVeQTiiXqMkg
11+
1g94h7hgPpLA9AkCAwEAAaOB4DCB3TAdBgNVHQ4EFgQUc/bPDUIvgLwg9xwf9CxP
12+
ec84o1YwHwYDVR0jBBgwFoAUv4ZtbM/ec9/H46q9bkJgKoc3xmUwgY8GA1UdEQSB
13+
hzCBhIIJbG9jYWxob3N0ghdsb2NhbGhvc3Q2LmxvY2FsZG9tYWluNocEfwAAAYcQ
14+
AAAAAAAAAAAAAAAAAAAAAYIKbG9jYWxob3N0NIIKbG9jYWxob3N0NoIVbG9jYWxo
15+
b3N0LmxvY2FsZG9tYWlughdsb2NhbGhvc3Q0LmxvY2FsZG9tYWluNDAJBgNVHRME
16+
AjAAMA0GCSqGSIb3DQEBCwUAA4IBAQAJW7WWQkuNjDlQQ5H6bhMr2LhbC9TZWgFK
17+
zWsIWuhd1QxiWbTp/Yegcbqs3hZ9MQtxU4egml/sMAdZSF3Kg3NeYtrHDj//oKYo
18+
VSfTPNjQLG1/ckCM0RDfFYOV+Sb3ktau5QZGL+5ZDfcfPLSHCSHeP0tft2R03Hp4
19+
pOX8/xAVmv0hxE74X5qodQyNFdDa6rtRZESLzY1b+oaEhKM49MZCNZL9TvvNUkWC
20+
hXdaVehqBVJkrlsnli6oqPBjpKNP2YkRG3eqy/Qd/sg6rwJqu/B0KBI8QBDkokSY
21+
YORRviEmSe0+hmcBCTYZWN8WX3BrEPuGdBJXWi5G8GPGFg4rrOUE
22+
-----END CERTIFICATE-----
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
-----BEGIN RSA PRIVATE KEY-----
2+
Proc-Type: 4,ENCRYPTED
3+
DEK-Info: DES-EDE3-CBC,A46C453D20DC86A7
4+
5+
eFBKmjJUmailcnfc1+a6lwR8G7sk4ff1De5hIYY8iNkpP6XVxZ/LrXttVF1x1SWy
6+
YaUJL35Optzy4W+LglJgAdNo9XGaCsHuSi3z7aqYNdihSldKxDw3iIJEEuB63Lv7
7+
eu4pEYdOlRElEs71cmjMCSmg1pfeDRruShB9RUKy3Iw8tM6tV+t+vIaiVftb3i9O
8+
AaTEUgAJqQjcISWy5JAxRwEwVDAhHe23vbVomxXlJKuTroezPFt5SxXQmdfNmP7B
9+
D8iZR/Uf+7XdCFKC/7n6enYZfg5/IoaOO9sPG4bueFKmLAdXpmN1hKvJwIG1qKQT
10+
Fz7x8FGi0S11BHDZMs5kJHBaiuXmq02mozb5XOFllQYl8+fsa4lscIFeQ/YbAjVo
11+
g5nEVbqRUCSLy6F6JSX6SJB4ng/JMHzKLfhAUSpvotBxZbJ4IpNu06oCKjggiIoR
12+
9z2YE6gR1pBJSyCDS8fJXtyLWN/WBdbvf1fw3t7utPFT606TYFOvt2KrSndcrTwb
13+
EByWHJufxv8J+anrnnNM11RMTqhpi4MeXsaaA7jUCzh5QzxnT8imOyNDF8OVxEKk
14+
Y9W9ToUchHojIJZGJhB2I1ndCUQaJF+OhLrjy2Zk/Imx3wBf3huyWAA8GNVQ04DD
15+
mhDxWdZ30lJgxJH4xgk4l3nWBNAQ+X04lIyRi83tD/E9plX3EX2sWzBBHCSybh0C
16+
bNHAQVMVaxEMTcCumk/USiuRcm4BL0495o4/debn9EExs95dw6pAhJoHZ8kc71GP
17+
YOYNuQvz0Ljbu4ZO1/OgmNDtFuNV83GlDa6yUme/Di0SqmLzxUwPJIZ9I2dNtgLf
18+
2emoUA9PSUl02Hcm5WN7AtmL/Pxz1joR/gKeNAII97PS9WFdqRS0ypwiiwp15mBU
19+
LilEGB4V3laVJFw6sLFwPjWUYZCEhzSdAMnHfxrIZuhpfSi2W39w8Frqwx0JOUoX
20+
HmogsyM/xqn9VelVNbWUP06IwJkcocWM1rzv3nkZOsKb5EhGOk1qrA/BKyajcazX
21+
49x4wpIpJoz4tgStrlgxGZ0DeMT8PIrZGbZDhQ78MxnQe376CiXIOKtrZVOp6uoo
22+
uDtYg9OiZZ2GDoSIgjAStpYbF4rkJI+3kyhR4oD8KfsC/rTG16hNCRnTIIiUECyU
23+
1jWBLmqYWuMTiekb4asB6cWlQYwUUtSBt6ySB+zU+Cl0Wi3u+kXrsMthFnJE0GWB
24+
EOCmHsvMqD+u0uArpJHpE0o9L3ePEkiDssU2MJdOLpb0AKW/uqAA/14a4JAr/y9Z
25+
v+pUPDbjeoIXRNqzXkWEdHKZOnEGAE5QBLzScJqWU0YY7WP1+xpyoYapM37v9V/J
26+
viNJW+gxvW9yZdxKzGm9P/UIjtndx2QnAa7mPgXOej/AMqpl+IkIJmvi13IEQTH2
27+
NuBghACrRp7YuffEroEs3P7fgCoiMHvabCiXkLhWoZqgVuiy72GuSwKEPK8bF30U
28+
8u7lencUvnIRU9jL0kDaQL0kESw0f3dgE+ltQbgew5/rmqMgKpmDDoouLJf95wi2
29+
rvPGRb4QXpBO8V4/8VMPPJKT55ZDygjN45z1gwCZ2tbYtnKUOH82drx1TB2bvrso
30+
-----END RSA PRIVATE KEY-----

0 commit comments

Comments
 (0)