Skip to content

Commit

Permalink
Enable SSL in reindex with security QA tests (#38293)
Browse files Browse the repository at this point in the history
Update the x-pack/qa/reindex-tests-with-security integration tests to
run with TLS enabled on the Rest interface.

Backport of: #37600
Relates: #37527
  • Loading branch information
tvernum authored Feb 4, 2019
1 parent 448acaf commit 3e2da3c
Show file tree
Hide file tree
Showing 10 changed files with 240 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -709,7 +709,8 @@ protected static void configureClient(RestClientBuilder builder, Settings settin
throw new IllegalStateException(TRUSTSTORE_PATH + " is set but points to a non-existing file");
}
try {
KeyStore keyStore = KeyStore.getInstance("jks");
final String keyStoreType = keystorePath.endsWith(".p12") ? "PKCS12" : "jks";
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
try (InputStream is = Files.newInputStream(path)) {
keyStore.load(is, keystorePass.toCharArray());
}
Expand Down
77 changes: 69 additions & 8 deletions x-pack/qa/reindex-tests-with-security/build.gradle
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
import javax.net.ssl.HttpsURLConnection
import javax.net.ssl.KeyManager
import javax.net.ssl.SSLContext
import javax.net.ssl.TrustManagerFactory
import java.nio.charset.StandardCharsets
import java.security.KeyStore
import java.security.SecureRandom

apply plugin: 'elasticsearch.standalone-rest-test'
apply plugin: 'elasticsearch.rest-test'

Expand All @@ -9,13 +17,31 @@ dependencies {
testCompile project(path: ':modules:reindex')
}

forbiddenPatterns {
exclude '**/*.key'
exclude '**/*.pem'
exclude '**/*.p12'
exclude '**/*.jks'
}

File caFile = project.file('src/test/resources/ssl/ca.p12')

integTestCluster {
// Whitelist reindexing from the local node so we can test it.
extraConfigFile 'http.key', project.projectDir.toPath().resolve('src/test/resources/ssl/http.key')
extraConfigFile 'http.crt', project.projectDir.toPath().resolve('src/test/resources/ssl/http.crt')
extraConfigFile 'ca.p12', caFile
setting 'reindex.remote.whitelist', '127.0.0.1:*'
setting 'xpack.ilm.enabled', 'false'
setting 'xpack.security.enabled', 'true'
setting 'xpack.ml.enabled', 'false'
setting 'xpack.license.self_generated.type', 'trial'
setting 'xpack.security.http.ssl.enabled', 'true'
setting 'xpack.security.http.ssl.certificate', 'http.crt'
setting 'xpack.security.http.ssl.key', 'http.key'
setting 'xpack.security.http.ssl.key_passphrase', 'http-password'
setting 'reindex.ssl.truststore.path', 'ca.p12'
setting 'reindex.ssl.truststore.password', 'password'
extraConfigFile 'roles.yml', 'roles.yml'
[
test_admin: 'superuser',
Expand All @@ -31,13 +57,48 @@ integTestCluster {
'bin/elasticsearch-users', 'useradd', user, '-p', 'x-pack-test-password', '-r', role
}
waitCondition = { node, ant ->
File tmpFile = new File(node.cwd, 'wait.success')
ant.get(src: "http://${node.httpUri()}/_cluster/health?wait_for_nodes=>=${numNodes}&wait_for_status=yellow",
dest: tmpFile.toString(),
username: 'test_admin',
password: 'x-pack-test-password',
ignoreerrors: true,
retries: 10)
return tmpFile.exists()
// Load the CA PKCS#12 file as a truststore
KeyStore ks = KeyStore.getInstance("PKCS12");
ks.load(caFile.newInputStream(), 'password'.toCharArray());
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(ks);

// Configre a SSL context for TLS1.2 using our CA trust manager
SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
sslContext.init(new KeyManager[0], tmf.getTrustManagers(), new SecureRandom());

// Check whether the cluster has started
URL url = new URL("https://${node.httpUri()}/_cluster/health?wait_for_nodes=${numNodes}&wait_for_status=yellow");
for (int i = 20; i >= 0; i--) {
// we use custom wait logic here for HTTPS
HttpsURLConnection httpURLConnection = null;
try {
logger.info("Trying ${url}");
httpURLConnection = (HttpsURLConnection) url.openConnection();
httpURLConnection.setSSLSocketFactory(sslContext.getSocketFactory());
httpURLConnection.setRequestProperty("Authorization",
"Basic " + Base64.getEncoder().encodeToString("test_admin:x-pack-test-password".getBytes(StandardCharsets.UTF_8)));
httpURLConnection.setRequestMethod("GET");
httpURLConnection.connect();
if (httpURLConnection.getResponseCode() == 200) {
logger.info("Cluster has started");
return true;
} else {
logger.debug("HTTP response was [{}]", httpURLConnection.getResponseCode());
}
} catch (IOException e) {
if (i == 0) {
logger.error("Failed to call cluster health - " + e)
}
logger.debug("Call to [{}] threw an exception", url, e)
} finally {
if (httpURLConnection != null) {
httpURLConnection.disconnect();
}
}
// did not start, so wait a bit before trying again
Thread.sleep(750L);
}
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,27 @@

import com.carrotsearch.randomizedtesting.annotations.Name;
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;

import org.elasticsearch.common.io.PathUtils;
import org.elasticsearch.common.settings.SecureString;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.util.concurrent.ThreadContext;
import org.elasticsearch.test.rest.yaml.ClientYamlTestCandidate;
import org.elasticsearch.test.rest.yaml.ESClientYamlSuiteTestCase;
import org.junit.AfterClass;
import org.junit.BeforeClass;

import java.io.FileNotFoundException;
import java.net.URL;
import java.nio.file.Path;

import static org.elasticsearch.xpack.core.security.authc.support.UsernamePasswordToken.basicAuthHeaderValue;

public class ReindexWithSecurityClientYamlTestSuiteIT extends ESClientYamlSuiteTestCase {
private static final String USER = "test_admin";
private static final String PASS = "x-pack-test-password";

private static Path httpTrustStore;

public ReindexWithSecurityClientYamlTestSuiteIT(@Name("yaml") ClientYamlTestCandidate testCandidate) {
super(testCandidate);
}
Expand All @@ -29,6 +37,25 @@ public static Iterable<Object[]> parameters() throws Exception {
return ESClientYamlSuiteTestCase.createParameters();
}

@BeforeClass
public static void findTrustStore( ) throws Exception {
final URL resource = ReindexWithSecurityClientYamlTestSuiteIT.class.getResource("/ssl/ca.p12");
if (resource == null) {
throw new FileNotFoundException("Cannot find classpath resource /ssl/ca.p12");
}
httpTrustStore = PathUtils.get(resource.toURI());
}

@AfterClass
public static void cleanupStatics() {
httpTrustStore = null;
}

@Override
protected String getProtocol() {
return "https";
}

/**
* All tests run as a an administrative user but use <code>es-security-runas-user</code> to become a less privileged user.
*/
Expand All @@ -37,6 +64,8 @@ protected Settings restClientSettings() {
String token = basicAuthHeaderValue(USER, new SecureString(PASS.toCharArray()));
return Settings.builder()
.put(ThreadContext.PREFIX + ".Authorization", token)
.put(TRUSTSTORE_PATH , httpTrustStore)
.put(TRUSTSTORE_PASSWORD, "password")
.build();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
body:
source:
remote:
host: http://${host}
host: https://${host}
username: test_admin
password: x-pack-test-password
index: source
Expand Down Expand Up @@ -63,7 +63,7 @@
body:
source:
remote:
host: http://${host}
host: https://${host}
username: minimal_user
password: x-pack-test-password
index: source
Expand Down Expand Up @@ -109,7 +109,7 @@
body:
source:
remote:
host: http://${host}
host: https://${host}
username: readonly_user
password: x-pack-test-password
index: source
Expand Down Expand Up @@ -154,7 +154,7 @@
body:
source:
remote:
host: http://${host}
host: https://${host}
username: dest_only_user
password: x-pack-test-password
index: source
Expand Down Expand Up @@ -196,7 +196,7 @@
body:
source:
remote:
host: http://${host}
host: https://${host}
username: test_admin
password: x-pack-test-password
index: source
Expand Down Expand Up @@ -255,7 +255,7 @@
body:
source:
remote:
host: http://${host}
host: https://${host}
username: can_not_see_hidden_docs_user
password: x-pack-test-password
index: source
Expand Down Expand Up @@ -312,7 +312,7 @@
body:
source:
remote:
host: http://${host}
host: https://${host}
username: can_not_see_hidden_fields_user
password: x-pack-test-password
index: source
Expand Down Expand Up @@ -377,7 +377,7 @@
body:
source:
remote:
host: http://${host}
host: https://${host}
username: test_admin
password: badpass
index: source
Expand Down Expand Up @@ -413,7 +413,7 @@
body:
source:
remote:
host: http://${host}
host: https://${host}
index: source
dest:
index: dest
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
= Keystore Details
This document details the steps used to create the certificate and keystore files in this directory.

== Instructions on generating certificates
The certificates in this directory have been generated using elasticsearch-certutil (7.0.0 SNAPSHOT)

[source,shell]
-----------------------------------------------------------------------------------------------------------
elasticsearch-certutil ca --pem --out=ca.zip --pass="ca-password" --days=3500
unzip ca.zip
mv ca/ca.* ./
-----------------------------------------------------------------------------------------------------------

[source,shell]
-----------------------------------------------------------------------------------------------------------
elasticsearch-certutil cert --pem --name=http --out=http.zip --pass="http-password" --days=3500 \
--ca-cert=ca.crt --ca-key=ca.key --ca-pass="ca-password" \
--dns=localhost --dns=localhost.localdomain --dns=localhost4 --dns=localhost4.localdomain4 --dns=localhost6 --dns=localhost6.localdomain6 \
--ip=127.0.0.1 --ip=0:0:0:0:0:0:0:1
unzip http.zip
mv http/http.* ./
-----------------------------------------------------------------------------------------------------------

[source,shell]
-----------------------------------------------------------------------------------------------------------
keytool -importcert -file ca.crt -keystore ca.p12 -storetype PKCS12 -storepass "password" -alias ca
-----------------------------------------------------------------------------------------------------------
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
-----BEGIN CERTIFICATE-----
MIIDSjCCAjKgAwIBAgIVAMp4ojQbvgxx3HBRFHadTvCjFn1+MA0GCSqGSIb3DQEB
CwUAMDQxMjAwBgNVBAMTKUVsYXN0aWMgQ2VydGlmaWNhdGUgVG9vbCBBdXRvZ2Vu
ZXJhdGVkIENBMB4XDTE4MTIxMzA2MDU0OVoXDTI4MDcxMzA2MDU0OVowNDEyMDAG
A1UEAxMpRWxhc3RpYyBDZXJ0aWZpY2F0ZSBUb29sIEF1dG9nZW5lcmF0ZWQgQ0Ew
ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCDtMpBiqR2EaLHC8jNojf9
G4xlqFYj+pLzQidPHQlmqEDYYpSUmSVxh2GT7f6VQ7acdlFecSIfbvngGE94aBFB
sSQwzrjk0Bgq3+31nQDdM9DwHPQxYWdq20mxs0qztfpV0BfzsS4hdTHVK3ZvtaN8
D+FTTvugM/e/PZxEXa2yFVt7GfCe2mF6DLvJpm86Eeyfr9HPZc6QK2vKaNkeaFSr
WFyovb8ivLb6yGMQva/fnQRAJNLZi0YnsMwUhn/Xe1MyfeRyLmkLvF+Q3XwiYInt
0721DMUH4VYaQ2EV76g3v0mxvbCdHMCRVudvlqiO3y4AXyq9RDJ5f3AZIEX8aBAr
AgMBAAGjUzBRMB0GA1UdDgQWBBTln4o7tJW/VyYSNJXbgrYYnIR3czAfBgNVHSME
GDAWgBTln4o7tJW/VyYSNJXbgrYYnIR3czAPBgNVHRMBAf8EBTADAQH/MA0GCSqG
SIb3DQEBCwUAA4IBAQB8AzUs0DIVmuasZoN5ftBOzNB2XUHI3p95Yju3lF+9E0i4
ZyAjqcQoNaDSHrd9bzhmQuLiPmN+dPEwGNhlg5ddclthfwY4qy+IxoIUM6L/vFlF
ApPx+XZK3zZtv/kXqjz8ZWA8Qj4BVWOo3XK4HodJkoMDIkhWPQXlA8BEJDNUnirl
8HTlibnihKvzGmZHEWvgm6YrUyS4YknUvafROW/EUm4Gl4zniFuLG8VVN/2dbJmy
v2xMsqji8Pf+2ZnZ/aXS0bg4hzGyPBljoifEI7lj0twg5zpEXeCZJ7BgsoFicgve
iYZV9yrDBHognEbFAIywiK3+GXrqAkvB/OQiGCTM
-----END CERTIFICATE-----
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,2DF8E98BAAF74EB5

Y5r4e8s5XV7aUr12V0PSfr1+67J+Ao6fAG0fjxM0M7Qv3IIghS9OdW0YKoWc8h8e
tlJbSrEAnpvopROqCXh860XCdGrDwwTKVEnazgvXb64+CIcVuZXK/HesrBiQIUwz
O/rZKN8HKtM5KTfVqpCtNsCu6TDenkHUEz5uOaG3p3/rvhFtsGp/4PGt5slYt/Z8
g5J0EJeLwRgJaRVR70/3LhmUryZxM4TPMvHjCU7GI4YbXzFzp8qbRSujWr4/l5qm
4Piid3pyxN1L47TviB6jRWt7XZrOcvr7Glqjuz0ak9beUyidL3QUJAgZGQD9O6zj
iPaGI/9AF01fAo9J8N7LDmGacPz9dvpvIsXOXfz+7COtXhKki2VqEx/XwWHz2opw
82uMj59bSBrCzf+Y417G60Me/mPuYdxiqRoFKsszrsH7HiQgQroBM/X8Trq6OmXc
CGDsYO0tUT0xYVFoW1j3rMGh4wV9z5G3LSKFtO54uHdGUmJUSFATcwOnME9acUUj
jG9qCn/dIkXjKIZ/jwaaA65GG/P60VGOJG+AjHbiBbEPXD/IA++Y4X2M2H4jvQrr
oG7bLD4Zaa/B88Jv7ymZh88SCZpYqd0I96G5DSzlzoNpqLwhNmcdy+ViSIqlFfD9
HpbQwT0mQJeUPj8KmXtOl2GVunwNkdBEaRURXiD4l9CPCmFXGb1RKt02RY6Nvf6X
w9/SvipGsCaGbALoQb1UvKiL7JqU9eYoslYb84A+abbPQtiy7MBZqbyhNQ2PI2ct
FV1z+h5GV/wzI1y+CWeCJWhjysShMBNv/eOfp8iStkIqI7M+2qKHyzMusqZxov3Y
8QgcQqbDSR/mWZ4Kl1/h/RC+qPy20bgeYAT5VvXhBasu7Mzq+5qiZ+T9FK/nTkq6
xLMYGLbFe2tRWJMBxeHVu/YuG8gwjWVrhalfFmWeh2skqPIeymGpTxU42XUaI4zr
7CVoyWalnMYZWbGculaVFutSyIlqshY0w56PXVpt5usow968rTw+Nf8YeQ/pLFi4
r0fteQSOEXdwGgy8/fcvhzaPbgJfTcIbaRgP89q/HORYDjm/P03jHXmiT11ZeF84
pqtGRTJqCbL7n/vc/5gXdvYt88alxEn9sIyhNugpXWp9EJefnyUscxI036wbBK4O
sNSewqIpp+kGn/Xf/PqfkKQVZkA9YacMcPiKoGVYExoujukfeHwZ/jq7geOqYa+H
+NPUd5VS8lxX/lhAt3Nit97UnJ2oQvbHsV/+eJ65/1e41hS0h1xpzd4HLhDoQEfV
Q0L+1h9cbwU/IyUXK+4fr4nUNolSYNzXfurGKDLVtjFpR+naupr2CwQU7gKHKikF
7GuogsTbtK9L3jkIla/lYTqKiJlz/vA6erTmI06aENt0DnnVKPaQZhJ8571lKmRV
xe+e56R4s0AZBOpZjykkr7hDWQ2QGwbgKOYHF9KRl/yQZwD1ezRu3feSUdPkRrLY
efPH24L0jEampqIhx4XGFbhYX/WnuvneA2oiswmB4zR4YT2F8PeMw4gd3t0nGljz
U/NbbQ7P5ZP8JjQbHecSIZf262mHCGuWtnul9T4DjTubyD3LO6AXxw==
-----END RSA PRIVATE KEY-----
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
-----BEGIN CERTIFICATE-----
MIIDszCCApugAwIBAgIVAImurbHhcSbc4LTPdTawV03y+KXtMA0GCSqGSIb3DQEB
CwUAMDQxMjAwBgNVBAMTKUVsYXN0aWMgQ2VydGlmaWNhdGUgVG9vbCBBdXRvZ2Vu
ZXJhdGVkIENBMB4XDTE4MTIxNDA1MDcwNloXDTI4MDcxNDA1MDcwNlowDzENMAsG
A1UEAxMEaHR0cDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAI5zBwHm
5kwiV3tYlOl0AEruYNUjRfYwQ2OtBIILCgnu0USMx4r1I6IoHDuLl9Z197I1UfSF
c49hG5U82gAFtWblYoITPkzW50sSB7un/rehXkwTIMbl0i024rWQfGGj6uGHmlU4
T+2YWZNksdGEWx7pcG9WZ4r7rjCy7A0SbewhHmD9SxxZgfsW2UI1bu/iXKC8cb7L
DYBnYCDiYheAA3zOPm1zIB12BDsMuFBF4vIEHlxwOH9pH8jC6vuSEnMqTct81uN9
6EwhPvEixrklffj3XDDYYQzoyF3yiabBt3PTm5v56IadcxjQZT/S5fGBuApTLfdV
w6aCzxTa0vEx0k0CAwEAAaOB4DCB3TAdBgNVHQ4EFgQUwQ35Nzes5weOuudemw3z
MK9ZlkcwHwYDVR0jBBgwFoAU5Z+KO7SVv1cmEjSV24K2GJyEd3MwgY8GA1UdEQSB
hzCBhIIJbG9jYWxob3N0ghdsb2NhbGhvc3Q2LmxvY2FsZG9tYWluNocEfwAAAYcQ
AAAAAAAAAAAAAAAAAAAAAYIKbG9jYWxob3N0NIIKbG9jYWxob3N0NoIVbG9jYWxo
b3N0LmxvY2FsZG9tYWlughdsb2NhbGhvc3Q0LmxvY2FsZG9tYWluNDAJBgNVHRME
AjAAMA0GCSqGSIb3DQEBCwUAA4IBAQBQ7B6jdsMjT7qHQJV68kVdrJwDLekpWPvQ
f+YgPZaWkQoVI7rpBJGm7ZY49RI61JLA1SDxjHS3wL3EYRo1FuXwQj6K/h9wxrpn
is1Ib9IewxeueGhi0DMr+Wf5Nh6cDC7I0Uftr2NJsmwivZV9ZlECjckpIZjwIHpb
imtb27MBcVzWjVLL+NLDa2upuVVYdeiuIcbpMqjOFW7mn6/FczgbMjg8zOQG7+fF
pUEduOJDkmxLe14aKagqyaZDMpX1g1CiM3V899/kYXMPPP9F5f7WOg0+QGfBSig3
3KNPfiQyaIeIePhtRC4iPgP1WI5QaiOVd0GwNwp1W39GeJv6/Wit
-----END CERTIFICATE-----
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,73350501C44BDD9D

3LAGS/e2rkuTBIyIVhFEFy/uG4gUJlJ+5rBTYkmxIfZWkUin+yEoThvJsYptiXCr
hjDIXhZkob2NVfEae9KRW6rETs/7ZwZfR5XpgeYbre8/JyfEo0I5QvcatZMAJ6Gz
3UEXnjIxrowg3voRW12oa6ppa8K1zwfr5y7GscCuJvL/eBp+/TkFAtCbcLwnvUBI
rZ3VjsUO5VvElRgmttI8L9zyt6KJA2laM6D/DZW25JYa++BNkFMBxP7DiEl+fmGL
x1d+ozHVxcxVANO/UrtkvBqyF5M9S69vbz0XSCZX/oV/a0IuzzHiZy0YnK2TPKZw
V6IgFPACzBoh4NSL/BKFmbw5jefQ11n80bGgQL7ijaKp0+1CdDo+0/My6RnpbbGK
lcKpPLTtkSL7/xD3YMbFZ/XbXBu14j8G5zZ3rD+QMYle+tVOJz5TALSEhqWZraS4
eNnjUaodChAzolZep6fIL3lyy/2rWs0QmWxLR92NjfSp8C2yw2c0X9FrsTXiCiWS
N+1+Pd3j+IRH0r+p9BPvTWRIXHotm6MmhOhyQarj4+6bE6JYcQST7bu4d9c2ng9c
VyWNWh0MgVMeBxIZ5EIbX8oZSOHhAQco0lqazydNc5t2A4KzvSrkog4EH7Bm4Tqc
b0YiqL4A7Ars0qzVRngd+/Xmpzx+zJKTRw/klb3RzsfGmrzgcdMqLJh9vcwV74Et
m7M5+q8wwyQkj+u1c8YS9bqCbo7R3aw8iImg9AGiP0Tx646AspUUm9FO7SnASxb1
e5+Hen0ggrMlX3iopUBHApmhkPYODKTlh0JyyVFidnDAJ5QV4RhAiTGdRE7GQMuv
2E9NnOk6Tkag5QAMiI9i8IhfMF3805OJAmvoindRT2cLYy1EjK42ohhkIOuD1SK/
15NbNFe32f2QuHlkpk8xpj2yzJwk/tBBGAUqmmB1MjP1xnVrLlGPp/Dowq7lU6zk
iH+jzIL2EAIMjfHLarJAhVzzmY+hpotUTku5iBzYDIwjL8k9nB44WnYhkTJhqp6G
IF85G31SXo5qUXguZ31/yZoaepmi26uZH+737V4ni39JuI/5KXqZCrlkfO0IkSZH
X0Lmzgg5m6gVvilCdN67CYz4Px433/tj89FNyKqBodo2v7WekkHCvZEo52skwgCm
t5C/G4HZeGui8DErK3e+ePZd5aQ6KdVMMBZF46MpAgakLRtgHO63AjI9U8SjohwP
7AnVRaK7dTnueMW/00FdtK1QGBdeLcuiWdEKUs4NBrl00SuAXgadaeGkRuOtqOBx
0aKfKtRlFHQ2shUR8eixKwtGx1awQ25xo4HMfI8xk+waN4ieWiMNjNaXGUHLYF7f
qIxURNS/RSzpQevoDHg/lYzgiVtvqgEmH8mjURHq91MU9iM0qn7i05Yn33zFl5y9
AHavhhM8qFDJ14LefTEAx39aJ0ZdeskBVPzYpXv6qlA4uDscJkOUuDG2vJxIlSnb
GeM1yqmbCrtYqJv5ygfNTQ+xycnwZAcRcxkdjenJ1XJscj8T2jUJAfL7qEUp+fMO
AodfQLZL40THoCy6AFZlFSy2mvr1yZ995Z7dyq30HpJE7BqH/z/4HpMn1rjTT/aE
-----END RSA PRIVATE KEY-----

0 comments on commit 3e2da3c

Please sign in to comment.