Sym solves painful access and approval problems with practical workflows-as-code.
Is your team experiencing:
Sym can help! This quickstart will help you launch a new access flow in under an hour. Your engineers will be able to safely and conveniently gain access to sensitive resources, all with the guardrails you need in place.
If you want to check out a demo, go here!
We're going to walk through setting up an access control workflow using Slack, AWS Lambda and Sym. By the end of this tutorial, you'll have the ability to wrap any resource that your Lambdas can access with a fully-configurable request-and-approval flow, using a declaratively provisioned Slack bot.
The complete code for this tutorial can be found at @symopsio/sym-lambda-adapter-quickstart
.
Users will interact with this Sym Flow
via Slack. Slack connects to the Sym platform, which executes a Flow
that uses the Integrations
we are wiring together in this tutorial.
This is what a request will look like.
Sym will send a request for approval to the appropriate users or channel based on your impl.py
.
Finally, upon approval, Sym invokes your AWS Lambda function and updates Slack.
To complete this tutorial, you should install Terraform, and make sure you have a working install of Python 3.
The environment includes everything you need to get a Lambda workflow up and running. Just configure a few variables in terraform.tfvars
and you're on your way!
Here's all that you'll need to do:
symflow
CLIThe Terraform configuration is set up to automatically build and package zips for a layer and function implementation whenever the requirements.txt
or Python files change.
You can iterate on your handler function locally by invoking your handler function directly. We've provided tools to help with local testing in the test
directory.
For local testing, the API URL and the API Key will be read from environment variables.
env.example
to the handler
directory, modify the API_KEY
and API_URL
values, and source
it:$ cp test/env.example .env
# modify API_URL and API_KEY
$ source .env
pip install -r requirements.txt
cat test/escalate.json | python handler.py
to invoke your API. application/x-www-form-urlencoded
data. The body of the request is constructed in the update_user
method in handler.py
.You'll need to work with the Sym team to get your organization set up with access to the Sym platform. Once you're onboarded, continue from here.
symflow
CLIThe symflow
CLI is what you use to interact with Sym's control plane.
$ brew install symopsio/tap/symflow
==> Tapping symopsio/tap
Cloning into '/opt/homebrew/Library/Taps/symopsio/homebrew-tap'...
remote: Enumerating objects: 1148, done.
remote: Counting objects: 100% (285/285), done.
remote: Compressing objects: 100% (222/222), done.
remote: Total 1148 (delta 134), reused 156 (delta 59), pack-reused 863
Receiving objects: 100% (1148/1148), 324.27 KiB | 6.36 MiB/s, done.
Resolving deltas: 100% (530/530), done.
Tapped 14 formulae (43 files, 582.7KB).
==> Downloading https://github.com/symopsio/sym-flow-cli-releases/releases/download/v1.3.7/sym-flow-cli-darwin-x64.tar.gz
######################################################################## 100.0%
==> Installing symflow from symopsio/tap
🍺 /opt/homebrew/Cellar/symflow/1.3.7: 10,351 files, 198MB, built in 33 second
We'll have to login before we can do anything else. Sym also supports SSO, if your organization has set it up.
$ symflow login
Sym Org: healthy-health
Username: sym-implementer@healthy-health.co
Password: ************
MFA Token: ******
Success! Welcome, Sym Implementer. 🤓
You simply have to take the slug
given to you by the Sym team, and set it in environments/main/terraform.tfvars
.
# environments/main/terraform.tfvars
sym_org_slug = "healthy-health"
Now that you've got symflow
installed, you need to install Sym's Slack app into your workspace.
The easiest place to find this is in the URL you see when you run Slack in your web browser. It will start with a T
, and look something like TABC123
.
This also goes in environments/main/terraform.tfvars
.
# environments/main/terraform.tfvars
slack_workspace_id = "TABC123"
symflow
has a convenient way to provision an instance of Sym's Slack app. This command will generate an install link that you can either use directly, or forward on to your Workspace Administrator.
$ symflow services create --service-type slack --external-id T123ABC
Successfully set up service type slack with external ID TABC123!
Generated an installation link for the Sym Slack app:
https://static.symops.com/slack/install?token=xxx
Please send this URL to an administrator who has permission to install the app. Or, if that's you, we can open it now.
Would you like to open the Slack installation URL in a browser window? [Y/n]:
Once Slack is set up, try launching the Sym app with /sym
in Slack.
You should see a welcome modal like this one, since we haven't set up a Flow
yet:
This Flow
is set up to route access requests to the #sym-requests
channel. You can change this channel in—wait for it—terraform.tfvars
.
# environments/main/terraform.tfvars
flow_vars = {
request_channel = "#sym-requests"
}
Sym will also send any errors that happen during a Run
(due to external failures or config issues) to a configurable error channel, which defaults to #sym-errors
.
# environments/main/terraform.tfvars
error_channel = "#sym-errors"
Now that Slack is set up, let's provision your Flow!
# environments/main/terraform.tfvars
api_url = "https://pastebin.com/api/api_post.php"
$ export AWS_PROFILE=my-profile
$ cd environments/main
$ terraform init
$ terraform apply
...
Plan: 25 to add, 0 to change, 0 to destroy.
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
Apply complete! Resources: 25 added, 0 changed, 0 destroyed.
Positive : By the way, if you plan to provision your flows from a CI pipeline, we've got you covered.
You should be able to make a request now with /sym req
. Once approved, the adapter-flow
example function should be invoked in your AWS account, and you'll see log output like:
START RequestId: dcb17aed-df38-4aba-b72f-4000fc63c871 Version: $LATEST
Got event:
sym_handler/handler.py:11 handle
log: SymLogEntry(
meta=LogEntryMeta(
schema_version=3,
),
run=LogEntryRun(
srn=SRN(org=my-org, model=run, slug=lambda_access, version=2.0.0, identifier=7cd568e8-d42a-4183-9007-d2b654dfce75),
parent=(
SRN(org=my-org, model=run, slug=flow_selection, version=1.0.0,
identifier=d394bcb6-3d98-4f32-a140-d79720faa81c)
),
flow=SRN(org=my-org, model=flow, slug=lambda_access, version=2.0.0),
),
event=LogEntryEvent(
srn=SRN(org=my-org, model=event, slug=approval, version=1.0.0),
type='approve',
template=SRN(org=my-org, model=template, slug=approval, version=1.0.0),
timestamp=datetime.datetime(2022, 2, 15, 14, 33, 8, 769366, tzinfo=datetime.timezone.utc),
),
...
Once you've got your Flow talking to the example AWS Lambda implementation, its time to customize the Lambda to do something interesting for your team.
Sym invokes your Lambda function with a SymLogEntry
payload. Read more about the properties of SymLogEntry
in our docs, or head over to the lambda-templates
repo to see example Lambdas in action.
You can add optional configuration in terraform.tfvars
to the lambda_vars
variable. Each key/value pair in lambda_vars
will be configured as an environment variable that your Lambda implementation can read. You can use the config
helper module to access these variables.
from config import get_config
config = get_config()
my_var = config.my_key
Your Lambda is set up to read secrets from AWS Parameter Store. If you create a secret prefixed with /symops.com/
then your Lambda already has permissions to read the secret. You can use the get_ssm_parameter
helper method in the config
module to read these secrets.
api_key = get_ssm_parameter("/symops.com/sym-lambda-function-name/API_KEY")
Now that you've configured your AWS Lambda implementation, its time to validate that your integration works end-to-end. Double check that your function is properly responding to escalation and de-escalation events and handling error cases!
Here are some next steps to consider:
LogDestinations
.Flow
to require that users be members of a safelist to approve access. flow_vars.approvers
with the safelist of approvers in terraform.tfvars
.hook
annotation on the on_approve
method in impl.py
. This is just one example of what you can do with hooks in the SDK!symflow
CLI to configure user mappings when required.Flow
logic. Maybe change things to allow self-approval only for on-call users?Flow
!