diff options
author | Bjørn Christian Seime <bjorncs@oath.com> | 2017-12-04 15:59:06 +0100 |
---|---|---|
committer | Bjørn Christian Seime <bjorncs@oath.com> | 2017-12-04 16:01:58 +0100 |
commit | b31044f987e3cc28d37f3d37460dbdde0462e9b6 (patch) | |
tree | 1fd6b85969529e05306fca4385493a4533900ff6 /athenz-identity-provider-service/src/main | |
parent | d164fbb93e277ef23ab610320a7cf8556e3c036e (diff) |
Add trust store configurator with config server's CA cert
Diffstat (limited to 'athenz-identity-provider-service/src/main')
3 files changed, 116 insertions, 1 deletions
diff --git a/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/AthenzSslTrustStoreConfigurator.java b/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/AthenzSslTrustStoreConfigurator.java new file mode 100644 index 00000000000..6855ffbf386 --- /dev/null +++ b/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/AthenzSslTrustStoreConfigurator.java @@ -0,0 +1,109 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.hosted.athenz.instanceproviderservice; + +import com.google.inject.Inject; +import com.yahoo.cloud.config.ConfigserverConfig; +import com.yahoo.jdisc.http.ssl.SslTrustStoreConfigurator; +import com.yahoo.jdisc.http.ssl.SslTrustStoreContext; +import com.yahoo.log.LogLevel; +import com.yahoo.vespa.hosted.athenz.instanceproviderservice.config.AthenzProviderServiceConfig; +import org.bouncycastle.asn1.ASN1ObjectIdentifier; +import org.bouncycastle.asn1.x500.X500Name; +import org.bouncycastle.asn1.x509.BasicConstraints; +import org.bouncycastle.asn1.x509.Extension; +import org.bouncycastle.asn1.x509.GeneralName; +import org.bouncycastle.asn1.x509.GeneralNames; +import org.bouncycastle.cert.X509v3CertificateBuilder; +import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter; +import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.operator.ContentSigner; +import org.bouncycastle.operator.OperatorCreationException; +import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; + +import java.io.IOException; +import java.math.BigInteger; +import java.security.KeyPair; +import java.security.KeyStore; +import java.security.Provider; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.time.Duration; +import java.time.Instant; +import java.util.Date; +import java.util.logging.Logger; + +/** + * @author bjorncs + */ +// TODO Add Athenz CA certificates to trust store +public class AthenzSslTrustStoreConfigurator implements SslTrustStoreConfigurator { + + private static final Logger log = Logger.getLogger(AthenzSslTrustStoreConfigurator.class.getName()); + + private static final Provider provider = new BouncyCastleProvider(); + private final KeyStore trustStore; + + @Inject + public AthenzSslTrustStoreConfigurator(KeyProvider keyProvider, + ConfigserverConfig configserverConfig, + AthenzProviderServiceConfig athenzProviderServiceConfig) { + this.trustStore = createTrustStore(keyProvider, configserverConfig, athenzProviderServiceConfig); + } + + @Override + public void configure(SslTrustStoreContext sslTrustStoreContext) { + sslTrustStoreContext.updateTrustStore(trustStore); + log.log(LogLevel.INFO, "Configured JDisc trust store with self-signed certificate"); + } + + private static KeyStore createTrustStore(KeyProvider keyProvider, + ConfigserverConfig configserverConfig, + AthenzProviderServiceConfig athenzProviderServiceConfig) { + try { + KeyPair keyPair = getKeyPair(keyProvider, configserverConfig, athenzProviderServiceConfig); + X509Certificate selfSignedCertificate = createSelfSignedCertificate(keyPair, configserverConfig); + log.log(LogLevel.FINE, "Generated self-signed certificate: " + selfSignedCertificate); + KeyStore trustStore = KeyStore.getInstance("JKS"); + trustStore.load(null); + trustStore.setCertificateEntry("cfgselfsigned", selfSignedCertificate); + return trustStore; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private static KeyPair getKeyPair(KeyProvider keyProvider, + ConfigserverConfig configserverConfig, + AthenzProviderServiceConfig athenzProviderServiceConfig) { + String key = configserverConfig.environment() + "." + configserverConfig.region(); + AthenzProviderServiceConfig.Zones zoneConfig = athenzProviderServiceConfig.zones(key); + return keyProvider.getKeyPair(zoneConfig.secretVersion()); + } + + private static X509Certificate createSelfSignedCertificate(KeyPair keyPair, ConfigserverConfig config) + throws IOException, CertificateException, OperatorCreationException { + ContentSigner contentSigner = new JcaContentSignerBuilder("SHA256WithRSA").build(keyPair.getPrivate()); + X500Name x500Name = new X500Name("CN="+ config.loadBalancerAddress()); + Instant now = Instant.now(); + Date notBefore = Date.from(now); + Date notAfter = Date.from(now.plus(Duration.ofDays(30))); + + GeneralNames generalNames = new GeneralNames( + config.zookeeperserver().stream() + .map(server -> new GeneralName(GeneralName.dNSName, server.hostname())) + .toArray(GeneralName[]::new)); + + X509v3CertificateBuilder certificateBuilder = + new JcaX509v3CertificateBuilder( + x500Name, BigInteger.valueOf(now.toEpochMilli()), notBefore, notAfter, x500Name, keyPair.getPublic() + ) + .addExtension(new ASN1ObjectIdentifier("2.5.29.19"), true, new BasicConstraints(true)) + .addExtension(Extension.subjectAlternativeName, false, generalNames); + + return new JcaX509CertificateConverter() + .setProvider(provider) + .getCertificate(certificateBuilder.build(contentSigner)); + } + +} diff --git a/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/KeyProvider.java b/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/KeyProvider.java index a72a2fcbc6c..1d141099428 100644 --- a/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/KeyProvider.java +++ b/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/KeyProvider.java @@ -1,6 +1,7 @@ // Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.hosted.athenz.instanceproviderservice; +import java.security.KeyPair; import java.security.PrivateKey; import java.security.PublicKey; @@ -11,4 +12,8 @@ public interface KeyProvider { PrivateKey getPrivateKey(int version); PublicKey getPublicKey(int version); + + default KeyPair getKeyPair(int version) { + return new KeyPair(getPublicKey(version), getPrivateKey(version)); + } } diff --git a/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/impl/SecretStoreKeyProvider.java b/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/impl/SecretStoreKeyProvider.java index e66131b6cf7..ac8c0eabf31 100644 --- a/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/impl/SecretStoreKeyProvider.java +++ b/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/impl/SecretStoreKeyProvider.java @@ -45,7 +45,8 @@ public class SecretStoreKeyProvider implements KeyProvider { return getKeyPair(version).getPublic(); } - private KeyPair getKeyPair(int version) { + @Override + public KeyPair getKeyPair(int version) { synchronized (secrets) { KeyPair keyPair = secrets.get(version); if (keyPair == null) { |