io.quarkus.vertx.http.runtime.security.JaxRsPathMatchingHttpSecurityPolicy Maven / Gradle / Ivy
package io.quarkus.vertx.http.runtime.security;
import static io.quarkus.vertx.http.runtime.PolicyMappingConfig.AppliesTo.JAXRS;
import java.util.HashMap;
import java.util.Map;
import jakarta.enterprise.inject.Instance;
import io.quarkus.security.identity.SecurityIdentity;
import io.quarkus.security.spi.runtime.BlockingSecurityExecutor;
import io.quarkus.security.spi.runtime.MethodDescription;
import io.quarkus.vertx.http.runtime.HttpBuildTimeConfig;
import io.quarkus.vertx.http.runtime.HttpConfiguration;
import io.quarkus.vertx.http.runtime.security.HttpSecurityPolicy.AuthorizationRequestContext;
import io.quarkus.vertx.http.runtime.security.HttpSecurityPolicy.CheckResult;
import io.quarkus.vertx.http.runtime.security.HttpSecurityPolicy.DefaultAuthorizationRequestContext;
import io.smallrye.mutiny.Uni;
import io.vertx.ext.web.RoutingContext;
/**
* Decorates {@link AbstractPathMatchingHttpSecurityPolicy} path matching capabilities
* with support for policies selected with {@link io.quarkus.vertx.http.security.AuthorizationPolicy}.
* Decorator may only run after HTTP requests have been matched with the endpoint class method.
* Extensions can make this class bean if they need it.
*/
public class JaxRsPathMatchingHttpSecurityPolicy {
private final AbstractPathMatchingHttpSecurityPolicy delegate;
private final boolean foundNoAnnotatedMethods;
private final AuthorizationRequestContext requestContext;
private final Map policyNameToPolicy;
private final AuthorizationPolicyStorage storage;
JaxRsPathMatchingHttpSecurityPolicy(AuthorizationPolicyStorage storage,
Instance installedPolicies, HttpConfiguration httpConfig,
HttpBuildTimeConfig buildTimeConfig, BlockingSecurityExecutor blockingSecurityExecutor) {
this.storage = storage;
this.delegate = new AbstractPathMatchingHttpSecurityPolicy(httpConfig.auth.permissions,
httpConfig.auth.rolePolicy, buildTimeConfig.rootPath, installedPolicies, JAXRS);
this.foundNoAnnotatedMethods = storage.getMethodToPolicyName().isEmpty();
this.requestContext = new DefaultAuthorizationRequestContext(blockingSecurityExecutor);
if (storage.getMethodToPolicyName().isEmpty()) {
this.policyNameToPolicy = Map.of();
} else {
var allPolicies = new HashMap();
for (HttpSecurityPolicy installedPolicy : installedPolicies) {
if (installedPolicy.name() != null) {
allPolicies.put(installedPolicy.name(), installedPolicy);
}
}
var annotationPoliciesOnly = new HashMap();
for (Map.Entry e : storage.getMethodToPolicyName().entrySet()) {
var policyName = e.getValue();
if (annotationPoliciesOnly.containsKey(policyName)) {
continue;
}
if (allPolicies.containsKey(policyName)) {
annotationPoliciesOnly.put(policyName, allPolicies.get(policyName));
continue;
}
var classAndMethodName = e.getKey().getClassName() + "#" + e.getKey().getMethodName();
throw new RuntimeException("""
Endpoint '%s' requires named HttpSecurityPolicy '%s' specified with '@AuthorizationPolicy',
but no such policies has bean found. Please provide required policy as CDI bean.
""".formatted(classAndMethodName, policyName));
}
policyNameToPolicy = Map.copyOf(annotationPoliciesOnly);
}
}
/**
* @param securedMethodDesc method description
* @return true if method is secured with {@link io.quarkus.vertx.http.security.AuthorizationPolicy}
*/
public boolean requiresAuthorizationPolicy(MethodDescription securedMethodDesc) {
return storage.requiresAuthorizationPolicy(securedMethodDesc);
}
/**
* @return true if there is no point running {@link #checkPermission(RoutingContext, Uni, MethodDescription)}
*/
public boolean hasNoPermissions() {
return delegate.hasNoPermissions() && foundNoAnnotatedMethods;
}
/**
* Applies {@link HttpSecurityPolicy} matched by path-matching rules
* or by {@link io.quarkus.vertx.http.security.AuthorizationPolicy}.
*/
public Uni checkPermission(RoutingContext routingContext, Uni identity,
MethodDescription description) {
var authorizationPolicy = findAuthorizationPolicy(description);
if (authorizationPolicy == null) {
return delegate.checkPermissions(routingContext, identity, requestContext);
} else {
return delegate.checkPermissions(routingContext, identity, requestContext, authorizationPolicy);
}
}
private HttpSecurityPolicy findAuthorizationPolicy(MethodDescription description) {
if (description != null) {
var policyName = storage.getMethodToPolicyName().get(description);
if (policyName != null) {
return policyNameToPolicy.get(policyName);
}
}
return null;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy