Repository: mozilla-releng/buildhub2
Issue category: Security Vulnerability

Do all security headers with Django (too)
At the moment, the `/__heartbeat__` (when in Production mode) is yielding warnings. That's because it depends on Nginx as the final frontier to the internet. Let's be more redundant instead and do it in both places. 
Do all security headers with Django (too)
At the moment, the `/__heartbeat__` (when in Production mode) is yielding warnings. That's because it depends on Nginx as the final frontier to the internet. Let's be more redundant instead and do it in both places. 


Functions to edit:
buildhub/settings.py:Base
buildhub/settings.py:Localdev
buildhub/settings.py:Test
buildhub/settings.py:Stage
Functions added: buildhub/settings.py:Base
buildhub/settings.py:Localdev

Patch:
diff --git a/buildhub/settings.py b/buildhub/settings.py
index c044b6c2..0a445417 100644
--- a/buildhub/settings.py
+++ b/buildhub/settings.py
@@ -288,6 +288,29 @@ def LOGGING(self):
             },
         }
 
+    # Security related
+
+    SILENCED_SYSTEM_CHECKS = values.ListValue(
+        [
+            # This rule is about having "X-FRAME-OPTIONS" set to "DENY" which is
+            # not important for Buildhub2 because it's considered NOT dangerous to
+            # put any of this data inside an iframe.
+            "security.W019",
+            # There are no POST endpoints that *change* data that is exposed.
+            # I.e. you can't CSRF attack this site because there's no URL to do so
+            # with.
+            "security.W003",
+        ]
+    )
+
+    SECURE_SSL_REDIRECT = values.BooleanValue(True)
+    SECURE_HSTS_SECONDS = values.IntegerValue(3600)
+    SECURE_HSTS_INCLUDE_SUBDOMAINS = values.BooleanValue(True)
+    SECURE_HSTS_PRELOAD = values.BooleanValue(True)
+    SECURE_CONTENT_TYPE_NOSNIFF = values.BooleanValue(True)
+    SECURE_BROWSER_XSS_FILTER = values.BooleanValue(True)
+    SECURE_SSL_REDIRECT = values.BooleanValue(True)
+
 
 class Localdev(Base):
     """Configuration to be used during local development and base class
@@ -333,6 +356,12 @@ def LOGGING(self):
         [{"class": "markus.backends.logging.LoggingMetrics"}]
     )
 
+    # When doing local development you don't need to redirect to HTTPS.
+    SECURE_SSL_REDIRECT = values.BooleanValue(False)
+    SECURE_HSTS_SECONDS = values.IntegerValue(0)
+    SECURE_HSTS_PRELOAD = values.BooleanValue(False)
+    SECURE_SSL_REDIRECT = values.BooleanValue(False)
+
 
 class Test(Base):
     """Configurat
@@ -353,6 +382,8 @@ def STATIC_ROOT(self):
 
     MARKUS_BACKENDS = []
 
+    SECURE_SSL_REDIRECT = False
+
 
 class Stage(Base):
     """Configuration for the Stage server."""
@@ -408,6 +439,8 @@ def RAVEN_CONFIG(self):
             )
         return config
 
+    SECURE_HSTS_SECONDS = values.IntegerValue(31536000)  # 1 year
+
 
 class Prod(Stage):
     """Configuration to be used in prod environment"""

Test patch: diff --git a/tests/test_views.py b/tests/test_views.py
index f3e7f9f0..a0648e57 100644
--- a/tests/test_views.py
+++ b/tests/test_views.py
@@ -3,10 +3,27 @@
 # file, you can obtain one at http://mozilla.org/MPL/2.0/.
 
 import os
+import random
+
+import pytest
+import mock
 
 from django.urls import reverse
 
 
+@pytest.mark.django_db
+@mock.patch("buildhub.dockerflow_extra.boto3")
+def test_heartbeat(mocked_boto3, client, settings):
+    settings.SECRET_KEY = str(random.random()) * 5
+    # This one doesn't make sense to enable for tests because we use the
+    # test client. So we just have to ignore it in tests.
+    settings.SILENCED_SYSTEM_CHECKS.append("security.W008")
+
+    response = client.get("/__heartbeat__")
+    assert response.status_code == 200
+    mocked_boto3.client().head_bucket.assert_called_with(Bucket="buildhubses")
+
+
 def test_always_index_html(client, temp_static_root, settings):
     with open(os.path.join(temp_static_root, "index.html"), "w") as f:
         f.write(