alexgorbatchev

Friday, March 6, 2015

Grails 3 App with Security (Part 1)

The great Spring Security Plugin is now available for Grails 3!

I will leave these blog posts up as a reference, but I would strongly suggest (as if you needed the suggestion) to use the Spring-Security plugin for Grails 3

Since Spring Security Core Plugin is not was not working for Grails 3, and I could not find any other resources for the spring-boot-starter-security related to Grails 3 I decided to share what I did to get up and going. I created a github project at https://github.com/dspies/grails-3-with-security and tagged each step if you want to follow along.
Uses:
  • Grails Version: 3.0.0.M2
  • Groovy Version: 2.4.1
  • JVM Version: 1.7.0_51

Setting up Security:

Simply add the following to build.gradle in the dependencies:
compile "org.springframework.boot:spring-boot-starter-security"
This will cause ALL HTTP endpoints to require authorization and a random password to be generated each time you start up your app. Also, because Spring-Boot-Security-Starter logs the randomly generated password at level INFO, you need to add the following to your logback.groovy file.
 //see http://logback.qos.ch/manual/groovy.html for more info
 logger('org.springframework.boot.autoconfigure.security', INFO)
This is not sufficient for anything but a demo, so let's customize it a bit. Let's start with the easiest part, creating a fixed password. There are a few methods of setting a static password, but we'll concentrate on two 1) in the application.yml or 2) in a WebSecurityConfigurerAdapter Class.

In the Application.yml file

    security:
        user:
            password: password

In a WebSecurityConfigurerAdapter Class

Using a WebSecurityConfigurerAdapter class, we can override the default implementation(s) used in spring-boot-starter-security.

grails-app/init/simpleappwithsecurity/SecurityConfiguration.groovy
package simpleappwithsecurity

import org.springframework.beans.factory.annotation.Autowired
import org.springframework.context.annotation.Configuration
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
@EnableWebSecurity
class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth
                .inMemoryAuthentication()
                .withUser("user").password("pwd").roles("USER");
    }
}
One important note, Grails does NOT know anything about the SecurityConfiguration class unless you do something to tell your Grails' app about the new class. The two easiest methods are to specify a bean in resources.groovy
grails-app/conf/spring/resources.groovy
import simpleappwithsecurity.SecurityConfiguration

beans = {
    webSecurityConfiguration(SecurityConfiguration)
}
If you use this, you do not need the class annotations @Configuration and @EnableWebSecurity on the SecurityConfiguration class. Another method is to enable Spring's Component Scan on the Grails application in the Application.groovy file by adding @ComponentScan to the Application class, such as
grails-app/init/Application.groovy

...
import org.springframework.context.annotation.ComponentScan;

@ComponentScan
class Application extends GrailsAutoConfiguration {
...
I think this depends on how you view your application. If it is a Grails Application, using primarily Grails Plugins with Spring sprinkled in, then use the first method. If it is a Spring Boot application with Grails sprinkled in, use the latter method. For now, our app is a Grails app, so we'll use the bean definition in resources.groovy.

Securing specific URIs (or request maps)

Let's extend our example by adding pattern matches to our SecurityConfiguration class.
grails-app/init/simpleappwithsecurity/SecurityConfiguration.groovy
...
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers('/admin/**').hasAnyRole('ADMIN')
                .antMatchers('/home/**').hasAnyRole('USER', 'ADMIN')
                .antMatchers('/').permitAll()
            .and()
                .formLogin().permitAll()
            .and()
                .logout().permitAll()
    }

    //<-- --="" .inmemoryauthentication="" .withuser="" auth="" code="" configureglobal="" end="" exception="" in="" of="" password="" previous="" public="" roles="" snippet="" throws="" user="" uthenticationmanagerbuilder="" utowired="" void="">
                .and()
                .withUser('admin').password('admin').roles('ADMIN');
    }

...
Restarting the application now will allow you to see the index page, but require authentication when attempting to access /home or /admin controllers.

Resources:

Thursday, April 3, 2014

Grails Gotchas: Configuration Files and GStrings

Configuration Files

