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

[WIP] Restrict project access by IP address #36044

Draft
wants to merge 10 commits into
base: master
Choose a base branch
from
Draft

Conversation

esoergel
Copy link
Contributor

@esoergel esoergel commented Mar 21, 2025

Product Description

Technical Summary

https://dimagi.atlassian.net/browse/USH-5818
https://dimagi.atlassian.net/browse/USH-5817
Design document

Feature Flag

Safety Assurance

Safety story

Automated test coverage

QA Plan

Rollback instructions

  • This PR can be reverted after deploy with no further considerations

Labels & Review

  • Risk label is set correctly
  • The set of people pinged as reviewers is appropriate for the level of risk of the change

Sorry, something went wrong.

@dimagimon dimagimon added the reindex/migration Reindex or migration will be required during or before deploy label Mar 21, 2025
@esoergel
Copy link
Contributor Author

@minhaminha here's a branch with the basic model for the IP access work - figure we can PR our respective changes into this and hopefully avoid too much conflict

esoergel and others added 2 commits March 25, 2025 11:22

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
Add middlware class to check IP access
@esoergel esoergel changed the title Add ip access model [WIP] Restrict project access by IP address Mar 25, 2025
@esoergel esoergel requested a review from minhaminha March 25, 2025 17:52
),
),
(
"ip_denylist",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there any need for a country_denylist?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I left it out for now since we don't need it and it makes the logic a bit harder to reason about. Though thinking about it again I think we could make it work by saying specificity wins (ie an IP rule beats a country rule), something like:

def is_allowed(ip):
    if ip in ip_denylist:
        return False
    if ip in ip_allowlist:
        return True
    if country_denylist and is_in_country(ip, country_denylist):
        return False
    return not country_allowlist or is_in_country(ip, country_allowlist):

That is, allowlisted IPs are always allowed even from denylisted countries.

Still, I think it's okay to hold off for now - we could always add it later if needed

@dimagimon dimagimon added the dependencies Pull requests that update a dependency file label Mar 26, 2025
@minhaminha
Copy link
Contributor

@esoergel I noticed that currently, a user that's not in an allowed country according to the domain's config can trigger multiple requests if they repeatedly try to access the domain. I'm thinking we should also add a session blocklist, so that when a user fails config.is_allowed they aren't allowed to try again but wanted to get your thoughts as well.

@esoergel
Copy link
Contributor Author

@minhaminha yeah that's a good thought - I had the same idea but was uncertain whether it'd be worth it. It certainly makes sense to cache the lookups we allow, since we expect users to make a bunch of requests in sequence. However, if their request is blocked, presumably they won't try again and again unless it's like a DOS attack, which this isn't intended to mitigate against.

Still though, I guess we wouldn't actually stick anything in the session for blocked IPs unless we do encounter one, so the cost should be trivial. I'd be on board with that.

@minhaminha
Copy link
Contributor

@esoergel blocking by the IP's origin country is now working properly on staging 🎉 . Is there anything else to be done on this PR before releasing it from the drafts? I created an IP Access monitoring dashboard on datadog here, and I'll add the requests-per-day counter on their too/setup the 1000 request threshold alert after this gets merged.
I saw in the design doc we were considering checking IPs for API requests too - did we decide which of 3 approaches you described to go with?
I'm also wondering if this line from the doc is necessary:

On subsequent requests, a middleware class should check the request IP against the IP address used to initiate the session. If the IP address differs, we flush the session and force the user to log in again.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
dependencies Pull requests that update a dependency file reindex/migration Reindex or migration will be required during or before deploy
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants