Part 5a: Additional Credential Security – Spring Data JPA + Jasypt

In this short addendum to my earlier series on Spring Boot, I’ll be covering a fairly trivial problem whose solution I had a somewhat hard time finding an example of. Like normal, I hope this will help someone out who is just getting started.

On my current project, we’re working with a security-focused consulting firm named Jemurai (http://jemurai.com). Before I go further I wanted to mention that I learned about this tool and many, many other things security-related from one of their people (@mkonda). A great learning experience, and a pleasure to work with. Check them out.

Back to my current project. We had a goal to encrypt sensitive data at rest in properties files. One of the things you’ll notice if you’ve been following through Part 5 is that the database credentials are stored, in plain text, in properties files. In this installment, we’ll be encrypting the password in that credential using Jasypt, an encryption tool for Java.

As usual, for this installment, I’ve created a copy of the code from Part 5 and created a new project called Part 5 With Jasypt. It’s committed to Github, ready for cloning.

Download and Configure
Add the jasypt dependency to your build.gradle file:

/build.gradle:

dependencies {
    compile('org.springframework.boot:spring-boot-starter-web')
    compile('org.springframework.boot:spring-boot-starter-security')
    compile('org.springframework.boot:spring-boot-starter-data-jpa')
    compile('org.thymeleaf:thymeleaf-spring4:2.1.2.RELEASE')
    compile('org.jasypt:jasypt-spring31:1.9.2') //<—here it is.
    runtime('mysql:mysql-connector-java:5.1.6')

    testCompile('junit:junit')
}

Next, download the jasypt distribution from http://jaspyt.org: http://sourceforge.net/projects/jasypt/files/jasypt/jasypt%201.9.2/. Since we’ll be encrypting the database credentials that are currently stored in a properties file, follow the instructions on the jasypt site outlining using their CLI tools (http://www.jasypt.org/encrypting-configuration.html) to encrypt your credential. I used the command below to perform this task. The task was run from the ‘/bin’ directory in the jasypt distribution. The param named “input” should be string you wish to encrypt, and the password param is the decryption key used to decode your password as it’s being ingested by Spring during app startup.

Justins-MacBook-Pro:bin justin$ ./encrypt.sh input="password" password=testtest

…and the output should look something similar to this:

    ----ENVIRONMENT-----------------

    Runtime: Oracle Corporation Java HotSpot(TM) 64-Bit Server VM 24.51-b03



    ----ARGUMENTS-------------------

    input: password
    password: testtest



    ----OUTPUT----------------------

    xpPrNtXz+SQmTYB0WQrc+2T8ZTubofox

Updating Properties
If you read the jasypt manual, you’ve probably already updated your properties file with the newly encrypted value. In order to decrypt it, we need to give jasypt a directive – an indicator that is used by jasypt to determine which values need to be decrypted while they’re being ingested. I’ve updated my application.properties file to include my newly encrypted password and the encryption directive.

spring.datasource.url=jdbc:mysql://localhost:3306/beyond-the-examples
spring.datasource.username=root
spring.datasource.password=ENC(xpPrNtXz+SQmTYB0WQrc+2T8ZTubofox)
spring.datasource.driverClassName=com.mysql.jdbc.Driver

spring.jpa.hibernate.dialect= org.hibernate.dialect.MySQLInnoDBDialect
spring.jpa.generate-ddl=false

Updating Spring Config
Last, you’ll need to update your Spring config to use Jasypt utilities to decrypt the password while ingesting the necessary properties prior to constructing our datasource.

    @Value("${spring.datasource.driverClassName}")
    private String databaseDriverClassName;

    @Value("${spring.datasource.url}")
    private String datasourceUrl;

    @Value("${spring.datasource.username}")
    private String databaseUsername;

    private String databasePassword;

    @Bean
    public DataSource datasource() throws IOException {
        org.apache.tomcat.jdbc.pool.DataSource ds = new org.apache.tomcat.jdbc.pool.DataSource();
        ds.setDriverClassName(databaseDriverClassName);
        ds.setUrl(datasourceUrl);
        ds.setUsername(databaseUsername);
        ds.setPassword(getSecurePassword());

        return ds;
    }

    private String getSecurePassword() throws IOException {
        StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
        encryptor.setPassword(System.getProperty("blogpost.jasypt.key"));
        Properties props = new EncryptableProperties(encryptor);
        props.load(this.getClass().getClassLoader().getResourceAsStream("application.properties"));
        return props.getProperty("datasource.password");
    }

Here you can see I’ve changed the reference to my “databasePassword” property – it is no longer being populated by the @Value annotation. You can also see that I’ve replaced the value passed to the mutator of the password property of the datasource bean with a reference to a helper method that retrieves our password.

In that method (“getSecurePassword”), there are a few things going on. We’re retrieving the password the encryptor will use to decrypt the value stored in our properties file. Note that it’s the same value we used on the CLI during encoding. Also note that I’m assuming the value used for this is stored in a system property. Anywhere you can read it from will work, although environment variables/system properties seem to be the best place from what I’ve heard anecdotally and read in the Jasypt docs. There are some tricks to passing JVM options to the bootRun task. See here and here for examples. You can see we’re using an extension of java.util.Properties called ‘EncryptableProperties’. This is a Jasypt class that understands how to react when reading a property value enclosed by the directive we talked about above. After that, we’re using these properties like we would use any other java.util.Properties class.

Testing
To test our changes, simply execute the app using gradle bootRun. If we did it property (and remembered to specify our jasypt password somewhere), we should notice no user-facing changes – just the same app we had before, but now with encrypted properties. Note that I specified the value of my SystemProperty in the gradle script.

Conclusion
I hope you found this entry a useful continuation of the Jasypt and Spring.io documentation. Check back soon for another installment!

Part 5: Integrating Spring Security with Spring Boot Web

Spring Boot provides utilities for quick and easy setup of Spring Security via auto-configuration and Java-based configuration. The getting started guide is quick and easy leads through configuring an in-memory AuthenticationManager in just minutes. Going beyond these examples, this installation will quickly review the getting started guide provided at Spring.io, and conclude with the configuration of a datasource-backed AuthenticationManager that uses Spring Data JPA, and the MySQL database platform.

As usual, for this installment, I’ve created a copy of the code from Part 4 and created a new project called Part 5. It’s committed to Github, ready for cloning.

Updating Dependencies
To install Spring Security, we first need to update our gradle script to include a dependency on spring-boot-starter-security. Update build.gradle to include the following dependency as seen below.

/build.gradle:

dependencies {
    compile("org.springframework.boot:spring-boot-starter-web")
    compile("org.springframework.boot:spring-boot-starter-security")
    compile("org.thymeleaf:thymeleaf-spring4:2.1.2.RELEASE")

    testCompile("junit:junit")
}

Following that, executing a build should pull in our new dependencies.

Creating The Security Configuration
Continuing to lift code from the Spring.io docs for review, below you’ll find the example of the base Java security configuration. We’ll review the important bits after the jump. We’ll create this in the same directory as our other configuration files:

/src/main/java/com.rodenbostel.sample/SecurityConfiguration.java:

package com.rodenbostel.sample;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.servlet.configuration.EnableWebMvcSecurity;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

@Configuration
@EnableWebMvcSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests().anyRequest().authenticated();
        http
                .formLogin().failureUrl("/login?error")
                .defaultSuccessUrl("/")
                .loginPage("/login")
                .permitAll()
                .and()
                .logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout")).logoutSuccessUrl("/login")
                .permitAll();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication().withUser("user").password("password").roles("USER");
    }
}

