Showing posts with label security. Show all posts
Showing posts with label security. Show all posts

Friday, November 1, 2013

Traffic redirection to https in Grails behind load balancer

Grails security plugin has nice feature that allows automatically redirect queries for specific pages to https. For example, you can put this code into Config.groovy to redirect all requests:


grails.plugins.springsecurity.secureChannel.definition = [
    '/**':         'REQUIRES_SECURE_CHANNEL'
]

Unfortunately this does not work when your Tomcat is behind load balancer that does all encryption. To do it requires a little more work.

First, it is needed to specify how to detect either connection is secure or not. Standard way to do it with load balancers is to use X-Forwarded-Proto header. So it needs to be specified in Config.groovy like:

grails.plugins.springsecurity.secureChannel.useHeaderCheckChannelSecurity = true
grails.plugins.springsecurity.portMapper.httpsPort = 443

Worst part, is that it requires Tomcat reconfiguration, so it is needed to update Connector element in server.xml, like:

<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443"  proxyName="yourserver.com" proxyPort="443" secure="true" scheme="https"  />

Good part is that it works nicely locally and across multiple environments, no need for fake certificates or different builds.


Friday, September 28, 2012

Using Spring Security with CXF in Grails

CXF plugin is super easy way to add SOAP web service to Grails application. It creates regular service class, with few specific parameters and voila - you have SOAP. But what if you want security?
REST web services are native citizens in Grails - they are just actions in controllers, so you can use Spring Security annotations to check permissions. But there is no annotations for services. There are two easy options.
First, you can restrict actions by defining static rules. This is very simple, but not very flexible as it does not allow to configure permissions on method level, you will have to create different services for different permissions. Also, old clients may not work if WSDL requires authentication.
Second method, is to check permissions manually. In practice this is similar to annotations, and can be converted to annotations easily. There is example:


  Secret secret(int id) {
    checkRights("VIEW_SECRET")
    return Secret.get(id)
  }

  void checkRights(String rights) {
    if (!SpringSecurityUtils.ifAllGranted(rights)) {
      throw new IllegalAccessException("You don't have permission")
    }
  }

Tuesday, April 3, 2012

Accessing request parameters from UserDetailsService in Spring Security

If you need to use several properties to authenticate user with Spring Security, for example, by login and domain, there is no built-in way to do it. Even when you override UserDetailsService it only calls method with one username parameter.
Fortunately, there is easy way to access request context with Grails, so it is possible to extract any parameter you need, like:


import org.springframework.web.context.request.RequestContextHolder

class UserDetailsService implements GrailsUserDetailsService  {

  UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    def otherParameter = RequestContextHolder.requestAttributes.params.other
       ...
  }
}


Friday, October 21, 2011

HTTPS without certificate validation check

By default Java validates certificates when you do HTTPS queries. If it is not needed (for test environments, for example), it is possible to disable it (even it is much more complicated then it should be). Just add this code somewhere during initialization (this is groovy, so sorry some formatting):


  import javax.net.ssl.*
  import java.security.cert.*

  javax.net.ssl.TrustManager tm = new javax.net.ssl.X509TrustManager() {
    public boolean isClientTrusted(X509Certificate[] chain) { return true; }
    public boolean isHostTrusted(X509Certificate[] chain) { return true; }
    public boolean isServerTrusted(X509Certificate[] chain) { return true; }
    public X509Certificate[] getAcceptedIssuers() { return null; }
    public void checkClientTrusted(X509Certificate[] chain, String s){  }
    public void checkServerTrusted(X509Certificate[] chain, String s) {  }
  }
  HostnameVerifier hv = new HostnameVerifier() {
        public boolean verify(String urlHostName, SSLSession session) { return true; }
  }
  TrustManager[] trustAllCerts = new TrustManager[1];
  trustAllCerts[0] = tm;
  SSLContext sc = SSLContext.getInstance("SSL");
  sc.init(null, trustAllCerts, new java.security.SecureRandom());
  HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
  HttpsURLConnection.setDefaultHostnameVerifier(hv);



Friday, October 14, 2011

InvalidClassException: GrailsUser and plugin upgrade

Recently when I tried to deploy new version of application on live server without downtime, I got error:

2011-10-14 11:02:52,058 [Tribes-Task-Receiver-4] ERROR org.apache.catalina.ha.session.DeltaManager- Manager [localhost#]: Unable to receive message through TCP channel
java.io.InvalidClassException: org.codehaus.groovy.grails.plugins.springsecurity.GrailsUser; local class incompatible: stream classdesc serialVersionUID = -3114204362518930756, local class serialVersionUID =
        at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:579)
        at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1600)
        at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1513)
        at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1600)
        at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1513)
        at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1749)
        at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1346)
        at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1963)
        at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1887)
        at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1770)
        at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1346)
        at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1963)

Basically, error is trivial, just some Spring security classes are not versioned and cluster can't synchronize users data. Fortunately, as I have found out, no hacking is needed and it can be easily fixed by upgrading spring-security-core plugin to the latest version.

To upgrade to latest version, just uninstall plugin and install it again, like:

grails uninstall-plugin spring-security-core
grails install-plugin spring-security-core

Saturday, July 16, 2011

Spring security in grails - roles and permissions

There is nice plugin for using Spring security in Grails - it integrates nicely in application, can be heavily customized and is easy to use. I didn't had extensive experience with Spring security before, but all security frameworks that I used, have something that represents roles and permissions. Role is group of permissions, and permissions are either defined only for groups or can be assigned to users explicitly. From first glance at Spring security there is only concept for roles (or as they called in plugin - Authorities). It confused me very much and created impression of very basic framework.

It took some time to figure out, that on the contrary - Spring security is very powerful and flexible also in this sense. Basically, all it cares is what authorities you return in your users getAuthorities() method. So you can generate whatever hierarchy of permissions you want, possibly adjust it by the time or the day, or simply generate it on the fly.