Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

⚠️ NE JAMAIS MERGER : Retour vers le futur #3786

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions config/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@
MIDDLEWARE = [
# Generate request Id
"django_datadog_logger.middleware.request_id.RequestIdMiddleware",
# Itou health check for Clever Cloud, don’t require requests to match ALLOWED_HOSTS
"itou.www.middleware.public_health_check",
# Django stack
"django.middleware.gzip.GZipMiddleware",
"django.middleware.security.SecurityMiddleware",
Expand Down
2 changes: 1 addition & 1 deletion itou/templates/static/security/security.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Contact: mailto:tech@inclusion.beta.gouv.fr
Expires: 2024-03-19T12:00:00.000Z
Expires: 2024-09-19T12:00:00.000Z
Preferred-Languages: fr,en
Canonical: https://emplois.inclusion.beta.gouv.fr/.well-known/security.txt
Policy: https://github.com/gip-inclusion/les-emplois/blob/master/.github/SECURITY.md
37 changes: 37 additions & 0 deletions itou/www/middleware.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
import sentry_sdk
from django.core.cache import cache
from django.core.files.storage import default_storage
from django.db import connection
from django.http.response import HttpResponse, HttpResponseServerError
from django.utils.cache import add_never_cache_headers


Expand All @@ -9,3 +14,35 @@ def middleware(request):
return response

return middleware


def public_health_check(get_response):
def middleware(request):
"""
Bypass ALLOWED_HOSTS checks

CleverCloud probes access this path through IP directly, we don’t want to serve
a 400 BadRequest because the request Host header is not in the ALLOWED_HOSTS.
"""
if request.path == "/check-health":
try:
with connection.cursor() as c:
c.execute("SELECT 'check-database-connection'")
cache.get("check-cache-connection")
default_storage.exists("check-s3-file-access.txt")
body = b"Healthy\n"
return HttpResponse(
body,
content_type="text/plain",
charset="utf-8",
# CommonMiddleware is later in the middleware chain, and it checks ALLOWED_HOSTS.
headers={
"Content-Length": str(len(body)),
},
)
except Exception as e:
sentry_sdk.capture_exception(e)
return HttpResponseServerError()
return get_response(request)

return middleware
26 changes: 14 additions & 12 deletions tests/www/approvals_views/test_list.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import datetime

from dateutil.relativedelta import relativedelta
from django.urls import reverse
from django.utils import timezone
Expand Down Expand Up @@ -125,42 +127,42 @@ def test_approval_state_filters(self, client):
company = CompanyFactory(with_membership=True)

expired_approval = ApprovalFactory(
start_at=now - relativedelta(years=3),
end_at=now - relativedelta(years=1),
start_at=now - datetime.timedelta(days=3 * 365),
end_at=now - datetime.timedelta(days=365),
with_jobapplication=True,
with_jobapplication__to_company=company,
)
future_approval = ApprovalFactory(
start_at=now + relativedelta(days=1),
start_at=now + datetime.timedelta(days=1),
with_jobapplication=True,
with_jobapplication__to_company=company,
)
valid_approval = ApprovalFactory(
start_at=now - relativedelta(years=1),
start_at=now - datetime.timedelta(days=365),
with_jobapplication=True,
with_jobapplication__to_company=company,
)
suspended_approval = ApprovalFactory(
start_at=now - relativedelta(years=1),
start_at=now - datetime.timedelta(days=365),
with_jobapplication=True,
with_jobapplication__to_company=company,
)
SuspensionFactory(
approval=suspended_approval,
start_at=now - relativedelta(days=1),
end_at=now + relativedelta(days=1),
start_at=now - datetime.timedelta(days=1),
end_at=now + datetime.timedelta(days=1),
)
# Add 2 suspensions on valid approval because it used to cause duplicates
# when valid and suspended filters were selected
SuspensionFactory(
approval=valid_approval,
start_at=now - relativedelta(days=10),
end_at=now - relativedelta(days=9),
start_at=now - datetime.timedelta(days=10),
end_at=now - datetime.timedelta(days=9),
)
SuspensionFactory(
approval=valid_approval,
start_at=now - relativedelta(days=3),
end_at=now - relativedelta(days=2),
start_at=now - datetime.timedelta(days=3),
end_at=now - datetime.timedelta(days=2),
)

employer = company.members.first()
Expand Down Expand Up @@ -234,7 +236,7 @@ def test_approval_state_filters(self, client):

assertContains(response, "366 jours")

assertContains(response, "730 jours")
assertContains(response, "729 jours")

assertContains(response, "0 jour")

Expand Down
21 changes: 21 additions & 0 deletions tests/www/test_check_health.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
class TestCheckHealth:
def test_get(self, client):
response = client.get("/check-health")
assert response.status_code == 200
assert response.charset == "utf-8"
assert response["Content-Type"] == "text/plain"
assert response["Content-Length"] == "8"
assert response.content.decode() == "Healthy\n"

def test_get_as_clever(self, client):
response = client.get(
"/check-health",
# CleverCloud probes connect directly through the IP, their HOST is not in the ALLOWED_HOSTS.
HTTP_HOST="10.2.2.2",
)
assert response.status_code == 200

def test_get_with_error(self, client, mocker):
mocker.patch("itou.www.middleware.connection.cursor", side_effect=Exception("Boom!"))
response = client.get("/check-health")
assert response.status_code == 500
Loading