From 1d643a92044561dd3061adb1a5fee2f49cc9029b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Le=20Ninivin?= <cedric.leninivin@tiolive.com>
Date: Fri, 28 Jun 2013 10:47:18 +0200
Subject: [PATCH] slaprunner: secure access to cloud9 with nginx

Nginx is set in front of cloud9 running in local with https to secure its access
---
 software/slaprunner/common.cfg                |  15 +++
 .../slaprunner/instance-resilient.cfg.jinja2  |   1 +
 .../slaprunner/instance-runner-export.cfg.in  |   6 +-
 .../slaprunner/instance-runner-import.cfg.in  |   5 +-
 software/slaprunner/instance-runner.cfg       | 107 +++++++++++++++++-
 software/slaprunner/launcher.in               |   6 +
 software/slaprunner/nginx_conf.in             |  43 +++++++
 7 files changed, 178 insertions(+), 5 deletions(-)
 create mode 100644 software/slaprunner/launcher.in
 create mode 100644 software/slaprunner/nginx_conf.in

diff --git a/software/slaprunner/common.cfg b/software/slaprunner/common.cfg
index c5ea15947..cdce374cf 100644
--- a/software/slaprunner/common.cfg
+++ b/software/slaprunner/common.cfg
@@ -7,6 +7,7 @@ extends =
   ../../component/dropbear/buildout.cfg
   ../../component/git/buildout.cfg
   ../../component/lxml-python/buildout.cfg
+  ../../component/nginx/buildout.cfg
   ../../component/rsync/buildout.cfg
   ../../stack/flask.cfg
   ../../stack/shacache-client.cfg
@@ -18,6 +19,7 @@ parts =
   rdiff-backup
   template
   eggs
+  nginx
 
   instance-runner-import
   instance-runner-export
@@ -66,6 +68,19 @@ output = ${buildout:directory}/instance-runner-export.cfg
 md5sum = 4028924d0edb61bdcfbf03bb2bac43b8
 mode = 0644
 
+[template_nginx_conf]
+recipe = slapos.recipe.download
+url = ${:_profile_base_location_}/nginx_conf.in
+filename = nginx_conf.in
+mode = 0644
+
+[template_launcher]
+recipe = slapos.recipe.download
+url = ${:_profile_base_location_}/launcher.in
+filename = launcher.in
+mode = 0644
+location = ${buildout:parts-directory}/${:_buildout_section_name_}
+
 [eggs]
 recipe = z3c.recipe.scripts
 eggs =
diff --git a/software/slaprunner/instance-resilient.cfg.jinja2 b/software/slaprunner/instance-resilient.cfg.jinja2
index f4c40fb48..4cd551136 100644
--- a/software/slaprunner/instance-resilient.cfg.jinja2
+++ b/software/slaprunner/instance-resilient.cfg.jinja2
@@ -34,6 +34,7 @@ config-domain = ${slap-parameter:domain}
 
 [publish-connection-informations]
 recipe = slapos.cookbook:publish
+1_info = Set your passord in slaprunner in order to access cloud9
 backend_url = ${request-runner:connection-backend_url}
 url = ${request-runner:connection-url}
 cloud9_url = ${request-runner:connection-cloud9_url}
diff --git a/software/slaprunner/instance-runner-export.cfg.in b/software/slaprunner/instance-runner-export.cfg.in
index 31aea46bd..811c10076 100644
--- a/software/slaprunner/instance-runner-export.cfg.in
+++ b/software/slaprunner/instance-runner-export.cfg.in
@@ -4,6 +4,10 @@ extends = ${template-runner:output}
 
 parts +=
     urls
+    certificate-authority
+    ca-nginx
+    nginx_conf
+    nginx-launcher
     slaprunner
     cron-entry-backup
 
@@ -22,6 +26,6 @@ rsync-binary = ${rsync:location}/bin/rsync
 <= resilient-publish-connection-parameter
 backend_url = $${slaprunner:access-url}
 url =  $${request-frontend:connection-site_url}
-cloud9_url = $${cloud9:access-url}
+cloud9_url = https://[$${nginx-frontend:ip}]:$${nginx-frontend:port}
 ssh_command = ssh $${dropbear-runner-server:host} -p $${dropbear-runner-server:port}
 password_recovery_code = $${recovery-code:passwd}
