summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMorten Tokle <morten.tokle@gmail.com>2017-10-26 18:00:57 +0200
committerGitHub <noreply@github.com>2017-10-26 18:00:57 +0200
commitdf0a439ce0de3a5c3c57667524a93716c64deb76 (patch)
tree2522814b23ac360cec338dc22560e4d32555a15f
parent1ed83a89c5387ab3d16ec1b329fab26dcd402881 (diff)
parentb3cb8033f7798ab4605d9089e394e8dca9c04ff5 (diff)
Merge pull request #3905 from vespa-engine/bjorncs/athenz-identity-provider-service-endpoint
Bjorncs/athenz identity provider service endpoint
-rw-r--r--athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/AthenzInstanceProviderService.java17
-rw-r--r--athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/impl/IdentityDocumentServlet.java51
-rw-r--r--athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/impl/InstanceConfirmationServlet.java (renamed from athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/impl/ProviderServiceServlet.java)34
-rw-r--r--athenz-identity-provider-service/src/main/resources/configdefinitions/athenz-provider-service.def2
-rw-r--r--athenz-identity-provider-service/src/test/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/AthenzInstanceProviderServiceTest.java6
-rw-r--r--container-disc/src/main/java/com/yahoo/container/jdisc/athenz/impl/ServiceProviderApi.java18
6 files changed, 88 insertions, 40 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 745aae62d3a..668444e2769 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
@@ -2,7 +2,6 @@
package com.yahoo.vespa.hosted.athenz.instanceproviderservice;
import com.google.inject.Inject;
-import com.yahoo.athenz.auth.util.Crypto;
import com.yahoo.component.AbstractComponent;
import com.yahoo.config.provision.SystemName;
import com.yahoo.config.provision.Zone;
@@ -12,9 +11,10 @@ import com.yahoo.vespa.hosted.athenz.instanceproviderservice.impl.AthenzCertific
import com.yahoo.vespa.hosted.athenz.instanceproviderservice.impl.CertificateClient;
import com.yahoo.vespa.hosted.athenz.instanceproviderservice.impl.FileBackedKeyProvider;
import com.yahoo.vespa.hosted.athenz.instanceproviderservice.impl.IdentityDocumentGenerator;
+import com.yahoo.vespa.hosted.athenz.instanceproviderservice.impl.IdentityDocumentServlet;
+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.ProviderServiceServlet;
import com.yahoo.vespa.hosted.athenz.instanceproviderservice.impl.StatusServlet;
import com.yahoo.vespa.hosted.provision.NodeRepository;
import org.eclipse.jetty.server.Server;
@@ -89,11 +89,14 @@ public class AthenzInstanceProviderService extends AbstractComponent {
server.addConnector(connector);
ServletHandler handler = new ServletHandler();
- ProviderServiceServlet providerServiceServlet =
- new ProviderServiceServlet(
- new InstanceValidator(keyProvider),
- new IdentityDocumentGenerator(config, nodeRepository, zone, keyProvider));
- handler.addServletWithMapping(new ServletHolder(providerServiceServlet), config.apiPath());
+ InstanceConfirmationServlet instanceConfirmationServlet =
+ new InstanceConfirmationServlet(new InstanceValidator(keyProvider));
+ handler.addServletWithMapping(new ServletHolder(instanceConfirmationServlet), config.apiPath() + "/instance");
+
+ IdentityDocumentServlet identityDocumentServlet =
+ new IdentityDocumentServlet(new IdentityDocumentGenerator(config, nodeRepository, zone, keyProvider));
+ handler.addServletWithMapping(new ServletHolder(identityDocumentServlet), config.apiPath() + "/identity-document");
+
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/IdentityDocumentServlet.java b/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/impl/IdentityDocumentServlet.java
new file mode 100644
index 00000000000..a66fdf9d82f
--- /dev/null
+++ b/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/impl/IdentityDocumentServlet.java
@@ -0,0 +1,51 @@
+// 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.yahoo.log.LogLevel;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.logging.Logger;
+
+/**
+ * @author bjorncs
+ */
+public class IdentityDocumentServlet extends HttpServlet {
+
+ private static final Logger log = Logger.getLogger(IdentityDocumentServlet.class.getName());
+
+ private final IdentityDocumentGenerator identityDocumentGenerator;
+
+ public IdentityDocumentServlet(IdentityDocumentGenerator identityDocumentGenerator) {
+ this.identityDocumentGenerator = identityDocumentGenerator;
+ }
+
+ @Override
+ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+ // TODO verify tls client cert
+ String hostname = req.getParameter("hostname");
+ if (hostname == null) {
+ String message = "The 'hostname' parameter is missing";
+ log.log(LogLevel.ERROR, message);
+ resp.sendError(HttpServletResponse.SC_BAD_REQUEST, message);
+ return;
+ }
+ try {
+ log.log(LogLevel.INFO, "Generating identity document for " + hostname);
+ String signedIdentityDocument = identityDocumentGenerator.generateSignedIdentityDocument(hostname);
+ resp.setContentType("application/json");
+ PrintWriter writer = resp.getWriter();
+ writer.print(signedIdentityDocument);
+ writer.flush();
+ } catch (Exception e) {
+ String message = String.format("Unable to generate identity doument [%s]", e.getMessage());
+ log.log(LogLevel.ERROR, message);
+ resp.sendError(HttpServletResponse.SC_NOT_FOUND, message);
+ }
+ }
+
+}
diff --git a/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/impl/ProviderServiceServlet.java b/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/impl/InstanceConfirmationServlet.java
index 7766dc9cc3c..766b95b443b 100644
--- a/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/impl/ProviderServiceServlet.java
+++ b/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/impl/InstanceConfirmationServlet.java
@@ -12,7 +12,6 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
-import java.io.PrintWriter;
import java.io.Reader;
import java.util.logging.Logger;
import java.util.stream.Collectors;
@@ -22,16 +21,14 @@ import java.util.stream.Collectors;
*
* @author bjorncs
*/
-public class ProviderServiceServlet extends HttpServlet {
+public class InstanceConfirmationServlet extends HttpServlet {
- private static final Logger log = Logger.getLogger(ProviderServiceServlet.class.getName());
+ private static final Logger log = Logger.getLogger(InstanceConfirmationServlet.class.getName());
private final InstanceValidator instanceValidator;
- private final IdentityDocumentGenerator identityDocumentGenerator;
- public ProviderServiceServlet(InstanceValidator instanceValidator, IdentityDocumentGenerator identityDocumentGenerator) {
+ public InstanceConfirmationServlet(InstanceValidator instanceValidator) {
this.instanceValidator = instanceValidator;
- this.identityDocumentGenerator = identityDocumentGenerator;
}
@Override
@@ -44,31 +41,18 @@ public class ProviderServiceServlet extends HttpServlet {
Utils.getMapper().readValue(confirmationContent, InstanceConfirmation.class);
log.log(LogLevel.DEBUG, () -> "Parsed confirmation content: " + instanceConfirmation.toString());
if (!instanceValidator.isValidInstance(instanceConfirmation)) {
- log.log(LogLevel.ERROR, "Invalid instance: " + instanceConfirmation);
- resp.setStatus(HttpServletResponse.SC_FORBIDDEN);
+ 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) {
- log.log(LogLevel.ERROR, "InstanceConfirmation is not valid JSON", e);
- resp.setStatus(HttpServletResponse.SC_BAD_REQUEST);
- }
- }
-
- @Override
- protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- // TODO verify tls client cert
- String hostname = req.getParameter("hostname");
- try {
- String signedIdentityDocument = identityDocumentGenerator.generateSignedIdentityDocument(hostname);
- resp.setContentType("application/json");
- PrintWriter writer = resp.getWriter();
- writer.print(signedIdentityDocument);
- writer.flush();
- } catch (Exception e) {
- resp.sendError(HttpServletResponse.SC_NOT_FOUND, String.format("Unable to generate identity doument [%s]", e.getMessage()));
+ String message = "InstanceConfirmation is not valid JSON";
+ log.log(LogLevel.ERROR, message, e);
+ resp.sendError(HttpServletResponse.SC_BAD_REQUEST, message);
}
}
diff --git a/athenz-identity-provider-service/src/main/resources/configdefinitions/athenz-provider-service.def b/athenz-identity-provider-service/src/main/resources/configdefinitions/athenz-provider-service.def
index af3abd8631b..7e9c19cb86a 100644
--- a/athenz-identity-provider-service/src/main/resources/configdefinitions/athenz-provider-service.def
+++ b/athenz-identity-provider-service/src/main/resources/configdefinitions/athenz-provider-service.def
@@ -17,7 +17,7 @@ port int default=8443
keyPathPrefix string
# InstanceConfirmation API path
-apiPath string default="/athenz/v1/provider/instance"
+apiPath string default="/athenz/v1/provider"
# Athenz principal authority header name
athenzPrincipalHeaderName string default="Athenz-Principal-Auth"
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 a15d681de39..c32f8e18c00 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
@@ -184,8 +184,8 @@ public class AthenzInstanceProviderServiceTest {
.keyPathPrefix("dummy-path")
.certDnsSuffix("dnsSuffix")
.ztsUrl("localhost/zts")
- .athenzPrincipalHeaderName("Yahoo-Principal-Auth")
- .apiPath("/"));
+ .athenzPrincipalHeaderName("Athenz-Principal-Auth")
+ .apiPath(""));
}
private static boolean getStatus(HttpClient client) {
@@ -199,7 +199,7 @@ public class AthenzInstanceProviderServiceTest {
}
private static void assertInstanceConfirmationSucceeds(HttpClient client, PrivateKey privateKey) throws IOException {
- HttpPost httpPost = new HttpPost("https://localhost:" + PORT + "/");
+ HttpPost httpPost = new HttpPost("https://localhost:" + PORT + "/instance");
httpPost.setEntity(createInstanceConfirmation(privateKey));
HttpResponse response = client.execute(httpPost);
assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
diff --git a/container-disc/src/main/java/com/yahoo/container/jdisc/athenz/impl/ServiceProviderApi.java b/container-disc/src/main/java/com/yahoo/container/jdisc/athenz/impl/ServiceProviderApi.java
index 388fc63d086..6c1c22d07e0 100644
--- a/container-disc/src/main/java/com/yahoo/container/jdisc/athenz/impl/ServiceProviderApi.java
+++ b/container-disc/src/main/java/com/yahoo/container/jdisc/athenz/impl/ServiceProviderApi.java
@@ -1,7 +1,9 @@
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.container.jdisc.athenz.impl;
+import com.yahoo.vespa.defaults.Defaults;
import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.methods.RequestBuilder;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContextBuilder;
@@ -13,6 +15,7 @@ import org.eclipse.jetty.http.HttpStatus;
import java.io.IOException;
import java.net.URI;
+import java.net.URLEncoder;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
@@ -33,12 +36,19 @@ public class ServiceProviderApi {
*/
public String getSignedIdentityDocument() {
try (CloseableHttpClient httpClient = createHttpClient()) {
- CloseableHttpResponse idDocResponse = httpClient.execute(RequestBuilder.get().setUri(providerUri + "/identity-document").build());
+ // TODO Figure out a proper way of determining the hostname matching what's registred in node-repository
+ String uri = providerUri + "/identity-document?hostname=" + URLEncoder.encode(
+ Defaults.getDefaults().vespaHostname(), "UTF-8");
+ HttpUriRequest request = RequestBuilder.get().setUri(uri).build();
+ CloseableHttpResponse idDocResponse = httpClient.execute(request);
+ String responseContent = EntityUtils.toString(idDocResponse.getEntity());
if (HttpStatus.isSuccess(idDocResponse.getStatusLine().getStatusCode())) {
- return EntityUtils.toString(idDocResponse.getEntity());
+ return responseContent;
} else {
- // make sure we have retried a few times (AND logged) before giving up
- throw new RuntimeException("Failed to initialize Athenz instance provider");
+ // TODO make sure we have retried a few times (AND logged) before giving up
+ throw new RuntimeException(
+ "Failed to initialize Athenz instance provider: " +
+ idDocResponse.getStatusLine() + ": " + responseContent);
}
} catch (IOException e) {
throw new RuntimeException("Failed getting signed identity document", e);