diff options
author | Jon Marius Venstad <jvenstad@yahoo-inc.com> | 2019-06-07 17:27:22 +0200 |
---|---|---|
committer | Jon Marius Venstad <jvenstad@yahoo-inc.com> | 2019-06-07 17:27:22 +0200 |
commit | ce08379e47b9e02836026d111e1a27681b21c715 (patch) | |
tree | 954830fead4acd24854a231b2d6d202676ac72ce /tenant-auth | |
parent | 65937b2191aad18db17403cdbf0b94db7aac7cc7 (diff) |
Move tenant authentication to new module tenant-auth, to override internally
Diffstat (limited to 'tenant-auth')
-rw-r--r-- | tenant-auth/OWNERS | 1 | ||||
-rw-r--r-- | tenant-auth/README.md | 1 | ||||
-rw-r--r-- | tenant-auth/pom.xml | 40 | ||||
-rw-r--r-- | tenant-auth/src/main/java/ai/vespa/hosted/auth/Authenticator.java | 73 | ||||
-rw-r--r-- | tenant-auth/src/test/java/ai/vespa/hosted/auth/AuthenticatorTest.java | 5 |
5 files changed, 120 insertions, 0 deletions
diff --git a/tenant-auth/OWNERS b/tenant-auth/OWNERS new file mode 100644 index 00000000000..d0a102ecbf4 --- /dev/null +++ b/tenant-auth/OWNERS @@ -0,0 +1 @@ +jonmv diff --git a/tenant-auth/README.md b/tenant-auth/README.md new file mode 100644 index 00000000000..0514b68400e --- /dev/null +++ b/tenant-auth/README.md @@ -0,0 +1 @@ +# Utilities that authenticate users to the hosted Vespa API, or to hosted Vespa applications. diff --git a/tenant-auth/pom.xml b/tenant-auth/pom.xml new file mode 100644 index 00000000000..be8b42dd6c2 --- /dev/null +++ b/tenant-auth/pom.xml @@ -0,0 +1,40 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. --> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>com.yahoo.vespa</groupId> + <artifactId>parent</artifactId> + <version>7-SNAPSHOT</version> + <relativePath>../parent/pom.xml</relativePath> + </parent> + <artifactId>tenant-auth</artifactId> + <description>Provides resources for authenticating with the hosted Vespa API or application containers</description> + + <dependencies> + <dependency> + <groupId>com.yahoo.vespa</groupId> + <artifactId>hosted-api</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>com.yahoo.vespa</groupId> + <artifactId>config-provisioning</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>com.yahoo.vespa</groupId> + <artifactId>security-utils</artifactId> + <version>${project.version}</version> + </dependency> + + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>test</scope> + </dependency> + </dependencies> +</project> diff --git a/tenant-auth/src/main/java/ai/vespa/hosted/auth/Authenticator.java b/tenant-auth/src/main/java/ai/vespa/hosted/auth/Authenticator.java new file mode 100644 index 00000000000..6ecf1100630 --- /dev/null +++ b/tenant-auth/src/main/java/ai/vespa/hosted/auth/Authenticator.java @@ -0,0 +1,73 @@ +package ai.vespa.hosted.auth; + +import ai.vespa.hosted.api.ControllerHttpClient; +import com.yahoo.config.provision.ApplicationId; +import com.yahoo.security.KeyUtils; +import com.yahoo.security.SslContextBuilder; +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.PrivateKey; +import java.security.cert.X509Certificate; +import java.time.Instant; +import java.util.Optional; + +/** + * Authenticates {@link HttpRequest}s against a hosted Vespa application based on mutual TLS. + * + * @author jonmv + */ +public class Authenticator { + + /** Returns an SSLContext from "key" and "cert" files found under {@code System.getProperty("vespa.test.credentials.root")}. */ + public SSLContext sslContext() { + try { + Path credentialsRoot = Path.of(System.getProperty("vespa.test.credentials.root")); + Path certificateFile = credentialsRoot.resolve("cert"); + Path privateKeyFile = credentialsRoot.resolve("key"); + + X509Certificate certificate = X509CertificateUtils.fromPem(new String(Files.readAllBytes(certificateFile))); + if (Instant.now().isBefore(certificate.getNotBefore().toInstant()) + || Instant.now().isAfter(certificate.getNotAfter().toInstant())) + throw new IllegalStateException("Certificate at '" + certificateFile + "' is valid between " + + certificate.getNotBefore() + " and " + certificate.getNotAfter() + " — not now."); + + PrivateKey privateKey = KeyUtils.fromPemEncodedPrivateKey(new String(Files.readAllBytes(privateKeyFile))); + return new SslContextBuilder().withKeyStore(privateKey, certificate).build(); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + public HttpRequest.Builder authenticated(HttpRequest.Builder request) { + return request; + } + + ApplicationId id = ApplicationId.from(requireNonBlankProperty("tenant"), + requireNonBlankProperty("application"), + getNonBlankProperty("instance").orElse("default")); + + URI endpoint = URI.create(requireNonBlankProperty("endpoint")); + Path privateKeyFile = Paths.get(requireNonBlankProperty("privateKeyFile")); + Optional<Path> certificateFile = getNonBlankProperty("certificateFile").map(Paths::get); + + ControllerHttpClient controller = certificateFile.isPresent() + ? ControllerHttpClient.withKeyAndCertificate(endpoint, privateKeyFile, certificateFile.get()) + : ControllerHttpClient.withSignatureKey(endpoint, privateKeyFile, id); + + static Optional<String> getNonBlankProperty(String name) { + return Optional.ofNullable(System.getProperty(name)).filter(value -> ! value.isBlank()); + } + + static String requireNonBlankProperty(String name) { + return getNonBlankProperty(name).orElseThrow(() -> new IllegalStateException("Missing required property '" + name + "'")); + } + +} diff --git a/tenant-auth/src/test/java/ai/vespa/hosted/auth/AuthenticatorTest.java b/tenant-auth/src/test/java/ai/vespa/hosted/auth/AuthenticatorTest.java new file mode 100644 index 00000000000..ff4bebce3ff --- /dev/null +++ b/tenant-auth/src/test/java/ai/vespa/hosted/auth/AuthenticatorTest.java @@ -0,0 +1,5 @@ +package ai.vespa.hosted.auth; + +public class AuthenticatorTest { + +} |