Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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 @@ -27,6 +27,7 @@ public class PeerClientPool {
private int clientTimeoutSeconds = 3;
private boolean ssl;
private Certificate certificate;
private boolean sslDisableVerification;
private ForwardingAuthentication authentication;

public PeerClientPool() {
Expand All @@ -49,6 +50,10 @@ public void setCertificate(final Certificate certificate) {
this.certificate = certificate;
}

public void setSslDisableVerification(final boolean sslDisableVerification) {
this.sslDisableVerification = sslDisableVerification;
}

public void setAuthentication(ForwardingAuthentication authentication) {
this.authentication = authentication;
}
Expand All @@ -68,8 +73,12 @@ private WebClient getHTTPClient(final String ipAddress) {
.tlsCustomizer(sslContextBuilder -> sslContextBuilder.trustManager(
new ByteArrayInputStream(certificate.getCertificate().getBytes(StandardCharsets.UTF_8))
)
)
.tlsNoVerifyHosts(ipAddress);
);

if(sslDisableVerification) {
clientFactoryBuilder.tlsNoVerifyHosts(ipAddress);
}

// TODO: Add keyManager configuration here
if (authentication == ForwardingAuthentication.MUTUAL_TLS) {
clientFactoryBuilder.tlsCustomizer(sslContextBuilder -> sslContextBuilder.keyManager(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ public PeerClientPool setPeerClientPool() {
if (ssl || useAcmCertForSsl) {
peerClientPool.setSsl(true);

peerClientPool.setSslDisableVerification(peerForwarderConfiguration.isSslDisableVerification());
peerClientPool.setCertificate(certificateProviderFactory.getCertificateProvider().getCertificate());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public class PeerForwarderConfiguration {
private boolean ssl = false;
private String sslCertificateFile;
private String sslKeyFile;
private boolean sslDisableVerification = false;
private ForwardingAuthentication authentication = ForwardingAuthentication.UNAUTHENTICATED;
private boolean useAcmCertificateForSsl = false;
private String acmCertificateArn;
Expand Down Expand Up @@ -61,6 +62,7 @@ public PeerForwarderConfiguration (
@JsonProperty("ssl") final Boolean ssl,
@JsonProperty("ssl_certificate_file") final String sslCertificateFile,
@JsonProperty("ssl_key_file") final String sslKeyFile,
@JsonProperty("ssl_insecure_disable_verification") final boolean sslDisableVerification,
@JsonProperty("authentication") final Map<String, Object> authentication,
@JsonProperty("use_acm_certificate_for_ssl") final Boolean useAcmCertificateForSsl,
@JsonProperty("acm_certificate_arn") final String acmCertificateArn,
Expand All @@ -86,6 +88,7 @@ public PeerForwarderConfiguration (
setUseAcmCertificateForSsl(useAcmCertificateForSsl);
setSslCertificateFile(sslCertificateFile);
setSslKeyFile(sslKeyFile);
setDisableVerification(sslDisableVerification);
setAuthentication(authentication);
setAcmCertificateArn(acmCertificateArn);
this.acmPrivateKeyPassword = acmPrivateKeyPassword;
Expand Down Expand Up @@ -263,6 +266,14 @@ private void setSslKeyFile(final String sslKeyFile) {
}
}

private void setDisableVerification(final boolean sslDisableVerification) {
this.sslDisableVerification = sslDisableVerification;
}

public boolean isSslDisableVerification() {
return sslDisableVerification;
}

private void setAuthentication(final Map<String, Object> authentication) {
if(authentication == null)
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@

package org.opensearch.dataprepper.peerforwarder;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EnumSource;
import org.junit.jupiter.params.provider.ValueSource;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

Expand All @@ -20,7 +23,11 @@
import org.hamcrest.core.IsInstanceOf;
import org.opensearch.dataprepper.peerforwarder.certificate.CertificateProviderFactory;
import org.opensearch.dataprepper.peerforwarder.discovery.DiscoveryMode;
import org.opensearch.dataprepper.plugins.certificate.CertificateProvider;
import org.opensearch.dataprepper.plugins.certificate.model.Certificate;

import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

Expand Down Expand Up @@ -67,6 +74,43 @@ void testCreatePeerClientPool_should_return() {
assertThat(returnedPeerClientPool, equalTo(peerClientPool));
}

@Nested
class WithSsl {

@Mock
private CertificateProvider certificateProvider;

@Mock
private Certificate certificate;

@BeforeEach
void setUp() {
when(peerForwarderConfiguration.isSsl()).thenReturn(true);
when(certificateProviderFactory.getCertificateProvider()).thenReturn(certificateProvider);

when(certificateProvider.getCertificate()).thenReturn(certificate);
}

@ParameterizedTest
@ValueSource(booleans = { true, false })
void setPeerClientPool_should_supply_sslDisableVerification_when_ssl_true(final boolean sslDisableVerification) {
when(peerForwarderConfiguration.isSslDisableVerification())
.thenReturn(sslDisableVerification);


createObjectUnderTest().setPeerClientPool();

verify(peerClientPool).setSslDisableVerification(sslDisableVerification);
}
}

@Test
void setPeerClientPool_should_not_supply_sslDisableVerification_when_ssl_false() {
createObjectUnderTest().setPeerClientPool();

verify(peerClientPool, never()).setSslDisableVerification(anyBoolean());
}

@ParameterizedTest
@EnumSource(ForwardingAuthentication.class)
void testCreatePeerClientPool_should_set_the_authentication(final ForwardingAuthentication authentication) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ void testPeerForwarderDefaultConfig() throws IOException {
assertThat(peerForwarderConfiguration.getMaxConnectionCount(), equalTo(500));
assertThat(peerForwarderConfiguration.getMaxPendingRequests(), equalTo(1024));
assertThat(peerForwarderConfiguration.isSsl(), equalTo(false));
assertThat(peerForwarderConfiguration.isSslDisableVerification(), equalTo(false));
assertThat(peerForwarderConfiguration.getAcmPrivateKeyPassword(), equalTo(null));
assertThat(peerForwarderConfiguration.isUseAcmCertificateForSsl(), equalTo(false));
assertThat(peerForwarderConfiguration.getDiscoveryMode(), equalTo(DiscoveryMode.LOCAL_NODE));
Expand All @@ -59,6 +60,7 @@ void testValidPeerForwarderConfig() throws IOException {
assertThat(peerForwarderConfiguration.getMaxConnectionCount(), equalTo(100));
assertThat(peerForwarderConfiguration.getMaxPendingRequests(), equalTo(512));
assertThat(peerForwarderConfiguration.isSsl(), equalTo(false));
assertThat(peerForwarderConfiguration.isSslDisableVerification(), equalTo(false));
assertThat(peerForwarderConfiguration.isUseAcmCertificateForSsl(), equalTo(false));
assertThat(peerForwarderConfiguration.getAcmCertificateArn(), equalTo(null));
assertThat(peerForwarderConfiguration.getDiscoveryMode(), equalTo(DiscoveryMode.STATIC));
Expand Down Expand Up @@ -88,6 +90,14 @@ void testValidPeerForwarderConfig_with_Unauthenticated() throws IOException {
assertThat(peerForwarderConfiguration.getAuthentication(), equalTo(ForwardingAuthentication.UNAUTHENTICATED));
}

@Test
void testValidPeerForwarderConfig_with_InsecureTls() throws IOException {
final PeerForwarderConfiguration peerForwarderConfiguration = makeConfig("src/test/resources/valid_peer_forwarder_config_with_insecure.yml");

assertThat(peerForwarderConfiguration.isSsl(), equalTo(true));
assertThat(peerForwarderConfiguration.isSslDisableVerification(), equalTo(true));
}

@Test
void test_with_acm_should_create_PeerForwarderConfiguration_object_even_with_null_files() throws IOException {
final PeerForwarderConfiguration peerForwarderConfiguration = makeConfig(TestDataProvider.VALID_PEER_FORWARDER_WITH_ACM_SSL_CONFIG_FILE);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ class PeerForwarder_ClientServerIT {
private static final String LOCALHOST = "127.0.0.1";
private static final String SSL_CERTIFICATE_FILE = "src/test/resources/test-crt.crt";
private static final String SSL_KEY_FILE = "src/test/resources/test-key.key";
private static final String ALTERNATE_SSL_CERTIFICATE_FILE = "src/test/resources/test-alternate-crt.crt";
private static final String ALTERNATE_SSL_KEY_FILE = "src/test/resources/test-alternate-key.key";
private ObjectMapper objectMapper;
private String pipelineName;
private String pluginId;
Expand Down Expand Up @@ -185,6 +187,20 @@ void send_Events_to_server_when_client_does_not_expect_SSL_should_throw() {
assertThat(receivedRecords, notNullValue());
assertThat(receivedRecords, is(empty()));
}

@Test
void send_Events_to_an_unknown_server_should_throw() {
final PeerForwarderConfiguration peerForwarderConfiguration = createConfiguration(
true, ForwardingAuthentication.UNAUTHENTICATED, ALTERNATE_SSL_CERTIFICATE_FILE, ALTERNATE_SSL_KEY_FILE, false);

final PeerForwarderClient client = createClient(peerForwarderConfiguration);

assertThrows(UnprocessedRequestException.class, () -> client.serializeRecordsAndSendHttpRequest(outgoingRecords, LOCALHOST, pluginId, pipelineName));

final Collection<Record<Event>> receivedRecords = getServerSideRecords(peerForwarderProvider);
assertThat(receivedRecords, notNullValue());
assertThat(receivedRecords, is(empty()));
}
}

@Nested
Expand Down Expand Up @@ -300,7 +316,7 @@ void send_Events_to_server() {
}

@Test
void send_Events_to_server_without_client_certificate_closes() {
void send_Events_to_server_when_client_has_no_certificate_closes() {
final PeerForwarderConfiguration peerForwarderConfiguration = createConfiguration(false, ForwardingAuthentication.UNAUTHENTICATED);

final PeerForwarderClient client = createClient(peerForwarderConfiguration);
Expand All @@ -313,10 +329,9 @@ void send_Events_to_server_without_client_certificate_closes() {
}

@Test
void send_Events_to_server_with_unknown_certificate_key_closes() {
final String alternateSigningKeyFile = "src/test/resources/test-alternate-key.key";
void send_Events_to_server_when_client_has_unknown_certificate_key_closes() {
final PeerForwarderConfiguration peerForwarderConfiguration = createConfiguration(
true, ForwardingAuthentication.MUTUAL_TLS, alternateSigningKeyFile);
true, ForwardingAuthentication.MUTUAL_TLS, SSL_CERTIFICATE_FILE, ALTERNATE_SSL_KEY_FILE, true);

final PeerForwarderClient client = createClient(peerForwarderConfiguration);
assertThrows(UnprocessedRequestException.class, () -> client.serializeRecordsAndSendHttpRequest(outgoingRecords, LOCALHOST, pluginId, pipelineName));
Expand All @@ -325,16 +340,32 @@ void send_Events_to_server_with_unknown_certificate_key_closes() {
assertThat(receivedRecords, notNullValue());
assertThat(receivedRecords, is(empty()));
}

@Test
void send_Events_to_an_unknown_server_should_throw() {
final PeerForwarderConfiguration peerForwarderConfiguration = createConfiguration(
true, ForwardingAuthentication.MUTUAL_TLS, ALTERNATE_SSL_CERTIFICATE_FILE, SSL_KEY_FILE, true);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Is the key supposed to be ALTERNATE_SSL_KEY_FILE here?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, but I see how this is confusing. I am intentionally using the trusted key. But, I'm configuring the client to trust the alternate key.


final PeerForwarderClient client = createClient(peerForwarderConfiguration);

assertThrows(UnprocessedRequestException.class, () -> client.serializeRecordsAndSendHttpRequest(outgoingRecords, LOCALHOST, pluginId, pipelineName));

final Collection<Record<Event>> receivedRecords = getServerSideRecords(peerForwarderProvider);
assertThat(receivedRecords, notNullValue());
assertThat(receivedRecords, is(empty()));
}
}

private PeerForwarderConfiguration createConfiguration(final boolean ssl, final ForwardingAuthentication authentication) {
return createConfiguration(ssl, authentication, SSL_KEY_FILE);
return createConfiguration(ssl, authentication, SSL_CERTIFICATE_FILE, SSL_KEY_FILE, true);
}

private PeerForwarderConfiguration createConfiguration(
final boolean ssl,
final ForwardingAuthentication authentication,
final String sslKeyFile) {
final String sslCertificateFile,
final String sslKeyFile,
final boolean sslDisableVerification) {
final Map<String, Object> authenticationMap = Collections.singletonMap(authentication.getName(), null);
return new PeerForwarderConfiguration(
21890,
Expand All @@ -343,8 +374,9 @@ private PeerForwarderConfiguration createConfiguration(
500,
1024,
ssl,
SSL_CERTIFICATE_FILE,
sslCertificateFile,
sslKeyFile,
sslDisableVerification,
authenticationMap,
false,
null,
Expand Down
37 changes: 20 additions & 17 deletions data-prepper-core/src/test/resources/test-alternate-crt.crt
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
-----BEGIN CERTIFICATE-----
MIIDDjCCAfYCCQCXNkX+YubACjANBgkqhkiG9w0BAQsFADBJMQswCQYDVQQGEwJV
UzELMAkGA1UECAwCVFgxDzANBgNVBAcMBkF1c3RpbjENMAsGA1UECgwEVGVzdDEN
MAsGA1UECwwEVGVzdDAeFw0yMjA5MTUxNDE5MzJaFw0yNTA5MTQxNDE5MzJaMEkx
CzAJBgNVBAYTAlVTMQswCQYDVQQIDAJUWDEPMA0GA1UEBwwGQXVzdGluMQ0wCwYD
VQQKDARUZXN0MQ0wCwYDVQQLDARUZXN0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
MIIBCgKCAQEArGuHRKJ+CVk2i4P7KCRC95imo5z0RaMm0Cq32FvvHas+rpe95fk0
Er4I4QRhJBAAqtpUfM1dyimSkRoHrAWPf8uOfdbejhu3LdawSKFNeOnp+2XG7iCq
MD22JOplHe8SKva1SgI1CMa2gwTDC9TxMsNejep6tKOSxR0S5K4Zau95LARWpWqx
gPpQLnGwVAiproCd9Z/YdTMAex8GlGif1DlUGd0rFCWWbaUpWwf9AzN020hPbXhM
bC/KUw6n3P01uFmR0Q7WYld/CENPm3XPvENF9UGeJ/Yv708Ik7hTiBs98Il1uXZt
a7mkJMntdPefTGrITcWo/dchP1ZORZMSTQIDAQABMA0GCSqGSIb3DQEBCwUAA4IB
AQANWSdgBJbBtx6DL3/3RU1g4gIieNaa5xQyFPV74uWlO11w+8GmzPccq1KfziwW
e3u0+clbGCsh0nliOIwo991PAFAnQmdHlM5EZOcVPyV0HbD1BDxzocUahpUolZpI
b2Kq8adPXNx7Yhf3fpRbT26STzQW8I+TJlPvaElb/CambrADHKZATX02Km4eFub0
diRMMaeY+7VqDUJYnFodJhGdnlELyEppFlmZ/bij3y3yGVGhL1zJ5Dhq2KyugzV0
vhcgYsnmdLaNzeVvmeYlmk8M0oPnfVRteaXqvfprqYwxG5evmLQwsRzNMBD5hE4t
Y9IMxWvIMcWsN5tnl/uaNtNe
MIIDmzCCAoOgAwIBAgIJAMKu9LwFOkU3MA0GCSqGSIb3DQEBCwUAMHAxDTALBgNV
BAcMBHRlc3QxGTAXBgNVBAoMEEV4YW1wbGUgQ29tIEluYy4xITAfBgNVBAsMGEV4
YW1wbGUgQ29tIEluYy4gUm9vdCBDQTEhMB8GA1UEAwwYZGF0YS1wcmVwcGVyLmV4
YW1wbGUuY29tMB4XDTIyMDkxNjIwMTA1N1oXDTI1MDkxNTIwMTA1N1owcDENMAsG
A1UEBwwEdGVzdDEZMBcGA1UECgwQRXhhbXBsZSBDb20gSW5jLjEhMB8GA1UECwwY
RXhhbXBsZSBDb20gSW5jLiBSb290IENBMSEwHwYDVQQDDBhkYXRhLXByZXBwZXIu
ZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDbhCNi
QVoglNi7whmU0gYaxPPxN5ulo+p/D3gx4LHTc7FtR9ibaAG78Q/Rbrx3+sS/fASv
dC7N6x6lHyN8+Iv/Pt99+ySaZ7pXXmF4Bh3IR9mB7ivsMuLLulyd8roZp/MfCxLw
RJi8EXQVMuWu2ENmMrOvaxlSgsh4lH0f63ursI3xHvk+tm/kSoj2oyxDWaHZBzUu
HD1Y78o6YCUk7gZ3Qd3lTQhnvRoMIfxu8Ii06755cWJybjfUYXFCEFBdSH9a46sx
4L78lTBOyzGblId35T2VZ8+hQF9r+Vi1eCn2vgyJbAWfS9wihfb3TIQpVyJ0Vl7t
tSV5vFoiRBO+TiBVAgMBAAGjODA2MDQGA1UdEQQtMCuCGGRhdGEtcHJlcHBlci5l
eGFtcGxlLmNvbYIJbG9jYWxob3N0hwR/AAABMA0GCSqGSIb3DQEBCwUAA4IBAQCC
QkdbXlko/vDAYkdDP+gh1ChtLm4MhMC4o1FlOfnhUCXrU/1+xZYgD11xcBoxarLV
4Ud7K+OVxtVlUIr3bVBkcDCgtip+hJB1lnIJev41eBzqas4dyXVv+frmv4HiDV78
r8/Fhvd2Lpb2yTUsERSKKi3dGbOxH4GKKGag8yYbM0k9nDisiDODfASomIJH4IPw
7DjxWALMyVhyBEZ8c6v+hIA78vibzoRYVE+ogVk+rN7IwB6IXHnJZqVkWeSTZxrE
fcwIPf7Iw3TaOunij85BhXCgrstWPLy+ISr0RbCXGYwY1bO2gP+YWw7n1jKEGXIF
xgsDqCFWqdIPyXflkWXW
-----END CERTIFICATE-----
52 changes: 26 additions & 26 deletions data-prepper-core/src/test/resources/test-alternate-key.key
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCsa4dEon4JWTaL
g/soJEL3mKajnPRFoybQKrfYW+8dqz6ul73l+TQSvgjhBGEkEACq2lR8zV3KKZKR
GgesBY9/y4591t6OG7ct1rBIoU146en7ZcbuIKowPbYk6mUd7xIq9rVKAjUIxraD
BMML1PEyw16N6nq0o5LFHRLkrhlq73ksBFalarGA+lAucbBUCKmugJ31n9h1MwB7
HwaUaJ/UOVQZ3SsUJZZtpSlbB/0DM3TbSE9teExsL8pTDqfc/TW4WZHRDtZiV38I
Q0+bdc+8Q0X1QZ4n9i/vTwiTuFOIGz3wiXW5dm1ruaQkye10959MashNxaj91yE/
Vk5FkxJNAgMBAAECggEBAI3aveSTB7zrQDwSru08wDfyyI7tz+8HJyS3MKB6KsWv
IRgF0f/GQrh0zttKfh1saRAoJsCzOcnc4DAvSUaXIJPUxnvz7xDd7pxw+IIY66Ni
V9Y0yzEZgMvFyfifO+gfzEO6zDaCkF2TF4+9uDcgz/yizkVWN/Qsa9FudR/duR3H
Y1aAihcszm2Ikhchz7w1z77ouL1ZWLHs0i7X6jNfIL8jy1H4WT/m/JCEemo8sxyj
6YmdXyUIZvl8h/kylKrY9XRncXdmwkWu+NbWYm5e5wUvfz0REnO1vx19xt2WuyMC
BrulT9rwGIub47edG83O/n6ps4s5MPCaqjYWUIQLpgUCgYEA5TdEmc1/6UMCvhzN
aijsg3/VmmDd8nbylpBSCZaOXiftOYQVXAMd+X2vaB8vL4sKo2MAP5yJcYmaFMFW
mhEgntw4glHCFsxqUequplNnFXmMtC0E12aoMARa+ikFq8iv3a1cmJwl/+2gr5ro
JLTBL5gi7HOxN2BBuRLprmBsNvcCgYEAwJFG71t3dWBBkpLXS5XqT6Cx+dyjv9B3
LNGL4DfcQnNOXcwEVC0o4kNjo8FySjQfWaQLACuGPs3sqNAggewZ993R4sN+BfOd
aN+AWAhPpxpBET2ZLURpRbD1bnbdIrzTimWAiG4xucmRQ7dgdvR+CF0m2I6lptNp
edAiA4lsG9sCgYB+rfjf988Fn99YKprsXQm582CeHYMMieiwhbqRSgAM0YwuCW20
mJRsWqYiqXlukS2j9wcgIOdlNGNPrTqrk2Ov6I3imEToTLlF5Kn5ioaiO7cjrO3M
DhRN1Vpif2F++z8XCMTwIvxtYWs5IifCgZNzNmW2wInkzPIF0woLMYcdKQKBgH7+
T92CYKGTvSrAlCNQ1pl0zGqPS54wCKgR+UEBFczs5f2Nkj1BGvk8n/Vamdi9zv76
5BZUnc/FVhFuUEHeRrHkI4p8ihu6sVB8NNPZh04YTljkWqQzvYksTm9vDB7gkFFw
5vcSVNDFUXtq778DNiql4/xk9nGycpjW3defRSCJAoGARgu/z25yVd4XruyHLMDr
qohh9dPuSZtUl5KIL4VgRl/MqKANEmcJyuDw3hzglDFYcXJPpRP6T/8Uu/8TZcJJ
JTIV2R/ELWTprQFS+dW0ard3nKmith+igf1p60OZgzZNI+8vRgeGK6tokaCKTvox
jYuXGLtjzeDasKQxfBNTOkU=
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDbhCNiQVoglNi7
whmU0gYaxPPxN5ulo+p/D3gx4LHTc7FtR9ibaAG78Q/Rbrx3+sS/fASvdC7N6x6l
HyN8+Iv/Pt99+ySaZ7pXXmF4Bh3IR9mB7ivsMuLLulyd8roZp/MfCxLwRJi8EXQV
MuWu2ENmMrOvaxlSgsh4lH0f63ursI3xHvk+tm/kSoj2oyxDWaHZBzUuHD1Y78o6
YCUk7gZ3Qd3lTQhnvRoMIfxu8Ii06755cWJybjfUYXFCEFBdSH9a46sx4L78lTBO
yzGblId35T2VZ8+hQF9r+Vi1eCn2vgyJbAWfS9wihfb3TIQpVyJ0Vl7ttSV5vFoi
RBO+TiBVAgMBAAECggEAM1PmYicdx9iGBQERsjaZrtC2qYRzJHv7bNJVLHR5oBPB
POg7wbrEDQoExNe7weIk9xEsl0n3V7bOZ5WsWqBTO8+bun1qxZ/TdnJfIA1uEVKb
jUH/iy8q0LA2z8fds/oNYwjX2M5xWChMmFhaVFPFDrR0R2Qne5+Q+IDf8QLC3BXx
d3RnvOfIgY4JrM1BVenFJbmo31kaC9Mh/G5GhsBG+eUrqpFH47Fl15JZriMPmtT6
6iznBijXHAdjVmJzpf0e5GzwHAORS0kmY3z+wKSqnjQKAVCCT6IK6wUx6EFU2zyB
bnDiNqXwCcgJVaxq7FFWrWuoXRHykFcmej+Y/tdv0QKBgQDyXVa8RxlHgPNOb4C9
8LrzRrtDUmkw/HzA2q7m5jC/D5y1EZmUL9CGaMoFTkIH/BMoFhhSTE91RzuSOCC/
pi9TulmjC/3ZJK5jH/IRd3ABBFTInZAuqVt64YiqeYH+utYmwIJmKJzEjYFtH1+8
mkhaPTdZpF7FCjWl5IHzcPQnKwKBgQDn3blquCPIeWqv45Gn8DQ/hQTNJ8c0o90f
Klzt+SEmoAqjUYNvDon8mesW3E8d7PVb7os6MkjFRs7gvyFyxWK6ZxLxnNZQLalu
BBdvKm8LpiwEnZa/57eLP0MXdOhifMS8xd3q+1Ndnhq9EX9QIiGknoZMtVof+tL4
HD7DpPMWfwKBgQDO2BI6RYOxnsAH5Om/MUCcd3VCk4brI9Fk1j4HGdXoee6IKikk
a1pQHAauWIfKQLworhK7yhzWPqD8vaJVbgNeNeBiYs2XENM0DgOOHJ0egQ/K145C
BI/qY6k7tM/ZEqPKFuozPd3tccdP1kLit9mgCja+7qVjDL+UgVzW40O8WQKBgDce
GwSGb2MpkbXsF+TfEdyDp2eJbC5UQa016c9cKIhBBSZbqy3MO/sDL8JIbrpDaPQI
maok5+2Vbno4lR/uUhDTjcpHqR54LE2NxXBUmv8e6lnSiFJoJ9Z/HFjIHrHCzRW+
x4kjY2bevaZyMVyAMJUsZep4NctiWaJHPJhPbsXLAoGBANerxrMxkKxnWBSCHonj
cUBiqyrvd63FHcqhzMqdzbmbN42ihe4VfS1F7FiuBKZc6RkV0SbqxFomqbL9QpcO
XSpTINMH/6/aZ2oSvLPVThvU/u7nFKLOJynM4qjhjmIuO/TFXAOEgX0e1QsJ0Z9T
7mdGVyKjWNDN6mUIrigT4KvT
-----END PRIVATE KEY-----
Loading