Skip to content

Commit

Permalink
Merge pull request #17 from yahoo/privatekeystore
Browse files Browse the repository at this point in the history
Move PrivateKeyStore interface to auth_core to be common for both servers
  • Loading branch information
havetisyan authored Feb 1, 2017
2 parents cbefbcf + 7bb6792 commit 385ba9c
Show file tree
Hide file tree
Showing 26 changed files with 87 additions and 349 deletions.
7 changes: 3 additions & 4 deletions docs/setup_zms.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* [JDK 8](#jdk-8)
* [Getting Software](#getting-software)
* [Configuration](#configuration)
* [Private/Public Key Pair](#privatepublic-key-pair)
* [Private Key](#private-key)
* [Self Signed X509 Certificate](#self-signed-x509-certificate)
* [User Authentication](#user-authentication)
* [System Administrators](#system-administrators)
Expand Down Expand Up @@ -48,17 +48,16 @@ $ cd athenz-zms-X.Y
To run ZMS Server, the system administrator must generate the keys
and make necessary changes to the configuration settings.

### Private/Public Key Pair
### Private Key
---------------------------

Generate a unique private/public key pair that ZMS Server will use
Generate a unique private key that ZMS Server will use
to sign any NTokens it issues. From the `athenz-zms-X.Y` directory
execute the following commands:

```shell
$ cd var/zms_server/keys
$ openssl genrsa -out zms_private.pem 2048
$ openssl rsa -in zms_private.pem -pubout > zms_public.pem
```

### Self Signed X509 Certificate
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,29 +13,21 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.yahoo.athenz.zms.pkey;
package com.yahoo.athenz.auth;

import java.security.PrivateKey;

public interface PrivateKeyStore {

/**
* Retrieve private key for this ZMS Server instance to sign its tokens
* Retrieve private key for this Athenz Server instance to sign its tokens
* The private key identifier must be updated in the privateKeyId out
* StringBuilder field. The Private Key Store Factory has the knowledge
* which hostname we're processing this request for.
* StringBuilder field.
* @param serverHostName hostname of the Athenz Server instance
* @param privateKeyId - out argument - must be updated to include key id
* @return private key for this ZMS Server instance.
*/
default PrivateKey getPrivateKey(StringBuilder privateKeyId) {
return null;
}

/**
* Retrieve server's corresponding public key in PEM format.
* @return public key in PEM format
*/
default String getPEMPublicKey() {
default PrivateKey getPrivateKey(String serverHostName, StringBuilder privateKeyId) {
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.yahoo.athenz.zms.pkey;
package com.yahoo.athenz.auth;

public interface PrivateKeyStoreFactory {

/**
* Create and return a new PrivateKeyStore instance
* @param serverHostName hostname of the ZMS Server instance
* @return PrivateKeyStore instance
*/
public PrivateKeyStore create(String serverHostName);
public PrivateKeyStore create();
}
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,10 @@ public static String ybase64DecodeString(String b64) {
return utf8String(ybase64Decode(b64));
}

public static String ybase64EncodeString(String str) {
return utf8String(YBase64.encode(utf8Bytes(str)));
}

public static X509Certificate loadX509Certificate(File certFile) throws CryptoException {
try (FileReader fileReader = new FileReader(certFile)) {
return loadX509Certificate(fileReader);
Expand Down Expand Up @@ -1016,16 +1020,16 @@ public static boolean validatePKCS7Signature(String data, String signature, Publ
return false;
}

public static String x509CertificateToPem(X509Certificate cert) {
public static String convertToPEMFormat(Object obj) {
StringWriter writer = new StringWriter();
try {
try (JcaPEMWriter pemWriter = new JcaPEMWriter(writer)) {
pemWriter.writeObject(cert);
pemWriter.writeObject(obj);
pemWriter.flush();
pemWriter.close();
}
} catch (IOException ex) {
LOG.error("x509CertificateToPem: unable to convert X509 cert to PEM: " + ex.getMessage());
LOG.error("convertToPEMFormat: unable to convert object to PEM: " + ex.getMessage());
return null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.yahoo.athenz.zms.pkey;
package com.yahoo.athenz.auth.impl;

import static org.testng.Assert.*;

import java.security.PrivateKey;

import org.testng.annotations.Test;

import com.yahoo.athenz.auth.PrivateKeyStore;

public class PrivateKeyStoreTest {

public class PrivateKeyStoreInstance implements PrivateKeyStore {
Expand All @@ -29,14 +31,8 @@ public class PrivateKeyStoreInstance implements PrivateKeyStore {
public void testGetPrivateKeyMulti() {
PrivateKeyStoreInstance keystore = new PrivateKeyStoreInstance();
StringBuilder sb = new StringBuilder();
PrivateKey key = keystore.getPrivateKey(sb);
PrivateKey key = keystore.getPrivateKey("hostname", sb);
assertNull(key);
}

@Test
public void testGetPEMPublicKey() {
PrivateKeyStoreInstance keystore = new PrivateKeyStoreInstance();
assertNull(keystore.getPEMPublicKey());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,7 @@ public void testGenerateX509CertificateAltNames() throws IOException {
System.out.println("****** Generated Certificate With Alternative Names *********");
System.out.println(cert.toString());
System.out.println("PEM format:");
System.out.println(Crypto.x509CertificateToPem(cert));
System.out.println(Crypto.convertToPEMFormat(cert));
}

@Test
Expand Down Expand Up @@ -457,7 +457,7 @@ public void testGenerateX509CertificateInvalid() throws IOException {
@Test
public void testX509CertificateToPem() {
X509Certificate cert = Crypto.loadX509Certificate(ecPublicX509Cert);
String pem = Crypto.x509CertificateToPem(cert);
String pem = Crypto.convertToPEMFormat(cert);
assertNotNull(pem);
assertTrue(pem.contains("BEGIN CERTIFICATE"), pem);
assertTrue(pem.contains("END CERTIFICATE"), pem);
Expand Down
2 changes: 1 addition & 1 deletion servers/zms/src/main/java/com/yahoo/athenz/zms/ZMS.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@
import org.eclipse.jetty.server.HttpConfiguration;

import com.yahoo.athenz.auth.Authority;
import com.yahoo.athenz.auth.PrivateKeyStoreFactory;
import com.yahoo.athenz.common.metrics.MetricFactory;
import com.yahoo.athenz.common.server.log.AuditLogFactory;
import com.yahoo.athenz.common.server.log.AuditLogMsgBuilder;
import com.yahoo.athenz.common.server.log.AuditLogger;
import com.yahoo.athenz.common.server.rest.Http.AuthorityList;
import com.yahoo.athenz.zms.pkey.PrivateKeyStoreFactory;

import java.net.InetAddress;

Expand Down
16 changes: 8 additions & 8 deletions servers/zms/src/main/java/com/yahoo/athenz/zms/ZMSImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,6 @@ public class ZMSImpl implements Authorizer, KeyStore, ZMSHandler {
protected DBService dbService = null;
protected Class<? extends ProviderClient> providerClass = null;
protected Schema schema = null;
protected String publicKey = null;
protected PrivateKey privateKey = null;
protected String privateKeyId = "0";
protected int userTokenTimeout = 3600;
Expand Down Expand Up @@ -354,13 +353,12 @@ void convertToLowerCase(Object obj) {
static String auditLoggerMsgBldrClass = null;

public ZMSImpl(String serverHostName, ObjectStore dbStore, Metric metric,
PrivateKey privateKey, String privateKeyId, String publicKey,
AuditLogger auditLog, String auditLogMsgBldrClass) {
PrivateKey privateKey, String privateKeyId, AuditLogger auditLog,
String auditLogMsgBldrClass) {

auditLogger = auditLog;
auditLoggerMsgBldrClass = auditLogMsgBldrClass;

this.publicKey = publicKey;
this.privateKey = privateKey;
this.privateKeyId = privateKeyId;
this.schema = ZMSSchema.instance();
Expand Down Expand Up @@ -465,8 +463,9 @@ void loadServerPublicKeys() {
// this should never happen but just in case we'll just
// use the public key we retrieved ourselves to the map

if (serverPublicKeyMap.isEmpty()) {
serverPublicKeyMap.put(privateKeyId, publicKey);
if (serverPublicKeyMap.isEmpty() && privateKey != null) {
final String publicKey = Crypto.convertToPEMFormat(Crypto.extractPublicKey(privateKey));
serverPublicKeyMap.put(privateKeyId, Crypto.ybase64EncodeString(publicKey));
}
}

Expand Down Expand Up @@ -559,9 +558,10 @@ void initObjectStore() {
createSubDomain(null, "sys", "auth", "The AuthNG domain", null, null, adminUsers,
null, 0, null, null, caller);

if (publicKey != null) {
if (privateKey != null) {
List<PublicKeyEntry> pubKeys = new ArrayList<>();
pubKeys.add(new PublicKeyEntry().setId(privateKeyId).setKey(publicKey));
final String publicKey = Crypto.convertToPEMFormat(Crypto.extractPublicKey(privateKey));
pubKeys.add(new PublicKeyEntry().setId(privateKeyId).setKey(Crypto.ybase64EncodeString(publicKey)));
ServiceIdentity id = new ServiceIdentity().setName("sys.auth.zms").setPublicKeys(pubKeys);
dbService.executePutServiceIdentity(null, SYS_AUTH, ZMS_SERVICE, id, null, caller);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@
import com.yahoo.athenz.auth.Authority;
import com.yahoo.athenz.auth.AuthorityKeyStore;
import com.yahoo.athenz.auth.Authorizer;
import com.yahoo.athenz.auth.PrivateKeyStore;
import com.yahoo.athenz.auth.PrivateKeyStoreFactory;
import com.yahoo.athenz.common.metrics.Metric;
import com.yahoo.athenz.common.metrics.MetricFactory;
import com.yahoo.athenz.common.server.db.DataSourceFactory;
import com.yahoo.athenz.common.server.db.PoolableDataSource;
import com.yahoo.athenz.common.server.log.AuditLogger;
import com.yahoo.athenz.common.server.rest.Http.AuthorityList;
import com.yahoo.athenz.zms.pkey.PrivateKeyStore;
import com.yahoo.athenz.zms.pkey.PrivateKeyStoreFactory;
import com.yahoo.athenz.zms.store.ObjectStore;
import com.yahoo.athenz.zms.store.file.FileObjectStore;
import com.yahoo.athenz.zms.store.jdbc.JDBCObjectStore;
Expand All @@ -50,9 +50,8 @@ public ZMSServerImpl(String serverHostName, PrivateKeyStoreFactory pkeyStoreFact
// extract the private key and public keys for our service

StringBuilder privKeyId = new StringBuilder(256);
PrivateKeyStore keyStore = pkeyStoreFactory.create(serverHostName);
PrivateKey pkey = keyStore.getPrivateKey(privKeyId);
String publicKey = keyStore.getPEMPublicKey();
PrivateKeyStore keyStore = pkeyStoreFactory.create();
PrivateKey pkey = keyStore.getPrivateKey(serverHostName, privKeyId);

// create our metric and increment our startup count

Expand All @@ -76,7 +75,7 @@ public ZMSServerImpl(String serverHostName, PrivateKeyStoreFactory pkeyStoreFact

try {
instance = new ZMSImpl(serverHostName, store, metric, pkey, privKeyId.toString(),
publicKey, auditLogger, auditLoggerMsgBldrClass);
auditLogger, auditLoggerMsgBldrClass);
instance.putAuthorityList(authList);
} catch (Exception ex) {
metric.increment("zms_startup_fail_sum");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.yahoo.athenz.auth.PrivateKeyStore;
import com.yahoo.athenz.auth.util.Crypto;
import com.yahoo.athenz.zms.ResourceException;
import com.yahoo.athenz.zms.ZMS;
import com.yahoo.athenz.zms.ZMSConsts;
import com.yahoo.athenz.zms.pkey.PrivateKeyStore;

public class FilePrivateKeyStore implements PrivateKeyStore {

Expand All @@ -37,7 +37,7 @@ public FilePrivateKeyStore() {
}

@Override
public PrivateKey getPrivateKey(StringBuilder privateKeyId) {
public PrivateKey getPrivateKey(String serverHostName, StringBuilder privateKeyId) {

String privKeyName = System.getProperty(ZMSConsts.ZMS_PROP_PRIVATE_KEY,
ZMS.getRootDir() + "/share/athenz/sys.auth/zms.key");
Expand Down Expand Up @@ -67,30 +67,6 @@ public PrivateKey getPrivateKey(StringBuilder privateKeyId) {
return pkey;
}

@Override
public String getPEMPublicKey() {

String pubKeyName = System.getProperty(ZMSConsts.ZMS_PROP_PUBLIC_KEY,
ZMSConsts.STR_DEF_ROOT + "/share/athenz/pubkeys/zms.key");

if (LOG.isDebugEnabled()) {
LOG.debug("FilePrivateKeyStore: public key file=" + pubKeyName);
}

// check to see if this is running in dev mode and thus it's
// a resource in our jar file

String pubKey = null;
if (pubKeyName.startsWith(ZMSConsts.STR_JAR_RESOURCE)) {
pubKey = retrieveKeyFromResource(pubKeyName.substring(ZMSConsts.STR_JAR_RESOURCE.length()));
} else {
File pubKeyFile = new File(pubKeyName);
pubKey = Crypto.encodedFile(pubKeyFile);
}

return pubKey;
}

String retrieveKeyFromResource(String resourceName) {

String key = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@
*/
package com.yahoo.athenz.zms.pkey.file;

import com.yahoo.athenz.zms.pkey.PrivateKeyStore;
import com.yahoo.athenz.zms.pkey.PrivateKeyStoreFactory;
import com.yahoo.athenz.auth.PrivateKeyStore;
import com.yahoo.athenz.auth.PrivateKeyStoreFactory;

public class FilePrivateKeyStoreFactory implements PrivateKeyStoreFactory {

@Override
public PrivateKeyStore create(String serverHostName) {
public PrivateKeyStore create() {
return new FilePrivateKeyStore();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ private ZMSImpl zmsInit() {

Metric debugMetric = new com.yahoo.athenz.common.metrics.impl.NoOpMetric();
ZMSImpl zmsObj = new ZMSImpl("localhost", store, debugMetric, privateKey,
privKeyId, pubKey, AuditLogFactory.getLogger(), null);
privKeyId, AuditLogFactory.getLogger(), null);

ServiceIdentity service = createServiceObject("sys.auth",
"zms", "http://localhost", "/usr/bin/java", "root",
Expand Down Expand Up @@ -305,7 +305,7 @@ ZMSImpl getZmsImpl(String storeDir, AuditLogger alogger) {

Metric debugMetric = new com.yahoo.athenz.common.metrics.impl.NoOpMetric();
ZMSImpl zmsObj = new ZMSImpl("localhost", store, debugMetric, privateKey,
privKeyId, pubKey, alogger, null);
privKeyId, alogger, null);
zmsObj.putServiceIdentity(mockDomRsrcCtx, "sys.auth", "zms", auditRef, service);
zmsObj.setProviderClientClass(ProviderMockClient.class);
return zmsObj;
Expand Down
Loading

0 comments on commit 385ba9c

Please sign in to comment.