Skip to content

Commit 85975e7

Browse files
committed
fix(vertx-http): fail build on duplicated named policies
1 parent fd4ac9a commit 85975e7

File tree

3 files changed

+101
-7
lines changed

3 files changed

+101
-7
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package io.quarkus.vertx.http.security;
2+
3+
import jakarta.enterprise.context.ApplicationScoped;
4+
5+
import org.junit.jupiter.api.Assertions;
6+
import org.junit.jupiter.api.Test;
7+
import org.junit.jupiter.api.extension.RegisterExtension;
8+
9+
import io.quarkus.security.identity.SecurityIdentity;
10+
import io.quarkus.test.QuarkusUnitTest;
11+
import io.quarkus.vertx.http.runtime.security.HttpSecurityPolicy;
12+
import io.smallrye.mutiny.Uni;
13+
import io.vertx.ext.web.RoutingContext;
14+
15+
public class DuplicatedNamedAuthPolicyValidationFailureTest {
16+
17+
private static final String POLICY_NAME = "p_o_l_i_c_y_n_a_m_e";
18+
19+
@RegisterExtension
20+
static final QuarkusUnitTest config = new QuarkusUnitTest()
21+
.withApplicationRoot((jar) -> jar
22+
.addClasses(NamedPolicy_1.class, NamedPolicy_2.class))
23+
.assertException(throwable -> {
24+
var errMsg = throwable.getMessage();
25+
Assertions.assertTrue(errMsg.contains("Only one HttpSecurityPolicy"), errMsg);
26+
Assertions.assertTrue(errMsg.contains(POLICY_NAME), errMsg);
27+
Assertions.assertTrue(errMsg.contains(NamedPolicy_1.class.getSimpleName()));
28+
Assertions.assertTrue(errMsg.contains(NamedPolicy_2.class.getSimpleName()));
29+
});
30+
31+
@Test
32+
public void test() {
33+
Assertions.fail("Build was supposed to fail due to validation");
34+
}
35+
36+
@ApplicationScoped
37+
public static class NamedPolicy_1 implements HttpSecurityPolicy {
38+
39+
@Override
40+
public Uni<CheckResult> checkPermission(RoutingContext request, Uni<SecurityIdentity> identity,
41+
AuthorizationRequestContext requestContext) {
42+
return null;
43+
}
44+
45+
@Override
46+
public String name() {
47+
return POLICY_NAME;
48+
}
49+
}
50+
51+
@ApplicationScoped
52+
public static class NamedPolicy_2 implements HttpSecurityPolicy {
53+
54+
@Override
55+
public Uni<CheckResult> checkPermission(RoutingContext request, Uni<SecurityIdentity> identity,
56+
AuthorizationRequestContext requestContext) {
57+
return null;
58+
}
59+
60+
@Override
61+
public String name() {
62+
return POLICY_NAME;
63+
}
64+
}
65+
}

extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/security/AbstractPathMatchingHttpSecurityPolicy.java

+31-6
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
import jakarta.enterprise.inject.Instance;
1818

19+
import io.quarkus.arc.ClientProxy;
1920
import io.quarkus.runtime.configuration.ConfigurationException;
2021
import io.quarkus.security.StringPermission;
2122
import io.quarkus.security.identity.SecurityIdentity;
@@ -236,7 +237,10 @@ private static Map<String, HttpSecurityPolicy> toNamedHttpSecPolicies(Map<String
236237
if (policy.name().isBlank()) {
237238
throw new ConfigurationException("HTTP Security policy '" + policy + "' name must not be blank");
238239
}
239-
namedPolicies.put(policy.name(), policy);
240+
var previousPolicy = namedPolicies.put(policy.name(), policy);
241+
if (previousPolicy != null) {
242+
throw duplicateNamedPoliciesNotAllowedEx(previousPolicy, policy);
243+
}
240244
}
241245
}
242246