Be careful in defining configuration information using double quotes, because if the value you are attempting to assign contains a dollar sign ($), grails will see that as a variable and attempt to substitute the letters/words following the dollar sign with variable information for those letters/words. While this situation probably only presents itself with passwords, I always use single quotes defining information in the configuration files, unless I explicitly want to inject variable data into a configuration attribute, so there is no confusion.

For example, the following error-causing configuration
datasource {
  ...
  password = "Thi$i$Secure"
  ...
}
would probably result in password = 'Thi', unless you defined an i or Secure variable somewhere else in the configuration file, in which case, you would assign the result of evaluating that information too.

Instead, I would suggest that you always specify your configuration information in single quotes
datasource {
  ...
  password = 'Thi$i$Secure'
  ...
}

For sake of completeness, you could alternatively escape the dollar sign ($)
datasource {
  ...
  password = "Thi\$i\$Secure"
  ...
}
however, this leaves the possibility for errors that may not be easy to spot. Especially, if you have an externalized config and this error arises in production.

Wednesday, March 12, 2014

Webstorm and Karma in Ubuntu 12 LTS

If you are attempting to run Karma unit tests from Webstorm in Ubuntu 12LTS you may run into the following error:
Cannot start Chrome
 Can not find the binary google-chrome
 Please set env variable CHROME_BIN
Attempting to export CHROME_BIN=/usr/bin/chromium-browser worked great for running karma from the command line, but did not fix my issue when running it from within Webstorm, so after a bit of searching I found that you can add environment variables to webstorm by editing the Run/Debug Configurations for Karma:
  1. Under Run > Edit Configurations...
  2. Select Karma > karma.conf.js 
  3. Add the Environment Variables:
    CHROME_BIN=<path to chromium-browser>
    • To find the location of chromium-browser:
      which chromium-browser

Friday, December 13, 2013

Jasmine Testing Framework - syntax comparison to Junit and Spock


Example Jasmine Test Suite

describe('This is my test suite', function () {
  var testObject;  

  beforeEach(function(){
    testObject = new TestObject();
  });

  it('This is my test', function(){
   expect(testObject.doSomething()).toEqual('Some Value');
  });

});
JasmineJUnitSpock
describeTestCaseSpecification
Describes a feature of an application and can be nested inside on another.

beforeEach@Before / setUp()setup()
Piece of code run before each test used to initialize testing objects.

it@Test<test function>()
Runs one test of the larger test suite.  Contains a test name and a function.

expect & (toEqual(), toBeTruthy(), etc)assert*()Any conditions in an expect: block
Conditions to check during the test.

afterEach@After / tearDown()cleanup()
Piece of code run after every test to tear down or destroy any testing objects.

Friday, November 22, 2013

Grails Cobertura Plugin Excludes

After setting up the Cobertura Plugin in my Jenkins-Grails build, I was a little surprised to see my build failing because of low test coverage, since I have unit tests to cover nearly every line of the domain, controller, and service classes.  What I failed to consider is the Cobertura plugin believes anything with a .groovy extension is a source file and should have tests.  This includes database migration scripts (i.e. changelog.groovy), non-standard config files, and other miscellaneous application files with a .groovy extension.  Therefore, to have the Jenkins-Cobertura plugin report and more importantly use accurate metrics in evaluating the quality of the build, you must exclude those files.  The coverage exclusions are based on package, so the easiest way to exclude them is to put all of your 'real' code into packages (which should be done anyway) and exclude all default package 'classes' with the following config block in BuildConfig.groovy

coverage {
    //('*') The Single asterik excludes top-level groovy classes/scripts, such as BootStrap, changelog (Database Migration), ApplicationResources, etc
    exclusions = ['*']

    // Creates xml output that can be parsed in the Jenkins-Cobertura plugin
    xml = true
    
    //Keeps the coverage results from a previous set of unit tests (see: https://github.com/beckje01/grails-code-coverage)
    appendCoverageResults = true
}


