authentik.policies.geoip.tests
geoip policy tests
1"""geoip policy tests""" 2 3from django.test import TestCase 4 5from authentik.core.tests.utils import create_test_user 6from authentik.events.models import Event, EventAction 7from authentik.events.utils import get_user 8from authentik.policies.engine import PolicyRequest, PolicyResult 9from authentik.policies.exceptions import PolicyException 10from authentik.policies.geoip.exceptions import GeoIPNotFoundException 11from authentik.policies.geoip.models import GeoIPPolicy 12 13 14class TestGeoIPPolicy(TestCase): 15 """Test GeoIP Policy""" 16 17 def setUp(self): 18 super().setUp() 19 self.user = create_test_user() 20 self.request = PolicyRequest(self.user) 21 22 self.context_disabled_geoip = {} 23 self.context_unknown_ip = {"asn": None, "geoip": None} 24 # 8.8.8.8 25 self.context = { 26 "asn": {"asn": 15169, "as_org": "GOOGLE", "network": "8.8.8.0/24"}, 27 "geoip": { 28 "continent": "NA", 29 "country": "US", 30 "lat": 37.751, 31 "long": -97.822, 32 "city": "", 33 }, 34 } 35 36 self.matching_asns = [13335, 15169] 37 self.matching_countries = ["US", "CA"] 38 self.mismatching_asns = [1, 2] 39 self.mismatching_countries = ["MX", "UA"] 40 41 def enrich_context_disabled_geoip(self): 42 pass 43 44 def enrich_context_unknown_ip(self): 45 self.request.context["asn"] = self.context_unknown_ip["asn"] 46 self.request.context["geoip"] = self.context_unknown_ip["geoip"] 47 48 def enrich_context(self): 49 self.request.context["asn"] = self.context["asn"] 50 self.request.context["geoip"] = self.context["geoip"] 51 52 def test_disabled_geoip(self): 53 """Test that disabled GeoIP raises PolicyException with GeoIPNotFoundException""" 54 self.enrich_context_disabled_geoip() 55 policy = GeoIPPolicy.objects.create( 56 asns=self.matching_asns, countries=self.matching_countries 57 ) 58 59 with self.assertRaises(PolicyException) as cm: 60 policy.passes(self.request) 61 62 self.assertIsInstance(cm.exception.src_exc, GeoIPNotFoundException) 63 64 def test_unknown_ip(self): 65 """Test that unknown IP raises PolicyException with GeoIPNotFoundException""" 66 self.enrich_context_unknown_ip() 67 policy = GeoIPPolicy.objects.create( 68 asns=self.matching_asns, countries=self.matching_countries 69 ) 70 71 with self.assertRaises(PolicyException) as cm: 72 policy.passes(self.request) 73 74 self.assertIsInstance(cm.exception.src_exc, GeoIPNotFoundException) 75 76 def test_empty_policy(self): 77 """Test that empty policy passes""" 78 self.enrich_context() 79 policy = GeoIPPolicy.objects.create() 80 81 result: PolicyResult = policy.passes(self.request) 82 83 self.assertTrue(result.passing) 84 85 def test_policy_with_matching_asns(self): 86 """Test that a policy with matching ASNs passes""" 87 self.enrich_context() 88 policy = GeoIPPolicy.objects.create(asns=self.matching_asns) 89 90 result: PolicyResult = policy.passes(self.request) 91 92 self.assertTrue(result.passing) 93 94 def test_policy_with_mismatching_asns(self): 95 """Test that a policy with mismatching ASNs fails""" 96 self.enrich_context() 97 policy = GeoIPPolicy.objects.create(asns=self.mismatching_asns) 98 99 result: PolicyResult = policy.passes(self.request) 100 101 self.assertFalse(result.passing) 102 103 def test_policy_with_matching_countries(self): 104 """Test that a policy with matching countries passes""" 105 self.enrich_context() 106 policy = GeoIPPolicy.objects.create(countries=self.matching_countries) 107 108 result: PolicyResult = policy.passes(self.request) 109 110 self.assertTrue(result.passing) 111 112 def test_policy_with_mismatching_countries(self): 113 """Test that a policy with mismatching countries fails""" 114 self.enrich_context() 115 policy = GeoIPPolicy.objects.create(countries=self.mismatching_countries) 116 117 result: PolicyResult = policy.passes(self.request) 118 119 self.assertFalse(result.passing) 120 121 def test_policy_requires_only_one_match(self): 122 """Test that a policy with one matching value passes""" 123 self.enrich_context() 124 policy = GeoIPPolicy.objects.create( 125 asns=self.mismatching_asns, countries=self.matching_countries 126 ) 127 128 result: PolicyResult = policy.passes(self.request) 129 130 self.assertTrue(result.passing) 131 132 def test_history(self): 133 """Test history checks""" 134 Event.objects.create( 135 action=EventAction.LOGIN, 136 user=get_user(self.user), 137 context={ 138 # Random location in Canada 139 "geo": {"lat": 55.868351, "long": -104.441011}, 140 }, 141 ) 142 # Random location in Poland 143 self.request.context["geoip"] = {"lat": 50.950613, "long": 20.363679} 144 145 policy = GeoIPPolicy.objects.create(check_history_distance=True) 146 147 result: PolicyResult = policy.passes(self.request) 148 self.assertFalse(result.passing) 149 150 def test_history_no_data(self): 151 """Test history checks (with no geoip data in context)""" 152 Event.objects.create( 153 action=EventAction.LOGIN, 154 user=get_user(self.user), 155 context={ 156 # Random location in Canada 157 "geo": {"lat": 55.868351, "long": -104.441011}, 158 }, 159 ) 160 161 policy = GeoIPPolicy.objects.create(check_history_distance=True) 162 163 result: PolicyResult = policy.passes(self.request) 164 self.assertFalse(result.passing) 165 166 def test_history_impossible_travel_failing(self): 167 """Test history checks""" 168 Event.objects.create( 169 action=EventAction.LOGIN, 170 user=get_user(self.user), 171 context={ 172 # Random location in Canada 173 "geo": {"lat": 55.868351, "long": -104.441011}, 174 }, 175 ) 176 # Random location in Poland 177 self.request.context["geoip"] = {"lat": 50.950613, "long": 20.363679} 178 179 policy = GeoIPPolicy.objects.create(check_impossible_travel=True) 180 181 result: PolicyResult = policy.passes(self.request) 182 self.assertFalse(result.passing) 183 184 def test_history_impossible_travel_passing(self): 185 """Test history checks""" 186 Event.objects.create( 187 action=EventAction.LOGIN, 188 user=get_user(self.user), 189 context={ 190 # Random location in Canada 191 "geo": {"lat": 55.868351, "long": -104.441011}, 192 }, 193 ) 194 # Same location 195 self.request.context["geoip"] = {"lat": 55.868351, "long": -104.441011} 196 197 policy = GeoIPPolicy.objects.create(check_impossible_travel=True) 198 199 result: PolicyResult = policy.passes(self.request) 200 self.assertTrue(result.passing) 201 202 def test_history_no_geoip(self): 203 """Test history checks (previous login with no geoip data)""" 204 Event.objects.create( 205 action=EventAction.LOGIN, 206 user=get_user(self.user), 207 context={}, 208 ) 209 # Random location in Poland 210 self.request.context["geoip"] = {"lat": 50.950613, "long": 20.363679} 211 212 policy = GeoIPPolicy.objects.create(check_history_distance=True) 213 214 result: PolicyResult = policy.passes(self.request) 215 self.assertFalse(result.passing) 216 217 def test_impossible_travel_no_geoip(self): 218 """Test impossible travel checks (previous login with no geoip data)""" 219 Event.objects.create( 220 action=EventAction.LOGIN, 221 user=get_user(self.user), 222 context={}, 223 ) 224 # Random location in Poland 225 self.request.context["geoip"] = {"lat": 50.950613, "long": 20.363679} 226 227 policy = GeoIPPolicy.objects.create(check_impossible_travel=True) 228 229 result: PolicyResult = policy.passes(self.request) 230 self.assertFalse(result.passing)
class
TestGeoIPPolicy(django.test.testcases.TestCase):
15class TestGeoIPPolicy(TestCase): 16 """Test GeoIP Policy""" 17 18 def setUp(self): 19 super().setUp() 20 self.user = create_test_user() 21 self.request = PolicyRequest(self.user) 22 23 self.context_disabled_geoip = {} 24 self.context_unknown_ip = {"asn": None, "geoip": None} 25 # 8.8.8.8 26 self.context = { 27 "asn": {"asn": 15169, "as_org": "GOOGLE", "network": "8.8.8.0/24"}, 28 "geoip": { 29 "continent": "NA", 30 "country": "US", 31 "lat": 37.751, 32 "long": -97.822, 33 "city": "", 34 }, 35 } 36 37 self.matching_asns = [13335, 15169] 38 self.matching_countries = ["US", "CA"] 39 self.mismatching_asns = [1, 2] 40 self.mismatching_countries = ["MX", "UA"] 41 42 def enrich_context_disabled_geoip(self): 43 pass 44 45 def enrich_context_unknown_ip(self): 46 self.request.context["asn"] = self.context_unknown_ip["asn"] 47 self.request.context["geoip"] = self.context_unknown_ip["geoip"] 48 49 def enrich_context(self): 50 self.request.context["asn"] = self.context["asn"] 51 self.request.context["geoip"] = self.context["geoip"] 52 53 def test_disabled_geoip(self): 54 """Test that disabled GeoIP raises PolicyException with GeoIPNotFoundException""" 55 self.enrich_context_disabled_geoip() 56 policy = GeoIPPolicy.objects.create( 57 asns=self.matching_asns, countries=self.matching_countries 58 ) 59 60 with self.assertRaises(PolicyException) as cm: 61 policy.passes(self.request) 62 63 self.assertIsInstance(cm.exception.src_exc, GeoIPNotFoundException) 64 65 def test_unknown_ip(self): 66 """Test that unknown IP raises PolicyException with GeoIPNotFoundException""" 67 self.enrich_context_unknown_ip() 68 policy = GeoIPPolicy.objects.create( 69 asns=self.matching_asns, countries=self.matching_countries 70 ) 71 72 with self.assertRaises(PolicyException) as cm: 73 policy.passes(self.request) 74 75 self.assertIsInstance(cm.exception.src_exc, GeoIPNotFoundException) 76 77 def test_empty_policy(self): 78 """Test that empty policy passes""" 79 self.enrich_context() 80 policy = GeoIPPolicy.objects.create() 81 82 result: PolicyResult = policy.passes(self.request) 83 84 self.assertTrue(result.passing) 85 86 def test_policy_with_matching_asns(self): 87 """Test that a policy with matching ASNs passes""" 88 self.enrich_context() 89 policy = GeoIPPolicy.objects.create(asns=self.matching_asns) 90 91 result: PolicyResult = policy.passes(self.request) 92 93 self.assertTrue(result.passing) 94 95 def test_policy_with_mismatching_asns(self): 96 """Test that a policy with mismatching ASNs fails""" 97 self.enrich_context() 98 policy = GeoIPPolicy.objects.create(asns=self.mismatching_asns) 99 100 result: PolicyResult = policy.passes(self.request) 101 102 self.assertFalse(result.passing) 103 104 def test_policy_with_matching_countries(self): 105 """Test that a policy with matching countries passes""" 106 self.enrich_context() 107 policy = GeoIPPolicy.objects.create(countries=self.matching_countries) 108 109 result: PolicyResult = policy.passes(self.request) 110 111 self.assertTrue(result.passing) 112 113 def test_policy_with_mismatching_countries(self): 114 """Test that a policy with mismatching countries fails""" 115 self.enrich_context() 116 policy = GeoIPPolicy.objects.create(countries=self.mismatching_countries) 117 118 result: PolicyResult = policy.passes(self.request) 119 120 self.assertFalse(result.passing) 121 122 def test_policy_requires_only_one_match(self): 123 """Test that a policy with one matching value passes""" 124 self.enrich_context() 125 policy = GeoIPPolicy.objects.create( 126 asns=self.mismatching_asns, countries=self.matching_countries 127 ) 128 129 result: PolicyResult = policy.passes(self.request) 130 131 self.assertTrue(result.passing) 132 133 def test_history(self): 134 """Test history checks""" 135 Event.objects.create( 136 action=EventAction.LOGIN, 137 user=get_user(self.user), 138 context={ 139 # Random location in Canada 140 "geo": {"lat": 55.868351, "long": -104.441011}, 141 }, 142 ) 143 # Random location in Poland 144 self.request.context["geoip"] = {"lat": 50.950613, "long": 20.363679} 145 146 policy = GeoIPPolicy.objects.create(check_history_distance=True) 147 148 result: PolicyResult = policy.passes(self.request) 149 self.assertFalse(result.passing) 150 151 def test_history_no_data(self): 152 """Test history checks (with no geoip data in context)""" 153 Event.objects.create( 154 action=EventAction.LOGIN, 155 user=get_user(self.user), 156 context={ 157 # Random location in Canada 158 "geo": {"lat": 55.868351, "long": -104.441011}, 159 }, 160 ) 161 162 policy = GeoIPPolicy.objects.create(check_history_distance=True) 163 164 result: PolicyResult = policy.passes(self.request) 165 self.assertFalse(result.passing) 166 167 def test_history_impossible_travel_failing(self): 168 """Test history checks""" 169 Event.objects.create( 170 action=EventAction.LOGIN, 171 user=get_user(self.user), 172 context={ 173 # Random location in Canada 174 "geo": {"lat": 55.868351, "long": -104.441011}, 175 }, 176 ) 177 # Random location in Poland 178 self.request.context["geoip"] = {"lat": 50.950613, "long": 20.363679} 179 180 policy = GeoIPPolicy.objects.create(check_impossible_travel=True) 181 182 result: PolicyResult = policy.passes(self.request) 183 self.assertFalse(result.passing) 184 185 def test_history_impossible_travel_passing(self): 186 """Test history checks""" 187 Event.objects.create( 188 action=EventAction.LOGIN, 189 user=get_user(self.user), 190 context={ 191 # Random location in Canada 192 "geo": {"lat": 55.868351, "long": -104.441011}, 193 }, 194 ) 195 # Same location 196 self.request.context["geoip"] = {"lat": 55.868351, "long": -104.441011} 197 198 policy = GeoIPPolicy.objects.create(check_impossible_travel=True) 199 200 result: PolicyResult = policy.passes(self.request) 201 self.assertTrue(result.passing) 202 203 def test_history_no_geoip(self): 204 """Test history checks (previous login with no geoip data)""" 205 Event.objects.create( 206 action=EventAction.LOGIN, 207 user=get_user(self.user), 208 context={}, 209 ) 210 # Random location in Poland 211 self.request.context["geoip"] = {"lat": 50.950613, "long": 20.363679} 212 213 policy = GeoIPPolicy.objects.create(check_history_distance=True) 214 215 result: PolicyResult = policy.passes(self.request) 216 self.assertFalse(result.passing) 217 218 def test_impossible_travel_no_geoip(self): 219 """Test impossible travel checks (previous login with no geoip data)""" 220 Event.objects.create( 221 action=EventAction.LOGIN, 222 user=get_user(self.user), 223 context={}, 224 ) 225 # Random location in Poland 226 self.request.context["geoip"] = {"lat": 50.950613, "long": 20.363679} 227 228 policy = GeoIPPolicy.objects.create(check_impossible_travel=True) 229 230 result: PolicyResult = policy.passes(self.request) 231 self.assertFalse(result.passing)
Test GeoIP Policy
def
setUp(self):
18 def setUp(self): 19 super().setUp() 20 self.user = create_test_user() 21 self.request = PolicyRequest(self.user) 22 23 self.context_disabled_geoip = {} 24 self.context_unknown_ip = {"asn": None, "geoip": None} 25 # 8.8.8.8 26 self.context = { 27 "asn": {"asn": 15169, "as_org": "GOOGLE", "network": "8.8.8.0/24"}, 28 "geoip": { 29 "continent": "NA", 30 "country": "US", 31 "lat": 37.751, 32 "long": -97.822, 33 "city": "", 34 }, 35 } 36 37 self.matching_asns = [13335, 15169] 38 self.matching_countries = ["US", "CA"] 39 self.mismatching_asns = [1, 2] 40 self.mismatching_countries = ["MX", "UA"]
Hook method for setting up the test fixture before exercising it.
def
test_disabled_geoip(self):
53 def test_disabled_geoip(self): 54 """Test that disabled GeoIP raises PolicyException with GeoIPNotFoundException""" 55 self.enrich_context_disabled_geoip() 56 policy = GeoIPPolicy.objects.create( 57 asns=self.matching_asns, countries=self.matching_countries 58 ) 59 60 with self.assertRaises(PolicyException) as cm: 61 policy.passes(self.request) 62 63 self.assertIsInstance(cm.exception.src_exc, GeoIPNotFoundException)
Test that disabled GeoIP raises PolicyException with GeoIPNotFoundException
def
test_unknown_ip(self):
65 def test_unknown_ip(self): 66 """Test that unknown IP raises PolicyException with GeoIPNotFoundException""" 67 self.enrich_context_unknown_ip() 68 policy = GeoIPPolicy.objects.create( 69 asns=self.matching_asns, countries=self.matching_countries 70 ) 71 72 with self.assertRaises(PolicyException) as cm: 73 policy.passes(self.request) 74 75 self.assertIsInstance(cm.exception.src_exc, GeoIPNotFoundException)
Test that unknown IP raises PolicyException with GeoIPNotFoundException
def
test_empty_policy(self):
77 def test_empty_policy(self): 78 """Test that empty policy passes""" 79 self.enrich_context() 80 policy = GeoIPPolicy.objects.create() 81 82 result: PolicyResult = policy.passes(self.request) 83 84 self.assertTrue(result.passing)
Test that empty policy passes
def
test_policy_with_matching_asns(self):
86 def test_policy_with_matching_asns(self): 87 """Test that a policy with matching ASNs passes""" 88 self.enrich_context() 89 policy = GeoIPPolicy.objects.create(asns=self.matching_asns) 90 91 result: PolicyResult = policy.passes(self.request) 92 93 self.assertTrue(result.passing)
Test that a policy with matching ASNs passes
def
test_policy_with_mismatching_asns(self):
95 def test_policy_with_mismatching_asns(self): 96 """Test that a policy with mismatching ASNs fails""" 97 self.enrich_context() 98 policy = GeoIPPolicy.objects.create(asns=self.mismatching_asns) 99 100 result: PolicyResult = policy.passes(self.request) 101 102 self.assertFalse(result.passing)
Test that a policy with mismatching ASNs fails
def
test_policy_with_matching_countries(self):
104 def test_policy_with_matching_countries(self): 105 """Test that a policy with matching countries passes""" 106 self.enrich_context() 107 policy = GeoIPPolicy.objects.create(countries=self.matching_countries) 108 109 result: PolicyResult = policy.passes(self.request) 110 111 self.assertTrue(result.passing)
Test that a policy with matching countries passes
def
test_policy_with_mismatching_countries(self):
113 def test_policy_with_mismatching_countries(self): 114 """Test that a policy with mismatching countries fails""" 115 self.enrich_context() 116 policy = GeoIPPolicy.objects.create(countries=self.mismatching_countries) 117 118 result: PolicyResult = policy.passes(self.request) 119 120 self.assertFalse(result.passing)
Test that a policy with mismatching countries fails
def
test_policy_requires_only_one_match(self):
122 def test_policy_requires_only_one_match(self): 123 """Test that a policy with one matching value passes""" 124 self.enrich_context() 125 policy = GeoIPPolicy.objects.create( 126 asns=self.mismatching_asns, countries=self.matching_countries 127 ) 128 129 result: PolicyResult = policy.passes(self.request) 130 131 self.assertTrue(result.passing)
Test that a policy with one matching value passes
def
test_history(self):
133 def test_history(self): 134 """Test history checks""" 135 Event.objects.create( 136 action=EventAction.LOGIN, 137 user=get_user(self.user), 138 context={ 139 # Random location in Canada 140 "geo": {"lat": 55.868351, "long": -104.441011}, 141 }, 142 ) 143 # Random location in Poland 144 self.request.context["geoip"] = {"lat": 50.950613, "long": 20.363679} 145 146 policy = GeoIPPolicy.objects.create(check_history_distance=True) 147 148 result: PolicyResult = policy.passes(self.request) 149 self.assertFalse(result.passing)
Test history checks
def
test_history_no_data(self):
151 def test_history_no_data(self): 152 """Test history checks (with no geoip data in context)""" 153 Event.objects.create( 154 action=EventAction.LOGIN, 155 user=get_user(self.user), 156 context={ 157 # Random location in Canada 158 "geo": {"lat": 55.868351, "long": -104.441011}, 159 }, 160 ) 161 162 policy = GeoIPPolicy.objects.create(check_history_distance=True) 163 164 result: PolicyResult = policy.passes(self.request) 165 self.assertFalse(result.passing)
Test history checks (with no geoip data in context)
def
test_history_impossible_travel_failing(self):
167 def test_history_impossible_travel_failing(self): 168 """Test history checks""" 169 Event.objects.create( 170 action=EventAction.LOGIN, 171 user=get_user(self.user), 172 context={ 173 # Random location in Canada 174 "geo": {"lat": 55.868351, "long": -104.441011}, 175 }, 176 ) 177 # Random location in Poland 178 self.request.context["geoip"] = {"lat": 50.950613, "long": 20.363679} 179 180 policy = GeoIPPolicy.objects.create(check_impossible_travel=True) 181 182 result: PolicyResult = policy.passes(self.request) 183 self.assertFalse(result.passing)
Test history checks
def
test_history_impossible_travel_passing(self):
185 def test_history_impossible_travel_passing(self): 186 """Test history checks""" 187 Event.objects.create( 188 action=EventAction.LOGIN, 189 user=get_user(self.user), 190 context={ 191 # Random location in Canada 192 "geo": {"lat": 55.868351, "long": -104.441011}, 193 }, 194 ) 195 # Same location 196 self.request.context["geoip"] = {"lat": 55.868351, "long": -104.441011} 197 198 policy = GeoIPPolicy.objects.create(check_impossible_travel=True) 199 200 result: PolicyResult = policy.passes(self.request) 201 self.assertTrue(result.passing)
Test history checks
def
test_history_no_geoip(self):
203 def test_history_no_geoip(self): 204 """Test history checks (previous login with no geoip data)""" 205 Event.objects.create( 206 action=EventAction.LOGIN, 207 user=get_user(self.user), 208 context={}, 209 ) 210 # Random location in Poland 211 self.request.context["geoip"] = {"lat": 50.950613, "long": 20.363679} 212 213 policy = GeoIPPolicy.objects.create(check_history_distance=True) 214 215 result: PolicyResult = policy.passes(self.request) 216 self.assertFalse(result.passing)
Test history checks (previous login with no geoip data)
def
test_impossible_travel_no_geoip(self):
218 def test_impossible_travel_no_geoip(self): 219 """Test impossible travel checks (previous login with no geoip data)""" 220 Event.objects.create( 221 action=EventAction.LOGIN, 222 user=get_user(self.user), 223 context={}, 224 ) 225 # Random location in Poland 226 self.request.context["geoip"] = {"lat": 50.950613, "long": 20.363679} 227 228 policy = GeoIPPolicy.objects.create(check_impossible_travel=True) 229 230 result: PolicyResult = policy.passes(self.request) 231 self.assertFalse(result.passing)
Test impossible travel checks (previous login with no geoip data)