diff options
author | Bjørn Christian Seime <bjorncs@verizonmedia.com> | 2020-05-14 16:58:07 +0200 |
---|---|---|
committer | Bjørn Christian Seime <bjorncs@verizonmedia.com> | 2020-05-18 13:21:38 +0200 |
commit | cf8af6d6ce0be3dd565b1f7a14f0648d482b3e42 (patch) | |
tree | c2ee7c98daf6f35a988f9e45cb48b78f84b761f9 /vespa-athenz | |
parent | 73fa58e682c278b190ad89f7c74919b5e70b1d24 (diff) |
Expose underlying certificate and private key from SiaIdentityProvider
Extend ServiceIdentityProvider interface with new methods.
Add class that bundles certificate with private key.
Use Path instead of File for better compatibility with mocked file system in unit tests.
Diffstat (limited to 'vespa-athenz')
4 files changed, 48 insertions, 23 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 e5ed885b316..180d052c8dc 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,18 +2,22 @@ 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 a service identity. - * Some similarities to {@link AthenzIdentityProvider}, but this type is not public api and intended for internal use. + * 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. * * @author bjorncs */ public interface ServiceIdentityProvider { AthenzIdentity identity(); SSLContext getIdentitySslContext(); + X509CertificateWithKey getIdentityCertificateWithKey(); + Path certificatePath(); + Path privateKeyPath(); } 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 4981b80998f..082925048cb 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 @@ -5,13 +5,13 @@ 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; @@ -26,34 +26,38 @@ 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; @Inject public SiaIdentityProvider(SiaProviderConfig config) { this(new AthenzService(config.athenzDomain(), config.athenzService()), - 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()), + 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()); } public SiaIdentityProvider(AthenzIdentity service, Path siaPath, - File trustStoreFile) { + Path trustStoreFile) { this(service, - SiaUtils.getPrivateKeyFile(siaPath, service).toFile(), - SiaUtils.getCertificateFile(siaPath, service).toFile(), + SiaUtils.getPrivateKeyFile(siaPath, service), + SiaUtils.getCertificateFile(siaPath, service), trustStoreFile, SiaProviderConfig.TrustStoreType.Enum.jks); } public SiaIdentityProvider(AthenzIdentity service, - File privateKeyFile, - File certificateFile, - File trustStoreFile, + Path privateKeyFile, + Path certificateFile, + Path trustStoreFile, SiaProviderConfig.TrustStoreType.Enum trustStoreType) { this.service = service; - this.keyManager = AutoReloadingX509KeyManager.fromPemFiles(privateKeyFile.toPath(), certificateFile.toPath()); - this.sslContext = createIdentitySslContext(keyManager, trustStoreFile.toPath(), trustStoreType); + this.keyManager = AutoReloadingX509KeyManager.fromPemFiles(privateKeyFile, certificateFile); + this.sslContext = createIdentitySslContext(keyManager, trustStoreFile, trustStoreType); + this.certificateFile = certificateFile; + this.privateKeyFile = privateKeyFile; } @Override @@ -66,6 +70,10 @@ 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; } + private static SSLContext createIdentitySslContext(AutoReloadingX509KeyManager keyManager, Path trustStoreFile, SiaProviderConfig.TrustStoreType.Enum trustStoreType) { var builder = new SslContextBuilder(); 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 71a4c1a9954..a52ad159fdc 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 @@ -10,11 +10,11 @@ import com.yahoo.container.core.identity.IdentityConfig; import com.yahoo.container.jdisc.athenz.AthenzIdentityProvider; import com.yahoo.container.jdisc.athenz.AthenzIdentityProviderException; import com.yahoo.jdisc.Metric; -import java.util.logging.Level; 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; @@ -44,6 +44,7 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.function.Function; +import java.util.logging.Level; import java.util.logging.Logger; import static com.yahoo.security.KeyStoreType.JKS; @@ -55,6 +56,8 @@ 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()); @@ -176,6 +179,16 @@ public final class AthenzIdentityProviderImpl extends AbstractComponent implemen } @Override + public X509CertificateWithKey getIdentityCertificateWithKey() { + AthenzCredentials copy = this.credentials; + return new X509CertificateWithKey(copy.getCertificate(), copy.getKeyPair().getPrivate()); + } + + // The files should ideally not be used directly, must be implemented later if necessary + @Override public Path certificatePath() { throw new UnsupportedOperationException(); } + @Override public Path privateKeyPath() { throw new UnsupportedOperationException(); } + + @Override public SSLContext getRoleSslContext(String domain, String role) { // This ssl context should ideally be cached as it is quite expensive to create. try { @@ -288,7 +301,7 @@ public final class AthenzIdentityProviderImpl extends AbstractComponent implemen private static SiaIdentityProvider createNodeIdentityProvider(IdentityConfig config, Path trustStore) { return new SiaIdentityProvider( - new AthenzService(config.nodeIdentityName()), SiaUtils.DEFAULT_SIA_DIRECTORY, trustStore.toFile()); + new AthenzService(config.nodeIdentityName()), SiaUtils.DEFAULT_SIA_DIRECTORY, trustStore); } private boolean isExpired(AthenzCredentials credentials) { 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 ce02860cc78..1fe32561f82 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 @@ -52,9 +52,9 @@ public class SiaIdentityProviderTest { SiaIdentityProvider provider = new SiaIdentityProvider( new AthenzService("domain", "service-name"), - keyFile, - certificateFile, - trustStoreFile, + keyFile.toPath(), + certificateFile.toPath(), + trustStoreFile.toPath(), SiaProviderConfig.TrustStoreType.Enum.jks); assertNotNull(provider.getIdentitySslContext()); @@ -76,9 +76,9 @@ public class SiaIdentityProviderTest { SiaIdentityProvider provider = new SiaIdentityProvider( new AthenzService("domain", "service-name"), - keyFile, - certificateFile, - trustStoreFile, + keyFile.toPath(), + certificateFile.toPath(), + trustStoreFile.toPath(), SiaProviderConfig.TrustStoreType.Enum.pem); assertNotNull(provider.getIdentitySslContext()); |