Skip to content

A little Slack CLI function to provide a groovy πŸ’… experience for reviewing infrastructure plans

Notifications You must be signed in to change notification settings

langwatch/terrafied

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

32 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ‘» Terrafied 🚨

a slack app that turns your terraform plans into a proper approval workflow. πŸ”” shaaame πŸ””

Slack notification showing a Terraform review request with change summary and action buttons
Review request lands in your channel


Slack notification showing a Terraform review request with change summary and action buttons
Review has been approved, and an apply action has been triggered
Approval modal showing detailed Terraform plan with resource changes and approve/reject buttons
Full plan review with one-click approval

when terraform runs and detects a change in the plan, this app:

  1. just found out the plans changed again
  2. posts a message to the #prod-infra-reviews channel
  3. lets you approve/reject, publicly, proudly
  4. stores the decision so you can pretend you actually reviewed it later

low risk, chill weekends

  • 🟒 low risk: "oh look, you're adding a tag. how brave."
  • 🟑 medium risk: "you're changing some stuff. i'm watching you."
  • ⚠️ high risk: "you're touching iam or security groups. i hope you know what you're doing."
  • πŸ”΄ critical risk: "love that for you"

architecture

sequenceDiagram
    participant CI as CI/CD Pipeline
    participant Webhook as Webhook
    participant Slack as Slack App
    participant User as Human Reviewer
    participant Datastore as Slack Datastore
    participant GitHub as GitHub API
    
    CI->>CI: Run Terraform Plan
    alt Plan has changes
        CI->>Webhook: POST Terraform plan data
        Webhook->>Slack: Trigger approval workflow
        Slack->>Datastore: Store review data
        Slack->>User: Post message with buttons
        User->>Slack: Click "Review & decide"
        Slack->>User: Open review modal
        User->>Slack: Approve/Reject in modal
        alt Approve
            Slack->>GitHub: POST repository_dispatch
            GitHub->>CI: Trigger workflow (approve)
            CI->>CI: Apply changes
            Slack->>User: Update: βœ… Approved
        else Reject
            Slack->>GitHub: POST repository_dispatch
            GitHub->>CI: Trigger workflow (reject)
            CI->>CI: Cancel pipeline
            Slack->>User: Update: ❌ Rejected
        end
    else No changes
        CI->>CI: Continue pipeline
    end
Loading

built with:

  • deno slack cli
  • slack ui components

getting going

prerequisites

  • a slack workspace (duh)
  • a github repository with terraform (also duh)
  • a ci/cd pipeline that can make http requests (github actions, gitlab ci, etc.)
  • the ability to read documentation (you're doing great so far!)

installation

more below.

  • clone this repo (you already did this, good job!) β€’ install the slack cli if you haven't:
brew install --cask slack-cli
  • link your app:
slack login
  • run the app:
slack run
  • get your webhook url from the slack app settings

configuration

add this to your ci/cd pipeline (github actions example):

- name: Notify Slack about Terraform Plan
  run: |
    curl -X POST ${{ secrets.SLACK_WEBHOOK_URL }} \
      -H "Content-Type: application/json" \
      -d '{
        "id": "${{ github.run_id }}",
        "slackChannelId": "C1234567890",
        "repositoryFullName": "${{ github.repository }}",
        "runId": "${{ github.run_id }}",
        "runNumber": "${{ github.run_number }}",
        "commitHash": "${{ github.sha }}",
        "terraformAdds": "5",
        "terraformChanges": "2",
        "terraformDestroys": "0",
        "commitMessage": "${{ github.event.head_commit.message }}",
        "commitTimeEpoch": "${{ github.event.head_commit.timestamp }}",
        "author": "${{ github.event.head_commit.author.name }}",
        "branch": "${{ github.ref_name }}",
        "organizationName": "${{ github.repository_owner }}",
        "repositoryName": "${{ github.event.repository.name }}",
        "friendlyName": "company/infrastructure",
        "terraformPlanJson": "{\"resource_changes\":[]}"
      }'

using Slack CLI

  • slack env set GH_TOKEN xxx which has permission to dispatch events to the repository
  • slack env set REVIEW_TRIGGER_URL xxx which is the url to dispatch the apply pipeline

how it actually works

the flow

  • webhook trigger: our infra cd pipeline hits the webhook with terraform plan data
  • workflow execution: slack starts the approval workflow
  • latest claim: if there's already a review for this repo, it gets marked as stale and the new one becomes "latest"
  • message posting: a beautiful message appears in your channel with:
    • summary of changes (adds/changes/destroys)
    • risk assessment (because we care about your job security)
    • links to the full plan
    • approve/reject buttons
  • decision time: someone (hopefully not an intern) clicks a button
  • github integration: the app calls github's api to approve/reject the run
  • audit trail: everything gets stored for when the lawyers come calling

risk assessment logic

the app has a SopHisTicAteED algorithm to determine risk levels:

  • iam changes: high risk (because permissions are scary)
  • security groups: high risk (because security is important)
  • database instances: high risk (because data is money)
  • eks clusters: medium risk (because kubernetes is complex)
  • s3 buckets: low risk (because storage is cheap)

one review at a time

to prevent chaos and ensure only the latest changes get applied:

  • latest claims: when a new terraform plan comes in, it becomes the "latest" and any existing reviews are marked as stale
  • modal blocking: only the latest review can open the approval modal - stale reviews show an error message
  • no confusion: no more wondering which review is the "real" one

development (for the brave souls)

slack cli

this app is weird, it's part of slack's new function platform.

it owns logs, deploying, running, the lot. nice.

# To run a dev version locally
slack run

# To deploy to production
slack deploy

# To view logs
slack logs

local development

# install dependencies (there aren't any, it's deno!)
# but you can run tests (there aren't any, yoloΒ±)
deno task test

# format code (because we're civilized)
deno fmt

# lint code (because we care about quality)
deno lint

project structure

β”œβ”€β”€ functions/          # the main logic (where the magic happens)
β”œβ”€β”€ workflows/          # essentially proxies traffic through to the "function" layer
β”œβ”€β”€ triggers/           # a webhook from our ci pipeline with infra review data
β”œβ”€β”€ datastores/         # stores the review data, avoid slacks interactivity shit
β”œβ”€β”€ types/              # 🍡
β”œβ”€β”€ utils/tf/           # terraform parsing and whatnot
└── assets/             # πŸ–ΌοΈ

About

A little Slack CLI function to provide a groovy πŸ’… experience for reviewing infrastructure plans

Resources

Stars

Watchers

Forks