This is an automated email from the ASF dual-hosted git repository. tallison pushed a commit to branch TIKA-3719 in repository https://gitbox.apache.org/repos/asf/tika.git
commit 4aa79edac8ea2d02766561422af8e416ad59da6d Author: tallison <[email protected]> AuthorDate: Wed Apr 20 16:45:32 2022 -0400 TIKA-3719 -- initial commit --- .../apache/tika/server/core/TikaServerConfig.java | 7 ++ .../apache/tika/server/core/TikaServerProcess.java | 39 +++++- .../org/apache/tika/server/core/TlsConfig.java | 133 +++++++++++++++++++++ .../tika/server/core/TikaServerConfigTest.java | 16 +++ .../resources/configs/tika-config-server-tls.xml | 40 +++++++ 5 files changed, 231 insertions(+), 4 deletions(-) diff --git a/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/TikaServerConfig.java b/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/TikaServerConfig.java index 990ffdf3f..f0afbc6aa 100644 --- a/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/TikaServerConfig.java +++ b/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/TikaServerConfig.java @@ -130,6 +130,7 @@ public class TikaServerConfig extends ConfigBase { private String forkedStatusFile; private int numRestarts = 0; + private TlsConfig tlsConfig = new TlsConfig(); /** * Config with only the defaults */ @@ -525,6 +526,12 @@ public class TikaServerConfig extends ConfigBase { this.returnStackTrace = returnStackTrace; } + public void setTlsConfig(TlsConfig tlsConfig) { + this.tlsConfig = tlsConfig; + } + public TlsConfig getTlsConfig() { + return tlsConfig; + } public List<String> getEndpoints() { return endpoints; } diff --git a/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/TikaServerProcess.java b/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/TikaServerProcess.java index 08b1bf9e4..0d3761991 100644 --- a/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/TikaServerProcess.java +++ b/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/TikaServerProcess.java @@ -22,6 +22,7 @@ import java.io.IOException; import java.io.InputStream; import java.net.BindException; import java.nio.file.Paths; +import java.security.GeneralSecurityException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -35,15 +36,21 @@ import org.apache.commons.cli.CommandLineParser; import org.apache.commons.cli.DefaultParser; import org.apache.commons.cli.Options; import org.apache.cxf.binding.BindingFactoryManager; +import org.apache.cxf.configuration.jsse.TLSParameterJaxBUtils; +import org.apache.cxf.configuration.jsse.TLSServerParameters; +import org.apache.cxf.configuration.security.KeyManagersType; +import org.apache.cxf.configuration.security.KeyStoreType; import org.apache.cxf.endpoint.Server; import org.apache.cxf.jaxrs.JAXRSBindingFactory; import org.apache.cxf.jaxrs.JAXRSServerFactoryBean; import org.apache.cxf.jaxrs.lifecycle.ResourceProvider; import org.apache.cxf.jaxrs.lifecycle.SingletonResourceProvider; +import org.apache.cxf.jaxrs.utils.JAXRSServerFactoryCustomizationUtils; import org.apache.cxf.rs.security.cors.CrossOriginResourceSharingFilter; import org.apache.cxf.service.factory.ServiceConstructionException; import org.apache.cxf.transport.common.gzip.GZIPInInterceptor; import org.apache.cxf.transport.common.gzip.GZIPOutInterceptor; +import org.apache.cxf.transport.http_jetty.JettyHTTPServerEngineFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.xml.sax.SAXException; @@ -248,13 +255,22 @@ public class TikaServerProcess { sf.setOutInterceptors(Collections.singletonList(new GZIPOutInterceptor())); sf.setInInterceptors(Collections.singletonList(new GZIPInInterceptor())); - String url = "http://" + host + ":" + port + "/"; + String protocol = tikaServerConfig.getTlsConfig().isActive() ? "https" : "http"; + String url = protocol + "://" + host + ":" + port + "/"; sf.setAddress(url); sf.setResourceComparator(new ProduceTypeResourceComparator()); BindingFactoryManager manager = sf.getBus().getExtension(BindingFactoryManager.class); - JAXRSBindingFactory factory = new JAXRSBindingFactory(); - factory.setBus(sf.getBus()); - manager.registerBindingFactory(JAXRSBindingFactory.JAXRS_BINDING_ID, factory); + if (tikaServerConfig.getTlsConfig().isActive()) { + TLSServerParameters tlsParams = getTlsParams(tikaServerConfig.getTlsConfig()); + JettyHTTPServerEngineFactory factory = new JettyHTTPServerEngineFactory(); + factory.setBus(sf.getBus()); + factory.setTLSServerParametersForPort(host, port, tlsParams); + JAXRSServerFactoryCustomizationUtils.customize(sf); + } else { + JAXRSBindingFactory factory = new JAXRSBindingFactory(); + factory.setBus(sf.getBus()); + manager.registerBindingFactory(JAXRSBindingFactory.JAXRS_BINDING_ID, factory); + } ServerDetails details = new ServerDetails(); details.sf = sf; details.url = url; @@ -263,6 +279,21 @@ public class TikaServerProcess { return details; } + private static TLSServerParameters getTlsParams(TlsConfig tlsConfig) + throws GeneralSecurityException, IOException { + KeyStoreType keyStore = new KeyStoreType(); + keyStore.setType(tlsConfig.getKeyStoreType()); + keyStore.setPassword(tlsConfig.getKeyStorePassword()); + keyStore.setResource(tlsConfig.getKeyStoreFile()); + + KeyManagersType kmt = new KeyManagersType(); + kmt.setKeyStore(keyStore); + kmt.setKeyPassword(tlsConfig.getKeyStorePassword()); + TLSServerParameters parameters = new TLSServerParameters(); + parameters.setKeyManagers(TLSParameterJaxBUtils.getKeyManagers(kmt)); + return parameters; + } + private static void loadAllProviders(TikaServerConfig tikaServerConfig, ServerStatus serverStatus, List<ResourceProvider> resourceProviders, diff --git a/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/TlsConfig.java b/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/TlsConfig.java new file mode 100644 index 000000000..8a85679e0 --- /dev/null +++ b/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/TlsConfig.java @@ -0,0 +1,133 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tika.server.core; + +import java.util.Map; + +import org.apache.tika.config.Initializable; +import org.apache.tika.config.InitializableProblemHandler; +import org.apache.tika.config.Param; +import org.apache.tika.exception.TikaConfigException; +import org.apache.tika.utils.StringUtils; + +public class TlsConfig implements Initializable { + + private boolean active = false; + //TODO make this configurable + private final boolean passwordsAESEncrypted = false; + private String keyStoreType = null; + private String keyStorePassword = null; + private String keyStoreFile = null; + private String trustStoreType = null; + private String trustStorePassword = null; + private String trustStoreFile = null; + + public boolean isActive() { + return active; + } + + public void setActive(boolean active) { + this.active = active; + } + + public boolean isPasswordsAESEncrypted() { + return passwordsAESEncrypted; + } + + public String getKeyStoreType() { + return keyStoreType; + } + + public void setKeyStoreType(String keyStoreType) { + this.keyStoreType = keyStoreType; + } + + public String getKeyStorePassword() { + return keyStorePassword; + } + + public void setKeyStorePassword(String keyStorePassword) { + this.keyStorePassword = keyStorePassword; + } + + public String getKeyStoreFile() { + return keyStoreFile; + } + + public void setKeyStoreFile(String keyStoreFile) { + this.keyStoreFile = keyStoreFile; + } + + public String getTrustStoreType() { + return trustStoreType; + } + + public void setTrustStoreType(String trustStoreType) { + this.trustStoreType = trustStoreType; + } + + public String getTrustStorePassword() { + return trustStorePassword; + } + + public void setTrustStorePassword(String trustStorePassword) { + this.trustStorePassword = trustStorePassword; + } + + public String getTrustStoreFile() { + return trustStoreFile; + } + + public void setTrustStoreFile(String trustStoreFile) { + this.trustStoreFile = trustStoreFile; + } + + @Override + public void initialize(Map<String, Param> params) throws TikaConfigException { + + } + + @Override + public void checkInitialization(InitializableProblemHandler problemHandler) + throws TikaConfigException { + if (active) { + if (StringUtils.isBlank(keyStoreType)) { + throw new TikaConfigException("must initialize keyStoreType"); + } else if (StringUtils.isBlank(keyStoreFile)) { + throw new TikaConfigException("must initialize keyStoreFile"); + } else if (StringUtils.isBlank(keyStorePassword)) { + throw new TikaConfigException("must initialize keyStorePassword"); + } else if (StringUtils.isBlank(trustStoreType)) { + throw new TikaConfigException("must initialize trustStoreType"); + } else if (StringUtils.isBlank(trustStoreFile)) { + throw new TikaConfigException("must initialize trustStoreFile"); + } else if (StringUtils.isBlank(trustStorePassword)) { + throw new TikaConfigException("must initialize trustStorePassword"); + } + } + } + + @Override + public String toString() { + return "TlsConfig{" + "active=" + active + ", passwordsAESEncrypted=" + + passwordsAESEncrypted + ", keyStoreType='" + keyStoreType + '\'' + + ", keyStorePassword='" + keyStorePassword + '\'' + ", keyStoreFile='" + + keyStoreFile + '\'' + ", trustStoreType='" + trustStoreType + '\'' + + ", trustStorePassword='" + trustStorePassword + '\'' + ", trustStoreFile='" + + trustStoreFile + '\'' + '}'; + } +} diff --git a/tika-server/tika-server-core/src/test/java/org/apache/tika/server/core/TikaServerConfigTest.java b/tika-server/tika-server-core/src/test/java/org/apache/tika/server/core/TikaServerConfigTest.java index 0f9a25c34..57ae3281e 100644 --- a/tika-server/tika-server-core/src/test/java/org/apache/tika/server/core/TikaServerConfigTest.java +++ b/tika-server/tika-server-core/src/test/java/org/apache/tika/server/core/TikaServerConfigTest.java @@ -98,4 +98,20 @@ public class TikaServerConfigTest { assertEquals(9994, ports[0]); assertEquals(9999, ports[5]); } + + @Test + public void testTlsConfig() throws Exception { + Set<String> settings = new HashSet<>(); + CommandLineParser parser = new DefaultParser(); + CommandLine emptyCommandLine = parser.parse(new Options(), new String[]{}); + Path path = Paths.get(TikaConfigTest.class.getResource( + "/configs/tika-config-server-tls.xml").toURI()); + TikaServerConfig config = TikaServerConfig + .load(path, + emptyCommandLine, + settings); + TlsConfig tlsConfig = config.getTlsConfig(); + System.out.println(tlsConfig); + } + } diff --git a/tika-server/tika-server-core/src/test/resources/configs/tika-config-server-tls.xml b/tika-server/tika-server-core/src/test/resources/configs/tika-config-server-tls.xml new file mode 100644 index 000000000..fdd90eb76 --- /dev/null +++ b/tika-server/tika-server-core/src/test/resources/configs/tika-config-server-tls.xml @@ -0,0 +1,40 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<properties> + <server> + <params> + <port>9999</port> + <taskTimeoutMillis>54321</taskTimeoutMillis> + <minimumTimeoutMillis>10</minimumTimeoutMillis> + <enableUnsecureFeatures>true</enableUnsecureFeatures> + <maxFiles>20</maxFiles> + <forkedJvmArgs> + <arg>-Xmx2g</arg> + </forkedJvmArgs> + <endpoints> + <endpoint>rmeta</endpoint> + </endpoints> + </params> + <tlsConfig> + <params> + <active>true</active> + <keyStoreType>myType</keyStoreType> + </params> + </tlsConfig> + </server> +</properties>
