Ensure web.xml filter-mapping from plugin is appended after springSecurityFilterChain - grails

I'm attempting to add a very simple DelegatingFilterProxy to my Grails application via a custom plugin.
I would like the filter to execute after the springSecurityFilterChain filter so that I can make use of certain security-specific information in the custom filter.
I've tried using loadAfter and loadBefore with different techniques in doWithWebDescriptor, but all end with the same result: my custom filter-mapping is always listed before springSecurityFilterChain. Below is my current iteration of doWithWebDescriptor
def contextParams = xml.'context-param'
contextParams[contextParams.size() - 1] + {
filter {
'filter-name'('auditFilter')
'filter-class'(DelegatingFilterProxy.name)
}
}
def filterMappings = xml.'filter-mapping'
filterMappings[filterMappings.size() - 1] + {
'filter-mapping' {
'filter-name'('auditFilter')
'url-pattern'('/*')
}
}
Is there a correct way to go about this?

The grails WebXmlConfig plugin provides additional features to work with the web.xml file. It hooks into an event, eventWebXmlEnd that listens for when the web.xml file is done generating. Once it's done, the plugin will attempt to re-order the servlet filters if necessary. It iterates over all other plugins and looks for a webXmlFilterOrder property in the plugin descriptor. If it finds that property, it registers the desired position and after looping over all plugins, rewrites the web.xml file.
The plugin is actually already included as a dependency of the Spring Security Core plugin, but you should also add it to your own plugin's BuildConfig.groovy file:
compile ':webxml:1.4.1'
So to hook in this functionality, you need to add a webXmlFilterOrder property to your plugin descriptor (really just a getter actually). You can throw this right above the doWithWebDescriptor closure (youll also need to import grails.plugin.webxml.FilterManager):
def getWebXmlFilterOrder() {
[auditFilter: FilterManager.GRAILS_WEB_REQUEST_POSITION + 101]
}
The getter returns a Map where the key is the name of your filter and the value is an int describing the desired position in web.xml. WebXmlConfig provides a FilterManager class with a few position constants that you can use. In this case, GRAILS_WEB_REQUEST_POSITION has a value of 1000.
A quick look at the Spring Security Core plugin descriptor shows that it's putting the springSecurityFilterChain filter at FilterManager.GRAILS_WEB_REQUEST_POSITION + 100, so by setting your auditFilter to anything higher, it will appear below spring security in web.xml.

Related

Vaadin 23: extending VaadinServlet with spring boot results in dual sessions (VaadinSession and SpringVaadinSession) and inconsistent behaviour

Vaadin 23
A little background, I have just converted an existing Vaadin 23 project to SpringBoot.
The existing code extends VaadinServlet for the following reasons:
Inject user object to all requests on a ThreadLocal
Supply custom SystemMessagesProvider
Provide a number of #WebInitParam
Add Session Create/Destroy hooks
If there is a way to achieve all of these functions without extending VaadinSession, that would be the preferred option.
I discovered the problem after a lot of debugging trying to load an image from a resource
StreamResource imageResource = new StreamResource("logo.svg",
() -> {
InputStream resourceAsStream = getClass().getResourceAsStream("/images/logo.svg");
return resourceAsStream;
});
logo = new Image(imageResource, "Logo");
So it turns out that the resource is associated with the VaadinSession, but when the browser requests the image the Vaadin code goes looking for it on the SpringVaadinSession - which does not contain the resource.
I have attempted to extend SpringServlet instead, but I have not been able to find any current examples of how to do this and my naive attempt results in Excepitons at runtime.

How to customize an existing Grails plugin functionality, modifying behavior of doWithSpring method

