jelastic grails redirects http to https - grails

I have one domain app.mydomain.com which is mapped with A record to public IP (from tomcat server that belongs to mysub.jelastic.dogado.eu)
I've configured SSL custom certificates and all HTTPS requests works very well.
All i need is that my app to use just HTTPS, all HTTP requests to be redirected to HTTPS,
Acordingly with spring security plugin (1.2.7.4 that i have on my app) i configured in this way:
grails.plugins.springsecurity.secureChannel.useHeaderCheckChannelSecurity = true
grails.plugins.springsecurity.portMapper.httpPort = 8080
grails.plugins.springsecurity.portMapper.httpsPort = 8443
grails.plugins.springsecurity.secureChannel.secureHeaderName = 'X-Forwarded-Proto'
grails.plugins.springsecurity.secureChannel.secureHeaderValue = 'http'
grails.plugins.springsecurity.secureChannel.insecureHeaderName = 'X-Forwarded-Proto'
grails.plugins.springsecurity.secureChannel.insecureHeaderValue = 'https'
grails.plugins.springsecurity.auth.forceHttps = true
grails.plugins.springsecurity.secureChannel.definition = [
'/**': 'REQUIRES_SECURE_CHANNEL'
]
On localhost it is working very good, all http requests were redirected to https but in jelastic nothig happend. I tried many configuration, replacing https port to 8743/443, but the same results. Any help will be apreciated.
Thanks a lot,
Catalin

