Skip to content
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

Group assignments #95

Merged
merged 64 commits into from
Sep 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
1d49401
feat: group access (dump work in progress)
EreminAnton Aug 26, 2024
cf565ee
feat: allow prividing config by terraform
EreminAnton Aug 27, 2024
6237f4e
feat: add a way to approve requests
EreminAnton Aug 27, 2024
c6f7351
refactor: more handle errors func to the errors.py
EreminAnton Aug 28, 2024
9084554
refactoring: move sso to the sso.py & add more type hints
EreminAnton Aug 28, 2024
990a20b
fix: import func from sso
EreminAnton Aug 28, 2024
d3928eb
refactoring: use one "show initial form func, and move request handli…
EreminAnton Aug 28, 2024
bbca552
cleanup: rm unused
EreminAnton Aug 29, 2024
bd5d73d
feat: refactor build_approval_request_message_blocks to work with bot…
EreminAnton Aug 29, 2024
b63aad1
feat: use build_initial_form_handler to show initial form fo both typ…
EreminAnton Aug 29, 2024
46c999a
fix: import build_approval_request_message_blocks from slack_helpers…
EreminAnton Aug 29, 2024
ef93af1
fmt: rm unused, refactor & more logs
EreminAnton Aug 29, 2024
09630ff
fix: run codeguru only in main branch commits
EreminAnton Aug 30, 2024
0822a7c
refactor: move schedule creation to the schedule.py
EreminAnton Aug 29, 2024
eca56e2
fmt: rm unused
EreminAnton Aug 29, 2024
398c1e3
feat: rename execute_decision to execute_decision_on_group_request
EreminAnton Aug 30, 2024
7195354
feat: handle if user is already in the group
EreminAnton Aug 30, 2024
ca72333
feat: more refactorings & rename test.py to group.py
EreminAnton Aug 30, 2024
9f0af73
feat: use default sesion
EreminAnton Aug 30, 2024
d86bf4f
fix: NA if response is unbound
EreminAnton Sep 2, 2024
1dfb02c
fix: import RequestForGroupAccessView from slack_helpers
EreminAnton Sep 2, 2024
8c37c37
fix: create response anyway, and use get to get value
EreminAnton Sep 2, 2024
fe0c32d
feat: handle execute_decision_on_group_request logs better
EreminAnton Sep 2, 2024
dd47c6b
fix: pass correct event to the get_and_delete_scheduled_revoke_event_…
EreminAnton Sep 2, 2024
9461be7
feat: add more logs to get_and_delete_scheduled_revoke_event_if_alrea…
EreminAnton Sep 2, 2024
394233c
fix: provide membership_id in any case
EreminAnton Sep 2, 2024
07b6bab
fix: add group_revoke_event to the get_scheduled_events
EreminAnton Sep 2, 2024
0bdd62d
feat: more logs for get_scheduled_events
EreminAnton Sep 2, 2024
6284261
fix: get right type of events
EreminAnton Sep 2, 2024
5e3598d
fix: use right class in get_and_delete_scheduled_revoke_event_if_alre…
EreminAnton Sep 2, 2024
2c2b807
feat: GroupMembership class
EreminAnton Sep 3, 2024
524fab4
feat: more logs & get_groups_from_config, not all groups
EreminAnton Sep 3, 2024
9e0ee53
feat: refactor is_user_in_group to more easely reuse list_group_membe…
EreminAnton Sep 3, 2024
39a4cde
feat: get group assignments from config
EreminAnton Sep 3, 2024
2aad954
feat: rm unused, and fix import
EreminAnton Sep 3, 2024
e7323d5
feat: check on inconsistency & scheduler revokation
EreminAnton Sep 3, 2024
5803a55
feat: get groups from statements & more logs
EreminAnton Sep 3, 2024
6cc127d
fix: add check_on_groups_inconsistency & handle_sso_elevator_group_sc…
EreminAnton Sep 3, 2024
b2b9754
fix: rm unneeded indent
EreminAnton Sep 3, 2024
b796ace
feat: add GROUP_STATEMENTS to revoker config
EreminAnton Sep 3, 2024
b2baeeb
fix: rm unused
EreminAnton Sep 3, 2024
5716612
feat: use new version of audit entry
EreminAnton Sep 4, 2024
534e011
feat: raise error if both configs are not provided
EreminAnton Sep 4, 2024
0dd1e97
feat: upd readme
EreminAnton Sep 4, 2024
2ab51a1
fmt: precommit run -a
EreminAnton Sep 4, 2024
0083fcf
feat: use aware datetimes to represent times in UTC.
EreminAnton Sep 5, 2024
10bc4f4
feat: fail if message is none on ButtonClickedPayload validations
EreminAnton Sep 5, 2024
7472b28
fix: try fix pytest ci by bypassing config validation
EreminAnton Sep 5, 2024
6a28ce7
fix: try fix ci
EreminAnton Sep 5, 2024
6215f18
fix: try fix config
EreminAnton Sep 5, 2024
083eec1
fix: fix config testing
EreminAnton Sep 5, 2024
6570962
fIx: try fix config tests
EreminAnton Sep 5, 2024
b2887ca
feat: add tests for group_config
EreminAnton Sep 5, 2024
7d00450
fix: rm unused
EreminAnton Sep 5, 2024
cae582d
fix: generate group id properly
EreminAnton Sep 5, 2024
4cbd21e
fix: use correct group id format
EreminAnton Sep 5, 2024
a9f9d73
fix: rm * from group test
EreminAnton Sep 5, 2024
f7ce2b8
fix: add optional part to group config id testing
EreminAnton Sep 5, 2024
00c3f88
fix: try fix config ci
EreminAnton Sep 5, 2024
a0b683d
fix: less examples: to slow
EreminAnton Sep 5, 2024
270de4c
fix: more group id parts
EreminAnton Sep 5, 2024
21609ba
fix: increase deadline
EreminAnton Sep 5, 2024
2dad56f
fix: supress HealthCheck.too_slow
EreminAnton Sep 5, 2024
056d231
fix: disable HealthCheck.too_slow for individual tests
EreminAnton Sep 5, 2024
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
2 changes: 1 addition & 1 deletion .github/workflows/code-guru.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: CodeGuru Review

