Skip to content

Commit 6652e49

Browse files
authored
Merge pull request #50899 from michalvavrik/feature/security-checks-for-jakarta-data-repos
Refactor security code to reflect annotation transformations for security annotations
2 parents 899330c + 2e3fe44 commit 6652e49

File tree

14 files changed

+692
-230
lines changed

14 files changed

+692
-230
lines changed

extensions/oidc/deployment/src/main/java/io/quarkus/oidc/deployment/OidcBuildStep.java

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import static io.quarkus.oidc.runtime.OidcRecorder.ACR_VALUES_TO_MAX_AGE_SEPARATOR;
1010
import static io.quarkus.oidc.runtime.OidcUtils.DEFAULT_TENANT_ID;
1111
import static io.quarkus.security.spi.ClassSecurityAnnotationBuildItem.useClassLevelSecurity;
12+
import static io.quarkus.security.spi.SecurityTransformerBuildItem.createSecurityTransformer;
1213
import static io.quarkus.vertx.http.deployment.EagerSecurityInterceptorBindingBuildItem.toTargetName;
1314
import static io.quarkus.vertx.http.deployment.HttpSecurityProcessor.collectAnnotatedClasses;
1415
import static io.quarkus.vertx.http.deployment.HttpSecurityProcessor.collectClassMethodsWithoutRbacAnnotation;
@@ -109,13 +110,14 @@
109110
import io.quarkus.security.spi.AdditionalSecuredMethodsBuildItem;
110111
import io.quarkus.security.spi.ClassSecurityAnnotationBuildItem;
111112
import io.quarkus.security.spi.RegisterClassSecurityCheckBuildItem;
113+
import io.quarkus.security.spi.SecurityTransformer;
114+
import io.quarkus.security.spi.SecurityTransformerBuildItem;
112115
import io.quarkus.smallrye.health.deployment.spi.HealthBuildItem;
113116
import io.quarkus.tls.deployment.spi.TlsRegistryBuildItem;
114117
import io.quarkus.vertx.core.deployment.CoreVertxBuildItem;
115118
import io.quarkus.vertx.http.deployment.EagerSecurityInterceptorBindingBuildItem;
116119
import io.quarkus.vertx.http.deployment.FilterBuildItem;
117120
import io.quarkus.vertx.http.deployment.HttpAuthMechanismAnnotationBuildItem;
118-
import io.quarkus.vertx.http.deployment.HttpSecurityUtils;
119121
import io.quarkus.vertx.http.deployment.PreRouterFinalizationBuildItem;
120122
import io.quarkus.vertx.http.deployment.SecurityInformationBuildItem;
121123
import io.quarkus.vertx.http.runtime.VertxHttpBuildTimeConfig;
@@ -437,11 +439,14 @@ public void registerAuthenticationContextInterceptor(Capabilities capabilities,
437439
BuildProducer<RegisterClassSecurityCheckBuildItem> registerClassSecurityCheckProducer,
438440
List<ClassSecurityAnnotationBuildItem> classSecurityAnnotations,
439441
BuildProducer<AdditionalSecuredMethodsBuildItem> additionalSecuredMethodsProducer,
440-
BuildProducer<EagerSecurityInterceptorBindingBuildItem> bindingProducer) {
442+
BuildProducer<EagerSecurityInterceptorBindingBuildItem> bindingProducer,
443+
Optional<SecurityTransformerBuildItem> securityTransformerBuildItem) {
441444
var authCtxAnnotations = combinedIndexBuildItem.getIndex().getAnnotations(AUTHENTICATION_CONTEXT_NAME);
442445
if (authCtxAnnotations.isEmpty() || !areEagerSecInterceptorsSupported(capabilities, httpBuildTimeConfig)) {
443446
return;
444447
}
448+
SecurityTransformer securityTransformer = SecurityTransformerBuildItem.createSecurityTransformer(
449+
combinedIndexBuildItem.getIndex(), securityTransformerBuildItem);
445450
bindingProducer.produce(new EagerSecurityInterceptorBindingBuildItem(recorder.authenticationContextInterceptorCreator(),
446451
ai -> {
447452
AnnotationValue maxAgeAnnotationValue = ai.value("maxAge");
@@ -468,18 +473,18 @@ public void registerAuthenticationContextInterceptor(Capabilities capabilities,
468473
.map(AnnotationInstance::target)
469474
.filter(at -> at.kind() == METHOD)
470475
.map(AnnotationTarget::asMethod)
471-
.toList());
476+
.toList(), securityTransformer);
472477
additionalSecuredMethodsProducer
473478
.produce(new AdditionalSecuredMethodsBuildItem(annotatedMethods, Optional.of(List.of("**"))));
474479
// method-level security; this registers @Authenticated if no RBAC is explicitly declared
475480
Predicate<ClassInfo> useClassLevelSecurity = useClassLevelSecurity(classSecurityAnnotations);
476481
Set<MethodInfo> annotatedClassMethods = collectClassMethodsWithoutRbacAnnotation(
477-
collectAnnotatedClasses(authCtxAnnotations, Predicate.not(useClassLevelSecurity)));
482+
collectAnnotatedClasses(authCtxAnnotations, Predicate.not(useClassLevelSecurity)), securityTransformer);
478483
additionalSecuredMethodsProducer
479484
.produce(new AdditionalSecuredMethodsBuildItem(annotatedClassMethods, Optional.of(List.of("**"))));
480485
// class-level security; this registers @Authenticated if no RBAC is explicitly declared
481486
collectAnnotatedClasses(authCtxAnnotations, useClassLevelSecurity).stream()
482-
.filter(Predicate.not(HttpSecurityUtils::hasSecurityAnnotation))
487+
.filter(Predicate.not(securityTransformer::hasSecurityAnnotation))
483488
.forEach(c -> registerClassSecurityCheckProducer.produce(
484489
new RegisterClassSecurityCheckBuildItem(c.name(), AnnotationInstance
485490
.builder(Authenticated.class).buildWithTarget(c))));

extensions/resteasy-classic/resteasy/deployment/src/main/java/io/quarkus/resteasy/deployment/DenyJaxRsTransformer.java

Lines changed: 0 additions & 43 deletions
This file was deleted.

extensions/resteasy-reactive/rest/deployment/src/main/java/io/quarkus/resteasy/reactive/server/deployment/ResteasyReactiveProcessor.java

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
import static io.quarkus.resteasy.reactive.common.deployment.QuarkusResteasyReactiveDotNames.HTTP_SERVER_REQUEST;
44
import static io.quarkus.resteasy.reactive.common.deployment.QuarkusResteasyReactiveDotNames.HTTP_SERVER_RESPONSE;
55
import static io.quarkus.resteasy.reactive.common.deployment.QuarkusResteasyReactiveDotNames.ROUTING_CONTEXT;
6+
import static io.quarkus.security.spi.SecurityTransformer.AuthorizationType.AUTHORIZATION_POLICY;
7+
import static io.quarkus.security.spi.SecurityTransformer.AuthorizationType.SECURITY_CHECK;
8+
import static io.quarkus.security.spi.SecurityTransformerBuildItem.createSecurityTransformer;
69
import static io.quarkus.vertx.http.deployment.EagerSecurityInterceptorMethodsBuildItem.collectInterceptedMethods;
710
import static java.util.stream.Collectors.toList;
811
import static org.jboss.resteasy.reactive.common.processor.ResteasyReactiveDotNames.DATE_FORMAT;
@@ -218,11 +221,11 @@
218221
import io.quarkus.security.AuthenticationRedirectException;
219222
import io.quarkus.security.ForbiddenException;
220223
import io.quarkus.security.spi.PermissionsAllowedMetaAnnotationBuildItem;
221-
import io.quarkus.security.spi.SecurityTransformerUtils;
224+
import io.quarkus.security.spi.SecurityTransformer;
225+
import io.quarkus.security.spi.SecurityTransformerBuildItem;
222226
import io.quarkus.vertx.http.deployment.AuthorizationPolicyInstancesBuildItem;
223227
import io.quarkus.vertx.http.deployment.EagerSecurityInterceptorMethodsBuildItem;
224228
import io.quarkus.vertx.http.deployment.FilterBuildItem;
225-
import io.quarkus.vertx.http.deployment.HttpSecurityUtils;
226229
import io.quarkus.vertx.http.deployment.RouteBuildItem;
227230
import io.quarkus.vertx.http.runtime.RouteConstants;
228231
import io.quarkus.vertx.http.runtime.VertxHttpBuildTimeConfig;
@@ -1765,10 +1768,13 @@ public void securityExceptionMappers(BuildProducer<ExceptionMapperBuildItem> exc
17651768
MethodScannerBuildItem integrateEagerSecurity(Capabilities capabilities, CombinedIndexBuildItem indexBuildItem,
17661769
Optional<AuthorizationPolicyInstancesBuildItem> authorizationPolicyInstancesItemOpt,
17671770
List<EagerSecurityInterceptorMethodsBuildItem> eagerSecurityInterceptors, JaxRsSecurityConfig securityConfig,
1768-
Optional<PermissionsAllowedMetaAnnotationBuildItem> permsAllowedMetaAnnotationItemOptional) {
1771+
Optional<PermissionsAllowedMetaAnnotationBuildItem> permsAllowedMetaAnnotationItemOptional,
1772+
Optional<SecurityTransformerBuildItem> securityTransformerBuildItem) {
17691773
if (!capabilities.isPresent(Capability.SECURITY)) {
17701774
return null;
17711775
}
1776+
SecurityTransformer securityTransformer = SecurityTransformerBuildItem.createSecurityTransformer(
1777+
indexBuildItem.getIndex(), securityTransformerBuildItem);
17721778
var authZPolicyInstancesItem = authorizationPolicyInstancesItemOpt.get();
17731779
var permsAllowedMetaAnnotationItem = permsAllowedMetaAnnotationItemOptional.get();
17741780

@@ -1787,17 +1793,19 @@ public List<HandlerChainCustomizer> scan(MethodInfo method, ClassInfo actualEndp
17871793
boolean isMethodIntercepted = interceptedMethods.containsKey(endpointImpl);
17881794
if (isMethodIntercepted) {
17891795
return createEagerSecCustomizerWithInterceptor(interceptedMethods, endpointImpl, method, endpointImpl,
1790-
withDefaultSecurityCheck, applyAuthorizationPolicy, permsAllowedMetaAnnotationItem);
1796+
withDefaultSecurityCheck, applyAuthorizationPolicy, permsAllowedMetaAnnotationItem,
1797+
securityTransformer);
17911798
} else {
17921799
isMethodIntercepted = interceptedMethods.containsKey(method);
17931800
if (isMethodIntercepted && !endpointImpl.equals(method)) {
17941801
return createEagerSecCustomizerWithInterceptor(interceptedMethods, method, method, endpointImpl,
1795-
withDefaultSecurityCheck, applyAuthorizationPolicy, permsAllowedMetaAnnotationItem);
1802+
withDefaultSecurityCheck, applyAuthorizationPolicy, permsAllowedMetaAnnotationItem,
1803+
securityTransformer);
17961804
}
17971805
}
17981806
}
17991807
return List.of(newEagerSecurityHandlerCustomizerInstance(method, endpointImpl, withDefaultSecurityCheck,
1800-
applyAuthorizationPolicy, permsAllowedMetaAnnotationItem));
1808+
applyAuthorizationPolicy, permsAllowedMetaAnnotationItem, securityTransformer));
18011809
}
18021810
});
18031811
}
@@ -1810,28 +1818,32 @@ private static boolean shouldApplyAuthZPolicy(MethodInfo method, MethodInfo endp
18101818
private static List<HandlerChainCustomizer> createEagerSecCustomizerWithInterceptor(
18111819
Map<MethodInfo, Boolean> interceptedMethods, MethodInfo method, MethodInfo originalMethod, MethodInfo endpointImpl,
18121820
boolean withDefaultSecurityCheck, boolean applyAuthorizationPolicy,
1813-
PermissionsAllowedMetaAnnotationBuildItem permsAllowedMetaAnnotationItem) {
1821+
PermissionsAllowedMetaAnnotationBuildItem permsAllowedMetaAnnotationItem,
1822+
SecurityTransformer securityTransformer) {
18141823
var requiresSecurityCheck = interceptedMethods.get(method);
18151824
final HandlerChainCustomizer eagerSecCustomizer;
18161825
if (requiresSecurityCheck && !applyAuthorizationPolicy) {
18171826
// standard security annotation and possibly authorization using configuration
18181827
eagerSecCustomizer = new HttpPermissionsAndSecurityChecksCustomizer();
18191828
} else {
18201829
eagerSecCustomizer = newEagerSecurityHandlerCustomizerInstance(originalMethod, endpointImpl,
1821-
withDefaultSecurityCheck, applyAuthorizationPolicy, permsAllowedMetaAnnotationItem);
1830+
withDefaultSecurityCheck, applyAuthorizationPolicy, permsAllowedMetaAnnotationItem,
1831+
securityTransformer);
18221832
}
18231833
return List.of(EagerSecurityInterceptorHandler.Customizer.newInstance(), eagerSecCustomizer);
18241834
}
18251835

