diff --git a/README.md b/README.md
index 9f858ce12..e9ca0a18d 100644
--- a/README.md
+++ b/README.md
@@ -78,6 +78,8 @@ $ kubectl create ns botkube && kubectl create -f deploy-all-in-one.yaml -n botku
- Check pod status in botkube namespace. Once running, send **@BotKube ping** in the Slack channel to confirm if BotKube is responding correctly.
+- To deploy with TLS, download and use deploy-all-in-one-tls.yaml. Replace **ENCODED_CERTIFICATE** with your base64 encoded certificate value in the secret.
+
## Add BotKube to your Mattermost team
Before adding `BotKube` to your Mattermost team, please make sure you have all the pre-requisites working.
@@ -92,6 +94,7 @@ Before adding `BotKube` to your Mattermost team, please make sure you have all t
In the helm chart, config.yaml or deploy-all-in-one.yaml update the following fields for enabling Mattermost support and providing Mattermost config parameters.
**MATTERMOST_SERVER_URL** is the URL where Mattermost is running
+**MATTERMOST_CERT** is the SSL certificate file for HTTPS connection. Place it in Helm directory and specify the path
**MATTERMOST_TOKEN** is the Token you received after installing BotKube user and creating Personal Access Token
**MATTERMOST_TEAM** is the team name where BotKube will be added
**MATTERMOST_CHANNEL** is the channel name where BotKube will be added
@@ -102,6 +105,7 @@ In the helm chart, config.yaml or deploy-all-in-one.yaml update the following fi
$ helm install --name botkube --namespace botkube \
--set config.communications.mattermost.enabled=true \
--set config.communications.mattermost.url={MATTERMOST_SERVER_URL} \
+--set config.communications.mattermost.cert={MATTERMOST_CERT} \
--set config.communications.mattermost.token={MATTERMOST_TOKEN} \
--set config.communications.mattermost.team={MATTERMOST_TEAM} \
--set config.communications.mattermost.channel={MATTERMOST_CHANNEL} \
diff --git a/deploy-all-in-one-tls.yaml b/deploy-all-in-one-tls.yaml
new file mode 100644
index 000000000..2910948b0
--- /dev/null
+++ b/deploy-all-in-one-tls.yaml
@@ -0,0 +1,253 @@
+---
+# Configmap
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: botkube-configmap
+ labels:
+ app: botkube
+data:
+ config.yaml: |
+ ## Resources you want to watch
+ resources:
+ - name: pods # Name of the resources e.g pods, deployments, ingresses, etc. (Resource name must be in plural form)
+ namespaces: # List of namespaces, "all" will watch all the namespaces
+ - all
+ events: # List of lifecycle events you want to receive, e.g create, update, delete OR all
+ - create
+ - delete
+ - name: services
+ namespaces:
+ - all
+ events:
+ - create
+ - delete
+ - name: deployments
+ namespaces:
+ - all
+ events:
+ - create
+ - delete
+ - name: ingresses
+ namespaces:
+ - all
+ events:
+ - create
+ - delete
+ - name: nodes
+ namespaces:
+ - all
+ events:
+ - create
+ - delete
+ - name: namespaces
+ namespaces:
+ - all
+ events:
+ - create
+ - delete
+ - name: persistentvolumes
+ namespaces:
+ - all
+ events:
+ - create
+ - delete
+ - name: persistentvolumeclaims
+ namespaces:
+ - all
+ events:
+ - create
+ - delete
+ - name: secrets
+ namespaces:
+ - all
+ events:
+ - create
+ - delete
+ - name: configmaps
+ namespaces:
+ - all
+ events:
+ - create
+ - delete
+ - name: daemonsets
+ namespaces:
+ - all
+ events:
+ - create
+ - delete
+ - name: jobs
+ namespaces:
+ - all
+ events:
+ - create
+ - delete
+ - name: roles
+ namespaces:
+ - all
+ events:
+ - create
+ - delete
+ - name: rolebindings
+ namespaces:
+ - all
+ events:
+ - create
+ - delete
+ - name: clusterroles
+ namespaces:
+ - all
+ events:
+ - create
+ - delete
+ - name: clusterrolebindings
+ namespace:
+ - all
+ events:
+ - create
+ - delete
+ - name: nodes
+ namespaces:
+ - all
+ events:
+ - create
+ - delete
+
+ # K8S error/warning events you want to receive for the configured resources
+ events:
+ types:
+ #- normal
+ - warning
+
+ # Check true if you want to receive recommendations
+ # about the best practices for the created resource
+ recommendations: true
+
+ # Channels configuration
+ communications:
+ # Settings for Slack
+ slack:
+ enabled: false
+ channel: 'SLACK_CHANNEL'
+ token: 'SLACK_API_TOKEN'
+
+ # Settings for Mattermost
+ mattermost:
+ enabled: false
+ url: 'MATTERMOST_SERVER_URL' # URL where Mattermost is running. e.g https://example.com:9243
+ token: 'MATTERMOST_TOKEN' # Personal Access token generated by BotKube user
+ team: 'MATTERMOST_TEAM' # Mattermost Team to configure with BotKube
+ channel: 'MATTERMOST_CHANNEL' # Mattermost Channel for receiving BotKube alerts
+
+ # Settings for ELS
+ elasticsearch:
+ enable: false
+ server: 'ELASTICSEARCH_ADDRESS' # e.g https://example.com:9243
+ username: 'ELASTICSEARCH_USERNAME'
+ password: 'ELASTICSEARCH_PASSWORD'
+ # ELS index settings
+ index:
+ name: botkube
+ type: botkube-event
+ shards: 1
+ replicas: 0
+
+ # Setting to support multiple clusters
+ settings:
+ # Cluster name to differentiate incoming messages
+ clustername: not-configured
+ # Set false to disable kubectl commands execution
+ allowkubectl: false
+---
+# serviceaccount
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: botkube-sa
+ labels:
+ app: botkube
+---
+# Source: botkube/templates/clusterrole.yaml
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+ name: botkube-clusterrole
+ labels:
+ app: botkube
+rules:
+ - apiGroups: ["*"]
+ resources: ["*"]
+ verbs: ["get", "watch", "list"]
+---
+# clusterrolebinding
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+ name: botkube-clusterrolebinding
+ labels:
+ app: botkube
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: ClusterRole
+ name: botkube-clusterrole
+subjects:
+- kind: ServiceAccount
+ name: botkube-sa
+ namespace: botkube
+---
+# Secret
+apiVersion: v1
+kind: Secret
+metadata:
+ name: botkube-secret
+ labels:
+ app: botkube
+data:
+ ca-certificates.crt: ENCODED_CERTIFICATE
+---
+# deployment
+apiVersion: extensions/v1beta1
+kind: Deployment
+metadata:
+ name: botkube
+ labels:
+ component: controller
+ app: botkube
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ component: controller
+ app: botkube
+ template:
+ metadata:
+ labels:
+ component: controller
+ app: botkube
+ spec:
+ serviceAccountName: botkube-sa
+ containers:
+ - name: botkube
+ image: "infracloud/botkube:0.7.0"
+ imagePullPolicy: Always
+ volumeMounts:
+ - name: config-volume
+ mountPath: "/config"
+ - name: certs
+ mountPath: "/etc/ssl/certs"
+ env:
+ - name: CONFIG_PATH
+ value: "/config/"
+ # set one of the log levels- info, warn, debug, error, fatal, panic
+ - name: LOG_LEVEL
+ value: "info"
+ # set BotKube release version
+ - name: BOTKUBE_VERSION
+ value: 0.7.0
+ volumes:
+ - name: config-volume
+ configMap:
+ name: botkube-configmap
+ - name: certs
+ secret:
+ secretName: botkube-secret
diff --git a/helm/botkube/templates/deployment.yaml b/helm/botkube/templates/deployment.yaml
index 38b604fc4..818a68a4f 100644
--- a/helm/botkube/templates/deployment.yaml
+++ b/helm/botkube/templates/deployment.yaml
@@ -31,6 +31,10 @@ spec:
volumeMounts:
- name: config-volume
mountPath: "/config"
+ {{- if ne .Values.config.communications.mattermost.cert "None" }}
+ - name: certs
+ mountPath: "/etc/ssl/certs"
+ {{ end }}
env:
- name: CONFIG_PATH
value: "/config/"
@@ -42,3 +46,8 @@ spec:
- name: config-volume
configMap:
name: {{ include "botkube.fullname" . }}-configmap
+ {{- if ne .Values.config.communications.mattermost.cert "None" }}
+ - name: certs
+ secret:
+ secretName: {{ include "botkube.fullname" . }}-secret
+ {{ end }}
diff --git a/helm/botkube/templates/secret.yaml b/helm/botkube/templates/secret.yaml
new file mode 100644
index 000000000..8ba14e07a
--- /dev/null
+++ b/helm/botkube/templates/secret.yaml
@@ -0,0 +1,15 @@
+{{- if ne .Values.config.communications.mattermost.cert "None" }}
+
+apiVersion: v1
+kind: Secret
+metadata:
+ name: {{ include "botkube.fullname" . }}-secret
+ labels:
+ app.kubernetes.io/name: {{ include "botkube.name" . }}
+ helm.sh/chart: {{ include "botkube.chart" . }}
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ app.kubernetes.io/managed-by: {{ .Release.Service }}
+data:
+ ca-certificates.crt: {{ .Files.Get (printf "%s" .Values.config.communications.mattermost.cert) | b64enc }}
+
+{{ end }}
diff --git a/helm/botkube/values.yaml b/helm/botkube/values.yaml
index 42f9497bc..241bb83a5 100644
--- a/helm/botkube/values.yaml
+++ b/helm/botkube/values.yaml
@@ -142,6 +142,7 @@ config:
mattermost:
enabled: false
url: 'MATTERMOST_SERVER_URL' # URL where Mattermost is running. e.g https://example.com:9243
+ cert: None # SSL Certificate file. Leave it None for http connection. e.g certs/my-cert.crt
token: 'MATTERMOST_TOKEN' # Personal Access token generated by BotKube user
team: 'MATTERMOST_TEAM' # Mattermost Team to configure with BotKube
channel: 'MATTERMOST_CHANNEL' # Mattermost Channel for receiving BotKube alerts
diff --git a/pkg/mattermost/mattermost.go b/pkg/mattermost/mattermost.go
index a5940bd7e..c6153ecdc 100644
--- a/pkg/mattermost/mattermost.go
+++ b/pkg/mattermost/mattermost.go
@@ -2,6 +2,7 @@ package mattermost
import (
"fmt"
+ "net/url"
"strings"
"github.com/infracloudio/botkube/pkg/config"
@@ -15,10 +16,10 @@ var client *model.Client4
const (
// BotName stores Botkube details
BotName = "botkube"
- // ChannelPurpose describes the purpose of Botkube channel
- ChannelPurpose = "Botkube alerts"
// WebSocketProtocol stores protocol initials for web socket
- WebSocketProtocol = "ws:"
+ WebSocketProtocol = "ws://"
+ // WebSocketSecureProtocol stores protocol initials for web socket
+ WebSocketSecureProtocol = "wss://"
)
// Bot listens for user's message, execute commands and sends back the response
@@ -56,32 +57,37 @@ func NewMattermostBot() *Bot {
}
}
-// Channel structure in Mattermost
-func mmChannel(channelName, teamID string) *model.Channel {
- return &model.Channel{
- Name: channelName,
- DisplayName: channelName,
- Purpose: ChannelPurpose,
- Type: model.CHANNEL_OPEN,
- TeamId: teamID,
- }
-}
-
// Start establishes mattermost connection and listens for messages
func (b *Bot) Start() {
client = model.NewAPIv4Client(b.ServerURL)
client.SetOAuthToken(b.Token)
+ // Check if Mattermost URL is valid
+ checkURL, err := url.Parse(b.ServerURL)
+ if err != nil {
+ logging.Logger.Error("The Mattermost URL entered is incorrect. URL: ", b.ServerURL, "\nError: ", err)
+ return
+ }
+
// Check connection to Mattermost server
- err := checkServerConnection()
+ err = checkServerConnection()
if err != nil {
logging.Logger.Error("There was a problem pinging the Mattermost server URL: ", b.ServerURL, "\nError: ", err)
return
}
// Create WebSocketClient and handle messages
- webSocketURL := WebSocketProtocol + strings.SplitN(b.ServerURL, ":", 2)[1]
- webSocketClient, _ := model.NewWebSocketClient4(webSocketURL, client.AuthToken)
+ webSocketURL := WebSocketProtocol + checkURL.Host
+ if checkURL.Scheme == "https" {
+ webSocketURL = WebSocketSecureProtocol + checkURL.Host
+ }
+ var modelError *model.AppError
+ webSocketClient, modelError := model.NewWebSocketClient4(webSocketURL, client.AuthToken)
+ if modelError != nil {
+ logging.Logger.Error("Error creating WebSocket for Mattermost connectivity. \nError: ", modelError)
+ return
+ }
+
webSocketClient.Listen()
go func() {
for {