diff --git a/software/slaprunner/instance-runner-import.cfg.in b/software/slaprunner/instance-runner-import.cfg.in
index 9845d1036..bc27c241b 100644
--- a/software/slaprunner/instance-runner-import.cfg.in
+++ b/software/slaprunner/instance-runner-import.cfg.in
@@ -2,8 +2,11 @@
 extends = ${template-runner:output}
           ${pbsready-import:output}
 
-
 parts +=
+    certificate-authority
+    ca-nginx
+    nginx_conf
+    nginx-launcher
     slaprunner
 # have to repeat the next one, as it's not inherited from pbsready-import
     import-on-notification
diff --git a/software/slaprunner/instance-runner.cfg b/software/slaprunner/instance-runner.cfg
index 34dbb5111..1e6ed6e38 100644
--- a/software/slaprunner/instance-runner.cfg
+++ b/software/slaprunner/instance-runner.cfg
@@ -1,6 +1,10 @@
 [buildout]
 parts =
+  nginx_conf
+  nginx-launcher
   cloud9
+  certificate-authority
+  ca-nginx
   slaprunner
   test-runner
   sshkeys-dropbear-runner
@@ -25,6 +29,7 @@ etc = $${buildout:directory}/etc/
 var = $${buildout:directory}/var/
 srv = $${buildout:directory}/srv/
 bin = $${buildout:directory}/bin/
+tmp = $${buildout:directory}/tmp/
 
 sshkeys = $${:srv}/sshkeys
 services = $${:etc}/service/
@@ -35,6 +40,9 @@ run = $${:var}/run/
 backup = $${:srv}/backup/
 promises = $${:etc}/promise/
 test = $${:etc}/test/
+nginx-data = $${rootdirectory:srv}/nginx
+ca-dir = $${:srv}/ssl
+
 
 [runnerdirectory]
 recipe = slapos.cookbook:mkdirectory
@@ -57,7 +65,7 @@ bytes = 4
 # Deploy cloud9 and slaprunner
 [cloud9]
 recipe = slapos.cookbook:cloud9
-ip = $${slap-network-information:global-ipv6}
+ip = $${slap-network-information:local-ipv4}
 port = 30000
 wrapper = $${directory:services}/cloud9
 working-directory = $${runnerdirectory:home}
@@ -146,7 +154,98 @@ recipe = slapos.cookbook:dropbear.add_authorized_key
 key = $${slap-parameter:authorized-key}
 
 
-# Request frontend
+#----------------
+#--
+#-- Set nginx as a frontend
+[tempdirectory]
+recipe = slapos.cookbook:mkdirectory
+client_body_temp_path = $${directory:tmp}/client_body_temp_path
+proxy_temp_path = $${directory:tmp}/proxy_temp_path
+fastcgi_temp_path = $${directory:tmp}/fastcgi_temp_path
+uwsgi_temp_path = $${directory:tmp}/uwsgi_temp_path
+scgi_temp_path = $${directory:tmp}/scgi_temp_path
+
+[nginx-frontend]
+# Options
+nb_workers = 2
+# Network
+ip = $${slap-network-information:global-ipv6}
+port = 4443
+# Backend
+backend-ip = $${cloud9:ip}
+backend-port = $${cloud9:port}
+# SSL
+ssl-certificate = $${ca-nginx:cert-file}
+ssl-key = $${ca-nginx:key-file}
+# Log
+path_pid = $${directory:run}/nginx.pid
+path_log = $${directory:log}/nginx.log
+path_access_log = $${directory:log}/nginx.access.log
+path_error_log = $${directory:log}/nginx.error.log
+path_tmp = $${buildout:directory}/tmp
+# Config files
+path_nginx_conf = $${directory:etc}/nginx.conf
+# Executables
+bin_nginx = ${nginx:location}/sbin/nginx
+bin_launcher = $${directory:services}/launcher
+# Utils
+path_shell = ${dash:location}/bin/dash
+
+
+
+[nginx_conf]
+recipe = slapos.recipe.template:jinja2
+template = ${template_nginx_conf:location}/${template_nginx_conf:filename}
+rendered = $${nginx-frontend:path_nginx_conf}
+context =
+    section param_nginx_frontend nginx-frontend
+    section param_tempdir tempdirectory
+
+[nginx-launcher]
+recipe = slapos.recipe.template:jinja2
+template = ${template_launcher:location}/${template_launcher:filename}
+rendered = $${nginx-frontend:bin_launcher}
+mode = 700
+context =
+    section param_nginx_frontend nginx-frontend
+
+#----------------
+#--
+#-- ssl for nginx
+
+[certificate-authority]
+recipe = slapos.cookbook:certificate_authority
+openssl-binary = ${openssl:location}/bin/openssl
+ca-dir = $${directory:ca-dir}
+requests-directory = $${cadirectory:requests}
+wrapper = $${directory:services}/certificate_authority
+ca-private = $${cadirectory:private}
+ca-certs = $${cadirectory:certs}
+ca-newcerts = $${cadirectory:newcerts}
+ca-crl = $${cadirectory:crl}
+
+[cadirectory]
+recipe = slapos.cookbook:mkdirectory
+requests = $${directory:ca-dir}/requests/
+private = $${directory:ca-dir}/private/
+certs = $${directory:ca-dir}/certs/
+newcerts = $${directory:ca-dir}/newcerts/
+crl = $${directory:ca-dir}/crl/
+
+[ca-nginx]
+<= certificate-authority
+recipe = slapos.cookbook:certificate_authority.request
+key-file = $${cadirectory:certs}/nginx_frontend.key
+cert-file = $${cadirectory:certs}/nginx_frontend.crt
+executable = $${directory:services}/launcher
+wrapper = $${directory:services}/ca-launcher
+# Put domain name
+name = example.com
+
+
+#----------------
+#--
+#-- Request frontend
 [request-frontend]
 <= slap-connection
 recipe = slapos.cookbook:requestoptional
