INT-2166: Add SecurityContext Propagation
JIRA: https://jira.spring.io/browse/INT-2166 * Introduce `ThreadStatePropagationChannelInterceptor` based on the `ExecutorChannelInterceptor` * Add `SecurityContextPropagationChannelInterceptor`,`SecurityContextCleanupChannelInterceptor` * Introduce `AbstractExecutorChannel` to utilize `ExecutorChannelInterceptor` logic * Introduce `MessageHandlingTaskDecorator` to avoid package tangle from `dispatcher` and `channel` * Introduce `SecurityContextCleanupAdvice` for those cases when we don't get deal with `MessageChannel`s already, but want to have proper way to cleanup `SecurityContext` * Make `GlobalChannelInterceptorProcessor` as `SmartInitializingSingleton` to avoid `phase` conflicts. * Fix `MessagingAnnotationPostProcessor` to use `beanFactory.initializeBean(endpoint, endpointBeanName);` instead of manual `start()` invocation bypassing the `phase` logic, hence having a bug, when endpoints have been started very early * Optimise `AbstractPollableChannel` to use `size` field from `ChannelInterceptorList` instead of `size()` from `Collection<?>` * Fix `AnnotatedEndpointActivationTests` extracting separate component for annotation configuration instead of using test class directly. This caused very late Messaging Annotations process on that class * Fix typo in the `spring-integration-jdbc-4.2.xsd` * Remove some `SOUT`s throughout the project TODO Docs PR Comments: * Remove redundant `AbstractExecutorChannel#executorInterceptors` and make logic based on the `super.interceptors` * Fix wrong imports order * JavaDocs for `ThreadStatePropagationChannelInterceptor` * Docs for `SecurityContext` propagation INT-3593: Fix FTP PartialSuccess Tests JIRA: https://jira.spring.io/browse/INT-3593 Sort the files for the MPUT tests. INT-2166: Add SecurityContext Propagation JIRA: https://jira.spring.io/browse/INT-2166 * Introduce `ThreadStatePropagationChannelInterceptor` based on the `ExecutorChannelInterceptor` * Add `SecurityContextPropagationChannelInterceptor`,`SecurityContextCleanupChannelInterceptor` * Introduce `AbstractExecutorChannel` to utilize `ExecutorChannelInterceptor` logic * Introduce `MessageHandlingTaskDecorator` to avoid package tangle from `dispatcher` and `channel` * Introduce `SecurityContextCleanupAdvice` for those cases when we don't get deal with `MessageChannel`s already, but want to have proper way to cleanup `SecurityContext` * Make `GlobalChannelInterceptorProcessor` as `SmartInitializingSingleton` to avoid `phase` conflicts. * Fix `MessagingAnnotationPostProcessor` to use `beanFactory.initializeBean(endpoint, endpointBeanName);` instead of manual `start()` invocation bypassing the `phase` logic, hence having a bug, when endpoints have been started very early * Optimise `AbstractPollableChannel` to use `size` field from `ChannelInterceptorList` instead of `size()` from `Collection<?>` * Fix `AnnotatedEndpointActivationTests` extracting separate component for annotation configuration instead of using test class directly. This caused very late Messaging Annotations process on that class * Fix typo in the `spring-integration-jdbc-4.2.xsd` * Remove some `SOUT`s throughout the project TODO Docs PR Comments: * Remove redundant `AbstractExecutorChannel#executorInterceptors` and make logic based on the `super.interceptors` * Fix wrong imports order * JavaDocs for `ThreadStatePropagationChannelInterceptor` * Docs for `SecurityContext` propagation Doc Polishing Address PR comments Address PR comments * Extract `ExecutorChannelInterceptor` logic in the `PollingConsumer` to have an ability to invoke `afterMessageHandled()` on the TaskScheduler's Thread for example for the `SecurityContext` clean up * Get rid of all that redundant "clean up" stuff * Docs polishing Fix `NPE` in the `PollingConsumer` Introduce `ExecutorChannelInterceptorAware` to avoid iterators on each message Polishing; Docs, Sonar
This commit is contained in:
committed by
Gary Russell
parent
fd35d43aba
commit
09fb4f78c9
@@ -4,7 +4,16 @@
|
||||
[[security-intro]]
|
||||
=== Introduction
|
||||
|
||||
Spring Integration builds upon the http://static.springframework.org/spring-security/site/[Spring Security project] to enable role based security checks to be applied to channel send and receive invocations.
|
||||
Security is one of the important functions in any modern enterprise (or cloud) application,
|
||||
moreover it is critical for distributed systems, such as those built using Enterprise
|
||||
Integration Patterns.
|
||||
Messaging independence and loosely-coupling allow target systems to communicate with each other
|
||||
with any type of data in the message's `payload`.
|
||||
We can either trust all those messages or _secure_ our service against "infecting" messages.
|
||||
|
||||
Spring Integration together with
|
||||
http://projects.spring.io/spring-security/[Spring Security] provide a simple and comprehensive way to
|
||||
secure message channels, as well as other part of the integration solution.
|
||||
|
||||
[[securing-channels]]
|
||||
=== Securing channels
|
||||
@@ -70,7 +79,7 @@ With the `@SecuredChannel` annotation, the Java configuration variant of the XML
|
||||
@EnableIntegration
|
||||
public class ContextConfiguration {
|
||||
|
||||
@Bean
|
||||
@Bean
|
||||
@SecuredChannel(interceptor = "channelSecurityInterceptor", sendAccess = "ROLE_ADMIN")
|
||||
public SubscribableChannel adminChannel() {
|
||||
return new DirectChannel();
|
||||
@@ -93,3 +102,60 @@ public class ContextConfiguration {
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
[[security-context-propagation]]
|
||||
=== SecurityContext Propagation
|
||||
|
||||
To be sure that our interaction with the application is secure, according to its security system rules, we should supply
|
||||
some _security context_ with an _authentication_ (principal) object.
|
||||
The Spring Security project provides a flexible, canonical mechanism to authenticate our application clients
|
||||
over HTTP, WebSocket or SOAP protocols (as can be done for any other integration protocol
|
||||
with a simple Spring Security extension) and it provides a `SecurityContext` for further authorization checks on the
|
||||
application objects, such as message channels.
|
||||
By default, the `SecurityContext` is tied with the current `Thread` 's execution state using the
|
||||
(`ThreadLocalSecurityContextHolderStrategy`).
|
||||
It is accessed by an AOP interceptor on secured methods to check if that `principal` of the invocation has
|
||||
sufficent permissions to call that method, for example.
|
||||
This works well with the current thread, but often, processing logic can be performed on another thread or even
|
||||
on several threads, or on to some external system(s).
|
||||
|
||||
Standard thread-bound behavior is easy to configure if our application is built on the Spring Integration components
|
||||
and its message channels.
|
||||
In this case, the secured objects may be any service activator or transformer, secured with a
|
||||
`MethodSecurityInterceptor` in their `<request-handler-advice-chain>` (see <<message-handler-advice-chain>>)
|
||||
or even `MessageChannel` (see <<securing-channels>> above).
|
||||
When using `DirectChannel` communication, the `SecurityContext` is available
|
||||
automatically, because the downstream flow runs on the current thread.
|
||||
But in case of the `QueueChannel`, `ExecutorChannel` and `PublishSubscribeChannel` with an `Executor`, messages are
|
||||
transferred from one thread to another (or several) by the nature of those channels.
|
||||
In order to support such scenarios,
|
||||
we can either transfer an `Authentication` object within the message headers and extract and authenticate it on the
|
||||
other side before secured object access.
|
||||
Or, we can _propagate_ the `SecurityContext` to the thread receiving the transferred message.
|
||||
|
||||
Starting with _version 4.2_ `SecurityContext` propagation has been introduced.
|
||||
It is implemented as a `SecurityContextPropagationChannelInterceptor`, which can simply be added to any `MessageChannel`
|
||||
or configured as a `@GlobalChannelInterceptor`.
|
||||
The logic of this interceptor is based on the `SecurityContext` extraction from the current thread from the `preSend()`
|
||||
method, and its populating to another thread from the `postReceive()` (`beforeHandle()`) method.
|
||||
Actually, this interceptor is an extension of the more generic `ThreadStatePropagationChannelInterceptor`, which wraps
|
||||
the message-to-send together with the state-to-propagate in an internal `Message<?>` extension -
|
||||
`MessageWithThreadState<S>`, - on one side and extracts the original message back and state-to-propagate on another.
|
||||
The `ThreadStatePropagationChannelInterceptor` can be extended for any context propagation use-case and
|
||||
`SecurityContextPropagationChannelInterceptor` is a good sample on the matter.
|
||||
|
||||
IMPORTANT: Since the logic of the `ThreadStatePropagationChannelInterceptor` is based on message modification
|
||||
(it returns an internal `MessageWithThreadState` object to send), you should be careful when combining this
|
||||
interceptor with any other which is intended to modify messages too, e.g. through the
|
||||
`MessageBuilder.withPayload(...)...build()` - the state-to-propagate may be lost.
|
||||
In most cases to overcome the issue, it's sufficient to order interceptors for the channel and ensure the
|
||||
`ThreadStatePropagationChannelInterceptor` is the last one in the stack.
|
||||
|
||||
Propagation and population of `SecurityContext` is just one half of the work.
|
||||
Since the message isn't an owner of the threads in the message flow and we should be sure that we are secure against
|
||||
any incoming messages, we have to _clean up_ the `SecurityContext` from `ThreadLocal`.
|
||||
The `SecurityContextPropagationChannelInterceptor` provides `afterMessageHandled()` interceptor's method
|
||||
implementation to do the clean up operation to free the Thread in the end of invocation from that propagated principal.
|
||||
This means that, when the thread that processes the handed-off message, completes the processing of the message
|
||||
(successfully or otherwise), the context is cleared so that it can't be inadvertently be used when processing another
|
||||
message.
|
||||
|
||||
@@ -19,7 +19,7 @@ However, this has some important implications for (some) user environments.
|
||||
For complete details, see <<metrics-management>> and <<jmx-42-improvements>>.
|
||||
|
||||
[[x4.2-mongodb-metadata-store]]
|
||||
==== MongodDB Metadata Store
|
||||
==== MongoDB Metadata Store
|
||||
|
||||
The `MongoDbMetadataStore` is now available. For more information, see <<mongodb-metadata-store>>.
|
||||
|
||||
@@ -29,6 +29,13 @@ The `MongoDbMetadataStore` is now available. For more information, see <<mongodb
|
||||
The `@SecuredChannel` annotation has been introduced, replacing the deprecated `ChannelSecurityInterceptorFactoryBean`.
|
||||
For more information, see <<security>>.
|
||||
|
||||
[[x4.2-security-context-propagation]]
|
||||
==== SecurityContext Propagation
|
||||
|
||||
The `SecurityContextPropagationChannelInterceptor` has been
|
||||
introduced for the `SecurityContext` propagation from one message flow's Thread to another.
|
||||
For more information, see <<security>>.
|
||||
|
||||
|
||||
[[x4.2-file-splitter]]
|
||||
==== FileSplitter
|
||||
|
||||
Reference in New Issue
Block a user