diff options
author | Arnstein Ressem <aressem@gmail.com> | 2018-02-20 09:57:12 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-02-20 09:57:12 +0100 |
commit | 6d7b65adfcd1e918da8173dab25bf701074f3cdc (patch) | |
tree | 483d67659494686c76b1cfdf5899f3f4ace36c17 | |
parent | 2ecdfefd5616743f62691f64a517ab787d6f0c10 (diff) | |
parent | 957325fa8ea36022f79df52378d0623f3f488783 (diff) |
Merge pull request #5072 from vespa-engine/revert-4984-mortent/ckms
Revert "Refactor identityprovider. Add SiaIdentityProvider"
-rw-r--r-- | athenz-identity-provider-service/pom.xml | 87 | ||||
-rw-r--r-- | config-model/src/main/java/com/yahoo/vespa/model/container/IdentityProvider.java | 3 | ||||
-rw-r--r-- | container-disc/src/main/java/com/yahoo/container/jdisc/Ckms.java | 14 | ||||
-rw-r--r-- | container-disc/src/main/java/com/yahoo/container/jdisc/athenz/AthenzIdentityProvider.java | 3 | ||||
-rw-r--r-- | container-disc/src/main/java/com/yahoo/container/jdisc/athenz/impl/AthenzCredentials.java (renamed from athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/identityprovider/AthenzCredentials.java) | 2 | ||||
-rw-r--r-- | container-disc/src/main/java/com/yahoo/container/jdisc/athenz/impl/AthenzCredentialsService.java (renamed from athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/identityprovider/AthenzCredentialsService.java) | 2 | ||||
-rw-r--r-- | container-disc/src/main/java/com/yahoo/container/jdisc/athenz/impl/AthenzIdentityProviderImpl.java (renamed from athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/identityprovider/AthenzIdentityProviderImpl.java) | 153 | ||||
-rw-r--r-- | container-disc/src/main/java/com/yahoo/container/jdisc/athenz/impl/AthenzService.java (renamed from athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/identityprovider/AthenzService.java) | 2 | ||||
-rw-r--r-- | container-disc/src/main/java/com/yahoo/container/jdisc/athenz/impl/CryptoUtils.java (renamed from athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/identityprovider/CryptoUtils.java) | 2 | ||||
-rw-r--r-- | container-disc/src/main/java/com/yahoo/container/jdisc/athenz/impl/IdentityDocumentService.java (renamed from athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/identityprovider/IdentityDocumentService.java) | 2 | ||||
-rw-r--r-- | container-disc/src/main/java/com/yahoo/container/jdisc/athenz/impl/InstanceIdentity.java (renamed from athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/identityprovider/InstanceIdentity.java) | 2 | ||||
-rw-r--r-- | container-disc/src/main/java/com/yahoo/container/jdisc/athenz/impl/InstanceRefreshInformation.java (renamed from athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/identityprovider/InstanceRefreshInformation.java) | 2 | ||||
-rw-r--r-- | container-disc/src/main/java/com/yahoo/container/jdisc/athenz/impl/InstanceRegisterInformation.java (renamed from athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/identityprovider/InstanceRegisterInformation.java) | 2 | ||||
-rw-r--r-- | container-disc/src/main/java/com/yahoo/container/jdisc/athenz/impl/SignedIdentityDocument.java (renamed from athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/identityprovider/SignedIdentityDocument.java) | 2 | ||||
-rw-r--r-- | container-disc/src/main/java/com/yahoo/container/jdisc/athenz/impl/package-info.java (renamed from athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/identityprovider/package-info.java) | 2 | ||||
-rw-r--r-- | container-disc/src/test/java/com/yahoo/container/jdisc/athenz/impl/AthenzIdentityProviderImplTest.java (renamed from athenz-identity-provider-service/src/test/java/com/yahoo/vespa/hosted/athenz/identityprovider/AthenzIdentityProviderImplTest.java) | 108 | ||||
-rw-r--r-- | container-disc/src/test/java/com/yahoo/container/jdisc/athenz/impl/CryptoUtilsTest.java (renamed from athenz-identity-provider-service/src/test/java/com/yahoo/vespa/hosted/athenz/identityprovider/CryptoUtilsTest.java) | 2 | ||||
-rw-r--r-- | parent/pom.xml | 2 | ||||
-rw-r--r-- | vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identity/SiaIdentityProvider.java | 51 | ||||
-rw-r--r-- | vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identity/package-info.java | 8 | ||||
-rw-r--r-- | vespa-athenz/src/main/resources/configdefinitions/sia-provider.def | 6 |
21 files changed, 294 insertions, 163 deletions
diff --git a/athenz-identity-provider-service/pom.xml b/athenz-identity-provider-service/pom.xml index 92ecd36b0c3..bfd02d54d43 100644 --- a/athenz-identity-provider-service/pom.xml +++ b/athenz-identity-provider-service/pom.xml @@ -14,6 +14,67 @@ <relativePath>../parent/pom.xml</relativePath> </parent> <dependencies> + <!-- COMPILE --> + <dependency> + <groupId>com.yahoo.athenz</groupId> + <artifactId>athenz-zms-java-client</artifactId> + <scope>compile</scope> + <exclusions> + <!-- Provided by JDisc / container-dev --> + <exclusion> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-api</artifactId> + </exclusion> + <!--Exclude all Jersey bundles provided by JDisc--> + <exclusion> + <groupId>org.glassfish.jersey.core</groupId> + <artifactId>jersey-client</artifactId> + </exclusion> + <exclusion> + <groupId>org.glassfish.jersey.media</groupId> + <artifactId>jersey-media-json-jackson</artifactId> + </exclusion> + <!--Exclude all Jackson bundles provided by JDisc --> + <exclusion> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-core</artifactId> + </exclusion> + <exclusion> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-databind</artifactId> + </exclusion> + <exclusion> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-annotations</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>com.yahoo.athenz</groupId> + <artifactId>athenz-zts-java-client</artifactId> + <scope>compile</scope> + <exclusions> + <!-- Provided by JDisc / container-dev --> + <exclusion> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-api</artifactId> + </exclusion> + <!--Exclude all Jackson bundles provided by JDisc --> + <exclusion> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-core</artifactId> + </exclusion> + <exclusion> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-databind</artifactId> + </exclusion> + <exclusion> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-annotations</artifactId> + </exclusion> + </exclusions> + </dependency> + <!-- PROVIDED --> <dependency> <groupId>com.yahoo.vespa</groupId> @@ -49,20 +110,6 @@ <version>${project.version}</version> <scope>provided</scope> </dependency> - <dependency> - <groupId>com.yahoo.vespa</groupId> - <artifactId>vespa-athenz</artifactId> - <version>${project.version}</version> - <scope>provided</scope> - </dependency> - <dependency> - <groupId>org.apache.httpcomponents</groupId> - <artifactId>httpclient</artifactId> - </dependency> - <dependency> - <groupId>org.apache.httpcomponents</groupId> - <artifactId>httpcore</artifactId> - </dependency> <!-- TEST --> <dependency> @@ -83,6 +130,18 @@ <scope>test</scope> </dependency> <dependency> + <groupId>org.apache.httpcomponents</groupId> + <artifactId>httpclient</artifactId> + <version>4.4.1</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.httpcomponents</groupId> + <artifactId>httpcore</artifactId> + <version>4.4.1</version> + <scope>test</scope> + </dependency> + <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-all</artifactId> <scope>test</scope> diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/IdentityProvider.java b/config-model/src/main/java/com/yahoo/vespa/model/container/IdentityProvider.java index 640a85d9b50..0368f7eaf3e 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/container/IdentityProvider.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/container/IdentityProvider.java @@ -5,13 +5,14 @@ import com.yahoo.config.provision.AthenzDomain; import com.yahoo.config.provision.AthenzService; import com.yahoo.config.provision.HostName; import com.yahoo.container.core.identity.IdentityConfig; +import com.yahoo.container.jdisc.athenz.impl.AthenzIdentityProviderImpl; import com.yahoo.vespa.model.container.component.SimpleComponent; /** * @author mortent */ public class IdentityProvider extends SimpleComponent implements IdentityConfig.Producer { - public static final String CLASS = "com.yahoo.vespa.hosted.athenz.identityprovider.AthenzIdentityProviderImpl"; + public static final String CLASS = AthenzIdentityProviderImpl.class.getName(); private final AthenzDomain domain; private final AthenzService service; diff --git a/container-disc/src/main/java/com/yahoo/container/jdisc/Ckms.java b/container-disc/src/main/java/com/yahoo/container/jdisc/Ckms.java deleted file mode 100644 index 26c71686a82..00000000000 --- a/container-disc/src/main/java/com/yahoo/container/jdisc/Ckms.java +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. - -package com.yahoo.container.jdisc; - -/** - * @author mortent - */ -public interface Ckms { - /** Returns the secret for this key */ - String getSecret(String key); - - /** Returns the secret for this key and version */ - String getSecret(String key, int version); -} diff --git a/container-disc/src/main/java/com/yahoo/container/jdisc/athenz/AthenzIdentityProvider.java b/container-disc/src/main/java/com/yahoo/container/jdisc/athenz/AthenzIdentityProvider.java index b7190927d11..c4c57f4bc47 100644 --- a/container-disc/src/main/java/com/yahoo/container/jdisc/athenz/AthenzIdentityProvider.java +++ b/container-disc/src/main/java/com/yahoo/container/jdisc/athenz/AthenzIdentityProvider.java @@ -7,7 +7,8 @@ import javax.net.ssl.SSLContext; * @author mortent */ public interface AthenzIdentityProvider { + String getNToken() throws AthenzIdentityProviderException; String getDomain(); String getService(); - SSLContext getIdentitySslContext(); + SSLContext getSslContext(); } diff --git a/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/identityprovider/AthenzCredentials.java b/container-disc/src/main/java/com/yahoo/container/jdisc/athenz/impl/AthenzCredentials.java index 36c1aee49e0..790a7c54333 100644 --- a/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/identityprovider/AthenzCredentials.java +++ b/container-disc/src/main/java/com/yahoo/container/jdisc/athenz/impl/AthenzCredentials.java @@ -1,5 +1,5 @@ // 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.identityprovider; +package com.yahoo.container.jdisc.athenz.impl; import java.security.KeyPair; import java.security.cert.X509Certificate; diff --git a/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/identityprovider/AthenzCredentialsService.java b/container-disc/src/main/java/com/yahoo/container/jdisc/athenz/impl/AthenzCredentialsService.java index 4072568d9d2..5786eb9e398 100644 --- a/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/identityprovider/AthenzCredentialsService.java +++ b/container-disc/src/main/java/com/yahoo/container/jdisc/athenz/impl/AthenzCredentialsService.java @@ -1,5 +1,5 @@ // 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.identityprovider; +package com.yahoo.container.jdisc.athenz.impl; import com.fasterxml.jackson.databind.ObjectMapper; import com.yahoo.container.core.identity.IdentityConfig; diff --git a/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/identityprovider/AthenzIdentityProviderImpl.java b/container-disc/src/main/java/com/yahoo/container/jdisc/athenz/impl/AthenzIdentityProviderImpl.java index 18f90ce545f..3b2b065fa8c 100644 --- a/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/identityprovider/AthenzIdentityProviderImpl.java +++ b/container-disc/src/main/java/com/yahoo/container/jdisc/athenz/impl/AthenzIdentityProviderImpl.java @@ -1,5 +1,5 @@ // 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.identityprovider; +package com.yahoo.container.jdisc.athenz.impl; import com.google.inject.Inject; import com.yahoo.component.AbstractComponent; @@ -9,11 +9,21 @@ import com.yahoo.container.jdisc.athenz.AthenzIdentityProviderException; import com.yahoo.jdisc.Metric; import com.yahoo.log.LogLevel; import com.yahoo.vespa.defaults.Defaults; -import com.yahoo.vespa.athenz.api.AthenzIdentityCertificate; -import com.yahoo.vespa.athenz.tls.AthenzSslContextBuilder; +import javax.net.ssl.KeyManager; +import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; -import java.io.File; +import javax.net.ssl.TrustManager; +import javax.net.ssl.TrustManagerFactory; +import java.io.FileInputStream; +import java.io.IOException; +import java.security.KeyManagementException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.UnrecoverableKeyException; +import java.security.cert.Certificate; +import java.security.cert.CertificateException; import java.time.Clock; import java.time.Duration; import java.time.Instant; @@ -53,8 +63,9 @@ public final class AthenzIdentityProviderImpl extends AbstractComponent implemen static final String METRICS_UPDATER_TAG = "metrics-updater"; - private volatile AthenzCredentials credentials; + private final AtomicReference<AthenzCredentials> credentials = new AtomicReference<>(); private final AtomicReference<Throwable> lastThrowable = new AtomicReference<>(); + private final CountDownLatch credentialsRetrievedSignal = new CountDownLatch(1); private final AthenzCredentialsService athenzCredentialsService; private final Scheduler scheduler; private final Clock clock; @@ -86,17 +97,26 @@ public final class AthenzIdentityProviderImpl extends AbstractComponent implemen this.clock = clock; this.domain = config.domain(); this.service = config.service(); + scheduler.submit(new RegisterInstanceTask()); + scheduler.schedule(new TimeoutInitialWaitTask(), INITIAL_WAIT_NTOKEN); + metricUpdater = new CertificateExpiryMetricUpdater(metric); - registerInstance(); } - private void registerInstance() { + @Override + public String getNToken() { try { - credentials = athenzCredentialsService.registerInstance(); - scheduler.schedule(new UpdateCredentialsTask(), UPDATE_PERIOD); - scheduler.submit(metricUpdater); - } catch (Throwable t) { - throw new AthenzIdentityProviderException("Could not retrieve Athenz credentials", t); + credentialsRetrievedSignal.await(); + AthenzCredentials credentialsSnapshot = credentials.get(); + if (credentialsSnapshot == null) { + throw new AthenzIdentityProviderException("Could not retrieve Athenz credentials", lastThrowable.get()); + } + if (isExpired(credentialsSnapshot)) { + throw new AthenzIdentityProviderException("Athenz credentials are expired", lastThrowable.get()); + } + return credentialsSnapshot.getNToken(); + } catch (InterruptedException e) { + throw new AthenzIdentityProviderException("Failed to register instance credentials", lastThrowable.get()); } } @@ -111,13 +131,49 @@ public final class AthenzIdentityProviderImpl extends AbstractComponent implemen } @Override - public SSLContext getIdentitySslContext() { - return new AthenzSslContextBuilder() - .withIdentityCertificate(new AthenzIdentityCertificate( - credentials.getCertificate(), - credentials.getKeyPair().getPrivate())) - .withTrustStore(new File(Defaults.getDefaults().underVespaHome("share/ssl/certs/yahoo_certificate_bundle.jks")), "JKS") - .build(); + public SSLContext getSslContext() { + try { + SSLContext sslContext = SSLContext.getInstance("TLSv1.2"); + sslContext.init(createKeyManagersWithServiceCertificate(), + createTrustManagersWithAthenzCa(), + null); + return sslContext; + } catch (NoSuchAlgorithmException | KeyManagementException e) { + throw new RuntimeException(e); + } + } + + private KeyManager[] createKeyManagersWithServiceCertificate() { + try { + credentialsRetrievedSignal.await(); + KeyStore keyStore = KeyStore.getInstance("JKS"); + keyStore.load(null); + keyStore.setKeyEntry("instance-key", + credentials.get().getKeyPair().getPrivate(), + new char[0], + new Certificate[]{credentials.get().getCertificate()}); + KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); + keyManagerFactory.init(keyStore, new char[0]); + return keyManagerFactory.getKeyManagers(); + } catch (KeyStoreException | NoSuchAlgorithmException | UnrecoverableKeyException | CertificateException | IOException e) { + throw new RuntimeException(e); + } catch (InterruptedException e) { + throw new AthenzIdentityProviderException("Failed to register instance credentials", lastThrowable.get()); + } + } + + private static TrustManager[] createTrustManagersWithAthenzCa() { + try { + KeyStore trustStore = KeyStore.getInstance("JKS"); + try (FileInputStream in = new FileInputStream(Defaults.getDefaults().underVespaHome("share/ssl/certs/yahoo_certificate_bundle.jks"))) { + trustStore.load(in, null); + } + TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + trustManagerFactory.init(trustStore); + return trustManagerFactory.getTrustManagers(); + } catch (CertificateException | IOException | KeyStoreException | NoSuchAlgorithmException e) { + throw new RuntimeException(e); + } } @Override @@ -133,19 +189,56 @@ public final class AthenzIdentityProviderImpl extends AbstractComponent implemen return credentials.getCreatedAt().plus(EXPIRES_AFTER).minus(EXPIRATION_MARGIN); } + private class RegisterInstanceTask implements RunnableWithTag { + + private final Duration backoffDelay; + + RegisterInstanceTask() { + this(INITIAL_BACKOFF_DELAY); + } + + RegisterInstanceTask(Duration backoffDelay) { + this.backoffDelay = backoffDelay; + } + + @Override + public void run() { + try { + credentials.set(athenzCredentialsService.registerInstance()); + credentialsRetrievedSignal.countDown(); + scheduler.schedule(new UpdateCredentialsTask(), UPDATE_PERIOD); + scheduler.submit(metricUpdater); + } catch (Throwable t) { + log.log(LogLevel.ERROR, "Failed to register instance: " + t.getMessage(), t); + lastThrowable.set(t); + Duration nextBackoffDelay = backoffDelay.multipliedBy(BACKOFF_DELAY_MULTIPLIER); + if (nextBackoffDelay.compareTo(MAX_REGISTER_BACKOFF_DELAY) > 0) { + nextBackoffDelay = MAX_REGISTER_BACKOFF_DELAY; + } + scheduler.schedule(new RegisterInstanceTask(nextBackoffDelay), backoffDelay); + } + } + + @Override + public String tag() { + return REGISTER_INSTANCE_TAG; + } + } + private class UpdateCredentialsTask implements RunnableWithTag { @Override public void run() { + AthenzCredentials currentCredentials = credentials.get(); try { - AthenzCredentials newCredentials = isExpired(credentials) + AthenzCredentials newCredentials = isExpired(currentCredentials) ? athenzCredentialsService.registerInstance() - : athenzCredentialsService.updateCredentials(credentials); - credentials = newCredentials; + : athenzCredentialsService.updateCredentials(currentCredentials); + credentials.set(newCredentials); scheduler.schedule(new UpdateCredentialsTask(), UPDATE_PERIOD); } catch (Throwable t) { log.log(LogLevel.WARNING, "Failed to update credentials: " + t.getMessage(), t); lastThrowable.set(t); - Duration timeToExpiration = Duration.between(clock.instant(), getExpirationTime(credentials)); + Duration timeToExpiration = Duration.between(clock.instant(), getExpirationTime(currentCredentials)); // NOTE: Update period might be after timeToExpiration, still we do not want to DDoS Athenz. Duration updatePeriod = timeToExpiration.compareTo(UPDATE_PERIOD) > 0 ? UPDATE_PERIOD : REDUCED_UPDATE_PERIOD; @@ -168,7 +261,7 @@ public final class AthenzIdentityProviderImpl extends AbstractComponent implemen @Override public void run() { - Instant expirationTime = getExpirationTime(credentials); + Instant expirationTime = getExpirationTime(credentials.get()); Duration remainingLifetime = Duration.between(clock.instant(), expirationTime); metric.set(CERTIFICATE_EXPIRY_METRIC_NAME, remainingLifetime.getSeconds(), null); scheduler.schedule(this, CERTIFICATE_EXPIRY_METRIC_UPDATE_PERIOD); @@ -180,6 +273,18 @@ public final class AthenzIdentityProviderImpl extends AbstractComponent implemen } } + private class TimeoutInitialWaitTask implements RunnableWithTag { + @Override + public void run() { + credentialsRetrievedSignal.countDown(); + } + + @Override + public String tag() { + return TIMEOUT_INITIAL_WAIT_TAG; + } + } + private static class ThreadPoolScheduler implements Scheduler { private static final Logger log = Logger.getLogger(ThreadPoolScheduler.class.getName()); diff --git a/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/identityprovider/AthenzService.java b/container-disc/src/main/java/com/yahoo/container/jdisc/athenz/impl/AthenzService.java index c9e3809ea96..898f90e3438 100644 --- a/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/identityprovider/AthenzService.java +++ b/container-disc/src/main/java/com/yahoo/container/jdisc/athenz/impl/AthenzService.java @@ -1,5 +1,5 @@ // 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.identityprovider; +package com.yahoo.container.jdisc.athenz.impl; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; diff --git a/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/identityprovider/CryptoUtils.java b/container-disc/src/main/java/com/yahoo/container/jdisc/athenz/impl/CryptoUtils.java index 6a766e7c49d..388b40a1fe0 100644 --- a/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/identityprovider/CryptoUtils.java +++ b/container-disc/src/main/java/com/yahoo/container/jdisc/athenz/impl/CryptoUtils.java @@ -1,5 +1,5 @@ // 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.identityprovider; +package com.yahoo.container.jdisc.athenz.impl; import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; import org.bouncycastle.asn1.x509.Extension; diff --git a/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/identityprovider/IdentityDocumentService.java b/container-disc/src/main/java/com/yahoo/container/jdisc/athenz/impl/IdentityDocumentService.java index 8a9137a491d..7878400964a 100644 --- a/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/identityprovider/IdentityDocumentService.java +++ b/container-disc/src/main/java/com/yahoo/container/jdisc/athenz/impl/IdentityDocumentService.java @@ -1,5 +1,5 @@ // 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.identityprovider; +package com.yahoo.container.jdisc.athenz.impl; import com.yahoo.vespa.defaults.Defaults; import org.apache.http.client.methods.CloseableHttpResponse; diff --git a/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/identityprovider/InstanceIdentity.java b/container-disc/src/main/java/com/yahoo/container/jdisc/athenz/impl/InstanceIdentity.java index d6e986959cb..20bbb2aa67e 100644 --- a/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/identityprovider/InstanceIdentity.java +++ b/container-disc/src/main/java/com/yahoo/container/jdisc/athenz/impl/InstanceIdentity.java @@ -1,5 +1,5 @@ // 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.identityprovider; +package com.yahoo.container.jdisc.athenz.impl; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; diff --git a/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/identityprovider/InstanceRefreshInformation.java b/container-disc/src/main/java/com/yahoo/container/jdisc/athenz/impl/InstanceRefreshInformation.java index d0c22d1d0d2..dd893cb3143 100644 --- a/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/identityprovider/InstanceRefreshInformation.java +++ b/container-disc/src/main/java/com/yahoo/container/jdisc/athenz/impl/InstanceRefreshInformation.java @@ -1,5 +1,5 @@ // 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.identityprovider; +package com.yahoo.container.jdisc.athenz.impl; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; diff --git a/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/identityprovider/InstanceRegisterInformation.java b/container-disc/src/main/java/com/yahoo/container/jdisc/athenz/impl/InstanceRegisterInformation.java index dd9f164fef1..e2355cb7a2d 100644 --- a/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/identityprovider/InstanceRegisterInformation.java +++ b/container-disc/src/main/java/com/yahoo/container/jdisc/athenz/impl/InstanceRegisterInformation.java @@ -1,5 +1,5 @@ // 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.identityprovider; +package com.yahoo.container.jdisc.athenz.impl; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; diff --git a/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/identityprovider/SignedIdentityDocument.java b/container-disc/src/main/java/com/yahoo/container/jdisc/athenz/impl/SignedIdentityDocument.java index 7bbd49c953f..5d5b5430859 100644 --- a/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/identityprovider/SignedIdentityDocument.java +++ b/container-disc/src/main/java/com/yahoo/container/jdisc/athenz/impl/SignedIdentityDocument.java @@ -1,5 +1,5 @@ // 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.identityprovider; +package com.yahoo.container.jdisc.athenz.impl; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; diff --git a/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/identityprovider/package-info.java b/container-disc/src/main/java/com/yahoo/container/jdisc/athenz/impl/package-info.java index 1b4842327dd..2d7cbbb6315 100644 --- a/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/identityprovider/package-info.java +++ b/container-disc/src/main/java/com/yahoo/container/jdisc/athenz/impl/package-info.java @@ -3,6 +3,6 @@ * @author mortent */ @ExportPackage -package com.yahoo.vespa.hosted.athenz.identityprovider; +package com.yahoo.container.jdisc.athenz.impl; import com.yahoo.osgi.annotation.ExportPackage;
\ No newline at end of file diff --git a/athenz-identity-provider-service/src/test/java/com/yahoo/vespa/hosted/athenz/identityprovider/AthenzIdentityProviderImplTest.java b/container-disc/src/test/java/com/yahoo/container/jdisc/athenz/impl/AthenzIdentityProviderImplTest.java index 3a506a39c43..1ee23334a16 100644 --- a/athenz-identity-provider-service/src/test/java/com/yahoo/vespa/hosted/athenz/identityprovider/AthenzIdentityProviderImplTest.java +++ b/container-disc/src/test/java/com/yahoo/container/jdisc/athenz/impl/AthenzIdentityProviderImplTest.java @@ -1,16 +1,14 @@ // 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.identityprovider; +package com.yahoo.container.jdisc.athenz.impl; import com.yahoo.container.core.identity.IdentityConfig; import com.yahoo.container.jdisc.athenz.AthenzIdentityProvider; -import com.yahoo.container.jdisc.athenz.AthenzIdentityProviderException; -import com.yahoo.vespa.hosted.athenz.identityprovider.AthenzIdentityProviderImpl.RunnableWithTag; -import com.yahoo.vespa.hosted.athenz.identityprovider.AthenzIdentityProviderImpl.Scheduler; +import com.yahoo.container.jdisc.athenz.impl.AthenzIdentityProviderImpl.RunnableWithTag; +import com.yahoo.container.jdisc.athenz.impl.AthenzIdentityProviderImpl.Scheduler; import com.yahoo.jdisc.Metric; import com.yahoo.test.ManualClock; import org.junit.Test; -import java.security.cert.X509Certificate; import java.time.Duration; import java.time.Instant; import java.util.ArrayList; @@ -25,15 +23,15 @@ import java.util.function.Predicate; import java.util.stream.Collectors; import java.util.stream.Stream; -import static com.yahoo.vespa.hosted.athenz.identityprovider.AthenzIdentityProviderImpl.INITIAL_BACKOFF_DELAY; -import static com.yahoo.vespa.hosted.athenz.identityprovider.AthenzIdentityProviderImpl.INITIAL_WAIT_NTOKEN; -import static com.yahoo.vespa.hosted.athenz.identityprovider.AthenzIdentityProviderImpl.MAX_REGISTER_BACKOFF_DELAY; -import static com.yahoo.vespa.hosted.athenz.identityprovider.AthenzIdentityProviderImpl.METRICS_UPDATER_TAG; -import static com.yahoo.vespa.hosted.athenz.identityprovider.AthenzIdentityProviderImpl.REDUCED_UPDATE_PERIOD; -import static com.yahoo.vespa.hosted.athenz.identityprovider.AthenzIdentityProviderImpl.REGISTER_INSTANCE_TAG; -import static com.yahoo.vespa.hosted.athenz.identityprovider.AthenzIdentityProviderImpl.TIMEOUT_INITIAL_WAIT_TAG; -import static com.yahoo.vespa.hosted.athenz.identityprovider.AthenzIdentityProviderImpl.UPDATE_CREDENTIALS_TAG; -import static com.yahoo.vespa.hosted.athenz.identityprovider.AthenzIdentityProviderImpl.UPDATE_PERIOD; +import static com.yahoo.container.jdisc.athenz.impl.AthenzIdentityProviderImpl.INITIAL_BACKOFF_DELAY; +import static com.yahoo.container.jdisc.athenz.impl.AthenzIdentityProviderImpl.INITIAL_WAIT_NTOKEN; +import static com.yahoo.container.jdisc.athenz.impl.AthenzIdentityProviderImpl.MAX_REGISTER_BACKOFF_DELAY; +import static com.yahoo.container.jdisc.athenz.impl.AthenzIdentityProviderImpl.METRICS_UPDATER_TAG; +import static com.yahoo.container.jdisc.athenz.impl.AthenzIdentityProviderImpl.REDUCED_UPDATE_PERIOD; +import static com.yahoo.container.jdisc.athenz.impl.AthenzIdentityProviderImpl.REGISTER_INSTANCE_TAG; +import static com.yahoo.container.jdisc.athenz.impl.AthenzIdentityProviderImpl.TIMEOUT_INITIAL_WAIT_TAG; +import static com.yahoo.container.jdisc.athenz.impl.AthenzIdentityProviderImpl.UPDATE_CREDENTIALS_TAG; +import static com.yahoo.container.jdisc.athenz.impl.AthenzIdentityProviderImpl.UPDATE_PERIOD; import static org.junit.Assert.assertEquals; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyString; @@ -48,33 +46,77 @@ public class AthenzIdentityProviderImplTest { private static final Metric DUMMY_METRIC = new Metric() { @Override - public void set(String s, Number number, Context context) { - } - + public void set(String s, Number number, Context context) {} @Override - public void add(String s, Number number, Context context) { - } - + public void add(String s, Number number, Context context) {} @Override - public Context createContext(Map<String, ?> stringMap) { - return null; - } + public Context createContext(Map<String, ?> stringMap) { return null; } }; private static final IdentityConfig IDENTITY_CONFIG = new IdentityConfig(new IdentityConfig.Builder() .service("tenantService").domain("tenantDomain").loadBalancerAddress("cfg")); - @Test (expected = AthenzIdentityProviderException.class) - public void component_creation_fails_when_credentials_not_found() { + private final Set<String> IGNORED_TASKS = Stream.of(UPDATE_CREDENTIALS_TAG, METRICS_UPDATER_TAG) + .collect(Collectors.toSet()); + + @Test + public void athenz_credentials_are_retrieved_after_component_contruction_completed() { + IdentityDocumentService identityDocumentService = mock(IdentityDocumentService.class); + AthenzService athenzService = mock(AthenzService.class); + ManualClock clock = new ManualClock(Instant.EPOCH); + MockScheduler scheduler = new MockScheduler(clock); + + when(identityDocumentService.getSignedIdentityDocument()).thenReturn(getIdentityDocument()); + when(athenzService.sendInstanceRegisterRequest(any(), any())).thenReturn( + new InstanceIdentity(null, "TOKEN")); + AthenzCredentialsService credentialService = + new AthenzCredentialsService(IDENTITY_CONFIG, identityDocumentService, athenzService, clock); + + AthenzIdentityProvider identityProvider = + new AthenzIdentityProviderImpl(IDENTITY_CONFIG, DUMMY_METRIC, credentialService, scheduler, clock); + + List<MockScheduler.CompletedTask> expectedTasks = + Arrays.asList( + new MockScheduler.CompletedTask(REGISTER_INSTANCE_TAG, Duration.ZERO), + new MockScheduler.CompletedTask(TIMEOUT_INITIAL_WAIT_TAG, INITIAL_WAIT_NTOKEN)); + // Don't run update credential tasks, otherwise infinite loop + List<MockScheduler.CompletedTask> completedTasks = + scheduler.runAllTasks(task -> !IGNORED_TASKS.contains(task.tag())); + assertEquals(expectedTasks, completedTasks); + assertEquals("TOKEN", identityProvider.getNToken()); + } + + @Test + public void register_instance_uses_exponential_backoff() { AthenzCredentialsService credentialService = mock(AthenzCredentialsService.class); when(credentialService.registerInstance()) - .thenThrow(new RuntimeException("athenz unavailable")); + .thenThrow(new RuntimeException("#1")) + .thenThrow(new RuntimeException("#2")) + .thenThrow(new RuntimeException("#3")) + .thenThrow(new RuntimeException("#4")) + .thenThrow(new RuntimeException("#5")) + .thenReturn(new AthenzCredentials("TOKEN", null, null, null, Instant.now())); ManualClock clock = new ManualClock(Instant.EPOCH); MockScheduler scheduler = new MockScheduler(clock); AthenzIdentityProvider identityProvider = new AthenzIdentityProviderImpl(IDENTITY_CONFIG, DUMMY_METRIC, credentialService, scheduler, clock); + + List<MockScheduler.CompletedTask> expectedTasks = + Arrays.asList( + new MockScheduler.CompletedTask(REGISTER_INSTANCE_TAG, Duration.ZERO), + new MockScheduler.CompletedTask(REGISTER_INSTANCE_TAG, INITIAL_BACKOFF_DELAY), + new MockScheduler.CompletedTask(TIMEOUT_INITIAL_WAIT_TAG, INITIAL_WAIT_NTOKEN), + new MockScheduler.CompletedTask(REGISTER_INSTANCE_TAG, INITIAL_BACKOFF_DELAY.multipliedBy(2)), + new MockScheduler.CompletedTask(REGISTER_INSTANCE_TAG, INITIAL_BACKOFF_DELAY.multipliedBy(4)), + new MockScheduler.CompletedTask(REGISTER_INSTANCE_TAG, INITIAL_BACKOFF_DELAY.multipliedBy(8)), + new MockScheduler.CompletedTask(REGISTER_INSTANCE_TAG, MAX_REGISTER_BACKOFF_DELAY)); + // Don't run update credential tasks, otherwise infinite loop + List<MockScheduler.CompletedTask> completedTasks = + scheduler.runAllTasks(task -> !IGNORED_TASKS.contains(task.tag())); + assertEquals(expectedTasks, completedTasks); + assertEquals("TOKEN", identityProvider.getNToken()); } @Test @@ -83,7 +125,6 @@ public class AthenzIdentityProviderImplTest { AthenzService athenzService = mock(AthenzService.class); ManualClock clock = new ManualClock(Instant.EPOCH); MockScheduler scheduler = new MockScheduler(clock); - X509Certificate x509Certificate = mock(X509Certificate.class); when(identityDocumentService.getSignedIdentityDocument()).thenReturn(getIdentityDocument()); when(athenzService.sendInstanceRegisterRequest(any(), any())).thenReturn( @@ -102,6 +143,8 @@ public class AthenzIdentityProviderImplTest { List<MockScheduler.CompletedTask> expectedTasks = Arrays.asList( + new MockScheduler.CompletedTask(REGISTER_INSTANCE_TAG, Duration.ZERO), + new MockScheduler.CompletedTask(TIMEOUT_INITIAL_WAIT_TAG, INITIAL_WAIT_NTOKEN), new MockScheduler.CompletedTask(UPDATE_CREDENTIALS_TAG, UPDATE_PERIOD), new MockScheduler.CompletedTask(UPDATE_CREDENTIALS_TAG, UPDATE_PERIOD), new MockScheduler.CompletedTask(UPDATE_CREDENTIALS_TAG, REDUCED_UPDATE_PERIOD), @@ -110,8 +153,9 @@ public class AthenzIdentityProviderImplTest { AtomicInteger counter = new AtomicInteger(0); List<MockScheduler.CompletedTask> completedTasks = scheduler.runAllTasks(task -> !task.tag().equals(METRICS_UPDATER_TAG) && - counter.getAndIncrement() < expectedTasks.size()); + counter.getAndIncrement() < expectedTasks.size()); assertEquals(expectedTasks, completedTasks); + assertEquals("TOKEN", identityProvider.getNToken()); } private static String getIdentityDocument() { @@ -188,7 +232,7 @@ public class AthenzIdentityProviderImplTest { if (o == null || getClass() != o.getClass()) return false; CompletedTask that = (CompletedTask) o; return Objects.equals(tag, that.tag) && - Objects.equals(delay, that.delay); + Objects.equals(delay, that.delay); } @Override @@ -199,9 +243,9 @@ public class AthenzIdentityProviderImplTest { @Override public String toString() { return "CompletedTask{" + - "tag='" + tag + '\'' + - ", delay=" + delay + - '}'; + "tag='" + tag + '\'' + + ", delay=" + delay + + '}'; } } } diff --git a/athenz-identity-provider-service/src/test/java/com/yahoo/vespa/hosted/athenz/identityprovider/CryptoUtilsTest.java b/container-disc/src/test/java/com/yahoo/container/jdisc/athenz/impl/CryptoUtilsTest.java index 0412b9071dd..dc9690355e8 100644 --- a/athenz-identity-provider-service/src/test/java/com/yahoo/vespa/hosted/athenz/identityprovider/CryptoUtilsTest.java +++ b/container-disc/src/test/java/com/yahoo/container/jdisc/athenz/impl/CryptoUtilsTest.java @@ -1,5 +1,5 @@ // Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.hosted.athenz.identityprovider; +package com.yahoo.container.jdisc.athenz.impl; import org.bouncycastle.pkcs.PKCS10CertificationRequest; import org.junit.Test; diff --git a/parent/pom.xml b/parent/pom.xml index cbcc218b27d..ccbe34841fc 100644 --- a/parent/pom.xml +++ b/parent/pom.xml @@ -707,7 +707,7 @@ <aries.util.version>1.0.0</aries.util.version> <asm-debug-all.version>5.0.3</asm-debug-all.version> <!-- Athenz dependencies. Make sure these dependencies matches those in Vespa's internal repositories --> - <athenz.version>1.7.43</athenz.version> + <athenz.version>1.7.41</athenz.version> <bouncycastle.version>1.58</bouncycastle.version> <commons-lang.version>2.6</commons-lang.version> <!-- WARNING: If you change curator version, you also need to update 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 deleted file mode 100644 index c050ddce2c6..00000000000 --- a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identity/SiaIdentityProvider.java +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.athenz.identity; - -import com.yahoo.athenz.auth.util.Crypto; -import com.yahoo.container.jdisc.athenz.AthenzIdentityProvider; -import com.yahoo.vespa.athenz.api.AthenzDomain; -import com.yahoo.vespa.athenz.api.AthenzIdentityCertificate; -import com.yahoo.vespa.athenz.api.AthenzService; -import com.yahoo.vespa.athenz.tls.AthenzSslContextBuilder; - -import javax.net.ssl.SSLContext; -import java.io.File; -import java.nio.file.Paths; -import java.security.PrivateKey; -import java.security.cert.X509Certificate; - -/** - * @author mortent - */ -public class SiaIdentityProvider implements AthenzIdentityProvider { - - private final AthenzDomain domain; - private final AthenzService service; - private final String path; - - public SiaIdentityProvider(SiaProviderConfig siaProviderConfig) { - this.domain = new AthenzDomain(siaProviderConfig.athenzDomain()); - this.service = new AthenzService(domain, siaProviderConfig.athenzService()); - this.path = siaProviderConfig.keyPathPrefix(); - } - - @Override - public String getDomain() { - return domain.getName(); - } - - @Override - public String getService() { - return service.getName(); - } - - @Override - public SSLContext getIdentitySslContext() { - X509Certificate certificate = Crypto.loadX509Certificate(Paths.get(path, "certs", String.format("%s.%s.cert.pem", getDomain(),getService())).toFile()); - PrivateKey privateKey = Crypto.loadPrivateKey(Paths.get(path, "keys", String.format("%s.%s.key.pem", getDomain(),getService())).toFile()); - - return new AthenzSslContextBuilder() - .withIdentityCertificate(new AthenzIdentityCertificate(certificate, privateKey)) - .build(); - } -} diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identity/package-info.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identity/package-info.java deleted file mode 100644 index da31e72a1fa..00000000000 --- a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identity/package-info.java +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -/** - * @author mortent - */ -@ExportPackage -package com.yahoo.vespa.athenz.identity; - -import com.yahoo.osgi.annotation.ExportPackage;
\ No newline at end of file diff --git a/vespa-athenz/src/main/resources/configdefinitions/sia-provider.def b/vespa-athenz/src/main/resources/configdefinitions/sia-provider.def deleted file mode 100644 index f668ef544f7..00000000000 --- a/vespa-athenz/src/main/resources/configdefinitions/sia-provider.def +++ /dev/null @@ -1,6 +0,0 @@ -# Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -namespace=vespa.athenz.identity - -athenzDomain string -athenzService string -keyPathPrefix string |