Disabling the HTTP trace method on the websocket port by default.  It
can be enabled by setting the parameter "http.enableTrace=true" on the
connection uri if it is needed for debugging.
This commit is contained in:
Christopher L. Shannon (cshannon) 2016-02-26 18:53:34 +00:00
parent 6e2edf08c3
commit 4fb8083977
2 changed files with 142 additions and 1 deletions

View File

@ -29,10 +29,13 @@ import org.apache.activemq.transport.WebTransportServerSupport;
import org.apache.activemq.transport.ws.jetty9.WSServlet;
import org.apache.activemq.util.IntrospectionSupport;
import org.apache.activemq.util.ServiceStopper;
import org.eclipse.jetty.security.ConstraintMapping;
import org.eclipse.jetty.security.ConstraintSecurityHandler;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.util.security.Constraint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -61,9 +64,14 @@ public class WSTransportServer extends WebTransportServerSupport {
URI boundTo = bind();
ServletContextHandler contextHandler =
new ServletContextHandler(server, "/", ServletContextHandler.NO_SECURITY);
new ServletContextHandler(server, "/", ServletContextHandler.SECURITY);
ServletHolder holder = new ServletHolder();
//AMQ-6182 - disabling trace by default
configureTraceMethod((ConstraintSecurityHandler) contextHandler.getSecurityHandler(),
getHttpOptions().isEnableTrace());
Map<String, Object> webSocketOptions = IntrospectionSupport.extractProperties(transportOptions, "websocket.");
for(Map.Entry<String,Object> webSocketEntry : webSocketOptions.entrySet()) {
Object value = webSocketEntry.getValue();
@ -106,6 +114,31 @@ public class WSTransportServer extends WebTransportServerSupport {
return (Integer)connector.getClass().getMethod("getLocalPort").invoke(connector);
}
private void configureTraceMethod(ConstraintSecurityHandler securityHandler,
boolean enableTrace) {
Constraint constraint = new Constraint();
constraint.setName("trace-security");
//If enableTrace is true, then we want to set authenticate to false to allow it
constraint.setAuthenticate(!enableTrace);
ConstraintMapping mapping = new ConstraintMapping();
mapping.setConstraint(constraint);
mapping.setMethod("TRACE");
mapping.setPathSpec("/");
securityHandler.addConstraintMapping(mapping);
}
protected static class HttpOptions {
private boolean enableTrace = false;
public boolean isEnableTrace() {
return enableTrace;
}
public void setEnableTrace(boolean enableTrace) {
this.enableTrace = enableTrace;
}
}
@Override
protected void doStop(ServiceStopper stopper) throws Exception {
Server temp = server;
@ -128,6 +161,15 @@ public class WSTransportServer extends WebTransportServerSupport {
this.connector = connector;
}
protected HttpOptions getHttpOptions() {
HttpOptions httpOptions = new HttpOptions();
if (transportOptions != null) {
Map<String, Object> httpOptionsMap = IntrospectionSupport.extractProperties(transportOptions, "http.");
IntrospectionSupport.setProperties(httpOptions, httpOptionsMap);
}
return httpOptions;
}
@Override
public void setTransportOption(Map<String, Object> transportOptions) {
Map<String, Object> socketOptions = IntrospectionSupport.extractProperties(transportOptions, "transport.");

View File

@ -0,0 +1,99 @@
/**
* 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.activemq.transport.ws;
import static org.junit.Assert.assertEquals;
import java.util.Arrays;
import java.util.Collection;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.client.api.Request;
import org.eclipse.jetty.client.api.Result;
import org.eclipse.jetty.client.util.BufferingResponseListener;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpStatus;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
@RunWith(Parameterized.class)
public class WSTransportHttpTraceTest extends WSTransportTest {
private String enableTraceParam;
private int expectedStatus;
@Parameters
public static Collection<Object[]> data() {
return Arrays.asList(new Object[][] {
//value is empty
{"http.enableTrace=", HttpStatus.FORBIDDEN_403},
//default, trace method not specified
{null, HttpStatus.FORBIDDEN_403},
// enable http trace method
{"http.enableTrace=true", HttpStatus.OK_200},
// disable trace method
{"http.enableTrace=false", HttpStatus.FORBIDDEN_403}
});
}
public WSTransportHttpTraceTest(final String enableTraceParam, final int expectedStatus) {
this.enableTraceParam = enableTraceParam;
this.expectedStatus = expectedStatus;
}
@Override
protected String getWSConnectorURI() {
String uri = "ws://127.0.0.1:61623?websocket.maxTextMessageSize=99999&transport.maxIdleTime=1001";
uri = enableTraceParam != null ? uri + "&" + enableTraceParam : uri;
return uri;
}
/**
* This tests whether the TRACE method is enabled or not
* @throws Exception
*/
@Test
public void testHttpTraceEnabled() throws Exception {
HttpClient httpClient = new HttpClient();
httpClient.start();
final CountDownLatch latch = new CountDownLatch(1);
Request request = httpClient.newRequest("http://127.0.0.1:61623").method(HttpMethod.TRACE);
final AtomicInteger status = new AtomicInteger();
request.send(new BufferingResponseListener() {
@Override
public void onComplete(Result result) {
status.set(result.getResponse().getStatus());
latch.countDown();
}
});
latch.await();
assertEquals(expectedStatus, status.get());
}
@Override
@Ignore
@Test
public void testBrokerStart() throws Exception {
}
}