Skip to content

Commit d6b620b

Browse files
committed
Make Observations Selectable
Closes gh-15678
1 parent 69e3c24 commit d6b620b

25 files changed

+927
-268
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/*
2+
* Copyright 2002-2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.security.config.annotation.method.configuration;
18+
19+
import io.micrometer.observation.ObservationRegistry;
20+
import org.aopalliance.intercept.MethodInvocation;
21+
22+
import org.springframework.beans.factory.ObjectProvider;
23+
import org.springframework.beans.factory.config.BeanDefinition;
24+
import org.springframework.context.annotation.Bean;
25+
import org.springframework.context.annotation.Configuration;
26+
import org.springframework.context.annotation.Role;
27+
import org.springframework.security.authorization.AuthorizationManager;
28+
import org.springframework.security.authorization.ObservationAuthorizationManager;
29+
import org.springframework.security.authorization.method.MethodInvocationResult;
30+
import org.springframework.security.config.annotation.ObjectPostProcessor;
31+
import org.springframework.security.config.observation.SecurityObservationSettings;
32+
33+
@Configuration(proxyBeanMethods = false)
34+
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
35+
class MethodObservationConfiguration {
36+
37+
private static final SecurityObservationSettings all = SecurityObservationSettings.withDefaults()
38+
.shouldObserveRequests(true)
39+
.shouldObserveAuthentications(true)
40+
.shouldObserveAuthorizations(true)
41+
.build();
42+
43+
@Bean
44+
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
45+
static ObjectPostProcessor<AuthorizationManager<MethodInvocation>> methodAuthorizationManagerPostProcessor(
46+
ObjectProvider<ObservationRegistry> registry, ObjectProvider<SecurityObservationSettings> predicate) {
47+
return new ObjectPostProcessor<>() {
48+
@Override
49+
public AuthorizationManager postProcess(AuthorizationManager object) {
50+
ObservationRegistry r = registry.getIfUnique(() -> ObservationRegistry.NOOP);
51+
boolean active = !r.isNoop() && predicate.getIfUnique(() -> all).shouldObserveAuthorizations();
52+
return active ? new ObservationAuthorizationManager<>(r, object) : object;
53+
}
54+
};
55+
}
56+
57+
@Bean
58+
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
59+
static ObjectPostProcessor<AuthorizationManager<MethodInvocationResult>> methodResultAuthorizationManagerPostProcessor(
60+
ObjectProvider<ObservationRegistry> registry, ObjectProvider<SecurityObservationSettings> predicate) {
61+
return new ObjectPostProcessor<>() {
62+
@Override
63+
public AuthorizationManager postProcess(AuthorizationManager object) {
64+
ObservationRegistry r = registry.getIfUnique(() -> ObservationRegistry.NOOP);
65+
boolean active = !r.isNoop() && predicate.getIfUnique(() -> all).shouldObserveAuthorizations();
66+
return active ? new ObservationAuthorizationManager<>(r, object) : object;
67+
}
68+
};
69+
}
70+
71+
}

config/src/main/java/org/springframework/security/config/annotation/method/configuration/MethodSecuritySelector.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,7 @@ public String[] selectImports(@NonNull AnnotationMetadata importMetadata) {
6868
imports.add(AuthorizationProxyDataConfiguration.class.getName());
6969
}
7070
if (isObservabilityPresent) {
71-
imports.add(
72-
"org.springframework.security.config.annotation.observation.configuration.ObservationConfiguration");
71+
imports.add(MethodObservationConfiguration.class.getName());
7372
}
7473
return imports.toArray(new String[0]);
7574
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/*
2+
* Copyright 2002-2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.security.config.annotation.method.configuration;
18+
19+
import io.micrometer.observation.ObservationRegistry;
20+
import org.aopalliance.intercept.MethodInvocation;
21+
22+
import org.springframework.beans.factory.ObjectProvider;
23+
import org.springframework.beans.factory.config.BeanDefinition;
24+
import org.springframework.context.annotation.Bean;
25+
import org.springframework.context.annotation.Configuration;
26+
import org.springframework.context.annotation.Role;
27+
import org.springframework.security.authorization.ObservationReactiveAuthorizationManager;
28+
import org.springframework.security.authorization.ReactiveAuthorizationManager;
29+
import org.springframework.security.authorization.method.MethodInvocationResult;
30+
import org.springframework.security.config.annotation.ObjectPostProcessor;
31+
import org.springframework.security.config.observation.SecurityObservationSettings;
32+
33+
@Configuration(proxyBeanMethods = false)
34+
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
35+
class ReactiveMethodObservationConfiguration {
36+
37+
private static final SecurityObservationSettings all = SecurityObservationSettings.withDefaults()
38+
.shouldObserveRequests(true)
39+
.shouldObserveAuthentications(true)
40+
.shouldObserveAuthorizations(true)
41+
.build();
42+
43+
@Bean
44+
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
45+
static ObjectPostProcessor<ReactiveAuthorizationManager<MethodInvocation>> methodAuthorizationManagerPostProcessor(
46+
ObjectProvider<ObservationRegistry> registry, ObjectProvider<SecurityObservationSettings> predicate) {
47+
return new ObjectPostProcessor<>() {
48+
@Override
49+
public ReactiveAuthorizationManager postProcess(ReactiveAuthorizationManager object) {
50+
ObservationRegistry r = registry.getIfUnique(() -> ObservationRegistry.NOOP);
51+
boolean active = !r.isNoop() && predicate.getIfUnique(() -> all).shouldObserveAuthorizations();
52+
return active ? new ObservationReactiveAuthorizationManager<>(r, object) : object;
53+
}
54+
};
55+
}
56+
57+
@Bean
58+
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
59+
static ObjectPostProcessor<ReactiveAuthorizationManager<MethodInvocationResult>> methodResultAuthorizationManagerPostProcessor(
60+
ObjectProvider<ObservationRegistry> registry, ObjectProvider<SecurityObservationSettings> predicate) {
61+
return new ObjectPostProcessor<>() {
62+
@Override
63+
public ReactiveAuthorizationManager postProcess(ReactiveAuthorizationManager object) {
64+
ObservationRegistry r = registry.getIfUnique(() -> ObservationRegistry.NOOP);
65+
boolean active = !r.isNoop() && predicate.getIfUnique(() -> all).shouldObserveAuthorizations();
66+
return active ? new ObservationReactiveAuthorizationManager<>(r, object) : object;
67+
}
68+
};
69+
}
70+
71+
}

config/src/main/java/org/springframework/security/config/annotation/method/configuration/ReactiveMethodSecurityConfiguration.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import org.springframework.beans.factory.config.BeanDefinition;
2323
import org.springframework.context.annotation.Bean;
2424
import org.springframework.context.annotation.Configuration;
25+
import org.springframework.context.annotation.Fallback;
2526
import org.springframework.context.annotation.ImportAware;
2627
import org.springframework.context.annotation.Role;
2728
import org.springframework.core.type.AnnotationMetadata;
@@ -82,6 +83,7 @@ static PrePostAdviceReactiveMethodInterceptor securityMethodInterceptor(Abstract
8283

8384
@Bean
8485
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
86+
@Fallback
8587
static DefaultMethodSecurityExpressionHandler methodSecurityExpressionHandler(
8688
ReactiveMethodSecurityConfiguration configuration) {
8789
DefaultMethodSecurityExpressionHandler handler = new DefaultMethodSecurityExpressionHandler();

config/src/main/java/org/springframework/security/config/annotation/method/configuration/ReactiveMethodSecuritySelector.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,7 @@ public String[] selectImports(AnnotationMetadata importMetadata) {
6262
imports.add(AuthorizationProxyDataConfiguration.class.getName());
6363
}
6464
if (isObservabilityPresent) {
65-
imports.add(
66-
"org.springframework.security.config.annotation.observation.configuration.ReactiveObservationConfiguration");
65+
imports.add(ReactiveMethodObservationConfiguration.class.getName());
6766
}
6867
imports.add(AuthorizationProxyConfiguration.class.getName());
6968
return imports.toArray(new String[0]);

config/src/main/java/org/springframework/security/config/annotation/observation/configuration/AbstractObservationObjectPostProcessor.java

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

config/src/main/java/org/springframework/security/config/annotation/observation/configuration/ObservationConfiguration.java

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

0 commit comments

Comments
 (0)