on:
push:
branches: [ "*" ]
branches: [ "main" ]
workflow_dispatch:

permissions:
Expand Down
115 changes: 96 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
- [Terraform module for implementing temporary elevated access via AWS IAM Identity Center (Successor to AWS Single Sign-On) and Slack](#terraform-module-for-implementing-temporary-elevated-access-via-aws-iam-identity-center-successor-to-aws-single-sign-on-and-slack)
- [Introduction](#introduction)
- [Functionality](#functionality)
- [Group Assignments Mode](#group-assignments-mode)
- [Important Considerations and Assumptions](#important-considerations-and-assumptions)
- [Deployment and Usage](#deployment-and-usage)
- [Note on dependencies](#note-on-dependencies)
Expand Down Expand Up @@ -69,6 +70,50 @@ For auditing purposes, information about all access grants and revocations is st

Additionally, the Access-Revoker continuously reconciles the revocation schedule with all user-level permission set assignments and issues warnings if it detects assignments without a revocation schedule (presumably created by someone manually). By default, the Access-Revoker will automatically revoke all unknown user-level permission set assignments daily. However, you can configure it to operate more or less frequently.

## Group Assignments Mode
Starting from version 2.0, Terraform AWS SSO Elevator introduces support for group access. Users can now use the /group-access command, which, instead of showing the form for account assignments, will present a Slack form where the user can select a group they want access to, specify a reason, and define the duration for which access is required.

The basic logic for access, configuration, and Slack integration remains the same as before. To enable the new Group Assignments Mode, you need to provide the module with a new group_config Terraform variable:
```hcl
group_config = [
{
"Resource" : ["99999999-8888-7777-6666-555555555555"], #ManagementAccountAdmins
"Approvers" : [
"[email protected]"
]
"ApprovalIsNotRequired": true
},
{
"Resource" : ["11111111-2222-3333-4444-555555555555"], #prod read only
"Approvers" : [
"[email protected]"
]
"AllowSelfApproval" : true,
},
{
"Resource" : ["44445555-3333-2222-1111-555557777777"], #ProdAdminAccess
"Approvers" : [
"[email protected]"
]
},
]
```
There are two key differences compared to the standard Elevator configuration:
- ResourceType is not required for group access configurations.
- In the Resource field, you must provide group IDs instead of account IDs.

The Elevator will only work with groups specified in the configuration.

If you were using Terraform AWS SSO Elevator before version 2.0.0, you need to update your Slack app manifest by adding a new shortcut to enable this functionality:
{
"name": "group-access",
"type": "global",
"callback_id": "request_for_group_membership",
"description": "Request access to SSO Group"
}
To disable this functionality, simply remove the shortcut from the manifest.


# Important Considerations and Assumptions

SSO elevator assumes that your Slack user email will match SSO user id otherwise it won't be able to match Slack user sending request to an AWS SSO user.
Expand All @@ -94,20 +139,20 @@ ECR is private for the following reasons:

Images and repositories are replicated in every region that AWS SSO supports exept these:
```
# ap_east_1
# eu_south_1
# ap_southeast_3
# af_south_1
# me_south_1
# il_central_1
# me_central_1
# eu_south_2
# ap_south_2
# eu_central_2
# ap_southeast_4
# ca_west_1
# us_gov_east_1
# us_gov_west_1
- ap_east_1
- eu_south_1
- ap_southeast_3
- af_south_1
- me_south_1
- il_central_1
- me_central_1
- eu_south_2
- ap_south_2
- eu_central_2
- ap_southeast_4
- ca_west_1
- us_gov_east_1
- us_gov_west_1
```
Those regions are not enabled by deafult. If you need to use a region that is not supported by the module, please let us know by creating an issue, and we will add support for it.

Expand Down Expand Up @@ -327,6 +372,28 @@ module "aws_sso_elevator" {
},

]
group_config = [
{
"Resource" : ["99999999-8888-7777-6666-555555555555"], #ManagementAccountAdmins
"Approvers" : [
"[email protected]"
]
"ApprovalIsNotRequired": true
},
{
"Resource" : ["11111111-2222-3333-4444-555555555555"], #prod read only
"Approvers" : [
"[email protected]"
]
"AllowSelfApproval" : true,
},
{
"Resource" : ["44445555-3333-2222-1111-555557777777"], #ProdAdminAccess
"Approvers" : [
"[email protected]"
]
},
]
}

output "aws_sso_elevator_lambda_function_url" {
Expand Down Expand Up @@ -354,6 +421,10 @@ features:
type: global
callback_id: request_for_access
description: Request access to Permission Set in AWS Account
- name: group-access # Delete this shortcut if you want to prohibit access to the Group Assignments Mode
type: global
callback_id: request_for_group_membership
description: Request access to SSO Group
oauth_config:
scopes:
bot:
Expand Down Expand Up @@ -397,7 +468,7 @@ settings:

| Name | Version |
|------|---------|
| <a name="provider_aws"></a> [aws](#provider\_aws) | 5.56.1 |
| <a name="provider_aws"></a> [aws](#provider\_aws) | 5.65.0 |
| <a name="provider_random"></a> [random](#provider\_random) | 3.6.2 |

## Modules
Expand All @@ -421,6 +492,7 @@ settings:
| [aws_iam_role.eventbridge_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource |
| [aws_iam_role_policy.eventbridge_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource |
| [aws_lambda_permission.eventbridge](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_permission) | resource |
| [aws_lambda_permission.url](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_permission) | resource |
| [aws_scheduler_schedule_group.one_time_schedule_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/scheduler_schedule_group) | resource |
| [aws_sns_topic.dlq](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sns_topic) | resource |
| [aws_sns_topic_subscription.dlq](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sns_topic_subscription) | resource |
Expand All @@ -439,9 +511,13 @@ settings:
| <a name="input_approver_renotification_initial_wait_time"></a> [approver\_renotification\_initial\_wait\_time](#input\_approver\_renotification\_initial\_wait\_time) | The initial wait time before the first re-notification to the approver is sent. This is measured in minutes. If set to 0, no re-notifications will be sent. | `number` | `15` | no |
| <a name="input_aws_sns_topic_subscription_email"></a> [aws\_sns\_topic\_subscription\_email](#input\_aws\_sns\_topic\_subscription\_email) | value for the email address to subscribe to the SNS topic | `string` | `""` | no |
| <a name="input_config"></a> [config](#input\_config) | value for the SSO Elevator config | `any` | n/a | yes |
| <a name="input_ecr_owner_account_id"></a> [ecr\_owner\_account\_id](#input\_ecr\_owner\_account\_id) | In what account is the ECR repository located. | `string` | `"754426185857"` | no |
| <a name="input_event_brige_check_on_inconsistency_rule_name"></a> [event\_brige\_check\_on\_inconsistency\_rule\_name](#input\_event\_brige\_check\_on\_inconsistency\_rule\_name) | value for the event bridge check on inconsistency rule name | `string` | `"sso_elevator_check_on_inconsistency"` | no |
| <a name="input_event_brige_scheduled_revocation_rule_name"></a> [event\_brige\_scheduled\_revocation\_rule\_name](#input\_event\_brige\_scheduled\_revocation\_rule\_name) | value for the event bridge scheduled revocation rule name | `string` | `"sso_elevator_scheduled_revocation"` | no |
| <a name="input_create_api_gateway"></a> [create\_api\_gateway](#input\_create\_api\_gateway) | If true, module will create & configure API Gateway for the Lambda function | `bool` | `true` | no |
| <a name="input_create_lambda_url"></a> [create\_lambda\_url](#input\_create\_lambda\_url) | If true, the Lambda function will continue to use the Lambda URL, which will be deprecated in the future<br>If false, Lambda url will be deleted. | `bool` | `true` | no |
| <a name="input_ecr_owner_account_id"></a> [ecr\_owner\_account\_id](#input\_ecr\_owner\_account\_id) | In what account is the ECR repository located. | `string` | `"222341826240"` | no |
| <a name="input_ecr_repo_name"></a> [ecr\_repo\_name](#input\_ecr\_repo\_name) | The name of the ECR repository. | `string` | `"aws-sso-elevator"` | no |
| <a name="input_event_brige_check_on_inconsistency_rule_name"></a> [event\_brige\_check\_on\_inconsistency\_rule\_name](#input\_event\_brige\_check\_on\_inconsistency\_rule\_name) | value for the event bridge check on inconsistency rule name | `string` | `"sso-elevator-check_on-inconsistency"` | no |
| <a name="input_event_brige_scheduled_revocation_rule_name"></a> [event\_brige\_scheduled\_revocation\_rule\_name](#input\_event\_brige\_scheduled\_revocation\_rule\_name) | value for the event bridge scheduled revocation rule name | `string` | `"sso-elevator-scheduled-revocation"` | no |
| <a name="input_group_config"></a> [group\_config](#input\_group\_config) | value for the SSO Elevator group config | `any` | n/a | yes |
| <a name="input_log_level"></a> [log\_level](#input\_log\_level) | value for the log level | `string` | `"INFO"` | no |
| <a name="input_max_permissions_duration_time"></a> [max\_permissions\_duration\_time](#input\_max\_permissions\_duration\_time) | Maximum duration of the permissions granted by the Elevator in hours. | `number` | `24` | no |
| <a name="input_request_expiration_hours"></a> [request\_expiration\_hours](#input\_request\_expiration\_hours) | After how many hours should the request expire? If set to 0, the request will never expire. | `number` | `8` | no |
Expand All @@ -458,7 +534,7 @@ settings:
| <a name="input_schedule_expression"></a> [schedule\_expression](#input\_schedule\_expression) | recovation schedule expression (will revoke all user-level assignments unknown to the Elevator) | `string` | `"cron(0 23 * * ? *)"` | no |
| <a name="input_schedule_expression_for_check_on_inconsistency"></a> [schedule\_expression\_for\_check\_on\_inconsistency](#input\_schedule\_expression\_for\_check\_on\_inconsistency) | how often revoker should check for inconsistency (warn if found unknown user-level assignments) | `string` | `"rate(2 hours)"` | no |
| <a name="input_schedule_group_name"></a> [schedule\_group\_name](#input\_schedule\_group\_name) | value for the schedule group name | `string` | `"sso-elevator-scheduled-revocation"` | no |
| <a name="input_schedule_role_name"></a> [schedule\_role\_name](#input\_schedule\_role\_name) | value for the schedule role name | `string` | `"event-bridge-role-for-sso-elevator"` | no |
| <a name="input_schedule_role_name"></a> [schedule\_role\_name](#input\_schedule\_role\_name) | value for the schedule role name | `string` | `"sso-elevator-event-bridge-role"` | no |
| <a name="input_slack_bot_token"></a> [slack\_bot\_token](#input\_slack\_bot\_token) | value for the Slack bot token | `string` | n/a | yes |
| <a name="input_slack_channel_id"></a> [slack\_channel\_id](#input\_slack\_channel\_id) | value for the Slack channel ID | `string` | n/a | yes |
| <a name="input_slack_signing_secret"></a> [slack\_signing\_secret](#input\_slack\_signing\_secret) | value for the Slack signing secret | `string` | n/a | yes |
Expand All @@ -470,6 +546,7 @@ settings:

| Name | Description |
|------|-------------|
| <a name="output_lambda_function_url"></a> [lambda\_function\_url](#output\_lambda\_function\_url) | value for the access\_requester lambda function URL |
| <a name="output_requester_api_endpoint_url"></a> [requester\_api\_endpoint\_url](#output\_requester\_api\_endpoint\_url) | The full URL to invoke the API. Pass this URL into the Slack App manifest as the Request URL. |
| <a name="output_sso_elevator_bucket_id"></a> [sso\_elevator\_bucket\_id](#output\_sso\_elevator\_bucket\_id) | The name of the SSO elevator bucket. |
<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
Expand Down
11 changes: 11 additions & 0 deletions perm_revoker_lambda.tf
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ module "access_revoker" {

SSO_INSTANCE_ARN = local.sso_instance_arn
STATEMENTS = jsonencode(var.config)
GROUP_STATEMENTS = jsonencode(var.group_config)
POWERTOOLS_LOGGER_LOG_EVENT = true

POST_UPDATE_TO_SLACK = var.revoker_post_update_to_slack
Expand Down Expand Up @@ -155,6 +156,16 @@ data "aws_iam_policy_document" "revoker" {
]
resources = ["${local.s3_bucket_arn}/${var.s3_bucket_partition_prefix}/*"]
}
statement {
effect = "Allow"
actions = [
"identitystore:ListGroups",
"identitystore:DescribeGroup",
"identitystore:ListGroupMemberships",
"identitystore:DeleteGroupMembership"
]
resources = ["*"]
}
}

resource "aws_cloudwatch_event_rule" "sso_elevator_scheduled_revocation" {
Expand Down
11 changes: 11 additions & 0 deletions slack_handler_lambda.tf
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ module "access_requester_slack_handler" {

SSO_INSTANCE_ARN = local.sso_instance_arn
STATEMENTS = jsonencode(var.config)
GROUP_STATEMENTS = jsonencode(var.group_config)
POWERTOOLS_LOGGER_LOG_EVENT = true
SCHEDULE_POLICY_ARN = aws_iam_role.eventbridge_role.arn
REVOKER_FUNCTION_ARN = local.revoker_lambda_arn
Expand Down Expand Up @@ -206,6 +207,16 @@ data "aws_iam_policy_document" "slack_handler" {
]
resources = ["*"]
}
statement {
effect = "Allow"
actions = [
"identitystore:ListGroups",
"identitystore:DescribeGroup",
"identitystore:ListGroupMemberships",
"identitystore:CreateGroupMembership",
]
resources = ["*"]
}
}

module "http_api" {
Expand Down
Loading
Loading