Externalized Grails 3 Spring Security Config - grails

I am working on externalizing the .YML file in Grails 3.x. The code to make this work, is as follows:
In my Application.groovy, I am implementing the setEnviroment method form the EnvironmentAware interface.
#Override
void setEnvironment(Environment environment) {
try {
String configPath = System.properties["local.config.location"]
def ymlConfig = new File(configPath)
Resource resourceConfig = new FileSystemResource(ymlConfig)
YamlPropertiesFactoryBean ypfb = new YamlPropertiesFactoryBean()
ypfb.setResources(resourceConfig)
ypfb.afterPropertiesSet()
Properties properties = ypfb.getObject()
environment.propertySources.addFirst(new PropertiesPropertySource("local.config.location", properties))
} catch (Exception e) {
log.error("unable to load the external configuration file", e)
}
}
I have edited the bootRun task in the build to this:
bootRun {
jvmArgs = ['-Dlocal.config.location=external-config.yml']
}
When printing out the values in the setEnvironment method, the properties are indeed being read and added from the loaded object.
Now, for the fun part. When I add this code to my original application.yml file:
---
grails:
plugin:
springsecurity:
securityConfigType: 'InterceptUrlMap'
interceptUrlMap: [
{pattern: '/**', access: ['permitAll']}
]
providerNames: ['ldapAuthProvider', 'anonymousAuthenticationProvider']
ldap:
context:
managerDn: 'uid=admin,ou=system'
managerPassword: 'secret'
server: 'ldap://localhost:10389'
authorities:
groupSearchBase: 'ou=Groups,dc=aye,dc=com'
retreiveGroupRoles: true
retreiveDatabaseRoles: false
groupSearchFilter: 'member={0}'
search:
base: 'ou=Users,dc=aye,dc=com'
password:
algoritham: 'SHA-256'
---
Everything works just fine. When I cut and paste it out into the external yml file, I get this beautiful error in Firefox.
I can tell that the configuration is correct in the provided code, as I can add more roles and filters, and everything works just fine when in original application.yml file. It is only when reading from the external file does this fail. If I remove the security code from both .yml files, .ofc, my page looks strange but the firefox error disappears.
Has anyone got an idea as to why this can be the case?

One thing you can attempt to test if it will work, is rename your external-config.yml file to application.yml. I believe that the default name should be application, unless otherwise specified.
This article here shows a good example of its correct use
When you do that, try to read the properties in one of your classes, to make sure that the yml files are merging. You can read these properties using a command like this:
grailsApplication.config.getProperty("grails.plugin.springsecurity.securityConfigType")
Or, you can print out all of them, using the Holders utility
def config = Holders.config

Related

log4j2 monitorInterval using spring cloud config server

I'm trying to read the log4j2 configuration from config server during application startup.
bootstrap.yml
spring:
application:
name: loggingApp
cloud:
config:
uri: http://localhost:8888
logging:
config: http://localhost:8888/loggingApp/raw/master/loggingApp-log4j2-DEV.xml
The application seems to get the configuration properly during start up as I see the appropriate log levels. However, the automatic configuration doesn't seem to work. When I change the log level of the loggers, looks like it didn't read the updated config from config server after the monitorInterval has passed. I've set the monitorInterval to 10 seconds. As per the documentation the minimum interval should be 5 seconds. If I point to a file on local drive, instead of the config server url, it is working fine. I tried using -Dlog4j.configurationFile as jvm arg as well as spring configuration logging.config to see if one of those work, but none worked.
https://logging.apache.org/log4j/2.x/manual/configuration.html#AutomaticReconfiguration
https://logging.apache.org/log4j/2.x/log4j-spring-cloud-config/log4j-spring-cloud-config-client/index.html
I'm using spring-boot 2.2.5.RELEASE, log4j2 2.13.1 and spring-cloud Hoxton.SR3 versions.
This is how the git repo looks like where config files are being read from
I too tried the same and it did not work. It seems the <Configuration monitorInternal="10"> property would only have worked if we use log4j.configurationFile property to load the log4j2 config file as mentioned in Apache's Log4j Spring Cloud Configuration Guide .
I used the spring actuator refresh approach to accomplish this task. However this does not reload the configs on its own. So there is work around to meet the required ends. Create a scheduler in your spring application that hits the actuator refresh url on specified intervals as below
#Component
#EnableScheduling
public class RefreshScheduler {
#Autowired
private RestTemplate restTemplate;
#Scheduled(fixedRate = 60000)
private void postRefreshEndPoint() {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> entity = new HttpEntity<>(headers);
restTemplate.postForEntity("http://localhost:8080/actuator/refresh", entity, String.class);
}
}
This is surely a very dirty way of somehow achieving the required functionality. It works though :)
As a side note : Isn't it better to not have automatic refresh? My argument would be : It's possible developers by mistake ( or just for fun ) do changes to the configs in GIT. And this will lead to a change in the live application in prodcution.
However if we have the actuator refresh URL as mandatory for refreshing the spring context, this can be stopped. Only authorized memebers from the production/operations team would have access to this refresh url and they can decide whether to actually refresh the production spring beans when a commit on GIT has been done.

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 - controlling access of asset resources

