Multiple Access Targets

Overview

Multiple Access Targets enable your users to select one or more Targets in a single request. If multiple Targets are requested and access is granted, the requesting user will be given access to all Targets simultaneously.

Multiple Access Targets are intended to be used with a combination of Dynamic Access Targets, which enables the Target prompt field to be populated on the fly, and can be enhanced with Prefetch Typeahead, which can pre-populate the dynamic field with values fetched on the fly.

🚧

Multiple Access Targets limitations

The table below displays which strategies support multi-selectable dynamic targets, and the name of the attribute that can be made into a multi-selectable dynamic target for each strategy.

StrategySupported Dynamic Target Setting
Oktagroup_id
AWS SSOaccount_id for aws_sso_permission_set Sym Targets
group_id for aws_sso_group Sym Targets
AWS IAMiam_group

Implementation

Add the setting to Prompt Fields

For a Target's setting to be populated dynamically, you will need to define it as a Prompt Field. The name of the Prompt Field must match the Key of the setting. For example, if to allow users to input an Okta group ID, the Prompt Field will be configured with name = group_id. To make the target also multi-selectable, the Prompt Field should be configured with a list type (i.e type = str_list).

In this example, we will be using an Okta Access Strategy. The goal is to request access to multiple Okta groups at the same time, and granting access to them with one approval.

resource "sym_flow" "this" {
  name  = "okta-2"
  label = "Okta Group Request"

  implementation = file("${path.module}/impl.py")
  environment_id = sym_environment.this.id

  params {
    strategy_id = sym_strategy.okta.id

    prompt_field {
      name     = "reason"
      label    = "Why do you need access?"
      type     = "string"
      required = true
    }

    prompt_field {
      name           = "duration"
      type           = "duration"
      allowed_values = ["30m", "1h"]
      required       = true
    }

    prompt_field {
      name           = "group_id"
      label          = "Group ID"
    	# type = str_list makes this field multi-selectable in the Slack interface
      type           = "str_list"
      # Note that you can alternatively supply the allowed_values attribute here instead of
      # using a prefetch reducer
      prefetch 			 = true  
      required       = true
    }
  }
}

To supply the options for group_id at request time, implement your prefetch reducer. Add the following code to your impl.py.

from sym.sdk.annotations import prefetch
from sym.sdk.field_option import FieldOption

@prefetch(field_name="group_id")
def get_group_id_options(event):
    return [
        FieldOption(value="00x1234", label="Read Access"),
        FieldOption(value="00x4567", label="Write Access"),
        FieldOption(value="0x12121", label="PowerUser Access")
    ]

After applying this, the new "Group ID" field will appear in the Slack request modal, and will allow the user to select more than one value at a time from the FieldOptions supplied by get_group_id_options. However, the Slack input is still not bound to the group_id field that exists in the Okta Target.

In the next step, we will bind it to the actual Okta Target setting group_id.

Create a Dynamic Target

For a Target to have Dynamic Settings, it needs to have a special attribute field_bindings. This attribute contains a list of settings that will be inputted by the user in the Slack Request modal. The setting key must match the setting key being replaced and the Prompt Field name.

In this example, the setting being dynamically populated is the group_id setting of an okta_group target.

resource "sym_target" "okta_s3_access" {
  type  = "okta_group"
  name  = "main-group-access"
  label = "Group Access"
	
  # This is binding the group_id form input to the group_id field in the target
  field_bindings = ["group_id"]
	
  # This is not needed anymore because it is provided by the field_bindings!
  # settings = {
	#	group_id = "00x1234"
  # }
}

The field_bindings will allow Sym to interpret the following configuration:

resource "sym_target" "okta_s3_access" {
	...
  field_bindings = ["group_id"]
}

So that it behaves like this:

resource "sym_target" "okta_s3_access" {
	...
  settings = {
    group_id = # The value provided by the user for `group_id`. In this case, a list of strings. 
  }
}

Now, when a user makes a request via Slack, the Group ID prompt field will be multi-selectable:

After the request is submitted, the message will have the chosen groups associated with the request.

Once this request is approved, the user will be escalated to both Okta groups!