summaryrefslogtreecommitdiffstats
path: root/config-model/src
diff options
context:
space:
mode:
Diffstat (limited to 'config-model/src')
-rw-r--r--config-model/src/main/java/com/yahoo/config/model/deploy/DeployState.java19
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/container/ApplicationContainer.java19
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/container/ApplicationContainerCluster.java11
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/container/http/ssl/ConfiguredDirectSslProvider.java5
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilder.java18
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerServiceBuilder.java9
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/content/Content.java2
-rwxr-xr-xconfig-model/src/test/java/com/yahoo/vespa/model/container/ContainerClusterTest.java2
-rw-r--r--config-model/src/test/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilderTest.java43
9 files changed, 116 insertions, 12 deletions
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 86c20bf96af..e8e12888768 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
@@ -24,6 +24,7 @@ import com.yahoo.config.model.provision.SingleNodeProvisioner;
import com.yahoo.config.model.test.MockApplicationPackage;
import com.yahoo.config.provision.Rotation;
import com.yahoo.config.provision.Zone;
+import com.yahoo.io.IOUtils;
import com.yahoo.io.reader.NamedReader;
import com.yahoo.searchdefinition.RankProfileRegistry;
import com.yahoo.searchdefinition.SearchBuilder;
@@ -39,8 +40,10 @@ import com.yahoo.vespa.model.container.search.SemanticRules;
import com.yahoo.vespa.model.search.SearchDefinition;
import java.io.File;
+import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.Reader;
+import java.io.UncheckedIOException;
import java.time.Instant;
import java.util.Collection;
import java.util.Collections;
@@ -263,6 +266,22 @@ public class DeployState implements ConfigDefinitionStore {
public Optional<TlsSecrets> tlsSecrets() { return properties.tlsSecrets(); }
+ public Optional<String> tlsClientAuthority() {
+ var caFile = applicationPackage.getClientSecurityFile();
+ if (caFile.exists()) {
+ try {
+ var caPem = IOUtils.readAll(caFile.createReader());
+ return Optional.of(caPem);
+ } catch (FileNotFoundException e) {
+ return Optional.empty();
+ } catch (IOException e) {
+ throw new UncheckedIOException("Failed reading certificate from application: " + caFile.getPath(), e);
+ }
+ } else {
+ return Optional.empty();
+ }
+ }
+
public static class Builder {
private ApplicationPackage applicationPackage = MockApplicationPackage.createEmpty();
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 d27812a80dd..82f0c87d074 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
@@ -26,11 +26,11 @@ public final class ApplicationContainer extends Container {
private final boolean isHostedVespa;
- 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, int index, boolean isHostedVespa, Optional<TlsSecrets> tlsSecrets, Optional<String> tlsCa) {
+ this(parent, name, false, index, isHostedVespa, tlsSecrets, tlsCa);
}
- public ApplicationContainer(AbstractConfigProducer parent, String name, boolean retired, int index, boolean isHostedVespa, Optional<TlsSecrets> tlsSecrets) {
+ public ApplicationContainer(AbstractConfigProducer parent, String name, boolean retired, int index, boolean isHostedVespa, Optional<TlsSecrets> tlsSecrets, Optional<String> tlsCa) {
super(parent, name, retired, index);
this.isHostedVespa = isHostedVespa;
@@ -40,8 +40,17 @@ public final class ApplicationContainer extends Container {
JettyHttpServer server = Optional.ofNullable(getHttp())
.map(Http::getHttpServer)
.orElse(getDefaultHttpServer());
- server.addConnector(new ConnectorFactory(connectorName, 4443,
- new ConfiguredDirectSslProvider(server.getComponentId().getName(), tlsSecrets.get().key(), tlsSecrets.get().certificate(), null, null)));
+
+ var sslProvider = new ConfiguredDirectSslProvider(
+ server.getComponentId().getName(),
+ tlsSecrets.get().key(),
+ tlsSecrets.get().certificate(),
+ null,
+ tlsCa.orElse(null),
+ null
+ );
+
+ server.addConnector(new ConnectorFactory(connectorName, 4443, sslProvider));
}
addComponent(getFS4ResourcePool()); // TODO Remove when FS4 based search protocol is gone
}
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 473971c5e7a..2b9cd18d64b 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
@@ -56,6 +56,8 @@ public final class ApplicationContainerCluster extends ContainerCluster<Applicat
private ContainerModelEvaluation modelEvaluation;
private Optional<TlsSecrets> tlsSecrets;
+ private Optional<String> tlsClientAuthority;
+ private boolean useTlsClientAuthority = false;
private final boolean enableGroupingSessionCache;
private MbusParams mbusParams;
@@ -65,6 +67,7 @@ public final class ApplicationContainerCluster extends ContainerCluster<Applicat
super(parent, subId, name, deployState);
this.tlsSecrets = deployState.tlsSecrets();
+ this.tlsClientAuthority = deployState.tlsClientAuthority();
this.enableGroupingSessionCache = deployState.getProperties().enableGroupingSessionCache();
restApiGroup = new ConfigProducerGroup<>(this, "rest-api");
servletGroup = new ConfigProducerGroup<>(this, "servlet");
@@ -183,6 +186,10 @@ public final class ApplicationContainerCluster extends ContainerCluster<Applicat
return tlsSecrets;
}
+ public Optional<String> getTlsClientAuthority() {
+ return tlsClientAuthority;
+ }
+
public boolean enableGroupingSessionCache() {
return enableGroupingSessionCache;
}
@@ -205,6 +212,10 @@ public final class ApplicationContainerCluster extends ContainerCluster<Applicat
null))));
}
+ public void useTlsClientAuthority(boolean value) {
+ this.useTlsClientAuthority = value;
+ }
+
public static class MbusParams {
// the amount of the maxpendingbytes to process concurrently, typically 0.2 (20%)
final Double maxConcurrentFactor;
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/http/ssl/ConfiguredDirectSslProvider.java b/config-model/src/main/java/com/yahoo/vespa/model/container/http/ssl/ConfiguredDirectSslProvider.java
index 28dba3331d3..b47aa501ece 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/container/http/ssl/ConfiguredDirectSslProvider.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/container/http/ssl/ConfiguredDirectSslProvider.java
@@ -26,9 +26,10 @@ public class ConfiguredDirectSslProvider extends SimpleComponent implements Conn
private final String privateKey;
private final String certificate;
private final String caCertificatePath;
+ private final String caCertificate;
private final ConnectorConfig.Ssl.ClientAuth.Enum clientAuthentication;
- public ConfiguredDirectSslProvider(String servername, String privateKey, String certificate, String caCertificatePath, String clientAuthentication) {
+ public ConfiguredDirectSslProvider(String servername, String privateKey, String certificate, String caCertificatePath, String caCertificate, String clientAuthentication) {
super(new ComponentModel(
new BundleInstantiationSpecification(new ComponentId(COMPONENT_ID_PREFIX+servername),
fromString(COMPONENT_CLASS),
@@ -36,6 +37,7 @@ public class ConfiguredDirectSslProvider extends SimpleComponent implements Conn
this.privateKey = privateKey;
this.certificate = certificate;
this.caCertificatePath = caCertificatePath;
+ this.caCertificate = caCertificate;
this.clientAuthentication = mapToConfigEnum(clientAuthentication);
}
@@ -45,6 +47,7 @@ public class ConfiguredDirectSslProvider extends SimpleComponent implements Conn
builder.ssl.privateKey(privateKey);
builder.ssl.certificate(certificate);
builder.ssl.caCertificateFile(Optional.ofNullable(caCertificatePath).orElse(""));
+ builder.ssl.caCertificate(Optional.ofNullable(caCertificate).orElse(""));
builder.ssl.clientAuth(clientAuthentication);
}
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilder.java b/config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilder.java
index 2bfb1da9dcb..00aa5423087 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilder.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilder.java
@@ -192,9 +192,21 @@ public class ContainerModelBuilder extends ConfigModelBuilder<ContainerModel> {
addClientProviders(deployState, spec, cluster);
addServerProviders(deployState, spec, cluster);
+ addTlsClientAuthority(deployState, spec, cluster);
+
addAthensCopperArgos(cluster, context); // Must be added after nodes.
}
+ private void addTlsClientAuthority(DeployState deployState, Element spec, ApplicationContainerCluster cluster) {
+ var clientAuthorized = XML.getChild(spec, "client-authorize");
+ if (clientAuthorized != null) {
+ if (deployState.tlsClientAuthority().isEmpty()) {
+ throw new RuntimeException("client-authorize set, but security/clients.pem is missing");
+ }
+ cluster.useTlsClientAuthority(true);
+ }
+ }
+
private void addSecretStore(ApplicationContainerCluster cluster, Element spec) {
Element secretStoreElement = XML.getChild(spec, "secret-store");
if (secretStoreElement != null) {
@@ -440,7 +452,7 @@ public class ContainerModelBuilder extends ConfigModelBuilder<ContainerModel> {
}
private void addStandaloneNode(ApplicationContainerCluster cluster) {
- ApplicationContainer container = new ApplicationContainer(cluster, "standalone", cluster.getContainers().size(), cluster.isHostedVespa(), cluster.getTlsSecrets());
+ ApplicationContainer container = new ApplicationContainer(cluster, "standalone", cluster.getContainers().size(), cluster.isHostedVespa(), cluster.getTlsSecrets(), cluster.getTlsClientAuthority());
cluster.addContainers(Collections.singleton(container));
}
@@ -506,7 +518,7 @@ public class ContainerModelBuilder extends ConfigModelBuilder<ContainerModel> {
Element nodesElement = XML.getChild(containerElement, "nodes");
Element rotationsElement = XML.getChild(containerElement, "rotations");
if (nodesElement == null) { // default single node on localhost
- ApplicationContainer node = new ApplicationContainer(cluster, "container.0", 0, cluster.isHostedVespa(), cluster.getTlsSecrets());
+ ApplicationContainer node = new ApplicationContainer(cluster, "container.0", 0, cluster.isHostedVespa(), cluster.getTlsSecrets(), cluster.getTlsClientAuthority());
HostResource host = allocateSingleNodeHost(cluster, log, containerElement, context);
node.setHostResource(host);
node.initService(context.getDeployLogger());
@@ -695,7 +707,7 @@ public class ContainerModelBuilder extends ConfigModelBuilder<ContainerModel> {
List<ApplicationContainer> nodes = new ArrayList<>();
for (Map.Entry<HostResource, ClusterMembership> entry : hosts.entrySet()) {
String id = "container." + entry.getValue().index();
- ApplicationContainer container = new ApplicationContainer(cluster, id, entry.getValue().retired(), entry.getValue().index(), cluster.isHostedVespa(), cluster.getTlsSecrets());
+ ApplicationContainer container = new ApplicationContainer(cluster, id, entry.getValue().retired(), entry.getValue().index(), cluster.isHostedVespa(), cluster.getTlsSecrets(), cluster.getTlsClientAuthority());
container.setHostResource(entry.getKey());
container.initService(deployLogger);
nodes.add(container);
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 46271d3c0a2..c976a7fb153 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,14 @@ 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.tlsSecrets());
+ return new ApplicationContainer(
+ parent,
+ id,
+ index,
+ deployState.isHosted(),
+ deployState.tlsSecrets(),
+ deployState.tlsClientAuthority()
+ );
}
}
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 8eda707be99..f028f0ac0cc 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().tlsSecrets());
+ modelContext.getDeployState().isHosted(), modelContext.getDeployState().tlsSecrets(), Optional.empty());
index++;
docprocService.useDynamicPorts();
docprocService.setHostResource(host);
diff --git a/config-model/src/test/java/com/yahoo/vespa/model/container/ContainerClusterTest.java b/config-model/src/test/java/com/yahoo/vespa/model/container/ContainerClusterTest.java
index ac85a958ed5..89169c44079 100755
--- a/config-model/src/test/java/com/yahoo/vespa/model/container/ContainerClusterTest.java
+++ b/config-model/src/test/java/com/yahoo/vespa/model/container/ContainerClusterTest.java
@@ -252,7 +252,7 @@ public class ContainerClusterTest {
}
private static void addContainer(DeployLogger deployLogger, ApplicationContainerCluster cluster, String name, String hostName) {
- ApplicationContainer container = new ApplicationContainer(cluster, name, 0, cluster.isHostedVespa(), cluster.getTlsSecrets());
+ ApplicationContainer container = new ApplicationContainer(cluster, name, 0, cluster.isHostedVespa(), cluster.getTlsSecrets(), cluster.getTlsClientAuthority());
container.setHostResource(new HostResource(new Host(null, hostName)));
container.initService(deployLogger);
cluster.addContainer(container);
diff --git a/config-model/src/test/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilderTest.java b/config-model/src/test/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilderTest.java
index 8b92e1091ca..e4fcf6305ed 100644
--- a/config-model/src/test/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilderTest.java
+++ b/config-model/src/test/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilderTest.java
@@ -25,6 +25,7 @@ import com.yahoo.container.servlet.ServletConfigConfig;
import com.yahoo.container.usability.BindingsOverviewHandler;
import com.yahoo.jdisc.http.ServletPathsConfig;
import com.yahoo.net.HostName;
+import com.yahoo.path.Path;
import com.yahoo.prelude.cluster.QrMonitorConfig;
import com.yahoo.search.config.QrStartConfig;
import com.yahoo.vespa.model.AbstractService;
@@ -35,13 +36,18 @@ import com.yahoo.vespa.model.container.SecretStore;
import com.yahoo.vespa.model.container.component.Component;
import com.yahoo.vespa.model.content.utils.ContentClusterUtils;
import com.yahoo.vespa.model.test.utils.VespaModelCreatorWithFilePkg;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;
+import java.io.File;
import java.io.IOException;
+import java.io.StringReader;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.Set;
import java.util.logging.Level;
import java.util.stream.Collectors;
@@ -72,6 +78,8 @@ import static org.junit.Assert.fail;
* @author gjoranv
*/
public class ContainerModelBuilderTest extends ContainerModelBuilderTestBase {
+ @Rule
+ public TemporaryFolder applicationFolder = new TemporaryFolder();
@Test
public void deprecated_jdisc_tag_is_allowed() {
@@ -645,6 +653,41 @@ public class ContainerModelBuilderTest extends ContainerModelBuilderTestBase {
}
@Test
+ public void client_ca_carts_fail_with_missing_clients_pem() {
+ Element clusterElem = DomBuilderTest.parse(
+ "<container version='1.0'>",
+ " <client-authorize />",
+ "</container>");
+ try {
+ createModel(root, clusterElem);
+ } catch (RuntimeException e) {
+ assertEquals(e.getMessage(), "client-authorize set, but security/clients.pem is missing");
+ return;
+ }
+ fail();
+ }
+
+ @Test
+ public void client_ca_carts_succeeds_with_client_authorize_and_clients_pem() {
+ var applicationPackage = new MockApplicationPackage.Builder()
+ .withRoot(applicationFolder.getRoot())
+ .build();
+
+ applicationPackage.getFile(Path.fromString("security")).createDirectory();
+ applicationPackage.getFile(Path.fromString("security/clients.pem")).writeFile(new StringReader("I am a very nice certificate"));
+
+ var deployState = DeployState.createTestState(applicationPackage);
+
+ Element clusterElem = DomBuilderTest.parse(
+ "<container version='1.0'>",
+ " <client-authorize />",
+ "</container>");
+
+ createModel(root, deployState, null, clusterElem);
+ assertEquals(Optional.of("I am a very nice certificate"), getContainerCluster("container").getTlsClientAuthority());
+ }
+
+ @Test
public void environment_vars_are_honoured() {
Element clusterElem = DomBuilderTest.parse(
"<container version='1.0'>",