18261836
private static HandlerChainCustomizer newEagerSecurityHandlerCustomizerInstance(MethodInfo method, MethodInfo endpointImpl,
18271837
boolean withDefaultSecurityCheck, boolean applyAuthorizationPolicy,
1828-
PermissionsAllowedMetaAnnotationBuildItem permsAllowedMetaAnnotationItem) {
1838+
PermissionsAllowedMetaAnnotationBuildItem permsAllowedMetaAnnotationItem,
1839+
SecurityTransformer securityTransformer) {
18291840
if (applyAuthorizationPolicy) {
18301841
// @AuthorizationPolicy and possibly authorization using configuration
18311842
return new AuthZPolicyCustomizer();
18321843
}
18331844
if (withDefaultSecurityCheck
1834-
|| consumesStandardSecurityAnnotations(method, endpointImpl, permsAllowedMetaAnnotationItem)) {
1845+
|| consumesStandardSecurityAnnotations(method, endpointImpl, permsAllowedMetaAnnotationItem,
1846+
securityTransformer)) {
18351847
// standard security annotation and possibly authorization using configuration
18361848
return new HttpPermissionsAndSecurityChecksCustomizer();
18371849
}
@@ -1904,25 +1916,27 @@ void registerSecurityBeans(Capabilities capabilities,
19041916
}
19051917

19061918
private static boolean consumesStandardSecurityAnnotations(MethodInfo methodInfo, MethodInfo endpointImpl,
1907-
PermissionsAllowedMetaAnnotationBuildItem permsAllowedMetaAnnotationItem) {
1919+
PermissionsAllowedMetaAnnotationBuildItem permsAllowedMetaAnnotationItem,
1920+
SecurityTransformer securityTransformer) {
19081921
// invoked method
1909-
if (consumesStandardSecurityAnnotations(endpointImpl, permsAllowedMetaAnnotationItem)) {
1922+
if (consumesStandardSecurityAnnotations(endpointImpl, permsAllowedMetaAnnotationItem, securityTransformer)) {
19101923
return true;
19111924
}
19121925

19131926
// fallback to original behavior
19141927
return !endpointImpl.equals(methodInfo)
1915-
&& consumesStandardSecurityAnnotations(methodInfo, permsAllowedMetaAnnotationItem);
1928+
&& consumesStandardSecurityAnnotations(methodInfo, permsAllowedMetaAnnotationItem, securityTransformer);
19161929
}
19171930

19181931
private static boolean consumesStandardSecurityAnnotations(MethodInfo methodInfo,
1919-
PermissionsAllowedMetaAnnotationBuildItem permsAllowedMetaAnnotationItem) {
1920-
boolean hasMethodLevelSecurityAnnotation = SecurityTransformerUtils.hasSecurityAnnotation(methodInfo)
1932+
PermissionsAllowedMetaAnnotationBuildItem permsAllowedMetaAnnotationItem,
1933+
SecurityTransformer securityTransformer) {
1934+
boolean hasMethodLevelSecurityAnnotation = securityTransformer.hasSecurityAnnotation(methodInfo, SECURITY_CHECK)
19211935
|| permsAllowedMetaAnnotationItem.hasPermissionsAllowed(methodInfo);
19221936
if (hasMethodLevelSecurityAnnotation) {
19231937
return true;
19241938
}
1925-
if (HttpSecurityUtils.hasAuthorizationPolicyAnnotation(methodInfo)) {
1939+
if (securityTransformer.hasSecurityAnnotation(methodInfo, AUTHORIZATION_POLICY)) {
19261940
// security annotations cannot be combined
19271941
// and the most specific wins, so if we have both class-level security check
19281942
// and the method-level @AuthorizationPolicy, the policy wins as it is more specific
@@ -1931,7 +1945,7 @@ private static boolean consumesStandardSecurityAnnotations(MethodInfo methodInfo
19311945
// on a method level thanks to validation
19321946
return false;
19331947
}
1934-
return SecurityTransformerUtils.hasSecurityAnnotation(methodInfo.declaringClass())
1948+
return securityTransformer.hasSecurityAnnotation(methodInfo.declaringClass(), SECURITY_CHECK)
19351949
|| permsAllowedMetaAnnotationItem.hasPermissionsAllowed(methodInfo.declaringClass());
19361950
}
19371951

extensions/security/deployment/src/main/java/io/quarkus/security/deployment/DenyUnannotatedPredicate.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,20 @@
66
import org.jboss.jandex.ClassInfo;
77
import org.jboss.jandex.MethodInfo;
88

9-
import io.quarkus.security.spi.SecurityTransformerUtils;
9+
import io.quarkus.security.spi.SecurityTransformer;
1010

1111
final class DenyUnannotatedPredicate implements Predicate<ClassInfo> {
1212

13+
private final SecurityTransformer securityTransformer;
14+
15+
DenyUnannotatedPredicate(SecurityTransformer securityTransformer) {
16+
this.securityTransformer = securityTransformer;
17+
}
18+
1319
@Override
1420
public boolean test(ClassInfo classInfo) {
1521
List<MethodInfo> methods = classInfo.methods();
16-
return !SecurityTransformerUtils.hasSecurityAnnotation(classInfo)
17-
&& methods.stream().anyMatch(SecurityTransformerUtils::hasSecurityAnnotation);
22+
return !securityTransformer.hasSecurityAnnotation(classInfo)
23+
&& methods.stream().anyMatch(securityTransformer::hasSecurityAnnotation);
1824
}
1925
}

0 commit comments

Comments
 (0)