Skip to content

Commit 7068591

Browse files
authored
Fix externally managed groups notification bug (#323)
1 parent 0f4e518 commit 7068591

File tree

2 files changed

+62
-0
lines changed

2 files changed

+62
-0
lines changed

api/syncer.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,7 @@ def expiring_access_notifications_user() -> None:
412412
)
413413
.join(OktaUserGroupMember.active_user)
414414
.join(OktaUserGroupMember.active_group)
415+
.filter(OktaGroup.is_managed.is_(True))
415416
.filter(db.and_(OktaUserGroupMember.ended_at >= day, OktaUserGroupMember.ended_at < next_day))
416417
.filter(OktaUserGroupMember.role_group_map_id.is_(None))
417418
.filter(OktaUserGroupMember.should_expire.is_(False))
@@ -459,6 +460,7 @@ def expiring_access_notifications_user() -> None:
459460
)
460461
.join(OktaUserGroupMember.active_user)
461462
.join(OktaUserGroupMember.active_group)
463+
.filter(OktaGroup.is_managed.is_(True))
462464
.filter(db.and_(OktaUserGroupMember.ended_at >= day, OktaUserGroupMember.ended_at < next_day))
463465
.filter(OktaUserGroupMember.role_group_map_id.is_(None))
464466
.filter(OktaUserGroupMember.should_expire.is_(False))
@@ -535,6 +537,7 @@ def expiring_access_notifications_owner() -> None:
535537
)
536538
.join(OktaUserGroupMember.active_user)
537539
.join(OktaUserGroupMember.active_group)
540+
.filter(OktaGroup.is_managed.is_(True))
538541
.filter(db.and_(OktaUserGroupMember.ended_at >= day, OktaUserGroupMember.ended_at < next_week))
539542
.filter(OktaUserGroupMember.role_group_map_id.is_(None))
540543
.filter(OktaUserGroupMember.should_expire.is_(False))
@@ -595,6 +598,7 @@ def expiring_access_notifications_owner() -> None:
595598
)
596599
.join(OktaUserGroupMember.active_user)
597600
.join(OktaUserGroupMember.active_group)
601+
.filter(OktaGroup.is_managed.is_(True))
598602
.filter(db.and_(OktaUserGroupMember.ended_at >= one_week, OktaUserGroupMember.ended_at < two_weeks))
599603
.filter(OktaUserGroupMember.role_group_map_id.is_(None))
600604
.filter(OktaUserGroupMember.should_expire.is_(False))
@@ -698,6 +702,7 @@ def expiring_access_notifications_owner() -> None:
698702
)
699703
.join(RoleGroupMap.active_role_group.of_type(role_group_alias))
700704
.join(RoleGroupMap.active_group)
705+
.filter(OktaGroup.is_managed.is_(True))
701706
.filter(db.and_(RoleGroupMap.ended_at >= day, RoleGroupMap.ended_at < next_week))
702707
.filter(RoleGroupMap.should_expire.is_(False))
703708
.all()
@@ -748,6 +753,7 @@ def expiring_access_notifications_owner() -> None:
748753
)
749754
.join(RoleGroupMap.active_role_group.of_type(role_group_alias))
750755
.join(RoleGroupMap.active_group)
756+
.filter(OktaGroup.is_managed.is_(True))
751757
.filter(db.and_(RoleGroupMap.ended_at >= one_week, RoleGroupMap.ended_at < two_weeks))
752758
.filter(RoleGroupMap.should_expire.is_(False))
753759
.all()
@@ -855,6 +861,7 @@ def expiring_access_notifications_role_owner() -> None:
855861
)
856862
.join(RoleGroupMap.active_role_group.of_type(role_group_alias))
857863
.join(RoleGroupMap.active_group)
864+
.filter(OktaGroup.is_managed.is_(True))
858865
.filter(db.and_(RoleGroupMap.ended_at >= day, RoleGroupMap.ended_at < next_day))
859866
.filter(RoleGroupMap.should_expire.is_(False))
860867
.all()
@@ -884,6 +891,7 @@ def expiring_access_notifications_role_owner() -> None:
884891
)
885892
.join(RoleGroupMap.active_role_group.of_type(role_group_alias))
886893
.join(RoleGroupMap.active_group)
894+
.filter(OktaGroup.is_managed.is_(True))
887895
.filter(db.and_(RoleGroupMap.ended_at >= day, RoleGroupMap.ended_at < next_day))
888896
.filter(RoleGroupMap.should_expire.is_(False))
889897
.all()

tests/test_expiring_access_notifications.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from datetime import datetime, timedelta
22

3+
from flask import Flask
34
from flask_sqlalchemy import SQLAlchemy
45
from pytest_mock import MockerFixture
56

@@ -771,3 +772,56 @@ def test_role_owner_expiring_access_notifications_role_multiple_dates(db: SQLAlc
771772
assert membership2 in kwargs["roles"]
772773
assert membership3 in kwargs["roles"]
773774
assert kwargs["expiration_datetime"] is None
775+
776+
777+
# Test with an externally managed group and a non-externally managed group. The Access admin should only be notified about
778+
# expiring access for the non-externally managed group
779+
def test_owner_expiring_access_notifications_managed_group_admin(
780+
db: SQLAlchemy, app: Flask, mocker: MockerFixture
781+
) -> None:
782+
# Create an externally managed group and an Access managed group
783+
group1 = OktaGroupFactory.create()
784+
group1.is_managed = False
785+
group2 = OktaGroupFactory.create()
786+
787+
user = OktaUserFactory.create()
788+
access_owner = OktaUser.query.filter(OktaUser.email == app.config["CURRENT_OKTA_USER_EMAIL"]).first()
789+
790+
expiration_datetime = datetime.now() + timedelta(days=2)
791+
792+
db.session.add(group1)
793+
db.session.add(group2)
794+
db.session.add(user)
795+
db.session.commit()
796+
797+
ModifyGroupUsers(
798+
group=group1, users_added_ended_at=expiration_datetime, members_to_add=[user.id], sync_to_okta=False
799+
).execute()
800+
ModifyGroupUsers(
801+
group=group2, users_added_ended_at=expiration_datetime, members_to_add=[user.id], sync_to_okta=False
802+
).execute()
803+
804+
membership = (
805+
OktaUserGroupMember.query.filter(OktaUserGroupMember.group_id == group2.id)
806+
.filter(OktaUserGroupMember.user_id == user.id)
807+
.first()
808+
)
809+
810+
hook = get_notification_hook()
811+
expiring_access_notification_spy = mocker.patch.object(hook, "access_expiring_owner")
812+
813+
expiring_access_notifications_owner()
814+
815+
# Access admin should only be notified about expiring access for the Access managed group
816+
assert expiring_access_notification_spy.call_count == 1
817+
_, kwargs = expiring_access_notification_spy.call_args
818+
assert kwargs["owner"].id == access_owner.id
819+
assert len(kwargs["group_user_associations"]) == 1
820+
assert membership in kwargs["group_user_associations"]
821+
assert kwargs["role_group_associations"] is None
822+
# TODO eventually clean this up, leaving for now for backwards compatibility
823+
assert len(kwargs["groups"]) == 1
824+
assert group2 in kwargs["groups"]
825+
assert len(kwargs["users"]) == 1
826+
assert user in kwargs["users"]
827+
assert kwargs["roles"] is None

0 commit comments

Comments
 (0)