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:
Artem Bilan
2015-07-05 12:58:33 -04:00
committed by Gary Russell
parent fd35d43aba
commit 09fb4f78c9
37 changed files with 1459 additions and 288 deletions

View File

@@ -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.

View File

@@ -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