lemur/docs/production/index.rst

291 lines
9.9 KiB
ReStructuredText
Raw Normal View History

2015-06-22 22:47:27 +02:00
Production
**********
There are several steps needed to make Lemur production ready. Here we focus on making Lemur more reliable and secure.
Basics
======
Because of the sensitivity of the information stored and maintain by Lemur it is important that you follow standard host hardening practices:
- Run Lemur with a limited user
- Disabled any unneeded service
- Enable remote logging
.. _CredentialManagement:
Credential Management
---------------------
Lemur often contains credentials such as mutual SSL keys that are used to communicate with third party resources and for encrypting stored secrets. Lemur comes with the ability
to automatically encrypt these keys such that your keys not be in clear text.
The keys are located within lemur/keys and broken down by environment
To utilize this ability use the following commands:
``lemur lock``
and
``lemur unlock``
If you choose to use this feature ensure that the KEY are decrypted before Lemur starts as it will have trouble communicating with the database otherwise.
SSL
====
Nginx
-----
Nginx is a very popular choice to serve a Python project:
- It's fast.
- It's lightweight.
- Configuration files are simple.
Nginx doesn't run any Python process, it only serves requests from outside to
the Python server.
Therefor there are two steps:
- Run the Python process.
- Run Nginx.
You will benefit from having:
- the possibility to have several projects listening to the port 80;
- your web site processes won't run with admin rights, even if --user doesn't
work on your OS;
- the ability to manage a Python process without touching Nginx or the other
processes. It's very handy for updates.
You must create a Nginx configuration file for Lemur. On GNU/Linux, they usually
go into /etc/nginx/conf.d/. Name it lemur.conf.
The minimal configuration file to run the site is::
server {
listen 80;
server_name www.yourwebsite.com;
location / {
proxy_pass http://127.0.0.1:5000;
}
}
`proxy_pass` just passes the external request to the Python process.
The port much match the one used by the 0bin process of course.
You can make some adjustments to get a better user experience::
server_tokens off;
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
server {
listen 80;
return 301 https://$host$request_uri;
}
server {
listen 443;
access_log /var/log/nginx/log/lemur.access.log;
error_log /var/log/nginx/log/lemur.error.log;
location /api {
proxy_pass http://127.0.0.1:5000;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
proxy_redirect off;
proxy_buffering off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location / {
<<<<<<< HEAD
2015-06-22 22:47:27 +02:00
root /apps/lemur/lemur/static/dist;
=======
root /www/lemur/lemur/static/dist;
include mime.types;
>>>>>>> b978435... Merge pull request #21 from kevgliss/buildfixes
2015-06-22 22:47:27 +02:00
index index.html;
}
}
This makes Nginx serve the favicon and static files which is is much better at than python.
It is highly recommended that you deploy SSL when deploying Lemur. This may be obvious given Lemur's purpose but the
sensitive nature of Lemur and what it controls makes this essential. This is a sample config for Lemur that also terminates SSL::
server_tokens off;
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
server {
listen 80;
return 301 https://$host$request_uri;
}
server {
listen 443;
access_log /var/log/nginx/log/lemur.access.log;
error_log /var/log/nginx/log/lemur.error.log;
# certs sent to the client in SERVER HELLO are concatenated in ssl_certificate
ssl_certificate /path/to/signed_cert_plus_intermediates;
ssl_certificate_key /path/to/private_key;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
# Diffie-Hellman parameter for DHE ciphersuites, recommended 2048 bits
ssl_dhparam /path/to/dhparam.pem;
# modern configuration. tweak to your needs.
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:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK';
ssl_prefer_server_ciphers on;
# HSTS (ngx_http_headers_module is required) (15768000 seconds = 6 months)
add_header Strict-Transport-Security max-age=15768000;
# OCSP Stapling ---
# fetch OCSP records from URL in ssl_certificate and cache them
ssl_stapling on;
ssl_stapling_verify on;
## verify chain of trust of OCSP response using Root CA and Intermediate certs
ssl_trusted_certificate /path/to/root_CA_cert_plus_intermediates;
resolver <IP DNS resolver>;
location /api {
proxy_pass http://127.0.0.1:5000;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
proxy_redirect off;
proxy_buffering off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location / {
<<<<<<< HEAD
2015-06-22 22:47:27 +02:00
root /apps/lemur/lemur/static/dist;
=======
root /www/lemur/lemur/static/dist;
include mime.types;
>>>>>>> b978435... Merge pull request #21 from kevgliss/buildfixes
2015-06-22 22:47:27 +02:00
index index.html;
}
}
Apache
------
An example apache config::
<VirtualHost *:443>
...
SSLEngine on
SSLCertificateFile /path/to/signed_certificate
SSLCertificateChainFile /path/to/intermediate_certificate
SSLCertificateKeyFile /path/to/private/key
SSLCACertificateFile /path/to/all_ca_certs
# intermediate configuration, tweak to your needs
SSLProtocol all -SSLv2 -SSLv3
SSLCipherSuite 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
SSLHonorCipherOrder on
# HSTS (mod_headers is required) (15768000 seconds = 6 months)
Header always set Strict-Transport-Security "max-age=15768000"
...
</VirtualHost>
Also included in the configurations above are several best practices when it comes to deploying SSL. Things like enabling
HSTS, disabling vulnerable ciphers are all good ideas when it comes to deploying Lemur into a production environment.
.. note::
This is a rather incomplete apache config for running Lemur (needs mod_wsgi etc.,), if you have a working apache config please let us know!
2015-06-22 22:47:27 +02:00
.. seealso::
`Mozilla SSL Configuration Generator <https://mozilla.github.io/server-side-tls/ssl-config-generator/>`_
.. _UsingSupervisor:
Supervisor
==========
Supervisor is a very nice way to manage you Python processes. We won't cover
the setup (which is just apt-get install supervisor or pip install supervisor
most of the time), but here is a quick overview on how to use it.
Create a configuration file named supervisor.ini::
[unix_http_server]
file=/tmp/supervisor.sock;
[supervisorctl]
serverurl=unix:///tmp/supervisor.sock;
[rpcinterface:supervisor]
supervisor.rpcinterface_factory=supervisor.rpcinterface:make_main_rpcinterface
[supervisord]
logfile=/tmp/lemur.log
logfile_maxbytes=50MB
logfile_backups=2
loglevel=trace
pidfile=/tmp/supervisord.pid
nodaemon=false
minfds=1024
minprocs=200
user=lemur
[program:lemur]
command=python /path/to/lemur/manage.py manage.py start
directory=/path/to/lemur/
environment=PYTHONPATH='/path/to/lemur/'
user=lemur
autostart=true
autorestart=true
The 4 first entries are just boiler plate to get you started, you can copy
them verbatim.
The last one define one (you can have many) process supervisor should manage.
It means it will run the command::
python manage.py start
In the directory, with the environment and the user you defined.
This command will be ran as a daemon, in the background.
`autostart` and `autorestart` just make it fire and forget: the site will always be
running, even it crashes temporarily or if you restart the machine.
The first time you run supervisor, pass it the configuration file::
supervisord -c /path/to/supervisor.ini
Then you can manage the process by running::
supervisorctl -c /path/to/supervisor.ini
It will start a shell from were you can start/stop/restart the service
You can read all errors that might occurs from /tmp/lemur.log.