From 3352797ee517dc1fce09ce7aeb962a3151c561ed 2016-11-22 22:25:09 From: Branko Majic Date: 2016-11-22 22:25:09 Subject: [PATCH] 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. --- diff --git a/docs/rolereference.rst b/docs/rolereference.rst index 7b5804678c4aa0136c9e1c8aa731d4fb1e916636..6fb9da20f2964a33a342d6ae54d52b268029e5cb 100644 --- a/docs/rolereference.rst +++ b/docs/rolereference.rst @@ -1134,7 +1134,9 @@ 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 @@ -1259,7 +1261,9 @@ Parameters **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 @@ -1452,7 +1456,9 @@ Parameters **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 diff --git a/docs/usage.rst b/docs/usage.rst index 294fdb05ef1c66f6c3a68046983dc3d55cbd1728..61538833808e24e68334d3e4b71b6733320b701d 100644 --- a/docs/usage.rst +++ b/docs/usage.rst @@ -1072,6 +1072,12 @@ 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. diff --git a/roles/php_website/templates/nginx_site.j2 b/roles/php_website/templates/nginx_site.j2 index 274c04354b5778a36eba711a40e3abfe732c8716..761f3e83eee3eab0cd7951a433b54fdfca0f7a28 100644 --- a/roles/php_website/templates/nginx_site.j2 +++ b/roles/php_website/templates/nginx_site.j2 @@ -26,6 +26,12 @@ server { 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 }} diff --git a/roles/web_server/templates/nginx-default.j2 b/roles/web_server/templates/nginx-default.j2 index 3e654c1df678e37741c1252f030e50b87ed26d4a..1ab3a553317a49276aa36913500d01508c30e882 100644 --- a/roles/web_server/templates/nginx-default.j2 +++ b/roles/web_server/templates/nginx-default.j2 @@ -28,6 +28,12 @@ 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; diff --git a/roles/wsgi_website/templates/nginx_site.j2 b/roles/wsgi_website/templates/nginx_site.j2 index 05f7eee9147368a351294869254f41508f266bc7..591a1a5d485bc654ec2d95da7b9ec82d7c8e10a8 100644 --- a/roles/wsgi_website/templates/nginx_site.j2 +++ b/roles/wsgi_website/templates/nginx_site.j2 @@ -25,6 +25,12 @@ server { 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 }}