summaryrefslogtreecommitdiffstats
path: root/vespa-athenz
diff options
context:
space:
mode:
authorHarald Musum <musum@verizonmedia.com>2020-05-28 18:31:38 +0200
committerGitHub <noreply@github.com>2020-05-28 18:31:38 +0200
commitab6c2c71d7d98120b09345b8e2cc59ec8374bb89 (patch)
tree78f5fcf60e8ce01af7c04b2b9b334ca0da4dbffb /vespa-athenz
parentfd776f01675f8e86a03e07e98fd84cf5ba5f4372 (diff)
Revert "Expose underlying certificate and private key from SiaIdentityProvider "
Diffstat (limited to 'vespa-athenz')
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identity/ServiceIdentityProvider.java44
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identity/SiaIdentityProvider.java64
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/client/AthenzCredentialsService.java3
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/client/AthenzIdentityProviderImpl.java36
-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.java29
6 files changed, 63 insertions, 122 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 f6888acb018..e5ed885b316 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
@@ -2,56 +2,18 @@
package com.yahoo.vespa.athenz.identity;
import com.yahoo.container.jdisc.athenz.AthenzIdentityProvider;
-import com.yahoo.security.X509CertificateWithKey;
import com.yahoo.vespa.athenz.api.AthenzIdentity;
+import com.yahoo.vespa.athenz.api.AthenzService;
import javax.net.ssl.SSLContext;
-import java.nio.file.Path;
/**
- * A interface for types that provides the Athenz service identity (SIA) from the environment.
- * Some similarities to {@link AthenzIdentityProvider}, but this type is not public API and intended for internal use.
+ * A interface for types that provides a service identity.
+ * Some similarities to {@link AthenzIdentityProvider}, but this type is not public api and intended for internal use.
*
* @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 a2a773ac751..4981b80998f 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,14 +3,15 @@ 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;
import com.yahoo.vespa.athenz.api.AthenzIdentity;
import com.yahoo.vespa.athenz.api.AthenzService;
import com.yahoo.vespa.athenz.utils.SiaUtils;
import javax.net.ssl.SSLContext;
+import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
@@ -25,43 +26,34 @@ public class SiaIdentityProvider extends AbstractComponent implements ServiceIde
private final AutoReloadingX509KeyManager keyManager;
private final SSLContext sslContext;
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) {
this(new AthenzService(config.athenzDomain(), config.athenzService()),
- 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()),
- Paths.get(config.athenzTruststorePath()));
+ SiaUtils.getPrivateKeyFile(Paths.get(config.keyPathPrefix()), new AthenzService(config.athenzDomain(), config.athenzService())).toFile(),
+ SiaUtils.getCertificateFile(Paths.get(config.keyPathPrefix()), new AthenzService(config.athenzDomain(), config.athenzService())).toFile(),
+ new File(config.trustStorePath()),
+ config.trustStoreType());
}
public SiaIdentityProvider(AthenzIdentity service,
Path siaPath,
- Path clientTruststoreFile,
- Path athenzTruststoreFile) {
+ File trustStoreFile) {
this(service,
- SiaUtils.getPrivateKeyFile(siaPath, service),
- SiaUtils.getCertificateFile(siaPath, service),
- athenzTruststoreFile,
- clientTruststoreFile);
+ SiaUtils.getPrivateKeyFile(siaPath, service).toFile(),
+ SiaUtils.getCertificateFile(siaPath, service).toFile(),
+ trustStoreFile,
+ SiaProviderConfig.TrustStoreType.Enum.jks);
}
public SiaIdentityProvider(AthenzIdentity service,
- Path privateKeyFile,
- Path certificateFile,
- Path athenzTruststoreFile,
- Path clientTruststoreFile) {
+ File privateKeyFile,
+ File certificateFile,
+ File trustStoreFile,
+ SiaProviderConfig.TrustStoreType.Enum trustStoreType) {
this.service = service;
- this.keyManager = AutoReloadingX509KeyManager.fromPemFiles(privateKeyFile, certificateFile);
- this.sslContext = createIdentitySslContext(keyManager, clientTruststoreFile);
- this.certificateFile = certificateFile;
- this.privateKeyFile = privateKeyFile;
- this.athenzTruststoreFile = athenzTruststoreFile;
- this.clientTruststoreFile = clientTruststoreFile;
+ this.keyManager = AutoReloadingX509KeyManager.fromPemFiles(privateKeyFile.toPath(), certificateFile.toPath());
+ this.sslContext = createIdentitySslContext(keyManager, trustStoreFile.toPath(), trustStoreType);
}
@Override
@@ -74,17 +66,17 @@ public class SiaIdentityProvider extends AbstractComponent implements ServiceIde
return sslContext;
}
- @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) {
- return new SslContextBuilder()
- .withTrustStore(trustStoreFile)
- .withKeyManager(keyManager)
- .build();
+ 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();
}
@Override
diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/client/AthenzCredentialsService.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/client/AthenzCredentialsService.java
index 8e029906c30..3b733e05708 100644
--- a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/client/AthenzCredentialsService.java
+++ b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/client/AthenzCredentialsService.java
@@ -64,9 +64,6 @@ class AthenzCredentialsService {
this.clock = clock;
}
- Path certificatePath() { return SiaUtils.getCertificateFile(VESPA_SIA_DIRECTORY, tenantIdentity); }
- Path privateKeyPath() { return SiaUtils.getPrivateKeyFile(VESPA_SIA_DIRECTORY, tenantIdentity); }
-
AthenzCredentials registerInstance() {
Optional<AthenzCredentials> athenzCredentialsFromDisk = tryReadCredentialsFromDisk();
if (athenzCredentialsFromDisk.isPresent()) {
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 62c5820c927..b816acfad38 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,9 +11,9 @@ 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;
import com.yahoo.security.tls.MutableX509KeyManager;
import com.yahoo.vespa.athenz.api.AthenzAccessToken;
import com.yahoo.vespa.athenz.api.AthenzDomain;
@@ -47,6 +47,7 @@ import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
+import static com.yahoo.security.KeyStoreType.JKS;
import static com.yahoo.security.KeyStoreType.PKCS12;
/**
@@ -55,8 +56,6 @@ import static com.yahoo.security.KeyStoreType.PKCS12;
* @author mortent
* @author bjorncs
*/
-// This class should probably not implement ServiceIdentityProvider,
-// as that interface is intended for providing the node's identity, not the tenant's application identity.
public final class AthenzIdentityProviderImpl extends AbstractComponent implements AthenzIdentityProvider, ServiceIdentityProvider {
private static final Logger log = Logger.getLogger(AthenzIdentityProviderImpl.class.getName());
@@ -68,9 +67,8 @@ 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 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");
+ // 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");
public static final String CERTIFICATE_EXPIRY_METRIC_NAME = "athenz-tenant-cert.expiry.seconds";
@@ -96,9 +94,9 @@ public final class AthenzIdentityProviderImpl extends AbstractComponent implemen
public AthenzIdentityProviderImpl(IdentityConfig config, Metric metric) {
this(config,
metric,
- CLIENT_TRUST_STORE,
+ DEFAULT_TRUST_STORE,
new AthenzCredentialsService(config,
- createNodeIdentityProvider(config),
+ createNodeIdentityProvider(config, DEFAULT_TRUST_STORE),
Defaults.getDefaults().vespaHostname(),
Clock.systemUTC()),
new ScheduledThreadPoolExecutor(1),
@@ -144,7 +142,7 @@ public final class AthenzIdentityProviderImpl extends AbstractComponent implemen
private static SSLContext createIdentitySslContext(X509ExtendedKeyManager keyManager, Path trustStore) {
return new SslContextBuilder()
.withKeyManager(keyManager)
- .withTrustStore(trustStore)
+ .withTrustStore(trustStore, JKS)
.build();
}
@@ -179,20 +177,6 @@ public final class AthenzIdentityProviderImpl extends AbstractComponent implemen
}
@Override
- public X509CertificateWithKey getIdentityCertificateWithKey() {
- AthenzCredentials copy = this.credentials;
- return new X509CertificateWithKey(copy.getCertificate(), copy.getKeyPair().getPrivate());
- }
-
- @Override public Path certificatePath() { return athenzCredentialsService.certificatePath(); }
-
- @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.
try {
@@ -271,7 +255,7 @@ public final class AthenzIdentityProviderImpl extends AbstractComponent implemen
X509Certificate roleCertificate = client.getRoleCertificate(role, csr);
return new SslContextBuilder()
.withKeyStore(credentials.getKeyPair().getPrivate(), roleCertificate)
- .withTrustStore(trustStore)
+ .withTrustStore(trustStore, KeyStoreType.JKS)
.build();
}
}
@@ -314,9 +298,9 @@ public final class AthenzIdentityProviderImpl extends AbstractComponent implemen
}
}
- private static SiaIdentityProvider createNodeIdentityProvider(IdentityConfig config) {
+ private static SiaIdentityProvider createNodeIdentityProvider(IdentityConfig config, Path trustStore) {
return new SiaIdentityProvider(
- new AthenzService(config.nodeIdentityName()), SiaUtils.DEFAULT_SIA_DIRECTORY, CLIENT_TRUST_STORE, ATHENZ_TRUST_STORE);
+ new AthenzService(config.nodeIdentityName()), SiaUtils.DEFAULT_SIA_DIRECTORY, trustStore.toFile());
}
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 894c04df233..12a8c3f911e 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,11 +53,10 @@ public class SiaUtils {
}
public static Path getCaCertificatesFile() {
- return getCaCertificatesFile(DEFAULT_SIA_DIRECTORY);
- }
-
- public static Path getCaCertificatesFile(Path root) {
- return root.resolve("certs").resolve("ca.cert.pem");
+ // 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");
}
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 b7db502b1d0..ce02860cc78 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,11 +2,15 @@
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;
@@ -17,11 +21,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;
/**
@@ -48,10 +52,10 @@ public class SiaIdentityProviderTest {
SiaIdentityProvider provider =
new SiaIdentityProvider(
new AthenzService("domain", "service-name"),
- keyFile.toPath(),
- certificateFile.toPath(),
- trustStoreFile.toPath(),
- trustStoreFile.toPath());
+ keyFile,
+ certificateFile,
+ trustStoreFile,
+ SiaProviderConfig.TrustStoreType.Enum.jks);
assertNotNull(provider.getIdentitySslContext());
}
@@ -72,10 +76,10 @@ public class SiaIdentityProviderTest {
SiaIdentityProvider provider =
new SiaIdentityProvider(
new AthenzService("domain", "service-name"),
- keyFile.toPath(),
- certificateFile.toPath(),
- trustStoreFile.toPath(),
- trustStoreFile.toPath());
+ keyFile,
+ certificateFile,
+ trustStoreFile,
+ SiaProviderConfig.TrustStoreType.Enum.pem);
assertNotNull(provider.getIdentitySslContext());
}
@@ -105,11 +109,14 @@ public class SiaIdentityProviderTest {
private void createPemTrustStoreFile(X509Certificate certificate, File trustStoreFile) {
var pemEncoded = X509CertificateUtils.toPem(certificate);
- uncheck(() -> Files.writeString(trustStoreFile.toPath(), pemEncoded));
+ Exceptions.uncheck(() -> Files.writeString(trustStoreFile.toPath(), pemEncoded));
}
private void createTrustStoreFile(X509Certificate certificate, File trustStoreFile) {
- uncheck(() -> Files.writeString(trustStoreFile.toPath(), X509CertificateUtils.toPem(certificate)));
+ KeyStore keystore = KeyStoreBuilder.withType(KeyStoreType.JKS)
+ .withCertificateEntry("dummy-cert", certificate)
+ .build();
+ KeyStoreUtils.writeKeyStoreToFile(keystore, trustStoreFile.toPath());
}
}