Remove jsonp support and associated tests, closes #9108

This commit is contained in:
Reuben Sutton 2015-01-11 10:01:51 +00:00
parent 285941f0d3
commit 85c221e9b1
7 changed files with 13 additions and 195 deletions

View File

@ -294,7 +294,7 @@
# and master node is elected. Multicast discovery is the default. # and master node is elected. Multicast discovery is the default.
# Set to ensure a node sees N other master eligible nodes to be considered # Set to ensure a node sees N other master eligible nodes to be considered
# operational within the cluster. This should be set to a quorum/majority of # operational within the cluster. This should be set to a quorum/majority of
# the master-eligible nodes in the cluster. # the master-eligible nodes in the cluster.
# #
#discovery.zen.minimum_master_nodes: 1 #discovery.zen.minimum_master_nodes: 1
@ -371,11 +371,3 @@
#monitor.jvm.gc.old.warn: 10s #monitor.jvm.gc.old.warn: 10s
#monitor.jvm.gc.old.info: 5s #monitor.jvm.gc.old.info: 5s
#monitor.jvm.gc.old.debug: 2s #monitor.jvm.gc.old.debug: 2s
################################## Security ################################
# Uncomment if you want to enable JSONP as a valid return transport on the
# http server. With this enabled, it may pose a security risk, so disabling
# it unless you need it is recommended (it is disabled by default).
#
#http.jsonp.enable: true

View File

@ -243,23 +243,6 @@ field names in the result will be returned in camel casing, otherwise,
underscore casing will be used. Note, this does not apply to the source underscore casing will be used. Note, this does not apply to the source
document indexed. document indexed.
[float]
=== JSONP
By default JSONP responses are disabled.
When enabled, all REST APIs accept a `callback` parameter
resulting in a http://en.wikipedia.org/wiki/JSONP[JSONP] result. You can enable
this behavior by adding the following to `config.yaml`:
http.jsonp.enable: true
Please note, when enabled, due to the architecture of Elasticsearch, this may pose
a security risk. Under some circumstances, an attacker may be able to exfiltrate
data in your Elasticsearch server if they're able to force your browser to make a
JSONP request on your behalf (e.g. by including a <script> tag on an untrusted site
with a legitimate query against a local Elasticsearch server).
[float] [float]
=== Request body in query string === Request body in query string

View File

@ -322,3 +322,14 @@ either the HTTP transport (enabled by default) or the node or transport Java cli
The `count` search type has been deprecated. All benefits from this search type can The `count` search type has been deprecated. All benefits from this search type can
now be achieved by using the `query_then_fetch` search type (which is the now be achieved by using the `query_then_fetch` search type (which is the
default) and setting `size` to `0`. default) and setting `size` to `0`.
=== JSONP support
JSONP callback support has now been removed. CORS should be used to access Elasticsearch
over AJAX instead:
[source,yaml]
---------------
http.cors.enabled: true
http.cors.allow-origin: /https?:\/\/localhost(:[0-9]+)?/
---------------

View File