I am new to grails and while working with Spring Security LDAP plugin it was identified that it accepts the ldap server password in plain text only. The task in hand is to pass an encrypted password which is decrypted before it is consumed by the plugin during its initialization phase.
I have already searched for all possible blogs and stackoverflow questions but could not find a way to extend the main plugin class to simply override the doWithSpring() method so that i can simply add the required decryption logic for the Ldap server password. Any help here will be appreciated.
I have already seen and tried jasypt plugin but it also does not work well if the password is stored in some external file and not application yml. So I am looking for a solution to extend the Spring security plugin main class, add the required behavior and register the custom class.
EDIT
Adding the snippet from Grails LDAP Security plugin, which I am trying to override. So If i am successfully able to update the value of securityConfig object before the plugin loads, the purpose is solved.
Some snippet from the plugin:
def conf = SpringSecurityUtils.securityConfig
...
...
contextSource(DefaultSpringSecurityContextSource, conf.ldap.context.server) { // 'ldap://localhost:389'
authenticationSource = ref('ldapAuthenticationSource')
authenticationStrategy = ref('authenticationStrategy')
userDn = conf.ldap.context.managerDn // 'cn=admin,dc=example,dc=com'
**password = conf.ldap.context.managerPassword // 'secret'**
contextFactory = contextFactoryClass
dirObjectFactory = dirObjectFactoryClass
baseEnvironmentProperties = conf.ldap.context.baseEnvironmentProperties // none
cacheEnvironmentProperties = conf.ldap.context.cacheEnvironmentProperties // true
anonymousReadOnly = conf.ldap.context.anonymousReadOnly // false
referral = conf.ldap.context.referral // null
}
ldapAuthenticationSource(SimpleAuthenticationSource) {
principal = conf.ldap.context.managerDn // 'cn=admin,dc=example,dc=com'
**credentials = conf.ldap.context.managerPassword // 'secret'**
}
You don't need to override the doWithSpring() method in the existing plugin. You can provide your own plugin which loads after the one you want to affect and have your doWithSpring() add whatever you want to the context. If you add beans with the same name as the ones added by the other plugin, yours will replace the ones provided by the other plugin as long as you configure your plugin to load after the other one. Similarly, you could do the same think in resources.groovy of the app if you don't want to write a plugin for this.
You have other options too. You could write a bean post processor or bean definition post processor that affects the beans created by the other plugin. Depending on the particulars, that might be a better idea.
EDIT:
After seeing your comment below I created a simple example that shows how you might use a definition post processor. See the project at https://github.com/jeffbrown/postprocessordemo.
The interesting bits:
https://github.com/jeffbrown/postprocessordemo/blob/master/src/main/groovy/demo/SomeBean.groovy
package demo
class SomeBean {
String someValue
}
https://github.com/jeffbrown/postprocessordemo/blob/master/src/main/groovy/demo/SomePostProcessor.groovy
package demo
import org.springframework.beans.BeansException
import org.springframework.beans.MutablePropertyValues
import org.springframework.beans.PropertyValue
import org.springframework.beans.factory.config.BeanDefinition
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory
import org.springframework.beans.factory.support.BeanDefinitionRegistry
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor
class SomePostProcessor implements BeanDefinitionRegistryPostProcessor{
#Override
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
BeanDefinition definition = registry.getBeanDefinition('someBean')
MutablePropertyValues values = definition.getPropertyValues()
PropertyValue value = values.getPropertyValue('someValue')
def originalValue = value.getValue()
// this is where you could do your decrypting...
values.addPropertyValue('someValue', "MODIFIED: ${originalValue}".toString())
}
#Override
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
}
}
https://github.com/jeffbrown/postprocessordemo/blob/master/grails-app/conf/spring/resources.groovy
beans = {
someBean(demo.SomeBean) {
someValue = 'Some Value'
}
somePostProcessor demo.SomePostProcessor
}
https://github.com/jeffbrown/postprocessordemo/blob/master/grails-app/init/postprocessordemo/BootStrap.groovy
package postprocessordemo
import demo.SomeBean
class BootStrap {
SomeBean someBean
def init = { servletContext ->
log.info "The Value: ${someBean.someValue}"
}
def destroy = {
}
}
At application startup you will see log output that looks something like this...
2017-10-23 19:04:54.356 INFO --- [ main] postprocessordemo.BootStrap : The Value: MODIFIED: Some Value
The "MODIFIED" there is evidence that the bean definition post processor modified the property value in the bean. In my example I am simply prepending some text to the string. In your implementation you could decrypt a password or do whatever you want to do there.
I hope that helps.
After trying Jasypt plugin and BeanPostProcessor solutions unsuccessfully for my use case, I found below solution to work perfectly.
To describe again the problem statement here,
a) we had to keep the passwords in an encrypted format inside properties files
b) and given we were packaging as a war file so the properties must not be kept inside the war to allow automated deployment scripts update the encrypted passwords depending on the environment
Jasypt plugin was a perfect solution for the use case a), but it was not able to cover the b) scenario
Moreover, the Grails LDAP Security plugin was getting loaded quite early hence Bean Post processors were also not helping out here.
Solution:
Created a new class by implementing the interface SpringApplicationRunListener. Extended its methods and parsed the properties file using YamlPropertySourceLoader
Sample code:
YamlPropertySourceLoader loader = new YamlPropertySourceLoader();
PropertySource<?> applicationYamlPropertySource = loader.load(
"application.yml", new ClassPathResource("application.yml"),"default");
return applicationYamlPropertySource;
Once the properties were loaded inside the MapPropertySource object, parsed them for the encrypted values and applied the decryption logic.
This whole implementation was executed before any plugins were initialized during Grails bootup process solving the purpose.
Hope it will help others.

Where to put log4j.xml in a Grails app?