I want to have control who can and can not access a specific folder in the assets folder.
I actually want to look in the database if the user can access that folder.
I am using the grails spring security plugin.
In the config file I declared assets as a permitAll because there are also resources that should be public available. I looked into the filtering of the plugin but most that I found was a custom authentication filter. I don't want to touch the auth. I just want to do some check additionally / on top
edit:
I also tried normal grails filters- I put the file "AssetsFilter.groovy" in the conf folder. But they are never called:
class AssetsFilter {
def filters = {
allURIs(uri: '/**') {
log.debug "aaa"
println "aaa1"
before = {
log.debug "bbb"
println "bbb1"
}
}
}
}

Dropwizard 0.8.0: serve static assets from /

I want my server to serve the static html files from /. Furthermore, css and js files should be served from /css respectively, /js. All json data should be accessible at /api.
However, I get a 404 for http://localhost:8080/ or any other path.
I use the following setting in the configuration file:
server:
type: simple
rootPath: /api/*
The application.initialize method looks like this:
#Override
public void initialize(io.dropwizard.setup.Bootstrap<MyConfiguration> bootstrap) {
bootstrap.addBundle(new AssetsBundle("/assets/css", "/css", null, "css"));
bootstrap.addBundle(new AssetsBundle("/assets/js", "/js", null, "js"));
bootstrap.addBundle(new AssetsBundle("/assets/pages", "/", "index.html", "html"));
}
I've just had to work through a similar problem (The documentation isn't the clearest, although with hindsight I guess most of the information is there somewhere), which I've resolved by setting both the applicationContextPath and the rootPath in my application config:
server:
type: simple
rootPath: /api/*
applicationContextPath: /
The default value for applicationContextPath is "/application" in a simple server, so your complete root-path would have been "/application/api/*". If you don't need to use the simple server, you could alternatively use the default server, which has the applicationContextPath set to "/" by default:
server:
rootPath: /api/*

Grails redirect redirects to invalid location

I'm running my app in development environment.
Using this simple controller:
class MyController {
def index() {
redirect uri: '/'
}
}
I'm getting redirected to http://localhost:8080/[:]/ location for some reason.
$appName seems good inside Config.groovy. grails.serverURL looks also OK.
What's the problem?
UPDATE 1
I'm using grails 2.2.4
UPDATE 2
The problem is with invalid grails.serverURL value. When I'm debugging the app, it has a correct value inside Config.groovy. When I'm printing out this value from servlet method it's set to http://localhost:8080/[:]/ for some reason. I'm using Spring Security Core 1.2.7.3 and Spring Security UI 0.2, I think that for some reason grails.serverURL is overwritted inside this plugin.
How to fix it?
The answer was simple. I've included MyConfig.groovy inside Config.groovy like this:
grails.config.locations = [ "classpath:${appName}-config.properties",
"classpath:${appName}-config.groovy",
MyConfig,
"file:${userHome}/.grails/${appName}-config.properties",
"file:${userHome}/.grails/${appName}-config.groovy"]
there was also environments.production, environments.development and environments.test sections however, $appName is undefined there. I've removed setting of grails.serverURL from MyConfig.groovy and its worked now.

Resources