@ -51,13 +51,6 @@ import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.*;
*/ */
public class NettyHttpChannel extends HttpChannel { public class NettyHttpChannel extends HttpChannel {
private static final ChannelBuffer END_JSONP;
static {
BytesRef U_END_JSONP = new BytesRef(");");
END_JSONP = ChannelBuffers.wrappedBuffer(U_END_JSONP.bytes, U_END_JSONP.offset, U_END_JSONP.length);
}
private final NettyHttpServerTransport transport; private final NettyHttpServerTransport transport;
private final Channel channel; private final Channel channel;
private final org.jboss.netty.handler.codec.http.HttpRequest nettyRequest; private final org.jboss.netty.handler.codec.http.HttpRequest nettyRequest;
@ -149,20 +142,6 @@ public class NettyHttpChannel extends HttpChannel {
} else { } else {
buffer = content.copyBytesArray().toChannelBuffer(); buffer = content.copyBytesArray().toChannelBuffer();
} }
// handle JSONP
String callback = request.param("callback");
if (callback != null) {
final BytesRef callbackBytes = new BytesRef(callback);
callbackBytes.bytes[callbackBytes.length] = '(';
callbackBytes.length++;
buffer = ChannelBuffers.wrappedBuffer(NettyUtils.DEFAULT_GATHERING,
ChannelBuffers.wrappedBuffer(callbackBytes.bytes, callbackBytes.offset, callbackBytes.length),
buffer,
ChannelBuffers.wrappedBuffer(END_JSONP)
);
// Add content-type header of "application/javascript"
resp.headers().add(HttpHeaders.Names.CONTENT_TYPE, "application/javascript");
}
resp.setContent(buffer); resp.setContent(buffer);
// If our response doesn't specify a content-type header, set one // If our response doesn't specify a content-type header, set one

View File

@ -43,7 +43,6 @@ import static org.elasticsearch.rest.RestStatus.*;
*/ */
public class RestController extends AbstractLifecycleComponent<RestController> { public class RestController extends AbstractLifecycleComponent<RestController> {
public static final String HTTP_JSON_ENABLE = "http.jsonp.enable";
private ImmutableSet<String> relevantHeaders = ImmutableSet.of(); private ImmutableSet<String> relevantHeaders = ImmutableSet.of();
private final PathTrie<RestHandler> getHandlers = new PathTrie<>(RestUtils.REST_DECODER); private final PathTrie<RestHandler> getHandlers = new PathTrie<>(RestUtils.REST_DECODER);
@ -182,26 +181,12 @@ public class RestController extends AbstractLifecycleComponent<RestController> {
} }
/** /**
* Checks the request parameters against enabled settings for JSONP and error trace support * Checks the request parameters against enabled settings for error trace support
* @param request * @param request
* @param channel * @param channel
* @return true if the request does not have any parameters that conflict with system settings * @return true if the request does not have any parameters that conflict with system settings
*/ */
boolean checkRequestParameters(final RestRequest request, final RestChannel channel) { boolean checkRequestParameters(final RestRequest request, final RestChannel channel) {
// If JSONP is disabled and someone sends a callback parameter we should bail out before querying
if (!settings.getAsBoolean(HTTP_JSON_ENABLE, false) && request.hasParam("callback")) {
try {
XContentBuilder builder = channel.newBuilder();
builder.startObject().field("error","JSONP is disabled.").endObject().string();
RestResponse response = new BytesRestResponse(FORBIDDEN, builder);
response.addHeader("Content-Type", "application/javascript");
channel.sendResponse(response);
} catch (IOException e) {
logger.warn("Failed to send response", e);
}
return false;
}
// error_trace cannot be used when we disable detailed errors // error_trace cannot be used when we disable detailed errors
if (channel.detailedErrorsEnabled() == false && request.paramAsBoolean("error_trace", false)) { if (channel.detailedErrorsEnabled() == false && request.paramAsBoolean("error_trace", false)) {
try { try {

View File

@ -1,71 +0,0 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch 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.elasticsearch.options.jsonp;
import org.apache.http.impl.client.HttpClients;
import org.elasticsearch.common.settings.ImmutableSettings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.http.HttpServerTransport;
import org.elasticsearch.node.Node;
import org.elasticsearch.rest.RestController;
import org.elasticsearch.test.ElasticsearchIntegrationTest;
import org.elasticsearch.test.ElasticsearchIntegrationTest.ClusterScope;
import org.elasticsearch.test.ElasticsearchIntegrationTest.Scope;
import org.elasticsearch.test.rest.client.http.HttpRequestBuilder;
import org.elasticsearch.test.rest.client.http.HttpResponse;
import org.junit.Test;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.is;
// Test to make sure that our JSONp response is disabled
@ClusterScope(scope = Scope.TEST, numDataNodes = 1)
public class JsonpOptionDisabledTest extends ElasticsearchIntegrationTest {
// Build our cluster settings
@Override
protected Settings nodeSettings(int nodeOrdinal) {
// false is the default!
if (randomBoolean()) {
logger.info("using default jsonp settings (should be false)");
return ImmutableSettings.settingsBuilder()
.put(super.nodeSettings(nodeOrdinal))
.put(Node.HTTP_ENABLED, true).build();
}
return ImmutableSettings.settingsBuilder()
.put(super.nodeSettings(nodeOrdinal))
.put(Node.HTTP_ENABLED, true)
.put(RestController.HTTP_JSON_ENABLE, false)
.build();
}
// Make sure our response has both the callback as well as our "JSONP is disabled" message.
@Test
public void testThatJSONPisDisabled() throws Exception {
// Make the HTTP request
HttpResponse response = new HttpRequestBuilder(HttpClients.createDefault()).httpTransport(internalCluster().getDataNodeInstance(HttpServerTransport.class))
.path("/")
.addParam("callback", "DisabledJSONPCallback").execute();
assertThat(response.getHeaders().get("Content-Type"), is("application/javascript"));
assertThat(response.getBody(), containsString("DisabledJSONPCallback("));
assertThat(response.getBody(), containsString("JSONP is disabled"));
}
}

View File

@ -1,61 +0,0 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch 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.elasticsearch.options.jsonp;
import org.apache.http.impl.client.HttpClients;
import org.elasticsearch.common.settings.ImmutableSettings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.http.HttpServerTransport;
import org.elasticsearch.node.Node;
import org.elasticsearch.rest.RestController;
import org.elasticsearch.test.ElasticsearchIntegrationTest;
import org.elasticsearch.test.ElasticsearchIntegrationTest.ClusterScope;
import org.elasticsearch.test.ElasticsearchIntegrationTest.Scope;
import org.elasticsearch.test.rest.client.http.HttpRequestBuilder;
import org.elasticsearch.test.rest.client.http.HttpResponse;
import org.junit.Test;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.is;
// Test to make sure that our JSONp response is enabled by default
@ClusterScope(scope = Scope.TEST, numDataNodes = 1)
public class JsonpOptionEnabledTest extends ElasticsearchIntegrationTest {
// Build our cluster settings
@Override
protected Settings nodeSettings(int nodeOrdinal) {
return ImmutableSettings.settingsBuilder()
.put(super.nodeSettings(nodeOrdinal))
.put(RestController.HTTP_JSON_ENABLE, true)
.put(Node.HTTP_ENABLED, true)
.build();
}
// Make sure our response has both the callback and opening paren, as well as the famous Elasticsearch tagline :)
@Test
public void testThatJSONPisEnabled() throws Exception {
// Make the HTTP request
HttpResponse response = new HttpRequestBuilder(HttpClients.createDefault()).httpTransport(internalCluster().getDataNodeInstance(HttpServerTransport.class)).path("/").addParam("callback", "EnabledJSONPCallback").execute();
assertThat(response.getHeaders().get("Content-Type"), is("application/javascript"));
assertThat(response.getBody(), containsString("EnabledJSONPCallback("));
assertThat(response.getBody(), containsString("You Know, for Search"));
}
}