Build a Pritunl Slack Slash Commands with a Serverless Backend
Introduction
For self-service automation, Slack is one of the leading platforms that it can provide. As DevOps, which also considers company administrators, we ensure team members, such as Developers or QA, are presented with their technical needs without always relying on us.
In this post, we will build and deploy a Slack Slash Command for Pritunl Enterprise VPN users so they can generate their VPN Profile and Keys to access the organization’s resources.
Quick Demo
Figure 1: Pritunl Slack Slash Commands Application
Slack App Setup
Create a new Slack application
Go to Slack API ->
Your Apps ->
Create New App.
Create an app Steps
From Create an app pop-up window ->
choose From an app manifest.
Step 1: Pick a workspace to develop your app
Pick a Workspace to develop your app in. Then proceed to next step.
Step 2: Enter app manifest below
The App manifest contains basic info, scopes, settings, and features.
Choose the YAML option, then copy and paste the code provided for you.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
display_information:
name: Pritunl
description: Pritunl
background_color: "#737373"
features:
bot_user:
display_name: Pritunl
always_online: false
slash_commands:
- command: /pritunl
description: Pritunl
should_escape: false
## Replace the URL with the actual endpoint later after Serverless backend deployment.
url: https://url-id.lambda-url.us-east-1.on.aws/
oauth_config:
scopes:
bot:
- commands
- users:read
- users:read.email
settings:
org_deploy_enabled: false
socket_mode_enabled: false
token_rotation_enabled: false
Once fill-in and without syntax or definition errors, proceed to next step.
Step 3: Review summary & create your app
Based on the YAML manifest from our previous step, inspect the OAuth
and Features
that suit our requirements, and finalize the app creation steps by clicking the Create button.
Improve App Visual Identity (Optional)
For our application to have a unique visual identity from the rest of our apps, we can change the app icon.
From the Pritunl app, go to ->
Settings ->
Basic Information ->
App Credentials ->
Display Information.
Download the Pritunl Icon and, upload it to the App icon & Preview
Prepare the Slack Credentials
We only need the Signing Secret
and Bot Token
. Then steps on how to obtain these.
Getting the Signing Secret
From the Pritunl app, go to ->
Settings ->
Basic Information ->
App Credentials.
Then, click the Show button in the Signing Secret
field to suppress the information and copy it for our Serverless backend deployment.
Getting the Bot Token
From the Pritunl app, go to ->
Settings ->
Basic Information ->
Install App.
Then on the Install App to Your Team page, click the Install to Workspace.
Review the app requesting permission to access our workspace, then click Allow.
Once installed in our workspace, the field Bot User OAuth Token
shows this will be our Bot Token
, which we copy for our Serverless backend deployment.
Deploy the Serverless Backend
Prepare the Pritunl Credentials
Before proceeding to Serverless backend deployment, also prepare the Pritunl credentials.
From the Pritunl Dashboard (Base URL: https://vpn.domain.tld/), go to ->
Administrators ->
Select an Administrator ->
then tick the Enable Token Authentication.
Copy the Pritunl API Token and API Secret.
Tooling Requirements
Install the AWS SAM CLI
Make sure you have the latest AWS SAM CLI installed in your system.
Serverless Backend Deployment
We will use the GitHub repository Pritunl Slack App Slash Commands application as our backend for the Slack application.
Deploy to AWS Lambda
Figure 2: Pritunl Slack Slash Commands Serverless Backend Deployment
Clone the Serverless Backend
1
2
git clone https://github.com/nathanielvarona/pritunl-slack-app.git
cd pritunl-slack-app
Deploy using AWS SAM
Make sure you have AWS SAM CLI installed.
Load the Credentials as Environment Variables
1
2
3
4
5
export PRITUNL_BASE_URL="https://vpn.domain.tld/"
export PRITUNL_API_SECRET="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
export PRITUNL_API_TOKEN="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
export SLACK_SIGNING_SECRET="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
export SLACK_BOT_TOKEN="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
Build the Serverless Application
The flag
--use-container
only works if Docker is installed. This method prevents failing builds and packaging issues and promotes the highest runtime compatibility on the serverless environment once deployed.
1
sam build --use-container --no-cached
Show Stdout
Starting Build inside a container
Building codeuri: .../pritunl-slack-app/pritunl_slack_app/function runtime: python3.10 metadata: {} architecture: x86_64 functions: PritunlSlackFunction
Fetching public.ecr.aws/sam/build-python3.10:latest-x86_64 Docker container image......
Mounting .../pritunl-slack-app/pritunl_slack_app/function as /tmp/samcli/source:ro,delegated, inside runtime container
Running PythonPipBuilder:ResolveDependencies
Running PythonPipBuilder:CopySource
Build Succeeded
Built Artifacts : .aws-sam/build
Built Template : .aws-sam/build/template.yaml
Commands you can use next
=========================
[*] Validate SAM template: sam validate
[*] Invoke Function: sam local invoke
[*] Test Function in the Cloud: sam sync --stack-name --watch
[*] Deploy: sam deploy --guided
Lets deploy the application
The flag
--no-confirm-changeset
will automatically deploy the application without reviews.
1
2
3
4
5
6
sam deploy --no-confirm-changeset --parameter-overrides "\
PritunlBaseUrl=${PRITUNL_BASE_URL} \
PritunlApiSecret=${PRITUNL_API_SECRET} \
PritunlApiToken=${PRITUNL_API_TOKEN} \
SlackSigningSecret=${SLACK_SIGNING_SECRET} \
SlackBotToken=${SLACK_BOT_TOKEN}"
Show Stdout
Managed S3 bucket: aws-sam-cli-managed-default-samclisourcebucket-XXXXXXXXXXXXX
A different default S3 bucket can be set in samconfig.toml
Or by specifying --s3-bucket explicitly.
Uploading to pritunl-slack-app/285144b7022df545f09fb472228be5a9 1073 / 1073 (100.00%)
Uploading to pritunl-slack-app/76f170eb0196cbb12a272dfde42894c7 899 / 899 (100.00%)
Uploading to pritunl-slack-app/1ba998885207ab33f89be0e16954258a 1104939 / 1104939 (100.00%)
Deploying with following values
===============================
Stack name : pritunl-slack-app
Region : us-east-1
Confirm changeset : False
Disable rollback : False
Deployment s3 bucket : aws-sam-cli-managed-default-samclisourcebucket-XXXXXXXXXXXXX
Capabilities : ["CAPABILITY_IAM"]
Parameter overrides : {"PritunlBaseUrl": "*****", "PritunlApiSecret": "*****", "PritunlApiToken": "*****", "SlackSigningSecret": "*****", "SlackBotToken": "*****"}
Signing Profiles : {}
Initiating deployment
=====================
Uploading to pritunl-slack-app/c1d1651005d8166da9b4e6fd66f52f6b.template 5546 / 5546 (100.00%)
Waiting for changeset to be created..
CloudFormation stack changeset
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Operation LogicalResourceId ResourceType Replacement
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ Add AWSPritunlBaseUrl AWS::SecretsManager::Secret N/A
+ Add AWSSecretPritunlApiSecret AWS::SecretsManager::Secret N/A
+ Add AWSSecretPritunlApiToken AWS::SecretsManager::Secret N/A
+ Add AWSSecretSlackBotToken AWS::SecretsManager::Secret N/A
+ Add AWSSecretSlackSigningSecret AWS::SecretsManager::Secret N/A
+ Add PritunlSlackFunctionRole AWS::IAM::Role N/A
+ Add PritunlSlackFunctionUrl AWS::Lambda::Url N/A
+ Add PritunlSlackFunction AWS::Lambda::Function N/A
+ Add PritunlSlackUrlFunctionPermissions AWS::Lambda::Permission N/A
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Changeset created successfully. arn:aws:cloudformation:us-east-1:############:changeSet/samcli-deploy1682663457/a848f39c-418b-47d9-8227-f6aa79ae2fa7
2023-04-28 14:31:07 - Waiting for stack create/update to complete
CloudFormation events from stack operations (refresh every 5.0 seconds)
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ResourceStatus ResourceType LogicalResourceId ResourceStatusReason
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
CREATE_IN_PROGRESS AWS::CloudFormation::Stack pritunl-slack-app User Initiated
CREATE_IN_PROGRESS AWS::SecretsManager::Secret AWSSecretSlackBotToken -
CREATE_IN_PROGRESS AWS::SecretsManager::Secret AWSSecretSlackSigningSecret -
CREATE_IN_PROGRESS AWS::SecretsManager::Secret AWSPritunlBaseUrl -
CREATE_IN_PROGRESS AWS::SecretsManager::Secret AWSSecretPritunlApiToken -
CREATE_IN_PROGRESS AWS::SecretsManager::Secret AWSSecretPritunlApiSecret -
CREATE_IN_PROGRESS AWS::SecretsManager::Secret AWSSecretSlackSigningSecret Resource creation Initiated
CREATE_IN_PROGRESS AWS::SecretsManager::Secret AWSSecretSlackBotToken Resource creation Initiated
CREATE_COMPLETE AWS::SecretsManager::Secret AWSSecretSlackSigningSecret -
CREATE_IN_PROGRESS AWS::SecretsManager::Secret AWSPritunlBaseUrl Resource creation Initiated
CREATE_IN_PROGRESS AWS::SecretsManager::Secret AWSSecretPritunlApiSecret Resource creation Initiated
CREATE_COMPLETE AWS::SecretsManager::Secret AWSSecretSlackBotToken -
CREATE_IN_PROGRESS AWS::SecretsManager::Secret AWSSecretPritunlApiToken Resource creation Initiated
CREATE_COMPLETE AWS::SecretsManager::Secret AWSSecretPritunlApiSecret -
CREATE_COMPLETE AWS::SecretsManager::Secret AWSPritunlBaseUrl -
CREATE_COMPLETE AWS::SecretsManager::Secret AWSSecretPritunlApiToken -
CREATE_IN_PROGRESS AWS::IAM::Role PritunlSlackFunctionRole -
CREATE_IN_PROGRESS AWS::IAM::Role PritunlSlackFunctionRole Resource creation Initiated
CREATE_COMPLETE AWS::IAM::Role PritunlSlackFunctionRole -
CREATE_IN_PROGRESS AWS::Lambda::Function PritunlSlackFunction -
CREATE_IN_PROGRESS AWS::Lambda::Function PritunlSlackFunction Resource creation Initiated
CREATE_COMPLETE AWS::Lambda::Function PritunlSlackFunction -
CREATE_IN_PROGRESS AWS::Lambda::Permission PritunlSlackUrlFunctionPermissions -
CREATE_IN_PROGRESS AWS::Lambda::Url PritunlSlackFunctionUrl -
CREATE_IN_PROGRESS AWS::Lambda::Permission PritunlSlackUrlFunctionPermissions Resource creation Initiated
CREATE_IN_PROGRESS AWS::Lambda::Url PritunlSlackFunctionUrl Resource creation Initiated
CREATE_COMPLETE AWS::Lambda::Url PritunlSlackFunctionUrl -
CREATE_COMPLETE AWS::Lambda::Permission PritunlSlackUrlFunctionPermissions -
CREATE_COMPLETE AWS::CloudFormation::Stack pritunl-slack-app -
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
CloudFormation outputs from deployed stack
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Outputs
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Key PritunlSlackFunction
Description Pritunl Slack App Lambda Function ARN
Value arn:aws:lambda:us-east-1:############:function:pritunl-slack-app-PritunlSlackFunction-hae24jz29SIN
Key PritunlSlackFunctionUrl
Description Pritunl Slack App Lambda Function URL
Value https://5lxvqp66eussnx4egwg5hz7dme0vbend.lambda-url.us-east-1.on.aws/
Key PritunlSlackFunctionIamRole
Description Implicit IAM Role created for Pritunl Slack App function
Value arn:aws:iam::############:role/pritunl-slack-app-PritunlSlackFunctionRole-XGLNKCQZS3H5
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Successfully created/updated stack - pritunl-slack-app in us-east-1
Modify our Slack Slash Commands configuration.
Copy the value of PritunlSlackFunctionUrl
from our sam deploy
outputs, such as the URL https://5lxvqp66eussnx4egwg5hz7dme0vbend.lambda-url.us-east-1.on.aws/
. Then modify our Slack Slash Commands Manifest configuration.
From the Pritunl app, go to ->
Features ->
App Manifest ->
YAML.
1
2
3
features:
slash_commands:
- url: https://5lxvqp66eussnx4egwg5hz7dme0vbend.lambda-url.us-east-1.on.aws/
Modify and Save Changes.
And we are done! We now have a working Pritunl Slack Application, as shown in the Quick Demo.
Other Methods of Deployment
Lambda Functions Using Docker Image as a Package Type
Only requires few changes for our SAM template.yaml
to work with Docker Image
Patch the SAM Template
Apply the patch file template.yaml.docker-image.patch for our template.yaml
using git.
1
git apply ./template.yaml.docker-image.patch
Build using SAM with extra Parameters
Docker requires extra build arguments to pass the AWS Credentials to download the AWS Parameter and Secrets Lambda extension at the build stage.
1
2
3
sam build --use-container --no-cached --parameter-overrides "\
AwsAccessKeyId=${AWS_ACCESS_KEY_ID} \
AwsSecretAccessKey=${AWS_SECRET_ACCESS_KEY}"
Then Deploy
The same way as how the Zip Package Type deploys.
1
2
3
4
5
6
sam deploy --no-confirm-changeset --parameter-overrides "\
PritunlBaseUrl=${PRITUNL_BASE_URL} \
PritunlApiSecret=${PRITUNL_API_SECRET} \
PritunlApiToken=${PRITUNL_API_TOKEN} \
SlackSigningSecret=${SLACK_SIGNING_SECRET} \
SlackBotToken=${SLACK_BOT_TOKEN}"
Kubernetes Cluster with Helm Package Manager
If you are in Kubernetes Cluster and highly reliant on Helm Package Manager, please consider checking the project I also created, the Pritunl Slack App Helm Chart.