The X-Forwarded-Proto header is only set if you have a load balancer in your environment (or using the shared resolver, but since you're using a custom SSL certificate that cannot apply in this case).
If you don't have a load balancer in your environment, that is why the check does not work - since those headers are simply not set.
If you do have a load balancer, all requests to your Tomcat are directed to port 80 (redirected via port forwarding to 8080); that includes requests sent to https (because the load balancer performs 'SSL offload' in this case. Therefore you are seeking an impossible combination in your grails rules (8743 and X-Forwarded-Proto). Depending on your environment topology you will have one of these cases or the other, but not both.
EDIT: You should also double-check your server.xml to make sure you have this:
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="443" />
Note the redirectPort value; it should be 443 because this is the port that will be sent to the browser for a redirect - with a load balancer (or Jelastic Shared Resolver) proxying the requests, the browser needs to request on port 443 (even though the Tomcat SSL connector is configured on 8743 - if applicable), because the proxy uses standard port numbering (i.e. https:// without any port number = 443).
Even if you are working with a standalone Tomcat (no load balancer, and not via the Jelastic Shared Resolver), those requests to 443 will be automatically forwarded to 8743 for you.

Thanks Damien, your answer solved the issue. For anyone interested this is the configuration(Config.groovy):
production {
grails.app.context = "/"
grails.serverURL = "https://yourdomain.com"
grails.plugins.springsecurity.portMapper.httpPort = 80
grails.plugins.springsecurity.portMapper.httpsPort = 443
grails.plugins.springsecurity.auth.forceHttps = true
grails.plugins.springsecurity.secureChannel.definition = [
'/**': 'REQUIRES_SECURE_CHANNEL'
]
}
Put this in server.xml:
<Connector port="80" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="443" />
I suppose 8080 also works.
Make war, deploy.

Related

Using apache SSL reverse proxy with a rails application

I have a rails application running on a private subnet, using port 8080, without SSL enabled.
I also have an Apache SSL server on a DMZ, which I use as a reverse proxy to the rails application I mention first.
The problem is, rails include some absolute url in the generated code, with adresses beginning with http://...
If i use config.force_ssl = true as I read here or there, there is a infinite redirection, because rails sees the requests coming as plain HTTP and issues a redirect to HTTPS, but as the client already is.
The solution was simple enough: put this line in the reverse proxy configuration file :
RequestHeader set X-Forwarded-Proto "https"

Amazon Load Balancer sticky sessions with ajp:8009

We configured ELB with sticky sessions for the JSESSIONID cookie for two tomcats (tomcat1 and tomcat2)(Flow is - Apache Http Server - ELB - tomcats)
AJP protocol with port 8009 has been configured on tomcat side as from AWS ELB there is no AJP option, we have configured with tcp:8009
So the Apache httpd.conf entry is, (xxx.amazonaws.com is ELB name)
BalancerMember ajp://xxx.amazonaws.com:8009
Somehow the sticky session is not working, the http request is sent to both tomcat servers. Is it because of the protocol on ELB side (tcp:8009)? We are not sure what is missing here, Need help!!
Once you change it to TCP you lose sticky sessions. It is an ELB limitation. You might be able to get away with switching the protocol to HTTP but with a different port other than 80.
Unless I am mistaken, you might have to setup an HA Proxy or something else instead of the ELB. Something that can do both TCP with sticky.
It is well know that websockets+sticky doesn't work on amazon.
https://forums.aws.amazon.com/thread.jspa?messageID=627367

AWS ELB keeps showing private IP in Location header on redirect

We are running a simple Rails 4.0 app (on Ubuntu 14.04) with config.force_ssl = true. SSL is uploaded to our ELB and both 443 and 80 ports on ELB forward to 80 on the servers.
We keep failing our PCI scan because with HTTP/1.0 the private IP of the ELB shows up in Location header. Any ides on how to fix this? I have researched this extensively for days and really stuck now.
$ telnet app.ourwebsite.com 80
GET / HTTP/1.0
HTTP/1.1 301 Moved Permanently
...
*Location: https://172.31.26.236/*
Server: nginx/1.6.2 + Phusion Passenger 4.0.57
Set-Cookie: AWSELB=...
The reason why it's failing PCI compliance is because the test being used, nessus plugin 10759, uses HTTP 1.0 and doesn't send a host header, and the AWS ELB crafts its own host header when it connects to your instance and for whatever reason sets it to the internal IP of the load balancer.
Here's a capture of such a request using Apache's mod_forensics. Note the host header, which is set to the internal IP of the load balancer:
+11143:551306af:1|GET / HTTP/1.1|host:10.3.2.57|X-Forwarded-For:REDACTED|X-Forwarded-Port:443|X-Forwarded-Proto:https|Connection:keep-alive
This is how the request was made (on *nix using bash):
(echo -ne "GET / HTTP/1.0\r\n\r\n"; sleep 2) | openssl s_client -connect 1.2.3.4:443
Where 1.2.3.4 is the IP address of your ELB. You must craft the request like this because the ELB won't accept \n\n directly typed into openssl.
Note that the only header sent here was GET.
My site was failing a PCI scan, which lead me here, so I felt this needed further explanation.
It sounds like your ELB is receiving https and then forwarding on http. So your Rails server doesn't need to worry about SSL, since the only thing it's communicating with is the ELB.
(This is how we have it set up also.)
So you can remove config.force_ssl = true from your Rails server and make your ELB require SSL.

Grails Spring Security redirect to login page using https

I have a Grails app using Spring Security Core running on an AWS machine behind a load balancer.
The load balancer decrypts the ssl connections and forwards to port 8080 of our instance adding appropriate X-Forwarded-Proto headers.
I would like any direct access to a secured page to redirect to the login page using https.
For example a request https://myapp.com/private/page should redirect to https://myapp.com/login/auth
I put this in my config.groovy:
grails.plugin.springsecurity.secureChannel.definition = [
'/login/**': 'REQUIRES_SECURE_CHANNEL'
]
but this causes a redirect loop (HTTP code 302) to the http login page (http://myapp.com/login/auth)
Then I tried just with:
grails.plugin.springsecurity.secureChannel.useHeaderCheckChannelSecurity = true
grails.plugin.springsecurity.auth.forceHttps = true
but this causes a redirect (HTTP code 302) to the http login page (http://myapp.com/login/auth)
The issue is presentig just with the production setup (war deployed to Tomcat behind the load balancer).
If I test the same config.groovy on my loacal dev machine the redirect to https://myapp.com/login/auth happens just fine.
I tried to specify a different httpsPort for spring security, again it works on my local dev machine but it is completely ignored in the deployed app that keeps redirecting to http
No luck lurking at similar posts, any idea?
I also am hosting my Grails app with Spring Security Core 2.0-RC4 on AWS with https and a load balancer, and thanks to spock99 (above) and Ravi L of AWS, I got it working.
I did the following in config.groovy:
// Required because user auth uses absolute redirects
grails.serverURL = "http://example.com"
grails.plugin.springsecurity.secureChannel.definition = [
'/assets/**': 'ANY_CHANNEL',// make js, css, images available to logged out pages
'/**': 'REQUIRES_SECURE_CHANNEL',
]
// overriding values in DefaultSecurityConfig.groovy from the SpringSecurityCore 2.0-RC4
grails.plugin.springsecurity.secureChannel.useHeaderCheckChannelSecurity = true
grails.plugin.springsecurity.portMapper.httpPort = 80
grails.plugin.springsecurity.portMapper.httpsPort = 443
NOTE: The following were not needed in Spring Security Core 2.0-RC4 - they are already in DefaultSecurityConfig.groovy
secureHeaderName = 'X-Forwarded-Proto'
secureHeaderValue = 'http'
insecureHeaderName = 'X-Forwarded-Proto'
insecureHeaderValue = 'https'
I was getting false 'Unhealthy' readings because hitting '/' returns a 302 redirect to /login/auth, so I added a health() method to HomeController (which I mapped to '/health') for AWS to hit:
class HomeController {
#Secured('IS_AUTHENTICATED_FULLY')
def index() { }
#Secured('permitAll')
def health() { render '' }
}
Key for me was that session cookies were not being handled properly with multiple instance running on the Load Balancer (I did not discover this until setting the minimum instance to 2), so in order for users to be able to log in and stay logged in, I did the following on AWS:
1. At Services / Elastic Beanstalk / Configuration / Load Balancing
a. set Application health check URL: /health
b. left Session Stickiness: unchecked
2. At Services / EC2 / Load Balancers / Description / Port Configuration:
For both port 80 (HTTP) and 443 (HTTPS)
1. Edit and select 'Enable Application Generated Cookie Stickiness'
2. Cookie Name: JSESSIONID
I just went through the same scenario. Got stuck on the https, then the redirects, and now all is well. Use these Config.groovy settings:
grails.plugin.springsecurity.secureChannel.useHeaderCheckChannelSecurity = true
grails.plugin.springsecurity.portMapper.httpPort = 80
grails.plugin.springsecurity.portMapper.httpsPort = 443
grails.plugin.springsecurity.secureChannel.secureHeaderName = 'X-Forwarded-Proto'
grails.plugin.springsecurity.secureChannel.secureHeaderValue = 'http'
grails.plugin.springsecurity.secureChannel.insecureHeaderName = 'X-Forwarded-Proto'
grails.plugin.springsecurity.secureChannel.insecureHeaderValue = 'https'
Note for those not using springsecurity 2.0, it is 'plugins' and not 'plugin' without the 's'.
My beanstalk load balancer settings look like this (I have an SSL cert installed, I didn't show it):
In the EC2 load balancer settings make sure your listeners are set right:
And finally in the EC2 security groups make sure the EB accepts requests on ports 80 and 443 from the ELB:
Note that nowhere in my setup of anything do I ever reference ports 8080 or 8443, even though that is what I use on my localhost for testing. Somebody reading this may think about trying to use those ports to fix the issues. My setup didn't require that.
I faced similar issue in similar environment where the front end was on https and behind the firewall grails server was on http.
When session was timed out, ajax and angular $http used to get a redirect message to http://myclient.com/myWar/login/auth. This redirect request used to cause access denied in browser because original url was https and mixed content was disabled.
I used to get SCRIPT7002: XMLHttpRequest: Network Error 0x80700013, Could not complete the operation due to error 80700013.”
This error occurred only in production and not in test environment.
Fix is simple, simply add the following to the configuration file.
grails.serverURL = "https://mywebsitespublicaddress.com/myWar"

Grails Spring Security appending :8080 to URL when behind Apache proxy

In production my Grails app is running on Tomcat port 8080 and sits behind an Apache proxy; port 80. All functions work except for authentication. When a user tries logging into the app Spring Security appends :8080 to the target URL and the connection times out since the request can't be routed.
I have already set the following in config.groovy but no success:
grails.serverURL = "http://domain.tld/${appName}"
grails.plugins.springsecurity.portMapper.httpPort = "80"
grails.plugins.springsecurity.portMapper.httpsPort = "443"
The issue occurs when I try with either built-in authentication or OpenID. The app had been working well for over 6 months before my hosting provider made changes by plugged a hole and started blocking port 8080 from the outside.
I just need Spring Security to write the URL without :8080
Any help is appreciated, thanks!
UPDATE
In the end the issue was with the host I was using. Something to do with Apache ProxyPass. The same application works fine on the new production VPS. Thanks for the input guys.
Add the following to your Config.groovy file:
grails.server.port.http = 80
I would consider change tomcat to port 80 and forward all apache requests to port 80. Pay attention to use x-forward proto header tag by spring security.
Already answered in the question
mod_rewrite not working to secure grails application
The tomcat configuration change works like a charm.

Resources