summaryrefslogtreecommitdiffstats
path: root/athenz-identity-provider-service
diff options
context:
space:
mode:
authorBjørn Christian Seime <bjorncs@oath.com>2017-11-16 13:23:36 +0100
committerBjørn Christian Seime <bjorncs@oath.com>2017-11-17 13:04:36 +0100
commit332a1c17e472a9816ed638db94dfc34fce1f8392 (patch)
treec4640fa1fae79e1340ec27a2e97ff511b12ef66f /athenz-identity-provider-service
parent29f7dbc63afe64683288d6552aaede77b92cb434 (diff)
Rewrite InstanceConfirmationServlet as jax-rs resource
Diffstat (limited to 'athenz-identity-provider-service')
-rw-r--r--athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/AthenzInstanceProviderService.java4
-rw-r--r--athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/impl/InstanceConfirmationResource.java53
-rw-r--r--athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/impl/InstanceConfirmationServlet.java65
-rw-r--r--athenz-identity-provider-service/src/test/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/AthenzInstanceProviderServiceTest.java60
4 files changed, 55 insertions, 127 deletions
diff --git a/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/AthenzInstanceProviderService.java b/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/AthenzInstanceProviderService.java
index b26b3e8ee18..c4b54d73ec3 100644
--- a/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/AthenzInstanceProviderService.java
+++ b/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/AthenzInstanceProviderService.java
@@ -15,7 +15,6 @@ import com.yahoo.vespa.hosted.athenz.instanceproviderservice.config.AthenzProvid
import com.yahoo.vespa.hosted.athenz.instanceproviderservice.impl.AthenzCertificateClient;
import com.yahoo.vespa.hosted.athenz.instanceproviderservice.impl.CertificateClient;
import com.yahoo.vespa.hosted.athenz.instanceproviderservice.impl.IdentityDocumentGenerator;
-import com.yahoo.vespa.hosted.athenz.instanceproviderservice.impl.InstanceConfirmationServlet;
import com.yahoo.vespa.hosted.athenz.instanceproviderservice.impl.InstanceValidator;
import com.yahoo.vespa.hosted.athenz.instanceproviderservice.impl.KeyProvider;
import com.yahoo.vespa.hosted.athenz.instanceproviderservice.impl.SecretStoreKeyProvider;
@@ -115,9 +114,6 @@ public class AthenzInstanceProviderService extends AbstractComponent {
CertificateSignerServlet certificateSignerServlet = new CertificateSignerServlet(certificateSigner);
handler.addServletWithMapping(new ServletHolder(certificateSignerServlet), config.apiPath() + "/sign");
- InstanceConfirmationServlet instanceConfirmationServlet = new InstanceConfirmationServlet(instanceValidator);
- handler.addServletWithMapping(new ServletHolder(instanceConfirmationServlet), config.apiPath() + "/instance");
-
handler.addServletWithMapping(StatusServlet.class, "/status.html");
server.setHandler(handler);
return server;
diff --git a/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/impl/InstanceConfirmationResource.java b/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/impl/InstanceConfirmationResource.java
new file mode 100644
index 00000000000..a8b837a3486
--- /dev/null
+++ b/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/impl/InstanceConfirmationResource.java
@@ -0,0 +1,53 @@
+// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.vespa.hosted.athenz.instanceproviderservice.impl;
+
+import com.google.inject.Inject;
+import com.yahoo.config.model.api.SuperModelProvider;
+import com.yahoo.config.provision.Zone;
+import com.yahoo.container.jaxrs.annotation.Component;
+import com.yahoo.jdisc.http.SecretStore;
+import com.yahoo.log.LogLevel;
+import com.yahoo.vespa.hosted.athenz.instanceproviderservice.config.AthenzProviderServiceConfig;
+import com.yahoo.vespa.hosted.athenz.instanceproviderservice.impl.model.InstanceConfirmation;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.ForbiddenException;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import java.util.logging.Logger;
+
+import static com.yahoo.vespa.hosted.athenz.instanceproviderservice.impl.Utils.getZoneConfig;
+
+/**
+ * @author bjorncs
+ */
+@Path("/instance")
+public class InstanceConfirmationResource {
+
+ private static final Logger log = Logger.getLogger(InstanceConfirmationResource.class.getName());
+
+ private final InstanceValidator instanceValidator;
+
+ @Inject
+ public InstanceConfirmationResource(@Component AthenzProviderServiceConfig config,
+ @Component SecretStore secretStore,
+ @Component SuperModelProvider superModelProvider,
+ @Component Zone zone) {
+ AthenzProviderServiceConfig.Zones zoneConfig = getZoneConfig(config, zone);
+ SecretStoreKeyProvider keyProvider = new SecretStoreKeyProvider(secretStore, zoneConfig.secretName());
+ this.instanceValidator = new InstanceValidator(keyProvider, superModelProvider);
+ }
+
+ @POST
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ public InstanceConfirmation confirmInstance(InstanceConfirmation instanceConfirmation) {
+ if (!instanceValidator.isValidInstance(instanceConfirmation)) {
+ log.log(LogLevel.ERROR, "Invalid instance: " + instanceConfirmation);
+ throw new ForbiddenException("Instance is invalid");
+ }
+ return instanceConfirmation;
+ }
+}
diff --git a/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/impl/InstanceConfirmationServlet.java b/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/impl/InstanceConfirmationServlet.java
deleted file mode 100644
index 766b95b443b..00000000000
--- a/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/impl/InstanceConfirmationServlet.java
+++ /dev/null
@@ -1,65 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.vespa.hosted.athenz.instanceproviderservice.impl;
-
-import com.fasterxml.jackson.core.JsonParseException;
-import com.fasterxml.jackson.databind.JsonMappingException;
-import com.yahoo.log.LogLevel;
-import com.yahoo.vespa.hosted.athenz.instanceproviderservice.impl.model.InstanceConfirmation;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.Reader;
-import java.util.logging.Logger;
-import java.util.stream.Collectors;
-
-/**
- * A Servlet implementing the Athenz Service Provider InstanceConfirmation API
- *
- * @author bjorncs
- */
-public class InstanceConfirmationServlet extends HttpServlet {
-
- private static final Logger log = Logger.getLogger(InstanceConfirmationServlet.class.getName());
-
- private final InstanceValidator instanceValidator;
-
- public InstanceConfirmationServlet(InstanceValidator instanceValidator) {
- this.instanceValidator = instanceValidator;
- }
-
- @Override
- protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- // TODO Validate that request originates from ZTS
- try {
- String confirmationContent = toString(req.getReader());
- log.log(LogLevel.DEBUG, () -> "Confirmation content: " + confirmationContent);
- InstanceConfirmation instanceConfirmation =
- Utils.getMapper().readValue(confirmationContent, InstanceConfirmation.class);
- log.log(LogLevel.DEBUG, () -> "Parsed confirmation content: " + instanceConfirmation.toString());
- if (!instanceValidator.isValidInstance(instanceConfirmation)) {
- String message = "Invalid instance: " + instanceConfirmation;
- log.log(LogLevel.ERROR, message);
- resp.sendError(HttpServletResponse.SC_FORBIDDEN, message);
- } else {
- resp.setStatus(HttpServletResponse.SC_OK);
- resp.setContentType("application/json");
- resp.getWriter().write(Utils.getMapper().writeValueAsString(instanceConfirmation));
- }
- } catch (JsonParseException | JsonMappingException e) {
- String message = "InstanceConfirmation is not valid JSON";
- log.log(LogLevel.ERROR, message, e);
- resp.sendError(HttpServletResponse.SC_BAD_REQUEST, message);
- }
- }
-
- private static String toString(Reader reader) throws IOException {
- try (BufferedReader bufferedReader = new BufferedReader(reader)) {
- return bufferedReader.lines().collect(Collectors.joining("\n"));
- }
- }
-
-}
diff --git a/athenz-identity-provider-service/src/test/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/AthenzInstanceProviderServiceTest.java b/athenz-identity-provider-service/src/test/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/AthenzInstanceProviderServiceTest.java
index c8c3826fc39..c58e86f7585 100644
--- a/athenz-identity-provider-service/src/test/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/AthenzInstanceProviderServiceTest.java
+++ b/athenz-identity-provider-service/src/test/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/AthenzInstanceProviderServiceTest.java
@@ -2,7 +2,6 @@
package com.yahoo.vespa.hosted.athenz.instanceproviderservice;
import athenz.shade.zts.jersey.repackaged.com.google.common.collect.ImmutableMap;
-import com.fasterxml.jackson.databind.ObjectMapper;
import com.yahoo.config.provision.Environment;
import com.yahoo.config.provision.RegionName;
import com.yahoo.config.provision.SystemName;
@@ -15,19 +14,11 @@ import com.yahoo.vespa.hosted.athenz.instanceproviderservice.impl.CertificateCli
import com.yahoo.vespa.hosted.athenz.instanceproviderservice.impl.IdentityDocumentGenerator;
import com.yahoo.vespa.hosted.athenz.instanceproviderservice.impl.InstanceValidator;
import com.yahoo.vespa.hosted.athenz.instanceproviderservice.impl.KeyProvider;
-import com.yahoo.vespa.hosted.athenz.instanceproviderservice.impl.Utils;
-import com.yahoo.vespa.hosted.athenz.instanceproviderservice.impl.model.IdentityDocument;
-import com.yahoo.vespa.hosted.athenz.instanceproviderservice.impl.model.InstanceConfirmation;
-import com.yahoo.vespa.hosted.athenz.instanceproviderservice.impl.model.ProviderUniqueId;
-import com.yahoo.vespa.hosted.athenz.instanceproviderservice.impl.model.SignedIdentityDocument;
-import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
-import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
-import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContextBuilder;
@@ -45,7 +36,6 @@ import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.junit.Test;
import javax.net.ssl.SSLContext;
-import java.io.IOException;
import java.math.BigInteger;
import java.security.KeyManagementException;
import java.security.KeyPair;
@@ -54,20 +44,15 @@ import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
-import java.security.Signature;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
-import java.time.Instant;
import java.time.temporal.TemporalAmount;
-import java.util.Base64;
import java.util.Calendar;
import java.util.Date;
import java.util.concurrent.ScheduledExecutorService;
import java.util.logging.Logger;
-import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyLong;
@@ -89,11 +74,10 @@ public class AthenzInstanceProviderServiceTest {
String service = "service";
AutoGeneratedKeyProvider keyProvider = new AutoGeneratedKeyProvider();
- PrivateKey privateKey = keyProvider.getPrivateKey(0);
AthenzProviderServiceConfig config = getAthenzProviderConfig(domain, service, "vespa.dns.suffix", ZONE);
SslContextFactory sslContextFactory = AthenzInstanceProviderService.createSslContextFactory();
AthenzCertificateUpdater certificateUpdater = new AthenzCertificateUpdater(
- new SelfSignedCertificateClient(keyProvider.getKeyPair(), config, getZoneConfig(config, ZONE)),
+ new SelfSignedCertificateClient(keyProvider.getKeyPair(), getZoneConfig(config, ZONE)),
sslContextFactory,
keyProvider,
config,
@@ -117,10 +101,8 @@ public class AthenzInstanceProviderServiceTest {
assertFalse(getStatus(client));
certificateUpdater.run();
assertTrue(getStatus(client));
- assertInstanceConfirmationSucceeds(client, privateKey);
certificateUpdater.run();
assertTrue(getStatus(client));
- assertInstanceConfirmationSucceeds(client, privateKey);
} finally {
athenzInstanceProviderService.deconstruct();
}
@@ -159,13 +141,6 @@ public class AthenzInstanceProviderServiceTest {
}
}
- private static void assertInstanceConfirmationSucceeds(HttpClient client, PrivateKey privateKey) throws IOException {
- HttpPost httpPost = new HttpPost("https://localhost:" + PORT + "/instance");
- httpPost.setEntity(createInstanceConfirmation(privateKey));
- HttpResponse response = client.execute(httpPost);
- assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
- }
-
private static CloseableHttpClient createHttpClient(String domain, String service)
throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException {
SSLContext sslContext = new SSLContextBuilder()
@@ -179,35 +154,6 @@ public class AthenzInstanceProviderServiceTest {
.build();
}
- private static HttpEntity createInstanceConfirmation(PrivateKey privateKey) {
- IdentityDocument identityDocument = new IdentityDocument(
- new ProviderUniqueId("tenant", "application", "environment", "region", "instance", "cluster-id", 0),
- "hostname",
- "instance-hostname",
- Instant.now());
- try {
- ObjectMapper mapper = Utils.getMapper();
- String encodedIdentityDocument =
- Base64.getEncoder().encodeToString(mapper.writeValueAsString(identityDocument).getBytes());
- Signature sigGenerator = Signature.getInstance("SHA512withRSA");
- sigGenerator.initSign(privateKey);
- sigGenerator.update(encodedIdentityDocument.getBytes());
-
- InstanceConfirmation instanceConfirmation = new InstanceConfirmation(
- "provider", "domain", "service",
- new SignedIdentityDocument(encodedIdentityDocument,
- Base64.getEncoder().encodeToString(sigGenerator.sign()),
- 0,
- identityDocument.providerUniqueId.asString(),
- "dnssuffix",
- "service",
- "localhost/zts",
- 1));
- return new StringEntity(mapper.writeValueAsString(instanceConfirmation));
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
public static class AutoGeneratedKeyProvider implements KeyProvider {
@@ -241,13 +187,11 @@ public class AthenzInstanceProviderServiceTest {
private static class SelfSignedCertificateClient implements CertificateClient {
private final KeyPair keyPair;
- private final AthenzProviderServiceConfig config;
private final AthenzProviderServiceConfig.Zones zoneConfig;
- private SelfSignedCertificateClient(KeyPair keyPair, AthenzProviderServiceConfig config,
+ private SelfSignedCertificateClient(KeyPair keyPair,
AthenzProviderServiceConfig.Zones zoneConfig) {
this.keyPair = keyPair;
- this.config = config;
this.zoneConfig = zoneConfig;
}