Grails: Simple IP-Filter

Here are a few code snippets to show how easy it is to create an ip filter in Grails, i.e. allowing access only from specific remote addresses using just plain Grails code without any plugin.

Nothing fancy and more or less officially documented. Summarized here to remind myself how easy it is. :-)

The allowed ip addresses can be configured by a regular expression admin.ip using the grails standard configuration stuff. E.g. Config.groovy with a line like this: admin.ip = 192.168.1.2|192.168.1.5 to allow 2 ip addresses. The .s will be escaped automatically by the filter code.

package softnoise

import static org.springframework.http.HttpStatus.FORBIDDEN


class IpFilters {
    def grailsApplication

    def filters = {
        all (controller:'*', action:'*', controllerExclude:'allowed') {
            before = {
                def ips = getIpRegEx (grailsApplication.config)

                if (request.remoteAddr =~ ips) {
                    return true
                }

                response.sendError (FORBIDDEN.value ())
                false
            }
        }
    }

    private String getIpRegEx (def config) {
        config.admin.ip.replaceAll  ('\\.', '\\\\.')
    }

}

Here are a couple of unit tests for it using Spock. The third test just checks if the filter has excluded the allowed controller.

package softnoise

import grails.test.mixin.TestFor
import grails.test.mixin.Mock
import spock.lang.Specification
import org.springframework.http.HttpStatus
import static org.springframework.http.HttpStatus.FORBIDDEN
import static org.springframework.http.HttpStatus.OK


@TestFor (GormController)
@Mock (IpFilters)
class IpFiltersSpec extends Specification
{
    static String VALID_REMOTE_ADDRESS = "162.168.1.2"
    static String INVALID_REMOTE_ADDRESS = "200.200.1.2"

    def setup () {
        grailsApplication.config.admin.ip = VALID_REMOTE_ADDRESS
    }

    def "reject access if the ip does NOT match the admin ip config" ()
    {
        given:
            request.remoteAddr = INVALID_REMOTE_ADDRESS

        when:
            withFilters (action:"index") {
                controller.index ()
            }

        then:
            HttpStatus.valueOf (response.status) == FORBIDDEN
    }

    def "allow access if the ip does match the admin ip config" ()
    {
        given:
            request.remoteAddr = VALID_REMOTE_ADDRESS

        when:
            withFilters (action:"index") {
                controller.index ()
            }

        then:
            HttpStatus.valueOf (response.status) == OK
    }

    def "allow access to 'allowed' controller from anywhere" () {
        given:
            request.remoteAddr = INVALID_REMOTE_ADDRESS

        when:
            withFilters (controller: 'allowed', action:"index") {
                controller.index ()
            }

        then:
            HttpStatus.valueOf (response.status) == OK
    }
}
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s