@@ -159,7 +258,9 @@ config-url = $${slaprunner:access-url}
 return = site_url
 
 
-# Send informations to SlapOS Master
+#----------------
+#--
+#-- Send informations to SlapOS Master
 [publish-connection-informations]
 recipe = slapos.cookbook:publish
 backend_url = $${slaprunner:access-url}
diff --git a/software/slaprunner/launcher.in b/software/slaprunner/launcher.in
new file mode 100644
index 000000000..094c1b933
--- /dev/null
+++ b/software/slaprunner/launcher.in
@@ -0,0 +1,6 @@
+#! {{ param_nginx_frontend['path_shell'] }}
+# BEWARE: This file is operated by slapgrid
+# BEWARE: It will be overwritten automatically
+
+# Run nginx
+exec {{ param_nginx_frontend['bin_nginx'] }} -c {{ param_nginx_frontend['path_nginx_conf'] }}
diff --git a/software/slaprunner/nginx_conf.in b/software/slaprunner/nginx_conf.in
new file mode 100644
index 000000000..fa7f16d32
--- /dev/null
+++ b/software/slaprunner/nginx_conf.in
@@ -0,0 +1,43 @@
+worker_processes {{ param_nginx_frontend['nb_workers'] }};
+
+pid {{ param_nginx_frontend['path_pid'] }};
+error_log {{ param_nginx_frontend['path_error_log'] }};
+
+daemon off;
+
+events {
+	worker_connections 1024;
+	accept_mutex off;
+}
+
+http {
+     default_type application/octet-stream;
+     access_log {{ param_nginx_frontend['path_access_log'] }} combined;
+
+     server {
+        listen [{{ param_nginx_frontend['ip'] }}]:{{ param_nginx_frontend['port'] }} ssl;
+        server_name _;
+        ssl_certificate     {{ param_nginx_frontend['ssl-certificate'] }};
+        ssl_certificate_key {{ param_nginx_frontend['ssl-key'] }};
+        ssl_protocols       SSLv3 TLSv1 TLSv1.1 TLSv1.2;
+        ssl_ciphers         HIGH:!aNULL:!MD5;
+
+        keepalive_timeout 5;
+        client_body_temp_path {{ param_tempdir['client_body_temp_path'] }};
+        proxy_temp_path {{ param_tempdir['proxy_temp_path'] }};
+        fastcgi_temp_path {{ param_tempdir['fastcgi_temp_path'] }};
+        uwsgi_temp_path {{ param_tempdir['uwsgi_temp_path'] }};
+        scgi_temp_path {{ param_tempdir['scgi_temp_path'] }};
+        location / {
+            auth_basic  "Restricted";
+            auth_basic_user_file   /srv/slapgrid-erp5/slappart2/etc/.htpasswd;
+            proxy_pass  http://{{ param_nginx_frontend['backend-ip'] }}:{{ param_nginx_frontend['backend-port'] }};
+            proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
+            proxy_redirect off;
+            proxy_buffering off;
+            proxy_set_header        Host            $host;
+            proxy_set_header        X-Real-IP       $remote_addr;
+            proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
+        }
+    }
+}
-- 
2.30.9