Skip to content

Commit 26cae68

Browse files
committed
Ensure all requests have no origin, and are requesting json content
1 parent 48a5451 commit 26cae68

5 files changed

Lines changed: 181 additions & 2 deletions

File tree

java/private/test.bzl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ def java_selenium_test_suite(
3535
name = "%s-base-lib" % name,
3636
srcs = srcs,
3737
deps = deps,
38+
testonly = True,
3839
**kwargs
3940
)
4041

java/server/src/org/openqa/selenium/grid/router/httpd/RouterServer.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@
4444
import org.openqa.selenium.remote.http.Route;
4545
import org.openqa.selenium.remote.tracing.Tracer;
4646

47-
import java.net.URI;
4847
import java.net.URL;
4948
import java.util.Collections;
5049
import java.util.Set;
@@ -116,7 +115,7 @@ protected void execute(Config config) {
116115
GraphqlHandler graphqlHandler = new GraphqlHandler(distributor, serverOptions.getExternalUri());
117116

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

java/server/src/org/openqa/selenium/grid/server/NetworkOptions.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,19 @@
1717

1818
package org.openqa.selenium.grid.server;
1919

20+
import com.google.common.collect.ImmutableList;
2021
import org.openqa.selenium.grid.config.Config;
22+
import org.openqa.selenium.grid.web.CheckContentTypeHeader;
23+
import org.openqa.selenium.grid.web.CheckOriginHeader;
2124
import org.openqa.selenium.internal.Require;
25+
import org.openqa.selenium.remote.http.Filter;
2226
import org.openqa.selenium.remote.http.HttpClient;
2327
import org.openqa.selenium.remote.tracing.TracedHttpClient;
2428
import org.openqa.selenium.remote.tracing.Tracer;
2529

30+
import java.util.List;
31+
import java.util.Optional;
32+
2633
public class NetworkOptions {
2734

2835
private final Config config;
@@ -34,4 +41,22 @@ public NetworkOptions(Config config) {
3441
public HttpClient.Factory getHttpClientFactory(Tracer tracer) {
3542
return new TracedHttpClient.Factory(tracer, HttpClient.Factory.createDefault());
3643
}
44+
45+
public Filter getSpecComplianceChecks() {
46+
// Base case: we do nothing
47+
Filter toReturn = httpHandler -> httpHandler;
48+
49+
if (config.getBool("network", "check_content_type").orElse(true)) {
50+
toReturn = toReturn.andThen(new CheckContentTypeHeader());
51+
}
52+
53+
boolean checkOrigin = config.getBool("network", "check_origin_header").orElse(true);
54+
Optional<List<String>> allowedOrigins = config.getAll("network", "allowed_origins");
55+
56+
if (checkOrigin || allowedOrigins.isPresent()) {
57+
toReturn = toReturn.andThen(new CheckOriginHeader(allowedOrigins.orElse(ImmutableList.of())));
58+
}
59+
60+
return toReturn;
61+
}
3762
}

java/server/test/org/openqa/selenium/grid/router/BUILD.bazel

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ load("//java:defs.bzl", "java_selenium_test_suite", "java_test_suite")
33

44
LARGE_TESTS = [
55
"DistributedCdpTest.java",
6+
"NewSessionCreationTest.java",
67
]
78

89
java_selenium_test_suite(
@@ -11,16 +12,21 @@ java_selenium_test_suite(
1112
srcs = LARGE_TESTS,
1213
deps = [
1314
"//java/client/src/org/openqa/selenium:core",
15+
"//java/client/src/org/openqa/selenium/chrome",
1416
"//java/client/src/org/openqa/selenium/devtools",
17+
"//java/client/src/org/openqa/selenium/firefox",
1518
"//java/client/src/org/openqa/selenium/json",
1619
"//java/client/src/org/openqa/selenium/remote",
1720
"//java/client/src/org/openqa/selenium/remote/http",
1821
"//java/client/src/org/openqa/selenium/support",
22+
"//java/client/test/org/openqa/selenium/remote/tracing:tracing-support",
1923
"//java/client/test/org/openqa/selenium/testing:annotations",
24+
"//java/client/test/org/openqa/selenium/testing/drivers",
2025
"//java/server/src/org/openqa/selenium/grid",
2126
"//java/server/src/org/openqa/selenium/grid/commands",
2227
"//java/server/src/org/openqa/selenium/grid/distributor/httpd",
2328
"//java/server/src/org/openqa/selenium/grid/sessionmap/httpd",
29+
"//java/server/test/org/openqa/selenium/grid/testing:testing",
2430
artifact("com.google.guava:guava"),
2531
artifact("junit:junit"),
2632
artifact("org.assertj:assertj-core"),
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
// Licensed to the Software Freedom Conservancy (SFC) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The SFC licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
package org.openqa.selenium.grid.router;
19+
20+
import com.google.common.collect.ImmutableList;
21+
import com.google.common.collect.ImmutableMap;
22+
import org.junit.Before;
23+
import org.junit.Test;
24+
import org.openqa.selenium.WebDriverInfo;
25+
import org.openqa.selenium.chrome.ChromeDriverInfo;
26+
import org.openqa.selenium.events.EventBus;
27+
import org.openqa.selenium.events.local.GuavaEventBus;
28+
import org.openqa.selenium.firefox.GeckoDriverInfo;
29+
import org.openqa.selenium.grid.config.MapConfig;
30+
import org.openqa.selenium.grid.data.Session;
31+
import org.openqa.selenium.grid.distributor.Distributor;
32+
import org.openqa.selenium.grid.distributor.local.LocalDistributor;
33+
import org.openqa.selenium.grid.node.Node;
34+
import org.openqa.selenium.grid.node.config.DriverServiceSessionFactory;
35+
import org.openqa.selenium.grid.node.local.LocalNode;
36+
import org.openqa.selenium.grid.server.BaseServerOptions;
37+
import org.openqa.selenium.grid.server.Server;
38+
import org.openqa.selenium.grid.sessionmap.SessionMap;
39+
import org.openqa.selenium.grid.sessionmap.local.LocalSessionMap;
40+
import org.openqa.selenium.grid.testing.TestSessionFactory;
41+
import org.openqa.selenium.grid.web.EnsureSpecCompliantHeaders;
42+
import org.openqa.selenium.netty.server.NettyServer;
43+
import org.openqa.selenium.remote.http.Contents;
44+
import org.openqa.selenium.remote.http.HttpClient;
45+
import org.openqa.selenium.remote.http.HttpRequest;
46+
import org.openqa.selenium.remote.http.HttpResponse;
47+
import org.openqa.selenium.remote.http.Routable;
48+
import org.openqa.selenium.remote.service.DriverService;
49+
import org.openqa.selenium.remote.tracing.DefaultTestTracer;
50+
import org.openqa.selenium.remote.tracing.Tracer;
51+
import org.openqa.selenium.testing.drivers.Browser;
52+
53+
import java.net.URI;
54+
import java.net.URISyntaxException;
55+
56+
import static java.net.HttpURLConnection.HTTP_INTERNAL_ERROR;
57+
import static org.assertj.core.api.Assertions.assertThat;
58+
import static org.assertj.core.api.Assumptions.assumeThat;
59+
import static org.openqa.selenium.json.Json.JSON_UTF_8;
60+
import static org.openqa.selenium.remote.http.HttpMethod.POST;
61+
62+
public class NewSessionCreationTest {
63+
64+
private Tracer tracer;
65+
private EventBus events;
66+
private HttpClient.Factory clientFactory;
67+
68+
@Before
69+
public void setup() {
70+
tracer = DefaultTestTracer.createTracer();
71+
events = new GuavaEventBus();
72+
clientFactory = HttpClient.Factory.createDefault();
73+
}
74+
75+
@Test
76+
public void ensureJsCannotCreateANewSession() throws URISyntaxException {
77+
ChromeDriverInfo chromeDriverInfo = new ChromeDriverInfo();
78+
assumeThat(chromeDriverInfo.isAvailable()).isTrue();
79+
GeckoDriverInfo geckoDriverInfo = new GeckoDriverInfo();
80+
assumeThat(geckoDriverInfo.isAvailable()).isTrue();
81+
82+
SessionMap sessions = new LocalSessionMap(tracer, events);
83+
Distributor distributor = new LocalDistributor(tracer, events, clientFactory, sessions, null);
84+
Routable router = new Router(tracer, clientFactory, sessions, distributor).with(new EnsureSpecCompliantHeaders(ImmutableList.of()));
85+
86+
Server<?> server = new NettyServer(
87+
new BaseServerOptions(new MapConfig(ImmutableMap.of())),
88+
router,
89+
new ProxyCdpIntoGrid(clientFactory, sessions))
90+
.start();
91+
92+
URI uri = server.getUrl().toURI();
93+
Node node = LocalNode.builder(
94+
tracer,
95+
events,
96+
uri,
97+
uri,
98+
null)
99+
.add(Browser.detect().getCapabilities(), new TestSessionFactory((id, caps) -> new Session(id, uri, caps)))
100+
.build();
101+
distributor.add(node);
102+
103+
HttpClient client = HttpClient.Factory.createDefault().createClient(server.getUrl());
104+
105+
// Attempt to create a session without setting the content type
106+
HttpResponse res = client.execute(
107+
new HttpRequest(POST, "/session")
108+
.setContent(Contents.asJson(ImmutableMap.of(
109+
"capabilities", ImmutableMap.of(
110+
"alwaysMatch", Browser.detect().getCapabilities())))));
111+
112+
assertThat(res.getStatus()).isEqualTo(HTTP_INTERNAL_ERROR);
113+
114+
// Attempt to create a session with an origin header but content type set
115+
res = client.execute(
116+
new HttpRequest(POST, "/session")
117+
.addHeader("Content-Type", JSON_UTF_8)
118+
.addHeader("Origin", "localhost")
119+
.setContent(Contents.asJson(ImmutableMap.of(
120+
"capabilities", ImmutableMap.of(
121+
"alwaysMatch", Browser.detect().getCapabilities())))));
122+
123+
assertThat(res.getStatus()).isEqualTo(HTTP_INTERNAL_ERROR);
124+
125+
// And now make sure the session is just fine
126+
res = client.execute(
127+
new HttpRequest(POST, "/session")
128+
.addHeader("Content-Type", JSON_UTF_8)
129+
.setContent(Contents.asJson(ImmutableMap.of(
130+
"capabilities", ImmutableMap.of(
131+
"alwaysMatch", Browser.detect().getCapabilities())))));
132+
133+
assertThat(res.isSuccessful()).isTrue();
134+
}
135+
136+
private LocalNode.Builder addDriverFactory(
137+
LocalNode.Builder builder,
138+
WebDriverInfo info,
139+
DriverService.Builder<?, ?> driverService) {
140+
return builder.add(
141+
info.getCanonicalCapabilities(),
142+
new DriverServiceSessionFactory(
143+
tracer,
144+
clientFactory,
145+
info::isSupporting,
146+
driverService));
147+
}
148+
}

0 commit comments

Comments
 (0)