summaryrefslogtreecommitdiffstats
path: root/vespa-athenz
diff options
context:
space:
mode:
authorBjørn Christian Seime <bjorncs@verizonmedia.com>2020-05-15 13:20:13 +0200
committerBjørn Christian Seime <bjorncs@verizonmedia.com>2020-05-18 13:31:05 +0200
commit848fa86f8836ba6b7d5840cc59b46dff9111010e (patch)
tree292fc162b0b8c7d7d2a8ef7ba546fe63bfc167f9 /vespa-athenz
parent480d205734db359a707c75768facf1aabea5acf4 (diff)
Provide path to trust stores from ServiceIdentityProvider
Model distinction between the Athenz and client trust store. Cleanup constructors and config for SiaIdentityProvider.
Diffstat (limited to 'vespa-athenz')
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identity/ServiceIdentityProvider.java34
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identity/SiaIdentityProvider.java42
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/client/AthenzIdentityProviderImpl.java23
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/utils/SiaUtils.java9
-rw-r--r--vespa-athenz/src/test/java/com/yahoo/vespa/athenz/identity/SiaIdentityProviderTest.java17
5 files changed, 78 insertions, 47 deletions
diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identity/ServiceIdentityProvider.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identity/ServiceIdentityProvider.java
index 180d052c8dc..f6888acb018 100644
--- a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identity/ServiceIdentityProvider.java
+++ b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identity/ServiceIdentityProvider.java
@@ -15,9 +15,43 @@ import java.nio.file.Path;
* @author bjorncs
*/
public interface ServiceIdentityProvider {
+ /**
+ *
+ * @return The Athenz identity of the environment
+ */
AthenzIdentity identity();
+
+ /**
+ * @return {@link SSLContext} that is automatically updated.
+ */
SSLContext getIdentitySslContext();
+
+ /**
+ * @return Current certificate and private key. Unlike {@link #getIdentitySslContext()} underlying credentials are not automatically updated.
+ */
X509CertificateWithKey getIdentityCertificateWithKey();
+
+ /**
+ * @return Path to X.509 certificate in PEM format
+ */
Path certificatePath();
+
+ /**
+ * @return Path to private key in PEM format
+ */
Path privateKeyPath();
+
+ /**
+ * @return Path to Athenz truststore in PEM format
+ */
+ Path athenzTruststorePath();
+
+ /**
+ * The client truststore contains the Athenz certificates from {@link #athenzTruststorePath()}
+ * and additional certificate authorities that issues trusted server certificates.
+ *
+ * @return Path to client truststore in PEM format
+ */
+ Path clientTruststorePath();
+
}
diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identity/SiaIdentityProvider.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identity/SiaIdentityProvider.java
index 082925048cb..a2a773ac751 100644
--- a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identity/SiaIdentityProvider.java
+++ b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identity/SiaIdentityProvider.java
@@ -3,7 +3,6 @@ package com.yahoo.vespa.athenz.identity;
import com.google.inject.Inject;
import com.yahoo.component.AbstractComponent;
-import com.yahoo.security.KeyStoreType;
import com.yahoo.security.SslContextBuilder;
import com.yahoo.security.X509CertificateWithKey;
import com.yahoo.security.tls.AutoReloadingX509KeyManager;
@@ -28,6 +27,8 @@ public class SiaIdentityProvider extends AbstractComponent implements ServiceIde
private final AthenzIdentity service;
private final Path certificateFile;
private final Path privateKeyFile;
+ private final Path clientTruststoreFile;
+ private final Path athenzTruststoreFile;
@Inject
public SiaIdentityProvider(SiaProviderConfig config) {
@@ -35,29 +36,32 @@ public class SiaIdentityProvider extends AbstractComponent implements ServiceIde
SiaUtils.getPrivateKeyFile(Paths.get(config.keyPathPrefix()), new AthenzService(config.athenzDomain(), config.athenzService())),
SiaUtils.getCertificateFile(Paths.get(config.keyPathPrefix()), new AthenzService(config.athenzDomain(), config.athenzService())),
Paths.get(config.trustStorePath()),
- config.trustStoreType());
+ Paths.get(config.athenzTruststorePath()));
}
public SiaIdentityProvider(AthenzIdentity service,
Path siaPath,
- Path trustStoreFile) {
+ Path clientTruststoreFile,
+ Path athenzTruststoreFile) {
this(service,
- SiaUtils.getPrivateKeyFile(siaPath, service),
- SiaUtils.getCertificateFile(siaPath, service),
- trustStoreFile,
- SiaProviderConfig.TrustStoreType.Enum.jks);
+ SiaUtils.getPrivateKeyFile(siaPath, service),
+ SiaUtils.getCertificateFile(siaPath, service),
+ athenzTruststoreFile,
+ clientTruststoreFile);
}
public SiaIdentityProvider(AthenzIdentity service,
Path privateKeyFile,
Path certificateFile,
- Path trustStoreFile,
- SiaProviderConfig.TrustStoreType.Enum trustStoreType) {
+ Path athenzTruststoreFile,
+ Path clientTruststoreFile) {
this.service = service;
this.keyManager = AutoReloadingX509KeyManager.fromPemFiles(privateKeyFile, certificateFile);
- this.sslContext = createIdentitySslContext(keyManager, trustStoreFile, trustStoreType);
+ this.sslContext = createIdentitySslContext(keyManager, clientTruststoreFile);
this.certificateFile = certificateFile;
this.privateKeyFile = privateKeyFile;
+ this.athenzTruststoreFile = athenzTruststoreFile;
+ this.clientTruststoreFile = clientTruststoreFile;
}
@Override
@@ -73,18 +77,14 @@ public class SiaIdentityProvider extends AbstractComponent implements ServiceIde
@Override public X509CertificateWithKey getIdentityCertificateWithKey() { return keyManager.getCurrentCertificateWithKey(); }
@Override public Path certificatePath() { return certificateFile; }
@Override public Path privateKeyPath() { return privateKeyFile; }
+ @Override public Path athenzTruststorePath() { return athenzTruststoreFile; }
+ @Override public Path clientTruststorePath() { return clientTruststoreFile; }
- private static SSLContext createIdentitySslContext(AutoReloadingX509KeyManager keyManager, Path trustStoreFile,
- SiaProviderConfig.TrustStoreType.Enum trustStoreType) {
- var builder = new SslContextBuilder();
- if (trustStoreType == SiaProviderConfig.TrustStoreType.Enum.pem) {
- builder = builder.withTrustStore(trustStoreFile);
- } else if (trustStoreType == SiaProviderConfig.TrustStoreType.Enum.jks) {
- builder = builder.withTrustStore(trustStoreFile, KeyStoreType.JKS);
- } else {
- throw new IllegalArgumentException("Unsupported trust store type: " + trustStoreType);
- }
- return builder.withKeyManager(keyManager).build();
+ private static SSLContext createIdentitySslContext(AutoReloadingX509KeyManager keyManager, Path trustStoreFile) {
+ return new SslContextBuilder()
+ .withTrustStore(trustStoreFile)
+ .withKeyManager(keyManager)
+ .build();
}
@Override
diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/client/AthenzIdentityProviderImpl.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/client/AthenzIdentityProviderImpl.java
index cc6061cb172..4cbfd4f9698 100644
--- a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/client/AthenzIdentityProviderImpl.java
+++ b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/client/AthenzIdentityProviderImpl.java
@@ -11,7 +11,6 @@ import com.yahoo.container.jdisc.athenz.AthenzIdentityProvider;
import com.yahoo.container.jdisc.athenz.AthenzIdentityProviderException;
import com.yahoo.jdisc.Metric;
import com.yahoo.security.KeyStoreBuilder;
-import com.yahoo.security.KeyStoreType;
import com.yahoo.security.Pkcs10Csr;
import com.yahoo.security.SslContextBuilder;
import com.yahoo.security.X509CertificateWithKey;
@@ -47,7 +46,6 @@ import java.util.function.Function;
import java.util.logging.Level;
import java.util.logging.Logger;
-import static com.yahoo.security.KeyStoreType.JKS;
import static com.yahoo.security.KeyStoreType.PKCS12;
/**
@@ -69,8 +67,9 @@ public final class AthenzIdentityProviderImpl extends AbstractComponent implemen
private final static Duration ROLE_SSL_CONTEXT_EXPIRY = Duration.ofHours(24);
private final static Duration ROLE_TOKEN_EXPIRY = Duration.ofMinutes(30);
- // TODO Make path to trust store config
- private static final Path DEFAULT_TRUST_STORE = Paths.get("/opt/yahoo/share/ssl/certs/yahoo_certificate_bundle.jks");
+ // TODO Make path to trust store paths config
+ private static final Path CLIENT_TRUST_STORE = Paths.get("/opt/yahoo/share/ssl/certs/yahoo_certificate_bundle.pem");
+ private static final Path ATHENZ_TRUST_STORE = Paths.get("/opt/yahoo/share/ssl/certs/athenz_certificate_bundle.pem");
public static final String CERTIFICATE_EXPIRY_METRIC_NAME = "athenz-tenant-cert.expiry.seconds";
@@ -96,9 +95,9 @@ public final class AthenzIdentityProviderImpl extends AbstractComponent implemen
public AthenzIdentityProviderImpl(IdentityConfig config, Metric metric) {
this(config,
metric,
- DEFAULT_TRUST_STORE,
+ CLIENT_TRUST_STORE,
new AthenzCredentialsService(config,
- createNodeIdentityProvider(config, DEFAULT_TRUST_STORE),
+ createNodeIdentityProvider(config),
Defaults.getDefaults().vespaHostname(),
Clock.systemUTC()),
new ScheduledThreadPoolExecutor(1),
@@ -144,7 +143,7 @@ public final class AthenzIdentityProviderImpl extends AbstractComponent implemen
private static SSLContext createIdentitySslContext(X509ExtendedKeyManager keyManager, Path trustStore) {
return new SslContextBuilder()
.withKeyManager(keyManager)
- .withTrustStore(trustStore, JKS)
+ .withTrustStore(trustStore)
.build();
}
@@ -188,6 +187,10 @@ public final class AthenzIdentityProviderImpl extends AbstractComponent implemen
@Override public Path privateKeyPath() { return athenzCredentialsService.privateKeyPath(); }
+ @Override public Path athenzTruststorePath() { return ATHENZ_TRUST_STORE; }
+
+ @Override public Path clientTruststorePath() { return CLIENT_TRUST_STORE; }
+
@Override
public SSLContext getRoleSslContext(String domain, String role) {
// This ssl context should ideally be cached as it is quite expensive to create.
@@ -256,7 +259,7 @@ public final class AthenzIdentityProviderImpl extends AbstractComponent implemen
X509Certificate roleCertificate = client.getRoleCertificate(role, csr);
return new SslContextBuilder()
.withKeyStore(credentials.getKeyPair().getPrivate(), roleCertificate)
- .withTrustStore(trustStore, KeyStoreType.JKS)
+ .withTrustStore(trustStore)
.build();
}
}
@@ -299,9 +302,9 @@ public final class AthenzIdentityProviderImpl extends AbstractComponent implemen
}
}
- private static SiaIdentityProvider createNodeIdentityProvider(IdentityConfig config, Path trustStore) {
+ private static SiaIdentityProvider createNodeIdentityProvider(IdentityConfig config) {
return new SiaIdentityProvider(
- new AthenzService(config.nodeIdentityName()), SiaUtils.DEFAULT_SIA_DIRECTORY, trustStore);
+ new AthenzService(config.nodeIdentityName()), SiaUtils.DEFAULT_SIA_DIRECTORY, CLIENT_TRUST_STORE, ATHENZ_TRUST_STORE);
}
private boolean isExpired(AthenzCredentials credentials) {
diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/utils/SiaUtils.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/utils/SiaUtils.java
index 12a8c3f911e..894c04df233 100644
--- a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/utils/SiaUtils.java
+++ b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/utils/SiaUtils.java
@@ -53,10 +53,11 @@ public class SiaUtils {
}
public static Path getCaCertificatesFile() {
- // The contents of this is the same as /opt/yahoo/share/ssl/certs/athenz_certificate_bundle.pem installed
- // by the yahoo_certificates_bundle RPM package, except the latter also contains a textual description
- // (decoded) of the certificates.
- return DEFAULT_SIA_DIRECTORY.resolve("certs").resolve("ca.cert.pem");
+ return getCaCertificatesFile(DEFAULT_SIA_DIRECTORY);
+ }
+
+ public static Path getCaCertificatesFile(Path root) {
+ return root.resolve("certs").resolve("ca.cert.pem");
}
public static Optional<PrivateKey> readPrivateKeyFile(AthenzIdentity service) {
diff --git a/vespa-athenz/src/test/java/com/yahoo/vespa/athenz/identity/SiaIdentityProviderTest.java b/vespa-athenz/src/test/java/com/yahoo/vespa/athenz/identity/SiaIdentityProviderTest.java
index 1fe32561f82..b7db502b1d0 100644
--- a/vespa-athenz/src/test/java/com/yahoo/vespa/athenz/identity/SiaIdentityProviderTest.java
+++ b/vespa-athenz/src/test/java/com/yahoo/vespa/athenz/identity/SiaIdentityProviderTest.java
@@ -2,15 +2,11 @@
package com.yahoo.vespa.athenz.identity;
import com.yahoo.security.KeyAlgorithm;
-import com.yahoo.security.KeyStoreBuilder;
-import com.yahoo.security.KeyStoreType;
-import com.yahoo.security.KeyStoreUtils;
import com.yahoo.security.KeyUtils;
import com.yahoo.security.SignatureAlgorithm;
import com.yahoo.security.X509CertificateBuilder;
import com.yahoo.security.X509CertificateUtils;
import com.yahoo.vespa.athenz.api.AthenzService;
-import com.yahoo.yolean.Exceptions;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
@@ -21,11 +17,11 @@ import java.io.IOException;
import java.math.BigInteger;
import java.nio.file.Files;
import java.security.KeyPair;
-import java.security.KeyStore;
import java.security.cert.X509Certificate;
import java.time.Duration;
import java.time.Instant;
+import static com.yahoo.yolean.Exceptions.uncheck;
import static org.junit.Assert.assertNotNull;
/**
@@ -55,7 +51,7 @@ public class SiaIdentityProviderTest {
keyFile.toPath(),
certificateFile.toPath(),
trustStoreFile.toPath(),
- SiaProviderConfig.TrustStoreType.Enum.jks);
+ trustStoreFile.toPath());
assertNotNull(provider.getIdentitySslContext());
}
@@ -79,7 +75,7 @@ public class SiaIdentityProviderTest {
keyFile.toPath(),
certificateFile.toPath(),
trustStoreFile.toPath(),
- SiaProviderConfig.TrustStoreType.Enum.pem);
+ trustStoreFile.toPath());
assertNotNull(provider.getIdentitySslContext());
}
@@ -109,14 +105,11 @@ public class SiaIdentityProviderTest {
private void createPemTrustStoreFile(X509Certificate certificate, File trustStoreFile) {
var pemEncoded = X509CertificateUtils.toPem(certificate);
- Exceptions.uncheck(() -> Files.writeString(trustStoreFile.toPath(), pemEncoded));
+ uncheck(() -> Files.writeString(trustStoreFile.toPath(), pemEncoded));
}
private void createTrustStoreFile(X509Certificate certificate, File trustStoreFile) {
- KeyStore keystore = KeyStoreBuilder.withType(KeyStoreType.JKS)
- .withCertificateEntry("dummy-cert", certificate)
- .build();
- KeyStoreUtils.writeKeyStoreToFile(keystore, trustStoreFile.toPath());
+ uncheck(() -> Files.writeString(trustStoreFile.toPath(), X509CertificateUtils.toPem(certificate)));
}
}