Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions core/src/test/java/io/confluent/rest/ApplicationServerTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,26 @@ private TestRestConfig configBasic() {
return new TestRestConfig(props);
}

private TestRestConfig configBasicWithWildcardSkipPath() {
Properties props = new Properties();
props.put(RestConfig.AUTHENTICATION_METHOD_CONFIG, RestConfig.AUTHENTICATION_METHOD_BASIC);
props.put(RestConfig.AUTHENTICATION_REALM_CONFIG, "c3");
props.put(RestConfig.AUTHENTICATION_ROLES_CONFIG, Collections.singletonList("Administrators"));
props.put(RestConfig.AUTHENTICATION_SKIP_PATHS, "/*");

return new TestRestConfig(props);
}

private TestRestConfig configBasicWithSkipPaths(String skipPaths) {
Properties props = new Properties();
props.put(RestConfig.AUTHENTICATION_METHOD_CONFIG, RestConfig.AUTHENTICATION_METHOD_BASIC);
props.put(RestConfig.AUTHENTICATION_REALM_CONFIG, "c3");
props.put(RestConfig.AUTHENTICATION_ROLES_CONFIG, Collections.singletonList("Administrators"));
props.put(RestConfig.AUTHENTICATION_SKIP_PATHS, skipPaths);

return new TestRestConfig(props);
}

/* Ensure security handlers are confined to a single context */
@Test
public void testSecurityHandlerIsolation() throws Exception {
Expand All @@ -97,6 +117,47 @@ public void testSecurityHandlerIsolation() throws Exception {
assertThat(makeGetRequest( "/app2/resource"), is(Code.UNAUTHORIZED));
}

/*
* Regression test: authentication.skip.paths="/*" must actually disable authentication for
* all paths, even though this skip pathSpec is identical to the hardcoded global auth
* constraint's pathSpec ("/*"). Before the fix in AuthUtil#createConstraint, an unauthenticated
* request here was rejected because Jetty's ConstraintSecurityHandler merges two mappings that
* share the same pathSpec, and the skip mapping's default Authorization.INHERIT deferred to the
* global constraint's real BASIC auth requirement instead of actually allowing the request.
*/
@Test
public void testUnsecuredWildcardSkipPathOverridesGlobalAuthConstraint() throws Exception {
TestApp app1 = new TestApp("/app1");
TestApp app2 = new TestApp(configBasicWithWildcardSkipPath(), "/app2");

server.registerApplication(app1);
server.registerApplication(app2);
server.start();

// app1 has no auth configured at all; sanity check that it stays open.
assertThat(makeGetRequest("/app1/resource"), is(Code.OK));
// app2 has BASIC auth enabled globally, but skips it for "/*": an unauthenticated request
// must still succeed.
assertThat(makeGetRequest("/app2/resource"), is(Code.OK));
}

/*
* Non-wildcard skip path: only the exact configured pathSpec should bypass authentication;
* every other path under the same app must remain protected by the global auth constraint.
*/
@Test
public void testUnsecuredSpecificSkipPathLeavesOtherPathsSecured() throws Exception {
TestApp app = new TestApp(configBasicWithSkipPaths("/resource"), "/app");

server.registerApplication(app);
server.start();

// "/resource" is an explicit skip path: unauthenticated requests must succeed.
assertThat(makeGetRequest("/app/resource"), is(Code.OK));
// "/exception" was not listed as a skip path, so it must still require authentication.
assertThat(makeGetRequest("/app/exception"), is(Code.UNAUTHORIZED));
}

/* Test Exception Mapper isolation */
@Test
public void testExceptionMapperIsolation() throws Exception {
Expand Down