Usage of hasPermission with Spring State Machine - spring

I know how to secure a method with hasPermission (ex : #PreAuthorize("hasPermission(#id, 'Review', 'read')").
It seems that Spring State Machine transitions can be secured using Spring Security. But I did not find any example that uses hasPermission with a reference of the object for which the state machine has been created. In fact I cannot see how to reference an object when I define a transition of a state machine.
Did you have to secured such cases? Did you find a solution?

Related

How to properly provide Authentication object (SecurityContext) to application itself?

Most of my application is secured with method level security (AspectJ, but it doesn't matter) and now that I am trying to call some code from within application itself (not controllers, but e.g. EventListener) I can't help to wonder if Spring Security provides some out-of-box way of giving Authentication object to the application itself, otherwise I cannot get past my method security since application has null security objects (Authentication in SecurityContext, if it even exists - depends on situation, You might have to init it first).
Sure I can do something like this (just before running relevant code):
UserDetails ud = User.builder()
.username("APPLICATION")
.password("APPLICATION")
.roles("APPLICATION")
.build();
Authentication auth = new UsernamePasswordAuthenticationToken(ud, ud.getPassword(), ud.getAuthorities());
SecurityContextHolder.getContext()
.setAuthentication(auth);
But is it safe to do this in deployment (security-wise)?
Is there any guarantee on which thread will own this SecurityContext? What about other threads and their tasks?
Once set, can it stay there? Will it for the rest of app's run (can be days/months), context could be reloaded, etc. I lack deep Spring knowledge to know what happens Thread-wise inside Spring.

Spring Integration: the SecurityContext propagation

I have some perplexity about the SecurityContext propagation in Spring Integration.
Here is the point of the documentation:
http://docs.spring.io/spring-integration/reference/htmlsingle/#security-context-propagation
My perplexity are the following:
(1) 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).
This means that the SecurityContext (normally) is accessible only for the current Thread. Right?
So, how to make it accessible for another thread of another application (integrated with Spring Integration) ?
(2) 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
(see Section 8.8, “Adding Behavior to Endpoints”) or even
MessageChannel (see Section D.2, “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.
This means that we have to extract the Principal manually? If yes, how?
Or it's enough to use the propagation aspect, from 4.2 version?
(3) 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, - 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.
"Starting with version 4.2 SecurityContext propagation has been introduced." => Ok, very well.
But: "It is implemented as a SecurityContextPropagationChannelInterceptor, which can simply be added to any MessageChannel or configured as a #GlobalChannelInterceptor."
What does it mean? I have to implement an interceptor that extends "SecurityContextPropagationChannelInterceptor" ?
What I have to "add" in my <int:channel> configuration?
And if I use <int:channel-interceptor> (the same of #GlobalChannelInterceptor), it's different from using <int:interceptors> ?
Other perplexity:
"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."
But why there are a "obtainPropagatingContext" method and a "populatePropagatedContext" method in the SecurityContextPropagationChannelInterceptor class?
Where is made the propagation? In the preSend() / postReceive() methods, or in those two methods?
Furthermore, I tried to propagate the SecurityContext to an external application, without success...
Any explanations about this argument would be appreciated.
You have a lot of questions here, but let me try to answer to them.
What does it mean? I have to implement an interceptor that extends "SecurityContextPropagationChannelInterceptor" ?
No, there is such an interceptor in the Framework out-of-the-box. What you have to do to understand how to add interceptor to MessageChannel: http://docs.spring.io/spring-integration/reference/html/messaging-channels-section.html#channel-configuration-interceptors.
Or like this:
#Bean
#GlobalChannelInterceptor(patterns = {
"#{'queueChannel'}",
"${security.channel:executorChannel}",
"publishSubscribeChannel" })
public ChannelInterceptor securityContextPropagationInterceptor() {
return new SecurityContextPropagationChannelInterceptor();
}
See their JavaDocs for more information.
But why there are a "obtainPropagatingContext" method and a "populatePropagatedContext" method in the SecurityContextPropagationChannelInterceptor class?
SecurityContextPropagationChannelInterceptor extends ThreadStatePropagationChannelInterceptor<Authentication> , where obtainPropagatingContext and populatePropagatedContext are just generic method to extract some current State in the preSend() (on Thread) and provide that State for population/manipulation in the postReceive(), which may happen in the different Thread.
Yes, SecurityContext is thread-bound in Spring Security and the logic to be sure that we can perform a secured function is fully based on the ThreadLocal variable. That's why we have to transfer it that way. The "propagation" is a process not state.
Not sure what you mean about "external application", but there is only one mechanism to do that: send credentials together with the request to that application.

Dynamically configuring spring state machine

Some queries on spring state machine.
Can we have more than one state machine in a single spring project,
where in one state machine serves for one work flow (may be a CD
player work flow) and the other for a turnstile?
Can I dynamically load the configuration in my config class, for instance from a big data source having JSON formatted data, where we stores our states, events, transitions etc.
One of my requirement is I may be having a frequently changing worklow or model, which I needs to configured in my spring project. How can I effectively do that with spring state machine.
1) You can have multiple machines. #EnableStateMachine has id property for a bean name. You can expose config as #EnableStateMachineFactory. If you want to work outside of javaconfig there is a manual builder model for it.
2/3) There is a public configuration api between javaconfig and statemachine. One user(outside of javaconfig) of this config model is uml based modeling which uses eclipse's uml xml file to load the config. Uml is your best bet as we don't have other build-in configuration hooks at this moment. contributions welcome ;)
You can configure the State machine dynamically using Builder. Builder is using same configuration interfaces behind the scenes that the #Configuration model using adapter classes.
Example:
StateMachine<String, String> buildMachine1() throws Exception {
Builder<String, String> builder = StateMachineBuilder.builder();
builder.configureStates()
.withStates()
.initial("S1")
.end("SF")
.states(new HashSet<String>(Arrays.asList("S1","S2","S3","S4")));
return builder.build();
}
Link to official docs: Dynamic Spring State Machine

