diff options
author | Martin Polden <mpolden@mpolden.no> | 2019-09-23 13:56:53 +0200 |
---|---|---|
committer | Martin Polden <mpolden@mpolden.no> | 2019-09-23 14:32:20 +0200 |
commit | e241ebcd59fcaab4749be542b16aaff590628e52 (patch) | |
tree | b16c73fe5f1adcdadd88fe30ca3eea7cc11233ec /athenz-identity-provider-service/src/main | |
parent | e0b06c1104b0815bf8bfe23628b4ada8f899918e (diff) |
Implement refresh instance
Diffstat (limited to 'athenz-identity-provider-service/src/main')
-rw-r--r-- | athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/ca/restapi/CertificateAuthorityApiHandler.java | 30 |
1 files changed, 22 insertions, 8 deletions
diff --git a/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/ca/restapi/CertificateAuthorityApiHandler.java b/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/ca/restapi/CertificateAuthorityApiHandler.java index ba4f0ce932c..b2120f24160 100644 --- a/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/ca/restapi/CertificateAuthorityApiHandler.java +++ b/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/ca/restapi/CertificateAuthorityApiHandler.java @@ -25,12 +25,14 @@ import java.security.PrivateKey; import java.security.cert.X509Certificate; import java.time.Clock; import java.util.Optional; +import java.util.function.Function; import java.util.logging.Level; /** * REST API for issuing and refreshing node certificates in a hosted Vespa system. * * The API implements the following subset of methods from the Athenz ZTS REST API: + * * - Instance registration * - Instance refresh * @@ -59,12 +61,12 @@ public class CertificateAuthorityApiHandler extends LoggingRequestHandler { try { switch (request.getMethod()) { case POST: return handlePost(request); - default: return ErrorResponse.methodNotAllowed("Method '" + request.getMethod() + "' is unsupported"); + default: return ErrorResponse.methodNotAllowed("Method " + request.getMethod() + " is unsupported"); } } catch (IllegalArgumentException e) { - return ErrorResponse.badRequest(Exceptions.toMessageString(e)); + return ErrorResponse.badRequest(request.getMethod() + " " + request.getUri() + " failed: " + Exceptions.toMessageString(e)); } catch (RuntimeException e) { - log.log(Level.WARNING, "Unexpected error handling '" + request.getUri() + "'", e); + log.log(Level.WARNING, "Unexpected error handling " + request.getMethod() + " " + request.getUri(), e); return ErrorResponse.internalServerError(Exceptions.toMessageString(e)); } } @@ -72,13 +74,12 @@ public class CertificateAuthorityApiHandler extends LoggingRequestHandler { private HttpResponse handlePost(HttpRequest request) { Path path = new Path(request.getUri()); if (path.matches("/ca/v1/instance/")) return registerInstance(request); - // TODO: Implement refresh + if (path.matches("/ca/v1/instance/{provider}/{domain}/{service}/{instanceId}")) return refreshInstance(request, path.get("provider"), path.get("service"), path.get("instanceId")); return ErrorResponse.notFoundError("Nothing at " + path); } private HttpResponse registerInstance(HttpRequest request) { - var body = slimeFromRequest(request); - var instanceRegistration = InstanceSerializer.registrationFromSlime(body); + var instanceRegistration = deserializeRequest(request, InstanceSerializer::registrationFromSlime); var certificate = certificates.create(instanceRegistration.csr(), caCertificate(), caPrivateKey()); var instanceId = Certificates.extractDnsName(instanceRegistration.csr()); var identity = new InstanceIdentity(instanceRegistration.provider(), instanceRegistration.service(), instanceId, @@ -86,6 +87,18 @@ public class CertificateAuthorityApiHandler extends LoggingRequestHandler { return new SlimeJsonResponse(InstanceSerializer.identityToSlime(identity)); } + private HttpResponse refreshInstance(HttpRequest request, String provider, String service, String instanceId) { + var instanceRefresh = deserializeRequest(request, InstanceSerializer::refreshFromSlime); + var instanceIdFromCsr = Certificates.extractDnsName(instanceRefresh.csr()); + if (!instanceIdFromCsr.equals(instanceId)) { + throw new IllegalArgumentException("Mismatched instance ID and SAN DNS name [instanceId=" + instanceId + + ",dnsName=" + instanceIdFromCsr + "]"); + } + var certificate = certificates.create(instanceRefresh.csr(), caCertificate(), caPrivateKey()); + var identity = new InstanceIdentity(provider, service, instanceIdFromCsr, Optional.of(certificate)); + return new SlimeJsonResponse(InstanceSerializer.identityToSlime(identity)); + } + /** Returns CA certificate from secret store */ private X509Certificate caCertificate() { var keyName = String.format("vespa.external.%s.configserver.ca.cert.cert", system.value().toLowerCase()); @@ -98,9 +111,10 @@ public class CertificateAuthorityApiHandler extends LoggingRequestHandler { return KeyUtils.fromPemEncodedPrivateKey(secretStore.getSecret(keyName)); } - private static Slime slimeFromRequest(HttpRequest request) { + private static <T> T deserializeRequest(HttpRequest request, Function<Slime, T> serializer) { try { - return SlimeUtils.jsonToSlime(request.getData().readAllBytes()); + var slime = SlimeUtils.jsonToSlime(request.getData().readAllBytes()); + return serializer.apply(slime); } catch (IOException e) { throw new UncheckedIOException(e); } |