Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 11 additions & 14 deletions src/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -496,28 +496,25 @@ def handle_account_selection(ack: Ack, body: dict, client: WebClient) -> SlackRe

if not valid_ps_names:
view_id = body["view"]["id"]
view = slack_helpers.RequestForAccessView.build()
blocks = slack_helpers.remove_blocks(
body["view"]["blocks"],
block_ids=[
slack_helpers.RequestForAccessView.PERMISSION_SET_PLACEHOLDER_BLOCK_ID,
slack_helpers.RequestForAccessView.PERMISSION_SET_BLOCK_ID,
],
updated_view = slack_helpers.RequestForAccessView.build_no_permission_sets_view(
view_blocks=body["view"]["blocks"]
)
blocks = slack_helpers.insert_blocks(
blocks=blocks,
blocks_to_insert=[slack_helpers.RequestForAccessView.build_no_permission_sets_block()],
after_block_id=slack_helpers.RequestForAccessView.ACCOUNT_BLOCK_ID,
)
view.blocks = blocks
return client.views_update(view_id=view_id, view=view)
return client.views_update(view_id=view_id, view=updated_view)

if "*" in valid_ps_names:
permission_sets = sso.get_permission_sets_from_config_with_cache(sso_client=sso_client, s3_client=s3_client, cfg=cfg)
else:
all_ps = sso.get_permission_sets_from_config_with_cache(sso_client=sso_client, s3_client=s3_client, cfg=cfg)
permission_sets = [ps for ps in all_ps if ps.name in valid_ps_names]

# Handle case where filtered list is empty (configured names don't exist in SSO)
if not permission_sets:
view_id = body["view"]["id"]
updated_view = slack_helpers.RequestForAccessView.build_no_permission_sets_view(
view_blocks=body["view"]["blocks"]
)
return client.views_update(view_id=view_id, view=updated_view)

view_id = body["view"]["id"]
updated_view = slack_helpers.RequestForAccessView.update_with_permission_sets(
view_blocks=body["view"]["blocks"],
Expand Down
47 changes: 31 additions & 16 deletions src/slack_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,11 @@ def build(cls) -> View:
callback_id=cls.CALLBACK_ID,
submit=PlainTextObject(text="Request"),
close=PlainTextObject(text="Cancel"),
title=PlainTextObject(text="Request AWS access"),
title=PlainTextObject(text="Request AWS Access"),
blocks=[
SectionBlock(
block_id=cls.DURATION_BLOCK_ID,
text=MarkdownTextObject(text="Access duration"),
text=MarkdownTextObject(text="How long do you need access?"),
accessory=StaticSelectElement(
action_id=cls.DURATION_ACTION_ID,
initial_option=get_max_duration_block(cfg)[0],
Expand All @@ -83,7 +83,7 @@ def build(cls) -> View:
),
InputBlock(
block_id=cls.REASON_BLOCK_ID,
label=PlainTextObject(text="Reason"),
label=PlainTextObject(text="Reason for access"),
element=PlainTextInputElement(
action_id=cls.REASON_ACTION_ID,
placeholder=PlainTextObject(text="What will this access be used for?"),
Expand All @@ -93,7 +93,7 @@ def build(cls) -> View:
DividerBlock(),
SectionBlock(
text=MarkdownTextObject(
text="Remember to use your access responsibly. All AWS actions are logged.",
text="All AWS API calls are logged for security compliance.",
),
),
SectionBlock(
Expand All @@ -115,7 +115,7 @@ def build_select_account_input_block(cls, accounts: list[entities.aws.Account])
sorted_accounts = sorted(accounts, key=lambda account: account.name)
return InputBlock(
block_id=cls.ACCOUNT_BLOCK_ID,
label=PlainTextObject(text="Account"),
label=PlainTextObject(text="AWS Account"),
element=StaticSelectElement(
action_id=cls.ACCOUNT_ACTION_ID,
placeholder=PlainTextObject(text="Select account"),
Expand Down Expand Up @@ -151,7 +151,7 @@ def update_with_accounts(cls, accounts: list[entities.aws.Account]) -> View:
cls.build_select_account_input_block(accounts),
SectionBlock(
block_id=cls.PERMISSION_SET_PLACEHOLDER_BLOCK_ID,
text=MarkdownTextObject(text=":point_up: Select an account to see available permission sets"),
text=MarkdownTextObject(text="Select an account above to see available permission sets"),
),
],
after_block_id=cls.REASON_BLOCK_ID,
Expand All @@ -176,9 +176,26 @@ def update_with_permission_sets(cls, view_blocks: list, permission_sets: list[en
def build_no_permission_sets_block(cls) -> SectionBlock:
return SectionBlock(
block_id=cls.PERMISSION_SET_PLACEHOLDER_BLOCK_ID,
text=MarkdownTextObject(text=":warning: No permission sets available for this account"),
text=MarkdownTextObject(text=":x: No permission sets configured for this account. Contact your admin."),
)

@classmethod
def build_no_permission_sets_view(cls, view_blocks: list) -> View:
"""Build view with warning and disabled submit button."""
view = cls.build()
view.submit_disabled = True
blocks = remove_blocks(
view_blocks,
block_ids=[cls.PERMISSION_SET_PLACEHOLDER_BLOCK_ID, cls.PERMISSION_SET_BLOCK_ID],
)
blocks = insert_blocks(
blocks=blocks,
blocks_to_insert=[cls.build_no_permission_sets_block()],
after_block_id=cls.ACCOUNT_BLOCK_ID,
)
view.blocks = blocks
return view

@classmethod
def parse(cls, obj: dict) -> RequestForAccess:
values = jp.search("view.state.values", obj)
Expand Down Expand Up @@ -542,13 +559,11 @@ def build(cls) -> View: # noqa: ANN102
callback_id=cls.CALLBACK_ID,
submit=PlainTextObject(text="Request"),
close=PlainTextObject(text="Cancel"),
title=PlainTextObject(text="Request AWS access"),
title=PlainTextObject(text="Request Group Access"),
blocks=[
SectionBlock(text=MarkdownTextObject(text=":wave: Hey! Please fill form below to request access to AWS SSO group.")),
DividerBlock(),
SectionBlock(
block_id=cls.DURATION_BLOCK_ID,
text=MarkdownTextObject(text="Select the duration for which the access will be provided"),
text=MarkdownTextObject(text="How long do you need access?"),
accessory=StaticSelectElement(
action_id=cls.DURATION_ACTION_ID,
initial_option=get_max_duration_block(cfg)[0],
Expand All @@ -558,23 +573,23 @@ def build(cls) -> View: # noqa: ANN102
),
InputBlock(
block_id=cls.REASON_BLOCK_ID,
label=PlainTextObject(text="Why do you need access?"),
label=PlainTextObject(text="Reason for access"),
element=PlainTextInputElement(
action_id=cls.REASON_ACTION_ID,
placeholder=PlainTextObject(text="Reason will be saved in audit logs. Please be specific."),
placeholder=PlainTextObject(text="What will this access be used for?"),
multiline=True,
),
),
DividerBlock(),
SectionBlock(
text=MarkdownTextObject(
text="Remember to use access responsibly. All actions (AWS API calls) are being recorded.",
text="All AWS API calls are logged for security compliance.",
),
),
SectionBlock(
block_id=cls.LOADING_BLOCK_ID,
text=MarkdownTextObject(
text=":hourglass: Loading available accounts and permission sets...",
text=":hourglass: Loading available groups...",
),
),
],
Expand Down Expand Up @@ -603,7 +618,7 @@ def build_select_group_input_block(cls, groups: list[entities.aws.SSOGroup]) ->
sorted_groups = sorted(groups, key=lambda groups: groups.name)
return InputBlock(
block_id=cls.GROUP_BLOCK_ID,
label=PlainTextObject(text="Select group"),
label=PlainTextObject(text="SSO Group"),
element=StaticSelectElement(
action_id=cls.GROUP_ACTION_ID,
placeholder=PlainTextObject(text="Select group"),
Expand Down
Loading