Fixes: #565
Also, split Dockerfile into two stages, so rust
and other build dependencies don't end up in the final image.
Note cryptography has binary wheels for various architectures,
but unfortunately not for 32-bit arm. And, starting from v35.0.0,
cryptography requires rust to build from source.
1. Drop API support for GET, DELETE requests with a request body.
Healthchecks had an undocumented quirk where you could authenticate a
GET or DELETE request by putting a '{"api_key":"..."}' in request body.
This commit removes this feature.
Note: POST requests can still authenticate either by sending
a X-Api-Key header, or by putting a "api_key" key in request body.
GET and DELETE requests can now only authenticate with the
request header.
2. Add missing @csrf_exempt annotations in API views
When client sends a HTTP POST request to a GET-only endpoint,
the server is supposed to respond with "405 Method Not Allowed".
Due to CSRF checking, a couple endpoints were responding with
"403 Forbidden" instead. Adding @csrf_exempt annotations fixes
the problem.
This fixes a security issue:
- attacker can crafts a redirect URL to an external site
- attacker gets victim to click on it
- victim logs in
- after login, Healthchecks redirects victim to the external site
The _allow_redirect function now additionally
requires the redirect URL is relative (has no scheme or domain).
Profile.next_nag_date tracks when the next hourly/daily reminder
should be sent. Normally, sendalerts sets this field when
a check goes down, and sendreports clears it out whenever
it is about to send a reminder but realizes all checks are up.
The problem: sendalerts can set next_nag_date to a non-null
value, but it does not clear it out when all checks are up.
This can result in a hourly/daily reminder being sent out
at the wrong time. Specific example, assuming hourly reminders:
13:00: Check A goes down. next_nag_date gets set to 14:00.
13:05: Check A goes up. next_nag_date remains set to 14:00.
13:55: Check B goes down. next_nag_date remains set to 14:00.
14:00: Healthchecks sends a hourly reminder, just 5 minutes
after Check B going down. It should have sent the reminder
at 13:55 + 1 hour = 14:55
The fix: sendalerts can now both set and clear the next_nag_date
field. The main changes are in Project.update_next_nag_dates()
and in Profile.update_next_nag_date(). With the fix:
13:00: Check A goes down. next_nag_date gets set to 14:00.
13:05: Check A goes up. next_nag_date gets set to null.
13:55: Check B goes down. next_nag_date gets set to 14:55.
14:55: Healthchecks sends a hourly reminder.