[Kimchi-devel] [PATCH] [Wok] Use system's nginx proxy service.
Daniel Henrique Barboza
dhbarboza82 at gmail.com
Tue Jul 19 21:43:59 UTC 2016
Reviewed-by: Daniel Barboza <danielhb at linux.vnet.ibm.com>
Tested-by: Daniel Barboza <danielhb at linux.vnet.ibm.com>
Note: I had to do a few additional steps to make it work by source code
running in F23. SELinux complained about nginx accessing a file in my home
dir. I had to issue the following commands:
$ ausearch -c 'nginx' --raw | audit2allow -M my-nginx
$ semodule -X 300 -i my-nginx.pp
For this patch to properly work. This step is not needed when installing
WoK by the RPM.
On 07/18/2016 06:59 PM, pvital at linux.vnet.ibm.com wrote:
> From: Paulo Vital <pvital at linux.vnet.ibm.com>
>
> This patch removes the code that executes a dedicated nginx proxy, making Wok
> to use the system's nginx service. This is a requirement to make Wok acceptable
> in community repositories.
>
> It also make sure that a Wok executed from path different than installed (from
> a cloned and builded source code, for example) will create a symbolic link in
> system's nginx config dir to the running configuration file.
>
> This patch solves part of issue #25
>
> Signed-off-by: Paulo Vital <pvital at linux.vnet.ibm.com>
> ---
> src/nginx/wok.conf.in | 95 +++++++++++++++++++++------------------------------
> src/wok/config.py.in | 6 +++-
> src/wok/i18n.py | 2 ++
> src/wok/proxy.py | 28 ++++++++-------
> src/wok/server.py | 6 +---
> 5 files changed, 63 insertions(+), 74 deletions(-)
>
> diff --git a/src/nginx/wok.conf.in b/src/nginx/wok.conf.in
> index cb05e4d..823d94d 100644
> --- a/src/nginx/wok.conf.in
> +++ b/src/nginx/wok.conf.in
> @@ -22,71 +22,54 @@
> # This is a template file to be used to generate a nginx
> # proxy config file at wokd script.
>
> -user ${user};
> -worker_processes 1;
> +client_max_body_size ${max_body_size}k;
>
> -error_log /var/log/nginx/error.log;
> +# Timeout set to 10 minutes to avoid the 504 Gateway Timeout
> +# when Wok is processing a request.
> +proxy_connect_timeout 600;
> +proxy_send_timeout 600;
> +proxy_read_timeout 600;
> +send_timeout 600;
>
> -events {
> - worker_connections 1024;
> +map $http_upgrade $connection_upgrade {
> + default upgrade;
> + '' close;
> }
>
> -http {
> - log_format main '$remote_addr - $remote_user [$time_local] "$request" '
> - '$status $body_bytes_sent "$http_referer" '
> - '"$http_user_agent" "$http_x_forwarded_for"';
> -
> - access_log /var/log/nginx/access.log main;
> - sendfile on;
> +upstream websocket {
> + server 127.0.0.1:${websockets_port};
> +}
>
> - client_max_body_size ${max_body_size}k;
> +server {
> + listen ${host_addr}:${proxy_ssl_port} ssl;
>
> - # Timeout set to 10 minutes to avoid the 504 Gateway Timeout
> - # when Wok is processing a request.
> - proxy_connect_timeout 600;
> - proxy_send_timeout 600;
> - proxy_read_timeout 600;
> - send_timeout 600;
> + ssl_certificate ${cert_pem};
> + ssl_certificate_key ${cert_key};
> + ssl_protocols TLSv1.1 TLSv1.2;
> + ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA:@STRENGTH';
> + ssl_prefer_server_ciphers on;
> + ssl_dhparam ${dhparams_pem};
> + ssl_session_timeout ${session_timeout}m;
>
> - map $http_upgrade $connection_upgrade {
> - default upgrade;
> - '' close;
> - }
> + add_header Strict-Transport-Security "max-age=31536000; includeSubdomains;";
> + add_header X-Frame-Options DENY;
> + add_header X-Content-Type-Options nosniff;
> + add_header X-XSS-Protection "1; mode=block";
>
> - upstream websocket {
> - server 127.0.0.1:${websockets_port};
> + location / {
> + proxy_pass http://127.0.0.1:${cherrypy_port};
> + proxy_set_header Host $host;
> + proxy_set_header X-Real-IP $remote_addr;
> + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
> + proxy_redirect http://127.0.0.1:${cherrypy_port}/ https://$host:${proxy_ssl_port}/;
> }
>
> - server {
> - listen ${host_addr}:${proxy_ssl_port} ssl;
> -
> - ssl_certificate ${cert_pem};
> - ssl_certificate_key ${cert_key};
> - ssl_protocols TLSv1.1 TLSv1.2;
> - ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA:@STRENGTH';
> - ssl_prefer_server_ciphers on;
> - ssl_dhparam ${dhparams_pem};
> - ssl_session_timeout ${session_timeout}m;
> -
> - add_header Strict-Transport-Security "max-age=31536000; includeSubdomains;";
> - add_header X-Frame-Options DENY;
> - add_header X-Content-Type-Options nosniff;
> - add_header X-XSS-Protection "1; mode=block";
> -
> - location / {
> - proxy_pass http://127.0.0.1:${cherrypy_port};
> - proxy_set_header Host $host;
> - proxy_set_header X-Real-IP $remote_addr;
> - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
> - proxy_redirect http://127.0.0.1:${cherrypy_port}/ https://$host:${proxy_ssl_port}/;
> - }
> -
> - location /websockify {
> - proxy_pass http://websocket;
> - proxy_http_version 1.1;
> - proxy_set_header Upgrade $http_upgrade;
> - proxy_set_header Connection $connection_upgrade;
> - }
> + location /websockify {
> + proxy_pass http://websocket;
> + proxy_http_version 1.1;
> + proxy_set_header Upgrade $http_upgrade;
> + proxy_set_header Connection $connection_upgrade;
> }
> - ${http_config}
> }
> +
> +${http_config}
> diff --git a/src/wok/config.py.in b/src/wok/config.py.in
> index 1ca6f73..d0bca9b 100644
> --- a/src/wok/config.py.in
> +++ b/src/wok/config.py.in
> @@ -76,9 +76,10 @@ class Paths(object):
> self.prefix = self.get_prefix()
> self.installed = (self.prefix == '@pkgdatadir@')
> self.ui_dir = self.add_prefix('ui')
> + self.sys_nginx_conf_dir = '@sysconfdir@/nginx/conf.d'
>
> if self.installed:
> - self.nginx_conf_dir = '@sysconfdir@/nginx/conf.d'
> + self.nginx_conf_dir = self.sys_nginx_conf_dir
> self.state_dir = '@localstatedir@/lib/wok'
> self.log_dir = '@localstatedir@/log/wok'
> self.conf_dir = '@sysconfdir@/wok'
> @@ -119,6 +120,9 @@ class Paths(object):
> def get_template_path(self, resource):
> return os.path.join(self.ui_dir, 'pages/%s.tmpl' % resource)
>
> + def is_wok_installed(self):
> + return self.installed
> +
>
> paths = Paths()
>
> diff --git a/src/wok/i18n.py b/src/wok/i18n.py
> index d6cb17c..33107ee 100644
> --- a/src/wok/i18n.py
> +++ b/src/wok/i18n.py
> @@ -55,6 +55,8 @@ messages = {
> "WOKUTILS0004E": _("Invalid data value '%(value)s'"),
> "WOKUTILS0005E": _("Invalid data unit '%(unit)s'"),
>
> + "WOKPROXY0001E": _("Unable to (re)start system's nginx.service. Details: '%(error)s'"),
> +
> # These messages (ending with L) are for user log purposes
> "WOKCOL0001L": _("Request made on collection"),
> "WOKRES0001L": _("Request made on resource"),
> diff --git a/src/wok/proxy.py b/src/wok/proxy.py
> index a74e88a..cf978ad 100644
> --- a/src/wok/proxy.py
> +++ b/src/wok/proxy.py
> @@ -26,11 +26,12 @@
>
> import os
> import pwd
> -import subprocess
> from string import Template
>
> from wok import sslcert
> from wok.config import paths
> +from wok.exception import OperationFailed
> +from wok.utils import run_command
>
>
> HTTP_CONFIG = """
> @@ -110,18 +111,21 @@ def _create_proxy_config(options):
> config_file.write(data)
> config_file.close()
>
> + # If not running from the installed path (from a cloned and builded source
> + # code), create a symbolic link in system's dir to prevent errors on read
> + # SSL certifications.
> + if not paths.is_wok_installed():
> + dst = os.path.join(paths.sys_nginx_conf_dir, "wok.conf")
> + if os.path.isfile(dst) or os.path.islink(dst):
> + os.remove(dst)
> + os.symlink(os.path.join(nginx_config_dir, "wok.conf"), dst)
> +
>
> def start_proxy(options):
> """Start nginx reverse proxy."""
> _create_proxy_config(options)
> - nginx_config_dir = paths.nginx_conf_dir
> - config_file = "%s/wok.conf" % nginx_config_dir
> - cmd = ['nginx', '-c', config_file]
> - subprocess.call(cmd)
> -
> -
> -def terminate_proxy():
> - """Stop nginx process."""
> - config_file = "%s/wok.conf" % paths.nginx_conf_dir
> - term_proxy_cmd = ['nginx', '-s', 'stop', '-c', config_file]
> - subprocess.call(term_proxy_cmd)
> + # Restart system's nginx service to reload wok configuration
> + cmd = ['systemctl', 'restart', 'nginx.service']
> + output, error, retcode = run_command(cmd, silent=True)
> + if retcode != 0:
> + raise OperationFailed('WOKPROXY0001E', {'error': error})
> diff --git a/src/wok/server.py b/src/wok/server.py
> index 8a02596..b1185e3 100644
> --- a/src/wok/server.py
> +++ b/src/wok/server.py
> @@ -33,7 +33,7 @@ from wok.config import config as configParser
> from wok.config import paths, PluginConfig, WokConfig
> from wok.control import sub_nodes
> from wok.model import model
> -from wok.proxy import start_proxy, terminate_proxy
> +from wok.proxy import start_proxy
> from wok.reqlogger import RequestLogger
> from wok.root import WokRoot
> from wok.safewatchedfilehandler import SafeWatchedFileHandler
> @@ -180,10 +180,6 @@ class Server(object):
> self.app = cherrypy.tree.mount(WokRoot(model_instance, dev_env),
> config=self.configObj)
> self._load_plugins(options)
> -
> - # Terminate proxy when cherrypy server is terminated
> - cherrypy.engine.subscribe('exit', terminate_proxy)
> -
> cherrypy.lib.sessions.init()
>
> def _load_plugins(self, options):
More information about the Kimchi-devel
mailing list