-
Notifications
You must be signed in to change notification settings - Fork 98
AAP-45047: Fix allow map to process grant case in create_claims #959
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
base: devel
Are you sure you want to change the base?
Changes from all commits
59e2bdb
30efae9
5822707
b2b0f81
c17d524
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | |||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -71,6 +71,18 @@ | ||||||||||
| [{1: False, 'enabled': True}], | |||||||||||
| id="map_type 'allow' with trigger 'never' sets 'access_allowed' to False", | |||||||||||
| ), | |||||||||||
| pytest.param( | |||||||||||
| {"always": {}}, | |||||||||||
| "allow", | |||||||||||
| "", | |||||||||||
| {}, | |||||||||||
| [], | |||||||||||
| True, | |||||||||||
| None, | |||||||||||
| {"team_membership": {}, "organization_membership": {}, 'rbac_roles': {'system': {'roles': {}}, 'organizations': {}}}, | |||||||||||
| [{1: True, 'enabled': True}], | |||||||||||
| id="map_type 'allow' with trigger 'always' keeps 'access_allowed' True", | |||||||||||
| ), | |||||||||||
| pytest.param( | |||||||||||
| {"always": {}}, | |||||||||||
| "team", | |||||||||||
|
|
@@ -274,6 +286,107 @@ def test_create_claims_bad_map_type_logged( | ||||||||||
| f"Map type bad_map_type of rule {local_authenticator_map.name} does not know how to be processed" in logger.error.call_args | |||||||||||
|
|
|||||||||||
|
|
|||||||||||
| @mock.patch("ansible_base.authentication.utils.claims.logger") | |||||||||||
| def test_create_claims_allow_grant_no_error_logged( | |||||||||||
| logger, | |||||||||||
| local_authenticator_map, | |||||||||||
| shut_up_logging, | |||||||||||
| ): | |||||||||||
| """ | |||||||||||
| Test that map_type 'allow' with a firing trigger does NOT log an error. | |||||||||||
| Regression test for AAP-45047. | |||||||||||
| """ | |||||||||||
| local_authenticator_map.triggers = {"always": {}} | |||||||||||
| local_authenticator_map.map_type = "allow" | |||||||||||
| local_authenticator_map.save() | |||||||||||
|
|
|||||||||||
| authenticator = local_authenticator_map.authenticator | |||||||||||
| claims.create_claims(authenticator, "username", {}, []) | |||||||||||
|
|
|||||||||||
| logger.error.assert_not_called() | |||||||||||
|
|
|||||||||||
|
|
|||||||||||
| def test_create_claims_deny_all_then_allow_override( | |||||||||||
| local_authenticator_map, | |||||||||||
| local_authenticator_map_1, | |||||||||||
| ): | |||||||||||
| """ | |||||||||||
| Test that a later allow map can override a deny-all map. | |||||||||||
| This is the documented pattern equivalent to AUTH_LDAP_REQUIRE_GROUP. | |||||||||||
| Regression test for AAP-45394. | |||||||||||
| """ | |||||||||||
| # Map 1 (order 1): deny all | |||||||||||
| local_authenticator_map.triggers = {"never": {}} | |||||||||||
| local_authenticator_map.map_type = "allow" | |||||||||||
| local_authenticator_map.order = 1 | |||||||||||
| local_authenticator_map.save() | |||||||||||
|
|
|||||||||||
| # Map 2 (order 2): allow override | |||||||||||
| local_authenticator_map_1.triggers = {"always": {}} | |||||||||||
| local_authenticator_map_1.map_type = "allow" | |||||||||||
| local_authenticator_map_1.order = 2 | |||||||||||
| local_authenticator_map_1.save() | |||||||||||
|
|
|||||||||||
| authenticator = local_authenticator_map.authenticator | |||||||||||
| res = claims.create_claims(authenticator, "username", {}, []) | |||||||||||
|
|
|||||||||||
| assert res["access_allowed"] is True | |||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit (non-blocking): Consider adding a reverse-order test — "allow-all (order=1) then deny-all (order=2)" — to verify that a later deny still correctly overrides an earlier allow. This would complete the ordering matrix:
This is minor since the deny path was already working before this fix, but it would document the expected bidirectional "last map wins" contract and guard against future regressions. |
|||||||||||
|
|
|||||||||||
|
|
|||||||||||
| def test_create_claims_deny_all_not_overridden_without_match( | |||||||||||
| local_authenticator_map, | |||||||||||
| local_authenticator_map_1, | |||||||||||
| ): | |||||||||||
| """ | |||||||||||
| Test that a deny-all is NOT overridden when the allow map trigger does not fire. | |||||||||||
| Ensures the fix does not accidentally grant access to non-matching users. | |||||||||||
| """ | |||||||||||
| # Map 1 (order 1): deny all | |||||||||||
| local_authenticator_map.triggers = {"never": {}} | |||||||||||
| local_authenticator_map.map_type = "allow" | |||||||||||
| local_authenticator_map.order = 1 | |||||||||||
| local_authenticator_map.save() | |||||||||||
|
|
|||||||||||
| # Map 2 (order 2): allow only users in group "aap-users" | |||||||||||
| local_authenticator_map_1.triggers = {"groups": {"has_or": ["aap-users"]}} | |||||||||||
| local_authenticator_map_1.map_type = "allow" | |||||||||||
| local_authenticator_map_1.order = 2 | |||||||||||
| local_authenticator_map_1.save() | |||||||||||
|
|
|||||||||||
| authenticator = local_authenticator_map.authenticator | |||||||||||
| # User is NOT in the required group | |||||||||||
| res = claims.create_claims(authenticator, "username", {}, ["other-group"]) | |||||||||||
|
|
|||||||||||
| assert res["access_allowed"] is False | |||||||||||
|
|
|||||||||||
|
|
|||||||||||
| def test_create_claims_deny_all_overridden_with_group_match( | |||||||||||
| local_authenticator_map, | |||||||||||
| local_authenticator_map_1, | |||||||||||
| ): | |||||||||||
| """ | |||||||||||
| Test that a deny-all IS overridden when the user matches the allow map group trigger. | |||||||||||
| End-to-end test of the deny-all + group-based allow pattern. | |||||||||||
| """ | |||||||||||
| # Map 1 (order 1): deny all | |||||||||||
| local_authenticator_map.triggers = {"never": {}} | |||||||||||
| local_authenticator_map.map_type = "allow" | |||||||||||
| local_authenticator_map.order = 1 | |||||||||||
| local_authenticator_map.save() | |||||||||||
|
|
|||||||||||
| # Map 2 (order 2): allow users in group "aap-users" | |||||||||||
| local_authenticator_map_1.triggers = {"groups": {"has_or": ["aap-users"]}} | |||||||||||
| local_authenticator_map_1.map_type = "allow" | |||||||||||
| local_authenticator_map_1.order = 2 | |||||||||||
| local_authenticator_map_1.save() | |||||||||||
|
|
|||||||||||
| authenticator = local_authenticator_map.authenticator | |||||||||||
| # User IS in the required group | |||||||||||
| res = claims.create_claims(authenticator, "username", {}, ["aap-users"]) | |||||||||||
|
|
|||||||||||
| assert res["access_allowed"] is True | |||||||||||
|
|
|||||||||||
|
|
|||||||||||
| def test_create_claims_multiple_same_org( | |||||||||||
| local_authenticator_map, | |||||||||||
| local_authenticator_map_1, | |||||||||||
|
|
|||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Clean fix. This now mirrors the
is_superuserpattern on line 127 (is_superuser = has_permission), making the handling consistent across map types. The "last evaluated map wins" semantic is correct for ordered map evaluation.The old code's
and not has_permissionguard meant allow maps could only deny — they could never grant access back. This simple change restores the intended bidirectional behavior.