Changeset - 3352797ee517
[Not reviewed]
0 5 0
Branko Majic (branko) - 9 years ago 2016-11-22 22:25:09
branko@majic.rs
MAR-68: When enforcing TLS in web_server, wsgi_website, or php_website roles, send connecting clients proper HSTS policy via Strict-Transport-Security header.
5 files changed with 33 insertions and 3 deletions:
0 comments (0 inline, 0 general)
docs/rolereference.rst
Show inline comments
 
@@ -1125,25 +1125,27 @@ Role dependencies
 
~~~~~~~~~~~~~~~~~
 

	
 
Depends on the following roles:
 

	
 
* **common**
 

	
 

	
 
Parameters
 
~~~~~~~~~~
 

	
 
**default_enforce_https** (boolean, optional, ``True``)
 
  Specify if HTTPS should be enforced for the default virtual host or not. If
 
  enforced, clients connecting via plaintext will be redirected to HTTPS.
 
  enforced, clients connecting via plaintext will be redirected to HTTPS, and
 
  clients will be served with ``Strict-Transport-Security`` header with value of
 
  ``max-age=31536000; includeSubDomains``.
 

	
 
**default_https_tls_certificate** (string, optional, ``{{ lookup('file', tls_certificate_dir + '/' + ansible_fqdn + '_https.pem') }}``)
 
  X.509 certificate used for TLS for HTTPS service. The file will be stored in
 
  directory ``/etc/ssl/certs/`` under name ``{{ ansible_fqdn }}_https.pem``.
 

	
 
**default_https_tls_key** (string, optional, ``{{ lookup('file', tls_private_key_dir + '/' + ansible_fqdn + '_https.key') }}``)
 
  Private key used for TLS for HTTPS service. The file will be stored in
 
  directory ``/etc/ssl/private/`` under name ``{{ ansible_fqdn }}_https.key``.
 

	
 
**web_default_title** (string, optional, ``Welcome``)
 
  Title for the default web page shown to users (if no other vhosts were matched).
 

	
 
@@ -1250,25 +1252,27 @@ Parameters
 
  UID of the dedicated website administrator user. The user will be member of
 
  website group.
 

	
 
**deny_files_regex** (list, optional, ``[]``)
 
  List of regular expressions for matching files/locations to which the web
 
  server should deny access. This is useful to block access to any sensitive
 
  files that should not be served directly by the web server. The format must be
 
  compatible with regular expressions used by ``nginx`` for ``location ~``
 
  syntax.
 

	
 
**enforce_https** (boolean, optional, ``True``)
 
  Specify if HTTPS should be enforced for the website or not. If enforced,
 
  clients connecting via plaintext will be redirected to HTTPS.
 
  clients connecting via plaintext will be redirected to HTTPS, and clients will
 
  be served with ``Strict-Transport-Security`` header with value of
 
  ``max-age=31536000; includeSubDomains``.
 

	
 
**fqdn** (string, mandatory)
 
  Fully-qualified domain name where the website is reachable. This value is used
 
  for calculating the user/group name for dedicated website user, as well as
 
  home directory of the website user (where data/code should be stored at).
 

	
 
**index** (string, optional, ``index.php``)
 
  Space-separated list of files which should be treated as index files by the
 
  web server. The web server will attempt opening these index files, in
 
  succession, until the first match, or until it runs out of matches, when a
 
  client requests an URI pointing to directory.
 

	
 
@@ -1443,25 +1447,27 @@ Parameters
 
  **comment** (string, mandatory)
 
    Comment describing the configuration option.
 

	
 
  **value** (string, mandatory)
 
    Configuration option.
 

	
 
**admin_uid** (integer, optional, ``whatever OS picks``)
 
  UID of the dedicated website administrator user. The user will be member of
 
  website group.
 

	
 
**enforce_https** (boolean, optional, ``True``)
 
  Specify if HTTPS should be enforced for the website or not. If enforced,
 
  clients connecting via plaintext will be redirected to HTTPS.
 
  clients connecting via plaintext will be redirected to HTTPS, and clients will
 
  be served with ``Strict-Transport-Security`` header with value of
 
  ``max-age=31536000; includeSubDomains``.
 

	
 
**fqdn** (string, mandatory)
 
  Fully-qualified domain name where the website is reachable. This value is used
 
  for calculating the user/group name for dedicated website user, as well as
 
  home directory of the website user (where data/code should be stored at).
 

	
 
**futures_version** (string, optional, ``3.0.5``)
 
  Version of ``futures`` package to deploy in virtual environment. Required by
 
  Gunicorn when using Python 2.7. Default version is tested with the test site.
 

	
 
**gunicorn_version** (string, optional, ``19.6.0``)
 
  Version of Gunicorn to deploy in virtual environment for running the WSGI
docs/usage.rst
Show inline comments
 