Sometimes I see, in a Grails app's Config.groovy, something like:
log4j = {
appenders {
...
}
root {
...
}
...etc.
}
This is clearly a programmatic way of specifying the log4j configs. I'm wondering:
Is it possible to specify the log4j configs in a log4j.xml file, and then tell the Grails app where to look for it?
If so, where should I place the log4j.xml inside the Grails app, and how/where do I "connect" it to the app?
Grails by default won't use log4j.xml. You have a few options.
Wire up Spring to use log4j.xml. This can be somewhat complex if you aren't familiar with Spring and the required beans. Which you and I already discussed.
Use the Log4j XML plugin for Grails.
For simple use cases the second option would be preferred.
Update
Based on your follow up question in the comments you might be better off configuring logging directly in your plugin using the DSL syntax. Burt explains how this is done in another post.
Grails automatically excludes any file in grails-app/conf that matches log4j.*:
From scripts/_GrailsWar.groovy:
ant.copy(todir:"${stagingDir}/WEB-INF/classes", failonerror:false, preservelastmodified:true) {
fileset(dir:"${basedir}/grails-app/conf") {
exclude(name:"*.groovy")
exclude(name:"log4j.*")
exclude(name:"**/hibernate/**")
exclude(name:"**/spring/**")
}
fileset(dir:"${basedir}/grails-app/conf/hibernate", includes:"**/**")
fileset(dir:"${grailsSettings.sourceDir}/java") {
include(name:"**/**")
exclude(name:"**/*.java")
}
fileset(dir:"${grailsSettings.sourceDir}/groovy") {
include(name:"**/**")
exclude(name:"**/*.groovy")
}
fileset(dir:"${resourcesDirPath}", includes:"log4j.properties")
}
As pointed out, there are other ways to achieve what you want without using the log4j.xml file, but if you do want to use it, you can add some logic to your grails-app/conf/BuildConfig.groovy to ensure that it gets packaged in your WAR:
grails.war.resources = { stagingDir, args ->
copy(todir:"${stagingDir}/WEB-INF/classes", failonerror:false, preservelastmodified:true) {
fileset(dir:"${basedir}/grails-app/conf") {
include(name:"log4j.xml")
}
}
}

Grails' Config.groovy in plugins and dependent apps

I am making both a Grails plugin and several Grails apps that will use the plugin.
I want to define a few properties and give them defaults in the plugin, but allow apps to override their values (optional). This question surrounds the mechanical details of how to wire both plugin and child app alike in this manner.
Say I want my plugin (grails-myplugin) to define the following properties in its Config.groovy:
myplugin {
fizz {
whistles = true // Default for all child apps using this plugin
buzz = 3 // Default for all child apps using this plugin
}
}
grails.plugins.anotherPlugin.widget = 'auto'
grails.plugins.anotherPlugin.foo = '${myplugin.fizz.buzz}-40' // Hence, by default, is '3-40'
Now, I would like a child Grails app, say, myapp.war (which uses grails-myplugin) to override the 2 fizz properties:
// myapp's Config.groovy:
myplugin {
fizz {
// whistles property not defined here so this app uses the
// plugin's default of "true"
// Overrides the plugin's value of 3; this imples
// grails.plugins.somePlugin.foo is '12-40'
buzz = 12
}
}
A few issues here:
Have I placed everything correctly for the desired functionality?
With the above configuration, in grails-myplugin's Config.groovy, I have an error message:
Multiple markers at this line: - The type groovy.lang.MetaClass cannot be resolved. It is indirectly referenced from required .class files. - The type groovy.lang.GroovyObject cannot be resolved. It is indirectly referenced from required .class files.
The fact that I'm getting this error tells me that I'm ether trying to do something that is impossible in Grails, or that I'm just doing it wrong. Ideas?
Here you have how the quartz plugin resolved it:
https://github.com/grails-plugins/grails-quartz/blob/master/QuartzGrailsPlugin.groovy
Take a look at loadQuartzConfig method.
Also be aware that grails plugin exclude some parts of it to avoid problems when installing. It's configured on the plugin file like this:
def pluginExcludes = [
'grails-app/jobs/**',
'src/docs/**',
'web-app/**'
]

OSGi/Felix Declarative Services: How to filter the services to be bound?

I am using Apache Felix and its Declarative Services (SCR) to wire the service dependencies between bundles.
For example, if I need access to a java.util.Dictionary I can say the following to have SCR provide one:
/**
* #scr.reference name=properties interface=java.util.Dictionary
*/
protected void bindProperties(Dictionary d) {
}
protected void unbindProperties(Dictionary d) {
}
Now, I have more than one Dictionary service available, and I want to filter them using the "name" service property (I only want "name=myDictionary"). I can do that with code (using a ServiceTracker), but I'd rather specify the filter in the #scr annotation instead.
I think
target="(name=myDictionary)"
should do the trick in the #scr.reference annotation. See http://felix.apache.org/site/apache-felix-maven-scr-plugin.html
In standard DS, you can use target attribute of the reference element. In Felix world, where annotations can be used, I don't know what is the equivalent.
The target attribute is an LDAP filter, which matches against the service properties. So, your filter should be:
(name=myDictionary)

Resources