[Kimchi-devel] [PATCH] [Wok] Use system's nginx proxy service.

Aline Manera alinefm at linux.vnet.ibm.com
Thu Jul 21 14:11:55 UTC 2016



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.

The session timeout is configurable in the wok config file so you should 
not assume 10 minutes.
You will need to get the timeout value and do the right count to set the 
nginx config file.

> +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
> +

In other part of the code, we are accessing self.installed directly! Any 
special reason to create this new function?
Seems like too Java huh

>   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