AWS IAM Identity Center (SSO) Access Strategy

Use Sym to seamlessly shift users in and out of AWS SSO roles.

πŸ‘

You can generate this!

You can automatically generate an AWS SSO Flow with symflow generate --type aws-sso!

Sym's AWS SSO Strategy uses a dedicated IAM role to assign and remove users from AWS SSO Permission Sets in a given AWS Account.

Connect the Sym Runtime with your AWS Account

Follow the Connect the Sym Runtime with your AWS Account tutorial on the main AWS page to set up your Runtime Connector module and Runtime Permission Context.

Add a AWS SSO Integration

Define the SSO Connector

The AWS SSO Access Strategy relies on a special module sso-connector. This module defines the AWS IAM Resources that enable Sym to manage SSO Permission Sets in your AWS Account.

provider "aws" {
  alias  = "sso"
  region = "us-east-1"

  # Change this profile name to a valid AWS profile for the AWS account where
  # your AWS SSO instance lives.
  profile = "sso"
}

# Get the AWS Account ID for the SSO profile.
data "aws_caller_identity" "sso" {
  provider = aws.sso
}

module "sso_connector" {
  source  = "symopsio/sso-connector/aws"
  version = ">= 1.0.0"

  # Provision the SSO connector in the AWS account where your AWS
  # SSO instance lives.
  providers = {
    aws = aws.sso
  }

  environment       = local.environment_name
  runtime_role_arns = [aws_iam_role.sym_runtime_connector_role.arn]
}

Define the AWS SSO Permission Context Integration

Define a sym_integration resource with type = permission_context. This tells Sym to assume the AWS IAM Role defined by the SSO Connector module when managing your SSO Permission Sets, and will be referenced in the sym_strategy resource later.

  • external_id: The instance_arn output from module.sso_connector.settings
  • settings: The settings output from module.sso_connector
resource "sym_integration" "sso_context" {
  type = "permission_context"
  name = "sso-context-main"

  external_id = module.sso_connector.settings.instance_arn
  settings    = module.sso_connector.settings
}

Allow the Sym Runtime to Assume Roles in your SSO Account

The sso-connector module will create an AWS IAM Role in your SSO Account that has the permissions to create and remove account assignments. You will need to grant the Sym Runtime permissions to assume this role. In runtime.tf, add the following IAM Policy and IAM Policy attachment.

resource "aws_iam_policy" "sso_assume_roles" {
  name = "${local.role_name}_SSOAssumeRoles"
  path = "/sym/"

  description = "This policy allows the Sym Runtime to assume roles in the /sym/ path in your AWS SSO account."
  policy = jsonencode({
    Statement = [{
      Action   = "sts:AssumeRole"
      Effect   = "Allow"
      Resource = ["arn:aws:iam::${data.aws_caller_identity.sso.account_id}:role/sym/*"]
    }]
    Version = "2012-10-17"
  })
}

resource "aws_iam_role_policy_attachment" "attach_assume_roles_sso" {
  policy_arn = aws_iam_policy.sso_assume_roles.arn
  role       = aws_iam_role.sym_runtime_connector_role.name
}

Add AWS SSO Access Targets

Define sym_target resources with type = aws_sso_permission_set for all of the AWS SSO Permission Sets that you wish to manage.

  • account_id: The AWS Account ID for the AWS SSO Permission Set
  • permission_set_arn: The ARN of the AWS SSO Permission Set.
resource "sym_target" "aws_sso" {
  type  = "aws_sso_permission_set"
  name  = "aws-sso-target-main"
  label = "AWS SSO Test Target"

  settings = {
    account_id = var.aws_sso_account_id
    permission_set_arn = aws_ssoadmin_permission_set.this.arn
  }
}

Add an AWS SSO Access Strategy

Define a sym_strategy resource with type = aws_sso and include the AWS SSO Permission Context and AWS SSO Access Targets you defined above.

  • instance_arn = The instance_arn output from module.sso_connector.settings
resource "sym_strategy" "aws_sso" {
  type           = "aws_sso"
  name           = "aws-sso-strategy-main"

  integration_id = sym_integration.sso_context.id
  targets        = [sym_target.aws_sso.id]

  settings = {
    instance_arn = module.sso_connector.settings.instance_arn
  }
}

Add the AWS SSO Strategy to your Flow

resource "sym_flow" "this" {
  name  = "sso-access-main"
  label = "AWS SSO Access"

  # ... other Flow attributes not shown

  params {
    strategy_id = sym_strategy.aws_sso.id

    # ... other Flow params not shown
  }
}

Full Example

You can find the complete code for this example in our AWS IAM Identity Center (SSO) Strategy Example.

🚧

Consider your session lengths

Sym access will provide your users with the keys to access escalated permissions, but AWS still governs the bounding sessions. This means:

  • If your Sym access is shorter than your default session length, users who access an escalated role will retain that role until their session times out.
  • Conversely, if your Sym access is longer than your default session length, users may be logged out and have to re-authenticate.

Advanced Concepts

Supply the AWS Account ID Dynamically

If you have many AWS Account IDs and don't want to create a Permission Set/Account ID combination for each one, you can use Dynamic Targets!

Add an Account ID Prompt Field

In your sym_flow configuration, add a new prompt field for account_id. This will add a text field "Account ID" to the Slack Request Modal.

Note, this prompt field must have name = "account_id", because we are using this prompt field to populate the required account_id setting of the AWS SSO Access Target.

resource "sym_flow" "this" {
  name  = "aws_sso_access"
  label = "AWS SSO Access"

  # ... other Flow attributes not shown

  params {
    strategy_id = sym_strategy.this.id

    prompt_field {
      name     = "account_id"
      label    = "Account ID"
      type     = "string"
      required = true
    }
  
    # ... other prompt_fields and Flow params not shown
  }
}

Define a Dynamic Target

Define a target for each AWS SSO Permission Set, but with a special attribute called field_bindings. This attribute indicates that the account_id setting will be populated dynamically by the requester.

The field binding must be account_id, because this is the required setting that is being dynamically populated.

resource "sym_target" "permission-set" {
  type  = "aws_sso_permission_set"

  name  = "permission-set-name"
  label = "Permission Set Name"

  # A special attribute that indicates the `account_id` setting is dynamic
  field_bindings = ["account_id"]
  
  settings = {
    permission_set_arn = "arn:aws:sso:::permissionSet/ssoins-aaaaaaaaaaaaaaaa/ps-aaaaaaaaaaaaaaaa"
  }
}

With these changes, your requests should now have a text input allowing requesters to specify to which AWS Account ID they wish to be escalated.