github-advanced-security[bot] commented on code in PR #1069:
URL: https://github.com/apache/tomcat/pull/1069#discussion_r4120339951


##########
modules/manager2/src/test/java/org/apache/tomcat/manager2/Manager2ConfigTestBase.java:
##########
@@ -0,0 +1,639 @@
+/*
+ * 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.tomcat.manager2;
+
+import java.io.File;
+import java.io.PrintWriter;
+import java.net.ServerSocket;
+import java.net.URI;
+import java.nio.charset.StandardCharsets;
+import java.security.SecureRandom;
+import java.security.cert.X509Certificate;
+import java.util.List;
+import java.util.Map;
+
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+
+import org.junit.After;
+import org.junit.Assert;
+
+import static org.apache.catalina.startup.SimpleHttpClient.CRLF;
+import org.apache.catalina.Context;
+import org.apache.catalina.core.StandardEngine;
+import org.apache.catalina.realm.MemoryRealm;
+import org.apache.catalina.servlets.DefaultServlet;
+import org.apache.catalina.startup.ExpandWar;
+import org.apache.catalina.startup.SimpleHttpClient;
+import org.apache.catalina.startup.Tomcat;
+import org.apache.catalina.startup.TomcatBaseTest;
+import org.apache.tomcat.util.json.JSONParser;
+
+
+/**
+ * Shared base for the integration tests of the manager2 configuration API 
({@code /api/config/*}). The tests deploy
+ * the {@code manager2.war} built by this module (via the {@code deploy} 
target) into a throw-away Tomcat instance and
+ * drive it over HTTP with {@link SimpleHttpClient}, exercising the component 
tree, attribute updates, structural
+ * add/remove of child components, lifecycle operations (start / stop / 
restart), and persistence to
+ * {@code server.xml} through storeconfig.
+ *
+ * <p>
+ * The test methods are split over the concrete subclasses so that they can 
run in parallel: the Ant JUnit task
+ * parallelizes at the granularity of a test class (the methods of one class 
always run sequentially in a single
+ * thread), so one large class would serialize the whole configuration suite. 
The name of this base class deliberately
+ * does not start with {@code Test}: the batch test of the module build only 
picks up {@code Test*.java} (the
+ * {@code skipNonTests} option is a second line of defense).
+ *
+ * <p>
+ * All mutable state lives under {@link #getTemporaryDirectory()} (unique per 
test class): the webapp is deployed from
+ * a private copy so that the store tests can rewrite the manager's own 
context file without restarting the contexts
+ * of the other test classes, and the {@code manager2.store.base} system 
property is set per method and cleared in the
+ * {@code @After} tear down.
+ */
+public abstract class Manager2ConfigTestBase extends TomcatBaseTest {
+
+    protected static final String MANAGER2 = "/manager2";
+
+    private String storeBaseProp = null;
+
+    protected File manager2DocBase = null;
+
+
+    @After
+    public void clearStoreBase() {
+        if (storeBaseProp != null) {
+            System.clearProperty("manager2.store.base");
+            storeBaseProp = null;
+        }
+    }
+
+
+    /**
+     * Fetch the node detail of the component with the given id.
+     *
+     * @param client    The client to use
+     * @param id        The component id
+     *
+     * @return The parsed node detail
+     */
+    protected Map<String, Object> fetchNode(SimpleHttpClient client, String 
id) throws Exception {
+        request(client, "GET", MANAGER2 + "/api/config/node/" + id, null, 
null, 200);
+        return parseObject(client.getResponseBody());
+    }
+
+
+    /**
+     * Count the direct children of a node with the given type.
+     *
+     * @param node      The node
+     * @param type      The child type to count
+     *
+     * @return The number of direct children of the given type
+     */
+    protected static long countChildrenOfType(Map<String, Object> node, String 
type) {
+        List<Object> children = getList(node, "children");
+        if (children == null) {
+            return 0;
+        }
+        long count = 0;
+        for (Object child : children) {
+            @SuppressWarnings("unchecked")
+            Map<String, Object> cm = (Map<String, Object>) child;
+            if (type.equals(cm.get("type"))) {
+                count++;
+            }
+        }
+        return count;
+    }
+
+
+    // -----------------------------------------------------------------------
+
+
+    protected void setStoreBase(File storeBase) {
+        System.setProperty("manager2.store.base", storeBase.getAbsolutePath());
+        storeBaseProp = storeBase.getAbsolutePath();
+    }
+
+
+    /**
+     * Best effort cleanup for the add/remove test if a removal failed midway: 
remove any components that are still
+     * present so the shared instance and subsequent tests are not affected.
+     *
+     * @param client        The client to use
+     * @param token         The CSRF token
+     * @param serviceId     Id of the service to remove, if any
+     * @param hostId        Id of the host to remove, if any
+     * @param contextId     Id of the context to remove, if any
+     * @param wrapperId     Id of the wrapper to remove, if any
+     * @param valveId       Id of the valve to remove, if any
+     * @param connectorId   Id of the connector to remove, if any
+     * @param executorId    Id of the executor to remove, if any
+     * @param aliasId       Id of the alias to remove, if any
+     *
+     * @throws Exception If the cleanup requests cannot be exchanged
+     */
+    protected void cleanup(SimpleHttpClient client, String token, String 
serviceId, String hostId, String contextId,
+            String wrapperId, String valveId, String connectorId, String 
executorId, String aliasId) throws Exception {
+        for (String id : new String[] { connectorId, executorId, wrapperId, 
valveId, aliasId, contextId, hostId,
+                serviceId }) {
+            if (id == null) {
+                continue;
+            }
+            try {
+                request(client, "DELETE", MANAGER2 + "/api/config/child", 
token,
+                        "{\"id\":\"" + id + "\",\"confirm\":\"confirm\"}", 
200);
+            } catch (AssertionError e) {
+                // Already removed (or never created): ignore.
+            }
+        }
+    }
+
+
+    protected static int freePort() throws Exception {
+        try (ServerSocket socket = new ServerSocket(0)) {
+            return socket.getLocalPort();
+        }
+    }
+
+
+    /**
+     * Issue an HTTPS GET against the given port with a trust-all trust 
manager (the test certificate is self signed).
+     * Returns the HTTP status code; any status proves that the TLS handshake 
succeeded and the connector served the
+     * request.
+     *
+     * @param port      The port to connect to
+     * @param path      The request path
+     *
+     * @return The HTTP status code
+     *
+     * @throws Exception If the request fails
+     */
+    protected static int httpsGet(int port, String path) throws Exception {
+        TrustManager[] trustAll = new TrustManager[] { new X509TrustManager() {
+            @Override
+            public void checkClientTrusted(X509Certificate[] chain, String 
authType) {
+            }
+
+            @Override
+            public void checkServerTrusted(X509Certificate[] chain, String 
authType) {
+            }
+
+            @Override
+            public X509Certificate[] getAcceptedIssuers() {
+                return new X509Certificate[0];
+            }
+        } };
+        SSLContext sslContext = SSLContext.getInstance("TLS");
+        sslContext.init(null, trustAll, new SecureRandom());
+        HttpsURLConnection connection = (HttpsURLConnection) 
URI.create("https://localhost:"; + port + path).toURL()
+                .openConnection();
+        connection.setSSLSocketFactory(sslContext.getSocketFactory());
+        connection.setHostnameVerifier((hostname, session) -> true);

Review Comment:
   ## CodeQL / Unsafe hostname verification
   
   The [hostname verifier](1) defined by [this type](2) always accepts any 
certificate, even if the hostname does not match.
   
   [Show more 
details](https://github.com/apache/tomcat/security/code-scanning/978)



##########
modules/manager2/src/test/java/org/apache/tomcat/manager2/Manager2ConfigTestBase.java:
##########
@@ -0,0 +1,639 @@
+/*
+ * 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.tomcat.manager2;
+
+import java.io.File;
+import java.io.PrintWriter;
+import java.net.ServerSocket;
+import java.net.URI;
+import java.nio.charset.StandardCharsets;
+import java.security.SecureRandom;
+import java.security.cert.X509Certificate;
+import java.util.List;
+import java.util.Map;
+
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+
+import org.junit.After;
+import org.junit.Assert;
+
+import static org.apache.catalina.startup.SimpleHttpClient.CRLF;
+import org.apache.catalina.Context;
+import org.apache.catalina.core.StandardEngine;
+import org.apache.catalina.realm.MemoryRealm;
+import org.apache.catalina.servlets.DefaultServlet;
+import org.apache.catalina.startup.ExpandWar;
+import org.apache.catalina.startup.SimpleHttpClient;
+import org.apache.catalina.startup.Tomcat;
+import org.apache.catalina.startup.TomcatBaseTest;
+import org.apache.tomcat.util.json.JSONParser;
+
+
+/**
+ * Shared base for the integration tests of the manager2 configuration API 
({@code /api/config/*}). The tests deploy
+ * the {@code manager2.war} built by this module (via the {@code deploy} 
target) into a throw-away Tomcat instance and
+ * drive it over HTTP with {@link SimpleHttpClient}, exercising the component 
tree, attribute updates, structural
+ * add/remove of child components, lifecycle operations (start / stop / 
restart), and persistence to
+ * {@code server.xml} through storeconfig.
+ *
+ * <p>
+ * The test methods are split over the concrete subclasses so that they can 
run in parallel: the Ant JUnit task
+ * parallelizes at the granularity of a test class (the methods of one class 
always run sequentially in a single
+ * thread), so one large class would serialize the whole configuration suite. 
The name of this base class deliberately
+ * does not start with {@code Test}: the batch test of the module build only 
picks up {@code Test*.java} (the
+ * {@code skipNonTests} option is a second line of defense).
+ *
+ * <p>
+ * All mutable state lives under {@link #getTemporaryDirectory()} (unique per 
test class): the webapp is deployed from
+ * a private copy so that the store tests can rewrite the manager's own 
context file without restarting the contexts
+ * of the other test classes, and the {@code manager2.store.base} system 
property is set per method and cleared in the
+ * {@code @After} tear down.
+ */
+public abstract class Manager2ConfigTestBase extends TomcatBaseTest {
+
+    protected static final String MANAGER2 = "/manager2";
+
+    private String storeBaseProp = null;
+
+    protected File manager2DocBase = null;
+
+
+    @After
+    public void clearStoreBase() {
+        if (storeBaseProp != null) {
+            System.clearProperty("manager2.store.base");
+            storeBaseProp = null;
+        }
+    }
+
+
+    /**
+     * Fetch the node detail of the component with the given id.
+     *
+     * @param client    The client to use
+     * @param id        The component id
+     *
+     * @return The parsed node detail
+     */
+    protected Map<String, Object> fetchNode(SimpleHttpClient client, String 
id) throws Exception {
+        request(client, "GET", MANAGER2 + "/api/config/node/" + id, null, 
null, 200);
+        return parseObject(client.getResponseBody());
+    }
+
+
+    /**
+     * Count the direct children of a node with the given type.
+     *
+     * @param node      The node
+     * @param type      The child type to count
+     *
+     * @return The number of direct children of the given type
+     */
+    protected static long countChildrenOfType(Map<String, Object> node, String 
type) {
+        List<Object> children = getList(node, "children");
+        if (children == null) {
+            return 0;
+        }
+        long count = 0;
+        for (Object child : children) {
+            @SuppressWarnings("unchecked")
+            Map<String, Object> cm = (Map<String, Object>) child;
+            if (type.equals(cm.get("type"))) {
+                count++;
+            }
+        }
+        return count;
+    }
+
+
+    // -----------------------------------------------------------------------
+
+
+    protected void setStoreBase(File storeBase) {
+        System.setProperty("manager2.store.base", storeBase.getAbsolutePath());
+        storeBaseProp = storeBase.getAbsolutePath();
+    }
+
+
+    /**
+     * Best effort cleanup for the add/remove test if a removal failed midway: 
remove any components that are still
+     * present so the shared instance and subsequent tests are not affected.
+     *
+     * @param client        The client to use
+     * @param token         The CSRF token
+     * @param serviceId     Id of the service to remove, if any
+     * @param hostId        Id of the host to remove, if any
+     * @param contextId     Id of the context to remove, if any
+     * @param wrapperId     Id of the wrapper to remove, if any
+     * @param valveId       Id of the valve to remove, if any
+     * @param connectorId   Id of the connector to remove, if any
+     * @param executorId    Id of the executor to remove, if any
+     * @param aliasId       Id of the alias to remove, if any
+     *
+     * @throws Exception If the cleanup requests cannot be exchanged
+     */
+    protected void cleanup(SimpleHttpClient client, String token, String 
serviceId, String hostId, String contextId,
+            String wrapperId, String valveId, String connectorId, String 
executorId, String aliasId) throws Exception {
+        for (String id : new String[] { connectorId, executorId, wrapperId, 
valveId, aliasId, contextId, hostId,
+                serviceId }) {
+            if (id == null) {
+                continue;
+            }
+            try {
+                request(client, "DELETE", MANAGER2 + "/api/config/child", 
token,
+                        "{\"id\":\"" + id + "\",\"confirm\":\"confirm\"}", 
200);
+            } catch (AssertionError e) {
+                // Already removed (or never created): ignore.
+            }
+        }
+    }
+
+
+    protected static int freePort() throws Exception {
+        try (ServerSocket socket = new ServerSocket(0)) {
+            return socket.getLocalPort();
+        }
+    }
+
+
+    /**
+     * Issue an HTTPS GET against the given port with a trust-all trust 
manager (the test certificate is self signed).
+     * Returns the HTTP status code; any status proves that the TLS handshake 
succeeded and the connector served the
+     * request.
+     *
+     * @param port      The port to connect to
+     * @param path      The request path
+     *
+     * @return The HTTP status code
+     *
+     * @throws Exception If the request fails
+     */
+    protected static int httpsGet(int port, String path) throws Exception {
+        TrustManager[] trustAll = new TrustManager[] { new X509TrustManager() {
+            @Override
+            public void checkClientTrusted(X509Certificate[] chain, String 
authType) {
+            }
+
+            @Override
+            public void checkServerTrusted(X509Certificate[] chain, String 
authType) {
+            }
+
+            @Override
+            public X509Certificate[] getAcceptedIssuers() {
+                return new X509Certificate[0];
+            }
+        } };
+        SSLContext sslContext = SSLContext.getInstance("TLS");
+        sslContext.init(null, trustAll, new SecureRandom());

Review Comment:
   ## CodeQL / `TrustManager` that accepts all certificates
   
   This uses [TrustManager](1), which is defined in 
[Manager2ConfigTestBase$](2) and trusts any certificate.
   
   [Show more 
details](https://github.com/apache/tomcat/security/code-scanning/979)



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to