Skip to content

Commit 4475af8

Browse files
authored
Merge pull request #15 from PostHog/tom/fix-2
Fix using permission set arn (again)
2 parents 9f810fc + d54c4fe commit 4475af8

File tree

6 files changed

+43
-23
lines changed

6 files changed

+43
-23
lines changed

src/access_control.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,10 @@ def determine_affected_statements(
4343
account_id: str | None = None,
4444
permission_set_name: str | None = None,
4545
group_id: str | None = None,
46+
permission_set_arn: str | None = None,
4647
) -> FrozenSet[Statement] | FrozenSet[GroupStatement]:
4748
if isinstance(statements, FrozenSet) and all(isinstance(item, Statement) for item in statements):
48-
return get_affected_statements(statements, account_id, permission_set_name) # type: ignore # noqa: PGH003
49+
return get_affected_statements(statements, account_id, permission_set_name, permission_set_arn) # type: ignore # noqa: PGH003
4950

5051
if isinstance(statements, FrozenSet) and all(isinstance(item, GroupStatement) for item in statements):
5152
return get_affected_group_statements(statements, group_id) # type: ignore # noqa: PGH003
@@ -63,6 +64,7 @@ def make_decision_on_access_request( # noqa: PLR0911, PLR0913
6364
account_id: str | None = None,
6465
group_id: str | None = None,
6566
user_group_ids: set[str] | None = None,
67+
permission_set_arn: str | None = None,
6668
) -> AccessRequestDecision:
6769
"""Make a decision on an access request.
6870
@@ -75,13 +77,14 @@ def make_decision_on_access_request( # noqa: PLR0911, PLR0913
7577
user_group_ids: The set of SSO group IDs the user belongs to.
7678
If None, group-based filtering is skipped (backwards compatible).
7779
If an empty set, only statements without required_group_membership will match.
80+
permission_set_arn: The ARN of the permission set (optional, for matching ARN-based config).
7881
"""
7982
# Filter statements by user's group membership eligibility if user_group_ids provided
8083
# This is only applicable to Statement (not GroupStatement)
8184
if user_group_ids is not None and isinstance(statements, frozenset) and all(isinstance(s, Statement) for s in statements):
8285
statements = get_eligible_statements_for_user(statements, user_group_ids) # type: ignore # noqa: PGH003
8386

84-
affected_statements = determine_affected_statements(statements, account_id, permission_set_name, group_id)
87+
affected_statements = determine_affected_statements(statements, account_id, permission_set_name, group_id, permission_set_arn)
8588

8689
decision_based_on_statements: set[Statement] | set[GroupStatement] = set()
8790
potential_approvers = set()
@@ -168,8 +171,9 @@ def make_decision_on_approve_request( # noqa: PLR0913
168171
permission_set_name: str | None = None,
169172
account_id: str | None = None,
170173
group_id: str | None = None,
174+
permission_set_arn: str | None = None,
171175
) -> ApproveRequestDecision:
172-
affected_statements = determine_affected_statements(statements, account_id, permission_set_name, group_id)
176+
affected_statements = determine_affected_statements(statements, account_id, permission_set_name, group_id, permission_set_arn)
173177

174178
for statement in affected_statements:
175179
if approver_email in statement.approvers:

src/main.py

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,9 @@ def handle_button_click(body: dict, client: WebClient, context: BoltContext) ->
258258
cache_for_dublicate_requests["account_id"] = payload.request.account_id
259259
cache_for_dublicate_requests["permission_set_name"] = payload.request.permission_set_name
260260

261+
# Look up permission set to get ARN for matching and name for display
262+
permission_set = sso.get_permission_set(sso_client, cfg.sso_instance_arn, payload.request.permission_set_name)
263+
261264
if payload.action == entities.ApproverAction.Discard:
262265
blocks = slack_helpers.HeaderSectionBlock.set_status(
263266
blocks=payload.message["blocks"],
@@ -281,7 +284,7 @@ def handle_button_click(body: dict, client: WebClient, context: BoltContext) ->
281284
distinct_id=requester.email,
282285
properties={
283286
"account_id": payload.request.account_id,
284-
"permission_set": payload.request.permission_set_name,
287+
"permission_set": permission_set.name,
285288
"approver_email": approver.email,
286289
"requester_email": requester.email,
287290
},
@@ -304,6 +307,7 @@ def handle_button_click(body: dict, client: WebClient, context: BoltContext) ->
304307
permission_set_name=payload.request.permission_set_name,
305308
approver_email=approver.email,
306309
requester_email=requester.email,
310+
permission_set_arn=permission_set.arn,
307311
)
308312
logger.info("Decision on request was made", extra={"decision": decision.dict()})
309313

