AWS Lambda Access Strategy
Sym's AWS Lambda Access Strategy gives you ultimate flexibility and safety when executing Lambdas in your own environment.
You can generate this!
You can automatically generate an AWS SSO Flow with
symflow generate aws-lambda
!Otherwise, follow the AWS Runtime Setup tutorial to set up your AWS dependencies.
Sym's AWS Lambda integration enables you to protect workflows and resources to which Sym doesn't directly integrate.
We'll call your function twice: when we escalate
a user after approval, and again on deescalate
. All of your SDK Reducers and Hooks still apply in the middle, giving you full flexibility to craft workflows around your own last-mile implementations.
Full Example
You can find the complete code for this example in our AWS Lambda Access Strategy Example.
Create a Lambda for Escalation and De-escalation
Before provisioning your flow, you will need a Lambda to invoke on escalate and de-escalate.
Input Payload
The payload supplied to your Lambda is very similar to that of the Reporting module. You can see a full schema here.
Lambda Response Format
Responses are required
If you don't include a formatted response from your Lambda, your Flow will succeed, but you will receive a warning message directing you to this guide.
The return from your Lambda must be formatted as a dict with two keys:
body: Dict[str, Any]
, a dict with one or more string keyserrors: List[str]
, a list of strings
For example:
{
"body": {
"message": "this is a custom message I'm going to DM someone!"
},
"errors": [] // send an empty array for no errors
}
Any errors in the response body will be displayed as bullets. For example:
def lambda_handler(event, context):
print("many magical things are happening here")
return {
"body": {
"message": "A message"
},
"errors": [
"Is this the real life?",
"Is this just fantasy?",
"Caught in a landslide",
"No escape from reality",
],
}
The above will result in the below error being sent to your Sym Errors channel:
Terraform your Lambda
We recommend managing your Lambda via Terraform with the terraform-aws-lambda module. Then, you will only need to provide a folder containing your Lambda handler function.
module "lambda_function" {
source = "terraform-aws-modules/lambda/aws"
version = "2.36.0"
function_name = "your_lambda"
description = "A Lambda to be invoked on escalate and de-escalate"
handler = "handler.lambda_handler"
runtime = "python3.8"
# The relative path to your lambda source code
source_path = "${path.module}/lambda_src"
}
Provision an AWS Lambda Strategy
Connect the Sym Runtime with your AWS Account
Follow the AWS Runtime Setup tutorial on the main AWS page to set up your runtime_connector
module.
Add a AWS Lambda Integration
Define the Lambda Connector
The AWS Lambda Access Strategy relies on a special module lambda-connector
. This module defines the AWS Lambda Resources that enable Sym to invoke a Lambda in your AWS Account.
lambda_arns
: A list of Lambdas you wish to allow the Sym Runtime to invoke
module "lambda_connector" {
source = "symopsio/lambda-connector/aws"
version = ">= 1.0.0"
environment = "main"
# Add ARN of the lambda you wish to invoke to this list.
lambda_arns = [module.lambda_function.lambda_function_arn]
runtime_role_arns = [module.runtime_connector.sym_runtime_connector_role.arn]
}
Define the Lambda Permission Context Integration
Define a sym_integration
resource with type = permission_context
. This tells Sym to assume the AWS IAM Role defined by the Lambda Connector module when invoking Lambdas, and will be referenced in the sym_strategy
resource later.
external_id
: Your AWS Account ID. Use theaccount_id
output frommodule.lambda-connector.settings
settings
: Thesettings
output frommodule.lambda-connector
resource "sym_integration" "lambda_context" {
type = "permission_context"
name = "lambda-context-main"
external_id = module.lambda_connector.settings.account_id
settings = module.lambda_connector.settings
}
Add an AWS Lambda Target
For an AWS Lambda Strategy, the sym_target
will be the Lambda you wish you invoke to handle your custom escalation and de-escalation.
arn
: A required setting, which must be set to the ARN of the Lambda to invoke on escalate and de-escalate.
resource "sym_target" "super_secret_button" {
type = "aws_lambda_function"
name = "super-secret-button"
label = "Super Secret Button"
settings = {
# For this example, we are using an ARN outputted by the module we used to terraform the lambda.
arn = module.lambda_function.lambda_function_arn
}
}
Add an AWS Lambda Access Strategy
Define a sym_strategy
resource with type = aws_lambda
and include the AWS Lambda Permission Context and AWS Lambda Access Targets you defined above.
resource "sym_strategy" "lambda" {
type = "aws_lambda"
name = "main-lambda-strategy"
integration_id = sym_integration.lambda_context.id
targets = [sym_target.super_secret_button.id]
}
Add the AWS Lambda Strategy to your Flow
In your sym_flow
resource, reference your AWS Lambda sym_strategy
as the strategy_id
in your Flow Parameters.
resource "sym_flow" "this" {
name = "secret-button"
label = "Secret Button Access"
# ... other Flow attributes not shown
params {
strategy_id = sym_strategy.lambda.id
# ... other Flow params not shown
}
}
Using Lambda responses in your impl.py
impl.py
Lambda responses can be retrieved in your Python implementation inside of a Hook that triggers after the Lambda is called:
after_escalate(event)
will be called after a user is escalated.after_deescalate(event)
will be called after a user is deescalated.
In both cases, your response output payload can be retrieved via get_step_output()
.
Best practices
The easiest way to work with your Lambda responses is to treat them like REST responses. Simply grab the payload, throw it in a local variable, and grab the keys off it as you would expect.
from sym.sdk.integrations import slack
from sym.sdk.templates import get_step_output
@hook
def after_escalate(event):
# Get your Lambda response body
escalate_output = get_step_output()
# Send a Slack message with the body from your output
slack.send_message(event.user, escalate_output["body"]["message"])
Lambda Templates
Our lambda-templates
repo provides a starting point for deploying a Lambda Function which can parse and process incoming payloads from Sym. In that repo, you'll find implementations in Python, Go, and Typescript, as well as a set of test payloads that you can use to test your implementation.
Updated 23 days ago