Skip to content

PostHog/terraform-aws-sso-elevator

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

569 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Terraform AWS SSO Elevator

Temporary elevated access to AWS accounts via AWS IAM Identity Center (SSO) and Slack.

Note: This is a fork of FivexL/terraform-aws-sso-elevator. Credit to FivexL for creating and maintaining the original module.

Overview

AWS IAM Identity Center doesn't support temporary assignment of permission sets. This module enables temporary elevated access to AWS accounts, achieving the principle of least privilege access without permanently assigned permission sets.

Users request access via a Slack form. Requests are approved/denied by designated approvers. Access is automatically revoked when the time expires.

How It Works

sequenceDiagram
    Requester->>Slack: submits form in Slack - CMD+K, search access or /access command
    Slack->>AWS Lambda - Access Requester: sends request to access-requester
    AWS Lambda - Access Requester->>Slack: sends a message to Slack channel with approve/deny buttons and tags approvers
    Approver->>Slack: pressed approve button in Slack message
    Slack->>AWS Lambda - Access Requester: Send approved request to access-requester
    AWS Lambda - Access Requester->>AWS IAM Identity Center(SSO): creates user-level permission set assignment based on approved request
    AWS Lambda - Access Requester->>AWS EventBridge: creates revocation schedule
    AWS Lambda - Access Requester->>AWS S3: logs audit record
    AWS EventBridge->>AWS Lambda - Access Revoker: sends revocation event when times come
    AWS Lambda - Access Revoker->>AWS IAM Identity Center(SSO): revokes user-level permission set assignment
    AWS Lambda - Access Revoker->>AWS S3: logs audit record
    AWS Lambda - Access Revoker->>Slack:  send notification about revocation
Loading

Quick Start

data "aws_ssoadmin_instances" "this" {}

data "aws_ssm_parameter" "slack_signing_secret" {
  name = "/sso-elevator/slack-signing-secret"
}

data "aws_ssm_parameter" "slack_bot_token" {
  name = "/sso-elevator/slack-bot-token"
}

module "aws_sso_elevator" {
  source = "github.com/PostHog/terraform-aws-sso-elevator"

  slack_signing_secret = data.aws_ssm_parameter.slack_signing_secret.value
  slack_bot_token      = data.aws_ssm_parameter.slack_bot_token.value
  slack_channel_id     = "C01234567"
  identity_store_id    = tolist(data.aws_ssoadmin_instances.this.identity_store_ids)[0]

  s3_logging = {
    target_bucket = "my-access-logs-bucket"
    target_prefix = "sso-elevator/"
  }

  config = [
    {
      "ResourceType" : "Account",
      "Resource" : "*",
      "PermissionSet" : "*",
      "Approvers" : ["admin@company.com"],
      "AllowSelfApproval" : true,
    },
  ]
}

output "api_endpoint_url" {
  value = module.aws_sso_elevator.requester_api_endpoint_url
}

Documentation

  • Configuration - Configuration structure, rules, explicit deny, auto-approval
  • Group Access - Group assignments mode, attribute-based sync
  • Deployment - SSO delegation, build process, Terraform examples, Slack app setup
  • Features - Secondary domains, direct messages, API gateway, request expiration
  • Cache Implementation - Details on caching mechanism
  • Athena Queries - Query audit logs with AWS Athena

Important Considerations

  • Your Slack user email must match your SSO user ID for requests to work.
  • The access-revoker will revoke all user-level Permission Set assignments not created by SSO Elevator. Use group-level assignments for permanent access.
  • If using group_config, SSO Elevator will remove users from those groups if they weren't added by SSO Elevator.

Terraform Docs

Requirements

Name Version
terraform ~> 1.0
aws >= 4.64
external >= 1.0
local >= 1.0
null >= 2.0
random >= 3.0

Providers

Name Version
aws >= 4.64
null >= 2.0
random >= 3.0

Modules

Name Source Version
access_requester_slack_handler terraform-aws-modules/lambda/aws 8.1.2
access_revoker terraform-aws-modules/lambda/aws 8.1.2
attribute_syncer terraform-aws-modules/lambda/aws 8.1.2
audit_bucket fivexl/account-baseline/aws//modules/s3_baseline 2.0.0
config_bucket fivexl/account-baseline/aws//modules/s3_baseline 2.0.0
http_api terraform-aws-modules/apigateway-v2/aws 5.0.0
slack_handler_alias terraform-aws-modules/lambda/aws//modules/alias 8.1.2
sso_elevator_dependencies terraform-aws-modules/lambda/aws 8.1.2

