Skip to content

Commit

Permalink
Add Athenz unit tests (apache#314)
Browse files Browse the repository at this point in the history
  • Loading branch information
nkurihar authored and merlimat committed Mar 24, 2017
1 parent 80986d7 commit 7dbd596
Show file tree
Hide file tree
Showing 13 changed files with 387 additions and 8 deletions.
5 changes: 3 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ flexible messaging model and an intuitive client API.</description>
<netty.version>4.0.40.Final</netty.version>
<storm.version>0.9.5</storm.version>
<jetty.version>9.3.11.v20160721</jetty.version>
<athenz.version>1.1.8</athenz.version>

</properties>

Expand Down Expand Up @@ -394,13 +395,13 @@ flexible messaging model and an intuitive client API.</description>
<dependency>
<groupId>com.yahoo.athenz</groupId>
<artifactId>zts_java_client</artifactId>
<version>1.1.3</version>
<version>${athenz.version}</version>
</dependency>

<dependency>
<groupId>com.yahoo.athenz</groupId>
<artifactId>zpe_java_client</artifactId>
<version>1.1.3</version>
<version>${athenz.version}</version>
</dependency>

</dependencies>
Expand Down
10 changes: 9 additions & 1 deletion pulsar-broker-auth-athenz/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,15 @@
<artifactId>pulsar-broker</artifactId>
<version>${project.version}</version>
</dependency>


<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>managed-ledger</artifactId>
<version>${project.version}</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>

<dependency>
<groupId>com.yahoo.athenz</groupId>
<artifactId>zpe_java_client</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
/**
* Copyright 2016 Yahoo Inc.
*
* 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
*
* http://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 com.yahoo.pulsar.broker.authentication;

import static org.testng.Assert.assertEquals;
import static org.testng.Assert.fail;
import org.testng.annotations.Test;
import org.testng.annotations.BeforeClass;

import org.apache.bookkeeper.test.PortManager;

import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.net.InetSocketAddress;
import java.nio.file.Files;
import java.nio.file.Paths;
import javax.naming.AuthenticationException;

import com.yahoo.athenz.zpe.ZpeConsts;
import com.yahoo.athenz.auth.token.RoleToken;

import com.yahoo.pulsar.broker.authentication.AuthenticationProviderAthenz;
import com.yahoo.pulsar.broker.authentication.AuthenticationDataSource;
import com.yahoo.pulsar.broker.authentication.AuthenticationDataCommand;
import com.yahoo.pulsar.broker.ServiceConfiguration;

public class AuthenticationProviderAthenzTest {

ServiceConfiguration config;
Properties properties;
AuthenticationProviderAthenz provider;

@BeforeClass
public void setup() throws Exception {

// Set provider domain name
properties = new Properties();
properties.setProperty("athenzDomainNames", "test_provider");
config = new ServiceConfiguration();
config.setProperties(properties);

// Initialize authentication provider
provider = new AuthenticationProviderAthenz();
provider.initialize(config);

// Specify Athenz configuration file for AuthZpeClient which is used in AuthenticationProviderAthenz
System.setProperty(ZpeConsts.ZPE_PROP_ATHENZ_CONF, "./src/test/resources/athenz.conf");
}

@Test
public void testAuthenticateSignedToken() throws Exception {

List<String> roles = new ArrayList<String>() {
{
add("test_role");
}
};
RoleToken token = new RoleToken.Builder("Z1", "test_provider", roles).principal("test_app").build();
String privateKey = new String(Files.readAllBytes(Paths.get("./src/test/resources/zts_private.pem")));
token.sign(privateKey);
AuthenticationDataSource authData = new AuthenticationDataCommand(token.getSignedToken(),
new InetSocketAddress("localhost", PortManager.nextFreePort()), null);
assertEquals(provider.authenticate(authData), "test_app");
}

@Test
public void testAuthenticateUnsignedToken() throws Exception {

List<String> roles = new ArrayList<String>() {
{
add("test_role");
}
};
RoleToken token = new RoleToken.Builder("Z1", "test_provider", roles).principal("test_app").build();
AuthenticationDataSource authData = new AuthenticationDataCommand(token.getUnsignedToken(),
new InetSocketAddress("localhost", PortManager.nextFreePort()), null);
try {
provider.authenticate(authData);
fail("Unsigned token should not be authenticated");
} catch (AuthenticationException e) {
// OK, expected
}
}

@Test
public void testAuthenticateSignedTokenWithDifferentDomain() throws Exception {

List<String> roles = new ArrayList<String>() {
{
add("test_role");
}
};
RoleToken token = new RoleToken.Builder("Z1", "invalid", roles).principal("test_app").build();
String privateKey = new String(Files.readAllBytes(Paths.get("./src/test/resources/zts_private.pem")));
token.sign(privateKey);
AuthenticationDataSource authData = new AuthenticationDataCommand(token.getSignedToken(),
new InetSocketAddress("localhost", PortManager.nextFreePort()), null);
try {
provider.authenticate(authData);
fail("Token which has different domain should not be authenticated");
} catch (AuthenticationException e) {
// OK, expected
}
}
}
16 changes: 16 additions & 0 deletions pulsar-broker-auth-athenz/src/test/resources/athenz.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"zmsUrl": "https://server-zms.athenzcompany.com:4443/",
"ztsUrl": "https://server-zts.athenzcompany.com:4443/",
"ztsPublicKeys": [
{
"id": "0",
"key": "LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUEydkZ4S0wvLzJBdm9zTlhEN3VqUQpkQmlQSWIxOVNFWUJ6MVY1SlBlL3VlczF0b1UybVQrU1pPRUt4dlBDMGY5dHkrNVA3VkVPNHljenpHVGJCQVdoCnJoTXVSYktrcTNWREVYbjlRR3pUR3VTaGd1UXdsRFVUakcvdXBhUHZUMHpaUTRaOUdXeEZrRkdzOG5WelN6R1cKVVdKaEJhWjNRaERhTnVhcHBXYS80KzQzZkh1ZXA2cEhldUxTa3FYSmNtdlBmcEtCVUNWMk9HOGdHZkd0TkNOQgpWU1F3ZG4yK3Y4OUUvZzJ6dEhPeCtxampsTWtJUzJxdHRWMjJzUEFsTjZnYmZrWWZDZWc4RWdyVHdoRzF6aWc2CnExNlNyazRGQjV1UjRjaVpBTFFMRVIzTUZ4U1ZlMXorbk1LUjJFSnRNSkE2VDcvZjdEdHBWOU14RGZrSUlWTXEKSXdJREFRQUIKLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tCg--"
}
],
"zmsPublicKeys": [
{
"id": "0",
"key": "LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUEydkZ4S0wvLzJBdm9zTlhEN3VqUQpkQmlQSWIxOVNFWUJ6MVY1SlBlL3VlczF0b1UybVQrU1pPRUt4dlBDMGY5dHkrNVA3VkVPNHljenpHVGJCQVdoCnJoTXVSYktrcTNWREVYbjlRR3pUR3VTaGd1UXdsRFVUakcvdXBhUHZUMHpaUTRaOUdXeEZrRkdzOG5WelN6R1cKVVdKaEJhWjNRaERhTnVhcHBXYS80KzQzZkh1ZXA2cEhldUxTa3FYSmNtdlBmcEtCVUNWMk9HOGdHZkd0TkNOQgpWU1F3ZG4yK3Y4OUUvZzJ6dEhPeCtxampsTWtJUzJxdHRWMjJzUEFsTjZnYmZrWWZDZWc4RWdyVHdoRzF6aWc2CnExNlNyazRGQjV1UjRjaVpBTFFMRVIzTUZ4U1ZlMXorbk1LUjJFSnRNSkE2VDcvZjdEdHBWOU14RGZrSUlWTXEKSXdJREFRQUIKLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tCg--"
}
]
}
27 changes: 27 additions & 0 deletions pulsar-broker-auth-athenz/src/test/resources/zts_private.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEA2vFxKL//2AvosNXD7ujQdBiPIb19SEYBz1V5JPe/ues1toU2
mT+SZOEKxvPC0f9ty+5P7VEO4yczzGTbBAWhrhMuRbKkq3VDEXn9QGzTGuShguQw
lDUTjG/upaPvT0zZQ4Z9GWxFkFGs8nVzSzGWUWJhBaZ3QhDaNuappWa/4+43fHue
p6pHeuLSkqXJcmvPfpKBUCV2OG8gGfGtNCNBVSQwdn2+v89E/g2ztHOx+qjjlMkI
S2qttV22sPAlN6gbfkYfCeg8EgrTwhG1zig6q16Srk4FB5uR4ciZALQLER3MFxSV
e1z+nMKR2EJtMJA6T7/f7DtpV9MxDfkIIVMqIwIDAQABAoIBAQC3byobtiEoZXHj
FnY+KBjd6+Wfox7f+qdxim8hJeEgZ4xtC1cfNj/0/QcGgRxszNC010lnz03lyuZ/
DNDiocVADxnpky6b6Hb0oXwpCgQkuAEJpR1+Tqm+M9mCNcM+cWhmRrtxHWF69LMt
wHGEQltqfD5FeZ7ZXz00WjUwOtHyqAoGB/a4ncffsJ2ZNOjhDsOMZJEHyPGw4EpO
VGQlqnxVab2CGBfb6YUgjm80KBvA4in+x9e78bOnVCim/K8QdceajszRaqwKqbl9
f6N064bXXbXp7k+uXoa5XY24DXZyD/+iW5NxVNZbCakqDkfDDgZuB4NeCf+ri2y6
cMs2Oo2hAoGBAPdaYrKYf6ARquR0/rGS641ZwJ1VTZwYNjnsHpepBO04NoTYJQH+
MSR1ZMUIM2IbfIBaz/eYksvAjeZUoGakU8fSXoK6WEXTPq/Bsv743t1UF1jU5Hra
/1UmvdGhToE1heO88/fqns9tZrCT7fr16sMfuLcnnr2W3Tw7tEt0ckHHAoGBAOKY
z12OgJHAkeODtYSlTEecrcwgK4ZhtarTEGkQfI32vlMb/6im+t2Xbqd1G7QlFLoN
tZlE3HjmSOeG8BBF6XJsOXv4xUFIv3ob9z401QMjmSWPd2hJAMVbQfKrRCA2FmE5
8TgSPi0r49oDfRMhM0S9pGxFgpdTU0bLmoQ1pRTFAoGAf8jpDjzsSgR2lbm/TnuJ
Ryfj8yP7iTWU5g2OrGj8C5UrzStgywvH1X70RTn8WaW7hw/jOpVO2QYsCJ8VkpE4
WxXaD403RzNfwiq+TyzA7fSgbxrkwnday2HNVHwR83x0I/gczaoeyyhIkdaKbkkX
NCCyK6TDREypFJH/ja+ly0cCgYAvL2Dm+3icYTw/4zpWP9GNi/vI6N4HYqtgwgjF
yBAXw8zII6luJi9RG2qIZmN5dMtHHvm0y9kZN+Lwi3HMAbLmB9FEln4E5TAyLkai
5n+A4tXOM3zK84C8mA84iB9skbbBUj5/zZSy9VPCHz3ZUO2LH+5wOV1DQ6+wq08m
vsD8fQKBgHksKLATUbzKv3/Vz9cnNeL5hACwJHW/7Azn8r1ywjcOl+w7yftAS9x+
k0NNkWuk1H9bwhVkqYtJyJYy1MVk8IB8SMViR3EVo06Kl2g8r5ABgWXaaxXRnoxo
AFqPsqowd35TsMRN+6ypjiMTppYoIiOODpUNCNeJVZ/0ykzHegnq
-----END RSA PRIVATE KEY-----
9 changes: 9 additions & 0 deletions pulsar-broker-auth-athenz/src/test/resources/zts_public.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2vFxKL//2AvosNXD7ujQ
dBiPIb19SEYBz1V5JPe/ues1toU2mT+SZOEKxvPC0f9ty+5P7VEO4yczzGTbBAWh
rhMuRbKkq3VDEXn9QGzTGuShguQwlDUTjG/upaPvT0zZQ4Z9GWxFkFGs8nVzSzGW
UWJhBaZ3QhDaNuappWa/4+43fHuep6pHeuLSkqXJcmvPfpKBUCV2OG8gGfGtNCNB
VSQwdn2+v89E/g2ztHOx+qjjlMkIS2qttV22sPAlN6gbfkYfCeg8EgrTwhG1zig6
q16Srk4FB5uR4ciZALQLER3MFxSVe1z+nMKR2EJtMJA6T7/f7DtpV9MxDfkIIVMq
IwIDAQAB
-----END PUBLIC KEY-----
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,11 @@ private boolean cachedRoleTokenIsValid() {

@Override
public void configure(Map<String, String> authParams) {
this.tenantDomain = authParams.get("tenant_domain");
this.tenantService = authParams.get("tenant_service");
this.providerDomain = authParams.get("provider_domain");
this.privateKeyPath = authParams.get("private_key_path");
this.keyId = authParams.getOrDefault("key_id", "0");
this.tenantDomain = authParams.get("tenantDomain");
this.tenantService = authParams.get("tenantService");
this.providerDomain = authParams.get("providerDomain");
this.privateKeyPath = authParams.get("privateKeyPath");
this.keyId = authParams.getOrDefault("keyId", "0");
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/**
* Copyright 2016 Yahoo Inc.
*
* 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
*
* http://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 com.yahoo.pulsar.client.impl.auth;

import static org.testng.Assert.assertEquals;
import org.testng.annotations.Test;
import org.testng.annotations.BeforeClass;

import java.io.IOException;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.yahoo.athenz.zts.RoleToken;
import com.yahoo.athenz.zts.ZTSClient;
import com.yahoo.pulsar.client.api.AuthenticationDataProvider;

public class AuthenticationAthenzTest {

private AuthenticationAthenz auth;
private static final String TENANT_DOMAIN = "test_tenant";
private static final String TENANT_SERVICE = "test_service";
private static final String PROVIDER_DOMAIN = "test_provider";
private static final String PRIVATE_KEY_PATH = "./src/test/resources/tenant_private.pem";

@BeforeClass
public void setup() throws Exception {

// Configure parameters
Map<String, String> params = new HashMap<String, String>() {
{
put("tenantDomain", TENANT_DOMAIN);
put("tenantService", TENANT_SERVICE);
put("providerDomain", PROVIDER_DOMAIN);
put("privateKeyPath", PRIVATE_KEY_PATH);
}
};
auth = new AuthenticationAthenz();
auth.configure(params);

// Set mock ztsClient which returns fixed token instead of fetching from ZTS server
Field field = auth.getClass().getDeclaredField("ztsClient");
field.setAccessible(true);
ZTSClient mockZtsClient = new ZTSClient("dummy") {
@Override
public RoleToken getRoleToken(String domainName, String roleName, Integer minExpiryTime,
Integer maxExpiryTime, boolean ignoreCache) {

List<String> roles = new ArrayList<String>() {
{
add("test_role");
}
};
com.yahoo.athenz.auth.token.RoleToken roleToken = new com.yahoo.athenz.auth.token.RoleToken.Builder(
"Z1", domainName, roles).principal(String.format("%s.%s", TENANT_DOMAIN, TENANT_SERVICE))
.build();

try {
String ztsPrivateKey = new String(
Files.readAllBytes(Paths.get("./src/test/resources/zts_private.pem")));
roleToken.sign(ztsPrivateKey);
} catch (IOException e) {
return null;
}

RoleToken token = new RoleToken();
token.setToken(roleToken.getSignedToken());

return token;
}

};
field.set(auth, mockZtsClient);
}

@Test
public void testGetAuthData() throws Exception {

com.yahoo.athenz.auth.token.RoleToken roleToken = new com.yahoo.athenz.auth.token.RoleToken(
auth.getAuthData().getCommandData());
assertEquals(roleToken.getPrincipal(), String.format("%s.%s", TENANT_DOMAIN, TENANT_SERVICE));

int count = 0;
for (Map.Entry<String, String> header : auth.getAuthData().getHttpHeaders()) {
if (header.getKey() == ZTSClient.getHeader()) {
com.yahoo.athenz.auth.token.RoleToken roleTokenFromHeader = new com.yahoo.athenz.auth.token.RoleToken(
header.getValue());
assertEquals(roleTokenFromHeader.getPrincipal(), String.format("%s.%s", TENANT_DOMAIN, TENANT_SERVICE));
count++;
}
}
assertEquals(count, 1);
}
}
16 changes: 16 additions & 0 deletions pulsar-client-auth-athenz/src/test/resources/athenz.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"zmsUrl": "https://server-zms.athenzcompany.com:4443/",
"ztsUrl": "https://server-zts.athenzcompany.com:4443/",
"ztsPublicKeys": [
{
"id": "0",
"key": "LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUEydkZ4S0wvLzJBdm9zTlhEN3VqUQpkQmlQSWIxOVNFWUJ6MVY1SlBlL3VlczF0b1UybVQrU1pPRUt4dlBDMGY5dHkrNVA3VkVPNHljenpHVGJCQVdoCnJoTXVSYktrcTNWREVYbjlRR3pUR3VTaGd1UXdsRFVUakcvdXBhUHZUMHpaUTRaOUdXeEZrRkdzOG5WelN6R1cKVVdKaEJhWjNRaERhTnVhcHBXYS80KzQzZkh1ZXA2cEhldUxTa3FYSmNtdlBmcEtCVUNWMk9HOGdHZkd0TkNOQgpWU1F3ZG4yK3Y4OUUvZzJ6dEhPeCtxampsTWtJUzJxdHRWMjJzUEFsTjZnYmZrWWZDZWc4RWdyVHdoRzF6aWc2CnExNlNyazRGQjV1UjRjaVpBTFFMRVIzTUZ4U1ZlMXorbk1LUjJFSnRNSkE2VDcvZjdEdHBWOU14RGZrSUlWTXEKSXdJREFRQUIKLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tCg--"
}
],
"zmsPublicKeys": [
{
"id": "0",
"key": "LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUEydkZ4S0wvLzJBdm9zTlhEN3VqUQpkQmlQSWIxOVNFWUJ6MVY1SlBlL3VlczF0b1UybVQrU1pPRUt4dlBDMGY5dHkrNVA3VkVPNHljenpHVGJCQVdoCnJoTXVSYktrcTNWREVYbjlRR3pUR3VTaGd1UXdsRFVUakcvdXBhUHZUMHpaUTRaOUdXeEZrRkdzOG5WelN6R1cKVVdKaEJhWjNRaERhTnVhcHBXYS80KzQzZkh1ZXA2cEhldUxTa3FYSmNtdlBmcEtCVUNWMk9HOGdHZkd0TkNOQgpWU1F3ZG4yK3Y4OUUvZzJ6dEhPeCtxampsTWtJUzJxdHRWMjJzUEFsTjZnYmZrWWZDZWc4RWdyVHdoRzF6aWc2CnExNlNyazRGQjV1UjRjaVpBTFFMRVIzTUZ4U1ZlMXorbk1LUjJFSnRNSkE2VDcvZjdEdHBWOU14RGZrSUlWTXEKSXdJREFRQUIKLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tCg--"
}
]
}
27 changes: 27 additions & 0 deletions pulsar-client-auth-athenz/src/test/resources/tenant_private.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEAr/PizSm8V5RuRs3axyMtrZ7WehRKzugEIA/WGzswAg2JKBr3
f4nRAQ7akvumkA6YuTf/kbCTJ+iumHl2vxYnlz8Ie7q/3r9tfGz+E5Dpe61tlFI8
gshYb7JBeSH6uFzZkBUg+Dzu8LgNnXXLZ9ReglCz/fiX57n6JftOqvsZ/y1lRETy
QzIegeiqGaxQbnfizI2sY/wzCKRqhYyU09BCY7lYTs8JDhrMO9Ru+LFJdItET5OF
+kGpW6YbVprLKjEqiYfVfjASMjcQtH7gIouwFGYvFjpt9hkDETHvoXVGP1kMVZ5A
ljX5C7vjePqLQcW08I/s/7QPmZUfYfnVK3aPPwIDAQABAoIBAEarO8KPKrg6Q3ho
oaAtvuDm1Nm/YLRtd4qxEZtqUEPiz92txw4QekNkheFW9XUSh8CMfzcypkf3KnjP
ACSLb2dNx8h6HyoF1KGO3RVatIwaAdL6nJcihHKIM8fFIAAAOtmlwtIxFv7TzZQa
hZG0OCk65K/ysoA9r/ylTNlbdPuJw223KznoUkArBpCs2fiTfkAnmfTIgp70yDT5
863jmFEyNs2hLH/ATCQ92GXO87V84qm715tS5b2m5fyz3F8n55JRD3zJHXpSCFOy
2byccyLqkijwt1RYMJ0R4El2P+y5DFlhda8Z88YWi2GQHNM1CeDQIo/4CS92akhp
ZqRfjSECgYEA3Nn+wrIKgcs2onPmqC6nCIPrNDTq96CTIJvzuyINoPjZscpc2yoJ
SJTjRFcIm6uoGjh90LkyYoAUncMNmNsTmkWwTveZn5XHZ2LTIr/zzNpZ3h/Nj+Iq
IoGDZv1tcbfB8GpsnsIiPf8Kamt93GyYUbFzDQeHybrQFaJI5cWjrRkCgYEAy/Sb
Vb1aTQ4s6q/za4wIGyhYxFoR4TcsKMUG4XAFhZ0ciItVADq8dEy5/wFdvL0TF1o5
5OEZ2RaJ7W0FEKrsZxqKWB29HVJ3nFj5H3vb32uh8gtipyMDO8avgzhhmrrkxKLW
JE2S+ShUou42z0jHQdmTiNh2GWi+DrhmYxjQUhcCgYAsREWcILOacHDy/ugsra0t
N8PdIv41xCm5T4j66UhyC28XA8i45SQXOECVYhyHl1CKcOhG/dfrhmCbfo0rJj43
neBI87gHFK5zOou3W2IynVGGBDnfrSVk5TDBY+qb8Ike9zXuXFsgsg4UZpdDp0Cg
n0DAS9IbzSYIMA8MfyDfgQKBgGJmgmcscxvIIg2clGGn7uVDYwhguE2jc8+7t2Ue
yds8AN8z8e+pZvDpb7dDbnk387UJl/MAU5s0T5lYRuBSxrm7yVFYD7zM495v4sm4
1U0Gvdxsd81RjCbT5iv2EMk5MFRah9x9/NHvDl6JdbIuV8xCb/bPELOToFazyto2
x5NDAoGAYmyTx+SUlwEDDg5y1iViIkEtR/oWSkjolQV0QkkHLYY0LYKnlyFTQJuM
V3Ft5459ZpOWDp6kPbY+HfdjGXJRUriBz5vUUL8vQO+JE/bIAJrME2wLQNixN4pI
fvMA/BjAjxHWp4PsVjehEzpxPbM1t1mN2rU1EPdoXQJisFbN2eY=
-----END RSA PRIVATE KEY-----
Loading

0 comments on commit 7dbd596

Please sign in to comment.