KNOX-2133 - Ensure that Knox always validates TLS (#203)
Signed-off-by: Kevin Risden <krisden@apache.org>
diff --git a/build-tools/src/main/resources/build-tools/forbiddenapis/signatures.txt b/build-tools/src/main/resources/build-tools/forbiddenapis/signatures.txt
new file mode 100644
index 0000000..4c0a57e
--- /dev/null
+++ b/build-tools/src/main/resources/build-tools/forbiddenapis/signatures.txt
@@ -0,0 +1,90 @@
+# 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.
+#
+# Signatures of APIs to avoid.
+# Cribbed from Elasticsearch and Apache Calcite
+
+java.lang.Character#codePointBefore(char[],int) @ Implicit start offset is error-prone when the char[] is a buffer and the first chars are random chars
+java.lang.Character#codePointAt(char[],int) @ Implicit end offset is error-prone when the char[] is a buffer and the last chars are random chars
+
+#@defaultMessage Only use wait / notify when really needed. Try to use concurrency primitives, latches or callbacks instead.
+#java.lang.Object#wait()
+#java.lang.Object#wait(long)
+#java.lang.Object#wait(long,int)
+#java.lang.Object#notify()
+#java.lang.Object#notifyAll()
+
+#@defaultMessage Use StringBuilder; it is more efficient
+#java.lang.StringBuffer
+
+@defaultMessage Please do not try to stop the world
+java.lang.System#gc()
+
+#@defaultMessage Please do not try to kill the world
+#java.lang.System#exit(int)
+#java.lang.Runtime#exit(int)
+
+@defaultMessage Don't interrupt threads use FutureUtils#cancel(Future<T>) instead
+java.util.concurrent.Future#cancel(boolean)
+
+@defaultMessage Spawning processes is a potential security issue
+java.lang.ProcessBuilder
+java.lang.Runtime#exec(java.lang.String)
+java.lang.Runtime#exec(java.lang.String[])
+java.lang.Runtime#exec(java.lang.String, java.lang.String[])
+java.lang.Runtime#exec(java.lang.String, java.lang.String[], java.io.File)
+java.lang.Runtime#exec(java.lang.String[], java.lang.String[])
+java.lang.Runtime#exec(java.lang.String[], java.lang.String[], java.io.File)
+
+#@defaultMessage For an enum, use == rather than equals
+#java.lang.Enum#equals(java.lang.Object)
+
+# Preconditions.checkArgument,
+# Preconditions.checkPositionIndex, and
+# Preconditions.checkState are still OK
+#@defaultMessage Use Objects.requireNonNull
+#com.google.common.base.Preconditions#checkNotNull(java.lang.Object)
+#com.google.common.base.Preconditions#checkNotNull(java.lang.Object, java.lang.Object)
+
+@defaultMessage Use java.util.Objects.equals
+com.google.common.base.Objects#equal(java.lang.Object, java.lang.Object)
+
+#@defaultMessage Use java.util.Objects
+#com.google.common.base.Objects
+
+@defaultMessage Use java.lang.String.join
+com.google.common.base.Joiner
+
+# Remove Guava calls to construct empty collections;
+# Sets.identityHashSet(),
+# Sets.newHashSet(Iterable) are still OK
+
+#@defaultMessage Use "new ArrayList<>()"
+#com.google.common.collect.Lists#newArrayList()
+
+@defaultMessage Use "new HashMap<>()"
+com.google.common.collect.Maps#newHashMap()
+
+@defaultMessage Use "new IdentityHashMap<>()"
+com.google.common.collect.Maps#newIdentityHashMap()
+
+@defaultMessage Use "new TreeMap<>()"
+com.google.common.collect.Maps#newTreeMap()
+
+@defaultMessage Use "new HashSet<>()"
+com.google.common.collect.Sets#newHashSet()
+
+@defaultMessage Fix the truststore instead of working around
+org.apache.http.conn.ssl.TrustSelfSignedStrategy
diff --git a/gateway-server/src/main/java/org/apache/knox/gateway/util/KnoxCLI.java b/gateway-server/src/main/java/org/apache/knox/gateway/util/KnoxCLI.java
index c4de38d..7b69a15 100644
--- a/gateway-server/src/main/java/org/apache/knox/gateway/util/KnoxCLI.java
+++ b/gateway-server/src/main/java/org/apache/knox/gateway/util/KnoxCLI.java
@@ -26,10 +26,8 @@
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
-import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
-import org.apache.http.ssl.SSLContexts;
import org.apache.knox.gateway.GatewayCommandLine;
import org.apache.knox.gateway.config.GatewayConfig;
import org.apache.knox.gateway.config.impl.GatewayConfigImpl;
@@ -63,7 +61,6 @@
import org.jboss.shrinkwrap.api.exporter.ExplodedExporter;
import org.jboss.shrinkwrap.api.spec.EnterpriseArchive;
-import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;
import java.io.BufferedReader;
import java.io.Console;
@@ -1674,7 +1671,6 @@
@Override
public void execute() {
attempts++;
- SSLContext ctx = null;
CloseableHttpClient client;
String http = "http://";
String https = "https://";
@@ -1682,7 +1678,6 @@
String gatewayPort;
String host;
-
if(cluster == null) {
printKnoxShellUsage();
out.println("A --cluster argument is required.");
@@ -1693,7 +1688,7 @@
host = hostname;
} else {
try {
- host = InetAddress.getLocalHost().getHostAddress();
+ host = InetAddress.getLocalHost().getHostName();
} catch (UnknownHostException e) {
out.println(e.toString());
out.println("Defaulting address to localhost. Use --hostname option to specify a different hostname");
@@ -1724,19 +1719,8 @@
out.println("Username and/or password not supplied. Expect HTTP 401 Unauthorized responses.");
}
-// Attempt to build SSL context for HTTP client.
- try {
- ctx = SSLContexts.custom().loadTrustMaterial(null, new TrustSelfSignedStrategy()).build();
- } catch (Exception e) {
- out.println(e.toString());
- }
-
// Initialize the HTTP client
- if(ctx == null) {
- client = HttpClients.createDefault();
- } else {
- client = HttpClients.custom().setSSLContext(ctx).build();
- }
+ client = HttpClients.createDefault();
HttpGet request;
if(ssl) {
diff --git a/gateway-service-test/src/main/java/org/apache/knox/gateway/service/test/ServiceTestResource.java b/gateway-service-test/src/main/java/org/apache/knox/gateway/service/test/ServiceTestResource.java
index 7a0a614..a1812a0 100644
--- a/gateway-service-test/src/main/java/org/apache/knox/gateway/service/test/ServiceTestResource.java
+++ b/gateway-service-test/src/main/java/org/apache/knox/gateway/service/test/ServiceTestResource.java
@@ -20,10 +20,8 @@
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIBuilder;
-import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
-import org.apache.http.ssl.SSLContexts;
import org.apache.knox.gateway.config.GatewayConfig;
import org.apache.knox.gateway.services.ServiceType;
import org.apache.knox.gateway.services.GatewayServices;
@@ -31,7 +29,6 @@
import org.apache.knox.gateway.topology.Service;
import org.apache.knox.gateway.topology.Topology;
-import javax.net.ssl.SSLContext;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
@@ -70,7 +67,6 @@
List<String> messages = new ArrayList<>();
String authString;
GatewayConfig config = (GatewayConfig) request.getServletContext().getAttribute(GatewayConfig.GATEWAY_CONFIG_ATTRIBUTE);
- SSLContext ctx = null;
CloseableHttpClient client = null;
String id = getTopologyName();
@@ -87,20 +83,9 @@
authString = null;
}
-// Attempt to build SSL context for HTTP client.
- try {
- ctx = SSLContexts.custom().loadTrustMaterial(null, new TrustSelfSignedStrategy()).build();
- } catch (Exception e) {
- messages.add(e.getMessage());
- }
-
// Initialize the HTTP client
try {
- if (ctx == null) {
- client = HttpClients.createDefault();
- } else {
- client = HttpClients.custom().setSSLContext(ctx).build();
- }
+ client = HttpClients.createDefault();
if (topology != null) {
for (Service s : topology.getServices()) {
diff --git a/gateway-shell/src/main/java/org/apache/knox/gateway/shell/KnoxSession.java b/gateway-shell/src/main/java/org/apache/knox/gateway/shell/KnoxSession.java
index 470aa44..5fa26c0 100644
--- a/gateway-shell/src/main/java/org/apache/knox/gateway/shell/KnoxSession.java
+++ b/gateway-shell/src/main/java/org/apache/knox/gateway/shell/KnoxSession.java
@@ -244,6 +244,7 @@
.connection().secure(false).end());
}
+ @SuppressForbidden
protected CloseableHttpClient createClient(ClientContext clientContext) throws GeneralSecurityException {
// SSL
diff --git a/gateway-spi/pom.xml b/gateway-spi/pom.xml
index 461b8d8..a5e2000 100644
--- a/gateway-spi/pom.xml
+++ b/gateway-spi/pom.xml
@@ -150,6 +150,16 @@
</dependency>
<dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-util</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>de.thetaphi</groupId>
+ <artifactId>forbiddenapis</artifactId>
+ </dependency>
+
+ <dependency>
<groupId>org.apache.knox</groupId>
<artifactId>gateway-test-utils</artifactId>
<scope>test</scope>
@@ -160,9 +170,5 @@
<artifactId>velocity</artifactId>
<scope>test</scope>
</dependency>
- <dependency>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-util</artifactId>
- </dependency>
</dependencies>
</project>
diff --git a/gateway-spi/src/main/java/org/apache/knox/gateway/dispatch/DefaultHttpClientFactory.java b/gateway-spi/src/main/java/org/apache/knox/gateway/dispatch/DefaultHttpClientFactory.java
index 2db6c12..8e5b34d 100644
--- a/gateway-spi/src/main/java/org/apache/knox/gateway/dispatch/DefaultHttpClientFactory.java
+++ b/gateway-spi/src/main/java/org/apache/knox/gateway/dispatch/DefaultHttpClientFactory.java
@@ -51,7 +51,6 @@
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
-import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.cookie.Cookie;
import org.apache.http.impl.DefaultConnectionReuseStrategy;
import org.apache.http.impl.client.BasicCredentialsProvider;
@@ -164,7 +163,7 @@
identityKeystore = null;
identityKeyPassphrase = null;
- // The the behavior before KNOX-1812 was to use the HttpClients default SslContext. However,
+ // The behavior before KNOX-1812 was to use the HttpClients default SslContext. However,
// if a truststore was explicitly configured in gateway-site (gateway.truststore.password.alias,
// gateway.truststore.path, gateway.truststore.type) create a custom SslContext and use it.
trustKeystore = ks.getTruststoreForHttpClient();
@@ -180,7 +179,7 @@
}
if (trustKeystore != null) {
- sslContextBuilder.loadTrustMaterial(trustKeystore, new TrustSelfSignedStrategy());
+ sslContextBuilder.loadTrustMaterial(trustKeystore, null);
}
return sslContextBuilder.build();
diff --git a/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/impl/CMFMasterService.java b/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/impl/CMFMasterService.java
index 47f2f18..0aba570 100644
--- a/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/impl/CMFMasterService.java
+++ b/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/impl/CMFMasterService.java
@@ -17,6 +17,7 @@
*/
package org.apache.knox.gateway.services.security.impl;
+import de.thetaphi.forbiddenapis.SuppressForbidden;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.FileUtils;
import org.apache.commons.net.ntp.TimeStamp;
@@ -176,6 +177,7 @@
}
}
+ @SuppressForbidden
private void chmod(String args, File file) throws IOException {
// TODO: move to Java 7 NIO support to add windows as well
// TODO: look into the following for Windows: Runtime.getRuntime().exec("attrib -r myFile");
diff --git a/pom.xml b/pom.xml
index 26ea966..52912a8 100644
--- a/pom.xml
+++ b/pom.xml
@@ -576,6 +576,15 @@
<!-- disallow unsafe commons-io classes -->
<bundledSignature>commons-io-unsafe-${commons-io.version}</bundledSignature>
</bundledSignatures>
+ <signaturesArtifacts>
+ <signaturesArtifact>
+ <groupId>org.apache.knox</groupId>
+ <artifactId>build-tools</artifactId>
+ <version>1.0.0</version>
+ <type>jar</type>
+ <path>build-tools/forbiddenapis/signatures.txt</path>
+ </signaturesArtifact>
+ </signaturesArtifacts>
</configuration>
<executions>
<execution>