As usual, the @Configuration annotation lets Spring know that this file contains configuration information. The next two annotations (@EnableWebMvcSecurity and @EnableGlobalMethodSecurity(prePostEnabled=true)) setup the automatically-configured portions of our security scheme, provided by Spring-Boot. EnableWebMvcSecurity basically pulls in the default SpringSecurity/SpringMVC integration. It’s an extension of the WebMvcConfigurerAdapter, and adds methods for handling and generating CSRF tokens and resolving the logged in user, and configures default AuthenticationManagers and Pre/Post object authorization implementations. The @EnableGlobalMethodSecurity sets up processors for authorization advice that can be added around methods and classes. This authorization advice lets a developer write Spring EL that inspects input parameters and return types.

Our SecurityConfiguration class also extends WebSecurityConfigurerAdapter. In Spring/Spring Boot, Configurer Adapters are classes that construct default bean configurations and contain empty methods which are meant to be overridden. Overriding these methods allow a developer to customize the Web Security Configuration during startup. Typically, the default configurations are constructed, and immediately following, the empty methods are called. If you’ve overridden an empty method, you’re able to inject custom behavior into the default configuration during the startup of the container.

In our case, the two coded parts of our SecurityConfiguration class (two methods named “configure”) are examples of these empty methods meant to be overridden. During container startup, after the HttpSecurity object’s default configuration is specified, our overridden method is called. Here we are able to customize the default configuration by specifying which requests to authorize, and how to route various security-related requests: default success URL, error routing, where to send logouts, etc. Also during container startup, after the AuthenticationManagerBuilder is configured, our configure method is called, and in this case we’re altering the default configuration, giving instructions to the AuthenticationManagerBuilder to build an in-memory AuthenticationManager with a default user credential and role.

