Преглед на файлове

add self signed certificates if no certificates provided

pull/342/head
Guillaume Vincent преди 8 години
родител
ревизия
1ed5f0ae7f
променени са 13 файла, в които са добавени 268 реда и са изтрити 14 реда
  1. +28
    -8
      Dockerfile
  2. +1
    -0
      README.md
  3. +10
    -6
      backend.conf.j2
  4. +0
    -0
      conf.d/mime.types
  5. +0
    -0
      conf.d/nginx.conf
  6. +15
    -0
      docker.env
  7. +0
    -0
      dockersible/__init__.py
  8. +44
    -0
      dockersible/files.py
  9. +18
    -0
      dockersible/ssl.py
  10. +5
    -0
      entrypoint.sh
  11. +59
    -0
      install.py
  12. +3
    -0
      tests/templates/test.j2
  13. +85
    -0
      tests/test_dockersible.py

+ 28
- 8
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
CMD ["nginx", "-g", "daemon off;"]

+ 1
- 0
README.md Целия файл

@@ -1,2 +1,3 @@
# nginx
nginx container for lesspass


conf.d/backend.conf → backend.conf.j2 Целия файл

@@ -1,6 +1,6 @@
server {
listen 80;
server_name localhost *.oslab.fr *.lesspass.com;
server_name {{ server_name }};

return 301 https://$server_name$request_uri;
}
@@ -10,12 +10,12 @@ server {
listen [::]:443 ssl;
listen 443 ssl;

server_name localhost *.oslab.fr *.lesspass.com;
server_name {{ server_name }};

charset utf-8;

ssl_certificate /etc/ssl/certs/lesspass.com.crt;
ssl_certificate_key /etc/ssl/private/lesspass.com.key;
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;
@@ -26,8 +26,12 @@ server {
ssl_stapling on;
ssl_stapling_verify on;

ssl_dhparam /etc/ssl/certs/dhparam.pem;
ssl_trusted_certificate /etc/ssl/certs/AddTrustExternalCARoot.crt;
{% 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;


mime.types → conf.d/mime.types Целия файл


nginx.conf → conf.d/nginx.conf Целия файл


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

+ 0
- 0
dockersible/__init__.py Целия файл


+ 44
- 0
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))

+ 18
- 0
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)

+ 5
- 0
entrypoint.sh Целия файл

@@ -0,0 +1,5 @@
#!/bin/sh

python3 install.py

exec "$@"

+ 59
- 0
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')

+ 3
- 0
tests/templates/test.j2 Целия файл

@@ -0,0 +1,3 @@
{% if dhparam %}
ssl_dhparam {{ dhparam_path }};
{% endif %}

+ 85
- 0
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()

Зареждане…
Отказ
Запис