Awesome
Bashbot
| Docker Hub | ghcr
BashBot is a slack bot written in golang for infrastructure/devops teams. A socket connection to slack provides bashbot with a stream of text from each channel it is invited to, and uses regular expressions to determine when to trigger bash commands. A configuration file defines a list of commands that can be run in public and/or private channels. Restricting certain commands to private channels gives granular control, over which users can execute them. Bashbot allows infrastructure/devops teams to extend the tools and scripts they already use to manage their environments, into slack, that also acts as an execution log, and leverages slack's access controls.
See the examples directory for more information about deploying, configuring and customizing Bashbot for your team. The most basic example of a bashbot command will just echo a string back to the user when triggered.
name: Ping/Pong
description: Return pong on pings
envvars: []
dependencies: []
help: "!bashbot ping"
trigger: ping
location: ./
command:
- echo "pong"
parameters: []
log: true
ephemeral: false
response: text
permissions:
- all
<img src="https://i.imgur.com/QyA6ECb.gif">
In this example, a user triggers a Jenkins job using Bashbot and another instance of Bashbot is deployed in a Jenkins job as a gating mechanism. The configuration for the secondary Bashbot could get info about the Jenkins job/host and provides controls to manually decide if the job should pass or fail, at a certain stage in the build.This method of deploying Bashbot gives basic Jenkins controls (trigger, pass, fail) to users in an organization, without giving them access to Jenkins itself. Bashbot commands can be restricted to private channels to limit access within slack.
<img src="https://i.imgur.com/P6IL10y.gif" />Slack tokens
Bashbot uses the Slack API's "Socket Mode" to connect to the slack servers over a socket connection and uses no webhooks/ingress to trigger commands. Bashbot "subscribes" to message and emoji events and determins if a command should be executed and what command should be executed by parsing the data in each event. To run Bashbot, you must have a "Bot User OAuth Token" and an "App-Level Token".
- Click "Create New App" from the Slack Apps page and follow the "From Scratch" prompts to give your instance of bashbot a unique name and a workspace for it to be installed in
- The "Basic Information" page gives controls to set a profile picture toward the bottom (make sure to save any changes)
- Enable "Socket Mode" from the "Socket Mode" page and add the default scopes
conversations.write
and note the "App-Level Token" that is generated to save in the .env file asSLACK_APP_TOKEN
- Enable events from the "Event Subscriptions" page and add the following bot event subscriptions and save changes
app_mention
message.channels
message.groups
reaction_added
reaction_removed
- From the "OAuth & Permissions" page, after setting the following "scopes" or permissions, install Bashbot in your workspace (this will require administrator approval of your slack workspace) and note the "Bot User OAuth Token" to save in the .env file as
SLACK_BOT_TOKEN
app_mentions:read
channels:history
channels:read
chat:write
files:write
groups:history
groups:read
incoming-webhook
reactions:read
reactions:write
users:read
Installation, setup and configuration
Example deployments and commands
Bashbot can be run as a go binary or as a container and requires a slack-bot-token, slack-app-token and a config.yaml. The go binary takes flags to set the slack-bot-token, slack-app-token and path to the config.yaml file and the container uses environment variables to trigger a go binary by entrypoint.sh. The Examples directory of this repository, has many deployment examples, commands used in automated tests, and can illustrate how bashbot can be used to trigger automation, or as automation itself, by leveraging secrets from the host running bashbot. For instance, one command might use an api token to curl a third-party api, and return the response back to the slack user, once triggered (aqi example). If deployed in a kubernetes cluster, with a service-account to access the kube-api, bashbot can allow slack users to execute (hopefully curated) kubectl/helm commands, for an SRE/Ops focused deployment (get/describe/delete pods/deployments/secrets etc).
Steps To Prove It's Working
- Invite the BashBot into a channel by typing
@BashBot
- Slackbot should respond with the message:
OK! I’ve invited @BashBot to this channel.
- Now type
!bashbot help
- If all is configured correctly, you should see BashBot respond immediately with
Processing command...
and momentarily post a full list of commands that are defined in config.yaml
Automation
Included in this repository, one github action is executed on commits to pull requests, and another is executed on merges to the main branch:
- On pull requests to the main branch , four jobs are run on every commit:
- linting and unit tests are run under the
unit_tests
job - a container is built and scanned by the anchore container scanning tool
- the golang code is analyzed by codeql SAST tool
- a container is built and deployed in a kind cluster, to run automated tests, to maintain/verify basic functionality (see Makefile target
make help
for more information)
- linting and unit tests are run under the
- The action will:
- cross compile go-binaries for linux/amd64, linux/arm64, darwin/amd64, and darwin/arm64
- package and release a helm chart with the chart-releaser action
- add the go-binaries as release artifacts
- use the buildx docker plugin to build and push a container for amd64/arm64 to docker hub and ghcr.
- use asdf to install the new version of bashbot
- notify the bashbot test slack workspace
- The action will check for new versions of dependencies installed with the asdf version manager, found in the .tool-versions file.
Makefile
run make help
for a full list of targets.
Note: yq is a dependency of running many makefile targets and can be installed with the binary: wget https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64 -q -O /usr/local/bin/yq && chmod +x /usr/local/bin/yq
+---------------------------------------------------------------+
| ____ _ ____ _ |
| | _ \ | | | _ \ | | |
| | |_) | __ _ ___| |__ | |_) | ___ | |_ |
| | _ < / _' / __| '_ \| _ < / _ \| __| |
| | |_) | (_| \__ \ | | | |_) | (_) | |_ |
| |____/ \__,_|___/_| |_|____/ \___/ \__| |
| |
| makefile targets |
+---------------------------------------------------------------+
v2.0.5
Usage:
make <target>
Go stuff
go-build build a go-binary for this host system-arch
go-clean delete any existing binaries at ./bin/*
go-setup install go-dependencies
go-cross-compile build go-binaries for linux/darwin amd64/arm64
go-run run the bashbot source code with go
go-version run the bashbot source code with the version argument
Docker stuff
docker-build build and tag $(REGISTRY_NAME):$(REGISTRY_TAG)
docker-run run an existing build of $(REGISTRY_NAME):$(REGISTRY_TAG)
docker-run-bash run an exsting build of $(REGISTRY_NAME):$(REGISTRY_TAG) but override the entrypoint with /bin/bash
Kubernetes stuff
test-kind run KinD tests
test-run run tests designed for bashbot running in kubernetes
kind-setup setup a KinD cluster to test bashbot's helm chart
kind-cleanup delete any KinD cluster set up for bashbot
version get the current helm chart version
bump-patch Bump-patch the semantic version of the helm chart using semver tool
bump-minor Bump-minor the semantic version of the helm chart using semver tool
bump-major Bump-major the semantic version of the helm chart using semver tool
helm-install install bashbot via helm into an existing KinD cluster to /usr/local/bin/bashbot
helm-uninstall uninstall bashbot via helm/kubectl from an existing cluster
pod-get with an existing pod bashbot pod running, use kubectl to get the pod name
pod-logs with an existing pod bashbot pod running, use kubectl to display the logs of the pod
pod-logs-json with an existing pod bashbot pod running, use kubectl to display the json logs of the pod and pipe to jq
pod-delete with an existing pod bashbot pod running, use kubectl to delete it
pod-exec with an existing pod bashbot pod running, use kubectl to exec into it
pod-exec-test with an existing pod bashbot pod running, use kubectl to exec into it and run the test-suite
Linters and Tests
test-lint-actions lint github actions with action-validator
test-lint lint go source with golangci-lint
test-docker use dockle to test the dockerfile for best practices
test-go run go coverage tests
Other stuff
help this
install-latest install the latest version of the bashbot binary to /usr/local/bin/bashbot with wget
update-asdf-deps trigger github action to update asdf dependencies listed in .tool-versions (requires GIT_TOKEN)
Any of these environment variables can be overridden by exporting a new value before running any makefile target.
GOOS?=$(shell go env GOOS)
GOARCH?=$(shell go env GOARCH)
VERSION?=$(shell make version)
LATEST_VERSION?=$(shell curl -s https://api.github.com/repos/mathew-fleisch/bashbot/releases/latest | grep tag_name | cut -d '"' -f 4)
BINARY?=bin/bashbot
SRC_LOCATION?=main.go
# Public builds: REGISTRY_NAME=mathewfleisch/bashbot or REGISTRY_NAME=ghcr.io/mathew-fleisch/bashbot
REGISTRY_NAME?=bashbot
# For latest tag: REGISTRY_TAG=latest"
REGISTRY_TAG?=local
NRUSER?=bb
BASHBOT_LOG_LEVEL?=info
BASHBOT_LOG_TYPE?=text
TESTING_CHANNEL?=C034FNXS3FA
ADMIN_CHANNEL?=GPFMM5MD2
NAMESPACE?=bashbot
BOTNAME?=bashbot
HELM_CONFIG_YAML?=$(PWD)/config.yaml
HELM_TOOL_VERSIONS?=$(PWD)/.tool-versions
HELM_ENV?=${PWD}/.env