Resources

Name Type
aws_cloudwatch_event_rule.attribute_sync_schedule resource
aws_cloudwatch_event_rule.sso_elevator_check_on_inconsistency resource
aws_cloudwatch_event_rule.sso_elevator_scheduled_revocation resource
aws_cloudwatch_event_target.attribute_sync_schedule resource
aws_cloudwatch_event_target.check_inconsistency resource
aws_cloudwatch_event_target.sso_elevator_scheduled_revocation resource
aws_iam_role.eventbridge_role resource
aws_iam_role_policy.eventbridge_policy resource
aws_lambda_permission.eventbridge resource
aws_lambda_provisioned_concurrency_config.slack_handler resource
aws_s3_object.approval_config resource
aws_scheduler_schedule_group.one_time_schedule_group resource
aws_sns_topic.dlq resource
aws_sns_topic_subscription.dlq resource
null_resource.attribute_sync_validation resource
random_string.random resource
aws_caller_identity.current data source
aws_iam_policy_document.attribute_syncer data source
aws_iam_policy_document.revoker data source
aws_iam_policy_document.slack_handler data source
aws_region.current data source
aws_ssoadmin_instances.all data source

Inputs

Name Description Type Default Required
allow_anyone_to_end_session_early Controls who can click the "End session early" button to revoke access before the scheduled expiration.
If false (default), only the requester and approvers listed in the matching statement can end the session.
If true, anyone in the Slack channel can end any session early.
bool false no
api_gateway_name The name of the API Gateway for SSO Elevator's access-requester Lambda string "sso-elevator-access-requster" no
api_gateway_throttling_burst_limit The maximum number of requests that API Gateway allows in a burst. number 5 no
api_gateway_throttling_rate_limit The maximum number of requests that API Gateway allows per second. number 1 no
approver_renotification_backoff_multiplier The multiplier applied to the wait time for each subsequent notification sent to the approver. Default is 2, which means the wait time will double for each attempt. number 2 no
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
attribute_sync_enabled Enable attribute-based group sync feature. When enabled, users will be automatically added to groups based on their Identity Store attributes. bool false no
attribute_sync_event_rule_name Name for the EventBridge rule that triggers the attribute syncer. string "sso-elevator-attribute-sync" no
attribute_sync_lambda_memory Memory allocation for attribute syncer Lambda (MB). Increase for large user/group sets. number 512 no
attribute_sync_lambda_timeout Timeout for attribute syncer Lambda (seconds). Increase for large user/group sets. number 300 no
attribute_sync_managed_groups List of group names to manage via attribute sync. Only these groups will be monitored and modified by the sync process. list(string) [] no
attribute_sync_manual_assignment_policy Policy for handling manual assignments (users in managed groups who don't match any rules): 'warn' only logs and notifies, 'remove' automatically removes them. string "remove" no
attribute_sync_rules Attribute mapping rules for group sync. Each rule specifies a group name and the attribute conditions that must be met for a user to be added to that group.
Example:
[
{
group_name = "Engineering"
attributes = {
department = "Engineering"
employeeType = "FullTime"
}
}
]
list(object({
group_name = string
attributes = map(string)
}))
[] no
attribute_sync_schedule Schedule expression for attribute sync (e.g., 'rate(1 hour)' or 'cron(0 * * * ? *)'). Determines how often the sync runs. string "rate(1 hour)" no
attribute_syncer_lambda_name Name for the attribute syncer Lambda function. string "attribute-syncer" no
aws_sns_topic_subscription_email value for the email address to subscribe to the SNS topic string "" no
cache_enabled Enable caching of AWS accounts and permission sets in S3. If set to false, caching is disabled but the S3 bucket will still be created for future config storage. bool true no
config value for the SSO Elevator config any [] no
config_bucket_kms_key_arn ARN of the KMS key to use for config S3 bucket encryption. If not provided, uses AES256 encryption. string null no
config_bucket_name Name of the S3 bucket for storing configuration and cache data (accounts, permission sets, and future config files) string "sso-elevator-config" no
create_api_gateway If true, module will create & configure API Gateway for the Lambda function bool true no
ecr_owner_account_id In what account is the ECR repository located. string "222341826240" no
ecr_repo_name The name of the ECR repository. string "aws-sso-elevator" no
ecr_repo_tag The tag of the image in the ECR repository. string "4.1.0" no
event_bridge_check_on_inconsistency_rule_name value for the event bridge check on inconsistency rule name string null no
event_bridge_scheduled_revocation_rule_name value for the event bridge scheduled revocation rule name string null no
event_brige_check_on_inconsistency_rule_name DEPRECATED: Use event_bridge_check_on_inconsistency_rule_name instead. This variable contains a typo and will be removed in a future version. string "sso-elevator-check-on-inconsistency" no
event_brige_scheduled_revocation_rule_name DEPRECATED: Use event_bridge_scheduled_revocation_rule_name instead. This variable contains a typo and will be removed in a future version. string "sso-elevator-scheduled-revocation" no
group_config value for the SSO Elevator group config any [] no
identity_store_id The Identity Store ID (e.g., "d-1234567890").
If not provided and sso_instance_arn is also not provided, it will be automatically discovered.

Providing this value is RECOMMENDED for API efficiency - it eliminates describe_sso_instance API calls
on every Lambda invocation. You can find this value in the AWS IAM Identity Center console or via:
aws sso-admin list-instances --query 'Instances[0].IdentityStoreId' --output text
string "" no
lambda_architecture The instruction set architecture for Lambda functions. Valid values are 'x86_64' or 'arm64'. Use 'arm64' for better price/performance on Graviton2. string "x86_64" no
lambda_memory_size Amount of memory in MB your Lambda Function can use at runtime. Valid value between 128 MB to 10,240 MB (10 GB), in 64 MB increments. number 256 no
lambda_timeout The amount of time your Lambda Function has to run in seconds. number 30 no
log_level value for the log level string "INFO" no
logs_retention_in_days The number of days you want to retain log events in the log group for both Lambda functions and API Gateway. number 365 no
max_permissions_duration_time Maximum duration (in hours) for permissions granted by Elevator. Max number - 48 hours.
Due to Slack's dropdown limit of 100 items, anything above 48 hours will cause issues when generating half-hour increments
and Elevator will not display more then 48 hours in the dropdown.
number 24 no
permission_duration_list_override An explicit list of duration values to appear in the drop-down menu users use to select how long to request permissions for.
Each entry in the list should be formatted as "hh:mm", e.g. "01:30" for an hour and a half. Note that while the number of minutes
must be between 0-59, the number of hours can be any number.
If this variable is set, the max_permission_duration_time is ignored.
list(string) [] no
posthog_api_key PostHog API key for analytics. Leave empty to disable analytics tracking. string "" no
posthog_host PostHog host URL for analytics. string "https://us.i.posthog.com" no
request_expiration_hours After how many hours should the request expire? If set to 0, the request will never expire. number 8 no
requester_lambda_name value for the requester lambda name string "access-requester" no
revoker_lambda_name value for the revoker lambda name string "access-revoker" no
revoker_post_update_to_slack Should revoker send a confirmation of the revocation to Slack? bool true no
s3_bucket_name_for_audit_entry The name of the S3 bucket that will be used by the module to store logs about every access request.
If s3_name_of_the_existing_bucket is not provided, the module will create a new bucket with this name.
string "sso-elevator-audit-entry" no
s3_bucket_partition_prefix The prefix for the S3 audit bucket object partitions.
Don't use slashes (/) in the prefix, as it will be added automatically, e.g. "logs" will be transformed to "logs/".
If you want to use the root of the bucket, leave this empty.
string "logs" no
s3_logging Map containing access bucket logging configuration.
If you are not providing s3_name_of_the_existing_bucket variable, then module will create bucket for you.
If the module is creating an audit bucket for you, then you must provide a logging configuration via this input variable, with at least the target_bucket key specified.
map(string) {} no
s3_mfa_delete Whether to enable MFA delete for the S3 bucket bool false no
s3_name_of_the_existing_bucket Name of an existing S3 bucket to use for storing SSO Elevator audit logs.
An audit log bucket is mandatory.
If you specify this variable, the module will use your existing bucket.
Otherwise, if you don't provide this variable, the module will create a new bucket named according to the "s3_bucket_name_for_audit_entry" variable.
If the module is creating an audit bucket for you, then you must provide a logging configuration via the s3_logging input variable, with at least the target_bucket key specified.
string "" no
s3_object_lock Enable object lock bool false no
s3_object_lock_configuration Object lock configuration any
{
"rule": {
"default_retention": {
"mode": "GOVERNANCE",
"years": 2
}
}
}
no
schedule_expression recovation schedule expression (will revoke all user-level assignments unknown to the Elevator) string "cron(0 23 * * ? *)" no
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
schedule_group_name value for the schedule group name string "sso-elevator-scheduled-revocation" no
schedule_role_name value for the schedule role name string "sso-elevator-event-bridge-role" no
secondary_fallback_email_domains Value example: ["@new.domain", "@second.domain"], every domain name should start with "@".
WARNING:
This feature is STRONGLY DISCOURAGED because it can introduce security risks and open up potential avenues for abuse.

SSO Elevator uses Slack email addresses to find users in AWS SSO. In some cases, the domain of a Slack user's email
(e.g., "john.doe@old.domain") differs from the domain defined in AWS SSO (e.g., "john.doe@new.domain"). By setting
these fallback domains, SSO Elevator will attempt to replace the original domain from Slack with each secondary domain
in order to locate a matching AWS SSO user.

Use Cases:
- This mechanism should only be used in rare or critical situations where you cannot align Slack and AWS SSO domains.

Use Case Example:
- Slack email: john.doe@old.domain
- AWS SSO email: john.doe@new.domain

Without fallback domains, SSO Elevator cannot find the SSO user due to the domain mismatch. By setting
secondary_fallback_email_domains = ["@new.domain"], SSO Elevator will swap out "@old.domain" for "@new.domain"
(and any other domain in the list) and attempt to locate "john.doe@new.domain" in AWS SSO.

Security Risks & Recommendations:
- If multiple SSO users share the same local-part (before the "@") across different domains, SSO Elevator may
grant permissions to the wrong user.
- Disable or remove entries in this variable as soon as you no longer need domain fallback functionality
to restore a more secure configuration.

IN SUMMARY:
Use "secondary_fallback_email_domains" ONLY if absolutely necessary. It is best practice to maintain
consistent, verified email domains in Slack and AWS SSO. Remove these fallback entries as soon as you
resolve the underlying domain mismatch to minimize security exposure.

Notes:
- SSO Elevator always prioritizes the primary domain from Slack (the Slack user's email) when searching for a user in AWS SSO.
- SSO Elevator adds a large warning message in Slack if it uses a secondary fallback domain to find a user in AWS SSO.
- The secondary domain feature works ONLY for the requester, approvers in the configuration must have the same email domain as in Slack.
list(string) [] no
send_dm_if_user_not_in_channel If the user is not in the SSO Elevator channel, Elevator will send them a direct message with the request status
(waiting for approval, declined, approved, etc.) and the result of the request.
Using this feature requires the following Slack app permissions: "channels:read", "groups:read", and "im:write".
Please ensure these permissions are enabled in the Slack app configuration.
bool true no
slack_bot_token value for the Slack bot token string n/a yes
slack_channel_id value for the Slack channel ID string n/a yes
slack_handler_provisioned_concurrent_executions Provisioned concurrent executions for the Slack handler Lambda. Set to a positive number to reduce cold starts. number -1 no
slack_signing_secret value for the Slack signing secret string n/a yes
sso_instance_arn value for the SSO instance ARN string "" no
tags A map of tags to assign to resources. map(string) {} no
use_pre_created_image If true, the image will be pulled from the ECR repository. If false, the image will be built using Docker from the source code. bool true no

Outputs

Name Description
attribute_sync_schedule_rule_arn The ARN of the EventBridge rule that triggers the attribute syncer.
attribute_syncer_lambda_arn The ARN of the attribute syncer Lambda function.
attribute_syncer_lambda_name The name of the attribute syncer Lambda function.
config_s3_bucket_arn The ARN of the S3 bucket for storing configuration and cache data.
config_s3_bucket_name The name of the S3 bucket for storing configuration and cache data.
requester_api_endpoint_url The full URL to invoke the API. Pass this URL into the Slack App manifest as the Request URL.
revoker_lambda_name The name of the revoker Lambda function.
schedule_group_name The name of the EventBridge Scheduler schedule group.
sso_elevator_bucket_id The name of the SSO elevator bucket.

More Info

About

Assign temporary AWS permissions to a user via Slack

Resources

License

Code of conduct

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Python 92.0%
  • HCL 7.6%
  • Other 0.4%