Skip to content

Commit

Permalink
Revised config handling, logging and other functions, use latest Matt…
Browse files Browse the repository at this point in the history
…ermost driver, implement auto reconnect
  • Loading branch information
danielchristianschroeter committed Jan 29, 2023
1 parent 0dada2a commit ee7b102
Show file tree
Hide file tree
Showing 14 changed files with 2,357 additions and 393 deletions.
1 change: 1 addition & 0 deletions .goreleaser.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ builds:
goos:
- darwin
- linux
- windows
goarch:
- amd64
- arm64
79 changes: 73 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,18 @@
### What is it ?
mattermost-bot can join any Mattermost channel and watches for commands to execute them locally on the same host or call other remote API services. For security reasons, not all commands of all roles are available to use.

Use `!help` to list all possible commands (depends on configured ROLES variable) you can use in the channel:
Use `!help` to list all possible commands (depends on configured ROLES variable) you can use in the Mattermost channel:

```
The following commands are availble to use:
[OpenShift Client]
!oc get Display one or many resources
!oc describe Show details of a specific resource or group of resources
!oc delete pod Delete a pod
!oc scale Set a new size for a deployment, replica set, or replication controller
!oc logs Print the logs for a container in a pod
!oc adm top Show usage statistics of resources on the server
!oc adm upgrade Check on upgrade status or upgrade the cluster to a newer version
!oc api-versions Print the supported API versions on the server, in the form of group/version
!oc api-resources Print the supported API resources on the server
!oc help Help about any command
Expand All @@ -28,15 +30,75 @@ The following commands are availble to use:
!terraform version Show the current Terraform version
Global options:
-chdir=DIR Switch to a different working directory before executing the given subcommand.
-help Show this help output, or the help for a specified subcommand.
-help Show help for a specified subcommand.
-version An alias for the version subcommand.
[Terraform Wrapper]
!tf plan <ENV> <ZONE> Show changes required by the current configuration for a zone within an environment.
!tf apply <ENV> <ZONE> Create or update infrastructure for a zone within an environment.
[Govc Client]
!govc about Display About info
!govc cluster.usage Cluster resource usage summary
!govc datacenter.info Information about datacenter
!govc datastore.cluster.info Display datastore cluster info
!govc device.info Device info for VM
!govc events Display events
!govc find Find managed objects
!govc metric.sample Display metrics of host
!govc vm.info Display info for VM
!govc vm.power VM power operations
Global options:
-help Show help for a specified subcommand.
```