On a related note, the Spring-Security-Core plugin generates source code instead of providing it via plugin, but does not create unit test code, so there will be little to no coverage out of the box.  Some may argue that the generated code is tested before being packaged into the plugin.  If you are one, then you could substitute the previous exclusions block with the one below:

    //('**/security/*') Excludes packages from the 'security' package, which
    // is where I put my generated Spring-Security-Core classes
    exclusions = ['*','**/security/*']

I would not recommend this however, because if you feel the need to have security on your application, you should test it.

Friday, August 30, 2013

Using MySQL LOAD DATA INFILE on Windows

Many times I need to load data into the MySQL database backing my Grails application before my initial release.  And frequently those databases include tables with last_updated and date_created timestamp fields.  Instead of entering the values into a csv file, I found it is very easy to set them programmatically while loading other data from a file like the following:

LOAD DATA INFILE 'D:\\sql_data\\available_samples.csv' 
INTO TABLE sample
FIELDS TERMINATED BY ',' 
OPTIONALLY ENCLOSED BY '"'
LINES TERMINATED BY '\r\n'
  (id, version, barcode, used)
 SET last_updated = NOW(), date_created = NOW();

References

Wednesday, August 28, 2013

My Grails Workflow: New Project Setup

Configuration changes

Build Config Changes
  • add organization's artifact repository to buildConfig.groovy
    mavenRepo https://my.url.org/nexus
    mavenRepo https://my.url.org/artifactory
    
    
  • Update all the plugins in buildConfig.groovy. Some of these plugins mature faster than the Grails releases and need to be updated when starting a new project.
    • Add (uncomment) cached resources - creates a hash of resources and sets expire headers so that your resources will not be downloaded over and over, helping to speed up your application
    • Add (uncomment) zipped resources - gzips the static resources in your application
    • Add build-test-data plugin - provides data that meets your domain constraints so you can concentrate on data under test
    • Add fixtures plugin - allows you to define dummy data for tests and development in the form of spring beans
    • Add spock plugin, if necessary - BDD Testing framework that makes tests much more expressive
        dependencies {
            test "org.spockframework:spock-grails-support:0.7-groovy-2.0" //Required for Grails v2.2+
        }
    
        plugins {
            runtime ":hibernate:$grailsVersion"
            runtime ":jquery:1.8.3"
            runtime ":resources:1.1.6"
            runtime ":zipped-resources:1.0"
            runtime ":cached-resources:1.0"
            runtime ":database-migration:1.3.2"
    
            build ":tomcat:$grailsVersion"
           
            compile ":cache-headers:1.1.5"
            compile ":cache:1.0.1"
            compile ":build-test-data:2.0.5"
    
            test (":spock:0.7") {
                    exclude "spock-grails-support"
            }
            test ':fixtures:1.2'
        }
Datasource Changes
  • Remove production block from datasource.groovy  (leaving the development and testing blocks).  I would remove all content, however, it appears that the database migration plugin has problems using alternative datasource configuration files when performing diffs/updates (http://jira.grails.org/browse/GPDATABASEMIGRATION-63)
  • Add <my app>-config.groovy to root directory for externalized configuration
  • Add /*-config.groovy to .gitignore to exclude it from the code repo.
Work Directory Change
This one is from Programming Grails by Burt Beckwith. Make target your work directory. This moves generated files, compiled classes, and installed plugins under the target directory and allows you to delete all of it by removing the target directory. This can help when Grails gets out of sync with your source code.
Change
  grails.project.class.dir = "target/classes"
  grails.project.test.class.dir = "target/test-classes"
  grails.project.test.reports.dir = "target/test-reports"
To
  grails.project.work.dir = 'target'


Setup/Preparation for Future Work

Front-End Development Preparation
  • Create and configure .editorconfig (This is not playing well with Intellij)
  • Disable caching, zipping, etc in development mode. This will allow you to make edits to the css and javascript while debugging/testing
      development {
        grails.resources.debug = true
      }
    
Database Migrations
Get the resources and artifacts prepared for the future. I like to setup the changelog prior to creating any domain classes.  This makes changelog.groovy  a simple list of includes.

dbm-generate-changelog changelog.groovy