Struts 2 tomcat request/session contamination

I am using Struts 2 v 2.3.16.3 with tomcat 6.
A user will click on an action which finds an object by id and the page displays it. I have encountered a sporadic bug where the user will all of a sudden get the id of another lookup from another user on another machine. So effectively they are both calling the same action but passing different id to the request, but both end up viewing the same id.
This is obviously disastrous, and the data is totally corrupted as both users think they are editing a different record. Any ideas how make sure session/request activity is kept secure to each session?
I am also using spring and am using the #Transactional annotation in my Service layer, which returns the objects from the DAO. Is there something I need to do with this annotation to make it secure for each session ?
I am using org.springframework.orm.hibernate3.HibernateTransactionManager
Classic Thread-UnSafe problem.
Since you nominated Spring, my first guess is that you have not specified the right scope for your action beans in Spring xml configuration.
Be sure you are using scope="prototype" because otherwise the default scope of Spring is Singleton, and you don't want a single(ton) instance of an Action, that would not be ThreadLocal (and hence ThreadSafe) anymore.
If it is not that, it could be something on an Interceptor (that, differently from an action, is not Thread Safe), or you are using something static (in your Business / DAO layer, or in the Action itself) that should be not.

Authentication object not found thrown by DispatcherServlet before #Preauthorize spring security annotation is applied

When i am trying to use #PreAuthorize("#accessControl.hasActivity('abc')") on spring controller method i am getting Authentication object was not found in security context.
After debugging found that DispactcherServlet is throwing this exception.
i have set SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_THREADLOCAL);
when i first create Authentication object and set in security context
Also tried with SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL); but no luck still it does not work.
I am not able to understand why spring is servlet is throwing this exception
First, doing authentication in a Spring MVC interceptor is odd. Consider using a filter before DispatcherServlet. There is a lot of documented examples.
Secondly, SecurityContextHolder.setStrategyName re-initializes the strategy and possibly makes all previously authentications inaccessible so you must only call it once (if any time), before any authentication is made.
Thirdly, if you want to set the current authentication to be used by #PreAuthorize and are sure what you are doing, use SecurityContextHolder.getContext().setAuthentication(anAuthentication);. In most cases, there is a suitable filter in the API that already does this for you.

Resources