You’ll notice in this configuration we’ve specified several URL paths that do not exist. There’s no login page or controller, and no way for a user to interact with the security configuration when the app is started up. Next, we’ll need to construct and wire in a login page to complete our beginning configuration.

Building The Login Page
The login page in the Spring.io sample is very straightforward. Just a simple form with an input for username and password. Let’s build that and review a few key parts.

/src/main/resources/templates/login.html:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
      xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
<head>
    <title>Spring Security Example</title>
</head>
<body>
<div th:if="${param.error}">
    Invalid username and password.
</div>
<div th:if="${param.logout}">
    You have been logged out.
</div>
<form th:action="@{/login}" method="post">
    <div><label> User Name : <input type="text" name="username"/> </label></div>
    <div><label> Password: <input type="password" name="password"/> </label></div>
    <div><input type="submit" value="Sign In"/></div>
</form>
</body>
</html>

Most importantly, we have inputs with the names of “username” and “password”. These are the Spring Security defaults. If you’re routing a request to Spring Security to authenticate, these are the parameters on the request that it will be looking for. Next, you’ll also notice that there are Thymeleaf conditionals (th:if) for displaying logout and error messages if they are present in the response parameters during rendering. You’ll also notice the path to this page is “/login”, and the action on this form routes back to “/login” – but we don’t have those registered anywhere…

Registering the Login Action
The path our login form is posting to is the default used by Spring Security. This is where what used to be called the “j_spring_security_check” servlet is listening for requests to authenticate. The request path (where we’re retrieving the login form by issuing a GET to /login) is normally mapped to a controller, but in this case, since we’re using automatically configured features of Spring Boot, we need to specify this mapping in our application configuration. Add the code below to your application configuration. You may notice the use of another @Override method – another hook where we can add logic to customize our application…

/src/main/java/com.rodenbostel.sample.Application.java:

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/login").setViewName("login");
    }

Log In!
Start your server, and try to access the app again. For me, that’s simply visiting http://localhost:8080.

Screen Shot 2014-05-30 at 4.59.05 PM

I’m immediately challenged.

If I put in an invalid username or password, we should see an error:

Screen Shot 2014-05-30 at 4.59.27 PM

If I put in the correct credentials (id: user/password: password), we should be able to log in:

Screen Shot 2014-05-30 at 5.00.33 PM

Screen Shot 2014-05-30 at 5.00.38 PM

There’s quite a bit missing here still – let’s take this example a bit further – we’ll wire in components that would make this configuration closer to production ready – an AuthenticationManager backed by JDBC, configurable password encoders, and a UserDetailsService implementation that we can use to manage users.