If the output exceeds the message limit from Mattermost, the full output will automatically uploaded to a custom PrivateBin server (https://privatebin.info/).

### Configuration

`MB_DEBUG`: Show more details, for better debugging puposes you should enable this value.

`MB_ROLES`: Define the roles you want to use, seperated by comma (Available roles are: govc, oc, terraform, tf)

`MB_MATTERMOST_URL`: The Mattermost URL with protocol.

`MB_MATTERMOST_USERTOKEN`: The Mattermost personal access user token of a user the application can use to watch for commands in a channel.

`MB_MATTERMOST_TEAM`: The Mattermost team the user account is assigned to.

`MB_MATTERMOST_CHANNEL`: The Mattermost channel where the bot should watch and response for commands.

`MB_PRIVATEBIN_ENABLE`: Enable or disable (true/false) Privatebin (https://github.com/PrivateBin/PrivateBin), if the response exceeds 6315 characters.

`MB_PRIVATEBIN_HOST`: The host of the Privatebin instance.

`MB_PRIVATEBIN_FORMATTER`: You can define the Privatebin formatter. (Recommendation: syntaxhighlighting).

`MB_PRIVATEBIN_EXPIRE`: Set the expire date when the links should be removed from Privatebin. (Recommendation: 6days)

`MB_PRIVATEBIN_OPENDISCUSSION`: Enable or disable (true/false) opendiscussion for Privatebin link. (Recommendation: false)

`MB_PRIVATEBIN_BURNAFTERREADING`: Enable or disable (true/false) burnafterreading for Privatebin link. (Recommendation: false)

`MB_PRIVATEBIN_PASSWORD`: Set a Privatebin password for the generated link. (Recommendation: leave the value empty)

`MB_GOVC_HOST`: Host from your vCenter Server.

`MB_GOVC_DATACENTER`: Datacenter of your vCenter Server.

`MB_GOVC_USERNAME`: Username with proper permissions to control vCenter Server.

`MB_GOVC_PASSWORD`: Password from the vCenter Server user account definied above.

`MB_TERRAFORM_EXECUTABLE`: Location of the terraform executable (https://developer.hashicorp.com/terraform/tutorials/aws-get-started/install-cli)

`MB_MB_TERRAFORM_WRAPPER_EXECUTABLE`: Location of the terraform wrapper script executable (misc/tf.sh)

`MB_OC_EXECUTABLE`: Location of the OpenShift client executable (From your OpenShift Dashboard or https://github.com/okd-project/okd)

`MB_GOVC_EXECUTABLE`: Location of the govc executable (https://github.com/vmware/govmomi)

The configuration is located in the `config.env` file (you can rename the sample file `config.env.sample`).

All parameters can also be set as environment variables.
The application will automatically use the environment variables if present, otherwise it will use the values from the config.env file.

### How you can build it?

Expand All @@ -49,17 +111,22 @@ You can build this Go project to a binary file on Ubuntu as follows:

You can also use the pre build binary from the releases page.

### How to create a proper Mattermost account?

Just create a normal user account for the bot (Bot Accounts are not working to read messages from a channel).
In the Profile page from this account, you need to create a "Personal Access Token". If you can not see this point in the Security menu, you have to enable this Option first in the System Console > Integration Management > Set "Enable Personal Access Tokens" to true.

### How can you run it ?

Rename `config.env.sample` to `config.env`, update the configuration and put the config file in the same directory as the executable (Alternative location: /etc/mattermost-bot/config.env)
Rename `config.env.sample` to `config.env`, update the configuration and put the config file in the same directory as the executable.

Execute the mattermost-bot binary and see if the bot joining the defined Mattermost channel and respond to `!help`.

If you want to put the bot in the background, you can use the systemd example in `misc/mattermost-bot.service`.

Please note that the bot requires higher permissions to execute certain commands.
Depending on your needs, the mattermost bot maybe nrequires higher permissions to execute certain commands.

Mattermost-bot is only tested on Ubuntu OS systems.
I tested the Mattermost-bot ony with Ubuntu OS, but it whould work on other OS too.

### Avilable roles

Expand Down
39 changes: 21 additions & 18 deletions config.env.sample
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
ROLES=govc,oc,terraform,tf
MATTERMOST_HOST=mattermost-host.tld
MATTERMOST_EMAIL=email@account.tld
MATTERMOST_USER=bpt-username
MATTERMOST_PASSWORD=secretpassword
MATTERMOST_TEAM=TEAM
MATTERMOST_CHANNEL=bot-channel
PRIVATEBIN_ENABLE=true
PRIVATEBIN_HOST=https://paste.yourdomain.tld
PRIVATEBIN_FORMATTER=syntaxhighlighting
PRIVATEBIN_EXPIRE=6days
PRIVATEBIN_OPENDISCUSSION=false
PRIVATEBIN_BURNAFTERREADING=false
PRIVATEBIN_PASSWORD=
GOVC_URL=https://vcsa.domain
GOVC_DATACENTER=datacenter
GOVC_USERNAME=vcsa_username
GOVC_PASSWORD=secretpassword
MB_DEBUG=true
MB_ROLES=govc,oc,terraform,tf
MB_MATTERMOST_URL=mattermost.example.com
MB_MATTERMOST_USERTOKEN=mysecretusertoken
MB_MATTERMOST_TEAM=test
MB_MATTERMOST_CHANNEL=town-square
MB_PRIVATEBIN_ENABLE=true
MB_PRIVATEBIN_HOST=paste.example.com
MB_PRIVATEBIN_FORMATTER=syntaxhighlighting
MB_PRIVATEBIN_EXPIRE=6days
MB_PRIVATEBIN_OPENDISCUSSION=false
MB_PRIVATEBIN_BURNAFTERREADING=false
MB_PRIVATEBIN_PASSWORD=
MB_GOVC_HOST=vcenter-server-appliance-endpoint.example.com
MB_GOVC_DATACENTER=mydatacenter
MB_GOVC_USERNAME=myvsphereusername
MB_GOVC_PASSWORD=mysecretpasswordformyvsphereusername
MB_TERRAFORM_EXECUTABLE=/usr/bin/terraform
MB_MB_TERRAFORM_WRAPPER_EXECUTABLE=/opt/terraform/tf.sh
MB_OC_EXECUTABLE=/usr/local/bin/oc
MB_GOVC_EXECUTABLE=/usr/local/bin/govc
205 changes: 205 additions & 0 deletions confighandler/confighandler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
package confighandler

import (
"log"
"os"

_ "github.com/joho/godotenv/autoload"
"github.com/mattermost/mattermost-server/v6/model"
"github.com/rs/zerolog"
"github.com/spf13/viper"
)

var version = "DEV"
var App = &Application{}

var Settings Config

// application struct to hold the dependencies for our bot
type Application struct {
Config Config
Logger zerolog.Logger
MattermostClient *model.Client4
MattermostWebSocketClient *model.WebSocketClient
MattermostUser *model.User
MattermostChannel *model.Channel
MattermostTeam *model.Team
}

type Config struct {
MB_ROLES string
MB_MATTERMOST_URL string
MB_MATTERMOST_USER string
MB_MATTERMOST_USERTOKEN string
MB_MATTERMOST_TEAM string
MB_MATTERMOST_CHANNEL string
MB_PRIVATEBIN_ENABLE string
MB_PRIVATEBIN_HOST string
MB_PRIVATEBIN_FORMATTER string
MB_PRIVATEBIN_EXPIRE string
MB_PRIVATEBIN_OPENDISCUSSION string
MB_PRIVATEBIN_BURNAFTERREADING string
MB_PRIVATEBIN_PASSWORD string
MB_TERRAFORM_EXECUTABLE string
MB_TERRAFORM_WRAPPER_EXECUTABLE string
MB_OC_EXECUTABLE string
MB_GOVC_EXECUTABLE string
MB_GOVC_HOST string
MB_GOVC_DATACENTER string
MB_GOVC_USERNAME string
MB_GOVC_PASSWORD string
}

func Init() {
// App = &Application{
// Logger: zerolog.New(
// zerolog.ConsoleWriter{
// Out: os.Stdout,
// TimeFormat: time.RFC822,
// NoColor: true,
// },
// ).With().Timestamp().Logger(),
// }

App = &Application{
Logger: zerolog.New(
os.Stdout,
).With().Timestamp().Logger(),
}

App.Config = LoadConfig()
}

func LoadConfig() Config {
App.Logger.Info().Msg("Mattermost-Bot (v" + version + ") started.")

viper.SetConfigName("config") // name of config file (without extension)
viper.SetConfigType("env") // REQUIRED if the config file does not have the extension in the name
//viper.AddConfigPath("/etc/bitbucket-mattermost-notifier/") // path to look for the config file in
viper.AddConfigPath(".") // optionally look for config in the working directory
viper.AutomaticEnv()
if err := viper.ReadInConfig(); err != nil {
if _, ok := err.(viper.ConfigFileNotFoundError); ok {
// Config file not found; ignore error if desired
} else {
// Config file was found but another error was produced
log.Fatal("Fatal error config file: %w", err)
}
}
// If MB_DEBUG is true, enable debug mode
zerolog.SetGlobalLevel(zerolog.InfoLevel)
if GetConfigBoolValue("MB_DEBUG") {
zerolog.SetGlobalLevel(zerolog.DebugLevel)
}
// if !checkParams("MATTERMOST_WEBHOOKURL", "MATTERMOST_CHANNEL") {
// log.Fatal("MATTERMOST_WEBHOOKURL or MATTERMOST_CHANNEL can NOT be empty")
// }
// settings.mattermostTeamName = os.Getenv("MM_TEAM")
// settings.mattermostUserName = os.Getenv("MM_USERNAME")
// settings.mattermostToken = os.Getenv("MM_TOKEN")
// settings.mattermostChannel = os.Getenv("MM_CHANNEL")
// settings.mattermostServer, _ = url.Parse(os.Getenv("MM_SERVER"))

settings := map[string]string{
"MB_ROLES": GetConfigValue("MB_ROLES"),
"MB_MATTERMOST_URL": GetConfigValue("MB_MATTERMOST_URL"),
"MB_MATTERMOST_USERTOKEN": GetConfigValue("MB_MATTERMOST_USERTOKEN"),
"MB_MATTERMOST_TEAM": GetConfigValue("MB_MATTERMOST_TEAM"),
"MB_MATTERMOST_CHANNEL": GetConfigValue("MB_MATTERMOST_CHANNEL"),
"MB_PRIVATEBIN_ENABLE": GetConfigValue("MB_PRIVATEBIN_ENABLE"),
"MB_PRIVATEBIN_HOST": GetConfigValue("MB_PRIVATEBIN_HOST"),
"MB_PRIVATEBIN_FORMATTER": GetConfigValue("MB_PRIVATEBIN_FORMATTER"),
"MB_PRIVATEBIN_EXPIRE": GetConfigValue("MB_PRIVATEBIN_EXPIRE"),
"MB_PRIVATEBIN_OPENDISCUSSION": GetConfigValue("MB_PRIVATEBIN_OPENDISCUSSION"),
"MB_PRIVATEBIN_BURNAFTERREADING": GetConfigValue("MB_PRIVATEBIN_BURNAFTERREADING"),
"MB_PRIVATEBIN_PASSWORD": GetConfigValue("MB_PRIVATEBIN_PASSWORD"),
"MB_TERRAFORM_EXECUTABLE": GetConfigValue("MB_TERRAFORM_EXECUTABLE"),
"MB_TERRAFORM_WRAPPER_EXECUTABLE": GetConfigValue("MB_TERRAFORM_WRAPPER_EXECUTABLE"),
"MB_OC_EXECUTABLE": GetConfigValue("MB_OC_EXECUTABLE"),
"MB_GOVC_EXECUTABLE": GetConfigValue("MB_GOVC_EXECUTABLE"),
"MB_GOVC_HOST": GetConfigValue("MB_GOVC_HOST"),
"MB_GOVC_DATACENTER": GetConfigValue("MB_GOVC_DATACENTER"),
"MB_GOVC_USERNAME": GetConfigValue("MB_GOVC_USERNAME"),
"MB_GOVC_PASSWORD": GetConfigValue("MB_GOVC_PASSWORD"),
}

// Settings.MB_ROLES = GetConfigValue("MB_ROLES")
// Settings.MB_MATTERMOST_URL = GetConfigValue("MB_MATTERMOST_URL")
// Settings.MB_MATTERMOST_USERTOKEN = GetConfigValue("MB_MATTERMOST_USERTOKEN")
// Settings.MB_MATTERMOST_TEAM = GetConfigValue("MB_MATTERMOST_TEAM")
// Settings.MB_MATTERMOST_CHANNEL = GetConfigValue("MB_MATTERMOST_CHANNEL")
// Settings.MB_PRIVATEBIN_ENABLE = GetConfigBoolValue("MB_PRIVATEBIN_ENABLE")
// Settings.MB_PRIVATEBIN_HOST = GetConfigValue("MB_PRIVATEBIN_HOST")
// Settings.MB_PRIVATEBIN_FORMATTER = GetConfigValue("MB_PRIVATEBIN_FORMATTER")
// Settings.MB_PRIVATEBIN_EXPIRE = GetConfigValue("MB_PRIVATEBIN_EXPIRE")
// Settings.MB_PRIVATEBIN_OPENDISCUSSION = GetConfigBoolValue("MB_PRIVATEBIN_OPENDISCUSSION")
// Settings.MB_PRIVATEBIN_BURNAFTERREADING = GetConfigBoolValue("MB_PRIVATEBIN_BURNAFTERREADING")
// Settings.MB_PRIVATEBIN_PASSWORD = GetConfigValue("MB_PRIVATEBIN_PASSWORD")
// Settings.MB_TERRAFORM_EXECUTABLE = GetConfigValue("MB_TERRAFORM_EXECUTABLE")
// Settings.MB_TERRAFORM_WRAPPER_EXECUTABLE = GetConfigValue("MB_TERRAFORM_WRAPPER_EXECUTABLE")
// Settings.MB_OC_EXECUTABLE = GetConfigValue("MB_OC_EXECUTABLE")
// Settings.MB_GOVC_EXECUTABLE = GetConfigValue("MB_GOVC_EXECUTABLE")
// Settings.MB_GOVC_HOST = GetConfigValue("MB_GOVC_HOST")
// Settings.MB_GOVC_DATACENTER = GetConfigValue("MB_GOVC_DATACENTER")
// Settings.MB_GOVC_USERNAME = GetConfigValue("MB_GOVC_USERNAME")
// Settings.MB_GOVC_PASSWORD = GetConfigValue("MB_GOVC_PASSWORD")

// TODO: No secret credentials in output
//App.Logger.Info().Msg(fmt.Sprint(Settings))

// Output all keys and values of the current loaded config
message := "Current configuration: "
for key, value := range settings {
if key == "MB_MATTERMOST_USERTOKEN" || key == "MB_PRIVATEBIN_PASSWORD" || key == "MB_GOVC_PASSWORD" {
continue
}
message += key + "=" + value + " "
}
message = message[:len(message)-1]

App.Logger.Info().Msg(message)

Settings := Config{
MB_ROLES: settings["MB_ROLES"],
MB_MATTERMOST_URL: settings["MB_MATTERMOST_URL"],
MB_MATTERMOST_USERTOKEN: settings["MB_MATTERMOST_USERTOKEN"],
MB_MATTERMOST_TEAM: settings["MB_MATTERMOST_TEAM"],
MB_MATTERMOST_CHANNEL: settings["MB_MATTERMOST_CHANNEL"],
MB_PRIVATEBIN_ENABLE: settings["MB_PRIVATEBIN_ENABLE"],
MB_PRIVATEBIN_HOST: settings["MB_PRIVATEBIN_HOST"],
MB_PRIVATEBIN_FORMATTER: settings["MB_PRIVATEBIN_FORMATTER"],
MB_PRIVATEBIN_EXPIRE: settings["MB_PRIVATEBIN_EXPIRE"],
MB_PRIVATEBIN_OPENDISCUSSION: settings["MB_PRIVATEBIN_OPENDISCUSSION"],
MB_PRIVATEBIN_BURNAFTERREADING: settings["MB_PRIVATEBIN_BURNAFTERREADING"],
MB_PRIVATEBIN_PASSWORD: settings["MB_PRIVATEBIN_PASSWORD"],
MB_TERRAFORM_EXECUTABLE: settings["MB_TERRAFORM_EXECUTABLE"],
MB_TERRAFORM_WRAPPER_EXECUTABLE: settings["MB_TERRAFORM_WRAPPER_EXECUTABLE"],
MB_OC_EXECUTABLE: settings["MB_OC_EXECUTABLE"],
MB_GOVC_EXECUTABLE: settings["MB_GOVC_EXECUTABLE"],
MB_GOVC_HOST: settings["MB_GOVC_HOST"],
MB_GOVC_DATACENTER: settings["MB_GOVC_DATACENTER"],
MB_GOVC_USERNAME: settings["MB_GOVC_USERNAME"],
MB_GOVC_PASSWORD: settings["MB_GOVC_PASSWORD"],
}

return Settings
}

func checkParams(params ...string) bool {
for _, param := range params {
if !viper.IsSet(param) {
return false
}
}
return true
}

func GetConfigValue(key string) string {
//LoadConfig()
return viper.GetString(key)
}

func GetConfigBoolValue(key string) bool {
//LoadConfig()
return viper.GetBool(key)
}
Loading

0 comments on commit ee7b102

Please sign in to comment.