User Impersonation

Protect sensitive endpoints and admin dashboards with Sym's web integrations.

A common use case of the sym:approval template is to put a request-and-approval workflow around endpoints or dashboards that allow the user to exert sensitive privileges, such as impersonating users or viewing admin data. These tools often lack multi-factor authentication or any kind of governance, but are frequently used and can leave gaping holes in an organization's security posture. With Sym, you can wrap an unobtrusive approval workflow around your pages without slowing down the users you support!

Prerequisites

You'll have to install the symflow CLI and log in before beginning the process of setting up Sym. You'll also need to go through the steps of deploying the platform and setting up the runtime.

What to expect

We'll start with a guide on how to provision your Flow in Terraform, followed by an example of how to use the Sym SDK to customize your request routing logic. We'll also cover how to wrap a view in Django with Sym's decorator, though Sym supports many other web frameworks as well.

All the code

Through the following steps, we'll walk through all the code you have to write to set Sym up. As a preview, here are the three files you'll end up creating.

from django.views.decorators.http import require_http_methods
from sym.django import sym_init, require_approval
from .models import Account

sym_init(token=ENV['SYM_TOKEN'])

def build_sym_request_data(request):
  account_id = request.query_params["account_id"]
  account = Account.objects.get(id=account_id)
  
  user_is_assigned = request.user.id in account.managers
  
  return {
    "customer_id": account_id,
    "customer_plan": account.plan, 
    "is_assigned": user_is_assigned,
  }

@require_approval(
  flow="user_impersonation", 
  build_data=build_sym_request_data,
  message="You must obtain approval to impersonate this user.",
)
@require_http_methods(["GET", "POST"])
def impersonation(request):
  # User impersonation logic here
  ...
from sym import events
from sym.annotations import hook, reducer
from sym.integrations import slack, pagerduty

@hook
def on_request(req):
    # Automatically approve requests for free tier customers
    if req.fields["customer_plan"] == "free":
        return events.approval.approve()
      
@reducer
def get_approver(req):
    # If the user is assigned to this account, then they can self-approve.
    if req.fields["is_assigned"]:
        return slack.user(req.user)
    else: # Otherwise, send the approval to the on-call managers.
        on_call_mgrs = pagerduty.on_call(schedule="id_of_mgr_on_call")
        # This would cause each on-call manager to be DMed
        return [slack.user(x) for x in on_call_mgrs]
terraform {
  required_version = ">= 0.14"
  required_providers {
    sym = {
      source = "terraform.symops.com/symopsio/sym"
      version = "0.1"
    }
  }
}

provider "sym" {
  org = "healthy-health"
}

# A Flow that will receive API calls from Django,
# route for approval in Slack, 
# then save the approval state in Sym.
resource "sym_flow" "this" {
  name = "user_impersonation"
  label = "User Impersonation"
    
  template = "sym:approval:1.0"
  # We'll cover this file in the next section:
  implementation = "impl.py"

  params = {
    # The Sym middleware integration from Django will submit these values.
    # `customer_id` & `customer_plan` will be looked up programatically,
    # and the user will supply a `reason`.
    fields = [{
      name = "customer_id"
      type = "int"
      required = true
    }, {
      name = "customer_plan"
      type = "string"
      required = true
    }, {
      name = "reason"
      type = "string"
      required = true
    }]
  }
}

Did this page help you?