From 20692f5761367faa3bdd4d3e732eaf8c499ecbb0 Mon Sep 17 00:00:00 2001 From: Bjørn Christian Seime Date: Wed, 6 Dec 2017 13:18:08 +0100 Subject: Don't warn when actual expiry is longer than expected --- .../AthenzSslKeyStoreConfigurator.java | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/AthenzSslKeyStoreConfigurator.java b/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/AthenzSslKeyStoreConfigurator.java index 3b7d05bf026..ed68372c164 100644 --- a/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/AthenzSslKeyStoreConfigurator.java +++ b/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/AthenzSslKeyStoreConfigurator.java @@ -15,7 +15,6 @@ import java.security.PrivateKey; import java.security.cert.Certificate; import java.security.cert.X509Certificate; import java.time.Duration; -import java.time.Instant; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; @@ -84,7 +83,7 @@ public class AthenzSslKeyStoreConfigurator extends AbstractComponent implements log.log(LogLevel.INFO, "Updating Athenz certificate from ZTS"); PrivateKey privateKey = keyProvider.getPrivateKey(zoneConfig.secretVersion()); X509Certificate certificate = certificateClient.updateCertificate(privateKey, CERTIFICATE_EXPIRY_TIME); - verifyActualExperiy(certificate); + verifyActualExpiry(certificate); String dummyPassword = "athenz"; KeyStore keyStore = KeyStore.getInstance("JKS"); @@ -97,11 +96,10 @@ public class AthenzSslKeyStoreConfigurator extends AbstractComponent implements } } - private void verifyActualExperiy(X509Certificate certificate) { - Instant notAfter = certificate.getNotAfter().toInstant(); - Instant notBefore = certificate.getNotBefore().toInstant(); - if (!notBefore.plus(CERTIFICATE_EXPIRY_TIME).equals(notAfter)) { - Duration actualExpiry = Duration.between(notBefore, notAfter); + private void verifyActualExpiry(X509Certificate certificate) { + Duration actualExpiry = + Duration.between(certificate.getNotBefore().toInstant(), certificate.getNotAfter().toInstant()); + if (CERTIFICATE_EXPIRY_TIME.compareTo(actualExpiry) > 0) { log.log(LogLevel.WARNING, String.format("Expected expiry %s, got %s", CERTIFICATE_EXPIRY_TIME, actualExpiry)); } -- cgit v1.2.3 From 7da97d9ff23a5bfa9e9270b01adf28d2f4a6a8ab Mon Sep 17 00:00:00 2001 From: Bjørn Christian Seime Date: Wed, 6 Dec 2017 14:40:42 +0100 Subject: Retrieve initial certificate in constructor for fail-fast semantics --- .../AthenzSslKeyStoreConfigurator.java | 60 +++++++++++++++------- 1 file changed, 41 insertions(+), 19 deletions(-) diff --git a/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/AthenzSslKeyStoreConfigurator.java b/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/AthenzSslKeyStoreConfigurator.java index ed68372c164..2492e8fddf2 100644 --- a/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/AthenzSslKeyStoreConfigurator.java +++ b/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/AthenzSslKeyStoreConfigurator.java @@ -10,15 +10,20 @@ import com.yahoo.log.LogLevel; import com.yahoo.vespa.hosted.athenz.instanceproviderservice.config.AthenzProviderServiceConfig; import com.yahoo.vespa.hosted.athenz.instanceproviderservice.impl.AthenzCertificateClient; +import java.io.IOException; import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.cert.Certificate; +import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.time.Duration; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; import java.util.logging.Logger; import static com.yahoo.vespa.hosted.athenz.instanceproviderservice.impl.Utils.getZoneConfig; @@ -33,12 +38,14 @@ public class AthenzSslKeyStoreConfigurator extends AbstractComponent implements // TODO Make expiry and update frequency configurable parameters private static final Duration CERTIFICATE_EXPIRY_TIME = Duration.ofDays(30); private static final Duration CERTIFICATE_UPDATE_PERIOD = Duration.ofDays(7); + private static final String DUMMY_PASSWORD = "athenz"; private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(); private final AthenzCertificateClient certificateClient; private final KeyProvider keyProvider; private final AthenzProviderServiceConfig.Zones zoneConfig; private final AtomicBoolean alreadyConfigured = new AtomicBoolean(); + private final AtomicReference initialKeyStore = new AtomicReference<>(); @Inject public AthenzSslKeyStoreConfigurator(KeyProvider keyProvider, @@ -48,6 +55,7 @@ public class AthenzSslKeyStoreConfigurator extends AbstractComponent implements this.certificateClient = new AthenzCertificateClient(config, zoneConfig); this.keyProvider = keyProvider; this.zoneConfig = zoneConfig; + this.initialKeyStore.set(downloadCertificate(keyProvider, certificateClient, zoneConfig)); } @Override @@ -55,8 +63,11 @@ public class AthenzSslKeyStoreConfigurator extends AbstractComponent implements if (alreadyConfigured.getAndSet(true)) { // For debugging purpose of SslKeyStoreConfigurator interface throw new IllegalStateException("Already configured. configure() can only be called once."); } - AthenzCertificateUpdater updater = new AthenzCertificateUpdater(sslKeyStoreContext); - scheduler.scheduleAtFixedRate(updater, /*initialDelay*/0, CERTIFICATE_UPDATE_PERIOD.toMinutes(), TimeUnit.MINUTES); + sslKeyStoreContext.updateKeyStore(initialKeyStore.getAndSet(null), DUMMY_PASSWORD); + scheduler.scheduleAtFixedRate(new AthenzCertificateUpdater(sslKeyStoreContext), + CERTIFICATE_UPDATE_PERIOD.toMinutes()/*initial delay*/, + CERTIFICATE_UPDATE_PERIOD.toMinutes(), + TimeUnit.MINUTES); } @Override @@ -69,6 +80,32 @@ public class AthenzSslKeyStoreConfigurator extends AbstractComponent implements } } + private static KeyStore downloadCertificate(KeyProvider keyProvider, + AthenzCertificateClient certificateClient, + AthenzProviderServiceConfig.Zones zoneConfig) { + try { + PrivateKey privateKey = keyProvider.getPrivateKey(zoneConfig.secretVersion()); + X509Certificate certificate = certificateClient.updateCertificate(privateKey, CERTIFICATE_EXPIRY_TIME); + verifyActualExpiry(certificate); + + KeyStore keyStore = KeyStore.getInstance("JKS"); + keyStore.load(null); + keyStore.setKeyEntry("athenz", privateKey, DUMMY_PASSWORD.toCharArray(), new Certificate[]{certificate}); + return keyStore; + } catch (IOException | NoSuchAlgorithmException | CertificateException | KeyStoreException e) { + throw new RuntimeException(e); + } + } + + private static void verifyActualExpiry(X509Certificate certificate) { + Duration actualExpiry = + Duration.between(certificate.getNotBefore().toInstant(), certificate.getNotAfter().toInstant()); + if (CERTIFICATE_EXPIRY_TIME.compareTo(actualExpiry) > 0) { + log.log(LogLevel.WARNING, + String.format("Expected expiry %s, got %s", CERTIFICATE_EXPIRY_TIME, actualExpiry)); + } + } + private class AthenzCertificateUpdater implements Runnable { private final SslKeyStoreContext sslKeyStoreContext; @@ -81,28 +118,13 @@ public class AthenzSslKeyStoreConfigurator extends AbstractComponent implements public void run() { try { log.log(LogLevel.INFO, "Updating Athenz certificate from ZTS"); - PrivateKey privateKey = keyProvider.getPrivateKey(zoneConfig.secretVersion()); - X509Certificate certificate = certificateClient.updateCertificate(privateKey, CERTIFICATE_EXPIRY_TIME); - verifyActualExpiry(certificate); - - String dummyPassword = "athenz"; - KeyStore keyStore = KeyStore.getInstance("JKS"); - keyStore.load(null); - keyStore.setKeyEntry("athenz", privateKey, dummyPassword.toCharArray(), new Certificate[]{certificate}); - sslKeyStoreContext.updateKeyStore(keyStore, dummyPassword); + KeyStore keyStore = downloadCertificate(keyProvider, certificateClient, zoneConfig); + sslKeyStoreContext.updateKeyStore(keyStore, DUMMY_PASSWORD); log.log(LogLevel.INFO, "Athenz certificate reload successfully completed"); } catch (Throwable e) { log.log(LogLevel.ERROR, "Failed to update certificate from ZTS: " + e.getMessage(), e); } } - private void verifyActualExpiry(X509Certificate certificate) { - Duration actualExpiry = - Duration.between(certificate.getNotBefore().toInstant(), certificate.getNotAfter().toInstant()); - if (CERTIFICATE_EXPIRY_TIME.compareTo(actualExpiry) > 0) { - log.log(LogLevel.WARNING, - String.format("Expected expiry %s, got %s", CERTIFICATE_EXPIRY_TIME, actualExpiry)); - } - } } } -- cgit v1.2.3 From f1fbd499da784fef06ef4f3bcaedf32d3ecc394a Mon Sep 17 00:00:00 2001 From: Bjørn Christian Seime Date: Wed, 6 Dec 2017 15:03:48 +0100 Subject: Remove unnecessary use of AtomicReference --- .../instanceproviderservice/AthenzSslKeyStoreConfigurator.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/AthenzSslKeyStoreConfigurator.java b/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/AthenzSslKeyStoreConfigurator.java index 2492e8fddf2..706f797cd2c 100644 --- a/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/AthenzSslKeyStoreConfigurator.java +++ b/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/AthenzSslKeyStoreConfigurator.java @@ -23,7 +23,6 @@ import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicReference; import java.util.logging.Logger; import static com.yahoo.vespa.hosted.athenz.instanceproviderservice.impl.Utils.getZoneConfig; @@ -45,7 +44,7 @@ public class AthenzSslKeyStoreConfigurator extends AbstractComponent implements private final KeyProvider keyProvider; private final AthenzProviderServiceConfig.Zones zoneConfig; private final AtomicBoolean alreadyConfigured = new AtomicBoolean(); - private final AtomicReference initialKeyStore = new AtomicReference<>(); + private KeyStore initialKeyStore; @Inject public AthenzSslKeyStoreConfigurator(KeyProvider keyProvider, @@ -55,7 +54,7 @@ public class AthenzSslKeyStoreConfigurator extends AbstractComponent implements this.certificateClient = new AthenzCertificateClient(config, zoneConfig); this.keyProvider = keyProvider; this.zoneConfig = zoneConfig; - this.initialKeyStore.set(downloadCertificate(keyProvider, certificateClient, zoneConfig)); + this.initialKeyStore = downloadCertificate(keyProvider, certificateClient, zoneConfig); } @Override @@ -63,7 +62,8 @@ public class AthenzSslKeyStoreConfigurator extends AbstractComponent implements if (alreadyConfigured.getAndSet(true)) { // For debugging purpose of SslKeyStoreConfigurator interface throw new IllegalStateException("Already configured. configure() can only be called once."); } - sslKeyStoreContext.updateKeyStore(initialKeyStore.getAndSet(null), DUMMY_PASSWORD); + sslKeyStoreContext.updateKeyStore(initialKeyStore, DUMMY_PASSWORD); + initialKeyStore = null; scheduler.scheduleAtFixedRate(new AthenzCertificateUpdater(sslKeyStoreContext), CERTIFICATE_UPDATE_PERIOD.toMinutes()/*initial delay*/, CERTIFICATE_UPDATE_PERIOD.toMinutes(), -- cgit v1.2.3