Securing Plone-Sites with https and nginx
At the plonator-sprint I finished a nginx-config to secure all authenticated traffic via https.
Some noteable things:
- There is more than one login-form. In fact I counted at least six different login-forms. Ever heard of 'failsafe_login_form'? Searching for /login_form will not be enough.
- The page you get after logging out has it's own login-form. Since I use this page to switch back to http I chose to remove the form by customizing the template 'logged_out.pt'.
- Since I redirect to https when Plone' s Authentication-cookie '__ac' is present calling '/logged_out' while still logged-in would result in an infinite recursion. That's why I break before the rule is called when '__ac' is still set.
- Don't use the login-portlet since I don't see how it can be delivered via https if you want to deliver the site with normal http.
- Never ever expose your zope-root or login using the zope-admin-Account via http since the zope-admins password is only uuencoded in a cookie!
Here is my config:
upstream myzope {
server localhost:8080;
}
ssl_certificate /home/starzel/nginx/starzel.crt;
ssl_certificate_key /home/starzel/nginx/starzel.key;
# http
server {
listen myserver.com:80;
server_name www.mysite.com;
access_log /var/log/nginx/mysite.com_access.log;
rewrite ^(.*)(/login_|/require_login|/failsafe_login_form)(.*) https://$server_name$1$2$3 redirect;
if ($http_cookie ~* "__ac=([^;]+)(?:;|$)" ) {
rewrite ^(.*) https://$host/$1 redirect;
}
location / {
proxy_pass http://myzope/VirtualHostBase/http/www.mysite.com:80/Plone/VirtualHostRoot/;
}
}
# https
server {
listen myserver.com:443 default ssl;
server_name www.mysite.com;
access_log /var/log/nginx/mysite.com_access.log;
if ($http_cookie ~* "__ac=([^;]+)(?:;|$)" ) {
# prevent infinite recursions between http and https
break;
}
rewrite ^(.*)(/logged_out)(.*) http://$server_name$1$2$3 redirect;
location / {
proxy_pass http://myzope/VirtualHostBase/https/www.mysite.com:443/Plone/VirtualHostRoot/;
}
}
# zmi
server {
listen myserver:443 ssl;
server_name manage.mysite.com;
access_log /var/log/nginx/heeschmusik_zmi.de_access.log;
location / {
proxy_pass http://myzope/VirtualHostBase/https/manage.myserver.com:443/VirtualHostRoot/;
}
}
The cookie-regex explained (thanks to Hanno Schulz and Vlad Vorobiev for their wisdom): $http_cookie (which is a string) is searched for anything containing '__ac=' followed by 1 or more characters which is not ';' (which would mean the cookie has no value), followed by either an ';' (signaling the beginning of another cookie) or the end of the line. If you are as ignorant of regex as me you might consider keeping this regex-cheatsheet close.
By the way, this site neither uses nginx nor is it not secured. But this one is: www.heeschmusik.de. I plan to move most sites to nginx in the near future.
Feeback appreciated.