diff options
author | Bjørn Christian Seime <bjorncs@oath.com> | 2018-06-13 16:28:13 +0200 |
---|---|---|
committer | Bjørn Christian Seime <bjorncs@oath.com> | 2018-06-13 16:28:20 +0200 |
commit | ffe8ed4966e26fd5cc0e5944900f2ac457c542bf (patch) | |
tree | f708d0eae612f293fda13bb792e7295b156d1eb2 /athenz-identity-provider-service | |
parent | 1003fa297992ca412bff990df1def643b3c132fd (diff) |
Store configserver certificate to VESPA_HOME/var/vespa/sia
Diffstat (limited to 'athenz-identity-provider-service')
-rw-r--r-- | athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/AthenzSslKeyStoreConfigurator.java | 97 |
1 files changed, 39 insertions, 58 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 2a517e06ae2..3437dea9ece 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 @@ -8,18 +8,17 @@ import com.yahoo.config.provision.Zone; import com.yahoo.jdisc.http.ssl.SslKeyStoreConfigurator; import com.yahoo.jdisc.http.ssl.SslKeyStoreContext; import com.yahoo.log.LogLevel; +import com.yahoo.vespa.athenz.api.AthenzService; import com.yahoo.vespa.athenz.identity.ServiceIdentityProvider; import com.yahoo.vespa.athenz.tls.KeyStoreBuilder; import com.yahoo.vespa.athenz.tls.KeyStoreType; +import com.yahoo.vespa.athenz.utils.SiaUtils; import com.yahoo.vespa.defaults.Defaults; import com.yahoo.vespa.hosted.athenz.instanceproviderservice.config.AthenzProviderServiceConfig; import com.yahoo.vespa.hosted.athenz.instanceproviderservice.impl.AthenzCertificateClient; -import java.io.IOException; -import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import java.security.GeneralSecurityException; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.PrivateKey; @@ -33,7 +32,6 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import java.util.logging.Logger; -import static com.yahoo.vespa.athenz.tls.KeyStoreUtils.writeKeyStoreToFile; import static com.yahoo.vespa.hosted.athenz.instanceproviderservice.impl.Utils.getZoneConfig; /** @@ -47,13 +45,14 @@ public class AthenzSslKeyStoreConfigurator extends AbstractComponent implements private static final Logger log = Logger.getLogger(AthenzSslKeyStoreConfigurator.class.getName()); private static final String CERTIFICATE_ALIAS = "athenz"; private static final Duration EXPIRATION_MARGIN = Duration.ofHours(6); + private static final Path VESPA_SIA_DIRECTORY = Paths.get(Defaults.getDefaults().underVespaHome("var/vespa/sia")); private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(); private final AthenzCertificateClient certificateClient; private final KeyProvider keyProvider; private final AthenzProviderServiceConfig.Zones zoneConfig; private final Duration updatePeriod; - private final Path keystoreDirectory; + private final AthenzService configserverIdentity; private volatile KeyStoreAndPassword currentKeyStore; @Inject @@ -63,55 +62,40 @@ public class AthenzSslKeyStoreConfigurator extends AbstractComponent implements Zone zone, ConfigserverConfig configserverConfig) { AthenzProviderServiceConfig.Zones zoneConfig = getZoneConfig(config, zone); - Path keystoreDirectory = createKeystoreCacheDirectory(configserverConfig); + AthenzService configserverIdentity = new AthenzService(zoneConfig.domain(), zoneConfig.serviceName()); AthenzCertificateClient certificateClient = new AthenzCertificateClient(bootstrapIdentity, zoneConfig); Duration updatePeriod = Duration.ofDays(config.updatePeriodDays()); this.certificateClient = certificateClient; this.keyProvider = keyProvider; this.zoneConfig = zoneConfig; - this.currentKeyStore = initializeKeystore(keyProvider, certificateClient, zoneConfig, keystoreDirectory, updatePeriod); + this.currentKeyStore = initializeKeystore(configserverIdentity, keyProvider, certificateClient, zoneConfig, updatePeriod); this.updatePeriod = updatePeriod; - this.keystoreDirectory = keystoreDirectory; + this.configserverIdentity = configserverIdentity; } - private static KeyStoreAndPassword initializeKeystore(KeyProvider keyProvider, - AthenzCertificateClient certificateClient, - AthenzProviderServiceConfig.Zones zoneConfig, - Path keystoreCacheDirectory, - Duration updatePeriod) { - return tryReadKeystoreFile(keystoreCacheDirectory, updatePeriod) - .orElseGet(() -> downloadCertificate(keyProvider, certificateClient, zoneConfig, keystoreCacheDirectory)); + private static KeyStoreAndPassword initializeKeystore(AthenzService configserverIdentity, + KeyProvider keyProvider, + AthenzCertificateClient zoneConfig, + AthenzProviderServiceConfig.Zones keystoreCacheDirectory, + Duration updatePeriod) { + return tryReadKeystoreFile(configserverIdentity, updatePeriod) + .orElseGet(() -> downloadCertificate(configserverIdentity, keyProvider, zoneConfig, keystoreCacheDirectory)); } - private static Optional<KeyStoreAndPassword> tryReadKeystoreFile(Path keystoreDirectory, Duration updatePeriod) { - try { - Path keystoreFile = keystoreFile(keystoreDirectory); - Path keystoreSecretFile = keystoreSecretFile(keystoreDirectory); - if (!Files.exists(keystoreFile) || !Files.exists(keystoreSecretFile)) return Optional.empty(); - KeyStore keyStore = KeyStoreBuilder.withType(KeyStoreType.JKS) - .fromFile(keystoreFile.toFile()) - .build(); - Instant minimumExpiration = Instant.now().plus(updatePeriod).plus(EXPIRATION_MARGIN); - boolean isExpired = getCertificateExpiry(keyStore).isBefore(minimumExpiration); - if (isExpired) return Optional.empty(); - char[] pwd = new String(Files.readAllBytes(keystoreSecretFile)).toCharArray(); - return Optional.of(new KeyStoreAndPassword(keyStore, pwd)); - } catch (GeneralSecurityException | IOException e) { - log.log(LogLevel.ERROR, "Failed to read keystore from disk: " + e.getMessage(), e); - return Optional.empty(); - } - } - - private static Path createKeystoreCacheDirectory(ConfigserverConfig configserverConfig) { - return Paths.get(Defaults.getDefaults().underVespaHome(configserverConfig.configServerDBDir())); - } + private static Optional<KeyStoreAndPassword> tryReadKeystoreFile(AthenzService configserverIdentity, + Duration updatePeriod) { + Optional<X509Certificate> certificate = SiaUtils.readCertificateFile(VESPA_SIA_DIRECTORY, configserverIdentity); + if (!certificate.isPresent()) return Optional.empty(); + Optional<PrivateKey> privateKey = SiaUtils.readPrivateKeyFile(VESPA_SIA_DIRECTORY, configserverIdentity); + if (!privateKey.isPresent()) return Optional.empty(); + Instant minimumExpiration = Instant.now().plus(updatePeriod).plus(EXPIRATION_MARGIN); + boolean isExpired = certificate.get().getNotAfter().toInstant().isBefore(minimumExpiration); + if (isExpired) return Optional.empty(); - private static Path keystoreFile(Path keystoreDirectory) { - return keystoreDirectory.resolve("server-x509-athenz-cert.jks"); - } - - private static Path keystoreSecretFile(Path keystoreDirectory) { - return keystoreDirectory.resolve("keystore-secret"); + KeyStore keyStore = KeyStoreBuilder.withType(KeyStoreType.JKS) + .withKeyEntry(CERTIFICATE_ALIAS, privateKey.get(), certificate.get()) + .build(); + return Optional.of(new KeyStoreAndPassword(keyStore, generateKeystorePassword())); } @Override @@ -142,12 +126,13 @@ public class AthenzSslKeyStoreConfigurator extends AbstractComponent implements return certificate.getNotAfter().toInstant(); } - private static KeyStoreAndPassword downloadCertificate(KeyProvider keyProvider, - AthenzCertificateClient certificateClient, - AthenzProviderServiceConfig.Zones zoneConfig, - Path keystoreDirectory) { + private static KeyStoreAndPassword downloadCertificate(AthenzService configserverIdentity, + KeyProvider keyProvider, + AthenzCertificateClient certificateClient, + AthenzProviderServiceConfig.Zones zoneConfig) { PrivateKey privateKey = keyProvider.getPrivateKey(zoneConfig.secretVersion()); X509Certificate certificate = certificateClient.updateCertificate(privateKey); + writeCredentials(configserverIdentity, certificate, privateKey); Instant expirationTime = certificate.getNotAfter().toInstant(); Duration expiry = Duration.between(certificate.getNotBefore().toInstant(), expirationTime); log.log(LogLevel.INFO, String.format("Got Athenz x509 certificate with expiry %s (expires %s)", expiry, expirationTime)); @@ -156,18 +141,14 @@ public class AthenzSslKeyStoreConfigurator extends AbstractComponent implements KeyStore keyStore = KeyStoreBuilder.withType(KeyStoreType.JKS) .withKeyEntry(CERTIFICATE_ALIAS, privateKey, keystorePassword, certificate) .build(); - KeyStoreAndPassword keyStoreAndPassword = new KeyStoreAndPassword(keyStore, keystorePassword); - tryWriteKeystore(keyStoreAndPassword, keystoreDirectory); - return keyStoreAndPassword; + return new KeyStoreAndPassword(keyStore, keystorePassword); } - private static void tryWriteKeystore(KeyStoreAndPassword keyStore, Path keystoreDirectory) { - try { - writeKeyStoreToFile(keyStore.keyStore, keystoreFile(keystoreDirectory).toFile()); - Files.write(keystoreSecretFile(keystoreDirectory), new String(keyStore.password).getBytes()); - } catch (Exception e) { - log.log(LogLevel.ERROR, "Failed to write keystore to disk: " + e.getMessage(), e); - } + private static void writeCredentials(AthenzService configserverIdentity, + X509Certificate certificate, + PrivateKey privateKey) { + SiaUtils.writeCertificateFile(VESPA_SIA_DIRECTORY, configserverIdentity, certificate); + SiaUtils.writePrivateKeyFile(VESPA_SIA_DIRECTORY, configserverIdentity, privateKey); } private static char[] generateKeystorePassword() { @@ -186,7 +167,7 @@ public class AthenzSslKeyStoreConfigurator extends AbstractComponent implements public void run() { try { log.log(LogLevel.INFO, "Updating Athenz certificate from ZTS"); - currentKeyStore = downloadCertificate(keyProvider, certificateClient, zoneConfig, keystoreDirectory); + currentKeyStore = downloadCertificate(configserverIdentity, keyProvider, certificateClient, zoneConfig); sslKeyStoreContext.updateKeyStore(currentKeyStore.keyStore, new String(currentKeyStore.password)); log.log(LogLevel.INFO, "Athenz certificate reload successfully completed"); } catch (Throwable e) { |