Grails: Inject LdapTemplate from spring security - grails

I'm using the spring security (core 2.0-SNAPSHOT and ldap 2.0-RC2) plugins in my Grails 2.4.RC1 project. I'd like to be able to reuse the LdapTemplate that has been configured for use in spring security but I'm not sure how to inject the LdapTemplate into my service class.
Here's my simple service:
#Transactional
class EmployeeSynchronizationService implements EmployeeSynchronizer {
LdapTemplate ldapTemplate
void syncEmployees() {
// do work with ldapTemplate... but ldapTemplate is null
println ldapTemplate
sync(getUsernameToEmployeeMap(), getEmployeeLdapInfo())
}
...
And based on this stackoverflow post, my resources.groovy file looks like this:
beans = {
employeeSynchronizer(employee.EmployeeSynchronizationService) {
ldapTemplate=ref(ldapTemplate)
}
}
However, when I inject the EmployeeSynchronizer into a controller and invoke its syncEmployees method I see that the LdapTemplate is null.
Note: this same question was asked (but not answered) here.

Related

Is there a way to up only security context in Spring Boot tests?

I want to write some kind of unit test which depends on Spring Security.
For example, I have some service method which uses some repository and marked with #PreAuthorize annotation. Repository I can mock with Mockito, there is no problem. Also I can mock Security Context by #WithSecurityContext annotation. But when I run test, the #PreAuthorize annotation is just ignored. Of course I can run that test with #SpringBootTest annotation as an integration test and in this case the Security Context is up but this way is heavy and slow.
Is there a way to run unit test with only Spring Security Context raised?
UPDATE
Made an example of such kind of test. Thanks to #Sam Brannen for giving right direction.
#ActiveProfiles("method-security-test")
#RunWith(SpringRunner.class)
#SpringBootTest(classes = {ExampleService.class, ExampleServiceTest.MethodSecurityConfiguration.class})
public class ExampleServiceTest {
private ExampleService service;
#Autowired
public void setService(ExampleService service) {
this.service = service;
}
#Test
#WithMockUser(username = "john_doe")
public void testAuthenticated() {
String actualMessage = service.example();
Assert.assertEquals("Message of john_doe", actualMessage);
}
#Test(expected = AuthenticationException.class)
public void testNotAuthenticated() {
service.example();
Assert.fail();
}
#TestConfiguration
#EnableGlobalMethodSecurity(prePostEnabled = true)
static class MethodSecurityConfiguration extends GlobalMethodSecurityConfiguration {
}
}
#Service
class ExampleService {
#PreAuthorize("isAuthenticated()")
String example() {
Principal principal = SecurityContextHolder.getContext().getAuthentication();
return "Message of " + principal.getName();
}
The #PreAuthorize annotation from Spring Security will only be honored if Spring Security proxies your component (e.g., service bean).
The simplest way to make that happen is by annotating an #Configuration class with #EnableGlobalMethodSecurity(prePostEnabled = true), having your component registered as a bean (e.g., via component scanning or an #Bean method), and including your AuthenticationManager setup.
You can then create a focused integration test using #ContextConfiguration (without Spring Boot testing support) to load an ApplicationContext from your #Configuration class. And you can use #Autowired to get access to your proxied component which will be advised with the #PreAuthorize security check support.
You might find this old blog post useful as well for background information: https://spring.io/blog/2013/07/04/spring-security-java-config-preview-method-security/

Spring WebFlux 5.0.RELEASE and Spring Security 5.0.M5

I am trying to build a web service using WebFlux. When I tried to configure Spring Security with Spring WebFlux, the requests are not intercepted by Spring Security. My Spring Security config is:
#EnableWebFlux
#EnableWebFluxSecurity
#Configuration
public class WebConfig {
#Bean
public MapUserDetailsRepository userDetailsRepository() {
UserDetails cust =
User.withUsername("user1").password("password")
.roles("USER").build();
UserDetails admin =
User.withUsername("admin1").password("password")
.roles("ADMIN").build();
return new MapUserDetailsRepository(cust, admin);
}
#Bean
public SecurityWebFilterChain springWebFilterChain(
HttpSecurity httpSecurity) {
return httpSecurity.authorizeExchange().anyExchange().
authenticated().and().build();
}
}
One way is to use method security. You need to add #EnableReactiveMethodSecurity to your configuration class and then secure handler component methods with annotations, such as #PreAuthorize("isAuthenticated()")
This is how I managed to get this working with Spring Boot 2.0.0.M4, but again this may depend on what kind of request handling you are doing.
This is an issue when using Spring Security with WebFlux. The workaround is posted here: https://jira.spring.io/browse/SPR-16144

Grails 3 Spring Security Pre Authentication

The application I have in works uses Grails 3. I am attempting to do Pre-Authentication, as described in this article , but am having a hard time as I cannot figure out how to disable the regular authentication provided by the grails 3 spring security plugin.
Here is my current scenario: User A hits my webpage. I want to parse the headers of the request and take out the roles and username information. If the username or roles are empty, I will redirect the user to some gateway. In simple terms, I want to use spring security for authorization only, by invoking the static rules provided by the plugin. i.e
grails.plugin.springsecurity.controllerAnnotations.staticRules = [
[pattern: '/serviceb/**', access: "hasAnyRole('ROLE_COOL','ROLE_UNCOOL')"],
[pattern: '/cools/**', access: ['ROLE_ADMINS']],
[pattern: '/*', access: 'isAuthenticated()']
]
This is the reason I do not need spring security to do any login functionality, as the first article states, we can use it for authentication only.
What I have tried:
First, I removed all authentication related calls in my application.groovy file (created by default when running the quick start for the plugin) i.e, connection strings, search filters, but not static rules
Next, I tried to use a solution provided by these two posts: on stack and this on blog.
I created a Filter to extend the AbstractPreAuthenticatedProcessingFilter
package Cool.service.authentication
import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter
import javax.servlet.http.HttpServletRequest
class CGAuthenticationFilter extends AbstractPreAuthenticatedProcessingFilter {
#Override
protected Object getPreAuthenticatedPrincipal(HttpServletRequest request) { "username" }
#Override
protected Object getPreAuthenticatedCredentials(HttpServletRequest request) { "N/A" }
}
My Boot config now looks like this:
import grails.plugin.springsecurity.SecurityFilterPosition
import grails.plugin.springsecurity.SpringSecurityUtils
class BootStrap {
def init = { servletContext ->
SpringSecurityUtils.clientRegisterFilter('CGAuthenticationFilter', SecurityFilterPosition.PRE_AUTH_FILTER.order)
}
}
And my Spring resources look like this:
import Cool.service.authentication.CGAuthenticationFilter
beans = {
myAuthenticationFilter(CGAuthenticationFilter) {
authenticationManager = ref('authenticationManager')
checkForPrincipalChanges = true
}
}
And lastly, added this line to my application.groovy configuration for spring security plugin:
grails.plugin.springsecurity.providerNames = ['preAuthenticatedAuthenticationProvider', 'anonymousAuthenticationProvider']
However, I am getting a super geneirc error when trying to run-app, where the server "fails" to start and java returns a non zero value back. This makes me believe I am headed in the wrong direction, and the implementation is completely wrong
To solve the problem, I had to change a few files. First, my Bootstrap file now contains the following init block:
SpringSecurityUtils.clientRegisterFilter('requestHeaderAuthenticationFilter', SecurityFilterPosition.PRE_AUTH_FILTER)
My beans (resources.groovy) file now contains:
userDetailsService(grails.plugin.springsecurity.userdetails.GormUserDetailsService) {
grailsApplication = ref('grailsApplication')
}
userDetailsByNameServiceWrapper(org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper) {
userDetailsService = ref('userDetailsService')
}
preAuthenticatedAuthenticationProvider(org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider) {
preAuthenticatedUserDetailsService = userDetailsByNameServiceWrapper
}
requestHeaderAuthenticationFilter(Cool.service.authentication.GCHeaderAuthenticationFilter) {
authenticationManager = ref('authenticationManager')
}
Other than that, the rest of the configuration is correct.

Grails: Grails3 : doWithWebDescriptor?

I am trying to get further into grails3 and I am unsure about plugin descriptor and doWithWebDescriptor:
src/main/groovy/grails/plugin/plugin/PluginGrailsPlugin.groovy
def doWithWebDescriptor = { xml ->
def listenerNode = xml.'listener'
listenerNode[listenerNode.size() - 1] + {
listener {
'listener-class'(someClass.name)
}
}
}
I tried grails install-templates under grails 3 and no web.xml was generated... I also had a look at the default generated plugin descriptor which did not appear to have doWithWebDescriptor...
Was wondering if this has changed - is it no longer producing a web.xml or if it is what should I be doing to register a listener under grails 3 .
I have managed to get default tomcat websocket listener to work via a spring boot grails app:
It is documented here:
https://github.com/vahidhedayati/testwebsocket-grails3
I have decided to update this post and include all my findings so far on this matter.
More specifically the application.groovy inside your application grails-app/init folder:
This bean initiates default tomcat websocket listener:
#Bean
public ServletListenerRegistrationBean<AnotherWebSocketHandler> httpSessionEventPublisher() {
return new ServletListenerRegistrationBean<AnotherWebSocketHandler>(new AnotherWebSocketHandler());
}
Whilst messing around to reuse in plugin, the findings are:
The above project is a basic grails application which does 2 things, a basic spring socket as well java 1.X Websocket:
Here is how to use Default websocket in a grails 3 plugin
In you plugin descriptor you have something like this:
Closure doWithSpring() {
{->
wsChatConfig DefaultWsChatConfig
}
}
In this plugin I have left both methods of initiating the listener:
#Bean
public ServletContextInitializer myInitializer() {
return new ServletContextInitializer() {
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
servletContext.addListener(WsCamEndpoint)
servletContext.addListener(WsChatFileEndpoint)
}
}
}
// Alternative way
#Bean
public ServletListenerRegistrationBean<WsChatEndpoint> httpSessionEventPublisher() {
return new ServletListenerRegistrationBean<WsChatEndpoint>(new WsChatEndpoint())
}
The top method came in very handy since you can only initialise 1 ServletListenerRegistrationBean and I had to resort to the top method to enable other listeners... I could have just used the top primary for all the calls. Left in for future reference..
With this in place, spring boot now emulates the same as web.xml would when registering a listener. The actual groovy classes that load the websockets from there are as they were i.e. using default websocket calls such as onOpen onMessage etc..
From Grails 3 there's a new way of adding runtime configuration using spring registration beans in the Plugin method doWithSpring. doWithWebDescriptor is not used anymore.
This should work for the Servlet Listeners:
Closure doWithSpring() {{ ->
MyListener(ServletListenerRegistrationBean) {
listener = bean(someClass)
order = Ordered.HIGHEST_PRECEDENCE
}
}}
Disclaimer: I didn't test this code.
Refer to the Gails documentation.

Grails custom security evaluator

I'm working on an app that has to do object level security checks, and the checks will be made by a service because it will need to make REST calls to a separate application. Because of this I'm not able to use Spring Security roles or ACLs because none of this information will be stored locally in the app. I'm trying to find an elegant way to handle this, and here are two options I can think of:
1) Create a custom annotation that will check permissions
2) Extend a Spring security annotation permission check (possibly with Permission Evaluator?) that lets me write the logic for checking access
For #1 I've created a custom annotation and am using filters to read the annotation and check access, although this seems to be more brittle and will only give me protection for controller actions, and it would be nice to also secure other services as well.
I've found bits an pieces of this information, but nothing complete.
THIS talks about customizing ACL but only for a new permission, not controlling the logic
THIS talks about using SpEL, but I'd like to have checks before a method runs, to make sure that no effect takes place that would be unauthorized.
THIS appears to be the closest to what I want to do, but is specific to Spring Security and not Grails - my biggest challenge is converting the information in applicationContext.xml into resources.groovy
Thanks in advance for any suggestions or advice you may have!
You should be able to do this with spring security and grails without much trouble.
I used the following 2 ways in the past for similar tasks. Both require the spring security ACL plugin which provides the #PreAuthorize and #PostAuthorize annotations.
Custom PermissionEvaluator
You can use the hasPermission() methods within security annotations and create a custom PermissionEvaluator. Within code this looks like this:
#PreAuthorize("hasPermission(#myObject, 'update')")
public void updateSomething(myObject) {
..
}
The hasPermission() calls are routed to a PermissionEvaluator by spring security. To write your own implementation you have to implement the PermissionEvaluator interface:
class MyPermissionEvaluator implements PermissionEvaluator {
#Override
public boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) {
// your custom logic..
}
#Override
public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission) {
// your custom logic
}
}
To register your PermissionEvaluator you have to override the bean named expressionHandler. You do this by adding the following lines in conf/spring/resources.groovy:
beans = {
expressionHandler(MyExpressionHandler) {
parameterNameDiscoverer = ref('parameterNameDiscoverer')
permissionEvaluator = ref('myPermissionEvaluator') // your PermissionEvaluator
roleHierarchy = ref('roleHierarchy')
trustResolver = ref('authenticationTrustResolver')
}
myPermissionEvaluator(MyPermissionEvaluator)
}
Within resources.groovy you can define beans like you would do in applicationContext.xml when using spring. The above lines create a bean of type MyPermissionEvaluator with the bean name myPermissionEvaluator. Spring securities expressionHandler bean is overridden with a bean of type MyExpressionHandler. The other dependencies are copied from the configuration file of the spring security ACL plugin.
Service calls in security annotations
If the design of the hasPermission() methods does not achive all you requirements you can use simple service calls instead. The #PostAuthorize and #PreAuthorize annotations use SPEL to evaluate the expression. Within SPEL you can use the # symbol to access beans. For example:
#PreAuthorize("#securityService.canAccess(#myObject)")
public void doSomething(myObject) {
..
}
This calls the canAccess method of the bean named securityService and passes the method argument to it.
To use this approach you have to register a BeanResolver on the EvaluationContext. To do this you have to override the DefaultMethodSecurityExpressionHandler which is configured by the spring security ACL plugin.
This can look like the following:
class MyExpressionHandler extends DefaultMethodSecurityExpressionHandler {
BeanResolver beanResolver
#Override
public EvaluationContext createEvaluationContext(Authentication auth, MethodInvocation mi) {
StandardEvaluationContext ctx = (StandardEvaluationContext) super.createEvaluationContext(auth, mi)
ctx.setBeanResolver(beanResolver) // set BeanResolver here
return ctx;
}
}
BeanResolver is a simple interface that resolves a bean name to a bean instance:
class GrailsBeanResolver implements BeanResolver {
GrailsApplication grailsApplication
#Override
public Object resolve(EvaluationContext evaluationContext, String beanName) throws AccessException {
return grailsApplication.mainContext.getBean(beanName)
}
}
And finally add the beans to resources.groovy:
expressionHandler(MyExpressionHandler) {
parameterNameDiscoverer = ref('parameterNameDiscoverer')
permissionEvaluator = ref('permissionEvaluator')
roleHierarchy = ref('roleHierarchy')
trustResolver = ref('authenticationTrustResolver')
beanResolver = ref('beanResolver') // this is your BeanResolver
}
// This is the service called within security expressions
// If you place your service in the grails service folder you can skip this line
securityService(MySecurityService)
// this is your BeanResolver
beanResolver(GrailsBeanResolver) {
grailsApplication = ref('grailsApplication')
}
Update (2013-10-22): Recently I wrote a blog post about exactly this which provides some additional information.

Resources