@@ -349,7 +353,7 @@ def handle_button_click(body: dict, client: WebClient, context: BoltContext) ->
349353
distinct_id=requester.email,
350354
properties={
351355
"account_id": payload.request.account_id,
352-
"permission_set": payload.request.permission_set_name,
356+
"permission_set": permission_set.name,
353357
"approver_email": approver.email,
354358
"requester_email": requester.email,
355359
"duration_hours": payload.request.permission_duration.total_seconds() / 3600,
@@ -443,12 +447,16 @@ def handle_request_for_access_submittion( # noqa: PLR0915, PLR0912
443447
user_principal_id=user_principal_id,
444448
)
445449

450+
# Look up permission set to get ARN for matching against ARN-based config
451+
permission_set = sso.get_permission_set(sso_client, cfg.sso_instance_arn, request.permission_set_name)
452+
446453
decision = access_control.make_decision_on_access_request(
447454
cfg.statements,
448455
account_id=request.account_id,
449456
permission_set_name=request.permission_set_name,
450457
requester_email=requester.email,
451458
user_group_ids=user_group_ids,
459+
permission_set_arn=permission_set.arn,
452460
)
453461
logger.info("Decision on request was made", extra={"decision": decision.dict()})
454462

@@ -457,7 +465,7 @@ def handle_request_for_access_submittion( # noqa: PLR0915, PLR0912
457465
distinct_id=requester.email,
458466
properties={
459467
"account_id": request.account_id,
460-
"permission_set": request.permission_set_name,
468+
"permission_set": permission_set.name,
461469
"requester_email": requester.email,
462470
"decision_reason": decision.reason.value,
463471
"granted": decision.grant,
@@ -478,7 +486,7 @@ def handle_request_for_access_submittion( # noqa: PLR0915, PLR0912
478486
slack_client=client,
479487
requester_slack_id=request.requester_slack_id,
480488
account=account,
481-
role_name=request.permission_set_name,
489+
role_name=permission_set.name,
482490
reason=request.reason,
483491
permission_duration=request.permission_duration,
484492
show_buttons=show_buttons,
@@ -590,7 +598,7 @@ def handle_request_for_access_submittion( # noqa: PLR0915, PLR0912
590598
distinct_id=requester.email,
591599
properties={
592600
"account_id": request.account_id,
593-
"permission_set": request.permission_set_name,
601+
"permission_set": permission_set.name,
594602
"approver_email": requester.email,
595603
"requester_email": requester.email,
596604
"duration_hours": request.permission_duration.total_seconds() / 3600,

src/revoker.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -463,9 +463,7 @@ def slack_notify_user_on_revoke( # noqa: PLR0913
463463
)
464464
# Delete the early revoke button from the thread
465465
slack_helpers.delete_early_revoke_button(slack_client, cfg.slack_channel_id, thread_ts)
466-
# Simplified message for threads (context already in thread)
467-
# Change the "Access revoked." message to something friendly and maybe even a bit cheeky. It's too serious. At a minimum "Access expired""ended"/"completed"
468-
text = "Access revoked."
466+
text = "Session complete."
469467
else:
470468
# Full message when not in a thread
471469
mention = slack_helpers.create_slack_mention_by_principal_id(
@@ -515,9 +513,7 @@ def slack_notify_user_on_group_access_revoke( # noqa: PLR0913
515513
)
516514
# Delete the early revoke button from the thread
517515
slack_helpers.delete_early_revoke_button(slack_client, cfg.slack_channel_id, thread_ts)
518-
# Simplified message for threads (context already in thread)
519-
# Change the "Access revoked." message to something friendly and maybe even a bit cheeky. It's too serious. At a minimum "Access expired""ended"/"completed"
520-
text = "Access revoked."
516+
text = "Session complete."
521517
else:
522518
# Full message when not in a thread
523519
mention = slack_helpers.create_slack_mention_by_principal_id(

src/slack_helpers.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ def build_select_permission_set_input_block(cls, permission_sets: list[entities.
137137
action_id=cls.PERMISSION_SET_ACTION_ID,
138138
placeholder=PlainTextObject(text="Select permission set"),
139139
options=[
140-
Option(text=PlainTextObject(text=permission_set.name), value=permission_set.name)
140+
Option(text=PlainTextObject(text=permission_set.name), value=permission_set.arn)
141141
for permission_set in sorted_permission_sets
142142
],
143143
),

src/sso.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -500,7 +500,7 @@ def get_permission_sets_from_config_with_cache(
500500
if "*" in cfg.permission_sets:
501501
return all_permission_sets
502502
else:
503-
return [ps for ps in all_permission_sets if ps.name in cfg.permission_sets]
503+
return [ps for ps in all_permission_sets if ps.name in cfg.permission_sets or ps.arn in cfg.permission_sets]
504504

505505

506506
def get_account_assignment_information(

src/statement.py

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,26 @@ class Statement(BaseStatement):
3232
resource_type: ResourceType = Field(default=ResourceType.Account, frozen=True)
3333
resource: FrozenSet[Union[AWSAccountId, WildCard]]
3434

35-
def affects(self, account_id: str, permission_set_name: str) -> bool: # noqa: ANN101
36-
return (account_id in self.resource or "*" in self.resource) and (
37-
permission_set_name in self.permission_set or "*" in self.permission_set
35+
def affects(self, account_id: str, permission_set_name: str, permission_set_arn: str | None = None) -> bool: # noqa: ANN101
36+
account_match = account_id in self.resource or "*" in self.resource
37+
ps_match = (
38+
permission_set_name in self.permission_set
39+
or "*" in self.permission_set
40+
or (permission_set_arn is not None and permission_set_arn in self.permission_set)
3841
)
39-
40-
41-
def get_affected_statements(statements: FrozenSet[Statement], account_id: str, permission_set_name: str) -> FrozenSet[Statement]:
42-
return frozenset(statement for statement in statements if statement.affects(account_id, permission_set_name))
42+
return account_match and ps_match
43+
44+
45+
def get_affected_statements(
46+
statements: FrozenSet[Statement],
47+
account_id: str,
48+
permission_set_name: str,
49+
permission_set_arn: str | None = None,
50+
) -> FrozenSet[Statement]:
51+
return frozenset(
52+
statement for statement in statements
53+
if statement.affects(account_id, permission_set_name, permission_set_arn)
54+
)
4355

4456

4557
def get_permission_sets_for_account(statements: FrozenSet[Statement], account_id: str) -> set[str]:

0 commit comments

Comments
 (0)