diff options
author | Jon Marius Venstad <jvenstad@yahoo-inc.com> | 2019-06-13 14:24:49 +0200 |
---|---|---|
committer | Jon Marius Venstad <jvenstad@yahoo-inc.com> | 2019-06-13 14:24:49 +0200 |
commit | 17579280e419347d76ff950ebac88844c27a4d8e (patch) | |
tree | 7c40f096cef1cec6529eaacfbd9f250cf9c8b261 | |
parent | 2bb71582b979a83a39260f3f11466737b94ee47f (diff) |
Separate API and deployment authenticators
-rw-r--r-- | hosted-api/src/main/java/ai/vespa/hosted/api/ApiAuthenticator.java | 8 | ||||
-rw-r--r-- | hosted-api/src/main/java/ai/vespa/hosted/api/EndpointAuthenticator.java (renamed from hosted-api/src/main/java/ai/vespa/hosted/api/Authenticator.java) | 7 | ||||
-rw-r--r-- | hosted-api/src/main/java/ai/vespa/hosted/api/TestConfig.java | 5 | ||||
-rw-r--r-- | tenant-auth/src/main/java/ai/vespa/hosted/auth/ApiAuthenticator.java | 16 | ||||
-rw-r--r-- | tenant-auth/src/main/java/ai/vespa/hosted/auth/EndpointAuthenticator.java (renamed from tenant-auth/src/main/java/ai/vespa/hosted/auth/Authenticator.java) | 20 | ||||
-rw-r--r-- | tenant-cd/src/main/java/ai/vespa/hosted/cd/TestRuntime.java | 45 | ||||
-rw-r--r-- | tenant-cd/src/main/java/ai/vespa/hosted/cd/http/HttpDeployment.java | 4 | ||||
-rw-r--r-- | tenant-cd/src/main/java/ai/vespa/hosted/cd/http/HttpEndpoint.java | 6 |
8 files changed, 69 insertions, 42 deletions
diff --git a/hosted-api/src/main/java/ai/vespa/hosted/api/ApiAuthenticator.java b/hosted-api/src/main/java/ai/vespa/hosted/api/ApiAuthenticator.java new file mode 100644 index 00000000000..674faaf0ee7 --- /dev/null +++ b/hosted-api/src/main/java/ai/vespa/hosted/api/ApiAuthenticator.java @@ -0,0 +1,8 @@ +package ai.vespa.hosted.api; + +public interface ApiAuthenticator { + + /** Returns a client authenticated to talk to the hosted Vespa API. */ + ControllerHttpClient controller(); + +} diff --git a/hosted-api/src/main/java/ai/vespa/hosted/api/Authenticator.java b/hosted-api/src/main/java/ai/vespa/hosted/api/EndpointAuthenticator.java index acd8a215e7f..62b1d2b4c92 100644 --- a/hosted-api/src/main/java/ai/vespa/hosted/api/Authenticator.java +++ b/hosted-api/src/main/java/ai/vespa/hosted/api/EndpointAuthenticator.java @@ -5,11 +5,11 @@ import java.net.http.HttpRequest; import java.util.Optional; /** - * Adds environment dependent authentication to HTTP request against hosted Vespa API and deployments. + * Adds environment dependent authentication to HTTP request against Vespa deployments. * * @author jonmv */ -public interface Authenticator { +public interface EndpointAuthenticator { /** Returns an SSLContext which provides authentication against a Vespa endpoint. */ SSLContext sslContext(); @@ -17,7 +17,4 @@ public interface Authenticator { /** Adds necessary authentication to the given HTTP request builder, to pass the data plane of a Vespa endpoint. */ HttpRequest.Builder authenticated(HttpRequest.Builder request); - /** Returns a client authenticated to talk to the hosted Vespa API. */ - ControllerHttpClient controller(); - } diff --git a/hosted-api/src/main/java/ai/vespa/hosted/api/TestConfig.java b/hosted-api/src/main/java/ai/vespa/hosted/api/TestConfig.java index a0c679f312e..897b5d3236d 100644 --- a/hosted-api/src/main/java/ai/vespa/hosted/api/TestConfig.java +++ b/hosted-api/src/main/java/ai/vespa/hosted/api/TestConfig.java @@ -59,10 +59,7 @@ public class TestConfig { public ZoneId zone() { return zone; } /** Returns an immutable view of deployments, per zone, of the application to test. */ - public Map<ZoneId, Map<String, URI>> allDeployments() { return deployments; } - - /** Returns the deployment to test in this test runtime. */ - public Map<String, URI> deploymentToTest() { return deployments.get(zone); } + public Map<ZoneId, Map<String, URI>> deployments() { return deployments; } /** Returns the hosted Vespa system this is run against. */ public SystemName system() { return system; } diff --git a/tenant-auth/src/main/java/ai/vespa/hosted/auth/ApiAuthenticator.java b/tenant-auth/src/main/java/ai/vespa/hosted/auth/ApiAuthenticator.java new file mode 100644 index 00000000000..2b5bbb188dc --- /dev/null +++ b/tenant-auth/src/main/java/ai/vespa/hosted/auth/ApiAuthenticator.java @@ -0,0 +1,16 @@ +package ai.vespa.hosted.auth; + +import ai.vespa.hosted.api.ControllerHttpClient; +import ai.vespa.hosted.api.Properties; + +public class ApiAuthenticator implements ai.vespa.hosted.api.ApiAuthenticator { + + /** Returns an authenticating controller client, using private key signatures for authentication. */ + @Override + public ControllerHttpClient controller() { + return ControllerHttpClient.withSignatureKey(Properties.endpoint(), + Properties.privateKeyFile(), + Properties.application()); + } + +} diff --git a/tenant-auth/src/main/java/ai/vespa/hosted/auth/Authenticator.java b/tenant-auth/src/main/java/ai/vespa/hosted/auth/EndpointAuthenticator.java index f2de1f1e210..abb4197bda1 100644 --- a/tenant-auth/src/main/java/ai/vespa/hosted/auth/Authenticator.java +++ b/tenant-auth/src/main/java/ai/vespa/hosted/auth/EndpointAuthenticator.java @@ -1,8 +1,6 @@ package ai.vespa.hosted.auth; -import ai.vespa.hosted.api.ControllerHttpClient; -import ai.vespa.hosted.api.Properties; -import com.yahoo.config.provision.ApplicationId; +import com.yahoo.config.provision.SystemName; import com.yahoo.security.KeyUtils; import com.yahoo.security.SslContextBuilder; import com.yahoo.security.X509CertificateUtils; @@ -10,11 +8,9 @@ import com.yahoo.security.X509CertificateUtils; import javax.net.ssl.SSLContext; import java.io.IOException; import java.io.UncheckedIOException; -import java.net.URI; import java.net.http.HttpRequest; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.cert.X509Certificate; @@ -22,14 +18,16 @@ import java.time.Instant; import java.util.Optional; import static ai.vespa.hosted.api.Properties.getNonBlankProperty; -import static ai.vespa.hosted.api.Properties.requireNonBlankProperty; /** * Authenticates against the hosted Vespa API using private key signatures, and against Vespa applications using mutual TLS. * * @author jonmv */ -public class Authenticator implements ai.vespa.hosted.api.Authenticator { +public class EndpointAuthenticator implements ai.vespa.hosted.api.EndpointAuthenticator { + + /** Don't touch. */ + public EndpointAuthenticator(@SuppressWarnings("unused") SystemName __) { } /** * If {@code System.getProperty("vespa.test.credentials.root")} is set, key and certificate files @@ -67,12 +65,4 @@ public class Authenticator implements ai.vespa.hosted.api.Authenticator { return request; } - /** Returns an authenticating controller client, using the (overridable) project properties of this Vespa application. */ - @Override - public ControllerHttpClient controller() { - return ControllerHttpClient.withSignatureKey(Properties.endpoint(), - Properties.privateKeyFile(), - Properties.application()); - } - } diff --git a/tenant-cd/src/main/java/ai/vespa/hosted/cd/TestRuntime.java b/tenant-cd/src/main/java/ai/vespa/hosted/cd/TestRuntime.java index fa09d7037c9..c6560e10665 100644 --- a/tenant-cd/src/main/java/ai/vespa/hosted/cd/TestRuntime.java +++ b/tenant-cd/src/main/java/ai/vespa/hosted/cd/TestRuntime.java @@ -1,18 +1,20 @@ package ai.vespa.hosted.cd; -import ai.vespa.hosted.api.Authenticator; +import ai.vespa.hosted.api.ApiAuthenticator; +import ai.vespa.hosted.api.EndpointAuthenticator; import ai.vespa.hosted.api.ControllerHttpClient; import ai.vespa.hosted.api.Properties; import ai.vespa.hosted.api.TestConfig; +import ai.vespa.hosted.cd.http.HttpDeployment; import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.Environment; -import com.yahoo.config.provision.RegionName; import com.yahoo.config.provision.zone.ZoneId; import java.nio.file.Files; import java.nio.file.Paths; +import java.util.Map; -import static ai.vespa.hosted.api.TestConfig.fromJson; +import static java.util.stream.Collectors.toUnmodifiableMap; /** * The place to obtain environment-dependent configuration for test of a Vespa deployment. @@ -24,11 +26,16 @@ public class TestRuntime { private static TestRuntime theRuntime; private final TestConfig config; - private final Authenticator authenticator; + private final Map<String, Deployment> productionDeployments; + private final Deployment deploymentToTest; - private TestRuntime(TestConfig config, Authenticator authenticator) { + private TestRuntime(TestConfig config, EndpointAuthenticator authenticator) { this.config = config; - this.authenticator = authenticator; + this.productionDeployments = config.deployments().entrySet().stream() + .filter(zoneDeployment -> zoneDeployment.getKey().environment() == Environment.prod) + .collect(toUnmodifiableMap(zoneDeployment -> zoneDeployment.getKey().region().value(), + zoneDeployment -> new HttpDeployment(zoneDeployment.getValue(), authenticator))); + this.deploymentToTest = new HttpDeployment(config.deployments().get(config.zone()), authenticator); } /** @@ -44,18 +51,30 @@ public class TestRuntime { public static synchronized TestRuntime get() { if (theRuntime == null) { String configPath = System.getProperty("vespa.test.config"); - Authenticator authenticator = new ai.vespa.hosted.auth.Authenticator(); - theRuntime = new TestRuntime(configPath != null ? fromFile(configPath) : fromController(authenticator), - authenticator); + TestConfig config = configPath != null ? fromFile(configPath) : fromController(); + theRuntime = new TestRuntime(config, + new ai.vespa.hosted.auth.EndpointAuthenticator(config.system())); } return theRuntime; } - /** Returns a copy of this runtime, with the given authenticator. */ - public TestRuntime with(Authenticator authenticator) { + /** Returns a copy of this runtime, with the given endpoint authenticator. */ + public TestRuntime with(EndpointAuthenticator authenticator) { return new TestRuntime(config, authenticator); } + /** Returns the full id of the application this is testing. */ + public ApplicationId application() { return config.application(); } + + /** Returns the zone of the deployment this is testing. */ + public ZoneId zone() { return config.zone(); } + + /** Returns all production deployments of the application this is testing. */ + public Map<String, Deployment> productionDeployments() { return productionDeployments; } + + /** Returns the deployment this is testing. */ + public Deployment deploymentToTest() { return deploymentToTest; } + private static TestConfig fromFile(String path) { try { return TestConfig.fromJson(Files.readAllBytes(Paths.get(path))); @@ -65,8 +84,8 @@ public class TestRuntime { } } - private static TestConfig fromController(Authenticator authenticator) { - ControllerHttpClient controller = authenticator.controller(); + private static TestConfig fromController() { + ControllerHttpClient controller = new ai.vespa.hosted.auth.ApiAuthenticator().controller(); ApplicationId id = Properties.application(); Environment environment = Properties.environment().orElse(Environment.dev); ZoneId zone = Properties.region().map(region -> ZoneId.from(environment, region)) diff --git a/tenant-cd/src/main/java/ai/vespa/hosted/cd/http/HttpDeployment.java b/tenant-cd/src/main/java/ai/vespa/hosted/cd/http/HttpDeployment.java index 6234b54c0a1..d53e08863f7 100644 --- a/tenant-cd/src/main/java/ai/vespa/hosted/cd/http/HttpDeployment.java +++ b/tenant-cd/src/main/java/ai/vespa/hosted/cd/http/HttpDeployment.java @@ -1,6 +1,6 @@ package ai.vespa.hosted.cd.http; -import ai.vespa.hosted.api.Authenticator; +import ai.vespa.hosted.api.EndpointAuthenticator; import ai.vespa.hosted.cd.Deployment; import ai.vespa.hosted.cd.Endpoint; import ai.vespa.hosted.cd.TestDeployment; @@ -19,7 +19,7 @@ public class HttpDeployment implements Deployment { private final Map<String, HttpEndpoint> endpoints; /** Creates a representation of the given deployment endpoints, using the authenticator for data plane access. */ - public HttpDeployment(Map<String, URI> endpoints, Authenticator authenticator) { + public HttpDeployment(Map<String, URI> endpoints, EndpointAuthenticator authenticator) { this.endpoints = endpoints.entrySet().stream() .collect(Collectors.toUnmodifiableMap(entry -> entry.getKey(), entry -> new HttpEndpoint(entry.getValue(), authenticator))); diff --git a/tenant-cd/src/main/java/ai/vespa/hosted/cd/http/HttpEndpoint.java b/tenant-cd/src/main/java/ai/vespa/hosted/cd/http/HttpEndpoint.java index 798eb1e692b..7a61c06c738 100644 --- a/tenant-cd/src/main/java/ai/vespa/hosted/cd/http/HttpEndpoint.java +++ b/tenant-cd/src/main/java/ai/vespa/hosted/cd/http/HttpEndpoint.java @@ -1,6 +1,6 @@ package ai.vespa.hosted.cd.http; -import ai.vespa.hosted.api.Authenticator; +import ai.vespa.hosted.api.EndpointAuthenticator; import com.yahoo.slime.Inspector; import com.yahoo.slime.JsonDecoder; import com.yahoo.slime.Slime; @@ -34,9 +34,9 @@ public class HttpEndpoint implements TestEndpoint { private final URI endpoint; private final HttpClient client; - private final ai.vespa.hosted.api.Authenticator authenticator; + private final EndpointAuthenticator authenticator; - public HttpEndpoint(URI endpoint, Authenticator authenticator) { + public HttpEndpoint(URI endpoint, EndpointAuthenticator authenticator) { this.endpoint = requireNonNull(endpoint); this.authenticator = requireNonNull(authenticator); this.client = HttpClient.newBuilder() |