Beyond The Examples
To begin taking steps closer to this solution being production-ready, we first need to back our app with a database. I’ll be using MySQL. I’ll assume you’ve got it installed and running (if you’re on a mac, I’d use Homebrew to accomplish that.

First, we’ll add the MySQL dependency to our gradle script:

/build.gradle:

dependencies {
    compile("org.springframework.boot:spring-boot-starter-web")
    compile("org.springframework.boot:spring-boot-starter-security")
    compile("org.springframework.boot:spring-boot-starter-data-jpa")
    compile("org.thymeleaf:thymeleaf-spring4:2.1.2.RELEASE")
    runtime('mysql:mysql-connector-java:5.1.6')

    testCompile("junit:junit")
}

Configuring A Datasource
I’ll be calling my schema in MySQL “beyond-the-examples”. I’ll assume you’ve used the same name. Conveniently, Spring Boot Starter projects have an automatically configured property source path. This means that using a properties file for configuration data we’d like to externalize simply requires creating an “application.properties” file and putting it somewhere on the application’s classpath. We’ll create that file now, and add properties that we’ll use to set up our datasource.

/src/main/resources/application.properties:

spring.datasource.url=jdbc:mysql://localhost:3306/beyond-the-examples
spring.datasource.username=root
spring.datasource.password=
spring.datasource.driverClassName=com.mysql.jdbc.Driver

spring.jpa.hibernate.dialect= org.hibernate.dialect.MySQLInnoDBDialect
spring.jpa.generate-ddl=false

You can see I’m using the default configuration for MySQL. I wouldn’t recommend that for production.

Next, we’ll build references to these properties in our application’s configuration, so that we can use them to create a datasource bean that we can inject into our security configuration. Update the application configuration file to add these properties:

/src/main/java/com.rodenbostel.sample.Application.java:

    @Value("${spring.datasource.driverClassName}")
    private String databaseDriverClassName;

    @Value("${spring.datasource.url}")
    private String datasourceUrl;

    @Value("${spring.datasource.username}")
    private String databaseUsername;

    @Value("${spring.datasource.password}")
    private String databasePassword;

Next create a Datasource @Bean using these properties in the same file.

/src/main/java/com.rodenbostel.sample.Application.java:

    @Bean
    public DataSource datasource() {
        org.apache.tomcat.jdbc.pool.DataSource ds = new org.apache.tomcat.jdbc.pool.DataSource();
        ds.setDriverClassName(databaseDriverClassName);
        ds.setUrl(datasourceUrl);
        ds.setUsername(databaseUsername);
        ds.setPassword(databasePassword);

        return ds;
    }

Now, we have a datasource configured that we can @Autowire into any of our Spring beans, configuration or otherwise.

Create the Spring Security Tables
The DDL from the Spring.io docs is for HSQLDB. It’s syntax is not compliant with MySQL. Shout out to this guy (http://springinpractice.com/2010/07/06/spring-security-database-schemas-for-mysql) for publishing the MySQL versions of the default Spring Security schema. If you’re using MySQL like me, use the DDL from that blog to create a “users” table and an “authorities” table, then thank him. Since we’ll be properly encoding our passwords, we may want to make that password column a bit wider. Here’s what I ran:

create table users (    username varchar(50) not null primary key,    password varchar(255) not null,    enabled boolean not null) engine = InnoDb;create table authorities (    username varchar(50) not null,    authority varchar(50) not null,    foreign key (username) references users (username),    unique index authorities_idx_1 (username, authority)) engine = InnoDb;

Building The New Configuration
To start using the new datasource in the security configuration, we first need to wire the datasource bean into our SecurityConfiguration class. Update your SecurityConfiguration file to instruct spring to @Autowire this bean:

/src/main/java/com.rodenbostel.sample.SecurityConfiguration.java:

    @Autowired
    private DataSource datasource;

Next, we’re going to make a few significant changes to our AuthenticationManagerBuilder configuration to reference this datasource and a few other things, which I’ll review after the code:

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        JdbcUserDetailsManager userDetailsService = new JdbcUserDetailsManager();
        userDetailsService.setDataSource(datasource);
        PasswordEncoder encoder = new BCryptPasswordEncoder();

        auth.userDetailsService(userDetailsService).passwordEncoder(encoder);
        auth.jdbcAuthentication().dataSource(datasource);

        if(!userDetailsService.userExists("user")) {
            List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
            authorities.add(new SimpleGrantedAuthority("USER"));
            User userDetails = new User("user", encoder.encode("password"), authorities);

            userDetailsService.createUser(userDetails);
        }
    }


Prior to this, our AuthenticationManagerBuilder was configured on a single line - we were using an in-memory configuration, and creating a user directly on it.  Here, we’ll use the AuthenticationManagerBuilder to move from using:


auth.inMemoryAuthentication()

to using:

auth.jdbcAuthentication().dataSource(datasource);

Assuming there are already users in the database, believe it or not, that’s all we need to begin using the JDBC-backed AuthenticationManager. The requirement for creating new users and managing existing users is a foregone conclusion. In our case, we’d like to automatically configure a default user on app startup just like we were before. We can get a handle on the automatically configuration (by Spring Boot) UserDetailsService through our AuthenticationManagerBuilder at:

auth.getDefaultUserDetailsService();

…but that doesn’t quite do everything we need. On the first line of our updated AuthenticationManagerBuilder configuration method, you can see we’ve created a new instance of one of the provide implementations of UserDetailsService provided by Spring. If you don’t have a reason to customize how you manage users in your system, that is a perfectly suitable implementation, but there are things to consider. Please consult the API docs for more detail (http://docs.spring.io/spring-security/site/docs/3.2.4.RELEASE/apidocs/org/springframework/security/provisioning/JdbcUserDetailsManager.html). After creating the new reference to the JdbcUserDetailsManager, we need to set a reference to our datasource on it. Following that, we add our encoder for storing our passwords securely, and then we use the JdbcUserDetailsManager’s built-in functionality to check to see if our test user exists, and create him if he doesn’t.

Testing Again
Running the application should yield no change in behavior when compared with what we saw earlier. This is desired. What we will see that’s different will be in our database. Startup the app using: "gradle bootRun", and using your favorite database management tool, query the database to see our newly create user and their encoded password:

Screen Shot 2014-05-30 at 5.44.38 PM

Conclusion
I cobbled the information in this post from many sources - some I’ve remembered and have mentioned, and others I have not. I hope putting this information in a single post helps whoever stumbles upon it! That concludes this series of Spring Boot posts, but during the time I’ve been writing these, I’ve come up with two more topics to touch on, mostly surrounding further securing your app (http://www.jasypt.org/) and easier maintenance of your database tables (http://flywaydb.org/). Check back soon!

SpringOne2GX, Day 2 Recap

Another good day at SpringOne.

The first session of the day was with Burt Beckwith going over the Spring Security plugin(s) for Grails. The last Grails work I did was with the Shiro/JSecurity plugin, which worked well, but I’ve always been interested in the extended feature set of Spring Security and it’s extensions. I thought the UI plugin looks useful, and the OpenID support looks like it’s got some nice features. Much of the rest still seems to be up in the air, but it’s maturing nicely. Glad to hear the demo code will be available.

Second talk was on the Google track, and was covering Spring Roo (which I promptly got stoked about yesterday) and it’s integration with GWT. I understand all of the browser compatibility advantages of GWT, but I’m still not convinced the complexity is worth it. Thankfully, Spring Roo does what it does best when it comes to GWT – generates and tucks away your boiler plate code. I’m not as excited about GWT as I thought I would be.

Third talk was with Burt Beckwith again – this time about strategies for handling database migrations in Grails apps. This is an aspect of Rails that I think is far superior to Grails. I didn’t get much from this talk other than how to correctly use Liquibase, but it was good to hear that this is something is being addressed in the upcoming version of Grails.

Fourth talk was about Extreme Scaffolding with Jean Barmash. We saw demos of a few interesting plugins for scaffolding and other UI enhancements, but I didn’t see anything really groundbreaking. It seems that a good command of grails templates, layouts and keeping DRY in mind would accomplish the same thing. It might even take longer to put all of these plugins in, and learn how to correctly use them, rather than just focus on writing good code and pushing out useful functionality.

Finishing the day with Stefan Schmidt and another great talk on the versatile persistence functionality available in the latest version of Spring Roo. The incremental reverse engineering is awesome and blows hibernate right out of the water. Grails and Rails are great for greenfield development, but this really makes Roo a compelling solution for developing new apps on existing databases. The JPA2 and NoSQL support were interesting. The one part I didn’t get was the discussion on Hades. Hades is a Roo add-on that generates the DAOs that Roo is made to get rid of (or at least hide). Maybe I missed something – it sounded interesting – I just didn’t see how it fit with the rest of the features of Roo, other than code generation, of course.

In all, not as good a day as the first, but I learned some interesting things. Spring Roo really seems like an exciting alternative Grails, especially if you’re developing in a dynamic language resistent environment. Looking forward to tomorrow.