diff options
15 files changed, 143 insertions, 21 deletions
diff --git a/config-model-api/abi-spec.json b/config-model-api/abi-spec.json index 9f86fe4dea2..8d83d16a272 100644 --- a/config-model-api/abi-spec.json +++ b/config-model-api/abi-spec.json @@ -111,6 +111,7 @@ "public java.util.List getQueryProfileFiles()", "public java.util.List getQueryProfileTypeFiles()", "public java.util.List getPageTemplateFiles()", + "public com.yahoo.config.application.api.ApplicationFile getClientSecurityFile()", "public abstract java.lang.String getHostSource()", "public abstract java.lang.String getServicesSource()", "public abstract java.util.Optional getDeployment()", @@ -148,6 +149,7 @@ "public static final com.yahoo.path.Path RULES_DIR", "public static final com.yahoo.path.Path DEPLOYMENT_FILE", "public static final com.yahoo.path.Path VALIDATION_OVERRIDES", + "public static final com.yahoo.path.Path SECURITY_DIR", "public static final java.lang.String SD_NAME_SUFFIX", "public static final java.lang.String RANKEXPRESSION_NAME_SUFFIX", "public static final java.lang.String RULES_NAME_SUFFIX", diff --git a/config-model-api/src/main/java/com/yahoo/config/application/api/ApplicationPackage.java b/config-model-api/src/main/java/com/yahoo/config/application/api/ApplicationPackage.java index 06f8034453d..5cd119dcf65 100644 --- a/config-model-api/src/main/java/com/yahoo/config/application/api/ApplicationPackage.java +++ b/config-model-api/src/main/java/com/yahoo/config/application/api/ApplicationPackage.java @@ -27,7 +27,6 @@ import java.util.Map; import java.util.Optional; import java.util.jar.JarEntry; import java.util.jar.JarFile; -import java.util.stream.Collectors; /** * Represents an application package, that is, used as input when creating a VespaModel and as @@ -73,6 +72,8 @@ public interface ApplicationPackage { Path DEPLOYMENT_FILE = Path.fromString("deployment.xml"); Path VALIDATION_OVERRIDES = Path.fromString("validation-overrides.xml"); + Path SECURITY_DIR = Path.fromString("security"); + String SD_NAME_SUFFIX = ".sd"; String RANKEXPRESSION_NAME_SUFFIX = ".expression"; String RULES_NAME_SUFFIX = ".sr"; @@ -178,6 +179,9 @@ public interface ApplicationPackage { /** Does {@link #getFiles} on the page template directory and gets all xml files */ default List<NamedReader> getPageTemplateFiles() { return getFiles(PAGE_TEMPLATES_DIR,".xml"); } + /** Returns handle for the file containing client certificate authorities */ + default ApplicationFile getClientSecurityFile() { return getFile(SECURITY_DIR.append("clients.pem")); } + //For generating error messages String getHostSource(); String getServicesSource(); 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 index 3cb4cedcbac..6a8b5a237ab 100644 --- 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 @@ -1,30 +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 class TlsSecrets { public static final TlsSecrets MISSING = new TlsSecrets(); - private final String certificate; + private final String certificate; private final String key; - private TlsSecrets() { - this(null,null); + private TlsSecrets() { + this(null, null); } - public TlsSecrets(String certificate, String key) { + public TlsSecrets(String certificate, String key) { this.certificate = certificate; this.key = key; } - public String certificate() { + public String certificate() { return certificate; } - public String key() { + public String key() { return key; } - public boolean isMissing() { + 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 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'>", diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ZooKeeperClient.java b/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ZooKeeperClient.java index 484124991d9..a99a2a2917d 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ZooKeeperClient.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ZooKeeperClient.java @@ -202,6 +202,9 @@ public class ZooKeeperClient { writeDir(app.getFile(ApplicationPackage.MODELS_GENERATED_REPLICATED_DIR), getZooKeeperAppPath(ConfigCurator.USERAPP_ZK_SUBPATH).append(ApplicationPackage.MODELS_GENERATED_REPLICATED_DIR), true); + writeDir(app.getFile(ApplicationPackage.SECURITY_DIR), + getZooKeeperAppPath(ConfigCurator.USERAPP_ZK_SUBPATH).append(ApplicationPackage.SECURITY_DIR), + true); } private void writeDir(ApplicationFile file, Path zooKeeperAppPath, boolean recurse) throws IOException { diff --git a/jdisc_http_service/abi-spec.json b/jdisc_http_service/abi-spec.json index 6f41c4ced06..6e04ba741e6 100644 --- a/jdisc_http_service/abi-spec.json +++ b/jdisc_http_service/abi-spec.json @@ -84,6 +84,7 @@ "public com.yahoo.jdisc.http.ConnectorConfig$Ssl$Builder certificateFile(java.lang.String)", "public com.yahoo.jdisc.http.ConnectorConfig$Ssl$Builder certificate(java.lang.String)", "public com.yahoo.jdisc.http.ConnectorConfig$Ssl$Builder caCertificateFile(java.lang.String)", + "public com.yahoo.jdisc.http.ConnectorConfig$Ssl$Builder caCertificate(java.lang.String)", "public com.yahoo.jdisc.http.ConnectorConfig$Ssl$Builder clientAuth(com.yahoo.jdisc.http.ConnectorConfig$Ssl$ClientAuth$Enum)", "public com.yahoo.jdisc.http.ConnectorConfig$Ssl build()" ], @@ -139,6 +140,7 @@ "public java.lang.String certificateFile()", "public java.lang.String certificate()", "public java.lang.String caCertificateFile()", + "public java.lang.String caCertificate()", "public com.yahoo.jdisc.http.ConnectorConfig$Ssl$ClientAuth$Enum clientAuth()" ], "fields": [] diff --git a/jdisc_http_service/src/main/resources/configdefinitions/jdisc.http.connector.def b/jdisc_http_service/src/main/resources/configdefinitions/jdisc.http.connector.def index c6de875417c..f02a0d7b4a3 100644 --- a/jdisc_http_service/src/main/resources/configdefinitions/jdisc.http.connector.def +++ b/jdisc_http_service/src/main/resources/configdefinitions/jdisc.http.connector.def @@ -69,8 +69,15 @@ ssl.certificateFile string default="" ssl.certificate string default="" # with trusted CA certificates in PEM format. Used to verify clients +# - this is the name of a file on the local container file system +# - only one of caCertificateFile and caCertificate ssl.caCertificateFile string default="" +# with trusted CA certificates in PEM format. Used to verify clients +# - this is the actual certificates instead of a pointer to the file +# - only one of caCertificateFile and caCertificate +ssl.caCertificate string default="" + # Client authentication mode. See SSLEngine.getNeedClientAuth()/getWantClientAuth() for details. ssl.clientAuth enum { DISABLED, WANT_AUTH, NEED_AUTH } default=DISABLED |