Skip to content

Commit

Permalink
Finish up x509/ssh cert signer separation (#550)
Browse files Browse the repository at this point in the history
  • Loading branch information
havetisyan authored Sep 17, 2018
1 parent 244698f commit dfa696a
Show file tree
Hide file tree
Showing 22 changed files with 284 additions and 598 deletions.
5 changes: 5 additions & 0 deletions clients/go/zts/model.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions clients/go/zts/zts_schema.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 14 additions & 0 deletions core/zts/src/main/java/com/yahoo/athenz/zts/SSHCertRequest.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
//

package com.yahoo.athenz.zts;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.yahoo.rdl.*;

//
Expand All @@ -11,6 +12,9 @@
public class SSHCertRequest {
public SSHCertRequestData certRequestData;
public SSHCertRequestMeta certRequestMeta;
@RdlOptional
@JsonInclude(JsonInclude.Include.NON_EMPTY)
public String csr;

public SSHCertRequest setCertRequestData(SSHCertRequestData certRequestData) {
this.certRequestData = certRequestData;
Expand All @@ -26,6 +30,13 @@ public SSHCertRequest setCertRequestMeta(SSHCertRequestMeta certRequestMeta) {
public SSHCertRequestMeta getCertRequestMeta() {
return certRequestMeta;
}
public SSHCertRequest setCsr(String csr) {
this.csr = csr;
return this;
}
public String getCsr() {
return csr;
}

@Override
public boolean equals(Object another) {
Expand All @@ -40,6 +51,9 @@ public boolean equals(Object another) {
if (certRequestMeta == null ? a.certRequestMeta != null : !certRequestMeta.equals(a.certRequestMeta)) {
return false;
}
if (csr == null ? a.csr != null : !csr.equals(a.csr)) {
return false;
}
}
return true;
}
Expand Down
3 changes: 2 additions & 1 deletion core/zts/src/main/java/com/yahoo/athenz/zts/ZTSSchema.java
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,8 @@ private static Schema build() {

sb.structType("SSHCertRequest")
.field("certRequestData", "SSHCertRequestData", false, "ssh certificate request data")
.field("certRequestMeta", "SSHCertRequestMeta", false, "ssh certificate request meta");
.field("certRequestMeta", "SSHCertRequestMeta", false, "ssh certificate request meta")
.field("csr", "String", true, "free-form csr if not using data/meta fields.");

sb.structType("SSHCertificate")
.field("certificate", "String", false, "the SSH certificate, signed by the CA")
Expand Down
1 change: 1 addition & 0 deletions core/zts/src/main/rdl/SSHCert.rdli
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ type SSHCertRequestMeta Struct {
type SSHCertRequest Struct {
SSHCertRequestData certRequestData; //ssh certificate request data
SSHCertRequestMeta certRequestMeta; //ssh certificate request meta
String csr (optional); //free-form csr if not using data/meta fields.
}

type SSHCertificate Struct {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,9 @@ public void testSSHCertRequest() {
data1.setPublicKey("publickey1");
data2.setPublicKey("publickey2");

req1.setCsr("csr1");
assertEquals("csr1", req1.getCsr());

req1.setCertRequestData(data1);
assertEquals(data1, req1.getCertRequestData());

Expand All @@ -191,6 +194,12 @@ public void testSSHCertRequest() {
assertNotEquals(req1, req2);

meta2.setRequestor("req1");
assertNotEquals(req1, req2);

req2.setCsr("csr2");
assertNotEquals(req1, req2);

req2.setCsr("csr1");
assertEquals(req1, req2);

assertNotEquals(null, req1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,24 +41,6 @@ default String getCACertificate() {
return null;
}

/**
* Generate an SSH Certificate based on the given request
* @param csr SSH Certificate Request
* @return SSH Certificate
*/
default String generateSSHCertificate(String csr) {
return null;
}

/**
* Retrieve the SSH Signer certificate for the given type
* @param type signer type user or host
* @return SSH Signer Certificate
*/
default String getSSHCertificate(String type) {
return null;
}

/** Retrieve the certificate max expiry time supported
* by the given signer
* @return expiry time in minutes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,22 +27,24 @@ public interface SSHSigner {
* for a given principal
* @param principal Principal requesting the ssh certificates
* @param certRequest SSH Certificate Request
* @param instanceId Instance ID of the origin host
* @param certType requested certificate type: user or host or null. If null,
* no verification is necessary otherwise the implementation
* must verify that the certRequest matches the requested type.
* @return SSH Certificates. Any error conditions are handled
* by throwing com.yahoo.athenz.common.rest.ResourceExceptions
*/
default SSHCertificates generateCertificate(Principal principal, SSHCertRequest certRequest,
final String instanceId) {
final String certType) {
return null;
}

/**
* Retrieve the SSH Signer certificate for the given type
* @param type signer type: user or host
* @param certType signer type: user or host
* @return SSH Signer Certificate. Any error conditions are handled
* by throwing com.yahoo.athenz.common.rest.ResourceExceptions
*/
default String getSignerCertificate(String type) {
default String getSignerCertificate(String certType) {
return null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,15 @@ public void testSSHSigner() {
SSHCertRequest certRequest = new SSHCertRequest();
Principal principal = Mockito.mock(Principal.class);
SSHCertificates certs = new SSHCertificates();
Mockito.when(signer.generateCertificate(principal, certRequest, "id")).thenReturn(certs);
Mockito.when(signer.generateCertificate(principal, certRequest, "user")).thenReturn(certs);
Mockito.when(signer.getSignerCertificate("user")).thenReturn("ssh-cert");

SSHSignerFactory factory = () -> signer;

SSHSigner testSigner = factory.create();
assertNotNull(testSigner);

assertEquals(certs, testSigner.generateCertificate(principal, certRequest, "id"));
assertEquals(certs, testSigner.generateCertificate(principal, certRequest, "user"));
assertEquals("ssh-cert", testSigner.getSignerCertificate("user"));
testSigner.close();
}
Expand Down
23 changes: 6 additions & 17 deletions servers/zts/src/main/java/com/yahoo/athenz/zts/ZTSImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@
import com.yahoo.athenz.zts.cert.InstanceCertManager;
import com.yahoo.athenz.zts.cert.X509CertRecord;
import com.yahoo.athenz.zts.cert.X509CertRequest;
import com.yahoo.athenz.zts.cert.impl.X509CertUtils;
import com.yahoo.athenz.zts.store.ChangeLogStore;
import com.yahoo.athenz.zts.store.ChangeLogStoreFactory;
import com.yahoo.athenz.zts.store.CloudStore;
Expand Down Expand Up @@ -1232,11 +1231,6 @@ public RoleToken getRoleToken(ResourceContext ctx, String domainName, String rol
+ " not authorized for proxy role token request", caller, ZTSConsts.ZTS_UNKNOWN_DOMAIN);
}

AuditLogMsgBuilder msgBldr = getAuditLogMsgBuilder(ctx, domainName, caller, HTTP_GET);
msgBldr.when(Timestamp.fromCurrentTime().toString()).
whatEntity("RoleToken").why("zts-audit").
whatDetails("RoleName=" + roleName);

// first retrieve our domain data object from the cache

DataCache data = dataStore.getDataCache(domainName);
Expand Down Expand Up @@ -1776,7 +1770,8 @@ public void postInstanceRegisterInformation(ResourceContext ctx, InstanceRegiste
// policy, service, etc name)

AthenzObject.INSTANCE_REGISTER_INFO.convertToLowerCase(info);


Principal principal = ((RsrcCtxWrapper) ctx).principal();
final String domain = info.getDomain();
final String service = info.getService();
final String cn = domain + "." + service;
Expand Down Expand Up @@ -1883,7 +1878,7 @@ public void postInstanceRegisterInformation(ResourceContext ctx, InstanceRegiste
// certificate for the instance as well

Object timerSSHCertMetric = metric.startTiming("certsignssh_timing", null);
instanceCertManager.generateSshIdentity(identity, info.getSsh(), ZTSConsts.ZTS_SSH_HOST);
instanceCertManager.generateSSHIdentity(principal, identity, info.getSsh(), ZTSConsts.ZTS_SSH_HOST);
metric.stopTiming(timerSSHCertMetric);

// set the other required attributes in the identity object
Expand Down Expand Up @@ -2218,7 +2213,7 @@ InstanceIdentity processProviderX509RefreshRequest(ResourceContext ctx, final Pr
// certificate for the instance as well

Object timerSSHCertMetric = metric.startTiming("certsignssh_timing", null);
instanceCertManager.generateSshIdentity(identity, info.getSsh(), null);
instanceCertManager.generateSSHIdentity(principal, identity, info.getSsh(), ZTSConsts.ZTS_SSH_HOST);
metric.stopTiming(timerSSHCertMetric);

// set the other required attributes in the identity object
Expand Down Expand Up @@ -2294,7 +2289,7 @@ InstanceIdentity processProviderSSHRefreshRequest(ResourceContext ctx, final Pri

InstanceIdentity identity = new InstanceIdentity().setName(principalName);
Object timerSSHCertMetric = metric.startTiming("certsignssh_timing", null);
if (!instanceCertManager.generateSshIdentity(identity, sshCsr, null)) {
if (!instanceCertManager.generateSSHIdentity(principal, identity, sshCsr, ZTSConsts.ZTS_SSH_USER)) {
throw serverError("unable to generate ssh identity", caller, domain);
}
metric.stopTiming(timerSSHCertMetric);
Expand Down Expand Up @@ -2603,18 +2598,12 @@ public SSHCertificates postSSHCertRequest(ResourceContext ctx, SSHCertRequest ce
metric.increment(HTTP_REQUEST);
metric.increment(caller, domainName);

// if we have a certificate then we'll try to extract
// the instance id for our request

final String instanceId = X509CertUtils.extractRequestInstanceId(principal.getX509Certificate());

// generate our certificate. the ssh signer interface throws
// rest ResourceExceptions so we'll catch and log those

SSHCertificates certs;
try {
certs = instanceCertManager.getSSHCertificates(principal,
certRequest, instanceId);
certs = instanceCertManager.generateSSHCertificates(principal, certRequest);
} catch (com.yahoo.athenz.common.server.rest.ResourceException ex) {
throw error(ex.getCode(), ex.getMessage(), caller, domainName);
}
Expand Down
Loading

0 comments on commit dfa696a

Please sign in to comment.