From 1ed5f0ae7fda2d923fc96f923e6aefc25ec5c249 Mon Sep 17 00:00:00 2001 From: Guillaume Vincent Date: Fri, 15 Apr 2016 21:03:52 +0200 Subject: [PATCH] add self signed certificates if no certificates provided --- Dockerfile | 36 ++++++++++--- README.md | 1 + backend.conf.j2 | 56 +++++++++++++++++++ conf.d/backend.conf | 52 ------------------ conf.d/mime.types | 135 ++++++++++++++++++++++++++++++++++++++++++++++ conf.d/nginx.conf | 134 +++++++++++++++++++++++++++++++++++++++++++++ docker.env | 15 ++++++ dockersible/__init__.py | 0 dockersible/files.py | 44 +++++++++++++++ dockersible/ssl.py | 18 +++++++ entrypoint.sh | 5 ++ install.py | 59 ++++++++++++++++++++ mime.types | 135 ---------------------------------------------- nginx.conf | 134 --------------------------------------------- tests/templates/test.j2 | 3 ++ tests/test_dockersible.py | 85 +++++++++++++++++++++++++++++ 16 files changed, 583 insertions(+), 329 deletions(-) create mode 100644 backend.conf.j2 delete mode 100644 conf.d/backend.conf create mode 100644 conf.d/mime.types create mode 100644 conf.d/nginx.conf create mode 100644 docker.env create mode 100644 dockersible/__init__.py create mode 100644 dockersible/files.py create mode 100644 dockersible/ssl.py create mode 100644 entrypoint.sh create mode 100644 install.py delete mode 100644 mime.types delete mode 100644 nginx.conf create mode 100644 tests/templates/test.j2 create mode 100644 tests/test_dockersible.py diff --git a/Dockerfile b/Dockerfile index 1a479c6..b42c74f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,14 +1,34 @@ -FROM nginx:1.8 +FROM nginx:1.8-alpine + +RUN apk update && apk add \ + python3 \ + openssl \ + && python3 -m ensurepip \ + && rm -r /usr/lib/python*/ensurepip \ + && pip3 install --upgrade pip setuptools \ + && rm -rf /var/cache/apk/* + +RUN pip3 install Jinja2==2.8 RUN rm /etc/nginx/nginx.conf RUN rm /etc/nginx/mime.types -COPY nginx.conf /etc/nginx/nginx.conf -COPY mime.types /etc/nginx/mime.types +COPY conf.d/nginx.conf /etc/nginx/nginx.conf +COPY conf.d/mime.types /etc/nginx/mime.types RUN rm /etc/nginx/conf.d/default.conf -COPY conf.d /etc/nginx/conf.d/ +COPY conf.d/default.conf /etc/nginx/conf.d/default.conf + +RUN mkdir /dockersible +COPY dockersible/ /dockersible +COPY backend.conf.j2 / +COPY install.py / + +RUN mkdir /certificates +VOLUME ["/certificates"] + +COPY entrypoint.sh / +RUN chmod 755 /entrypoint.sh + +ENTRYPOINT ["/entrypoint.sh"] -COPY ssl/lesspass.com.crt /etc/ssl/certs/lesspass.com.crt -COPY ssl/lesspass.com.key /etc/ssl/private/lesspass.com.key -COPY ssl/dhparam.pem /etc/ssl/certs/dhparam.pem -COPY ssl/AddTrustExternalCARoot.crt /etc/ssl/certs/AddTrustExternalCARoot.crt \ No newline at end of file +CMD ["nginx", "-g", "daemon off;"] \ No newline at end of file diff --git a/README.md b/README.md index 160e53b..9dbcef1 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,3 @@ # nginx nginx container for lesspass + diff --git a/backend.conf.j2 b/backend.conf.j2 new file mode 100644 index 0000000..8749bcc --- /dev/null +++ b/backend.conf.j2 @@ -0,0 +1,56 @@ +server { + listen 80; + server_name {{ server_name }}; + + return 301 https://$server_name$request_uri; +} + + +server { + listen [::]:443 ssl; + listen 443 ssl; + + server_name {{ server_name }}; + + charset utf-8; + + ssl_certificate /etc/ssl/certs/certificate.crt; + ssl_certificate_key /etc/ssl/private/private.key; + + ssl_session_cache shared:SSL:20m; + ssl_session_timeout 30m; + + ssl_protocols TLSv1 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:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-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; + ssl_prefer_server_ciphers on; + ssl_stapling on; + ssl_stapling_verify on; + +{% if dhparam %} + ssl_dhparam {{ dhparam_path }}; +{% endif %} +{% if ssl_trusted_certificate %} + ssl_trusted_certificate {{ ssl_trusted_certificate_path }}; +{% endif %} + + add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; + + location ~ /(static|media)/ { + autoindex on; + root /backend/www; + } + + location ~ /(api|admin) { + proxy_pass http://backend:8000; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + } + + location / { + proxy_pass http://frontend:8080; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + } +} \ No newline at end of file diff --git a/conf.d/backend.conf b/conf.d/backend.conf deleted file mode 100644 index fa3207f..0000000 --- a/conf.d/backend.conf +++ /dev/null @@ -1,52 +0,0 @@ -server { - listen 80; - server_name localhost *.oslab.fr *.lesspass.com; - - return 301 https://$server_name$request_uri; -} - - -server { - listen [::]:443 ssl; - listen 443 ssl; - - server_name localhost *.oslab.fr *.lesspass.com; - - charset utf-8; - - ssl_certificate /etc/ssl/certs/lesspass.com.crt; - ssl_certificate_key /etc/ssl/private/lesspass.com.key; - - ssl_session_cache shared:SSL:20m; - ssl_session_timeout 30m; - - ssl_protocols TLSv1 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:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-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; - ssl_prefer_server_ciphers on; - ssl_stapling on; - ssl_stapling_verify on; - - ssl_dhparam /etc/ssl/certs/dhparam.pem; - ssl_trusted_certificate /etc/ssl/certs/AddTrustExternalCARoot.crt; - - add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; - - location ~ /(static|media)/ { - autoindex on; - root /backend/www; - } - - location ~ /(api|admin) { - proxy_pass http://backend:8000; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header Host $host; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - } - - location / { - proxy_pass http://frontend:8080; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header Host $host; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - } -} \ No newline at end of file diff --git a/conf.d/mime.types b/conf.d/mime.types new file mode 100644 index 0000000..b295c78 --- /dev/null +++ b/conf.d/mime.types @@ -0,0 +1,135 @@ +types { + + # Data interchange + + application/atom+xml atom; + application/json json map topojson; + application/ld+json jsonld; + application/rss+xml rss; + application/vnd.geo+json geojson; + application/xml rdf xml; + + + # JavaScript + + # Normalize to standard type. + # https://tools.ietf.org/html/rfc4329#section-7.2 + application/javascript js; + + + # Manifest files + + application/manifest+json webmanifest; + application/x-web-app-manifest+json webapp; + text/cache-manifest appcache; + + + # Media files + + audio/midi mid midi kar; + audio/mp4 aac f4a f4b m4a; + audio/mpeg mp3; + audio/ogg oga ogg opus; + audio/x-realaudio ra; + audio/x-wav wav; + image/bmp bmp; + image/gif gif; + image/jpeg jpeg jpg; + image/png png; + image/svg+xml svg svgz; + image/tiff tif tiff; + image/vnd.wap.wbmp wbmp; + image/webp webp; + image/x-jng jng; + video/3gpp 3gp 3gpp; + video/mp4 f4p f4v m4v mp4; + video/mpeg mpeg mpg; + video/ogg ogv; + video/quicktime mov; + video/webm webm; + video/x-flv flv; + video/x-mng mng; + video/x-ms-asf asf asx; + video/x-ms-wmv wmv; + video/x-msvideo avi; + + # Serving `.ico` image files with a different media type + # prevents Internet Explorer from displaying then as images: + # https://github.com/h5bp/html5-boilerplate/commit/37b5fec090d00f38de64b591bcddcb205aadf8ee + + image/x-icon cur ico; + + + # Microsoft Office + + application/msword doc; + application/vnd.ms-excel xls; + application/vnd.ms-powerpoint ppt; + application/vnd.openxmlformats-officedocument.wordprocessingml.document docx; + application/vnd.openxmlformats-officedocument.spreadsheetml.sheet xlsx; + application/vnd.openxmlformats-officedocument.presentationml.presentation pptx; + + + # Web fonts + + application/font-woff woff; + application/font-woff2 woff2; + application/vnd.ms-fontobject eot; + + # Browsers usually ignore the font media types and simply sniff + # the bytes to figure out the font type. + # https://mimesniff.spec.whatwg.org/#matching-a-font-type-pattern + # + # However, Blink and WebKit based browsers will show a warning + # in the console if the following font types are served with any + # other media types. + + application/x-font-ttf ttc ttf; + font/opentype otf; + + + # Other + + application/java-archive ear jar war; + application/mac-binhex40 hqx; + application/octet-stream bin deb dll dmg exe img iso msi msm msp safariextz; + application/pdf pdf; + application/postscript ai eps ps; + application/rtf rtf; + application/vnd.google-earth.kml+xml kml; + application/vnd.google-earth.kmz kmz; + application/vnd.wap.wmlc wmlc; + application/x-7z-compressed 7z; + application/x-bb-appworld bbaw; + application/x-bittorrent torrent; + application/x-chrome-extension crx; + application/x-cocoa cco; + application/x-java-archive-diff jardiff; + application/x-java-jnlp-file jnlp; + application/x-makeself run; + application/x-opera-extension oex; + application/x-perl pl pm; + application/x-pilot pdb prc; + application/x-rar-compressed rar; + application/x-redhat-package-manager rpm; + application/x-sea sea; + application/x-shockwave-flash swf; + application/x-stuffit sit; + application/x-tcl tcl tk; + application/x-x509-ca-cert crt der pem; + application/x-xpinstall xpi; + application/xhtml+xml xhtml; + application/xslt+xml xsl; + application/zip zip; + text/css css; + text/html htm html shtml; + text/mathml mml; + text/plain txt; + text/vcard vcard vcf; + text/vnd.rim.location.xloc xloc; + text/vnd.sun.j2me.app-descriptor jad; + text/vnd.wap.wml wml; + text/vtt vtt; + text/x-component htc; + +} diff --git a/conf.d/nginx.conf b/conf.d/nginx.conf new file mode 100644 index 0000000..988ca80 --- /dev/null +++ b/conf.d/nginx.conf @@ -0,0 +1,134 @@ +# nginx Configuration File +# http://wiki.nginx.org/Configuration + +# Run as a less privileged user for security reasons. +# user www www; + +# How many worker threads to run; +# "auto" sets it to the number of CPU cores available in the system, and +# offers the best performance. Don't set it higher than the number of CPU +# cores if changing this parameter. + +# The maximum number of connections for Nginx is calculated by: +# max_clients = worker_processes * worker_connections +worker_processes auto; + +# Maximum open file descriptors per process; +# should be > worker_connections. +worker_rlimit_nofile 8192; + +events { + # When you need > 8000 * cpu_cores connections, you start optimizing your OS, + # and this is probably the point at which you hire people who are smarter than + # you, as this is *a lot* of requests. + worker_connections 8000; +} + +# Default error log file +# (this is only used when you don't override error_log on a server{} level) +error_log /var/log/nginx/error.log warn; +pid /var/run/nginx.pid; + +http { + + # Hide nginx version information. + server_tokens off; + + # Define the MIME types for files. + include mime.types; + default_type application/octet-stream; + + # Update charset_types due to updated mime.types + charset_types text/css text/plain text/vnd.wap.wml application/javascript application/json application/rss+xml application/xml; + + # Format to use in log files + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + + # Default log file + # (this is only used when you don't override access_log on a server{} level) + access_log /var/log/nginx/access.log main; + + # How long to allow each connection to stay idle; longer values are better + # for each individual client, particularly for SSL, but means that worker + # connections are tied up longer. (Default: 65) + keepalive_timeout 20; + + # Speed up file transfers by using sendfile() to copy directly + # between descriptors rather than using read()/write(). + # For performance reasons, on FreeBSD systems w/ ZFS + # this option should be disabled as ZFS's ARC caches + # frequently used files in RAM by default. + sendfile on; + + # Tell Nginx not to send out partial frames; this increases throughput + # since TCP frames are filled up before being sent out. (adds TCP_CORK) + tcp_nopush on; + + + # Compression + + # Enable Gzip compressed. + gzip on; + + # Compression level (1-9). + # 5 is a perfect compromise between size and cpu usage, offering about + # 75% reduction for most ascii files (almost identical to level 9). + gzip_comp_level 5; + + # Don't compress anything that's already small and unlikely to shrink much + # if at all (the default is 20 bytes, which is bad as that usually leads to + # larger files after gzipping). + gzip_min_length 256; + + # Compress data even for clients that are connecting to us via proxies, + # identified by the "Via" header (required for CloudFront). + gzip_proxied any; + + # Tell proxies to cache both the gzipped and regular version of a resource + # whenever the client's Accept-Encoding capabilities header varies; + # Avoids the issue where a non-gzip capable client (which is extremely rare + # today) would display gibberish if their proxy gave them the gzipped version. + gzip_vary on; + + # Compress all output labeled with one of the following MIME-types. + gzip_types + application/atom+xml + application/javascript + application/json + application/ld+json + application/manifest+json + application/rss+xml + application/vnd.geo+json + application/vnd.ms-fontobject + application/x-font-ttf + application/x-web-app-manifest+json + application/xhtml+xml + application/xml + font/opentype + image/bmp + image/svg+xml + image/x-icon + text/cache-manifest + text/css + text/plain + text/vcard + text/vnd.rim.location.xloc + text/vtt + text/x-component + text/x-cross-domain-policy; + # text/html is always compressed by HttpGzipModule + + # This should be turned on if you are going to have pre-compressed copies (.gz) of + # static files available. If not it should be left off as it will cause extra I/O + # for the check. It is best if you enable this in a location{} block for + # a specific directory, or on an individual server{} level. + # gzip_static on; + + # Include files in the sites-enabled folder. server{} configuration files should be + # placed in the sites-available folder, and then the configuration should be enabled + # by creating a symlink to it in the sites-enabled folder. + # See doc/sites-enabled.md for more info. + include conf.d/*.conf; +} diff --git a/docker.env b/docker.env new file mode 100644 index 0000000..9ff7907 --- /dev/null +++ b/docker.env @@ -0,0 +1,15 @@ +############################### +## self-signed certificates ## +############################### +domain=lesspass.com +server_name=localhost +############################### +## use custom certificate ## +############################### +#domain, server_name, private_key and certificate are mandatory +#domain=lesspass.com +#server_name=localhost *.lesspass.com +#private_key=lesspass.com.key +#certificate=lesspass.com.crt +#dhparam=dhparam.pem +#ssl_trusted_certificate=AddTrustExternalCARoot.crt diff --git a/dockersible/__init__.py b/dockersible/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/dockersible/files.py b/dockersible/files.py new file mode 100644 index 0000000..0350b5d --- /dev/null +++ b/dockersible/files.py @@ -0,0 +1,44 @@ +import os +import shutil +import fnmatch + +from jinja2 import Template + + +def pattern_filter(file, patterns=None): + if patterns is None: + return True + + for p in patterns: + if fnmatch.fnmatch(file, p): + return True + + return False + + +def find(paths, patterns=None): + certificates = [] + for root, dirs, files in os.walk(paths): + for file in files: + if pattern_filter(file, patterns.split(',')): + certificates.append({'path': os.path.normpath(os.path.join(root, file))}) + return certificates + + +def copy(source, destination, basename=None, mode='0755'): + if not os.path.exists(destination): + os.makedirs(destination) + + shutil.copy2(src=source, dst=destination) + + file_path = os.path.join(destination, os.path.basename(source)) + os.chmod(file_path, int(mode, 8)) + + if basename: + os.rename(file_path, os.path.join(destination, basename)) + + +def template(source, context, destination): + jinja_template = Template(open(source).read()) + with open(destination, 'w') as f: + f.write(jinja_template.render(context)) diff --git a/dockersible/ssl.py b/dockersible/ssl.py new file mode 100644 index 0000000..b6c6c6a --- /dev/null +++ b/dockersible/ssl.py @@ -0,0 +1,18 @@ +import os +import shutil + + +def copy_certificates(certificates, destination='/etc/ssl', domain='example.org'): + private_key_folder = os.path.join(destination, 'private') + if not os.path.exists(private_key_folder): + os.makedirs(private_key_folder) + private_key = os.path.join(private_key_folder, domain + '.key') + shutil.copy2(certificates['key'], private_key) + os.chmod(private_key, 0o600) + + certificates_folder = os.path.join(destination, 'certs') + if not os.path.exists(certificates_folder): + os.makedirs(certificates_folder) + certificate = os.path.join(certificates_folder, domain + '.crt') + shutil.copy2(certificates['crt'], certificate) + os.chmod(certificate, 0o644) diff --git a/entrypoint.sh b/entrypoint.sh new file mode 100644 index 0000000..b06ce4c --- /dev/null +++ b/entrypoint.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +python3 install.py + +exec "$@" \ No newline at end of file diff --git a/install.py b/install.py new file mode 100644 index 0000000..4ff5320 --- /dev/null +++ b/install.py @@ -0,0 +1,59 @@ +import os + +import subprocess + +from dockersible.files import copy, template + + +def copy_certificates(): + copy(source=(os.path.join('/certificates', os.environ['private_key'])), + destination='/etc/ssl/private', + basename='private.key', + mode='0600') + copy(source=os.path.join('/certificates', os.environ['certificate']), + destination='/etc/ssl/certs', + basename='certificate.crt', + mode='0644') + context = { + 'server_name': os.environ['server_name'], + 'dhparam': False, + 'ssl_trusted_certificate': False + } + cert_folder = os.path.join('/etc/ssl/certs') + if 'dhparam' in os.environ: + dhparam = os.environ['dhparam'] + copy(source=os.path.join('/certificates', dhparam), destination=cert_folder, mode='0644') + context['dhparam'] = True + context['dhparam_path'] = os.path.join(cert_folder, dhparam) + if 'certificate' in os.environ: + certificate = os.environ['ssl_trusted_certificate'] + copy(source=os.path.join('/certificates', certificate), destination=cert_folder, mode='0644') + context['ssl_trusted_certificate'] = True + context['ssl_trusted_certificate_path'] = os.path.join(cert_folder, certificate) + return context + + +def create_certificates(): + cmd = """openssl req \ + -new \ + -newkey rsa:4096 \ + -days 365 \ + -nodes \ + -x509 \ + -subj "/C=US/ST=State/L=City/O=Company/CN=%s" \ + -keyout /etc/ssl/private/private.key \ + -out /etc/ssl/certs/certificate.crt""".format(os.environ['domain']) + subprocess.call(cmd, shell=True) + return { + 'server_name': os.environ['server_name'], + 'dhparam': False, + 'ssl_trusted_certificate': False + } + + +if __name__ == "__main__": + if 'private_key' in os.environ and 'certificate' in os.environ: + context = copy_certificates() + else: + context = create_certificates() + template('/backend.conf.j2', context, '/etc/nginx/conf.d/backend.conf') diff --git a/mime.types b/mime.types deleted file mode 100644 index b295c78..0000000 --- a/mime.types +++ /dev/null @@ -1,135 +0,0 @@ -types { - - # Data interchange - - application/atom+xml atom; - application/json json map topojson; - application/ld+json jsonld; - application/rss+xml rss; - application/vnd.geo+json geojson; - application/xml rdf xml; - - - # JavaScript - - # Normalize to standard type. - # https://tools.ietf.org/html/rfc4329#section-7.2 - application/javascript js; - - - # Manifest files - - application/manifest+json webmanifest; - application/x-web-app-manifest+json webapp; - text/cache-manifest appcache; - - - # Media files - - audio/midi mid midi kar; - audio/mp4 aac f4a f4b m4a; - audio/mpeg mp3; - audio/ogg oga ogg opus; - audio/x-realaudio ra; - audio/x-wav wav; - image/bmp bmp; - image/gif gif; - image/jpeg jpeg jpg; - image/png png; - image/svg+xml svg svgz; - image/tiff tif tiff; - image/vnd.wap.wbmp wbmp; - image/webp webp; - image/x-jng jng; - video/3gpp 3gp 3gpp; - video/mp4 f4p f4v m4v mp4; - video/mpeg mpeg mpg; - video/ogg ogv; - video/quicktime mov; - video/webm webm; - video/x-flv flv; - video/x-mng mng; - video/x-ms-asf asf asx; - video/x-ms-wmv wmv; - video/x-msvideo avi; - - # Serving `.ico` image files with a different media type - # prevents Internet Explorer from displaying then as images: - # https://github.com/h5bp/html5-boilerplate/commit/37b5fec090d00f38de64b591bcddcb205aadf8ee - - image/x-icon cur ico; - - - # Microsoft Office - - application/msword doc; - application/vnd.ms-excel xls; - application/vnd.ms-powerpoint ppt; - application/vnd.openxmlformats-officedocument.wordprocessingml.document docx; - application/vnd.openxmlformats-officedocument.spreadsheetml.sheet xlsx; - application/vnd.openxmlformats-officedocument.presentationml.presentation pptx; - - - # Web fonts - - application/font-woff woff; - application/font-woff2 woff2; - application/vnd.ms-fontobject eot; - - # Browsers usually ignore the font media types and simply sniff - # the bytes to figure out the font type. - # https://mimesniff.spec.whatwg.org/#matching-a-font-type-pattern - # - # However, Blink and WebKit based browsers will show a warning - # in the console if the following font types are served with any - # other media types. - - application/x-font-ttf ttc ttf; - font/opentype otf; - - - # Other - - application/java-archive ear jar war; - application/mac-binhex40 hqx; - application/octet-stream bin deb dll dmg exe img iso msi msm msp safariextz; - application/pdf pdf; - application/postscript ai eps ps; - application/rtf rtf; - application/vnd.google-earth.kml+xml kml; - application/vnd.google-earth.kmz kmz; - application/vnd.wap.wmlc wmlc; - application/x-7z-compressed 7z; - application/x-bb-appworld bbaw; - application/x-bittorrent torrent; - application/x-chrome-extension crx; - application/x-cocoa cco; - application/x-java-archive-diff jardiff; - application/x-java-jnlp-file jnlp; - application/x-makeself run; - application/x-opera-extension oex; - application/x-perl pl pm; - application/x-pilot pdb prc; - application/x-rar-compressed rar; - application/x-redhat-package-manager rpm; - application/x-sea sea; - application/x-shockwave-flash swf; - application/x-stuffit sit; - application/x-tcl tcl tk; - application/x-x509-ca-cert crt der pem; - application/x-xpinstall xpi; - application/xhtml+xml xhtml; - application/xslt+xml xsl; - application/zip zip; - text/css css; - text/html htm html shtml; - text/mathml mml; - text/plain txt; - text/vcard vcard vcf; - text/vnd.rim.location.xloc xloc; - text/vnd.sun.j2me.app-descriptor jad; - text/vnd.wap.wml wml; - text/vtt vtt; - text/x-component htc; - -} diff --git a/nginx.conf b/nginx.conf deleted file mode 100644 index 988ca80..0000000 --- a/nginx.conf +++ /dev/null @@ -1,134 +0,0 @@ -# nginx Configuration File -# http://wiki.nginx.org/Configuration - -# Run as a less privileged user for security reasons. -# user www www; - -# How many worker threads to run; -# "auto" sets it to the number of CPU cores available in the system, and -# offers the best performance. Don't set it higher than the number of CPU -# cores if changing this parameter. - -# The maximum number of connections for Nginx is calculated by: -# max_clients = worker_processes * worker_connections -worker_processes auto; - -# Maximum open file descriptors per process; -# should be > worker_connections. -worker_rlimit_nofile 8192; - -events { - # When you need > 8000 * cpu_cores connections, you start optimizing your OS, - # and this is probably the point at which you hire people who are smarter than - # you, as this is *a lot* of requests. - worker_connections 8000; -} - -# Default error log file -# (this is only used when you don't override error_log on a server{} level) -error_log /var/log/nginx/error.log warn; -pid /var/run/nginx.pid; - -http { - - # Hide nginx version information. - server_tokens off; - - # Define the MIME types for files. - include mime.types; - default_type application/octet-stream; - - # Update charset_types due to updated mime.types - charset_types text/css text/plain text/vnd.wap.wml application/javascript application/json application/rss+xml application/xml; - - # Format to use in log files - log_format main '$remote_addr - $remote_user [$time_local] "$request" ' - '$status $body_bytes_sent "$http_referer" ' - '"$http_user_agent" "$http_x_forwarded_for"'; - - # Default log file - # (this is only used when you don't override access_log on a server{} level) - access_log /var/log/nginx/access.log main; - - # How long to allow each connection to stay idle; longer values are better - # for each individual client, particularly for SSL, but means that worker - # connections are tied up longer. (Default: 65) - keepalive_timeout 20; - - # Speed up file transfers by using sendfile() to copy directly - # between descriptors rather than using read()/write(). - # For performance reasons, on FreeBSD systems w/ ZFS - # this option should be disabled as ZFS's ARC caches - # frequently used files in RAM by default. - sendfile on; - - # Tell Nginx not to send out partial frames; this increases throughput - # since TCP frames are filled up before being sent out. (adds TCP_CORK) - tcp_nopush on; - - - # Compression - - # Enable Gzip compressed. - gzip on; - - # Compression level (1-9). - # 5 is a perfect compromise between size and cpu usage, offering about - # 75% reduction for most ascii files (almost identical to level 9). - gzip_comp_level 5; - - # Don't compress anything that's already small and unlikely to shrink much - # if at all (the default is 20 bytes, which is bad as that usually leads to - # larger files after gzipping). - gzip_min_length 256; - - # Compress data even for clients that are connecting to us via proxies, - # identified by the "Via" header (required for CloudFront). - gzip_proxied any; - - # Tell proxies to cache both the gzipped and regular version of a resource - # whenever the client's Accept-Encoding capabilities header varies; - # Avoids the issue where a non-gzip capable client (which is extremely rare - # today) would display gibberish if their proxy gave them the gzipped version. - gzip_vary on; - - # Compress all output labeled with one of the following MIME-types. - gzip_types - application/atom+xml - application/javascript - application/json - application/ld+json - application/manifest+json - application/rss+xml - application/vnd.geo+json - application/vnd.ms-fontobject - application/x-font-ttf - application/x-web-app-manifest+json - application/xhtml+xml - application/xml - font/opentype - image/bmp - image/svg+xml - image/x-icon - text/cache-manifest - text/css - text/plain - text/vcard - text/vnd.rim.location.xloc - text/vtt - text/x-component - text/x-cross-domain-policy; - # text/html is always compressed by HttpGzipModule - - # This should be turned on if you are going to have pre-compressed copies (.gz) of - # static files available. If not it should be left off as it will cause extra I/O - # for the check. It is best if you enable this in a location{} block for - # a specific directory, or on an individual server{} level. - # gzip_static on; - - # Include files in the sites-enabled folder. server{} configuration files should be - # placed in the sites-available folder, and then the configuration should be enabled - # by creating a symlink to it in the sites-enabled folder. - # See doc/sites-enabled.md for more info. - include conf.d/*.conf; -} diff --git a/tests/templates/test.j2 b/tests/templates/test.j2 new file mode 100644 index 0000000..13c3927 --- /dev/null +++ b/tests/templates/test.j2 @@ -0,0 +1,3 @@ +{% if dhparam %} +ssl_dhparam {{ dhparam_path }}; +{% endif %} \ No newline at end of file diff --git a/tests/test_dockersible.py b/tests/test_dockersible.py new file mode 100644 index 0000000..07932d9 --- /dev/null +++ b/tests/test_dockersible.py @@ -0,0 +1,85 @@ +import os +import shutil +import tempfile +import unittest + +from dockersible.ssl import copy_certificates +from dockersible.files import find, copy, template + + +class DockersibleTestCase(unittest.TestCase): + def test_find(self): + parent_directory = os.path.dirname(os.path.realpath(__file__)) + ssl_directory = os.path.join(parent_directory, 'ssl') + certificates = find(paths=ssl_directory, patterns='*.key,*.crt') + for certificate in certificates: + expected_path = [os.path.join(ssl_directory, 'test.key'), os.path.join(ssl_directory, 'test.crt')] + self.assertTrue(certificate['path'] in expected_path) + + def test_copy_certificates(self): + temp_folder = tempfile.mkdtemp() + private_key_origin = os.path.join(temp_folder, 'test.key') + with open(private_key_origin, 'w') as f: f.write('') + certificate_origin = os.path.join(temp_folder, 'test.crt') + with open(certificate_origin, 'w') as f: f.write('') + certificates = { + 'key': private_key_origin, + 'crt': certificate_origin, + } + copy_certificates(certificates, temp_folder, 'oslab.fr') + private_key = os.path.join(temp_folder, 'private', 'oslab.fr.key') + self.assertTrue(os.path.exists(private_key)) + self.assertTrue((os.stat(private_key).st_mode & 0o777) == 0o600) + self.assertTrue(os.path.exists(private_key_origin)) + + certificate = os.path.join(temp_folder, 'certs', 'oslab.fr.crt') + self.assertTrue(os.path.exists(certificate)) + self.assertTrue((os.stat(certificate).st_mode & 0o777) == 0o644) + self.assertTrue(os.path.exists(certificate_origin)) + shutil.rmtree(temp_folder) + + def test_copy_file(self): + private_key_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'ssl', 'test.key') + destination = tempfile.mkdtemp() + copy(source=private_key_path, destination=destination) + self.assertTrue(os.path.exists(os.path.join(destination, 'test.key'))) + shutil.rmtree(destination) + + def test_copy_file_change_basename(self): + private_key_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'ssl', 'test.key') + destination = tempfile.mkdtemp() + copy(source=private_key_path, destination=destination, basename='lesspass.com.key', mode='0600') + self.assertTrue(os.path.exists(os.path.join(destination, 'lesspass.com.key'))) + shutil.rmtree(destination) + + def test_copy_file_change_mode(self): + private_key_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'ssl', 'test.key') + destination = tempfile.mkdtemp() + + copy(source=private_key_path, destination=destination) + expected_private_key_path = os.path.join(destination, 'test.key') + self.assertTrue((os.stat(expected_private_key_path).st_mode & 0o777) == 0o755) + + copy(source=private_key_path, destination=destination, basename='lesspass.com.key', mode='0600') + expected_private_key_path = os.path.join(destination, 'lesspass.com.key') + self.assertTrue((os.stat(expected_private_key_path).st_mode & 0o777) == 0o600) + + shutil.rmtree(destination) + + def test_template_module_with_source_file(self): + template_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'templates', 'test.j2') + destination = tempfile.mkdtemp() + context = { + 'dhparam': True, + 'dhparam_path': '/etc/ssl/certs/dhparam.pem' + } + destination_file = os.path.join(destination, 'test.txt') + + template(source=template_path, context=context, destination=destination_file) + + self.assertEqual('\nssl_dhparam /etc/ssl/certs/dhparam.pem;\n', open(destination_file).read()) + shutil.rmtree(destination) + + +if __name__ == '__main__': + unittest.main()