Skip to content

Commit

Permalink
Ensure all requests have no origin, and are requesting json content
Browse files Browse the repository at this point in the history
  • Loading branch information
shs96c committed Jul 7, 2020
1 parent 48a5451 commit 26cae68
Show file tree
Hide file tree
Showing 5 changed files with 181 additions and 2 deletions.
1 change: 1 addition & 0 deletions java/private/test.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ def java_selenium_test_suite(
name = "%s-base-lib" % name,
srcs = srcs,
deps = deps,
testonly = True,
**kwargs
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@
import org.openqa.selenium.remote.http.Route;
import org.openqa.selenium.remote.tracing.Tracer;

import java.net.URI;
import java.net.URL;
import java.util.Collections;
import java.util.Set;
Expand Down Expand Up @@ -116,7 +115,7 @@ protected void execute(Config config) {
GraphqlHandler graphqlHandler = new GraphqlHandler(distributor, serverOptions.getExternalUri());

Route handler = Route.combine(
new Router(tracer, clientFactory, sessions, distributor),
new Router(tracer, clientFactory, sessions, distributor).with(networkOptions.getSpecComplianceChecks()),
Route.post("/graphql").to(() -> graphqlHandler),
get("/readyz").to(() -> req -> new HttpResponse().setStatus(HTTP_NO_CONTENT)));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,19 @@

package org.openqa.selenium.grid.server;

import com.google.common.collect.ImmutableList;
import org.openqa.selenium.grid.config.Config;
import org.openqa.selenium.grid.web.CheckContentTypeHeader;
import org.openqa.selenium.grid.web.CheckOriginHeader;
import org.openqa.selenium.internal.Require;
import org.openqa.selenium.remote.http.Filter;
import org.openqa.selenium.remote.http.HttpClient;
import org.openqa.selenium.remote.tracing.TracedHttpClient;
import org.openqa.selenium.remote.tracing.Tracer;

import java.util.List;
import java.util.Optional;

public class NetworkOptions {

private final Config config;
Expand All @@ -34,4 +41,22 @@ public NetworkOptions(Config config) {
public HttpClient.Factory getHttpClientFactory(Tracer tracer) {
return new TracedHttpClient.Factory(tracer, HttpClient.Factory.createDefault());
}

public Filter getSpecComplianceChecks() {
// Base case: we do nothing
Filter toReturn = httpHandler -> httpHandler;

if (config.getBool("network", "check_content_type").orElse(true)) {
toReturn = toReturn.andThen(new CheckContentTypeHeader());
}

boolean checkOrigin = config.getBool("network", "check_origin_header").orElse(true);
Optional<List<String>> allowedOrigins = config.getAll("network", "allowed_origins");

if (checkOrigin || allowedOrigins.isPresent()) {
toReturn = toReturn.andThen(new CheckOriginHeader(allowedOrigins.orElse(ImmutableList.of())));
}

return toReturn;
}
}
6 changes: 6 additions & 0 deletions java/server/test/org/openqa/selenium/grid/router/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ load("//java:defs.bzl", "java_selenium_test_suite", "java_test_suite")

LARGE_TESTS = [
"DistributedCdpTest.java",
"NewSessionCreationTest.java",
]

java_selenium_test_suite(
Expand All @@ -11,16 +12,21 @@ java_selenium_test_suite(
srcs = LARGE_TESTS,
deps = [
"//java/client/src/org/openqa/selenium:core",
"//java/client/src/org/openqa/selenium/chrome",
"//java/client/src/org/openqa/selenium/devtools",
"//java/client/src/org/openqa/selenium/firefox",
"//java/client/src/org/openqa/selenium/json",
"//java/client/src/org/openqa/selenium/remote",
"//java/client/src/org/openqa/selenium/remote/http",
"//java/client/src/org/openqa/selenium/support",
"//java/client/test/org/openqa/selenium/remote/tracing:tracing-support",
"//java/client/test/org/openqa/selenium/testing:annotations",
"//java/client/test/org/openqa/selenium/testing/drivers",
"//java/server/src/org/openqa/selenium/grid",
"//java/server/src/org/openqa/selenium/grid/commands",
"//java/server/src/org/openqa/selenium/grid/distributor/httpd",
"//java/server/src/org/openqa/selenium/grid/sessionmap/httpd",
"//java/server/test/org/openqa/selenium/grid/testing:testing",
artifact("com.google.guava:guava"),
artifact("junit:junit"),
artifact("org.assertj:assertj-core"),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
// Licensed to the Software Freedom Conservancy (SFC) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The SFC 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.openqa.selenium.grid.router;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import org.junit.Before;
import org.junit.Test;
import org.openqa.selenium.WebDriverInfo;
import org.openqa.selenium.chrome.ChromeDriverInfo;
import org.openqa.selenium.events.EventBus;
import org.openqa.selenium.events.local.GuavaEventBus;
import org.openqa.selenium.firefox.GeckoDriverInfo;
import org.openqa.selenium.grid.config.MapConfig;
import org.openqa.selenium.grid.data.Session;
import org.openqa.selenium.grid.distributor.Distributor;
import org.openqa.selenium.grid.distributor.local.LocalDistributor;
import org.openqa.selenium.grid.node.Node;
import org.openqa.selenium.grid.node.config.DriverServiceSessionFactory;
import org.openqa.selenium.grid.node.local.LocalNode;
import org.openqa.selenium.grid.server.BaseServerOptions;
import org.openqa.selenium.grid.server.Server;
import org.openqa.selenium.grid.sessionmap.SessionMap;
import org.openqa.selenium.grid.sessionmap.local.LocalSessionMap;
import org.openqa.selenium.grid.testing.TestSessionFactory;
import org.openqa.selenium.grid.web.EnsureSpecCompliantHeaders;
import org.openqa.selenium.netty.server.NettyServer;
import org.openqa.selenium.remote.http.Contents;
import org.openqa.selenium.remote.http.HttpClient;
import org.openqa.selenium.remote.http.HttpRequest;
import org.openqa.selenium.remote.http.HttpResponse;
import org.openqa.selenium.remote.http.Routable;
import org.openqa.selenium.remote.service.DriverService;
import org.openqa.selenium.remote.tracing.DefaultTestTracer;
import org.openqa.selenium.remote.tracing.Tracer;
import org.openqa.selenium.testing.drivers.Browser;

import java.net.URI;
import java.net.URISyntaxException;

import static java.net.HttpURLConnection.HTTP_INTERNAL_ERROR;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assumptions.assumeThat;
import static org.openqa.selenium.json.Json.JSON_UTF_8;
import static org.openqa.selenium.remote.http.HttpMethod.POST;

public class NewSessionCreationTest {

private Tracer tracer;
private EventBus events;
private HttpClient.Factory clientFactory;

@Before
public void setup() {
tracer = DefaultTestTracer.createTracer();
events = new GuavaEventBus();
clientFactory = HttpClient.Factory.createDefault();
}

@Test
public void ensureJsCannotCreateANewSession() throws URISyntaxException {
ChromeDriverInfo chromeDriverInfo = new ChromeDriverInfo();
assumeThat(chromeDriverInfo.isAvailable()).isTrue();
GeckoDriverInfo geckoDriverInfo = new GeckoDriverInfo();
assumeThat(geckoDriverInfo.isAvailable()).isTrue();

SessionMap sessions = new LocalSessionMap(tracer, events);
Distributor distributor = new LocalDistributor(tracer, events, clientFactory, sessions, null);
Routable router = new Router(tracer, clientFactory, sessions, distributor).with(new EnsureSpecCompliantHeaders(ImmutableList.of()));

Server<?> server = new NettyServer(
new BaseServerOptions(new MapConfig(ImmutableMap.of())),
router,
new ProxyCdpIntoGrid(clientFactory, sessions))
.start();

URI uri = server.getUrl().toURI();
Node node = LocalNode.builder(
tracer,
events,
uri,
uri,
null)
.add(Browser.detect().getCapabilities(), new TestSessionFactory((id, caps) -> new Session(id, uri, caps)))
.build();
distributor.add(node);

HttpClient client = HttpClient.Factory.createDefault().createClient(server.getUrl());

// Attempt to create a session without setting the content type
HttpResponse res = client.execute(
new HttpRequest(POST, "/session")
.setContent(Contents.asJson(ImmutableMap.of(
"capabilities", ImmutableMap.of(
"alwaysMatch", Browser.detect().getCapabilities())))));

assertThat(res.getStatus()).isEqualTo(HTTP_INTERNAL_ERROR);

// Attempt to create a session with an origin header but content type set
res = client.execute(
new HttpRequest(POST, "/session")
.addHeader("Content-Type", JSON_UTF_8)
.addHeader("Origin", "localhost")
.setContent(Contents.asJson(ImmutableMap.of(
"capabilities", ImmutableMap.of(
"alwaysMatch", Browser.detect().getCapabilities())))));

assertThat(res.getStatus()).isEqualTo(HTTP_INTERNAL_ERROR);

// And now make sure the session is just fine
res = client.execute(
new HttpRequest(POST, "/session")
.addHeader("Content-Type", JSON_UTF_8)
.setContent(Contents.asJson(ImmutableMap.of(
"capabilities", ImmutableMap.of(
"alwaysMatch", Browser.detect().getCapabilities())))));

assertThat(res.isSuccessful()).isTrue();
}

private LocalNode.Builder addDriverFactory(
LocalNode.Builder builder,
WebDriverInfo info,
DriverService.Builder<?, ?> driverService) {
return builder.add(
info.getCanonicalCapabilities(),
new DriverServiceSessionFactory(
tracer,
clientFactory,
info::isSupporting,
driverService));
}
}

0 comments on commit 26cae68

Please sign in to comment.