@@ -271,12 +275,26 @@ private static Map<String, HttpSecurityPolicy> toNamedHttpSecPolicies(Map<String
271275
roleToPermissions.put(role, Set.copyOf(permissions));
272276
}
273277
}
274-
namedPolicies.put(e.getKey(),
275-
new RolesAllowedHttpSecurityPolicy(policyConfig.rolesAllowed(), roleToPermissions, policyConfig.roles()));
278+
var rolesAllowedPolicy = new RolesAllowedHttpSecurityPolicy(policyConfig.rolesAllowed(), roleToPermissions,
279+
policyConfig.roles());
280+
var previousPolicy = namedPolicies.put(e.getKey(), rolesAllowedPolicy);
281+
if (previousPolicy != null) {
282+
throw duplicateNamedPoliciesNotAllowedEx(previousPolicy, rolesAllowedPolicy);
283+
}
284+
}
285+
286+
var previousPolicy = namedPolicies.put("deny", DenySecurityPolicy.INSTANCE);
287+
if (previousPolicy != null) {
288+
throw duplicateNamedPoliciesNotAllowedEx(previousPolicy, DenySecurityPolicy.INSTANCE);
289+
}
290+
previousPolicy = namedPolicies.put("permit", new PermitSecurityPolicy());
291+
if (previousPolicy != null) {
292+
throw duplicateNamedPoliciesNotAllowedEx(previousPolicy, new PermitSecurityPolicy());
293+
}
294+
previousPolicy = namedPolicies.put("authenticated", new AuthenticatedHttpSecurityPolicy());
295+
if (previousPolicy != null) {
296+
throw duplicateNamedPoliciesNotAllowedEx(previousPolicy, new AuthenticatedHttpSecurityPolicy());
276297
}
277-
namedPolicies.put("deny", new DenySecurityPolicy());
278-
namedPolicies.put("permit", new PermitSecurityPolicy());
279-
namedPolicies.put("authenticated", new AuthenticatedHttpSecurityPolicy());
280298
return namedPolicies;
281299
}
282300

@@ -386,6 +404,13 @@ private void addAction(String action) {
386404
}
387405
}
388406

407+
static ConfigurationException duplicateNamedPoliciesNotAllowedEx(HttpSecurityPolicy policy1, HttpSecurityPolicy policy2) {
408+
String policyClassName1 = ClientProxy.unwrap(policy1).getClass().getName();
409+
String policyClassName2 = ClientProxy.unwrap(policy2).getClass().getName();
410+
return new ConfigurationException("Only one HttpSecurityPolicy with the name '"
411+
+ policy1.name() + "' is allowed, but found: " + policyClassName1 + " and " + policyClassName2);
412+
}
413+
389414
record HttpMatcher(String authMechanism, Set<String> methods, HttpSecurityPolicy checker) {
390415

391416
}

extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/security/JaxRsPathMatchingHttpSecurityPolicy.java

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package io.quarkus.vertx.http.runtime.security;
22

33
import static io.quarkus.vertx.http.runtime.PolicyMappingConfig.AppliesTo.JAXRS;
4+
import static io.quarkus.vertx.http.runtime.security.AbstractPathMatchingHttpSecurityPolicy.duplicateNamedPoliciesNotAllowedEx;
45

56
import java.util.HashMap;
67
import java.util.Map;
@@ -46,7 +47,10 @@ public class JaxRsPathMatchingHttpSecurityPolicy {
4647
var allPolicies = new HashMap<String, HttpSecurityPolicy>();
4748
for (HttpSecurityPolicy installedPolicy : installedPolicies) {
4849
if (installedPolicy.name() != null) {
49-
allPolicies.put(installedPolicy.name(), installedPolicy);
50+
var previousPolicy = allPolicies.put(installedPolicy.name(), installedPolicy);
51+
if (previousPolicy != null) {
52+
throw duplicateNamedPoliciesNotAllowedEx(previousPolicy, installedPolicy);
53+
}
5054
}
5155
}
5256
var annotationPoliciesOnly = new HashMap<String, HttpSecurityPolicy>();

0 commit comments

Comments
 (0)