@@ -1063,24 +1063,30 @@ Let us first define what we want to deploy on the web server. Here is the plan:
 
      this is supported and possible). Being written in PHP, this will
 
      demonstrate the role for PHP web application deployment.
 

	
 
   2. `Django Wiki <https://github.com/django-wiki/django-wiki>`_ - a wiki
 
      application written in Django. This will serve as a demo of how the WSGI
 
      role works.
 

	
 
It should be noted that the web application deployment roles are a bit more
 
complex - namely they are not meant to be used directly, but instead as a
 
dependency for a custom role. They do come with decent amount of batteries
 
included, and also play nice with the web server role.
 

	
 
As mentioned before, all roles will enforce TLS by default. The web server roles
 
will additionaly implement HSTS policy by sending connecting clients
 
``Strict-Transport-Security`` header with value set to ``max-age=31536000;
 
includeSubDomains`` (if you disable enforcement of TLS, the header will not be
 
sent).
 

	
 
With all the above noted, let us finally move on to the next step.
 

	
 

	
 
Setting-up the web server
 
-------------------------
 

	
 
Finally we are moving on to the web server deployment, and we shell start
 
with... Well, erm, web server deployment! To be more precise, we will set-up
 
Nginx.
 

	
 
1. Update the playbook for web server to include the web server role.
 

	
roles/php_website/templates/nginx_site.j2
Show inline comments
 
@@ -17,24 +17,30 @@ server {
 
{% if not enforce_https %}
 

	
 
    # HTTP (plaintext) configuration.
 
    listen 80;
 

	
 
{% endif %}
 
    # HTTPS (TLS) configuration.
 
    listen 443 ssl;
 
    listen [::]:443 ssl;
 
    ssl_certificate_key /etc/ssl/private/{{ fqdn }}_https.key;
 
    ssl_certificate /etc/ssl/certs/{{ fqdn }}_https.pem;
 

	
 
{% if default_enforce_https -%}
 
    # Set-up HSTS header for preventing downgrades for users that visited the
 
    # site via HTTPS at least once.
 
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";
 
{% endif -%}
 

	
 
    {% for config in additional_nginx_config -%}
 
    # {{ config.comment }}
 
    {{ config.value }}
 
    {% endfor -%}
 

	
 
    {% if rewrites -%}
 
    # Generic URL rewrites.
 
    {% for rewrite in rewrites -%}
 
    rewrite {{ rewrite }};
 
    {% endfor -%}
 
    {% endif %}
 

	
roles/web_server/templates/nginx-default.j2
Show inline comments
 
@@ -19,24 +19,30 @@ server {
 
{% if not default_enforce_https %}
 
    # HTTP (plaintext) configuration.
 
    listen 80 default_server;
 
    listen [::]:80 default_server;
 

	
 
{% endif %}
 
    # HTTPS (TLS) configuration.
 
    listen 443 ssl default_server;
 
    listen [::]:443 ssl default_server;
 
    ssl_certificate_key /etc/ssl/private/{{ ansible_fqdn }}_https.key;
 
    ssl_certificate /etc/ssl/certs/{{ ansible_fqdn }}_https.pem;
 

	
 
{% if default_enforce_https %}
 
    # Set-up HSTS header for preventing downgrades for users that visited the
 
    # site via HTTPS at least once.
 
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";
 
{% endif %}
 

	
 
    # Set-up the serving of default page.
 
    root /var/www/default/;
 
    index index.html;
 

	
 
    # Set server_name to something that won't be matched (for default server).
 
    server_name _;
 

	
 
    location / {
 
        # Always point user to the same index page.
 
        try_files $uri /index.html;
 
    }
 
}
roles/wsgi_website/templates/nginx_site.j2
Show inline comments
 
@@ -16,24 +16,30 @@ server {
 
{% if not enforce_https %}
 

	
 
    # HTTP (plaintext) configuration.
 
    listen 80;
 

	
 
{% endif %}
 
    # HTTPS (TLS) configuration.
 
    listen 443 ssl;
 
    listen [::]:443 ssl;
 
    ssl_certificate_key /etc/ssl/private/{{ fqdn }}_https.key;
 
    ssl_certificate /etc/ssl/certs/{{ fqdn }}_https.pem;
 

	
 
{% if default_enforce_https -%}
 
    # Set-up HSTS header for preventing downgrades for users that visited the
 
    # site via HTTPS at least once.
 
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";
 
{% endif -%}
 

	
 
    {% for config in additional_nginx_config -%}
 
    # {{ config.comment }}
 
    {{ config.value }}
 
    {% endfor -%}
 

	
 
    {% if rewrites -%}
 
    # Site rewrites.
 
    {% for rewrite in rewrites -%}
 
    rewrite {{ rewrite }};
 
    {% endfor -%}
 
    {% endif %}
 

	
0 comments (0 inline, 0 general)