diff options
Diffstat (limited to 'samples/services')
20 files changed, 819 insertions, 79 deletions
diff --git a/samples/services/modsecurity/docker/.htaccess b/samples/services/modsecurity/docker/.htaccess new file mode 100644 index 0000000..a2b059c --- /dev/null +++ b/samples/services/modsecurity/docker/.htaccess @@ -0,0 +1,3 @@ +RewriteEngine on
+RewriteCond %{REQUEST_URI} !^/index.html$
+RewriteRule . /index.html [L]
\ No newline at end of file diff --git a/samples/services/modsecurity/docker/Dockerfile b/samples/services/modsecurity/docker/Dockerfile new file mode 100644 index 0000000..5a01f21 --- /dev/null +++ b/samples/services/modsecurity/docker/Dockerfile @@ -0,0 +1,37 @@ +FROM owasp/modsecurity:v2-ubuntu-apache
+MAINTAINER Jing Lu lvjing5@huawei.com
+
+ARG COMMIT=v3.1/dev
+ARG REPO=SpiderLabs/owasp-modsecurity-crs
+ENV PARANOIA=1
+
+RUN a2enmod rewrite
+
+RUN apt-get update && \
+ apt-get -y install python git ca-certificates iproute2 vim
+
+RUN cd /opt && \
+ git clone https://github.com/${REPO}.git owasp-modsecurity-crs-3.1 && \
+ cd owasp-modsecurity-crs-3.1 && \
+ git checkout -qf ${COMMIT}
+
+RUN cd /opt && \
+ cp -R /opt/owasp-modsecurity-crs-3.1/ /etc/apache2/modsecurity.d/owasp-crs/ && \
+ mv /etc/apache2/modsecurity.d/owasp-crs/crs-setup.conf.example /etc/apache2/modsecurity.d/owasp-crs/crs-setup.conf && \
+ cd /etc/apache2/modsecurity.d && \
+ printf "include modsecurity.d/owasp-crs/crs-setup.conf\ninclude modsecurity.d/owasp-crs/rules/*.conf" > include.conf && \
+ sed -i -e 's/SecRuleEngine DetectionOnly/SecRuleEngine On/g' /etc/apache2/modsecurity.d/modsecurity.conf && \
+ a2enmod proxy proxy_http
+
+COPY proxy.conf /etc/apache2/modsecurity.d/proxy.conf
+COPY docker-entrypoint.sh /
+
+RUN chmod 777 /docker-entrypoint.sh
+
+COPY .htaccess /var/www/html/.htaccess
+COPY apache2.conf /etc/apache2/apache2.conf
+
+EXPOSE 80
+
+ENTRYPOINT ["/docker-entrypoint.sh"]
+CMD ["apachectl", "-D", "FOREGROUND"]
diff --git a/samples/services/modsecurity/docker/apache2.conf b/samples/services/modsecurity/docker/apache2.conf new file mode 100644 index 0000000..f7c62d6 --- /dev/null +++ b/samples/services/modsecurity/docker/apache2.conf @@ -0,0 +1,227 @@ +# This is the main Apache server configuration file. It contains the +# configuration directives that give the server its instructions. +# See http://httpd.apache.org/docs/2.4/ for detailed information about +# the directives and /usr/share/doc/apache2/README.Debian about Debian specific +# hints. +# +# +# Summary of how the Apache 2 configuration works in Debian: +# The Apache 2 web server configuration in Debian is quite different to +# upstream's suggested way to configure the web server. This is because Debian's +# default Apache2 installation attempts to make adding and removing modules, +# virtual hosts, and extra configuration directives as flexible as possible, in +# order to make automating the changes and administering the server as easy as +# possible. + +# It is split into several files forming the configuration hierarchy outlined +# below, all located in the /etc/apache2/ directory: +# +# /etc/apache2/ +# |-- apache2.conf +# | `-- ports.conf +# |-- mods-enabled +# | |-- *.load +# | `-- *.conf +# |-- conf-enabled +# | `-- *.conf +# `-- sites-enabled +# `-- *.conf +# +# +# * apache2.conf is the main configuration file (this file). It puts the pieces +# together by including all remaining configuration files when starting up the +# web server. +# +# * ports.conf is always included from the main configuration file. It is +# supposed to determine listening ports for incoming connections which can be +# customized anytime. +# +# * Configuration files in the mods-enabled/, conf-enabled/ and sites-enabled/ +# directories contain particular configuration snippets which manage modules, +# global configuration fragments, or virtual host configurations, +# respectively. +# +# They are activated by symlinking available configuration files from their +# respective *-available/ counterparts. These should be managed by using our +# helpers a2enmod/a2dismod, a2ensite/a2dissite and a2enconf/a2disconf. See +# their respective man pages for detailed information. +# +# * The binary is called apache2. Due to the use of environment variables, in +# the default configuration, apache2 needs to be started/stopped with +# /etc/init.d/apache2 or apache2ctl. Calling /usr/bin/apache2 directly will not +# work with the default configuration. + + +# Global configuration +# + +# +# ServerRoot: The top of the directory tree under which the server's +# configuration, error, and log files are kept. +# +# NOTE! If you intend to place this on an NFS (or otherwise network) +# mounted filesystem then please read the Mutex documentation (available +# at <URL:http://httpd.apache.org/docs/2.4/mod/core.html#mutex>); +# you will save yourself a lot of trouble. +# +# Do NOT add a slash at the end of the directory path. +# +#ServerRoot "/etc/apache2" + +# +# The accept serialization lock file MUST BE STORED ON A LOCAL DISK. +# +#Mutex file:${APACHE_LOCK_DIR} default + +# +# The directory where shm and other runtime files will be stored. +# + +DefaultRuntimeDir ${APACHE_RUN_DIR} + +# +# PidFile: The file in which the server should record its process +# identification number when it starts. +# This needs to be set in /etc/apache2/envvars +# +PidFile ${APACHE_PID_FILE} + +# +# Timeout: The number of seconds before receives and sends time out. +# +Timeout 300 + +# +# KeepAlive: Whether or not to allow persistent connections (more than +# one request per connection). Set to "Off" to deactivate. +# +KeepAlive On + +# +# MaxKeepAliveRequests: The maximum number of requests to allow +# during a persistent connection. Set to 0 to allow an unlimited amount. +# We recommend you leave this number high, for maximum performance. +# +MaxKeepAliveRequests 100 + +# +# KeepAliveTimeout: Number of seconds to wait for the next request from the +# same client on the same connection. +# +KeepAliveTimeout 5 + + +# These need to be set in /etc/apache2/envvars +User ${APACHE_RUN_USER} +Group ${APACHE_RUN_GROUP} + +# +# HostnameLookups: Log the names of clients or just their IP addresses +# e.g., www.apache.org (on) or 204.62.129.132 (off). +# The default is off because it'd be overall better for the net if people +# had to knowingly turn this feature on, since enabling it means that +# each client request will result in AT LEAST one lookup request to the +# nameserver. +# +HostnameLookups Off + +# ErrorLog: The location of the error log file. +# If you do not specify an ErrorLog directive within a <VirtualHost> +# container, error messages relating to that virtual host will be +# logged here. If you *do* define an error logfile for a <VirtualHost> +# container, that host's errors will be logged there and not here. +# +ErrorLog ${APACHE_LOG_DIR}/error.log + +# +# LogLevel: Control the severity of messages logged to the error_log. +# Available values: trace8, ..., trace1, debug, info, notice, warn, +# error, crit, alert, emerg. +# It is also possible to configure the log level for particular modules, e.g. +# "LogLevel info ssl:warn" +# +LogLevel warn + +# Include module configuration: +IncludeOptional mods-enabled/*.load +IncludeOptional mods-enabled/*.conf + +# Include list of ports to listen on +Include ports.conf + + +# Sets the default security model of the Apache2 HTTPD server. It does +# not allow access to the root filesystem outside of /usr/share and /var/www. +# The former is used by web applications packaged in Debian, +# the latter may be used for local directories served by the web server. If +# your system is serving content from a sub-directory in /srv you must allow +# access here, or in any related virtual host. +<Directory /> + Options FollowSymLinks + AllowOverride None + Require all denied +</Directory> + +<Directory /usr/share> + AllowOverride None + Require all granted +</Directory> + +<Directory /var/www/> + Options Indexes FollowSymLinks + AllowOverride All + Require all granted +</Directory> + +#<Directory /srv/> +# Options Indexes FollowSymLinks +# AllowOverride None +# Require all granted +#</Directory> + + + + +# AccessFileName: The name of the file to look for in each directory +# for additional configuration directives. See also the AllowOverride +# directive. +# +AccessFileName .htaccess + +# +# The following lines prevent .htaccess and .htpasswd files from being +# viewed by Web clients. +# +<FilesMatch "^\.ht"> + Require all denied +</FilesMatch> + + +# +# The following directives define some format nicknames for use with +# a CustomLog directive. +# +# These deviate from the Common Log Format definitions in that they use %O +# (the actual bytes sent including headers) instead of %b (the size of the +# requested file), because the latter makes it impossible to detect partial +# requests. +# +# Note that the use of %{X-Forwarded-For}i instead of %h is not recommended. +# Use mod_remoteip instead. +# +LogFormat "%v:%p %h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" vhost_combined +LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined +LogFormat "%h %l %u %t \"%r\" %>s %O" common +LogFormat "%{Referer}i -> %U" referer +LogFormat "%{User-agent}i" agent + +# Include of directories ignores editors' and dpkg's backup files, +# see README.Debian for details. + +# Include generic snippets of statements +IncludeOptional conf-enabled/*.conf + +# Include the virtual host configurations: +IncludeOptional sites-enabled/*.conf + +# vim: syntax=apache ts=4 sw=4 sts=4 sr noet diff --git a/samples/services/nginx/docker/process/nginx_process.sh b/samples/services/modsecurity/docker/build.sh index 00edc66..ea0feed 100755..100644 --- a/samples/services/nginx/docker/process/nginx_process.sh +++ b/samples/services/modsecurity/docker/build.sh @@ -8,5 +8,9 @@ # http://www.apache.org/licenses/LICENSE-2.0 # -service nginx restart +IMAGE_PATH=${IMAGE_PATH:-"localhost:5000"} +IMAGE_NAME=${IMAGE_NAME:-"clover-ns-modsecurity-crs"} +docker build -t $IMAGE_NAME . +docker tag $IMAGE_NAME $IMAGE_PATH/$IMAGE_NAME +docker push $IMAGE_PATH/$IMAGE_NAME diff --git a/samples/services/modsecurity/docker/docker-entrypoint.sh b/samples/services/modsecurity/docker/docker-entrypoint.sh new file mode 100644 index 0000000..e8e3013 --- /dev/null +++ b/samples/services/modsecurity/docker/docker-entrypoint.sh @@ -0,0 +1,15 @@ +#!/bin/bash +python -c "import re;import os;out=re.sub('(#SecAction[\S\s]*id:900000[\s\S]*paranoia_level=1\")','SecAction \\\\\n \"id:900000, \\\\\n phase:1, \\\\\n nolog, \\\\\n pass, \\\\\n t:none, \\\\\n setvar:tx.paranoia_level='+os.environ['PARANOIA']+'\"',open('/etc/apache2/modsecurity.d/owasp-crs/crs-setup.conf','r').read());open('/etc/apache2/modsecurity.d/owasp-crs/crs-setup.conf','w').write(out)" && \ +python -c "import re;import os;out=re.sub('(#SecAction[\S\s]*id:900330[\s\S]*total_arg_length=64000\")','SecAction \\\\\n \"id:900330, \\\\\n phase:1, \\\\\n nolog, \\\\\n pass, \\\\\n t:none, \\\\\n setvar:tx.total_arg_length=64000\"',open('/etc/apache2/modsecurity.d/owasp-crs/crs-setup.conf','r').read());open('/etc/apache2/modsecurity.d/owasp-crs/crs-setup.conf','w').write(out)" && \ + +if [ ! -z $PROXY ]; then + if [ $PROXY -eq 1 ]; then + APACHE_ARGUMENTS='-D crs_proxy' + if [ -z "$UPSTREAM" ]; then + export UPSTREAM=$(/sbin/ip route | grep ^default | perl -pe 's/^.*?via ([\d.]+).*/$1/g'):81 + fi + fi +fi + + +exec "$@" $APACHE_ARGUMENTS diff --git a/samples/services/modsecurity/docker/proxy.conf b/samples/services/modsecurity/docker/proxy.conf new file mode 100644 index 0000000..4dee0c9 --- /dev/null +++ b/samples/services/modsecurity/docker/proxy.conf @@ -0,0 +1,3 @@ +<IfDefine crs_proxy> + ProxyPass "/" "http://${UPSTREAM}/" +</IfDefine> diff --git a/samples/services/modsecurity/yaml/manifest.template b/samples/services/modsecurity/yaml/manifest.template new file mode 100644 index 0000000..afeb9dc --- /dev/null +++ b/samples/services/modsecurity/yaml/manifest.template @@ -0,0 +1,38 @@ +--- +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: {{ deploy_name }} + labels: + app: {{ deploy_name }} +spec: + replicas: 1 + template: + metadata: + labels: + app: {{ deploy_name }} + spec: + containers: + - name: {{ deploy_name }} + image: {{ image_path }}/{{ image_name }}:{{ image_tag }} + ports: + - containerPort: {{ http_port }} + env: + - name: PARANOIA + value: {{ paranoia_level }} + +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ deploy_name }} + labels: + app: {{ deploy_name }} +spec: + ports: + - port: {{ http_port }} + name: http-modsecurity-crs + targetPort: {{ http_port }} + selector: + app: {{ deploy_name }} +--- diff --git a/samples/services/modsecurity/yaml/modsecurity-deployment.yaml b/samples/services/modsecurity/yaml/modsecurity-deployment.yaml new file mode 100644 index 0000000..450ede5 --- /dev/null +++ b/samples/services/modsecurity/yaml/modsecurity-deployment.yaml @@ -0,0 +1,22 @@ +apiVersion: extensions/v1beta1
+kind: Deployment
+metadata:
+ name: modsecurity-crs
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ app: modsecurity-crs
+ template:
+ metadata:
+ labels:
+ app: modsecurity-crs
+ spec:
+ containers:
+ - name: modsecurity-crs
+ image: clover/clover-ns-modsecurity-crs
+ ports:
+ - containerPort: 80
+ env:
+ - name: PARANOIA
+ value: '1'
diff --git a/samples/services/modsecurity/yaml/modsecurity-service.yaml b/samples/services/modsecurity/yaml/modsecurity-service.yaml new file mode 100644 index 0000000..8548dca --- /dev/null +++ b/samples/services/modsecurity/yaml/modsecurity-service.yaml @@ -0,0 +1,13 @@ +apiVersion: v1
+kind: Service
+metadata:
+ name: modsecurity-crs
+spec:
+ type: NodePort
+ ports:
+ - port: 80
+ name: http-modsecurity-crs
+ protocol: TCP
+ targetPort: 80
+ selector:
+ app: modsecurity-crs
diff --git a/samples/services/modsecurity/yaml/render_yaml.py b/samples/services/modsecurity/yaml/render_yaml.py new file mode 100644 index 0000000..54f8069 --- /dev/null +++ b/samples/services/modsecurity/yaml/render_yaml.py @@ -0,0 +1,60 @@ +# Copyright (c) Authors of Clover +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 + +import argparse + +from jinja2 import Template + + +def render_yaml(args): + template_file = 'manifest.template' + out_file = 'modsecurity.yaml' + + try: + with open(template_file) as f: + tmpl = Template(f.read()) + output = tmpl.render( + image_path=args['image_path'], + image_name=args['image_name'], + image_tag=args['image_tag'], + deploy_name=args['deploy_name'], + http_port=args['http_port'], + paranoia_level=args['paranoia_level'] + ) + with open(out_file, "wb") as fh: + fh.write(output) + return "Generated manifest for {}".format(args['deploy_name']) + except Exception as e: + print(e) + return "Unable to generate manifest for {}".format( + args['deploy_name']) + + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument( + '--image_name', default='clover-ns-modsecurity-crs', + help='The image name to use') + parser.add_argument( + '--image_path', default='localhost:5000', + help='The path to the image to use') + parser.add_argument( + '--image_tag', default='latest', + help='The image tag to use') + parser.add_argument( + '--deploy_name', default='modsecurity-crs', + help='The k8s deploy name to use') + parser.add_argument( + '--http_port', default='80', + help='Analyze http traffic on this port') + parser.add_argument( + '--paranoia_level', default='1', + help='The modsecurity paranoia level') + + args = parser.parse_args() + print(render_yaml(vars(args))) + diff --git a/samples/services/nginx/docker/grpc/nginx.proto b/samples/services/nginx/docker/grpc/nginx.proto index 3779a82..8255719 100644 --- a/samples/services/nginx/docker/grpc/nginx.proto +++ b/samples/services/nginx/docker/grpc/nginx.proto @@ -36,6 +36,10 @@ message ConfigServer { string server_name = 2; string site_root = 3; string site_index = 4; + string upload_path_config = 5; + string locations = 6; + string upload_path_test = 7; + string files = 8; } message ConfigLB { diff --git a/samples/services/nginx/docker/grpc/nginx_client.py b/samples/services/nginx/docker/grpc/nginx_client.py index 7a07464..e4ddb2a 100644 --- a/samples/services/nginx/docker/grpc/nginx_client.py +++ b/samples/services/nginx/docker/grpc/nginx_client.py @@ -66,9 +66,21 @@ def modify_proxy(stub): def modify_server(stub): + loc = [] + val = {} + val['uri_match'] = "/test" + val['directive'] = "try_files $uri @default1" + val['path'] = "/test" + loc.append(val) + locations = pickle.dumps(loc) + files = pickle.dumps([]) response = stub.ModifyServer(nginx_pb2.ConfigServer( - server_port='9180', server_name='clover-server', - site_root='/var/www/html', site_index='index.nginx-debian.html')) + server_port='9180', server_name='clover-server1', + upload_path_config='/upload', + upload_path_test='/upload_test', + locations=locations, + files=files, + site_root='/var/www/html', site_index='index.html')) print(response.message) diff --git a/samples/services/nginx/docker/grpc/nginx_grpc_server.py b/samples/services/nginx/docker/grpc/nginx_grpc_server.py index 1dfe708..5ad64b5 100644 --- a/samples/services/nginx/docker/grpc/nginx_grpc_server.py +++ b/samples/services/nginx/docker/grpc/nginx_grpc_server.py @@ -8,9 +8,12 @@ from concurrent import futures import time +import os import sys import grpc import subprocess +import psutil +import shutil import pickle import logging import nginx_pb2 @@ -28,23 +31,32 @@ class Controller(nginx_pb2_grpc.ControllerServicer): logging.basicConfig(filename='nginx.log', level=logging.DEBUG) self.service_type = service_type self.out_file = '/etc/nginx/nginx.conf' - # self.out_file = 'testfile' + self.nginx = 0 if service_type == "proxy": - # self.template_file = 'templates/proxy.template' self.template_file = '/grpc/templates/proxy.template' self.ModifyProxy(nginx_pb2.ConfigProxy( server_port='9180', server_name='proxy-access-control', location_path='/', proxy_path='http://http-lb:9180', mirror_path='http://snort-ids:80'), "") if service_type == "server": - # self.template_file = 'templates/server.template' self.template_file = '/grpc/templates/server.template' + loc = [] + val = {} + val['uri_match'] = "/test" + val['directive'] = "try_files $uri @default1" + val['path'] = "/test" + loc.append(val) + locations = pickle.dumps(loc) + files = pickle.dumps([]) self.ModifyServer(nginx_pb2.ConfigServer( server_port='9180', server_name='clover-server', site_root='/var/www/html', - site_index='index.nginx-debian.html'), "") + upload_path_config='/upload', + upload_path_test='/upload_test', + locations=locations, + files=files, + site_index='index.html'), "") if service_type == "lb": - # self.template_file = 'templates/lb.template' self.template_file = '/grpc/templates/lb.template' slb_list = pickle.dumps( ['clover-server1:9180', 'clover-server2:9180', @@ -76,18 +88,54 @@ class Controller(nginx_pb2_grpc.ControllerServicer): def ModifyServer(self, r, context): try: + locations = pickle.loads(r.locations) + # Generate nginx config with open(self.template_file) as f: tmpl = Template(f.read()) output = tmpl.render( server_port=r.server_port, server_name=r.server_name, site_root=r.site_root, - site_index=r.site_index + site_index=r.site_index, + upload_path_config=r.upload_path_config, + upload_path_test=r.upload_path_test, + locations=locations ) with open(self.out_file, "wb") as fh: fh.write(output) + + # Make dirs for locations + for l in locations: + self.MakeDirs(l['path']) + + # Generate upload form for config + template_upload = '/grpc/templates/upload_form.template' + out_file = r.site_root + '/' + r.site_index + with open(template_upload) as f: + tmpl = Template(f.read()) + output = tmpl.render( + upload_path=r.upload_path_config + ) + with open(out_file, "wb") as fh: + fh.write(output) + + # Generate upload form for test + template_upload = '/grpc/templates/upload_form.template' + out_file = r.site_root + '/' + 'upload_test.html' + with open(template_upload) as f: + tmpl = Template(f.read()) + output = tmpl.render( + upload_path=r.upload_path_test + ) + with open(out_file, "wb") as fh: + fh.write(output) + msg = "Modified nginx config" - self.RestartNginx() + self.RestartNginx('custom') + + # Move files that have been uploaded + file_ops = pickle.loads(r.files) + self.MoveServerFiles(file_ops) except Exception as e: logging.debug(e) msg = "Failed to modify nginx config" @@ -113,9 +161,54 @@ class Controller(nginx_pb2_grpc.ControllerServicer): msg = "Failed to modify nginx config" return nginx_pb2.NginxReply(message=msg) - def RestartNginx(self): - subprocess.Popen( - ["service nginx restart"], shell=True) + def DeleteServerFiles(self, upload_folder): + for f in os.listdir(upload_folder): + file_path = os.path.join(upload_folder, f) + try: + if os.path.isfile(file_path): + os.unlink(file_path) + except Exception as e: + logging.debug(e) + + def MoveServerFiles(self, file_ops): + response = 1 + try: + for fo in file_ops: + try: + shutil.move(fo['src_file'], fo['dest_file']) + except Exception as e: + logging.debug(e) + response = 0 + except Exception as e: + logging.debug(e) + return response + + def RestartNginx(self, package='default'): + if package == 'custom': + if self.nginx == 0: + p = subprocess.Popen(["nginx"], + stdout=subprocess.PIPE, + shell=True, + preexec_fn=os.setsid) + else: + for proc in psutil.process_iter(): + if proc.name() == "nginx": + proc.kill() + p = subprocess.Popen(["nginx"], + stdout=subprocess.PIPE, + shell=True, + preexec_fn=os.setsid) + self.nginx = p + else: + subprocess.Popen( + ["service nginx restart"], shell=True) + + def MakeDirs(self, path, prefix='/var/www/html/'): + try: + path = prefix + path.strip('/') + os.makedirs(path) + except Exception as e: + logging.debug(e) def ProcessAlerts(self, request, context): try: diff --git a/samples/services/nginx/docker/grpc/nginx_pb2.py b/samples/services/nginx/docker/grpc/nginx_pb2.py index 3600b6d..5665fc4 100644 --- a/samples/services/nginx/docker/grpc/nginx_pb2.py +++ b/samples/services/nginx/docker/grpc/nginx_pb2.py @@ -19,7 +19,7 @@ DESCRIPTOR = _descriptor.FileDescriptor( name='nginx.proto', package='nginx', syntax='proto3', - serialized_pb=_b('\n\x0bnginx.proto\x12\x05nginx\"3\n\x0c\x41lertMessage\x12\x10\n\x08\x65vent_id\x18\x01 \x01(\t\x12\x11\n\tredis_key\x18\x02 \x01(\t\"w\n\x0b\x43onfigProxy\x12\x13\n\x0bserver_port\x18\x01 \x01(\t\x12\x13\n\x0bserver_name\x18\x02 \x01(\t\x12\x15\n\rlocation_path\x18\x03 \x01(\t\x12\x12\n\nproxy_path\x18\x04 \x01(\t\x12\x13\n\x0bmirror_path\x18\x05 \x01(\t\"_\n\x0c\x43onfigServer\x12\x13\n\x0bserver_port\x18\x01 \x01(\t\x12\x13\n\x0bserver_name\x18\x02 \x01(\t\x12\x11\n\tsite_root\x18\x03 \x01(\t\x12\x12\n\nsite_index\x18\x04 \x01(\t\"j\n\x08\x43onfigLB\x12\x13\n\x0bserver_port\x18\x01 \x01(\t\x12\x13\n\x0bserver_name\x18\x02 \x01(\t\x12\x10\n\x08slb_list\x18\x03 \x01(\t\x12\x11\n\tslb_group\x18\x04 \x01(\t\x12\x0f\n\x07lb_path\x18\x05 \x01(\t\"\x1d\n\nNginxReply\x12\x0f\n\x07message\x18\x01 \x01(\t2\xeb\x01\n\nController\x12\x36\n\x0bModifyProxy\x12\x12.nginx.ConfigProxy\x1a\x11.nginx.NginxReply\"\x00\x12\x38\n\x0cModifyServer\x12\x13.nginx.ConfigServer\x1a\x11.nginx.NginxReply\"\x00\x12\x30\n\x08ModifyLB\x12\x0f.nginx.ConfigLB\x1a\x11.nginx.NginxReply\"\x00\x12\x39\n\rProcessAlerts\x12\x13.nginx.AlertMessage\x1a\x11.nginx.NginxReply\"\x00\x62\x06proto3') + serialized_pb=_b('\n\x0bnginx.proto\x12\x05nginx\"3\n\x0c\x41lertMessage\x12\x10\n\x08\x65vent_id\x18\x01 \x01(\t\x12\x11\n\tredis_key\x18\x02 \x01(\t\"w\n\x0b\x43onfigProxy\x12\x13\n\x0bserver_port\x18\x01 \x01(\t\x12\x13\n\x0bserver_name\x18\x02 \x01(\t\x12\x15\n\rlocation_path\x18\x03 \x01(\t\x12\x12\n\nproxy_path\x18\x04 \x01(\t\x12\x13\n\x0bmirror_path\x18\x05 \x01(\t\"\xb7\x01\n\x0c\x43onfigServer\x12\x13\n\x0bserver_port\x18\x01 \x01(\t\x12\x13\n\x0bserver_name\x18\x02 \x01(\t\x12\x11\n\tsite_root\x18\x03 \x01(\t\x12\x12\n\nsite_index\x18\x04 \x01(\t\x12\x1a\n\x12upload_path_config\x18\x05 \x01(\t\x12\x11\n\tlocations\x18\x06 \x01(\t\x12\x18\n\x10upload_path_test\x18\x07 \x01(\t\x12\r\n\x05\x66iles\x18\x08 \x01(\t\"j\n\x08\x43onfigLB\x12\x13\n\x0bserver_port\x18\x01 \x01(\t\x12\x13\n\x0bserver_name\x18\x02 \x01(\t\x12\x10\n\x08slb_list\x18\x03 \x01(\t\x12\x11\n\tslb_group\x18\x04 \x01(\t\x12\x0f\n\x07lb_path\x18\x05 \x01(\t\"\x1d\n\nNginxReply\x12\x0f\n\x07message\x18\x01 \x01(\t2\xeb\x01\n\nController\x12\x36\n\x0bModifyProxy\x12\x12.nginx.ConfigProxy\x1a\x11.nginx.NginxReply\"\x00\x12\x38\n\x0cModifyServer\x12\x13.nginx.ConfigServer\x1a\x11.nginx.NginxReply\"\x00\x12\x30\n\x08ModifyLB\x12\x0f.nginx.ConfigLB\x1a\x11.nginx.NginxReply\"\x00\x12\x39\n\rProcessAlerts\x12\x13.nginx.AlertMessage\x1a\x11.nginx.NginxReply\"\x00\x62\x06proto3') ) @@ -157,6 +157,34 @@ _CONFIGSERVER = _descriptor.Descriptor( message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='upload_path_config', full_name='nginx.ConfigServer.upload_path_config', index=4, + number=5, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='locations', full_name='nginx.ConfigServer.locations', index=5, + number=6, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='upload_path_test', full_name='nginx.ConfigServer.upload_path_test', index=6, + number=7, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='files', full_name='nginx.ConfigServer.files', index=7, + number=8, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), ], extensions=[ ], @@ -169,8 +197,8 @@ _CONFIGSERVER = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=196, - serialized_end=291, + serialized_start=197, + serialized_end=380, ) @@ -228,8 +256,8 @@ _CONFIGLB = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=293, - serialized_end=399, + serialized_start=382, + serialized_end=488, ) @@ -259,8 +287,8 @@ _NGINXREPLY = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=401, - serialized_end=430, + serialized_start=490, + serialized_end=519, ) DESCRIPTOR.message_types_by_name['AlertMessage'] = _ALERTMESSAGE @@ -313,8 +341,8 @@ _CONTROLLER = _descriptor.ServiceDescriptor( file=DESCRIPTOR, index=0, options=None, - serialized_start=433, - serialized_end=668, + serialized_start=522, + serialized_end=757, methods=[ _descriptor.MethodDescriptor( name='ModifyProxy', diff --git a/samples/services/nginx/docker/grpc/templates/server.template b/samples/services/nginx/docker/grpc/templates/server.template index b5f8f1f..c1582fa 100644 --- a/samples/services/nginx/docker/grpc/templates/server.template +++ b/samples/services/nginx/docker/grpc/templates/server.template @@ -3,69 +3,142 @@ worker_processes auto; pid /run/nginx.pid; events { - worker_connections 768; - # multi_accept on; + worker_connections 768; + # multi_accept on; } http { - ## - # Basic Settings - ## + ## + # Basic Settings + ## - sendfile on; - tcp_nopush on; - tcp_nodelay on; - keepalive_timeout 65; - types_hash_max_size 2048; - # server_tokens off; + sendfile on; + tcp_nopush on; + tcp_nodelay on; + keepalive_timeout 65; + types_hash_max_size 2048; + # server_tokens off; - include /etc/nginx/mime.types; - default_type application/octet-stream; + include /etc/nginx/mime.types; + default_type application/octet-stream; - ## - # SSL Settings - ## + ## + # SSL Settings + ## - ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE - ssl_prefer_server_ciphers on; + ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE + ssl_prefer_server_ciphers on; - ## - # Logging Settings - ## + ## + # Logging Settings + ## - access_log /var/log/nginx/access.log; - error_log /var/log/nginx/error.log; + access_log /var/log/nginx/access.log; + error_log /var/log/nginx/error.log; - ## - # Gzip Settings - ## + ## + # Gzip Settings + ## - gzip on; - gzip_disable "msie6"; + gzip on; + gzip_disable "msie6"; - # gzip_vary on; - # gzip_proxied any; - # gzip_comp_level 6; - # gzip_buffers 16 8k; - # gzip_http_version 1.1; - # gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; + # gzip_vary on; + # gzip_proxied any; + # gzip_comp_level 6; + # gzip_buffers 16 8k; + # gzip_http_version 1.1; + # gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; - ## - # Virtual Host Configs - ## + ## + # Virtual Host Configs + ## - include /etc/nginx/conf.d/*.conf; - #include /etc/nginx/sites-enabled/*; + include /etc/nginx/conf.d/*.conf; + #include /etc/nginx/sites-enabled/*; - server { - listen {{ server_port }}; - server_name {{ server_name }}; + server { + listen {{ server_port }}; + server_name {{ server_name }}; + client_max_body_size 500m; - root {{ site_root }}; - index {{ site_index }}; - } + root {{ site_root }}; + index {{ site_index }}; -} + {%- for l in locations %} + + location {{ l["uri_match"] }} { + {{ l["directive"] }}; + } + + {%- endfor %} + + location @default1 { + index ../index.html; + } + + location @default2 { + index ../../index.html; + } + + location @default3 { + index ../../../index.html; + } + + # Use to upload files for download + location {{ upload_path_config }} { + # Pass altered request body to this location + upload_pass @return_config; + + # Store files to this directory + upload_resumable on; + upload_state_store /tmp/state; + upload_store {{ site_root }}{{ upload_path_config }}; + + # Allow uploaded files to be read only by user + #upload_store_access user:r; + + # Set specified fields in request body + upload_set_form_field $upload_field_name.name "$upload_file_name"; + upload_set_form_field $upload_field_name.content_type "$upload_content_type"; + upload_set_form_field $upload_field_name.path "$upload_tmp_path"; + upload_set_form_field $upload_field_name.server "$server_name"; + + # Inform backend about hash and size of a file + upload_aggregate_form_field "$upload_field_name.md5" "$upload_file_md5"; + upload_aggregate_form_field "$upload_field_name.size" "$upload_file_size"; + upload_pass_form_field "^submit$|^description$"; + + upload_cleanup 400 404 499 500-505; + } + + location @return_config { + proxy_pass http://clover-controller:80; + proxy_http_version 1.1; + } + + # Use to upload files for performance testing + location {{ upload_path_test }} { + + upload_pass @return_path; + + # Store files to this directory + upload_resumable on; + upload_state_store /tmp/state; + upload_store {{ site_root }}{{ upload_path_test }}; + + upload_pass_form_field "^submit$|^description$"; + + upload_cleanup 400 404 499 500-505; + } + + location @return_path { + return 204; + } + + + } +} diff --git a/samples/services/nginx/docker/grpc/templates/upload_form.template b/samples/services/nginx/docker/grpc/templates/upload_form.template new file mode 100644 index 0000000..60f3967 --- /dev/null +++ b/samples/services/nginx/docker/grpc/templates/upload_form.template @@ -0,0 +1,19 @@ +<!DOCTYPE html> +<html> + <head> + <title>Test upload</title> + </head> + <body> + <h2>Select files to upload</h2> + <form name="upload" method="POST" enctype="multipart/form-data" action="{{ upload_path }}"> + <input type="file" name="file1"><br> + <input type="file" name="file2"><br> + <input type="file" name="file3"><br> + <input type="file" name="file4"><br> + <input type="file" name="file5"><br> + <input type="file" name="file6"><br> + <input type="submit" name="submit" value="Upload"> + <input type="hidden" name="test" value="value"> + </form> + </body> +</html> diff --git a/samples/services/nginx/docker/process/start_process.sh b/samples/services/nginx/docker/process/start_process.sh index b84d2d6..47d164b 100755 --- a/samples/services/nginx/docker/process/start_process.sh +++ b/samples/services/nginx/docker/process/start_process.sh @@ -8,8 +8,5 @@ # http://www.apache.org/licenses/LICENSE-2.0 # -# Start the nginx process -./process/nginx_process.sh - # Start the grpc server ./process/grpc_process.sh $1 -D diff --git a/samples/services/nginx/docker/subservices/lb/Dockerfile b/samples/services/nginx/docker/subservices/lb/Dockerfile index 3b13631..0cef954 100644 --- a/samples/services/nginx/docker/subservices/lb/Dockerfile +++ b/samples/services/nginx/docker/subservices/lb/Dockerfile @@ -20,7 +20,7 @@ RUN \ python-pip \ && \ # Install required python packages - python -m pip install grpcio redis jinja2 protobuf + python -m pip install grpcio redis jinja2 protobuf psutil COPY /process /process COPY /grpc /grpc diff --git a/samples/services/nginx/docker/subservices/proxy/Dockerfile b/samples/services/nginx/docker/subservices/proxy/Dockerfile index b063de7..07ac5f8 100644 --- a/samples/services/nginx/docker/subservices/proxy/Dockerfile +++ b/samples/services/nginx/docker/subservices/proxy/Dockerfile @@ -20,7 +20,7 @@ RUN \ python-pip \ && \ # Install required python packages - python -m pip install grpcio redis jinja2 protobuf + python -m pip install grpcio redis jinja2 protobuf psutil COPY /process /process COPY /grpc /grpc diff --git a/samples/services/nginx/docker/subservices/server/Dockerfile b/samples/services/nginx/docker/subservices/server/Dockerfile index 434a8d4..1a87c82 100644 --- a/samples/services/nginx/docker/subservices/server/Dockerfile +++ b/samples/services/nginx/docker/subservices/server/Dockerfile @@ -7,7 +7,7 @@ FROM ubuntu:16.04 LABEL maintainer="Eddie Arrage" maintainer_email="eddie.arrage@huawei.com" -LABEL version="0.1" description="Clover - Nginx HTTP Server" +LABEL version="0.2" description="Clover - Nginx HTTP Server" RUN \ apt-get update && apt-get install -y \ @@ -15,14 +15,106 @@ RUN \ wget \ libdnet \ net-tools \ -# Nginx as proxy - nginx \ +# Packages required to build nginx from source + build-essential \ + libpcre3-dev \ + libpcre3++-dev \ + libgeoip-dev \ + libxslt-dev \ + git \ +# Install required python packages python-pip \ && \ -# Install required python packages - python -m pip install grpcio redis jinja2 protobuf + python -m pip install grpcio redis jinja2 protobuf psutil \ +&& \ +# Get nginx and module add-on source + wget https://nginx.org/download/nginx-1.15.0.tar.gz && tar zxvf nginx-1.15.0.tar.gz \ +&& \ + wget https://ftp.pcre.org/pub/pcre/pcre-8.42.tar.gz && tar xzvf pcre-8.42.tar.gz \ +&& \ + wget http://www.zlib.net/zlib-1.2.11.tar.gz && tar xzvf zlib-1.2.11.tar.gz \ +&& \ + wget https://www.openssl.org/source/openssl-1.1.0f.tar.gz && tar xzvf openssl-1.1.0f.tar.gz \ +&& \ + git clone https://github.com/Austinb/nginx-upload-module.git \ +&& \ + wget https://github.com/arut/nginx-rtmp-module/archive/v1.2.1.tar.gz && tar xzvf v1.2.1.tar.gz +RUN rm -rf *.tar.gz + +# Build supporting modules +ENV LDFLAGS -fPIC +WORKDIR /pcre-8.42 +RUN ./configure +RUN make +RUN make install + +WORKDIR /zlib-1.2.11 +RUN ./configure +RUN make +RUN make install + +WORKDIR /openssl-1.1.0f +RUN ./config +RUN make +RUN make install + +WORKDIR /nginx-1.15.0 + +# Build nginx with all modules in stock Ubuntu 16.04 version +# Add upload and rtmp modules +RUN ./configure \ + --prefix=/usr/share/nginx \ + --http-fastcgi-temp-path=/var/lib/nginx/fastcgi \ + --http-scgi-temp-path=/var/lib/nginx/scgi \ + --sbin-path=/usr/sbin/nginx \ + --conf-path=/etc/nginx/nginx.conf \ + --error-log-path=/var/log/nginx/error.log \ + --http-log-path=/var/log/nginx/access.log \ + --pid-path=/run/nginx.pid \ + --lock-path=/var/lock/nginx.lock \ + --with-pcre=../pcre-8.42 \ + --with-pcre-jit \ + --with-ipv6 \ + --with-http_stub_status_module \ + # --with-http_image_filter_module \ + --with-http_xslt_module \ + --with-mail \ + --with-zlib=../zlib-1.2.11 \ + --with-openssl=../openssl-1.1.0f \ + --with-openssl-opt=enable-ec_nistp_64_gcc_128 \ + --with-openssl-opt=no-nextprotoneg \ + --with-openssl-opt=no-weak-ssl-ciphers \ + --with-openssl-opt=no-ssl3 \ + --with-http_ssl_module \ + --with-stream \ + --with-stream_ssl_module \ + --with-threads \ + --with-mail=dynamic \ + --with-mail_ssl_module \ + --http-client-body-temp-path=/var/lib/nginx/body \ + --http-proxy-temp-path=/var/lib/nginx/proxy \ + --with-http_realip_module \ + --with-http_geoip_module \ + --http-uwsgi-temp-path=/var/lib/nginx/uwsgi \ + --with-http_v2_module \ + --with-http_sub_module \ + --with-http_addition_module \ + --with-http_dav_module \ + --with-http_auth_request_module \ + --with-http_gunzip_module \ + --with-http_gzip_static_module \ + --with-debug \ + --add-module=../nginx-upload-module \ + --add-module=../nginx-rtmp-module-1.2.1 + +RUN make +RUN make install + +WORKDIR / +RUN mkdir /var/lib/nginx +RUN mkdir /var/www +RUN mkdir /var/www/html COPY /process /process COPY /grpc /grpc CMD ./process/start_process.sh server - |