Custom Access Strategies
Define Access Strategies for services that Sym does not support out of the box.
Overview
In addition to native Access Strategies and AWS Lambda, Sym provides an interface that enables implementers to define fully custom Access Strategies.
Want to jump right in? Try the quickstart!
If you're ready to dive in, these resources have everything you need to start building:
Custom Strategy Framework
The Sym Strategy Framework provides the tools to:
- Define custom Strategy logic for
escalate
,deescalate
, and identity fetching/matching - Define user-facing
targets
to which the Strategy can be applied - Deploy the Strategy as a custom Flow.
Of course, as with any Sym Strategy, implementers can also define Workflow Handlers to customize, automate, and route their Flows.
The Custom logic
The bulk of the Custom Strategy is defined in the strategy.py
file that lives alongside your Flow definition and implementation.
Restrictions Apply
Your Custom Strategy will be executed inside of a RestrictedPython environment, and as a result certain methods might not be available (e.g.
all()
,next()
).In addition, only imports from the following modules are allowed:
sym.sdk
requests
json
datetime
from sym.sdk.strategies import AccessStrategy
from sym.sdk.integrations import slack
class CustomAccess(AccessStrategy):
def fetch_remote_identity(self, user):
return user.email
def escalate(self, target_id, event):
requester = self.get_requester_identity(event)
target_identifier = event.payload.fields["target"].settings["identifier"]
slack.send_message(slack.user(requester), f"Access to {target_identifier} granted!")
def deescalate(self, target_id, event):
requester = self.get_requester_identity(event)
target_identifier = event.payload.fields["target"].settings["identifier"]
slack.send_message(slack.user(requester), f"Access to {target_identifier} revoked!")
Declaring the Flow, Strategy, and Target definitions
Like any Sym Strategy, a Custom Strategy needs to be declared in Terraform.
The
get_identity
reducer is not used by Custom StrategiesWhile you can use the same
impl.py
file for all your flows, including flows that use Custom Strategies, Custom Strategies never call theget_identity
reducer. Instead, implement your custom identity discovery logic in thefetch_remote_identity()
method of your Custom Strategy.
# A custom Integration can be used to access secrets in your custom strategy implementation
# as well as manage identities.
resource "sym_integration" "custom" {
type = "custom"
name = local.flow_name
external_id = var.integration_identifier
settings = {
secret_ids_json = jsonencode([sym_secret.api_key.id])
}
}
# The targets that your Sym Strategy manages access to.
resource "sym_target" "targets" {
for_each = { for target in var.targets : target["identifier"] => target["label"] }
type = "custom"
name = "${local.flow_name}-${each.key}"
label = each.value
settings = {
identifier = each.key
}
}
# The Strategy your Flow uses to manage access.
resource "sym_strategy" "this" {
type = "custom"
name = local.flow_name
implementation = "${path.module}/strategy.py"
integration_id = sym_integration.custom.id
targets = [for target in var.targets : sym_target.targets[target["identifier"]].id]
}
# The Flow that grants users access to custom targets.
resource "sym_flow" "this" {
name = local.flow_name
label = "Custom Quickstart"
implementation = file("${path.module}/impl.py")
environment_id = var.sym_environment.id
vars = var.flow_vars
params {
strategy_id = sym_strategy.this.id
prompt_field {
name = "reason"
type = "string"
required = true
}
}
}
Deploying the Strategy
Finally, the full Strategy is deployed as a Flow.
module "custom_access_flow" {
source = "../modules/custom-access-flow"
flow_vars = var.flow_vars
secrets_settings = module.sym_runtime.secrets_settings
sym_environment = module.sym_runtime.prod_environment
targets = var.targets
}
Updated about 1 month ago