diff options
author | Morten Tokle <mortent@oath.com> | 2019-06-19 15:53:15 +0200 |
---|---|---|
committer | Morten Tokle <mortent@oath.com> | 2019-06-19 15:53:15 +0200 |
commit | fd45fa97427d75d1837dd9bb6abfeab3e42767cf (patch) | |
tree | ff422193bc595ec1809929429b27461395c97884 | |
parent | e6c2b04c12f77920804119747eca50403ee5745a (diff) |
Read from secret store
20 files changed, 157 insertions, 50 deletions
diff --git a/config-model-api/src/main/java/com/yahoo/config/model/api/ModelContext.java b/config-model-api/src/main/java/com/yahoo/config/model/api/ModelContext.java index f69fa42ba0e..031bc3467f5 100644 --- a/config-model-api/src/main/java/com/yahoo/config/model/api/ModelContext.java +++ b/config-model-api/src/main/java/com/yahoo/config/model/api/ModelContext.java @@ -58,7 +58,7 @@ public interface ModelContext { boolean useAdaptiveDispatch(); // TODO: Remove when 7.61 is the oldest model in use default boolean enableMetricsProxyContainer() { return false; } - String tlsSecretsKeyName(); + Optional<TlsSecrets> tlsSecrets(); } } diff --git a/config-model-api/src/main/java/com/yahoo/config/model/api/TlsSecrets.java b/config-model-api/src/main/java/com/yahoo/config/model/api/TlsSecrets.java new file mode 100644 index 00000000000..a066152aa0b --- /dev/null +++ b/config-model-api/src/main/java/com/yahoo/config/model/api/TlsSecrets.java @@ -0,0 +1,30 @@ +// Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.config.model.api; + +public class TlsSecrets { + public static final TlsSecrets MISSING = new TlsSecrets(); + + private final String certificate; + private final String key; + + private TlsSecrets() { + this(null,null); + } + + public TlsSecrets(String certificate, String key) { + this.certificate = certificate; + this.key = key; + } + + public String certificate() { + return certificate; + } + + public String key() { + return key; + } + + public boolean isMissing() { + return this == MISSING; + } +} diff --git a/config-model/src/main/java/com/yahoo/config/model/deploy/DeployState.java b/config-model/src/main/java/com/yahoo/config/model/deploy/DeployState.java index 5b7672e2d29..2ea1bdb15ee 100644 --- a/config-model/src/main/java/com/yahoo/config/model/deploy/DeployState.java +++ b/config-model/src/main/java/com/yahoo/config/model/deploy/DeployState.java @@ -14,6 +14,7 @@ import com.yahoo.config.model.api.ConfigDefinitionRepo; import com.yahoo.config.model.api.HostProvisioner; import com.yahoo.config.model.api.Model; import com.yahoo.config.model.api.ModelContext; +import com.yahoo.config.model.api.TlsSecrets; import com.yahoo.config.model.api.ValidationParameters; import com.yahoo.config.model.application.provider.BaseDeployLogger; import com.yahoo.config.model.application.provider.MockFileRegistry; @@ -75,7 +76,7 @@ public class DeployState implements ConfigDefinitionStore { private final Version wantedNodeVespaVersion; private final Instant now; private final HostProvisioner provisioner; - private final Optional<String> tlsSecretsKeyName; + private final Optional<TlsSecrets> tlsSecrets; public static DeployState createTestState() { return new Builder().build(); @@ -103,7 +104,7 @@ public class DeployState implements ConfigDefinitionStore { SemanticRules semanticRules, Instant now, Version wantedNodeVespaVersion, - Optional<String> tlsSecretsKeyName) { + Optional<TlsSecrets> tlsSecrets) { this.logger = deployLogger; this.fileRegistry = fileRegistry; this.rankProfileRegistry = rankProfileRegistry; @@ -122,7 +123,7 @@ public class DeployState implements ConfigDefinitionStore { this.semanticRules = semanticRules; // TODO: Remove this by seeing how pagetemplates are propagated this.importedModels = new ImportedMlModels(applicationPackage.getFileReference(ApplicationPackage.MODELS_DIR), modelImporters); - this.tlsSecretsKeyName = tlsSecretsKeyName; + this.tlsSecrets = tlsSecrets; ValidationOverrides suppliedValidationOverrides = applicationPackage.getValidationOverrides().map(ValidationOverrides::fromXml) .orElse(ValidationOverrides.empty); @@ -251,7 +252,7 @@ public class DeployState implements ConfigDefinitionStore { public Instant now() { return now; } - public Optional<String> tlsSecretsKeyName() { return tlsSecretsKeyName; } + public Optional<TlsSecrets> tlsSecrets() { return tlsSecrets; } public static class Builder { @@ -269,7 +270,7 @@ public class DeployState implements ConfigDefinitionStore { private Zone zone = Zone.defaultZone(); private Instant now = Instant.now(); private Version wantedNodeVespaVersion = Vtag.currentVersion; - private Optional<String> tlsSecretsKeyName = Optional.empty(); + private Optional<TlsSecrets> tlsSecrets = Optional.empty(); public Builder applicationPackage(ApplicationPackage applicationPackage) { this.applicationPackage = applicationPackage; @@ -341,8 +342,8 @@ public class DeployState implements ConfigDefinitionStore { return this; } - public Builder tlsSecretsKeyName(String tlsSecretsKeyName) { - this.tlsSecretsKeyName = Optional.ofNullable(tlsSecretsKeyName); + public Builder tlsSecrets(Optional<TlsSecrets> tlsSecrets) { + this.tlsSecrets = tlsSecrets; return this; } @@ -373,7 +374,7 @@ public class DeployState implements ConfigDefinitionStore { semanticRules, now, wantedNodeVespaVersion, - tlsSecretsKeyName); + tlsSecrets); } private SearchDocumentModel createSearchDocumentModel(RankProfileRegistry rankProfileRegistry, diff --git a/config-model/src/main/java/com/yahoo/config/model/deploy/TestProperties.java b/config-model/src/main/java/com/yahoo/config/model/deploy/TestProperties.java index becc46484f4..40d465d1ee6 100644 --- a/config-model/src/main/java/com/yahoo/config/model/deploy/TestProperties.java +++ b/config-model/src/main/java/com/yahoo/config/model/deploy/TestProperties.java @@ -4,6 +4,7 @@ package com.yahoo.config.model.deploy; import com.google.common.collect.ImmutableList; import com.yahoo.config.model.api.ConfigServerSpec; import com.yahoo.config.model.api.ModelContext; +import com.yahoo.config.model.api.TlsSecrets; import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.HostName; import com.yahoo.config.provision.Rotation; @@ -12,6 +13,7 @@ import com.yahoo.config.provision.Zone; import java.net.URI; import java.util.Collections; import java.util.List; +import java.util.Optional; import java.util.Set; /** @@ -37,7 +39,7 @@ public class TestProperties implements ModelContext.Properties { private boolean useFdispatchByDefault = true; private boolean dispatchWithProtobuf = true; private boolean useAdaptiveDispatch = false; - private String tlsSecretsKeyName = null; + private Optional<TlsSecrets> tlsSecrets = Optional.empty(); @Override public boolean multitenant() { return multitenant; } @@ -55,7 +57,7 @@ public class TestProperties implements ModelContext.Properties { @Override public boolean useDedicatedNodeForLogserver() { return useDedicatedNodeForLogserver; } @Override public boolean useFdispatchByDefault() { return useFdispatchByDefault; } @Override public boolean dispatchWithProtobuf() { return dispatchWithProtobuf; } - @Override public String tlsSecretsKeyName() { return tlsSecretsKeyName; } + @Override public Optional<TlsSecrets> tlsSecrets() { return tlsSecrets; } public TestProperties setApplicationId(ApplicationId applicationId) { this.applicationId = applicationId; @@ -88,8 +90,8 @@ public class TestProperties implements ModelContext.Properties { } - public TestProperties setTlsSecretsKeyName(String tlsSecretsKeyName) { - this.tlsSecretsKeyName = tlsSecretsKeyName; + public TestProperties setTlsSecrets(Optional<TlsSecrets> tlsSecrets) { + this.tlsSecrets = tlsSecrets; return this; } diff --git a/config-model/src/main/java/com/yahoo/vespa/model/VespaModelFactory.java b/config-model/src/main/java/com/yahoo/vespa/model/VespaModelFactory.java index 78d46533b96..37eb37c9e61 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/VespaModelFactory.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/VespaModelFactory.java @@ -143,7 +143,7 @@ public class VespaModelFactory implements ModelFactory { .zone(zone) .now(clock.instant()) .wantedNodeVespaVersion(modelContext.wantedNodeVespaVersion()) - .tlsSecretsKeyName(modelContext.properties().tlsSecretsKeyName()); + .tlsSecrets(modelContext.properties().tlsSecrets()); modelContext.previousModel().ifPresent(builder::previousModel); return builder.build(validationParameters); } diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/ApplicationContainer.java b/config-model/src/main/java/com/yahoo/vespa/model/container/ApplicationContainer.java index d52eeb41c8c..ce0aa78d8d1 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/container/ApplicationContainer.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/container/ApplicationContainer.java @@ -2,6 +2,7 @@ package com.yahoo.vespa.model.container; import com.yahoo.component.ComponentId; +import com.yahoo.config.model.api.TlsSecrets; import com.yahoo.config.model.api.container.ContainerServiceType; import com.yahoo.config.model.producer.AbstractConfigProducer; import com.yahoo.vespa.model.container.http.ConnectorFactory; @@ -21,23 +22,23 @@ public final class ApplicationContainer extends Container { private final boolean isHostedVespa; - private final Optional<String> tlsSecretsKey; + private final Optional<TlsSecrets> tlsSecrets; - public ApplicationContainer(AbstractConfigProducer parent, String name, int index, boolean isHostedVespa, Optional<String> tlsSecretsKey) { - this(parent, name, false, index, isHostedVespa, tlsSecretsKey); + public ApplicationContainer(AbstractConfigProducer parent, String name, int index, boolean isHostedVespa, Optional<TlsSecrets> tlsSecrets) { + this(parent, name, false, index, isHostedVespa, tlsSecrets); } - public ApplicationContainer(AbstractConfigProducer parent, String name, boolean retired, int index, boolean isHostedVespa, Optional<String> tlsSecretsKey) { + public ApplicationContainer(AbstractConfigProducer parent, String name, boolean retired, int index, boolean isHostedVespa, Optional<TlsSecrets> tlsSecrets) { super(parent, name, retired, index); this.isHostedVespa = isHostedVespa; - this.tlsSecretsKey = tlsSecretsKey; + this.tlsSecrets = tlsSecrets; - if (isHostedVespa && tlsSecretsKey.isPresent()) { + if (isHostedVespa && tlsSecrets.isPresent()) { // set up port 4443 based on tlsSecretsKey String server = "DefaultHttpsServer"; // TODO: verify that using this makes sense in all cases below final JettyHttpServer defaultHttpsServer = new JettyHttpServer(new ComponentId(server)); defaultHttpsServer.addConnector(new ConnectorFactory(server, 4443, - new ConfiguredDirectSslProvider(server, tlsSecretsKey + "TODO", tlsSecretsKey + "TODO", null, null))); + new ConfiguredDirectSslProvider(server, tlsSecrets.get().key(), tlsSecrets.get().certificate(), null, null))); } } diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/ApplicationContainerCluster.java b/config-model/src/main/java/com/yahoo/vespa/model/container/ApplicationContainerCluster.java index e9271b7f8cb..5bb68465d47 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/container/ApplicationContainerCluster.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/container/ApplicationContainerCluster.java @@ -4,6 +4,7 @@ package com.yahoo.vespa.model.container; import com.yahoo.component.ComponentId; import com.yahoo.config.FileReference; import com.yahoo.config.application.api.ComponentInfo; +import com.yahoo.config.model.api.TlsSecrets; import com.yahoo.config.model.deploy.DeployState; import com.yahoo.config.model.producer.AbstractConfigProducer; import com.yahoo.container.BundlesConfig; @@ -46,12 +47,12 @@ public final class ApplicationContainerCluster extends ContainerCluster<Applicat private ContainerModelEvaluation modelEvaluation; - private Optional<String> tlsSecretsKeyName; + private Optional<TlsSecrets> tlsSecretsKeyName; public ApplicationContainerCluster(AbstractConfigProducer<?> parent, String subId, String name, DeployState deployState) { super(parent, subId, name, deployState); - this.tlsSecretsKeyName = deployState.tlsSecretsKeyName(); + this.tlsSecretsKeyName = deployState.tlsSecrets(); restApiGroup = new ConfigProducerGroup<>(this, "rest-api"); servletGroup = new ConfigProducerGroup<>(this, "servlet"); @@ -144,7 +145,7 @@ public final class ApplicationContainerCluster extends ContainerCluster<Applicat if (modelEvaluation != null) modelEvaluation.getConfig(builder); } - public Optional<String> getTlsSecretsKeyName() { + public Optional<TlsSecrets> getTlsSecretsKeyName() { return tlsSecretsKeyName; } diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerServiceBuilder.java b/config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerServiceBuilder.java index f82564987f6..46271d3c0a2 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerServiceBuilder.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerServiceBuilder.java @@ -22,7 +22,7 @@ public class ContainerServiceBuilder extends VespaDomBuilder.DomConfigProducerBu @Override protected ApplicationContainer doBuild(DeployState deployState, AbstractConfigProducer parent, Element nodeElem) { - return new ApplicationContainer(parent, id, index, deployState.isHosted(), deployState.tlsSecretsKeyName()); + return new ApplicationContainer(parent, id, index, deployState.isHosted(), deployState.tlsSecrets()); } } diff --git a/config-model/src/main/java/com/yahoo/vespa/model/content/Content.java b/config-model/src/main/java/com/yahoo/vespa/model/content/Content.java index c02a4019286..8eda707be99 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/content/Content.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/content/Content.java @@ -324,7 +324,7 @@ public class Content extends ConfigModel { if (!processedHosts.contains(host)) { String containerName = String.valueOf(searchNode.getDistributionKey()); ApplicationContainer docprocService = new ApplicationContainer(indexingCluster, containerName, index, - modelContext.getDeployState().isHosted(), modelContext.getDeployState().tlsSecretsKeyName()); + modelContext.getDeployState().isHosted(), modelContext.getDeployState().tlsSecrets()); index++; docprocService.useDynamicPorts(); docprocService.setHostResource(host); diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/GlobalComponentRegistry.java b/configserver/src/main/java/com/yahoo/vespa/config/server/GlobalComponentRegistry.java index d420c3f21fe..1eb18773898 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/GlobalComponentRegistry.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/GlobalComponentRegistry.java @@ -7,6 +7,7 @@ import com.yahoo.config.model.api.ConfigDefinitionRepo; import com.yahoo.config.provision.Provisioner; import com.yahoo.config.provision.TenantName; import com.yahoo.config.provision.Zone; +import com.yahoo.container.jdisc.secretstore.SecretStore; import com.yahoo.vespa.config.server.application.PermanentApplicationPackage; import com.yahoo.vespa.config.server.host.HostRegistries; import com.yahoo.vespa.config.server.modelfactory.ModelFactoryRegistry; @@ -46,4 +47,5 @@ public interface GlobalComponentRegistry { StripedExecutor<TenantName> getZkWatcherExecutor(); FlagSource getFlagSource(); ExecutorService getZkCacheExecutor(); + SecretStore getSecretStore(); } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/InjectedGlobalComponentRegistry.java b/configserver/src/main/java/com/yahoo/vespa/config/server/InjectedGlobalComponentRegistry.java index ff76afd1c98..9badd19009f 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/InjectedGlobalComponentRegistry.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/InjectedGlobalComponentRegistry.java @@ -9,6 +9,7 @@ import com.yahoo.config.model.api.ConfigDefinitionRepo; import com.yahoo.config.provision.Provisioner; import com.yahoo.config.provision.TenantName; import com.yahoo.config.provision.Zone; +import com.yahoo.container.jdisc.secretstore.SecretStore; import com.yahoo.vespa.config.server.application.PermanentApplicationPackage; import com.yahoo.vespa.config.server.host.HostRegistries; import com.yahoo.vespa.config.server.modelfactory.ModelFactoryRegistry; @@ -48,6 +49,7 @@ public class InjectedGlobalComponentRegistry implements GlobalComponentRegistry private final Zone zone; private final ConfigServerDB configServerDB; private final FlagSource flagSource; + private final SecretStore secretStore; private final StripedExecutor<TenantName> zkWatcherExecutor; private final ExecutorService zkCacheExecutor; @@ -67,7 +69,8 @@ public class InjectedGlobalComponentRegistry implements GlobalComponentRegistry HostProvisionerProvider hostProvisionerProvider, Zone zone, ConfigServerDB configServerDB, - FlagSource flagSource) { + FlagSource flagSource, + SecretStore secretStore) { this.curator = curator; this.configCurator = configCurator; this.metrics = metrics; @@ -82,6 +85,7 @@ public class InjectedGlobalComponentRegistry implements GlobalComponentRegistry this.zone = zone; this.configServerDB = configServerDB; this.flagSource = flagSource; + this.secretStore = secretStore; this.zkWatcherExecutor = new StripedExecutor<>(); this.zkCacheExecutor = Executors.newFixedThreadPool(1, ThreadFactoryFactory.getThreadFactory(TenantRepository.class.getName())); } @@ -137,4 +141,9 @@ public class InjectedGlobalComponentRegistry implements GlobalComponentRegistry public ExecutorService getZkCacheExecutor() { return zkCacheExecutor; } + + @Override + public SecretStore getSecretStore() { + return secretStore; + } } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ModelContextImpl.java b/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ModelContextImpl.java index 13a94caf04f..97eed129f2f 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ModelContextImpl.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ModelContextImpl.java @@ -10,6 +10,7 @@ import com.yahoo.config.model.api.ConfigServerSpec; import com.yahoo.config.model.api.HostProvisioner; import com.yahoo.config.model.api.Model; import com.yahoo.config.model.api.ModelContext; +import com.yahoo.config.model.api.TlsSecrets; import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.HostName; import com.yahoo.config.provision.Rotation; @@ -132,7 +133,7 @@ public class ModelContextImpl implements ModelContext { private final boolean useFdispatchByDefault; private final boolean useAdaptiveDispatch; private final boolean dispatchWithProtobuf; - private final String tlsSecretsKeyName; + private final Optional<TlsSecrets> tlsSecrets; public Properties(ApplicationId applicationId, boolean multitenantFromConfig, @@ -146,7 +147,7 @@ public class ModelContextImpl implements ModelContext { boolean isBootstrap, boolean isFirstTimeDeployment, FlagSource flagSource, - String tlsSecretsKeyName) { + Optional<TlsSecrets> tlsSecrets) { this.applicationId = applicationId; this.multitenant = multitenantFromConfig || hostedVespa || Boolean.getBoolean("multitenant"); this.configServerSpecs = configServerSpecs; @@ -166,7 +167,7 @@ public class ModelContextImpl implements ModelContext { .with(FetchVector.Dimension.APPLICATION_ID, applicationId.serializedForm()).value(); this.useAdaptiveDispatch = Flags.USE_ADAPTIVE_DISPATCH.bindTo(flagSource) .with(FetchVector.Dimension.APPLICATION_ID, applicationId.serializedForm()).value(); - this.tlsSecretsKeyName = tlsSecretsKeyName; + this.tlsSecrets = tlsSecrets; } @Override @@ -219,7 +220,7 @@ public class ModelContextImpl implements ModelContext { public boolean useAdaptiveDispatch() { return useAdaptiveDispatch; } @Override - public String tlsSecretsKeyName() { return tlsSecretsKeyName; } + public Optional<TlsSecrets> tlsSecrets() { return tlsSecrets; } } } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ActivatedModelsBuilder.java b/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ActivatedModelsBuilder.java index 3fb640cb91a..08bc222a4c4 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ActivatedModelsBuilder.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ActivatedModelsBuilder.java @@ -12,6 +12,7 @@ import com.yahoo.config.provision.AllocatedHosts; import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.HostName; import com.yahoo.config.provision.TenantName; +import com.yahoo.container.jdisc.secretstore.SecretStore; import com.yahoo.log.LogLevel; import com.yahoo.vespa.config.server.ConfigServerSpec; import com.yahoo.vespa.config.server.GlobalComponentRegistry; @@ -54,6 +55,7 @@ public class ActivatedModelsBuilder extends ModelsBuilder<Application> { private final Curator curator; private final DeployLogger logger; private final FlagSource flagSource; + private final SecretStore secretStore; public ActivatedModelsBuilder(TenantName tenant, long appGeneration, @@ -72,6 +74,7 @@ public class ActivatedModelsBuilder extends ModelsBuilder<Application> { this.curator = globalComponentRegistry.getCurator(); this.logger = new SilentDeployLogger(); this.flagSource = globalComponentRegistry.getFlagSource(); + this.secretStore = globalComponentRegistry.getSecretStore(); } @Override @@ -131,7 +134,7 @@ public class ActivatedModelsBuilder extends ModelsBuilder<Application> { false, // We may be bootstrapping, but we only know and care during prepare false, // Always false, assume no one uses it when activating flagSource, - new TlsSecretsKeys(curator, TenantRepository.getTenantPath(tenant)).readTlsSecretsKeyFromZookeeper(applicationId).orElse(null)); + new TlsSecretsKeys(curator, TenantRepository.getTenantPath(tenant), secretStore).readTlsSecretsKeyFromZookeeper(applicationId)); } } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionPreparer.java b/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionPreparer.java index 56a964710cd..b224a218a9d 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionPreparer.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionPreparer.java @@ -12,11 +12,13 @@ import com.yahoo.config.application.api.DeploymentSpec; import com.yahoo.config.application.api.FileRegistry; import com.yahoo.config.model.api.ConfigDefinitionRepo; import com.yahoo.config.model.api.ModelContext; +import com.yahoo.config.model.api.TlsSecrets; import com.yahoo.config.provision.AllocatedHosts; import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.HostName; import com.yahoo.config.provision.Rotation; import com.yahoo.config.provision.Zone; +import com.yahoo.container.jdisc.secretstore.SecretStore; import com.yahoo.lang.SettableOptional; import com.yahoo.log.LogLevel; import com.yahoo.path.Path; @@ -69,6 +71,7 @@ public class SessionPreparer { private final Curator curator; private final Zone zone; private final FlagSource flagSource; + private final SecretStore secretStore; @Inject public SessionPreparer(ModelFactoryRegistry modelFactoryRegistry, @@ -79,7 +82,8 @@ public class SessionPreparer { ConfigDefinitionRepo configDefinitionRepo, Curator curator, Zone zone, - FlagSource flagSource) { + FlagSource flagSource, + SecretStore secretStore) { this.modelFactoryRegistry = modelFactoryRegistry; this.fileDistributionFactory = fileDistributionFactory; this.hostProvisionerProvider = hostProvisionerProvider; @@ -89,6 +93,7 @@ public class SessionPreparer { this.curator = curator; this.zone = zone; this.flagSource = flagSource; + this.secretStore = secretStore; } /** @@ -142,10 +147,11 @@ public class SessionPreparer { final com.yahoo.component.Version vespaVersion; final Rotations rotations; // TODO: Remove this once we have migrated fully to container endpoints - final TlsSecretsKeys tlsSecretsKeys; final ContainerEndpointsCache containerEndpoints; final Set<Rotation> rotationsSet; final ModelContext.Properties properties; + private final TlsSecretsKeys tlsSecretsKeys; + private final Optional<TlsSecrets> tlsSecrets; private ApplicationPackage applicationPackage; private List<PreparedModelsBuilder.PreparedModelResult> modelResultList; @@ -164,9 +170,11 @@ public class SessionPreparer { this.applicationId = params.getApplicationId(); this.vespaVersion = params.vespaVersion().orElse(Vtag.currentVersion); this.rotations = new Rotations(curator, tenantPath); - this.tlsSecretsKeys = new TlsSecretsKeys(curator, tenantPath); this.containerEndpoints = new ContainerEndpointsCache(tenantPath, curator); this.rotationsSet = getRotations(params.rotations()); + this.tlsSecretsKeys = new TlsSecretsKeys(curator, tenantPath, secretStore); + this.tlsSecrets = tlsSecretsKeys.getTlsSecrets(params.tlsSecretsKeyName(), applicationId); + this.properties = new ModelContextImpl.Properties(params.getApplicationId(), configserverConfig.multitenant(), ConfigServerSpec.fromConfig(configserverConfig), @@ -179,7 +187,7 @@ public class SessionPreparer { params.isBootstrap(), ! currentActiveApplicationSet.isPresent(), context.getFlagSource(), - params.tlsSecretsKeyName().orElse(null)); + tlsSecrets); this.preparedModelsBuilder = new PreparedModelsBuilder(modelFactoryRegistry, permanentApplicationPackage, configDefinitionRepo, diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TlsSecretsKeys.java b/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TlsSecretsKeys.java index 893dd81deca..b336b527aa7 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TlsSecretsKeys.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TlsSecretsKeys.java @@ -3,9 +3,10 @@ package com.yahoo.vespa.config.server.tenant; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; +import com.yahoo.config.model.api.TlsSecrets; import com.yahoo.config.provision.ApplicationId; +import com.yahoo.container.jdisc.secretstore.SecretStore; import com.yahoo.path.Path; - import com.yahoo.vespa.curator.Curator; import com.yahoo.vespa.curator.transaction.CuratorOperations; import com.yahoo.vespa.curator.transaction.CuratorTransaction; @@ -20,19 +21,21 @@ import java.util.Optional; public class TlsSecretsKeys { private final Path path; + private final SecretStore secretStore; private final Curator curator; - public TlsSecretsKeys(Curator curator, Path tenantPath) { + public TlsSecretsKeys(Curator curator, Path tenantPath, SecretStore secretStore) { this.curator = curator; this.path = tenantPath.append("tlsSecretsKeys/"); + this.secretStore = secretStore; } - public Optional<String> readTlsSecretsKeyFromZookeeper(ApplicationId application) { + public Optional<TlsSecrets> readTlsSecretsKeyFromZookeeper(ApplicationId application) { try { Optional<byte[]> data = curator.getData(tlsSecretsKeyOf(application)); if (data.isEmpty() || data.get().length == 0) return Optional.empty(); String tlsSecretsKey = new ObjectMapper().readValue(data.get(), new TypeReference<String>() {}); - return Optional.of(tlsSecretsKey); + return readFromSecretStore(Optional.ofNullable(tlsSecretsKey)); } catch (Exception e) { throw new RuntimeException("Error reading TLS secret key of " + application, e); } @@ -48,6 +51,27 @@ public class TlsSecretsKeys { } } + public Optional<TlsSecrets> getTlsSecrets(Optional<String> secretKeyname, ApplicationId applicationId) { + if (secretKeyname == null || secretKeyname.isEmpty()) { + return readTlsSecretsKeyFromZookeeper(applicationId); + } + return readFromSecretStore(secretKeyname); + } + + private Optional<TlsSecrets> readFromSecretStore(Optional<String> secretKeyname) { + if(secretKeyname.isEmpty()) return Optional.empty(); + TlsSecrets tlsSecretParameters = TlsSecrets.MISSING; + try { + String cert = secretStore.getSecret(secretKeyname + "-cert"); + String key = secretStore.getSecret(secretKeyname + "-key"); + tlsSecretParameters = new TlsSecrets(cert, key); + } catch (RuntimeException e) { + // Assume not ready yet +// log.log(LogLevel.DEBUG, "Could not fetch certificate/key with prefix: " + secretKeyname.get(), e); + } + return Optional.of(tlsSecretParameters); + } + /** Returns a transaction which deletes these tls secrets key if they exist */ public CuratorTransaction delete(ApplicationId application) { if (!curator.exists(tlsSecretsKeyOf(application))) return CuratorTransaction.empty(curator); diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/InjectedGlobalComponentRegistryTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/InjectedGlobalComponentRegistryTest.java index 9b113cae715..e4ff8702ff1 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/InjectedGlobalComponentRegistryTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/InjectedGlobalComponentRegistryTest.java @@ -78,7 +78,7 @@ public class InjectedGlobalComponentRegistryTest { globalComponentRegistry = new InjectedGlobalComponentRegistry(curator, configCurator, metrics, modelFactoryRegistry, sessionPreparer, rpcServer, configserverConfig, generationCounter, defRepo, permanentApplicationPackage, hostRegistries, hostProvisionerProvider, zone, - new ConfigServerDB(configserverConfig), new InMemoryFlagSource()); + new ConfigServerDB(configserverConfig), new InMemoryFlagSource(), new MockSecretStore()); } @Test diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/MockSecretStore.java b/configserver/src/test/java/com/yahoo/vespa/config/server/MockSecretStore.java new file mode 100644 index 00000000000..2e521b5e600 --- /dev/null +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/MockSecretStore.java @@ -0,0 +1,16 @@ +// Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.config.server; + +import com.yahoo.container.jdisc.secretstore.SecretStore; + +public class MockSecretStore implements SecretStore { + @Override + public String getSecret(String key) { + return null; + } + + @Override + public String getSecret(String key, int version) { + return null; + } +} diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/TestComponentRegistry.java b/configserver/src/test/java/com/yahoo/vespa/config/server/TestComponentRegistry.java index 62685734a47..a304f74858b 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/TestComponentRegistry.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/TestComponentRegistry.java @@ -5,12 +5,12 @@ import com.google.common.io.Files; import com.yahoo.cloud.config.ConfigserverConfig; import com.yahoo.concurrent.InThreadExecutorService; import com.yahoo.concurrent.StripedExecutor; -import com.yahoo.concurrent.ThreadFactoryFactory; import com.yahoo.config.model.NullConfigModelRegistry; import com.yahoo.config.model.api.ConfigDefinitionRepo; import com.yahoo.config.provision.Provisioner; import com.yahoo.config.provision.TenantName; import com.yahoo.config.provision.Zone; +import com.yahoo.container.jdisc.secretstore.SecretStore; import com.yahoo.vespa.config.server.application.PermanentApplicationPackage; import com.yahoo.vespa.config.server.host.HostRegistries; import com.yahoo.vespa.config.server.modelfactory.ModelFactoryRegistry; @@ -21,7 +21,6 @@ import com.yahoo.vespa.config.server.session.MockFileDistributionFactory; import com.yahoo.vespa.config.server.session.SessionPreparer; import com.yahoo.vespa.config.server.tenant.MockTenantListener; import com.yahoo.vespa.config.server.tenant.TenantListener; -import com.yahoo.vespa.config.server.tenant.TenantRepository; import com.yahoo.vespa.config.server.tenant.TenantRequestHandlerTest; import com.yahoo.vespa.config.server.zookeeper.ConfigCurator; import com.yahoo.vespa.curator.Curator; @@ -34,7 +33,6 @@ import java.time.Clock; import java.util.Collections; import java.util.Optional; import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; /** @@ -60,6 +58,7 @@ public class TestComponentRegistry implements GlobalComponentRegistry { private final ConfigServerDB configServerDB; private final StripedExecutor<TenantName> zkWatcherExecutor; private final ExecutorService zkCacheExecutor; + private final SecretStore secretStore; private TestComponentRegistry(Curator curator, ConfigCurator configCurator, Metrics metrics, ModelFactoryRegistry modelFactoryRegistry, @@ -73,7 +72,8 @@ public class TestComponentRegistry implements GlobalComponentRegistry { ReloadListener reloadListener, TenantListener tenantListener, Zone zone, - Clock clock) { + Clock clock, + SecretStore secretStore) { this.curator = curator; this.configCurator = configCurator; this.metrics = metrics; @@ -92,6 +92,7 @@ public class TestComponentRegistry implements GlobalComponentRegistry { this.configServerDB = new ConfigServerDB(configserverConfig); this.zkWatcherExecutor = new StripedExecutor<>(new InThreadExecutorService()); this.zkCacheExecutor = new InThreadExecutorService(); + this.secretStore = secretStore; } public static class Builder { @@ -161,14 +162,15 @@ public class TestComponentRegistry implements GlobalComponentRegistry { .orElse(new MockFileDistributionFactory(configserverConfig)); HostProvisionerProvider hostProvisionerProvider = hostProvisioner. map(HostProvisionerProvider::withProvisioner).orElseGet(HostProvisionerProvider::empty); + SecretStore secretStore = new MockSecretStore(); SessionPreparer sessionPreparer = new SessionPreparer(modelFactoryRegistry, fileDistributionFactory, hostProvisionerProvider, permApp, configserverConfig, defRepo, curator, - zone, new InMemoryFlagSource()); + zone, new InMemoryFlagSource(), secretStore); return new TestComponentRegistry(curator, ConfigCurator.create(curator), metrics, modelFactoryRegistry, permApp, fileDistributionFactory, hostRegistries, configserverConfig, sessionPreparer, hostProvisioner, defRepo, reloadListener, tenantListener, - zone, clock); + zone, clock, secretStore); } } @@ -220,6 +222,11 @@ public class TestComponentRegistry implements GlobalComponentRegistry { return zkCacheExecutor; } + @Override + public SecretStore getSecretStore() { + return secretStore; + } + public FileDistributionFactory getFileDistributionFactory() { return fileDistributionFactory; } } diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionPreparerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionPreparerTest.java index 6b2810af66c..379481f49d6 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionPreparerTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionPreparerTest.java @@ -17,6 +17,7 @@ import com.yahoo.path.Path; import com.yahoo.slime.Slime; import com.yahoo.vespa.applicationmodel.ClusterId; import com.yahoo.vespa.config.server.MockReloadHandler; +import com.yahoo.vespa.config.server.MockSecretStore; import com.yahoo.vespa.config.server.TestComponentRegistry; import com.yahoo.vespa.config.server.TimeoutBudgetTest; import com.yahoo.vespa.config.server.application.PermanentApplicationPackage; @@ -72,7 +73,7 @@ public class SessionPreparerTest { private SessionPreparer preparer; private TestComponentRegistry componentRegistry; private MockFileDistributionFactory fileDistributionFactory; - + private MockSecretStore secretStore = new MockSecretStore(); @Rule public TemporaryFolder folder = new TemporaryFolder(); @@ -107,7 +108,8 @@ public class SessionPreparerTest { componentRegistry.getStaticConfigDefinitionRepo(), curator, componentRegistry.getZone(), - flagSource); + flagSource, + secretStore); } @Test(expected = InvalidApplicationException.class) diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionTest.java index 95f6c7718e2..b2ad0af8f9a 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionTest.java @@ -21,7 +21,7 @@ public class SessionTest { public boolean isPrepared = false; public MockSessionPreparer() { - super(null, null, null, null, null, null, new MockCurator(), null, null); + super(null, null, null, null, null, null, new MockCurator(), null, null, null); } @Override |