Merge pull request #9242 from reuben-sutton/remove_jsonp

Remove jsonp support and associated tests, closes #9108
This commit is contained in:
Simon Willnauer 2015-04-01 18:18:52 +02:00
commit efb82910a1
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.
# 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.
#
#discovery.zen.minimum_master_nodes: 1
@ -371,11 +371,3 @@
#monitor.jvm.gc.old.warn: 10s
#monitor.jvm.gc.old.info: 5s
#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
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]
=== 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
now be achieved by using the `query_then_fetch` search type (which is the
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 {
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 Channel channel;
private final org.jboss.netty.handler.codec.http.HttpRequest nettyRequest;
@ -149,20 +142,6 @@ public class NettyHttpChannel extends HttpChannel {
} else {
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);
// 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 static final String HTTP_JSON_ENABLE = "http.jsonp.enable";
private ImmutableSet<String> relevantHeaders = ImmutableSet.of();
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 channel
* @return true if the request does not have any parameters that conflict with system settings
*/
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
if (channel.detailedErrorsEnabled() == false && request.paramAsBoolean("error_trace", false)) {
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"));
}
}