parent
69e3c248fa
commit
d6b620b9f7
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.config.annotation.method.configuration;
|
||||
|
||||
import io.micrometer.observation.ObservationRegistry;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Role;
|
||||
import org.springframework.security.authorization.AuthorizationManager;
|
||||
import org.springframework.security.authorization.ObservationAuthorizationManager;
|
||||
import org.springframework.security.authorization.method.MethodInvocationResult;
|
||||
import org.springframework.security.config.annotation.ObjectPostProcessor;
|
||||
import org.springframework.security.config.observation.SecurityObservationSettings;
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
class MethodObservationConfiguration {
|
||||
|
||||
private static final SecurityObservationSettings all = SecurityObservationSettings.withDefaults()
|
||||
.shouldObserveRequests(true)
|
||||
.shouldObserveAuthentications(true)
|
||||
.shouldObserveAuthorizations(true)
|
||||
.build();
|
||||
|
||||
@Bean
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
static ObjectPostProcessor<AuthorizationManager<MethodInvocation>> methodAuthorizationManagerPostProcessor(
|
||||
ObjectProvider<ObservationRegistry> registry, ObjectProvider<SecurityObservationSettings> predicate) {
|
||||
return new ObjectPostProcessor<>() {
|
||||
@Override
|
||||
public AuthorizationManager postProcess(AuthorizationManager object) {
|
||||
ObservationRegistry r = registry.getIfUnique(() -> ObservationRegistry.NOOP);
|
||||
boolean active = !r.isNoop() && predicate.getIfUnique(() -> all).shouldObserveAuthorizations();
|
||||
return active ? new ObservationAuthorizationManager<>(r, object) : object;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
static ObjectPostProcessor<AuthorizationManager<MethodInvocationResult>> methodResultAuthorizationManagerPostProcessor(
|
||||
ObjectProvider<ObservationRegistry> registry, ObjectProvider<SecurityObservationSettings> predicate) {
|
||||
return new ObjectPostProcessor<>() {
|
||||
@Override
|
||||
public AuthorizationManager postProcess(AuthorizationManager object) {
|
||||
ObservationRegistry r = registry.getIfUnique(() -> ObservationRegistry.NOOP);
|
||||
boolean active = !r.isNoop() && predicate.getIfUnique(() -> all).shouldObserveAuthorizations();
|
||||
return active ? new ObservationAuthorizationManager<>(r, object) : object;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
|
@ -68,8 +68,7 @@ final class MethodSecuritySelector implements ImportSelector {
|
|||
imports.add(AuthorizationProxyDataConfiguration.class.getName());
|
||||
}
|
||||
if (isObservabilityPresent) {
|
||||
imports.add(
|
||||
"org.springframework.security.config.annotation.observation.configuration.ObservationConfiguration");
|
||||
imports.add(MethodObservationConfiguration.class.getName());
|
||||
}
|
||||
return imports.toArray(new String[0]);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.config.annotation.method.configuration;
|
||||
|
||||
import io.micrometer.observation.ObservationRegistry;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Role;
|
||||
import org.springframework.security.authorization.ObservationReactiveAuthorizationManager;
|
||||
import org.springframework.security.authorization.ReactiveAuthorizationManager;
|
||||
import org.springframework.security.authorization.method.MethodInvocationResult;
|
||||
import org.springframework.security.config.annotation.ObjectPostProcessor;
|
||||
import org.springframework.security.config.observation.SecurityObservationSettings;
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
class ReactiveMethodObservationConfiguration {
|
||||
|
||||
private static final SecurityObservationSettings all = SecurityObservationSettings.withDefaults()
|
||||
.shouldObserveRequests(true)
|
||||
.shouldObserveAuthentications(true)
|
||||
.shouldObserveAuthorizations(true)
|
||||
.build();
|
||||
|
||||
@Bean
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
static ObjectPostProcessor<ReactiveAuthorizationManager<MethodInvocation>> methodAuthorizationManagerPostProcessor(
|
||||
ObjectProvider<ObservationRegistry> registry, ObjectProvider<SecurityObservationSettings> predicate) {
|
||||
return new ObjectPostProcessor<>() {
|
||||
@Override
|
||||
public ReactiveAuthorizationManager postProcess(ReactiveAuthorizationManager object) {
|
||||
ObservationRegistry r = registry.getIfUnique(() -> ObservationRegistry.NOOP);
|
||||
boolean active = !r.isNoop() && predicate.getIfUnique(() -> all).shouldObserveAuthorizations();
|
||||
return active ? new ObservationReactiveAuthorizationManager<>(r, object) : object;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
static ObjectPostProcessor<ReactiveAuthorizationManager<MethodInvocationResult>> methodResultAuthorizationManagerPostProcessor(
|
||||
ObjectProvider<ObservationRegistry> registry, ObjectProvider<SecurityObservationSettings> predicate) {
|
||||
return new ObjectPostProcessor<>() {
|
||||
@Override
|
||||
public ReactiveAuthorizationManager postProcess(ReactiveAuthorizationManager object) {
|
||||
ObservationRegistry r = registry.getIfUnique(() -> ObservationRegistry.NOOP);
|
||||
boolean active = !r.isNoop() && predicate.getIfUnique(() -> all).shouldObserveAuthorizations();
|
||||
return active ? new ObservationReactiveAuthorizationManager<>(r, object) : object;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
|
@ -22,6 +22,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Fallback;
|
||||
import org.springframework.context.annotation.ImportAware;
|
||||
import org.springframework.context.annotation.Role;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
|
@ -82,6 +83,7 @@ class ReactiveMethodSecurityConfiguration implements ImportAware {
|
|||
|
||||
@Bean
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
@Fallback
|
||||
static DefaultMethodSecurityExpressionHandler methodSecurityExpressionHandler(
|
||||
ReactiveMethodSecurityConfiguration configuration) {
|
||||
DefaultMethodSecurityExpressionHandler handler = new DefaultMethodSecurityExpressionHandler();
|
||||
|
|
|
@ -62,8 +62,7 @@ class ReactiveMethodSecuritySelector implements ImportSelector {
|
|||
imports.add(AuthorizationProxyDataConfiguration.class.getName());
|
||||
}
|
||||
if (isObservabilityPresent) {
|
||||
imports.add(
|
||||
"org.springframework.security.config.annotation.observation.configuration.ReactiveObservationConfiguration");
|
||||
imports.add(ReactiveMethodObservationConfiguration.class.getName());
|
||||
}
|
||||
imports.add(AuthorizationProxyConfiguration.class.getName());
|
||||
return imports.toArray(new String[0]);
|
||||
|
|
|
@ -1,53 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.config.annotation.observation.configuration;
|
||||
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
|
||||
import io.micrometer.observation.ObservationRegistry;
|
||||
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.security.config.annotation.ObjectPostProcessor;
|
||||
|
||||
abstract class AbstractObservationObjectPostProcessor<O> implements ObjectPostProcessor<O> {
|
||||
|
||||
private final ObjectProvider<ObservationRegistry> observationRegistry;
|
||||
|
||||
private final BiFunction<ObservationRegistry, O, O> wrapper;
|
||||
|
||||
AbstractObservationObjectPostProcessor(ObjectProvider<ObservationRegistry> observationRegistry,
|
||||
Function<ObservationRegistry, O> constructor) {
|
||||
this(observationRegistry, (registry, object) -> constructor.apply(registry));
|
||||
}
|
||||
|
||||
AbstractObservationObjectPostProcessor(ObjectProvider<ObservationRegistry> observationRegistry,
|
||||
BiFunction<ObservationRegistry, O, O> constructor) {
|
||||
this.observationRegistry = observationRegistry;
|
||||
this.wrapper = constructor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <O1 extends O> O1 postProcess(O1 object) {
|
||||
ObservationRegistry registry = this.observationRegistry.getIfUnique(() -> ObservationRegistry.NOOP);
|
||||
if (registry.isNoop()) {
|
||||
return object;
|
||||
}
|
||||
return (O1) this.wrapper.apply(registry, object);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,87 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.config.annotation.observation.configuration;
|
||||
|
||||
import io.micrometer.observation.ObservationRegistry;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Role;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.ObservationAuthenticationManager;
|
||||
import org.springframework.security.authorization.AuthorizationManager;
|
||||
import org.springframework.security.authorization.ObservationAuthorizationManager;
|
||||
import org.springframework.security.authorization.method.MethodInvocationResult;
|
||||
import org.springframework.security.config.annotation.ObjectPostProcessor;
|
||||
import org.springframework.security.web.FilterChainProxy;
|
||||
import org.springframework.security.web.ObservationFilterChainDecorator;
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
class ObservationConfiguration {
|
||||
|
||||
private final ObjectProvider<ObservationRegistry> observationRegistry;
|
||||
|
||||
ObservationConfiguration(ObjectProvider<ObservationRegistry> observationRegistry) {
|
||||
this.observationRegistry = observationRegistry;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
ObjectPostProcessor<AuthorizationManager<MethodInvocation>> methodAuthorizationManagerPostProcessor() {
|
||||
return new AbstractObservationObjectPostProcessor<>(this.observationRegistry,
|
||||
ObservationAuthorizationManager::new) {
|
||||
};
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
ObjectPostProcessor<AuthorizationManager<MethodInvocationResult>> methodResultAuthorizationManagerPostProcessor() {
|
||||
return new AbstractObservationObjectPostProcessor<>(this.observationRegistry,
|
||||
ObservationAuthorizationManager::new) {
|
||||
};
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
ObjectPostProcessor<AuthorizationManager<HttpServletRequest>> webAuthorizationManagerPostProcessor() {
|
||||
return new AbstractObservationObjectPostProcessor<>(this.observationRegistry,
|
||||
ObservationAuthorizationManager::new) {
|
||||
};
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
ObjectPostProcessor<AuthenticationManager> authenticationManagerPostProcessor() {
|
||||
return new AbstractObservationObjectPostProcessor<>(this.observationRegistry,
|
||||
ObservationAuthenticationManager::new) {
|
||||
};
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
ObjectPostProcessor<FilterChainProxy.FilterChainDecorator> filterChainDecoratorPostProcessor() {
|
||||
return new AbstractObservationObjectPostProcessor<>(this.observationRegistry,
|
||||
ObservationFilterChainDecorator::new) {
|
||||
};
|
||||
}
|
||||
|
||||
}
|
|
@ -1,87 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.config.annotation.observation.configuration;
|
||||
|
||||
import io.micrometer.observation.ObservationRegistry;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Role;
|
||||
import org.springframework.security.authentication.ObservationReactiveAuthenticationManager;
|
||||
import org.springframework.security.authentication.ReactiveAuthenticationManager;
|
||||
import org.springframework.security.authorization.ObservationReactiveAuthorizationManager;
|
||||
import org.springframework.security.authorization.ReactiveAuthorizationManager;
|
||||
import org.springframework.security.authorization.method.MethodInvocationResult;
|
||||
import org.springframework.security.config.annotation.ObjectPostProcessor;
|
||||
import org.springframework.security.web.server.ObservationWebFilterChainDecorator;
|
||||
import org.springframework.security.web.server.WebFilterChainProxy;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
class ReactiveObservationConfiguration {
|
||||
|
||||
private final ObjectProvider<ObservationRegistry> observationRegistry;
|
||||
|
||||
ReactiveObservationConfiguration(ObjectProvider<ObservationRegistry> observationRegistry) {
|
||||
this.observationRegistry = observationRegistry;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
ObjectPostProcessor<ReactiveAuthorizationManager<MethodInvocation>> methodAuthorizationManagerPostProcessor() {
|
||||
return new AbstractObservationObjectPostProcessor<>(this.observationRegistry,
|
||||
ObservationReactiveAuthorizationManager::new) {
|
||||
};
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
ObjectPostProcessor<ReactiveAuthorizationManager<MethodInvocationResult>> methodResultAuthorizationManagerPostProcessor() {
|
||||
return new AbstractObservationObjectPostProcessor<>(this.observationRegistry,
|
||||
ObservationReactiveAuthorizationManager::new) {
|
||||
};
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
ObjectPostProcessor<ReactiveAuthorizationManager<ServerWebExchange>> webAuthorizationManagerPostProcessor() {
|
||||
return new AbstractObservationObjectPostProcessor<>(this.observationRegistry,
|
||||
ObservationReactiveAuthorizationManager::new) {
|
||||
};
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
ObjectPostProcessor<ReactiveAuthenticationManager> authenticationManagerPostProcessor() {
|
||||
return new AbstractObservationObjectPostProcessor<>(this.observationRegistry,
|
||||
ObservationReactiveAuthenticationManager::new) {
|
||||
};
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
ObjectPostProcessor<WebFilterChainProxy.WebFilterChainDecorator> filterChainDecoratorPostProcessor() {
|
||||
return new AbstractObservationObjectPostProcessor<>(this.observationRegistry,
|
||||
ObservationWebFilterChainDecorator::new) {
|
||||
};
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.config.annotation.rsocket;
|
||||
|
||||
import io.micrometer.observation.ObservationRegistry;
|
||||
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Role;
|
||||
import org.springframework.security.authentication.ObservationReactiveAuthenticationManager;
|
||||
import org.springframework.security.authentication.ReactiveAuthenticationManager;
|
||||
import org.springframework.security.authorization.ObservationReactiveAuthorizationManager;
|
||||
import org.springframework.security.authorization.ReactiveAuthorizationManager;
|
||||
import org.springframework.security.config.annotation.ObjectPostProcessor;
|
||||
import org.springframework.security.config.observation.SecurityObservationSettings;
|
||||
import org.springframework.security.web.server.ObservationWebFilterChainDecorator;
|
||||
import org.springframework.security.web.server.WebFilterChainProxy.WebFilterChainDecorator;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
class ReactiveObservationConfiguration {
|
||||
|
||||
private static final SecurityObservationSettings all = SecurityObservationSettings.withDefaults()
|
||||
.shouldObserveRequests(true)
|
||||
.shouldObserveAuthentications(true)
|
||||
.shouldObserveAuthorizations(true)
|
||||
.build();
|
||||
|
||||
@Bean
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
static ObjectPostProcessor<ReactiveAuthorizationManager<ServerWebExchange>> webAuthorizationManagerPostProcessor(
|
||||
ObjectProvider<ObservationRegistry> registry, ObjectProvider<SecurityObservationSettings> predicate) {
|
||||
return new ObjectPostProcessor<>() {
|
||||
@Override
|
||||
public ReactiveAuthorizationManager postProcess(ReactiveAuthorizationManager object) {
|
||||
ObservationRegistry r = registry.getIfUnique(() -> ObservationRegistry.NOOP);
|
||||
boolean active = !r.isNoop() && predicate.getIfUnique(() -> all).shouldObserveAuthorizations();
|
||||
return active ? new ObservationReactiveAuthorizationManager<>(r, object) : object;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
static ObjectPostProcessor<ReactiveAuthenticationManager> authenticationManagerPostProcessor(
|
||||
ObjectProvider<ObservationRegistry> registry, ObjectProvider<SecurityObservationSettings> predicate) {
|
||||
return new ObjectPostProcessor<>() {
|
||||
@Override
|
||||
public ReactiveAuthenticationManager postProcess(ReactiveAuthenticationManager object) {
|
||||
ObservationRegistry r = registry.getIfUnique(() -> ObservationRegistry.NOOP);
|
||||
boolean active = !r.isNoop() && predicate.getIfUnique(() -> all).shouldObserveAuthentications();
|
||||
return active ? new ObservationReactiveAuthenticationManager(r, object) : object;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
static ObjectPostProcessor<WebFilterChainDecorator> filterChainDecoratorPostProcessor(
|
||||
ObjectProvider<ObservationRegistry> registry, ObjectProvider<SecurityObservationSettings> predicate) {
|
||||
return new ObjectPostProcessor<>() {
|
||||
@Override
|
||||
public WebFilterChainDecorator postProcess(WebFilterChainDecorator object) {
|
||||
ObservationRegistry r = registry.getIfUnique(() -> ObservationRegistry.NOOP);
|
||||
boolean active = !r.isNoop() && predicate.getIfUnique(() -> all).shouldObserveRequests();
|
||||
return active ? new ObservationWebFilterChainDecorator(r) : object;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
|
@ -44,8 +44,7 @@ class ReactiveObservationImportSelector implements ImportSelector {
|
|||
if (!observabilityPresent) {
|
||||
return new String[0];
|
||||
}
|
||||
return new String[] {
|
||||
"org.springframework.security.config.annotation.observation.configuration.ReactiveObservationConfiguration" };
|
||||
return new String[] { ReactiveObservationConfiguration.class.getName() };
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.config.annotation.web.configuration;
|
||||
|
||||
import io.micrometer.observation.ObservationRegistry;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Role;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.ObservationAuthenticationManager;
|
||||
import org.springframework.security.authorization.AuthorizationManager;
|
||||
import org.springframework.security.authorization.ObservationAuthorizationManager;
|
||||
import org.springframework.security.config.annotation.ObjectPostProcessor;
|
||||
import org.springframework.security.config.observation.SecurityObservationSettings;
|
||||
import org.springframework.security.web.FilterChainProxy.FilterChainDecorator;
|
||||
import org.springframework.security.web.ObservationFilterChainDecorator;
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
class ObservationConfiguration {
|
||||
|
||||
private static final SecurityObservationSettings all = SecurityObservationSettings.withDefaults()
|
||||
.shouldObserveRequests(true)
|
||||
.shouldObserveAuthentications(true)
|
||||
.shouldObserveAuthorizations(true)
|
||||
.build();
|
||||
|
||||
@Bean
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
static ObjectPostProcessor<AuthorizationManager<HttpServletRequest>> webAuthorizationManagerPostProcessor(
|
||||
ObjectProvider<ObservationRegistry> registry, ObjectProvider<SecurityObservationSettings> predicate) {
|
||||
return new ObjectPostProcessor<>() {
|
||||
@Override
|
||||
public AuthorizationManager postProcess(AuthorizationManager object) {
|
||||
ObservationRegistry r = registry.getIfUnique(() -> ObservationRegistry.NOOP);
|
||||
boolean active = !r.isNoop() && predicate.getIfUnique(() -> all).shouldObserveAuthorizations();
|
||||
return active ? new ObservationAuthorizationManager<>(r, object) : object;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
static ObjectPostProcessor<AuthenticationManager> authenticationManagerPostProcessor(
|
||||
ObjectProvider<ObservationRegistry> registry, ObjectProvider<SecurityObservationSettings> predicate) {
|
||||
return new ObjectPostProcessor<>() {
|
||||
@Override
|
||||
public AuthenticationManager postProcess(AuthenticationManager object) {
|
||||
ObservationRegistry r = registry.getIfUnique(() -> ObservationRegistry.NOOP);
|
||||
boolean active = !r.isNoop() && predicate.getIfUnique(() -> all).shouldObserveAuthentications();
|
||||
return active ? new ObservationAuthenticationManager(r, object) : object;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
static ObjectPostProcessor<FilterChainDecorator> filterChainDecoratorPostProcessor(
|
||||
ObjectProvider<ObservationRegistry> registry, ObjectProvider<SecurityObservationSettings> predicate) {
|
||||
return new ObjectPostProcessor<>() {
|
||||
@Override
|
||||
public FilterChainDecorator postProcess(FilterChainDecorator object) {
|
||||
ObservationRegistry r = registry.getIfUnique(() -> ObservationRegistry.NOOP);
|
||||
boolean active = !r.isNoop() && predicate.getIfUnique(() -> all).shouldObserveRequests();
|
||||
return active ? new ObservationFilterChainDecorator(r) : object;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
|
@ -43,8 +43,7 @@ class ObservationImportSelector implements ImportSelector {
|
|||
if (!observabilityPresent) {
|
||||
return new String[0];
|
||||
}
|
||||
return new String[] {
|
||||
"org.springframework.security.config.annotation.observation.configuration.ObservationConfiguration" };
|
||||
return new String[] { ObservationConfiguration.class.getName() };
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.config.annotation.web.reactive;
|
||||
|
||||
import io.micrometer.observation.ObservationRegistry;
|
||||
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Role;
|
||||
import org.springframework.security.authentication.ObservationReactiveAuthenticationManager;
|
||||
import org.springframework.security.authentication.ReactiveAuthenticationManager;
|
||||
import org.springframework.security.authorization.ObservationReactiveAuthorizationManager;
|
||||
import org.springframework.security.authorization.ReactiveAuthorizationManager;
|
||||
import org.springframework.security.config.annotation.ObjectPostProcessor;
|
||||
import org.springframework.security.config.observation.SecurityObservationSettings;
|
||||
import org.springframework.security.web.server.ObservationWebFilterChainDecorator;
|
||||
import org.springframework.security.web.server.WebFilterChainProxy.WebFilterChainDecorator;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
class ReactiveObservationConfiguration {
|
||||
|
||||
private static final SecurityObservationSettings all = SecurityObservationSettings.withDefaults()
|
||||
.shouldObserveRequests(true)
|
||||
.shouldObserveAuthentications(true)
|
||||
.shouldObserveAuthorizations(true)
|
||||
.build();
|
||||
|
||||
@Bean
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
static ObjectPostProcessor<ReactiveAuthorizationManager<ServerWebExchange>> webAuthorizationManagerPostProcessor(
|
||||
ObjectProvider<ObservationRegistry> registry, ObjectProvider<SecurityObservationSettings> predicate) {
|
||||
return new ObjectPostProcessor<>() {
|
||||
@Override
|
||||
public ReactiveAuthorizationManager postProcess(ReactiveAuthorizationManager object) {
|
||||
ObservationRegistry r = registry.getIfUnique(() -> ObservationRegistry.NOOP);
|
||||
boolean active = !r.isNoop() && predicate.getIfUnique(() -> all).shouldObserveAuthorizations();
|
||||
return active ? new ObservationReactiveAuthorizationManager<>(r, object) : object;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
static ObjectPostProcessor<ReactiveAuthenticationManager> authenticationManagerPostProcessor(
|
||||
ObjectProvider<ObservationRegistry> registry, ObjectProvider<SecurityObservationSettings> predicate) {
|
||||
return new ObjectPostProcessor<>() {
|
||||
@Override
|
||||
public ReactiveAuthenticationManager postProcess(ReactiveAuthenticationManager object) {
|
||||
ObservationRegistry r = registry.getIfUnique(() -> ObservationRegistry.NOOP);
|
||||
boolean active = !r.isNoop() && predicate.getIfUnique(() -> all).shouldObserveAuthentications();
|
||||
return active ? new ObservationReactiveAuthenticationManager(r, object) : object;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
static ObjectPostProcessor<WebFilterChainDecorator> filterChainDecoratorPostProcessor(
|
||||
ObjectProvider<ObservationRegistry> registry, ObjectProvider<SecurityObservationSettings> predicate) {
|
||||
return new ObjectPostProcessor<>() {
|
||||
@Override
|
||||
public WebFilterChainDecorator postProcess(WebFilterChainDecorator object) {
|
||||
ObservationRegistry r = registry.getIfUnique(() -> ObservationRegistry.NOOP);
|
||||
boolean active = !r.isNoop() && predicate.getIfUnique(() -> all).shouldObserveRequests();
|
||||
return active ? new ObservationWebFilterChainDecorator(r) : object;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
|
@ -43,8 +43,7 @@ class ReactiveObservationImportSelector implements ImportSelector {
|
|||
if (!observabilityPresent) {
|
||||
return new String[0];
|
||||
}
|
||||
return new String[] {
|
||||
"org.springframework.security.config.annotation.observation.configuration.ReactiveObservationConfiguration" };
|
||||
return new String[] { ReactiveObservationConfiguration.class.getName() };
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.config.annotation.observation.configuration;
|
||||
package org.springframework.security.config.annotation.web.socket;
|
||||
|
||||
import io.micrometer.observation.ObservationRegistry;
|
||||
|
||||
|
@ -27,22 +27,29 @@ import org.springframework.messaging.Message;
|
|||
import org.springframework.security.authorization.AuthorizationManager;
|
||||
import org.springframework.security.authorization.ObservationAuthorizationManager;
|
||||
import org.springframework.security.config.annotation.ObjectPostProcessor;
|
||||
import org.springframework.security.config.observation.SecurityObservationSettings;
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
class WebSocketObservationConfiguration {
|
||||
|
||||
private final ObjectProvider<ObservationRegistry> observationRegistry;
|
||||
|
||||
WebSocketObservationConfiguration(ObjectProvider<ObservationRegistry> observationRegistry) {
|
||||
this.observationRegistry = observationRegistry;
|
||||
}
|
||||
private static final SecurityObservationSettings all = SecurityObservationSettings.withDefaults()
|
||||
.shouldObserveRequests(true)
|
||||
.shouldObserveAuthentications(true)
|
||||
.shouldObserveAuthorizations(true)
|
||||
.build();
|
||||
|
||||
@Bean
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
ObjectPostProcessor<AuthorizationManager<Message<?>>> messageAuthorizationManagerPostProcessor() {
|
||||
return new AbstractObservationObjectPostProcessor<>(this.observationRegistry,
|
||||
ObservationAuthorizationManager::new) {
|
||||
static ObjectPostProcessor<AuthorizationManager<Message<?>>> webAuthorizationManagerPostProcessor(
|
||||
ObjectProvider<ObservationRegistry> registry, ObjectProvider<SecurityObservationSettings> predicate) {
|
||||
return new ObjectPostProcessor<>() {
|
||||
@Override
|
||||
public AuthorizationManager postProcess(AuthorizationManager object) {
|
||||
ObservationRegistry r = registry.getIfUnique(() -> ObservationRegistry.NOOP);
|
||||
boolean active = !r.isNoop() && predicate.getIfUnique(() -> all).shouldObserveAuthorizations();
|
||||
return active ? new ObservationAuthorizationManager<>(r, object) : object;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
@ -43,8 +43,7 @@ class WebSocketObservationImportSelector implements ImportSelector {
|
|||
if (!observabilityPresent) {
|
||||
return new String[0];
|
||||
}
|
||||
return new String[] {
|
||||
"org.springframework.security.config.annotation.observation.configuration.WebSocketObservationConfiguration" };
|
||||
return new String[] { WebSocketObservationConfiguration.class.getName() };
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.config.observation;
|
||||
|
||||
import io.micrometer.observation.ObservationPredicate;
|
||||
|
||||
/**
|
||||
* An {@link ObservationPredicate} that can be used to change which Spring Security
|
||||
* observations are made with Micrometer.
|
||||
*
|
||||
* <p>
|
||||
* By default, web requests are not observed and authentications and authorizations are
|
||||
* observed.
|
||||
*
|
||||
* @author Josh Cummings
|
||||
* @since 6.4
|
||||
*/
|
||||
public final class SecurityObservationSettings {
|
||||
|
||||
private final boolean observeRequests;
|
||||
|
||||
private final boolean observeAuthentications;
|
||||
|
||||
private final boolean observeAuthorizations;
|
||||
|
||||
private SecurityObservationSettings(boolean observeRequests, boolean observeAuthentications,
|
||||
boolean observeAuthorizations) {
|
||||
this.observeRequests = observeRequests;
|
||||
this.observeAuthentications = observeAuthentications;
|
||||
this.observeAuthorizations = observeAuthorizations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make no Spring Security observations
|
||||
* @return a {@link SecurityObservationSettings} with all exclusions turned on
|
||||
*/
|
||||
public static SecurityObservationSettings noObservations() {
|
||||
return new SecurityObservationSettings(false, false, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Begin the configuration of a {@link SecurityObservationSettings}
|
||||
* @return a {@link Builder} where filter chain observations are off and authn/authz
|
||||
* observations are on
|
||||
*/
|
||||
public static Builder withDefaults() {
|
||||
return new Builder(false, true, true);
|
||||
}
|
||||
|
||||
public boolean shouldObserveRequests() {
|
||||
return this.observeRequests;
|
||||
}
|
||||
|
||||
public boolean shouldObserveAuthentications() {
|
||||
return this.observeAuthentications;
|
||||
}
|
||||
|
||||
public boolean shouldObserveAuthorizations() {
|
||||
return this.observeAuthorizations;
|
||||
}
|
||||
|
||||
/**
|
||||
* A builder for configuring a {@link SecurityObservationSettings}
|
||||
*/
|
||||
public static final class Builder {
|
||||
|
||||
private boolean observeRequests;
|
||||
|
||||
private boolean observeAuthentications;
|
||||
|
||||
private boolean observeAuthorizations;
|
||||
|
||||
Builder(boolean observeRequests, boolean observeAuthentications, boolean observeAuthorizations) {
|
||||
this.observeRequests = observeRequests;
|
||||
this.observeAuthentications = observeAuthentications;
|
||||
this.observeAuthorizations = observeAuthorizations;
|
||||
}
|
||||
|
||||
public Builder shouldObserveRequests(boolean excludeFilters) {
|
||||
this.observeRequests = excludeFilters;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder shouldObserveAuthentications(boolean excludeAuthentications) {
|
||||
this.observeAuthentications = excludeAuthentications;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder shouldObserveAuthorizations(boolean excludeAuthorizations) {
|
||||
this.observeAuthorizations = excludeAuthorizations;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SecurityObservationSettings build() {
|
||||
return new SecurityObservationSettings(this.observeRequests, this.observeAuthentications,
|
||||
this.observeAuthorizations);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -87,6 +87,7 @@ import org.springframework.security.authorization.method.PrePostTemplateDefaults
|
|||
import org.springframework.security.config.Customizer;
|
||||
import org.springframework.security.config.annotation.SecurityContextChangedListenerConfig;
|
||||
import org.springframework.security.config.core.GrantedAuthorityDefaults;
|
||||
import org.springframework.security.config.observation.SecurityObservationSettings;
|
||||
import org.springframework.security.config.test.SpringTestContext;
|
||||
import org.springframework.security.config.test.SpringTestContextExtension;
|
||||
import org.springframework.security.config.test.SpringTestParentApplicationContextExecutionListener;
|
||||
|
@ -114,6 +115,7 @@ import static org.mockito.Mockito.never;
|
|||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
|
||||
/**
|
||||
* Tests for {@link PrePostMethodSecurityConfiguration}.
|
||||
|
@ -1062,6 +1064,43 @@ public class PrePostMethodSecurityConfigurationTests {
|
|||
verify(handler).onError(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockUser
|
||||
public void prePostMethodWhenExcludeAuthorizationObservationsThenUnobserved() {
|
||||
this.spring
|
||||
.register(MethodSecurityServiceEnabledConfig.class, ObservationRegistryConfig.class,
|
||||
SelectableObservationsConfig.class)
|
||||
.autowire();
|
||||
this.methodSecurityService.preAuthorizePermitAll();
|
||||
ObservationHandler<?> handler = this.spring.getContext().getBean(ObservationHandler.class);
|
||||
assertThatExceptionOfType(AccessDeniedException.class).isThrownBy(this.methodSecurityService::preAuthorize);
|
||||
verifyNoInteractions(handler);
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockUser
|
||||
public void securedMethodWhenExcludeAuthorizationObservationsThenUnobserved() {
|
||||
this.spring
|
||||
.register(MethodSecurityServiceEnabledConfig.class, ObservationRegistryConfig.class,
|
||||
SelectableObservationsConfig.class)
|
||||
.autowire();
|
||||
this.methodSecurityService.securedUser();
|
||||
ObservationHandler<?> handler = this.spring.getContext().getBean(ObservationHandler.class);
|
||||
verifyNoInteractions(handler);
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockUser
|
||||
public void jsr250MethodWhenExcludeAuthorizationObservationsThenUnobserved() {
|
||||
this.spring
|
||||
.register(MethodSecurityServiceEnabledConfig.class, ObservationRegistryConfig.class,
|
||||
SelectableObservationsConfig.class)
|
||||
.autowire();
|
||||
this.methodSecurityService.jsr250RolesAllowedUser();
|
||||
ObservationHandler<?> handler = this.spring.getContext().getBean(ObservationHandler.class);
|
||||
verifyNoInteractions(handler);
|
||||
}
|
||||
|
||||
private static Consumer<ConfigurableWebApplicationContext> disallowBeanOverriding() {
|
||||
return (context) -> ((AnnotationConfigWebApplicationContext) context).setAllowBeanDefinitionOverriding(false);
|
||||
}
|
||||
|
@ -1742,4 +1781,14 @@ public class PrePostMethodSecurityConfigurationTests {
|
|||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class SelectableObservationsConfig {
|
||||
|
||||
@Bean
|
||||
SecurityObservationSettings observabilityDefaults() {
|
||||
return SecurityObservationSettings.withDefaults().shouldObserveAuthorizations(false).build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -33,9 +33,11 @@ import reactor.core.publisher.Flux;
|
|||
import reactor.core.publisher.Mono;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Role;
|
||||
|
@ -55,6 +57,7 @@ import org.springframework.security.authorization.method.AuthorizeReturnObject;
|
|||
import org.springframework.security.authorization.method.MethodAuthorizationDeniedHandler;
|
||||
import org.springframework.security.config.Customizer;
|
||||
import org.springframework.security.config.core.GrantedAuthorityDefaults;
|
||||
import org.springframework.security.config.observation.SecurityObservationSettings;
|
||||
import org.springframework.security.config.test.SpringTestContext;
|
||||
import org.springframework.security.config.test.SpringTestContextExtension;
|
||||
import org.springframework.security.core.Authentication;
|
||||
|
@ -69,6 +72,7 @@ import static org.mockito.Mockito.mock;
|
|||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
|
||||
/**
|
||||
* @author Tadaya Tsuyukubo
|
||||
|
@ -260,6 +264,27 @@ public class ReactiveMethodSecurityConfigurationTests {
|
|||
verify(handler).onError(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockUser
|
||||
public void prePostMethodWhenExcludeAuthorizationObservationsThenUnobserved() {
|
||||
this.spring
|
||||
.register(MethodSecurityServiceConfig.class, ObservationRegistryConfig.class,
|
||||
SelectableObservationsConfig.class)
|
||||
.autowire();
|
||||
ReactiveMethodSecurityService service = this.spring.getContext().getBean(ReactiveMethodSecurityService.class);
|
||||
Authentication user = TestAuthentication.authenticatedUser();
|
||||
StepVerifier
|
||||
.create(service.preAuthorizeUser().contextWrite(ReactiveSecurityContextHolder.withAuthentication(user)))
|
||||
.expectNextCount(1)
|
||||
.verifyComplete();
|
||||
ObservationHandler<?> handler = this.spring.getContext().getBean(ObservationHandler.class);
|
||||
StepVerifier
|
||||
.create(service.preAuthorizeAdmin().contextWrite(ReactiveSecurityContextHolder.withAuthentication(user)))
|
||||
.expectError()
|
||||
.verify();
|
||||
verifyNoInteractions(handler);
|
||||
}
|
||||
|
||||
private static Consumer<User.UserBuilder> authorities(String... authorities) {
|
||||
return (builder) -> builder.authorities(authorities);
|
||||
}
|
||||
|
@ -432,9 +457,37 @@ public class ReactiveMethodSecurityConfigurationTests {
|
|||
}
|
||||
|
||||
@Bean
|
||||
PrePostMethodSecurityConfigurationTests.ObservationRegistryPostProcessor observationRegistryPostProcessor(
|
||||
ObservationRegistryPostProcessor observationRegistryPostProcessor(
|
||||
ObjectProvider<ObservationHandler<Observation.Context>> handler) {
|
||||
return new PrePostMethodSecurityConfigurationTests.ObservationRegistryPostProcessor(handler);
|
||||
return new ObservationRegistryPostProcessor(handler);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class ObservationRegistryPostProcessor implements BeanPostProcessor {
|
||||
|
||||
private final ObjectProvider<ObservationHandler<Observation.Context>> handler;
|
||||
|
||||
ObservationRegistryPostProcessor(ObjectProvider<ObservationHandler<Observation.Context>> handler) {
|
||||
this.handler = handler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
|
||||
if (bean instanceof ObservationRegistry registry) {
|
||||
registry.observationConfig().observationHandler(this.handler.getObject());
|
||||
}
|
||||
return bean;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class SelectableObservationsConfig {
|
||||
|
||||
@Bean
|
||||
SecurityObservationSettings observabilityDefaults() {
|
||||
return SecurityObservationSettings.withDefaults().shouldObserveAuthorizations(false).build();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -47,6 +47,7 @@ import org.springframework.security.config.annotation.web.AbstractRequestMatcher
|
|||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.core.GrantedAuthorityDefaults;
|
||||
import org.springframework.security.config.observation.SecurityObservationSettings;
|
||||
import org.springframework.security.config.test.SpringTestContext;
|
||||
import org.springframework.security.config.test.SpringTestContextExtension;
|
||||
import org.springframework.security.core.Authentication;
|
||||
|
@ -80,6 +81,7 @@ import static org.mockito.Mockito.atLeastOnce;
|
|||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
import static org.springframework.security.config.Customizer.withDefaults;
|
||||
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.authentication;
|
||||
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
|
||||
|
@ -650,6 +652,18 @@ public class AuthorizeHttpRequestsConfigurerTests {
|
|||
verify(handler).onError(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenExcludeAuthorizationObservationsThenUnobserved() throws Exception {
|
||||
this.spring
|
||||
.register(RoleUserConfig.class, BasicController.class, ObservationRegistryConfig.class,
|
||||
SelectableObservationsConfig.class)
|
||||
.autowire();
|
||||
ObservationHandler<Observation.Context> handler = this.spring.getContext().getBean(ObservationHandler.class);
|
||||
this.mvc.perform(get("/").with(user("user").roles("USER"))).andExpect(status().isOk());
|
||||
this.mvc.perform(get("/").with(user("user").roles("WRONG"))).andExpect(status().isForbidden());
|
||||
verifyNoInteractions(handler);
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
static class GrantedAuthorityDefaultHasRoleConfig {
|
||||
|
@ -1288,4 +1302,14 @@ public class AuthorizeHttpRequestsConfigurerTests {
|
|||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class SelectableObservationsConfig {
|
||||
|
||||
@Bean
|
||||
SecurityObservationSettings observabilityDefaults() {
|
||||
return SecurityObservationSettings.withDefaults().shouldObserveAuthorizations(false).build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@ import org.springframework.security.config.annotation.ObjectPostProcessor;
|
|||
import org.springframework.security.config.annotation.SecurityContextChangedListenerConfig;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.observation.SecurityObservationSettings;
|
||||
import org.springframework.security.config.test.SpringTestContext;
|
||||
import org.springframework.security.config.test.SpringTestContextExtension;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
|
@ -63,6 +64,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.atLeastOnce;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.springframework.security.config.Customizer.withDefaults;
|
||||
|
@ -189,6 +191,26 @@ public class HttpBasicConfigurerTests {
|
|||
assertThat(context.getValue()).isInstanceOf(AuthenticationObservationContext.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void httpBasicWhenExcludeAuthenticationObservationsThenUnobserved() throws Exception {
|
||||
this.spring
|
||||
.register(HttpBasic.class, Users.class, Home.class, ObservationRegistryConfig.class,
|
||||
SelectableObservationsConfig.class)
|
||||
.autowire();
|
||||
ObservationHandler<Observation.Context> handler = this.spring.getContext().getBean(ObservationHandler.class);
|
||||
this.mvc.perform(get("/").with(httpBasic("user", "password")))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string("user"));
|
||||
ArgumentCaptor<Observation.Context> context = ArgumentCaptor.forClass(Observation.Context.class);
|
||||
verify(handler, atLeastOnce()).onStart(context.capture());
|
||||
assertThat(context.getAllValues()).noneMatch((c) -> c instanceof AuthenticationObservationContext);
|
||||
context = ArgumentCaptor.forClass(Observation.Context.class);
|
||||
verify(handler, atLeastOnce()).onStop(context.capture());
|
||||
assertThat(context.getAllValues()).noneMatch((c) -> c instanceof AuthenticationObservationContext);
|
||||
this.mvc.perform(get("/").with(httpBasic("user", "wrong"))).andExpect(status().isUnauthorized());
|
||||
verify(handler, never()).onError(any());
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
static class ObjectPostProcessorConfig {
|
||||
|
@ -455,4 +477,14 @@ public class HttpBasicConfigurerTests {
|
|||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class SelectableObservationsConfig {
|
||||
|
||||
@Bean
|
||||
SecurityObservationSettings observabilityDefaults() {
|
||||
return SecurityObservationSettings.withDefaults().shouldObserveAuthentications(false).build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -69,6 +69,7 @@ import org.springframework.security.authorization.AuthorizationDecision;
|
|||
import org.springframework.security.authorization.AuthorizationManager;
|
||||
import org.springframework.security.config.annotation.SecurityContextChangedListenerConfig;
|
||||
import org.springframework.security.config.annotation.web.messaging.MessageSecurityMetadataSourceRegistry;
|
||||
import org.springframework.security.config.observation.SecurityObservationSettings;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.annotation.AnnotationTemplateExpressionDefaults;
|
||||
import org.springframework.security.core.annotation.AuthenticationPrincipal;
|
||||
|
@ -106,6 +107,7 @@ import static org.mockito.ArgumentMatchers.any;
|
|||
import static org.mockito.Mockito.atLeastOnce;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
import static org.springframework.security.web.csrf.CsrfTokenAssert.assertThatCsrfToken;
|
||||
|
||||
public class WebSocketMessageBrokerSecurityConfigurationTests {
|
||||
|
@ -414,6 +416,28 @@ public class WebSocketMessageBrokerSecurityConfigurationTests {
|
|||
verify(observationHandler).onError(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sendMessageWhenExcludeAuthorizationObservationsThenUnobserved() {
|
||||
loadConfig(WebSocketSecurityConfig.class, ObservationRegistryConfig.class, SelectableObservationsConfig.class);
|
||||
SimpMessageHeaderAccessor headers = SimpMessageHeaderAccessor.create(SimpMessageType.CONNECT);
|
||||
headers.setNativeHeader(this.token.getHeaderName(), XOR_CSRF_TOKEN_VALUE);
|
||||
Message<?> message = message(headers, "/authenticated");
|
||||
headers.getSessionAttributes().put(CsrfToken.class.getName(), this.token);
|
||||
clientInboundChannel().send(message);
|
||||
ObservationHandler<Observation.Context> observationHandler = this.context.getBean(ObservationHandler.class);
|
||||
headers = SimpMessageHeaderAccessor.create(SimpMessageType.CONNECT);
|
||||
headers.setNativeHeader(this.token.getHeaderName(), XOR_CSRF_TOKEN_VALUE);
|
||||
message = message(headers, "/denyAll");
|
||||
headers.getSessionAttributes().put(CsrfToken.class.getName(), this.token);
|
||||
try {
|
||||
clientInboundChannel().send(message);
|
||||
}
|
||||
catch (MessageDeliveryException ex) {
|
||||
// okay
|
||||
}
|
||||
verifyNoInteractions(observationHandler);
|
||||
}
|
||||
|
||||
private void assertHandshake(HttpServletRequest request) {
|
||||
TestHandshakeHandler handshakeHandler = this.context.getBean(TestHandshakeHandler.class);
|
||||
assertThatCsrfToken(handshakeHandler.attributes.get(CsrfToken.class.getName())).isEqualTo(this.token);
|
||||
|
@ -968,4 +992,14 @@ public class WebSocketMessageBrokerSecurityConfigurationTests {
|
|||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class SelectableObservationsConfig {
|
||||
|
||||
@Bean
|
||||
SecurityObservationSettings observabilityDefaults() {
|
||||
return SecurityObservationSettings.withDefaults().shouldObserveAuthorizations(false).build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.config.observation;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link SecurityObservationSettings}
|
||||
*/
|
||||
public class SecurityObservationSettingsTests {
|
||||
|
||||
@Test
|
||||
void withDefaultsThenFilterOffAuthenticationOnAuthorizationOn() {
|
||||
SecurityObservationSettings defaults = SecurityObservationSettings.withDefaults().build();
|
||||
assertThat(defaults.shouldObserveRequests()).isFalse();
|
||||
assertThat(defaults.shouldObserveAuthentications()).isTrue();
|
||||
assertThat(defaults.shouldObserveAuthorizations()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void noObservationsWhenConstructedThenAllOff() {
|
||||
SecurityObservationSettings defaults = SecurityObservationSettings.noObservations();
|
||||
assertThat(defaults.shouldObserveRequests()).isFalse();
|
||||
assertThat(defaults.shouldObserveAuthentications()).isFalse();
|
||||
assertThat(defaults.shouldObserveAuthorizations()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void withDefaultsWhenExclusionsThenInstanceReflects() {
|
||||
SecurityObservationSettings defaults = SecurityObservationSettings.withDefaults()
|
||||
.shouldObserveAuthentications(false)
|
||||
.shouldObserveAuthorizations(false)
|
||||
.shouldObserveRequests(true)
|
||||
.build();
|
||||
assertThat(defaults.shouldObserveRequests()).isTrue();
|
||||
assertThat(defaults.shouldObserveAuthentications()).isFalse();
|
||||
assertThat(defaults.shouldObserveAuthorizations()).isFalse();
|
||||
}
|
||||
|
||||
}
|
|
@ -187,7 +187,7 @@ Xml::
|
|||
If you don't want any Spring Security observations, in a Spring Boot application you can publish a `ObservationRegistry.NOOP` `@Bean`.
|
||||
However, this may turn off observations for more than just Spring Security.
|
||||
|
||||
Instead, you can alter the provided `ObservationRegistry` with an `ObservationPredicate` like the following:
|
||||
Instead, you can publish a `SecurityObservationSettings` like the following:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
|
@ -196,9 +196,8 @@ Java::
|
|||
[source,java,role="primary"]
|
||||
----
|
||||
@Bean
|
||||
ObservationRegistryCustomizer<ObservationRegistry> noSpringSecurityObservations() {
|
||||
ObservationPredicate predicate = (name, context) -> !name.startsWith("spring.security.");
|
||||
return (registry) -> registry.observationConfig().observationPredicate(predicate);
|
||||
SecurityObservationSettings noSpringSecurityObservations() {
|
||||
return SecurityObservationSettings.noObservations();
|
||||
}
|
||||
----
|
||||
|
||||
|
@ -207,17 +206,77 @@ Kotlin::
|
|||
[source,kotlin,role="secondary"]
|
||||
----
|
||||
@Bean
|
||||
fun noSpringSecurityObservations(): ObservationRegistryCustomizer<ObservationRegistry> {
|
||||
ObservationPredicate predicate = (name: String, context: Observation.Context) -> !name.startsWith("spring.security.")
|
||||
(registry: ObservationRegistry) -> registry.observationConfig().observationPredicate(predicate)
|
||||
fun noSpringSecurityObservations(): SecurityObservationSettings {
|
||||
return SecurityObservationSettings.noObservations()
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
and then Spring Security will not wrap any filter chains, authentications, or authorizations in their `ObservationXXX` counterparts.
|
||||
|
||||
[TIP]
|
||||
There is no facility for disabling observations with XML support.
|
||||
Instead, simply do not set the `observation-registry-ref` attribute.
|
||||
|
||||
You can also disable security for only a subset of Security's observations.
|
||||
For example, the `SecurityObservationSettings` bean excludes the filter chain observations by default.
|
||||
So, you can also do:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,role="primary"]
|
||||
----
|
||||
@Bean
|
||||
SecurityObservationSettings defaultSpringSecurityObservations() {
|
||||
return SecurityObservationSettings.withDefaults().build();
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,role="secondary"]
|
||||
----
|
||||
@Bean
|
||||
fun defaultSpringSecurityObservations(): SecurityObservationSettings {
|
||||
return SecurityObservationSettings.withDefaults().build()
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
Or you can turn on and off observations individually, based on the defaults:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,role="primary"]
|
||||
----
|
||||
@Bean
|
||||
SecurityObservationSettings allSpringSecurityObservations() {
|
||||
return SecurityObservationSettings.withDefaults()
|
||||
.shouldObserveFilterChains(true).build();
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,role="secondary"]
|
||||
----
|
||||
@Bean
|
||||
fun allSpringSecurityObservations(): SecurityObservationSettings {
|
||||
return SecurityObservabilityDefaults.builder()
|
||||
.shouldObserveFilterChains(true).build()
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
[NOTE]
|
||||
=====
|
||||
For backward compatibility, all Spring Security observations are made unless a `SecurityObservationSettings` is published.
|
||||
=====
|
||||
|
||||
[[webflux-observability-tracing-listing]]
|
||||
=== Trace Listing
|
||||
|
||||
|
|
|
@ -192,7 +192,7 @@ Xml::
|
|||
If you don't want any Spring Security observations, in a Spring Boot application you can publish a `ObservationRegistry.NOOP` `@Bean`.
|
||||
However, this may turn off observations for more than just Spring Security.
|
||||
|
||||
Instead, you can alter the provided `ObservationRegistry` with an `ObservationPredicate` like the following:
|
||||
Instead, you can publish a `SecurityObservationSettings` like the following:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
|
@ -201,9 +201,8 @@ Java::
|
|||
[source,java,role="primary"]
|
||||
----
|
||||
@Bean
|
||||
ObservationRegistryCustomizer<ObservationRegistry> noSpringSecurityObservations() {
|
||||
ObservationPredicate predicate = (name, context) -> !name.startsWith("spring.security.");
|
||||
return (registry) -> registry.observationConfig().observationPredicate(predicate);
|
||||
SecurityObservationSettings noSpringSecurityObservations() {
|
||||
return SecurityObservationSettings.noObservations();
|
||||
}
|
||||
----
|
||||
|
||||
|
@ -212,21 +211,77 @@ Kotlin::
|
|||
[source,kotlin,role="secondary"]
|
||||
----
|
||||
@Bean
|
||||
fun noSpringSecurityObservations(): ObservationRegistryCustomizer<ObservationRegistry> {
|
||||
val predicate = ObservationPredicate { name: String, _: Observation.Context? ->
|
||||
!name.startsWith("spring.security.")
|
||||
}
|
||||
return ObservationRegistryCustomizer { registry: ObservationRegistry ->
|
||||
registry.observationConfig().observationPredicate(predicate)
|
||||
}
|
||||
fun noSpringSecurityObservations(): SecurityObservationSettings {
|
||||
return SecurityObservationSettings.noObservations()
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
and then Spring Security will not wrap any filter chains, authentications, or authorizations in their `ObservationXXX` counterparts.
|
||||
|
||||
[TIP]
|
||||
There is no facility for disabling observations with XML support.
|
||||
Instead, simply do not set the `observation-registry-ref` attribute.
|
||||
|
||||
You can also disable security for only a subset of Security's observations.
|
||||
For example, the `SecurityObservationSettings` bean excludes the filter chain observations by default.
|
||||
So, you can also do:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,role="primary"]
|
||||
----
|
||||
@Bean
|
||||
SecurityObservationSettings defaultSpringSecurityObservations() {
|
||||
return SecurityObservationSettings.withDefaults().build();
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,role="secondary"]
|
||||
----
|
||||
@Bean
|
||||
fun defaultSpringSecurityObservations(): SecurityObservationSettings {
|
||||
return SecurityObservationSettings.withDefaults().build()
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
Or you can turn on and off observations individually, based on the defaults:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,role="primary"]
|
||||
----
|
||||
@Bean
|
||||
SecurityObservationSettings allSpringSecurityObservations() {
|
||||
return SecurityObservationSettings.withDefaults()
|
||||
.shouldObserveFilterChains(true).build();
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,role="secondary"]
|
||||
----
|
||||
@Bean
|
||||
fun allSpringSecurityObservations(): SecurityObservationSettings {
|
||||
return SecurityObservationSettings.builder()
|
||||
.shouldObserveFilterChains(true).build()
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
[NOTE]
|
||||
=====
|
||||
For backward compatibility, the all Spring Security observations are made unless a `SecurityObservationSettings` is published.
|
||||
=====
|
||||
|
||||
[[observability-tracing-listing]]
|
||||
=== Trace Listing
|
||||
|
||||
|
|
Loading…
Reference in New Issue