diff --git a/cmd/botkube/main.go b/cmd/botkube/main.go index 3a50fb9e9..269cf2712 100644 --- a/cmd/botkube/main.go +++ b/cmd/botkube/main.go @@ -211,6 +211,7 @@ func run(ctx context.Context) error { CommandGuard: cmdGuard, PluginManager: pluginManager, BotKubeVersion: botkubeVersion, + RestCfg: kubeConfig, AuditReporter: auditReporter, }, ) @@ -380,7 +381,7 @@ func run(ctx context.Context) error { actionProvider := action.NewProvider(logger.WithField(componentLogFieldKey, "Action Provider"), conf.Actions, executorFactory) - sourcePluginDispatcher := source.NewDispatcher(logger, bots, sinkNotifiers, pluginManager, actionProvider, reporter, auditReporter) + sourcePluginDispatcher := source.NewDispatcher(logger, bots, sinkNotifiers, pluginManager, actionProvider, reporter, auditReporter, kubeConfig) scheduler := source.NewScheduler(logger, conf, sourcePluginDispatcher) err = scheduler.Start(ctx) if err != nil { diff --git a/cmd/source/cm-watcher/main.go b/cmd/source/cm-watcher/main.go index 5a5082b71..eb6c08302 100644 --- a/cmd/source/cm-watcher/main.go +++ b/cmd/source/cm-watcher/main.go @@ -4,7 +4,6 @@ import ( "context" "fmt" "log" - "os" "github.com/MakeNowJust/heredoc" "github.com/hashicorp/go-plugin" @@ -76,13 +75,13 @@ func (CMWatcher) Stream(ctx context.Context, in source.StreamInput) (source.Stre Output: make(chan []byte), } - go listenEvents(ctx, cfg.ConfigMap, out.Output) + go listenEvents(ctx, in.Context.KubeConfig, cfg.ConfigMap, out.Output) return out, nil } -func listenEvents(ctx context.Context, obj Object, sink chan<- []byte) { - config, err := clientcmd.BuildConfigFromFlags("", os.Getenv("KUBECONFIG")) +func listenEvents(ctx context.Context, kubeConfig []byte, obj Object, sink chan<- []byte) { + config, err := clientcmd.RESTConfigFromKubeConfig(kubeConfig) exitOnError(err) clientset, err := kubernetes.NewForConfig(config) exitOnError(err) diff --git a/go.mod b/go.mod index c761367f6..09eb04173 100644 --- a/go.mod +++ b/go.mod @@ -57,6 +57,7 @@ require ( k8s.io/kubectl v0.25.4 k8s.io/utils v0.0.0-20221108210102-8e77b1f39fe2 sigs.k8s.io/controller-runtime v0.13.1 + sigs.k8s.io/yaml v1.3.0 ) require ( @@ -204,7 +205,6 @@ require ( sigs.k8s.io/kustomize/api v0.12.1 // indirect sigs.k8s.io/kustomize/kyaml v0.13.9 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect - sigs.k8s.io/yaml v1.3.0 // indirect ) go 1.19 diff --git a/helm/botkube/README.md b/helm/botkube/README.md index 9be0075e4..f8e062f23 100644 --- a/helm/botkube/README.md +++ b/helm/botkube/README.md @@ -46,178 +46,208 @@ Controller for the Botkube Slack app which helps you monitor your Kubernetes clu | [actions.show-logs-on-error.bindings.executors](./values.yaml#L104) | list | `["k8s-default-tools"]` | Executors configuration used to execute a configured command. | | [sources](./values.yaml#L113) | object | See the `values.yaml` file for full object. | Map of sources. Source contains configuration for Kubernetes events and sending recommendations. The property name under `sources` object is an alias for a given configuration. You can define multiple sources configuration with different names. Key name is used as a binding reference. | | [sources.k8s-recommendation-events.botkube/kubernetes](./values.yaml#L118) | object | See the `values.yaml` file for full object. | Describes Kubernetes source configuration. | -| [sources.k8s-recommendation-events.botkube/kubernetes.config.recommendations](./values.yaml#L125) | object | `{"ingress":{"backendServiceValid":true,"tlsSecretValid":true},"pod":{"labelsSet":true,"noLatestImageTag":true}}` | Describes configuration for various recommendation insights. | -| [sources.k8s-recommendation-events.botkube/kubernetes.config.recommendations.pod](./values.yaml#L127) | object | `{"labelsSet":true,"noLatestImageTag":true}` | Recommendations for Pod Kubernetes resource. | -| [sources.k8s-recommendation-events.botkube/kubernetes.config.recommendations.pod.noLatestImageTag](./values.yaml#L129) | bool | `true` | If true, notifies about Pod containers that use `latest` tag for images. | -| [sources.k8s-recommendation-events.botkube/kubernetes.config.recommendations.pod.labelsSet](./values.yaml#L131) | bool | `true` | If true, notifies about Pod resources created without labels. | -| [sources.k8s-recommendation-events.botkube/kubernetes.config.recommendations.ingress](./values.yaml#L133) | object | `{"backendServiceValid":true,"tlsSecretValid":true}` | Recommendations for Ingress Kubernetes resource. | -| [sources.k8s-recommendation-events.botkube/kubernetes.config.recommendations.ingress.backendServiceValid](./values.yaml#L135) | bool | `true` | If true, notifies about Ingress resources with invalid backend service reference. | -| [sources.k8s-recommendation-events.botkube/kubernetes.config.recommendations.ingress.tlsSecretValid](./values.yaml#L137) | bool | `true` | If true, notifies about Ingress resources with invalid TLS secret reference. | -| [sources.k8s-all-events.botkube/kubernetes](./values.yaml#L143) | object | See the `values.yaml` file for full object. | Describes Kubernetes source configuration. | -| [sources.k8s-all-events.botkube/kubernetes.config.filters](./values.yaml#L148) | object | See the `values.yaml` file for full object. | Filter settings for various sources. | -| [sources.k8s-all-events.botkube/kubernetes.config.filters.objectAnnotationChecker](./values.yaml#L150) | bool | `true` | If true, enables support for `botkube.io/disable` resource annotation. | -| [sources.k8s-all-events.botkube/kubernetes.config.filters.nodeEventsChecker](./values.yaml#L152) | bool | `true` | If true, filters out Node-related events that are not important. | -| [sources.k8s-all-events.botkube/kubernetes.config.namespaces](./values.yaml#L156) | object | `{"include":[".*"]}` | Describes namespaces for every Kubernetes resources you want to watch or exclude. These namespaces are applied to every resource specified in the resources list. However, every specified resource can override this by using its own namespaces object. | -| [sources.k8s-err-with-logs-events.botkube/kubernetes.config.namespaces.include](./values.yaml#L160) | list | `[".*"]` | Include contains a list of allowed Namespaces. It can also contain regex expressions: `- ".*"` - to specify all Namespaces. | -| [sources.k8s-all-events.botkube/kubernetes.config.namespaces.include](./values.yaml#L160) | list | `[".*"]` | Include contains a list of allowed Namespaces. It can also contain regex expressions: `- ".*"` - to specify all Namespaces. | -| [sources.k8s-create-events.botkube/kubernetes.config.namespaces.include](./values.yaml#L160) | list | `[".*"]` | Include contains a list of allowed Namespaces. It can also contain regex expressions: `- ".*"` - to specify all Namespaces. | -| [sources.k8s-err-events.botkube/kubernetes.config.namespaces.include](./values.yaml#L160) | list | `[".*"]` | Include contains a list of allowed Namespaces. It can also contain regex expressions: `- ".*"` - to specify all Namespaces. | -| [sources.k8s-all-events.botkube/kubernetes.config.event](./values.yaml#L170) | object | `{"message":{"exclude":[],"include":[]},"reason":{"exclude":[],"include":[]},"types":["create","delete","error"]}` | Describes event constraints for Kubernetes resources. These constraints are applied for every resource specified in the `resources` list, unless they are overridden by the resource's own `events` object. | -| [sources.k8s-all-events.botkube/kubernetes.config.event.types](./values.yaml#L172) | list | `["create","delete","error"]` | Lists all event types to be watched. | -| [sources.k8s-all-events.botkube/kubernetes.config.event.reason](./values.yaml#L178) | object | `{"exclude":[],"include":[]}` | Optional list of exact values or regex patterns to filter events by event reason. Skipped, if both include/exclude lists are empty. | -| [sources.k8s-all-events.botkube/kubernetes.config.event.reason.include](./values.yaml#L180) | list | `[]` | Include contains a list of allowed values. It can also contain regex expressions. | -| [sources.k8s-all-events.botkube/kubernetes.config.event.reason.exclude](./values.yaml#L183) | list | `[]` | Exclude contains a list of values to be ignored even if allowed by Include. It can also contain regex expressions. Exclude list is checked before the Include list. | -| [sources.k8s-all-events.botkube/kubernetes.config.event.message](./values.yaml#L186) | object | `{"exclude":[],"include":[]}` | Optional list of exact values or regex patterns to filter event by event message. Skipped, if both include/exclude lists are empty. If a given event has multiple messages, it is considered a match if any of the messages match the constraints. | -| [sources.k8s-all-events.botkube/kubernetes.config.event.message.include](./values.yaml#L188) | list | `[]` | Include contains a list of allowed values. It can also contain regex expressions. | -| [sources.k8s-all-events.botkube/kubernetes.config.event.message.exclude](./values.yaml#L191) | list | `[]` | Exclude contains a list of values to be ignored even if allowed by Include. It can also contain regex expressions. Exclude list is checked before the Include list. | -| [sources.k8s-all-events.botkube/kubernetes.config.annotations](./values.yaml#L195) | object | `{}` | Filters Kubernetes resources to watch by annotations. Each resource needs to have all the specified annotations. Regex expressions are not supported. | -| [sources.k8s-all-events.botkube/kubernetes.config.labels](./values.yaml#L198) | object | `{}` | Filters Kubernetes resources to watch by labels. Each resource needs to have all the specified labels. Regex expressions are not supported. | -| [sources.k8s-all-events.botkube/kubernetes.config.resources](./values.yaml#L205) | list | See the `values.yaml` file for full object. | Describes the Kubernetes resources to watch. Resources are identified by its type in `{group}/{version}/{kind (plural)}` format. Examples: `apps/v1/deployments`, `v1/pods`. Each resource can override the namespaces and event configuration by using dedicated `event` and `namespaces` field. Also, each resource can specify its own `annotations`, `labels` and `name` regex. | -| [sources.k8s-err-events.botkube/kubernetes](./values.yaml#L315) | object | See the `values.yaml` file for full object. | Describes Kubernetes source configuration. | -| [sources.k8s-err-events.botkube/kubernetes.config.namespaces](./values.yaml#L321) | object | `{"include":[".*"]}` | Describes namespaces for every Kubernetes resources you want to watch or exclude. These namespaces are applied to every resource specified in the resources list. However, every specified resource can override this by using its own namespaces object. | -| [sources.k8s-err-events.botkube/kubernetes.config.event](./values.yaml#L325) | object | `{"types":["error"]}` | Describes event constraints for Kubernetes resources. These constraints are applied for every resource specified in the `resources` list, unless they are overridden by the resource's own `events` object. | -| [sources.k8s-err-events.botkube/kubernetes.config.event.types](./values.yaml#L327) | list | `["error"]` | Lists all event types to be watched. | -| [sources.k8s-err-events.botkube/kubernetes.config.resources](./values.yaml#L332) | list | See the `values.yaml` file for full object. | Describes the Kubernetes resources you want to watch. | -| [sources.k8s-err-with-logs-events.botkube/kubernetes](./values.yaml#L354) | object | See the `values.yaml` file for full object. | Describes Kubernetes source configuration. | -| [sources.k8s-err-with-logs-events.botkube/kubernetes.config.namespaces](./values.yaml#L360) | object | `{"include":[".*"]}` | Describes namespaces for every Kubernetes resources you want to watch or exclude. These namespaces are applied to every resource specified in the resources list. However, every specified resource can override this by using its own namespaces object. | -| [sources.k8s-err-with-logs-events.botkube/kubernetes.config.event](./values.yaml#L364) | object | `{"types":["error"]}` | Describes event constraints for Kubernetes resources. These constraints are applied for every resource specified in the `resources` list, unless they are overridden by the resource's own `events` object. | -| [sources.k8s-err-with-logs-events.botkube/kubernetes.config.event.types](./values.yaml#L366) | list | `["error"]` | Lists all event types to be watched. | -| [sources.k8s-err-with-logs-events.botkube/kubernetes.config.resources](./values.yaml#L371) | list | See the `values.yaml` file for full object. | Describes the Kubernetes resources you want to watch. | -| [sources.k8s-create-events.botkube/kubernetes](./values.yaml#L384) | object | See the `values.yaml` file for full object. | Describes Kubernetes source configuration. | -| [sources.k8s-create-events.botkube/kubernetes.config.namespaces](./values.yaml#L390) | object | `{"include":[".*"]}` | Describes namespaces for every Kubernetes resources you want to watch or exclude. These namespaces are applied to every resource specified in the resources list. However, every specified resource can override this by using its own namespaces object. | -| [sources.k8s-create-events.botkube/kubernetes.config.event](./values.yaml#L394) | object | `{"types":["create"]}` | Describes event constraints for Kubernetes resources. These constraints are applied for every resource specified in the `resources` list, unless they are overridden by the resource's own `events` object. | -| [sources.k8s-create-events.botkube/kubernetes.config.event.types](./values.yaml#L396) | list | `["create"]` | Lists all event types to be watched. | -| [sources.k8s-create-events.botkube/kubernetes.config.resources](./values.yaml#L401) | list | See the `values.yaml` file for full object. | Describes the Kubernetes resources you want to watch. | -| [sources.prometheus.botkube/prometheus.enabled](./values.yaml#L418) | bool | `false` | If true, enables `prometheus` source. | -| [sources.prometheus.botkube/prometheus.config.url](./values.yaml#L421) | string | `"http://localhost:9090"` | Prometheus endpoint without api version and resource. | -| [sources.prometheus.botkube/prometheus.config.ignoreOldAlerts](./values.yaml#L423) | bool | `true` | If set as true, Prometheus source plugin will not send alerts that is created before plugin start time. | -| [sources.prometheus.botkube/prometheus.config.alertStates](./values.yaml#L425) | list | `["firing","pending","inactive"]` | Only the alerts that have state provided in this config will be sent as notification. https://pkg.go.dev/github.com/prometheus/prometheus/rules#AlertState | -| [sources.prometheus.botkube/prometheus.config.log](./values.yaml#L427) | object | `{"level":"info"}` | Logging configuration | -| [sources.prometheus.botkube/prometheus.config.log.level](./values.yaml#L429) | string | `"info"` | Log level | -| [executors](./values.yaml#L437) | object | See the `values.yaml` file for full object. | Map of executors. Executor contains configuration for running `kubectl` commands. The property name under `executors` is an alias for a given configuration. You can define multiple executor configurations with different names. Key name is used as a binding reference. | -| [executors.k8s-default-tools.kubectl.namespaces.include](./values.yaml#L446) | list | `[".*"]` | List of allowed Kubernetes Namespaces for command execution. It can also contain a regex expressions: `- ".*"` - to specify all Namespaces. | -| [executors.k8s-default-tools.kubectl.namespaces.exclude](./values.yaml#L451) | list | `[]` | List of ignored Kubernetes Namespace. It can also contain a regex expressions: `- "test-.*"` - to specify all Namespaces. | -| [executors.k8s-default-tools.kubectl.enabled](./values.yaml#L453) | bool | `false` | If true, enables `kubectl` commands execution. | -| [executors.k8s-default-tools.kubectl.commands.verbs](./values.yaml#L457) | list | `["api-resources","api-versions","cluster-info","describe","explain","get","logs","top"]` | Configures which `kubectl` methods are allowed. | -| [executors.k8s-default-tools.kubectl.commands.resources](./values.yaml#L459) | list | `["deployments","pods","namespaces","daemonsets","statefulsets","storageclasses","nodes","configmaps","services","ingresses"]` | Configures which K8s resource are allowed. | -| [executors.k8s-default-tools.kubectl.defaultNamespace](./values.yaml#L461) | string | `"default"` | Configures the default Namespace for executing Botkube `kubectl` commands. If not set, uses the 'default'. | -| [executors.k8s-default-tools.kubectl.restrictAccess](./values.yaml#L463) | bool | `false` | If true, enables commands execution from configured channel only. | -| [executors.k8s-default-tools.botkube/helm.enabled](./values.yaml#L469) | bool | `false` | If true, enables `helm` commands execution. | -| [executors.k8s-default-tools.botkube/helm.config.helmDriver](./values.yaml#L474) | string | `"secret"` | Allowed values are configmap, secret, memory. | -| [executors.k8s-default-tools.botkube/helm.config.helmConfigDir](./values.yaml#L476) | string | `"/tmp/helm/"` | Location for storing Helm configuration. | -| [executors.k8s-default-tools.botkube/helm.config.helmCacheDir](./values.yaml#L478) | string | `"/tmp/helm/.cache"` | Location for storing cached files. Must be under the Helm config directory. | -| [executors.k8s-default-tools.botkube/kubectl.context.rbac](./values.yaml#L481) | object | `{"group":{"prefix":"","static":{"values":["botkube-plugins-default"]},"type":"Static"},"user":{"prefix":"","static":{"value":"default"},"type":"Static"}}` | RBAC configuration for this plugin. | -| [executors.k8s-default-tools.botkube/helm.context.rbac](./values.yaml#L481) | object | `{"group":{"prefix":"","static":{"values":["botkube-plugins-default"]},"type":"Static"},"user":{"prefix":"","static":{"value":"default"},"type":"Static"}}` | RBAC configuration for this plugin. | -| [executors.k8s-default-tools.botkube/helm.context.rbac.group](./values.yaml#L483) | object | `{"prefix":"","static":{"values":["botkube-plugins-default"]},"type":"Static"}` | Static impersonation for a given username and groups. | -| [executors.k8s-default-tools.botkube/kubectl.context.rbac.group](./values.yaml#L483) | object | `{"prefix":"","static":{"values":["botkube-plugins-default"]},"type":"Static"}` | Static impersonation for a given username and groups. | -| [executors.k8s-default-tools.botkube/kubectl.context.rbac.group.prefix](./values.yaml#L486) | string | `""` | Prefix that will be applied to .static.value[*]. | -| [executors.k8s-default-tools.botkube/helm.context.rbac.group.prefix](./values.yaml#L486) | string | `""` | Prefix that will be applied to .static.value[*]. | -| [executors.k8s-default-tools.botkube/kubectl.context.rbac.group.static.values](./values.yaml#L489) | list | `["botkube-plugins-default"]` | Name of group.rbac.authorization.k8s.io the plugin will be bound to. | -| [executors.k8s-default-tools.botkube/helm.context.rbac.group.static.values](./values.yaml#L489) | list | `["botkube-plugins-default"]` | Name of group.rbac.authorization.k8s.io the plugin will be bound to. | -| [executors.k8s-default-tools.botkube/kubectl.context.rbac.user.prefix](./values.yaml#L493) | string | `""` | Prefix that will be applied to .static.value[*]. | -| [executors.k8s-default-tools.botkube/helm.context.rbac.user.prefix](./values.yaml#L493) | string | `""` | Prefix that will be applied to .static.value[*]. | -| [executors.k8s-default-tools.botkube/kubectl.context.rbac.user.static.value](./values.yaml#L496) | string | `"default"` | Name of user.rbac.authorization.k8s.io the plugin will be bound to. | -| [executors.k8s-default-tools.botkube/helm.context.rbac.user.static.value](./values.yaml#L496) | string | `"default"` | Name of user.rbac.authorization.k8s.io the plugin will be bound to. | -| [executors.k8s-default-tools.botkube/kubectl.config](./values.yaml#L504) | object | See the `values.yaml` file for full object including optional properties related to interactive builder. | Custom kubectl configuration. | -| [aliases](./values.yaml#L529) | object | See the `values.yaml` file for full object. | Custom aliases for given commands. The aliases are replaced with the underlying command before executing it. Aliases can replace a single word or multiple ones. For example, you can define a `k` alias for `kubectl`, or `kgp` for `kubectl get pods`. | -| [existingCommunicationsSecretName](./values.yaml#L549) | string | `""` | Configures existing Secret with communication settings. It MUST be in the `botkube` Namespace. To reload Botkube once it changes, add label `botkube.io/config-watch: "true"`. | -| [communications](./values.yaml#L556) | object | See the `values.yaml` file for full object. | Map of communication groups. Communication group contains settings for multiple communication platforms. The property name under `communications` object is an alias for a given configuration group. You can define multiple communication groups with different names. | -| [communications.default-group.socketSlack.enabled](./values.yaml#L561) | bool | `false` | If true, enables Slack bot. | -| [communications.default-group.socketSlack.channels](./values.yaml#L565) | object | `{"default":{"bindings":{"executors":["k8s-default-tools"],"sources":["k8s-err-events","k8s-recommendation-events"]},"name":"SLACK_CHANNEL"}}` | Map of configured channels. The property name under `channels` object is an alias for a given configuration. | -| [communications.default-group.socketSlack.channels.default.name](./values.yaml#L568) | string | `"SLACK_CHANNEL"` | Slack channel name without '#' prefix where you have added Botkube and want to receive notifications in. | -| [communications.default-group.socketSlack.channels.default.bindings.executors](./values.yaml#L571) | list | `["k8s-default-tools"]` | Executors configuration for a given channel. | -| [communications.default-group.socketSlack.channels.default.bindings.sources](./values.yaml#L574) | list | `["k8s-err-events","k8s-recommendation-events"]` | Notification sources configuration for a given channel. | -| [communications.default-group.socketSlack.botToken](./values.yaml#L579) | string | `""` | Slack bot token for your own Slack app. [Ref doc](https://api.slack.com/authentication/token-types). | -| [communications.default-group.socketSlack.appToken](./values.yaml#L582) | string | `""` | Slack app-level token for your own Slack app. [Ref doc](https://api.slack.com/authentication/token-types). | -| [communications.default-group.mattermost.enabled](./values.yaml#L586) | bool | `false` | If true, enables Mattermost bot. | -| [communications.default-group.mattermost.botName](./values.yaml#L588) | string | `"Botkube"` | User in Mattermost which belongs the specified Personal Access token. | -| [communications.default-group.mattermost.url](./values.yaml#L590) | string | `"MATTERMOST_SERVER_URL"` | The URL (including http/https schema) where Mattermost is running. e.g https://example.com:9243 | -| [communications.default-group.mattermost.token](./values.yaml#L592) | string | `"MATTERMOST_TOKEN"` | Personal Access token generated by Botkube user. | -| [communications.default-group.mattermost.team](./values.yaml#L594) | string | `"MATTERMOST_TEAM"` | The Mattermost Team name where Botkube is added. | -| [communications.default-group.mattermost.channels](./values.yaml#L598) | object | `{"default":{"bindings":{"executors":["k8s-default-tools"],"sources":["k8s-err-events","k8s-recommendation-events"]},"name":"MATTERMOST_CHANNEL","notification":{"disabled":false}}}` | Map of configured channels. The property name under `channels` object is an alias for a given configuration. | -| [communications.default-group.mattermost.channels.default.name](./values.yaml#L602) | string | `"MATTERMOST_CHANNEL"` | The Mattermost channel name for receiving Botkube alerts. The Botkube user needs to be added to it. | -| [communications.default-group.mattermost.channels.default.notification.disabled](./values.yaml#L605) | bool | `false` | If true, the notifications are not sent to the channel. They can be enabled with `@Botkube` command anytime. | -| [communications.default-group.mattermost.channels.default.bindings.executors](./values.yaml#L608) | list | `["k8s-default-tools"]` | Executors configuration for a given channel. | -| [communications.default-group.mattermost.channels.default.bindings.sources](./values.yaml#L611) | list | `["k8s-err-events","k8s-recommendation-events"]` | Notification sources configuration for a given channel. | -| [communications.default-group.teams.enabled](./values.yaml#L618) | bool | `false` | If true, enables MS Teams bot. | -| [communications.default-group.teams.botName](./values.yaml#L620) | string | `"Botkube"` | The Bot name set while registering Bot to MS Teams. | -| [communications.default-group.teams.appID](./values.yaml#L622) | string | `"APPLICATION_ID"` | The Botkube application ID generated while registering Bot to MS Teams. | -| [communications.default-group.teams.appPassword](./values.yaml#L624) | string | `"APPLICATION_PASSWORD"` | The Botkube application password generated while registering Bot to MS Teams. | -| [communications.default-group.teams.bindings.executors](./values.yaml#L627) | list | `["k8s-default-tools"]` | Executor bindings apply to all MS Teams channels where Botkube has access to. | -| [communications.default-group.teams.bindings.sources](./values.yaml#L630) | list | `["k8s-err-events","k8s-recommendation-events"]` | Source bindings apply to all channels which have notification turned on with `@Botkube enable notifications` command. | -| [communications.default-group.teams.messagePath](./values.yaml#L634) | string | `"/bots/teams"` | The path in endpoint URL provided while registering Botkube to MS Teams. | -| [communications.default-group.teams.port](./values.yaml#L636) | int | `3978` | The Service port for bot endpoint on Botkube container. | -| [communications.default-group.discord.enabled](./values.yaml#L641) | bool | `false` | If true, enables Discord bot. | -| [communications.default-group.discord.token](./values.yaml#L643) | string | `"DISCORD_TOKEN"` | Botkube Bot Token. | -| [communications.default-group.discord.botID](./values.yaml#L645) | string | `"DISCORD_BOT_ID"` | Botkube Application Client ID. | -| [communications.default-group.discord.channels](./values.yaml#L649) | object | `{"default":{"bindings":{"executors":["k8s-default-tools"],"sources":["k8s-err-events","k8s-recommendation-events"]},"id":"DISCORD_CHANNEL_ID","notification":{"disabled":false}}}` | Map of configured channels. The property name under `channels` object is an alias for a given configuration. | -| [communications.default-group.discord.channels.default.id](./values.yaml#L653) | string | `"DISCORD_CHANNEL_ID"` | Discord channel ID for receiving Botkube alerts. The Botkube user needs to be added to it. | -| [communications.default-group.discord.channels.default.notification.disabled](./values.yaml#L656) | bool | `false` | If true, the notifications are not sent to the channel. They can be enabled with `@Botkube` command anytime. | -| [communications.default-group.discord.channels.default.bindings.executors](./values.yaml#L659) | list | `["k8s-default-tools"]` | Executors configuration for a given channel. | -| [communications.default-group.discord.channels.default.bindings.sources](./values.yaml#L662) | list | `["k8s-err-events","k8s-recommendation-events"]` | Notification sources configuration for a given channel. | -| [communications.default-group.elasticsearch.enabled](./values.yaml#L669) | bool | `false` | If true, enables Elasticsearch. | -| [communications.default-group.elasticsearch.awsSigning.enabled](./values.yaml#L673) | bool | `false` | If true, enables awsSigning using IAM for Elasticsearch hosted on AWS. Make sure AWS environment variables are set. [Ref doc](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-envvars.html). | -| [communications.default-group.elasticsearch.awsSigning.awsRegion](./values.yaml#L675) | string | `"us-east-1"` | AWS region where Elasticsearch is deployed. | -| [communications.default-group.elasticsearch.awsSigning.roleArn](./values.yaml#L677) | string | `""` | AWS IAM Role arn to assume for credentials, use this only if you don't want to use the EC2 instance role or not running on AWS instance. | -| [communications.default-group.elasticsearch.server](./values.yaml#L679) | string | `"ELASTICSEARCH_ADDRESS"` | The server URL, e.g https://example.com:9243 | -| [communications.default-group.elasticsearch.username](./values.yaml#L681) | string | `"ELASTICSEARCH_USERNAME"` | Basic Auth username. | -| [communications.default-group.elasticsearch.password](./values.yaml#L683) | string | `"ELASTICSEARCH_PASSWORD"` | Basic Auth password. | -| [communications.default-group.elasticsearch.skipTLSVerify](./values.yaml#L686) | bool | `false` | If true, skips the verification of TLS certificate of the Elastic nodes. It's useful for clusters with self-signed certificates. | -| [communications.default-group.elasticsearch.indices](./values.yaml#L690) | object | `{"default":{"bindings":{"sources":["k8s-err-events","k8s-recommendation-events"]},"name":"botkube","replicas":0,"shards":1,"type":"botkube-event"}}` | Map of configured indices. The `indices` property name is an alias for a given configuration. | -| [communications.default-group.elasticsearch.indices.default.name](./values.yaml#L693) | string | `"botkube"` | Configures Elasticsearch index settings. | -| [communications.default-group.elasticsearch.indices.default.bindings.sources](./values.yaml#L699) | list | `["k8s-err-events","k8s-recommendation-events"]` | Notification sources configuration for a given index. | -| [communications.default-group.webhook.enabled](./values.yaml#L706) | bool | `false` | If true, enables Webhook. | -| [communications.default-group.webhook.url](./values.yaml#L708) | string | `"WEBHOOK_URL"` | The Webhook URL, e.g.: https://example.com:80 | -| [communications.default-group.webhook.bindings.sources](./values.yaml#L711) | list | `["k8s-err-events","k8s-recommendation-events"]` | Notification sources configuration for the webhook. | -| [communications.default-group.slack](./values.yaml#L721) | object | See the `values.yaml` file for full object. | Settings for deprecated Slack integration. **DEPRECATED:** Legacy Slack integration has been deprecated and removed from the Slack App Directory. Use `socketSlack` instead. Read more here: https://docs.botkube.io/installation/slack/ | -| [settings.clusterName](./values.yaml#L739) | string | `"not-configured"` | Cluster name to differentiate incoming messages. | -| [settings.lifecycleServer](./values.yaml#L742) | object | `{"enabled":true,"port":2113}` | Server configuration which exposes functionality related to the app lifecycle. | -| [settings.healthPort](./values.yaml#L745) | int | `2114` | | -| [settings.upgradeNotifier](./values.yaml#L747) | bool | `true` | If true, notifies about new Botkube releases. | -| [settings.log.level](./values.yaml#L751) | string | `"info"` | Sets one of the log levels. Allowed values: `info`, `warn`, `debug`, `error`, `fatal`, `panic`. | -| [settings.log.disableColors](./values.yaml#L753) | bool | `false` | If true, disable ANSI colors in logging. | -| [settings.systemConfigMap](./values.yaml#L756) | object | `{"name":"botkube-system"}` | Botkube's system ConfigMap where internal data is stored. | -| [settings.persistentConfig](./values.yaml#L761) | object | `{"runtime":{"configMap":{"annotations":{},"name":"botkube-runtime-config"},"fileName":"_runtime_state.yaml"},"startup":{"configMap":{"annotations":{},"name":"botkube-startup-config"},"fileName":"_startup_state.yaml"}}` | Persistent config contains ConfigMap where persisted configuration is stored. The persistent configuration is evaluated from both chart upgrade and Botkube commands used in runtime. | -| [ssl.enabled](./values.yaml#L776) | bool | `false` | If true, specify cert path in `config.ssl.cert` property or K8s Secret in `config.ssl.existingSecretName`. | -| [ssl.existingSecretName](./values.yaml#L782) | string | `""` | Using existing SSL Secret. It MUST be in `botkube` Namespace. | -| [ssl.cert](./values.yaml#L785) | string | `""` | SSL Certificate file e.g certs/my-cert.crt. | -| [service](./values.yaml#L788) | object | `{"name":"metrics","port":2112,"targetPort":2112}` | Configures Service settings for ServiceMonitor CR. | -| [ingress](./values.yaml#L795) | object | `{"annotations":{"kubernetes.io/ingress.class":"nginx"},"create":false,"host":"HOST","tls":{"enabled":false,"secretName":""}}` | Configures Ingress settings that exposes MS Teams endpoint. [Ref doc](https://kubernetes.io/docs/concepts/services-networking/ingress/#the-ingress-resource). | -| [serviceMonitor](./values.yaml#L806) | object | `{"enabled":false,"interval":"10s","labels":{},"path":"/metrics","port":"metrics"}` | Configures ServiceMonitor settings. [Ref doc](https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#servicemonitor). | -| [deployment.annotations](./values.yaml#L816) | object | `{}` | Extra annotations to pass to the Botkube Deployment. | -| [extraAnnotations](./values.yaml#L823) | object | `{}` | Extra annotations to pass to the Botkube Pod. | -| [extraLabels](./values.yaml#L825) | object | `{}` | Extra labels to pass to the Botkube Pod. | -| [priorityClassName](./values.yaml#L827) | string | `""` | Priority class name for the Botkube Pod. | -| [nameOverride](./values.yaml#L830) | string | `""` | Fully override "botkube.name" template. | -| [fullnameOverride](./values.yaml#L832) | string | `""` | Fully override "botkube.fullname" template. | -| [resources](./values.yaml#L838) | object | `{}` | The Botkube Pod resource request and limits. We usually recommend not to specify default resources and to leave this as a conscious choice for the user. This also increases chances charts run on environments with little resources, such as Minikube. [Ref docs](https://kubernetes.io/docs/user-guide/compute-resources/) | -| [extraEnv](./values.yaml#L850) | list | `[{"name":"LOG_LEVEL_SOURCE_BOTKUBE_KUBERNETES","value":"debug"}]` | Extra environment variables to pass to the Botkube container. [Ref docs](https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#environment-variables). | -| [extraVolumes](./values.yaml#L864) | list | `[]` | Extra volumes to pass to the Botkube container. Mount it later with extraVolumeMounts. [Ref docs](https://kubernetes.io/docs/reference/kubernetes-api/config-and-storage-resources/volume/#Volume). | -| [extraVolumeMounts](./values.yaml#L879) | list | `[]` | Extra volume mounts to pass to the Botkube container. [Ref docs](https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#volumes-1). | -| [nodeSelector](./values.yaml#L897) | object | `{}` | Node labels for Botkube Pod assignment. [Ref doc](https://kubernetes.io/docs/user-guide/node-selection/). | -| [tolerations](./values.yaml#L901) | list | `[]` | Tolerations for Botkube Pod assignment. [Ref doc](https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/). | -| [affinity](./values.yaml#L905) | object | `{}` | Affinity for Botkube Pod assignment. [Ref doc](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity). | -| [serviceAccount.create](./values.yaml#L909) | bool | `true` | If true, a ServiceAccount is automatically created. | -| [serviceAccount.name](./values.yaml#L912) | string | `""` | The name of the service account to use. If not set, a name is generated using the fullname template. | -| [serviceAccount.annotations](./values.yaml#L914) | object | `{}` | Extra annotations for the ServiceAccount. | -| [extraObjects](./values.yaml#L917) | list | `[]` | Extra Kubernetes resources to create. Helm templating is allowed as it is evaluated before creating the resources. | -| [analytics.disable](./values.yaml#L945) | bool | `false` | If true, sending anonymous analytics is disabled. To learn what date we collect, see [Privacy Policy](https://docs.botkube.io/privacy#privacy-policy). | -| [configWatcher.enabled](./values.yaml#L950) | bool | `true` | If true, restarts the Botkube Pod on config changes. | -| [configWatcher.tmpDir](./values.yaml#L952) | string | `"/tmp/watched-cfg/"` | Directory, where watched configuration resources are stored. | -| [configWatcher.initialSyncTimeout](./values.yaml#L955) | int | `0` | Timeout for the initial Config Watcher sync. If set to 0, waiting for Config Watcher sync will be skipped. In a result, configuration changes may not reload Botkube app during the first few seconds after Botkube startup. | -| [configWatcher.image.registry](./values.yaml#L958) | string | `"ghcr.io"` | Config watcher image registry. | -| [configWatcher.image.repository](./values.yaml#L960) | string | `"kubeshop/k8s-sidecar"` | Config watcher image repository. | -| [configWatcher.image.tag](./values.yaml#L962) | string | `"ignore-initial-events"` | Config watcher image tag. | -| [configWatcher.image.pullPolicy](./values.yaml#L964) | string | `"IfNotPresent"` | Config watcher image pull policy. | -| [plugins](./values.yaml#L967) | object | `{"cacheDir":"/tmp","repositories":{"botkube":{"url":"https://github.com/kubeshop/botkube/releases/download/v9.99.9-dev/plugins-index.yaml"}}}` | Configuration for Botkube executors and sources plugins. | -| [plugins.cacheDir](./values.yaml#L969) | string | `"/tmp"` | Directory, where downloaded plugins are cached. | -| [plugins.repositories](./values.yaml#L971) | object | `{"botkube":{"url":"https://github.com/kubeshop/botkube/releases/download/v9.99.9-dev/plugins-index.yaml"}}` | List of plugins repositories. | -| [plugins.repositories.botkube](./values.yaml#L973) | object | `{"url":"https://github.com/kubeshop/botkube/releases/download/v9.99.9-dev/plugins-index.yaml"}` | This repository serves officially supported Botkube plugins. | -| [config](./values.yaml#L977) | object | `{"provider":{"apiKey":"","endpoint":"https://api.botkube.io/graphql","identifier":""}}` | Configuration for synchronizing Botkube configuration. | -| [config.provider](./values.yaml#L979) | object | `{"apiKey":"","endpoint":"https://api.botkube.io/graphql","identifier":""}` | Base provider definition. | -| [config.provider.identifier](./values.yaml#L982) | string | `""` | Unique identifier for remote Botkube settings. If set to an empty string, Botkube won't fetch remote configuration. | -| [config.provider.endpoint](./values.yaml#L984) | string | `"https://api.botkube.io/graphql"` | Endpoint to fetch Botkube settings from. | -| [config.provider.apiKey](./values.yaml#L986) | string | `""` | Key passed as a `X-API-Key` header to the provider's endpoint. | +| [executors.k8s-default-tools.botkube/helm.context.rbac](./values.yaml#L122) | object | `{"group":{"prefix":"","static":{"values":["botkube-plugins-default"]},"type":"Static"},"user":{"prefix":"","static":{"value":"botkube-plugins-default"},"type":"Static"}}` | RBAC configuration for this plugin. | +| [sources.k8s-err-events.botkube/kubernetes.context.rbac](./values.yaml#L122) | object | `{"group":{"prefix":"","static":{"values":["botkube-plugins-default"]},"type":"Static"},"user":{"prefix":"","static":{"value":"botkube-plugins-default"},"type":"Static"}}` | RBAC configuration for this plugin. | +| [sources.k8s-err-with-logs-events.botkube/kubernetes.context.rbac](./values.yaml#L122) | object | `{"group":{"prefix":"","static":{"values":["botkube-plugins-default"]},"type":"Static"},"user":{"prefix":"","static":{"value":"botkube-plugins-default"},"type":"Static"}}` | RBAC configuration for this plugin. | +| [sources.k8s-all-events.botkube/kubernetes.context.rbac](./values.yaml#L122) | object | `{"group":{"prefix":"","static":{"values":["botkube-plugins-default"]},"type":"Static"},"user":{"prefix":"","static":{"value":"botkube-plugins-default"},"type":"Static"}}` | RBAC configuration for this plugin. | +| [sources.k8s-create-events.botkube/kubernetes.context.rbac](./values.yaml#L122) | object | `{"group":{"prefix":"","static":{"values":["botkube-plugins-default"]},"type":"Static"},"user":{"prefix":"","static":{"value":"botkube-plugins-default"},"type":"Static"}}` | RBAC configuration for this plugin. | +| [executors.k8s-default-tools.botkube/kubectl.context.rbac](./values.yaml#L122) | object | `{"group":{"prefix":"","static":{"values":["botkube-plugins-default"]},"type":"Static"},"user":{"prefix":"","static":{"value":"botkube-plugins-default"},"type":"Static"}}` | RBAC configuration for this plugin. | +| [sources.k8s-recommendation-events.botkube/kubernetes.context.rbac](./values.yaml#L122) | object | `{"group":{"prefix":"","static":{"values":["botkube-plugins-default"]},"type":"Static"},"user":{"prefix":"","static":{"value":"botkube-plugins-default"},"type":"Static"}}` | RBAC configuration for this plugin. | +| [sources.k8s-err-with-logs-events.botkube/kubernetes.context.rbac.group](./values.yaml#L124) | object | `{"prefix":"","static":{"values":["botkube-plugins-default"]},"type":"Static"}` | Static impersonation for a given username and groups. | +| [executors.k8s-default-tools.botkube/helm.context.rbac.group](./values.yaml#L124) | object | `{"prefix":"","static":{"values":["botkube-plugins-default"]},"type":"Static"}` | Static impersonation for a given username and groups. | +| [sources.k8s-create-events.botkube/kubernetes.context.rbac.group](./values.yaml#L124) | object | `{"prefix":"","static":{"values":["botkube-plugins-default"]},"type":"Static"}` | Static impersonation for a given username and groups. | +| [sources.k8s-err-events.botkube/kubernetes.context.rbac.group](./values.yaml#L124) | object | `{"prefix":"","static":{"values":["botkube-plugins-default"]},"type":"Static"}` | Static impersonation for a given username and groups. | +| [sources.k8s-all-events.botkube/kubernetes.context.rbac.group](./values.yaml#L124) | object | `{"prefix":"","static":{"values":["botkube-plugins-default"]},"type":"Static"}` | Static impersonation for a given username and groups. | +| [sources.k8s-recommendation-events.botkube/kubernetes.context.rbac.group](./values.yaml#L124) | object | `{"prefix":"","static":{"values":["botkube-plugins-default"]},"type":"Static"}` | Static impersonation for a given username and groups. | +| [executors.k8s-default-tools.botkube/kubectl.context.rbac.group](./values.yaml#L124) | object | `{"prefix":"","static":{"values":["botkube-plugins-default"]},"type":"Static"}` | Static impersonation for a given username and groups. | +| [sources.k8s-err-with-logs-events.botkube/kubernetes.context.rbac.group.prefix](./values.yaml#L127) | string | `""` | Prefix that will be applied to .static.value[*]. | +| [executors.k8s-default-tools.botkube/kubectl.context.rbac.group.prefix](./values.yaml#L127) | string | `""` | Prefix that will be applied to .static.value[*]. | +| [sources.k8s-all-events.botkube/kubernetes.context.rbac.group.prefix](./values.yaml#L127) | string | `""` | Prefix that will be applied to .static.value[*]. | +| [sources.k8s-recommendation-events.botkube/kubernetes.context.rbac.group.prefix](./values.yaml#L127) | string | `""` | Prefix that will be applied to .static.value[*]. | +| [sources.k8s-err-events.botkube/kubernetes.context.rbac.group.prefix](./values.yaml#L127) | string | `""` | Prefix that will be applied to .static.value[*]. | +| [sources.k8s-create-events.botkube/kubernetes.context.rbac.group.prefix](./values.yaml#L127) | string | `""` | Prefix that will be applied to .static.value[*]. | +| [executors.k8s-default-tools.botkube/helm.context.rbac.group.prefix](./values.yaml#L127) | string | `""` | Prefix that will be applied to .static.value[*]. | +| [sources.k8s-recommendation-events.botkube/kubernetes.context.rbac.group.static.values](./values.yaml#L130) | list | `["botkube-plugins-default"]` | Name of group.rbac.authorization.k8s.io the plugin will be bound to. | +| [sources.k8s-create-events.botkube/kubernetes.context.rbac.group.static.values](./values.yaml#L130) | list | `["botkube-plugins-default"]` | Name of group.rbac.authorization.k8s.io the plugin will be bound to. | +| [sources.k8s-err-with-logs-events.botkube/kubernetes.context.rbac.group.static.values](./values.yaml#L130) | list | `["botkube-plugins-default"]` | Name of group.rbac.authorization.k8s.io the plugin will be bound to. | +| [sources.k8s-err-events.botkube/kubernetes.context.rbac.group.static.values](./values.yaml#L130) | list | `["botkube-plugins-default"]` | Name of group.rbac.authorization.k8s.io the plugin will be bound to. | +| [executors.k8s-default-tools.botkube/helm.context.rbac.group.static.values](./values.yaml#L130) | list | `["botkube-plugins-default"]` | Name of group.rbac.authorization.k8s.io the plugin will be bound to. | +| [sources.k8s-all-events.botkube/kubernetes.context.rbac.group.static.values](./values.yaml#L130) | list | `["botkube-plugins-default"]` | Name of group.rbac.authorization.k8s.io the plugin will be bound to. | +| [executors.k8s-default-tools.botkube/kubectl.context.rbac.group.static.values](./values.yaml#L130) | list | `["botkube-plugins-default"]` | Name of group.rbac.authorization.k8s.io the plugin will be bound to. | +| [sources.k8s-err-events.botkube/kubernetes.context.rbac.user.prefix](./values.yaml#L134) | string | `""` | Prefix that will be applied to .static.value[*]. | +| [sources.k8s-all-events.botkube/kubernetes.context.rbac.user.prefix](./values.yaml#L134) | string | `""` | Prefix that will be applied to .static.value[*]. | +| [executors.k8s-default-tools.botkube/helm.context.rbac.user.prefix](./values.yaml#L134) | string | `""` | Prefix that will be applied to .static.value[*]. | +| [sources.k8s-err-with-logs-events.botkube/kubernetes.context.rbac.user.prefix](./values.yaml#L134) | string | `""` | Prefix that will be applied to .static.value[*]. | +| [executors.k8s-default-tools.botkube/kubectl.context.rbac.user.prefix](./values.yaml#L134) | string | `""` | Prefix that will be applied to .static.value[*]. | +| [sources.k8s-recommendation-events.botkube/kubernetes.context.rbac.user.prefix](./values.yaml#L134) | string | `""` | Prefix that will be applied to .static.value[*]. | +| [sources.k8s-create-events.botkube/kubernetes.context.rbac.user.prefix](./values.yaml#L134) | string | `""` | Prefix that will be applied to .static.value[*]. | +| [sources.k8s-all-events.botkube/kubernetes.context.rbac.user.static.value](./values.yaml#L137) | string | `"botkube-plugins-default"` | Name of user.rbac.authorization.k8s.io the plugin will be bound to. | +| [executors.k8s-default-tools.botkube/kubectl.context.rbac.user.static.value](./values.yaml#L137) | string | `"botkube-plugins-default"` | Name of user.rbac.authorization.k8s.io the plugin will be bound to. | +| [sources.k8s-err-with-logs-events.botkube/kubernetes.context.rbac.user.static.value](./values.yaml#L137) | string | `"botkube-plugins-default"` | Name of user.rbac.authorization.k8s.io the plugin will be bound to. | +| [sources.k8s-create-events.botkube/kubernetes.context.rbac.user.static.value](./values.yaml#L137) | string | `"botkube-plugins-default"` | Name of user.rbac.authorization.k8s.io the plugin will be bound to. | +| [executors.k8s-default-tools.botkube/helm.context.rbac.user.static.value](./values.yaml#L137) | string | `"botkube-plugins-default"` | Name of user.rbac.authorization.k8s.io the plugin will be bound to. | +| [sources.k8s-err-events.botkube/kubernetes.context.rbac.user.static.value](./values.yaml#L137) | string | `"botkube-plugins-default"` | Name of user.rbac.authorization.k8s.io the plugin will be bound to. | +| [sources.k8s-recommendation-events.botkube/kubernetes.context.rbac.user.static.value](./values.yaml#L137) | string | `"botkube-plugins-default"` | Name of user.rbac.authorization.k8s.io the plugin will be bound to. | +| [sources.k8s-recommendation-events.botkube/kubernetes.config.recommendations](./values.yaml#L144) | object | `{"ingress":{"backendServiceValid":true,"tlsSecretValid":true},"pod":{"labelsSet":true,"noLatestImageTag":true}}` | Describes configuration for various recommendation insights. | +| [sources.k8s-recommendation-events.botkube/kubernetes.config.recommendations.pod](./values.yaml#L146) | object | `{"labelsSet":true,"noLatestImageTag":true}` | Recommendations for Pod Kubernetes resource. | +| [sources.k8s-recommendation-events.botkube/kubernetes.config.recommendations.pod.noLatestImageTag](./values.yaml#L148) | bool | `true` | If true, notifies about Pod containers that use `latest` tag for images. | +| [sources.k8s-recommendation-events.botkube/kubernetes.config.recommendations.pod.labelsSet](./values.yaml#L150) | bool | `true` | If true, notifies about Pod resources created without labels. | +| [sources.k8s-recommendation-events.botkube/kubernetes.config.recommendations.ingress](./values.yaml#L152) | object | `{"backendServiceValid":true,"tlsSecretValid":true}` | Recommendations for Ingress Kubernetes resource. | +| [sources.k8s-recommendation-events.botkube/kubernetes.config.recommendations.ingress.backendServiceValid](./values.yaml#L154) | bool | `true` | If true, notifies about Ingress resources with invalid backend service reference. | +| [sources.k8s-recommendation-events.botkube/kubernetes.config.recommendations.ingress.tlsSecretValid](./values.yaml#L156) | bool | `true` | If true, notifies about Ingress resources with invalid TLS secret reference. | +| [sources.k8s-all-events.botkube/kubernetes](./values.yaml#L162) | object | See the `values.yaml` file for full object. | Describes Kubernetes source configuration. | +| [sources.k8s-all-events.botkube/kubernetes.config.filters](./values.yaml#L168) | object | See the `values.yaml` file for full object. | Filter settings for various sources. | +| [sources.k8s-all-events.botkube/kubernetes.config.filters.objectAnnotationChecker](./values.yaml#L170) | bool | `true` | If true, enables support for `botkube.io/disable` resource annotation. | +| [sources.k8s-all-events.botkube/kubernetes.config.filters.nodeEventsChecker](./values.yaml#L172) | bool | `true` | If true, filters out Node-related events that are not important. | +| [sources.k8s-all-events.botkube/kubernetes.config.namespaces](./values.yaml#L176) | object | `{"include":[".*"]}` | Describes namespaces for every Kubernetes resources you want to watch or exclude. These namespaces are applied to every resource specified in the resources list. However, every specified resource can override this by using its own namespaces object. | +| [sources.k8s-err-events.botkube/kubernetes.config.namespaces.include](./values.yaml#L180) | list | `[".*"]` | Include contains a list of allowed Namespaces. It can also contain regex expressions: `- ".*"` - to specify all Namespaces. | +| [sources.k8s-create-events.botkube/kubernetes.config.namespaces.include](./values.yaml#L180) | list | `[".*"]` | Include contains a list of allowed Namespaces. It can also contain regex expressions: `- ".*"` - to specify all Namespaces. | +| [sources.k8s-all-events.botkube/kubernetes.config.namespaces.include](./values.yaml#L180) | list | `[".*"]` | Include contains a list of allowed Namespaces. It can also contain regex expressions: `- ".*"` - to specify all Namespaces. | +| [sources.k8s-err-with-logs-events.botkube/kubernetes.config.namespaces.include](./values.yaml#L180) | list | `[".*"]` | Include contains a list of allowed Namespaces. It can also contain regex expressions: `- ".*"` - to specify all Namespaces. | +| [sources.k8s-all-events.botkube/kubernetes.config.event](./values.yaml#L190) | object | `{"message":{"exclude":[],"include":[]},"reason":{"exclude":[],"include":[]},"types":["create","delete","error"]}` | Describes event constraints for Kubernetes resources. These constraints are applied for every resource specified in the `resources` list, unless they are overridden by the resource's own `events` object. | +| [sources.k8s-all-events.botkube/kubernetes.config.event.types](./values.yaml#L192) | list | `["create","delete","error"]` | Lists all event types to be watched. | +| [sources.k8s-all-events.botkube/kubernetes.config.event.reason](./values.yaml#L198) | object | `{"exclude":[],"include":[]}` | Optional list of exact values or regex patterns to filter events by event reason. Skipped, if both include/exclude lists are empty. | +| [sources.k8s-all-events.botkube/kubernetes.config.event.reason.include](./values.yaml#L200) | list | `[]` | Include contains a list of allowed values. It can also contain regex expressions. | +| [sources.k8s-all-events.botkube/kubernetes.config.event.reason.exclude](./values.yaml#L203) | list | `[]` | Exclude contains a list of values to be ignored even if allowed by Include. It can also contain regex expressions. Exclude list is checked before the Include list. | +| [sources.k8s-all-events.botkube/kubernetes.config.event.message](./values.yaml#L206) | object | `{"exclude":[],"include":[]}` | Optional list of exact values or regex patterns to filter event by event message. Skipped, if both include/exclude lists are empty. If a given event has multiple messages, it is considered a match if any of the messages match the constraints. | +| [sources.k8s-all-events.botkube/kubernetes.config.event.message.include](./values.yaml#L208) | list | `[]` | Include contains a list of allowed values. It can also contain regex expressions. | +| [sources.k8s-all-events.botkube/kubernetes.config.event.message.exclude](./values.yaml#L211) | list | `[]` | Exclude contains a list of values to be ignored even if allowed by Include. It can also contain regex expressions. Exclude list is checked before the Include list. | +| [sources.k8s-all-events.botkube/kubernetes.config.annotations](./values.yaml#L215) | object | `{}` | Filters Kubernetes resources to watch by annotations. Each resource needs to have all the specified annotations. Regex expressions are not supported. | +| [sources.k8s-all-events.botkube/kubernetes.config.labels](./values.yaml#L218) | object | `{}` | Filters Kubernetes resources to watch by labels. Each resource needs to have all the specified labels. Regex expressions are not supported. | +| [sources.k8s-all-events.botkube/kubernetes.config.resources](./values.yaml#L225) | list | See the `values.yaml` file for full object. | Describes the Kubernetes resources to watch. Resources are identified by its type in `{group}/{version}/{kind (plural)}` format. Examples: `apps/v1/deployments`, `v1/pods`. Each resource can override the namespaces and event configuration by using dedicated `event` and `namespaces` field. Also, each resource can specify its own `annotations`, `labels` and `name` regex. | +| [sources.k8s-err-events.botkube/kubernetes](./values.yaml#L335) | object | See the `values.yaml` file for full object. | Describes Kubernetes source configuration. | +| [sources.k8s-err-events.botkube/kubernetes.config.namespaces](./values.yaml#L342) | object | `{"include":[".*"]}` | Describes namespaces for every Kubernetes resources you want to watch or exclude. These namespaces are applied to every resource specified in the resources list. However, every specified resource can override this by using its own namespaces object. | +| [sources.k8s-err-events.botkube/kubernetes.config.event](./values.yaml#L346) | object | `{"types":["error"]}` | Describes event constraints for Kubernetes resources. These constraints are applied for every resource specified in the `resources` list, unless they are overridden by the resource's own `events` object. | +| [sources.k8s-err-events.botkube/kubernetes.config.event.types](./values.yaml#L348) | list | `["error"]` | Lists all event types to be watched. | +| [sources.k8s-err-events.botkube/kubernetes.config.resources](./values.yaml#L353) | list | See the `values.yaml` file for full object. | Describes the Kubernetes resources you want to watch. | +| [sources.k8s-err-with-logs-events.botkube/kubernetes](./values.yaml#L375) | object | See the `values.yaml` file for full object. | Describes Kubernetes source configuration. | +| [sources.k8s-err-with-logs-events.botkube/kubernetes.config.namespaces](./values.yaml#L382) | object | `{"include":[".*"]}` | Describes namespaces for every Kubernetes resources you want to watch or exclude. These namespaces are applied to every resource specified in the resources list. However, every specified resource can override this by using its own namespaces object. | +| [sources.k8s-err-with-logs-events.botkube/kubernetes.config.event](./values.yaml#L386) | object | `{"types":["error"]}` | Describes event constraints for Kubernetes resources. These constraints are applied for every resource specified in the `resources` list, unless they are overridden by the resource's own `events` object. | +| [sources.k8s-err-with-logs-events.botkube/kubernetes.config.event.types](./values.yaml#L388) | list | `["error"]` | Lists all event types to be watched. | +| [sources.k8s-err-with-logs-events.botkube/kubernetes.config.resources](./values.yaml#L393) | list | See the `values.yaml` file for full object. | Describes the Kubernetes resources you want to watch. | +| [sources.k8s-create-events.botkube/kubernetes](./values.yaml#L406) | object | See the `values.yaml` file for full object. | Describes Kubernetes source configuration. | +| [sources.k8s-create-events.botkube/kubernetes.config.namespaces](./values.yaml#L413) | object | `{"include":[".*"]}` | Describes namespaces for every Kubernetes resources you want to watch or exclude. These namespaces are applied to every resource specified in the resources list. However, every specified resource can override this by using its own namespaces object. | +| [sources.k8s-create-events.botkube/kubernetes.config.event](./values.yaml#L417) | object | `{"types":["create"]}` | Describes event constraints for Kubernetes resources. These constraints are applied for every resource specified in the `resources` list, unless they are overridden by the resource's own `events` object. | +| [sources.k8s-create-events.botkube/kubernetes.config.event.types](./values.yaml#L419) | list | `["create"]` | Lists all event types to be watched. | +| [sources.k8s-create-events.botkube/kubernetes.config.resources](./values.yaml#L424) | list | See the `values.yaml` file for full object. | Describes the Kubernetes resources you want to watch. | +| [sources.prometheus.botkube/prometheus.enabled](./values.yaml#L441) | bool | `false` | If true, enables `prometheus` source. | +| [sources.prometheus.botkube/prometheus.config.url](./values.yaml#L444) | string | `"http://localhost:9090"` | Prometheus endpoint without api version and resource. | +| [sources.prometheus.botkube/prometheus.config.ignoreOldAlerts](./values.yaml#L446) | bool | `true` | If set as true, Prometheus source plugin will not send alerts that is created before plugin start time. | +| [sources.prometheus.botkube/prometheus.config.alertStates](./values.yaml#L448) | list | `["firing","pending","inactive"]` | Only the alerts that have state provided in this config will be sent as notification. https://pkg.go.dev/github.com/prometheus/prometheus/rules#AlertState | +| [sources.prometheus.botkube/prometheus.config.log](./values.yaml#L450) | object | `{"level":"info"}` | Logging configuration | +| [sources.prometheus.botkube/prometheus.config.log.level](./values.yaml#L452) | string | `"info"` | Log level | +| [executors](./values.yaml#L460) | object | See the `values.yaml` file for full object. | Map of executors. Executor contains configuration for running `kubectl` commands. The property name under `executors` is an alias for a given configuration. You can define multiple executor configurations with different names. Key name is used as a binding reference. | +| [executors.k8s-default-tools.kubectl.namespaces.include](./values.yaml#L469) | list | `[".*"]` | List of allowed Kubernetes Namespaces for command execution. It can also contain a regex expressions: `- ".*"` - to specify all Namespaces. | +| [executors.k8s-default-tools.kubectl.namespaces.exclude](./values.yaml#L474) | list | `[]` | List of ignored Kubernetes Namespace. It can also contain a regex expressions: `- "test-.*"` - to specify all Namespaces. | +| [executors.k8s-default-tools.kubectl.enabled](./values.yaml#L476) | bool | `false` | If true, enables `kubectl` commands execution. | +| [executors.k8s-default-tools.kubectl.commands.verbs](./values.yaml#L480) | list | `["api-resources","api-versions","cluster-info","describe","explain","get","logs","top"]` | Configures which `kubectl` methods are allowed. | +| [executors.k8s-default-tools.kubectl.commands.resources](./values.yaml#L482) | list | `["deployments","pods","namespaces","daemonsets","statefulsets","storageclasses","nodes","configmaps","services","ingresses"]` | Configures which K8s resource are allowed. | +| [executors.k8s-default-tools.kubectl.defaultNamespace](./values.yaml#L484) | string | `"default"` | Configures the default Namespace for executing Botkube `kubectl` commands. If not set, uses the 'default'. | +| [executors.k8s-default-tools.kubectl.restrictAccess](./values.yaml#L486) | bool | `false` | If true, enables commands execution from configured channel only. | +| [executors.k8s-default-tools.botkube/helm.enabled](./values.yaml#L492) | bool | `false` | If true, enables `helm` commands execution. | +| [executors.k8s-default-tools.botkube/helm.config.helmDriver](./values.yaml#L497) | string | `"secret"` | Allowed values are configmap, secret, memory. | +| [executors.k8s-default-tools.botkube/helm.config.helmConfigDir](./values.yaml#L499) | string | `"/tmp/helm/"` | Location for storing Helm configuration. | +| [executors.k8s-default-tools.botkube/helm.config.helmCacheDir](./values.yaml#L501) | string | `"/tmp/helm/.cache"` | Location for storing cached files. Must be under the Helm config directory. | +| [executors.k8s-default-tools.botkube/kubectl.config](./values.yaml#L510) | object | See the `values.yaml` file for full object including optional properties related to interactive builder. | Custom kubectl configuration. | +| [aliases](./values.yaml#L535) | object | See the `values.yaml` file for full object. | Custom aliases for given commands. The aliases are replaced with the underlying command before executing it. Aliases can replace a single word or multiple ones. For example, you can define a `k` alias for `kubectl`, or `kgp` for `kubectl get pods`. | +| [existingCommunicationsSecretName](./values.yaml#L555) | string | `""` | Configures existing Secret with communication settings. It MUST be in the `botkube` Namespace. To reload Botkube once it changes, add label `botkube.io/config-watch: "true"`. | +| [communications](./values.yaml#L562) | object | See the `values.yaml` file for full object. | Map of communication groups. Communication group contains settings for multiple communication platforms. The property name under `communications` object is an alias for a given configuration group. You can define multiple communication groups with different names. | +| [communications.default-group.socketSlack.enabled](./values.yaml#L567) | bool | `false` | If true, enables Slack bot. | +| [communications.default-group.socketSlack.channels](./values.yaml#L571) | object | `{"default":{"bindings":{"executors":["k8s-default-tools"],"sources":["k8s-err-events","k8s-recommendation-events"]},"name":"SLACK_CHANNEL"}}` | Map of configured channels. The property name under `channels` object is an alias for a given configuration. | +| [communications.default-group.socketSlack.channels.default.name](./values.yaml#L574) | string | `"SLACK_CHANNEL"` | Slack channel name without '#' prefix where you have added Botkube and want to receive notifications in. | +| [communications.default-group.socketSlack.channels.default.bindings.executors](./values.yaml#L577) | list | `["k8s-default-tools"]` | Executors configuration for a given channel. | +| [communications.default-group.socketSlack.channels.default.bindings.sources](./values.yaml#L580) | list | `["k8s-err-events","k8s-recommendation-events"]` | Notification sources configuration for a given channel. | +| [communications.default-group.socketSlack.botToken](./values.yaml#L585) | string | `""` | Slack bot token for your own Slack app. [Ref doc](https://api.slack.com/authentication/token-types). | +| [communications.default-group.socketSlack.appToken](./values.yaml#L588) | string | `""` | Slack app-level token for your own Slack app. [Ref doc](https://api.slack.com/authentication/token-types). | +| [communications.default-group.mattermost.enabled](./values.yaml#L592) | bool | `false` | If true, enables Mattermost bot. | +| [communications.default-group.mattermost.botName](./values.yaml#L594) | string | `"Botkube"` | User in Mattermost which belongs the specified Personal Access token. | +| [communications.default-group.mattermost.url](./values.yaml#L596) | string | `"MATTERMOST_SERVER_URL"` | The URL (including http/https schema) where Mattermost is running. e.g https://example.com:9243 | +| [communications.default-group.mattermost.token](./values.yaml#L598) | string | `"MATTERMOST_TOKEN"` | Personal Access token generated by Botkube user. | +| [communications.default-group.mattermost.team](./values.yaml#L600) | string | `"MATTERMOST_TEAM"` | The Mattermost Team name where Botkube is added. | +| [communications.default-group.mattermost.channels](./values.yaml#L604) | object | `{"default":{"bindings":{"executors":["k8s-default-tools"],"sources":["k8s-err-events","k8s-recommendation-events"]},"name":"MATTERMOST_CHANNEL","notification":{"disabled":false}}}` | Map of configured channels. The property name under `channels` object is an alias for a given configuration. | +| [communications.default-group.mattermost.channels.default.name](./values.yaml#L608) | string | `"MATTERMOST_CHANNEL"` | The Mattermost channel name for receiving Botkube alerts. The Botkube user needs to be added to it. | +| [communications.default-group.mattermost.channels.default.notification.disabled](./values.yaml#L611) | bool | `false` | If true, the notifications are not sent to the channel. They can be enabled with `@Botkube` command anytime. | +| [communications.default-group.mattermost.channels.default.bindings.executors](./values.yaml#L614) | list | `["k8s-default-tools"]` | Executors configuration for a given channel. | +| [communications.default-group.mattermost.channels.default.bindings.sources](./values.yaml#L617) | list | `["k8s-err-events","k8s-recommendation-events"]` | Notification sources configuration for a given channel. | +| [communications.default-group.teams.enabled](./values.yaml#L624) | bool | `false` | If true, enables MS Teams bot. | +| [communications.default-group.teams.botName](./values.yaml#L626) | string | `"Botkube"` | The Bot name set while registering Bot to MS Teams. | +| [communications.default-group.teams.appID](./values.yaml#L628) | string | `"APPLICATION_ID"` | The Botkube application ID generated while registering Bot to MS Teams. | +| [communications.default-group.teams.appPassword](./values.yaml#L630) | string | `"APPLICATION_PASSWORD"` | The Botkube application password generated while registering Bot to MS Teams. | +| [communications.default-group.teams.bindings.executors](./values.yaml#L633) | list | `["k8s-default-tools"]` | Executor bindings apply to all MS Teams channels where Botkube has access to. | +| [communications.default-group.teams.bindings.sources](./values.yaml#L636) | list | `["k8s-err-events","k8s-recommendation-events"]` | Source bindings apply to all channels which have notification turned on with `@Botkube enable notifications` command. | +| [communications.default-group.teams.messagePath](./values.yaml#L640) | string | `"/bots/teams"` | The path in endpoint URL provided while registering Botkube to MS Teams. | +| [communications.default-group.teams.port](./values.yaml#L642) | int | `3978` | The Service port for bot endpoint on Botkube container. | +| [communications.default-group.discord.enabled](./values.yaml#L647) | bool | `false` | If true, enables Discord bot. | +| [communications.default-group.discord.token](./values.yaml#L649) | string | `"DISCORD_TOKEN"` | Botkube Bot Token. | +| [communications.default-group.discord.botID](./values.yaml#L651) | string | `"DISCORD_BOT_ID"` | Botkube Application Client ID. | +| [communications.default-group.discord.channels](./values.yaml#L655) | object | `{"default":{"bindings":{"executors":["k8s-default-tools"],"sources":["k8s-err-events","k8s-recommendation-events"]},"id":"DISCORD_CHANNEL_ID","notification":{"disabled":false}}}` | Map of configured channels. The property name under `channels` object is an alias for a given configuration. | +| [communications.default-group.discord.channels.default.id](./values.yaml#L659) | string | `"DISCORD_CHANNEL_ID"` | Discord channel ID for receiving Botkube alerts. The Botkube user needs to be added to it. | +| [communications.default-group.discord.channels.default.notification.disabled](./values.yaml#L662) | bool | `false` | If true, the notifications are not sent to the channel. They can be enabled with `@Botkube` command anytime. | +| [communications.default-group.discord.channels.default.bindings.executors](./values.yaml#L665) | list | `["k8s-default-tools"]` | Executors configuration for a given channel. | +| [communications.default-group.discord.channels.default.bindings.sources](./values.yaml#L668) | list | `["k8s-err-events","k8s-recommendation-events"]` | Notification sources configuration for a given channel. | +| [communications.default-group.elasticsearch.enabled](./values.yaml#L675) | bool | `false` | If true, enables Elasticsearch. | +| [communications.default-group.elasticsearch.awsSigning.enabled](./values.yaml#L679) | bool | `false` | If true, enables awsSigning using IAM for Elasticsearch hosted on AWS. Make sure AWS environment variables are set. [Ref doc](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-envvars.html). | +| [communications.default-group.elasticsearch.awsSigning.awsRegion](./values.yaml#L681) | string | `"us-east-1"` | AWS region where Elasticsearch is deployed. | +| [communications.default-group.elasticsearch.awsSigning.roleArn](./values.yaml#L683) | string | `""` | AWS IAM Role arn to assume for credentials, use this only if you don't want to use the EC2 instance role or not running on AWS instance. | +| [communications.default-group.elasticsearch.server](./values.yaml#L685) | string | `"ELASTICSEARCH_ADDRESS"` | The server URL, e.g https://example.com:9243 | +| [communications.default-group.elasticsearch.username](./values.yaml#L687) | string | `"ELASTICSEARCH_USERNAME"` | Basic Auth username. | +| [communications.default-group.elasticsearch.password](./values.yaml#L689) | string | `"ELASTICSEARCH_PASSWORD"` | Basic Auth password. | +| [communications.default-group.elasticsearch.skipTLSVerify](./values.yaml#L692) | bool | `false` | If true, skips the verification of TLS certificate of the Elastic nodes. It's useful for clusters with self-signed certificates. | +| [communications.default-group.elasticsearch.indices](./values.yaml#L696) | object | `{"default":{"bindings":{"sources":["k8s-err-events","k8s-recommendation-events"]},"name":"botkube","replicas":0,"shards":1,"type":"botkube-event"}}` | Map of configured indices. The `indices` property name is an alias for a given configuration. | +| [communications.default-group.elasticsearch.indices.default.name](./values.yaml#L699) | string | `"botkube"` | Configures Elasticsearch index settings. | +| [communications.default-group.elasticsearch.indices.default.bindings.sources](./values.yaml#L705) | list | `["k8s-err-events","k8s-recommendation-events"]` | Notification sources configuration for a given index. | +| [communications.default-group.webhook.enabled](./values.yaml#L712) | bool | `false` | If true, enables Webhook. | +| [communications.default-group.webhook.url](./values.yaml#L714) | string | `"WEBHOOK_URL"` | The Webhook URL, e.g.: https://example.com:80 | +| [communications.default-group.webhook.bindings.sources](./values.yaml#L717) | list | `["k8s-err-events","k8s-recommendation-events"]` | Notification sources configuration for the webhook. | +| [communications.default-group.slack](./values.yaml#L727) | object | See the `values.yaml` file for full object. | Settings for deprecated Slack integration. **DEPRECATED:** Legacy Slack integration has been deprecated and removed from the Slack App Directory. Use `socketSlack` instead. Read more here: https://docs.botkube.io/installation/slack/ | +| [settings.clusterName](./values.yaml#L745) | string | `"not-configured"` | Cluster name to differentiate incoming messages. | +| [settings.lifecycleServer](./values.yaml#L748) | object | `{"enabled":true,"port":2113}` | Server configuration which exposes functionality related to the app lifecycle. | +| [settings.healthPort](./values.yaml#L751) | int | `2114` | | +| [settings.upgradeNotifier](./values.yaml#L753) | bool | `true` | If true, notifies about new Botkube releases. | +| [settings.log.level](./values.yaml#L757) | string | `"info"` | Sets one of the log levels. Allowed values: `info`, `warn`, `debug`, `error`, `fatal`, `panic`. | +| [settings.log.disableColors](./values.yaml#L759) | bool | `false` | If true, disable ANSI colors in logging. | +| [settings.systemConfigMap](./values.yaml#L762) | object | `{"name":"botkube-system"}` | Botkube's system ConfigMap where internal data is stored. | +| [settings.persistentConfig](./values.yaml#L767) | object | `{"runtime":{"configMap":{"annotations":{},"name":"botkube-runtime-config"},"fileName":"_runtime_state.yaml"},"startup":{"configMap":{"annotations":{},"name":"botkube-startup-config"},"fileName":"_startup_state.yaml"}}` | Persistent config contains ConfigMap where persisted configuration is stored. The persistent configuration is evaluated from both chart upgrade and Botkube commands used in runtime. | +| [ssl.enabled](./values.yaml#L782) | bool | `false` | If true, specify cert path in `config.ssl.cert` property or K8s Secret in `config.ssl.existingSecretName`. | +| [ssl.existingSecretName](./values.yaml#L788) | string | `""` | Using existing SSL Secret. It MUST be in `botkube` Namespace. | +| [ssl.cert](./values.yaml#L791) | string | `""` | SSL Certificate file e.g certs/my-cert.crt. | +| [service](./values.yaml#L794) | object | `{"name":"metrics","port":2112,"targetPort":2112}` | Configures Service settings for ServiceMonitor CR. | +| [ingress](./values.yaml#L801) | object | `{"annotations":{"kubernetes.io/ingress.class":"nginx"},"create":false,"host":"HOST","tls":{"enabled":false,"secretName":""}}` | Configures Ingress settings that exposes MS Teams endpoint. [Ref doc](https://kubernetes.io/docs/concepts/services-networking/ingress/#the-ingress-resource). | +| [serviceMonitor](./values.yaml#L812) | object | `{"enabled":false,"interval":"10s","labels":{},"path":"/metrics","port":"metrics"}` | Configures ServiceMonitor settings. [Ref doc](https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#servicemonitor). | +| [deployment.annotations](./values.yaml#L822) | object | `{}` | Extra annotations to pass to the Botkube Deployment. | +| [extraAnnotations](./values.yaml#L829) | object | `{}` | Extra annotations to pass to the Botkube Pod. | +| [extraLabels](./values.yaml#L831) | object | `{}` | Extra labels to pass to the Botkube Pod. | +| [priorityClassName](./values.yaml#L833) | string | `""` | Priority class name for the Botkube Pod. | +| [nameOverride](./values.yaml#L836) | string | `""` | Fully override "botkube.name" template. | +| [fullnameOverride](./values.yaml#L838) | string | `""` | Fully override "botkube.fullname" template. | +| [resources](./values.yaml#L844) | object | `{}` | The Botkube Pod resource request and limits. We usually recommend not to specify default resources and to leave this as a conscious choice for the user. This also increases chances charts run on environments with little resources, such as Minikube. [Ref docs](https://kubernetes.io/docs/user-guide/compute-resources/) | +| [extraEnv](./values.yaml#L856) | list | `[{"name":"LOG_LEVEL_SOURCE_BOTKUBE_KUBERNETES","value":"debug"}]` | Extra environment variables to pass to the Botkube container. [Ref docs](https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#environment-variables). | +| [extraVolumes](./values.yaml#L870) | list | `[]` | Extra volumes to pass to the Botkube container. Mount it later with extraVolumeMounts. [Ref docs](https://kubernetes.io/docs/reference/kubernetes-api/config-and-storage-resources/volume/#Volume). | +| [extraVolumeMounts](./values.yaml#L885) | list | `[]` | Extra volume mounts to pass to the Botkube container. [Ref docs](https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#volumes-1). | +| [nodeSelector](./values.yaml#L903) | object | `{}` | Node labels for Botkube Pod assignment. [Ref doc](https://kubernetes.io/docs/user-guide/node-selection/). | +| [tolerations](./values.yaml#L907) | list | `[]` | Tolerations for Botkube Pod assignment. [Ref doc](https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/). | +| [affinity](./values.yaml#L911) | object | `{}` | Affinity for Botkube Pod assignment. [Ref doc](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity). | +| [serviceAccount.create](./values.yaml#L915) | bool | `true` | If true, a ServiceAccount is automatically created. | +| [serviceAccount.name](./values.yaml#L918) | string | `""` | The name of the service account to use. If not set, a name is generated using the fullname template. | +| [serviceAccount.annotations](./values.yaml#L920) | object | `{}` | Extra annotations for the ServiceAccount. | +| [extraObjects](./values.yaml#L923) | list | `[]` | Extra Kubernetes resources to create. Helm templating is allowed as it is evaluated before creating the resources. | +| [analytics.disable](./values.yaml#L951) | bool | `false` | If true, sending anonymous analytics is disabled. To learn what date we collect, see [Privacy Policy](https://docs.botkube.io/privacy#privacy-policy). | +| [configWatcher.enabled](./values.yaml#L956) | bool | `true` | If true, restarts the Botkube Pod on config changes. | +| [configWatcher.tmpDir](./values.yaml#L958) | string | `"/tmp/watched-cfg/"` | Directory, where watched configuration resources are stored. | +| [configWatcher.initialSyncTimeout](./values.yaml#L961) | int | `0` | Timeout for the initial Config Watcher sync. If set to 0, waiting for Config Watcher sync will be skipped. In a result, configuration changes may not reload Botkube app during the first few seconds after Botkube startup. | +| [configWatcher.image.registry](./values.yaml#L964) | string | `"ghcr.io"` | Config watcher image registry. | +| [configWatcher.image.repository](./values.yaml#L966) | string | `"kubeshop/k8s-sidecar"` | Config watcher image repository. | +| [configWatcher.image.tag](./values.yaml#L968) | string | `"ignore-initial-events"` | Config watcher image tag. | +| [configWatcher.image.pullPolicy](./values.yaml#L970) | string | `"IfNotPresent"` | Config watcher image pull policy. | +| [plugins](./values.yaml#L973) | object | `{"cacheDir":"/tmp","repositories":{"botkube":{"url":"https://github.com/kubeshop/botkube/releases/download/v9.99.9-dev/plugins-index.yaml"}}}` | Configuration for Botkube executors and sources plugins. | +| [plugins.cacheDir](./values.yaml#L975) | string | `"/tmp"` | Directory, where downloaded plugins are cached. | +| [plugins.repositories](./values.yaml#L977) | object | `{"botkube":{"url":"https://github.com/kubeshop/botkube/releases/download/v9.99.9-dev/plugins-index.yaml"}}` | List of plugins repositories. | +| [plugins.repositories.botkube](./values.yaml#L979) | object | `{"url":"https://github.com/kubeshop/botkube/releases/download/v9.99.9-dev/plugins-index.yaml"}` | This repository serves officially supported Botkube plugins. | +| [config](./values.yaml#L983) | object | `{"provider":{"apiKey":"","endpoint":"https://api.botkube.io/graphql","identifier":""}}` | Configuration for synchronizing Botkube configuration. | +| [config.provider](./values.yaml#L985) | object | `{"apiKey":"","endpoint":"https://api.botkube.io/graphql","identifier":""}` | Base provider definition. | +| [config.provider.identifier](./values.yaml#L988) | string | `""` | Unique identifier for remote Botkube settings. If set to an empty string, Botkube won't fetch remote configuration. | +| [config.provider.endpoint](./values.yaml#L990) | string | `"https://api.botkube.io/graphql"` | Endpoint to fetch Botkube settings from. | +| [config.provider.apiKey](./values.yaml#L992) | string | `""` | Key passed as a `X-API-Key` header to the provider's endpoint. | ### AWS IRSA on EKS support diff --git a/helm/botkube/e2e-test-values.yaml b/helm/botkube/e2e-test-values.yaml index c5bca917f..114760ace 100644 --- a/helm/botkube/e2e-test-values.yaml +++ b/helm/botkube/e2e-test-values.yaml @@ -1,6 +1,17 @@ analytics: disable: true +rbac: + create: true + rules: + - apiGroups: [ "*" ] + resources: [ "*" ] + verbs: [ "get", "watch", "list" ] # defaults + - apiGroups: [ "" ] + resources: [ "services" ] + verbs: [ "patch" ] # needed for label action + staticGroupName: &static-group-name "botkube-plugins-default" + communications: 'default-group': slack: # Configuration for the Slack app with RTM support @@ -65,6 +76,25 @@ sources: 'k8s-events': displayName: "K8s recommendations" 'botkube/kubernetes': + context: &defaultPluginContext + defaultNamespace: "default" + # -- RBAC configuration for this plugin. + rbac: + # -- Static impersonation for a given username and groups. + group: + type: Static + # -- Prefix that will be applied to .static.value[*]. + prefix: "" + static: + # -- Name of group.rbac.authorization.k8s.io the plugin will be bound to. + values: [*static-group-name] # "botkube-plugins-read-only" is the default + user: + type: Static + # -- Prefix that will be applied to .static.value[*]. + prefix: "" + static: + # -- Name of user.rbac.authorization.k8s.io the plugin will be bound to. + value: *static-group-name enabled: true config: log: @@ -88,6 +118,7 @@ sources: 'k8s-annotated-cm-delete': displayName: "K8s ConfigMap delete events" 'botkube/kubernetes': + context: *defaultPluginContext enabled: true config: log: @@ -105,6 +136,7 @@ sources: 'k8s-pod-create-events': 'botkube/kubernetes': + context: *defaultPluginContext enabled: true config: log: @@ -121,6 +153,7 @@ sources: 'k8s-service-create-event-for-action-only': displayName: "K8s Service creation, used only by action" 'botkube/kubernetes': + context: *defaultPluginContext enabled: true config: namespaces: @@ -135,6 +168,7 @@ sources: 'k8s-updates': displayName: "K8s ConfigMaps updates" 'botkube/kubernetes': + context: *defaultPluginContext enabled: true config: log: @@ -159,6 +193,7 @@ sources: 'plugin-based': displayName: "K8s ConfigMaps changes" botkube/cm-watcher: + context: *defaultPluginContext enabled: true config: configMap: @@ -229,6 +264,7 @@ executors: changeResponseToUpperCase: true botkube/helm: + context: *defaultPluginContext enabled: true plugins: @@ -288,17 +324,6 @@ settings: extraAnnotations: botkube.io/disable: "true" -rbac: - create: true - rules: - - apiGroups: [ "*" ] - resources: [ "*" ] - verbs: [ "get", "watch", "list" ] # defaults - - apiGroups: [ "" ] - resources: [ "services" ] - verbs: [ "patch" ] # needed for label action - - extraEnv: - name: LOG_LEVEL_SOURCE_BOTKUBE_KUBERNETES value: debug diff --git a/helm/botkube/templates/clusterrole.yaml b/helm/botkube/templates/clusterrole.yaml index 633e16ecf..32d8db0d6 100644 --- a/helm/botkube/templates/clusterrole.yaml +++ b/helm/botkube/templates/clusterrole.yaml @@ -21,6 +21,14 @@ rules: - apiGroups: [""] resources: ["namespaces"] verbs: ["get"] + - apiGroups: + - "" + resources: + - users + - groups + - serviceaccounts + verbs: + - impersonate --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole diff --git a/helm/botkube/values.yaml b/helm/botkube/values.yaml index f5e59f4b0..ad10086fd 100644 --- a/helm/botkube/values.yaml +++ b/helm/botkube/values.yaml @@ -116,6 +116,25 @@ sources: # -- Describes Kubernetes source configuration. # @default -- See the `values.yaml` file for full object. botkube/kubernetes: + context: &defaultPluginContext + defaultNamespace: "default" + # -- RBAC configuration for this plugin. + rbac: + # -- Static impersonation for a given username and groups. + group: + type: Static + # -- Prefix that will be applied to .static.value[*]. + prefix: "" + static: + # -- Name of group.rbac.authorization.k8s.io the plugin will be bound to. + values: [*static-group-name] # "botkube-plugins-read-only" is the default + user: + type: Static + # -- Prefix that will be applied to .static.value[*]. + prefix: "" + static: + # -- Name of user.rbac.authorization.k8s.io the plugin will be bound to. + value: *static-group-name enabled: true config: namespaces: @@ -141,6 +160,7 @@ sources: # -- Describes Kubernetes source configuration. # @default -- See the `values.yaml` file for full object. botkube/kubernetes: + context: *defaultPluginContext enabled: true config: # -- Filter settings for various sources. @@ -313,6 +333,7 @@ sources: # -- Describes Kubernetes source configuration. # @default -- See the `values.yaml` file for full object. botkube/kubernetes: + context: *defaultPluginContext enabled: true config: # -- Describes namespaces for every Kubernetes resources you want to watch or exclude. @@ -352,6 +373,7 @@ sources: # -- Describes Kubernetes source configuration. # @default -- See the `values.yaml` file for full object. botkube/kubernetes: + context: *defaultPluginContext enabled: true config: # -- Describes namespaces for every Kubernetes resources you want to watch or exclude. @@ -382,6 +404,7 @@ sources: # -- Describes Kubernetes source configuration. # @default -- See the `values.yaml` file for full object. botkube/kubernetes: + context: *defaultPluginContext enabled: true config: # -- Describes namespaces for every Kubernetes resources you want to watch or exclude. @@ -476,24 +499,7 @@ executors: helmConfigDir: "/tmp/helm/" # -- Location for storing cached files. Must be under the Helm config directory. helmCacheDir: "/tmp/helm/.cache" - context: &defaultExecutorContext - # -- RBAC configuration for this plugin. - rbac: - # -- Static impersonation for a given username and groups. - group: - type: Static - # -- Prefix that will be applied to .static.value[*]. - prefix: "" - static: - # -- Name of group.rbac.authorization.k8s.io the plugin will be bound to. - values: [*static-group-name] # "botkube-plugins-read-only" is the default - user: - type: Static - # -- Prefix that will be applied to .static.value[*]. - prefix: "" - static: - # -- Name of user.rbac.authorization.k8s.io the plugin will be bound to. - value: "default" + context: *defaultPluginContext ## Kubectl executor configuration ## Plugin name syntax: /[@]. If version is not provided, the latest version from repository is used. @@ -518,7 +524,7 @@ executors: # verbs: [ "api-resources", "api-versions", "cluster-info", "describe", "explain", "get", "logs", "top" ] # # Configures which K8s resource are displayed in resources dropdown. # resources: [ "deployments", "pods", "namespaces", "daemonsets", "statefulsets", "storageclasses", "nodes", "configmaps", "services", "ingresses", "replicasets", "secrets", "cronjobs", "jobs" ] - context: *defaultExecutorContext + context: *defaultPluginContext # -- Custom aliases for given commands. # The aliases are replaced with the underlying command before executing it. diff --git a/internal/executor/helm/executor.go b/internal/executor/helm/executor.go index 55ab16ce6..84ecc1f71 100644 --- a/internal/executor/helm/executor.go +++ b/internal/executor/helm/executor.go @@ -3,6 +3,7 @@ package helm import ( "context" "fmt" + "os" "github.com/MakeNowJust/heredoc" "github.com/alexflint/go-arg" @@ -104,37 +105,47 @@ func (e *Executor) Execute(ctx context.Context, in executor.ExecuteInput) (execu in.Command = fmt.Sprintf("%s -n %s", in.Command, cfg.DefaultNamespace) } + kubeConfigPath, deleteFn, err := pluginx.PersistKubeConfig(ctx, in.Context.KubeConfig) + if err != nil { + return executor.ExecuteOutput{}, fmt.Errorf("while writing kubeConfig file: %w", err) + } + defer func() { + if deleteErr := deleteFn(ctx); deleteErr != nil { + fmt.Fprintf(os.Stderr, "failed to delete cube config file %s: %v", kubeConfigPath, deleteErr) + } + }() + switch { case helmCmd.Install != nil: - return e.handleHelmCommand(ctx, helmCmd.Install, cfg, wasHelpRequested, in.Command) + return e.handleHelmCommand(ctx, helmCmd.Install, cfg, wasHelpRequested, in.Command, kubeConfigPath) case helmCmd.UninstallCommandAliases.Get() != nil: - return e.handleHelmCommand(ctx, helmCmd.UninstallCommandAliases.Get(), cfg, wasHelpRequested, in.Command) + return e.handleHelmCommand(ctx, helmCmd.UninstallCommandAliases.Get(), cfg, wasHelpRequested, in.Command, kubeConfigPath) case helmCmd.ListCommandAliases.Get() != nil: - return e.handleHelmCommand(ctx, helmCmd.ListCommandAliases.Get(), cfg, wasHelpRequested, in.Command) + return e.handleHelmCommand(ctx, helmCmd.ListCommandAliases.Get(), cfg, wasHelpRequested, in.Command, kubeConfigPath) case helmCmd.Version != nil: - return e.handleHelmCommand(ctx, helmCmd.Version, cfg, wasHelpRequested, in.Command) + return e.handleHelmCommand(ctx, helmCmd.Version, cfg, wasHelpRequested, in.Command, kubeConfigPath) case helmCmd.Status != nil: - return e.handleHelmCommand(ctx, helmCmd.Status, cfg, wasHelpRequested, in.Command) + return e.handleHelmCommand(ctx, helmCmd.Status, cfg, wasHelpRequested, in.Command, kubeConfigPath) case helmCmd.Test != nil: - return e.handleHelmCommand(ctx, helmCmd.Test, cfg, wasHelpRequested, in.Command) + return e.handleHelmCommand(ctx, helmCmd.Test, cfg, wasHelpRequested, in.Command, kubeConfigPath) case helmCmd.Rollback != nil: - return e.handleHelmCommand(ctx, helmCmd.Rollback, cfg, wasHelpRequested, in.Command) + return e.handleHelmCommand(ctx, helmCmd.Rollback, cfg, wasHelpRequested, in.Command, kubeConfigPath) case helmCmd.Upgrade != nil: - return e.handleHelmCommand(ctx, helmCmd.Upgrade, cfg, wasHelpRequested, in.Command) + return e.handleHelmCommand(ctx, helmCmd.Upgrade, cfg, wasHelpRequested, in.Command, kubeConfigPath) case helmCmd.HistoryCommandAliases.Get() != nil: - return e.handleHelmCommand(ctx, helmCmd.HistoryCommandAliases.Get(), cfg, wasHelpRequested, in.Command) + return e.handleHelmCommand(ctx, helmCmd.HistoryCommandAliases.Get(), cfg, wasHelpRequested, in.Command, kubeConfigPath) case helmCmd.Get != nil: switch { case helmCmd.Get.All != nil: - return e.handleHelmCommand(ctx, helmCmd.Get.All, cfg, wasHelpRequested, in.Command) + return e.handleHelmCommand(ctx, helmCmd.Get.All, cfg, wasHelpRequested, in.Command, kubeConfigPath) case helmCmd.Get.Hooks != nil: - return e.handleHelmCommand(ctx, helmCmd.Get.Hooks, cfg, wasHelpRequested, in.Command) + return e.handleHelmCommand(ctx, helmCmd.Get.Hooks, cfg, wasHelpRequested, in.Command, kubeConfigPath) case helmCmd.Get.Manifest != nil: - return e.handleHelmCommand(ctx, helmCmd.Get.Manifest, cfg, wasHelpRequested, in.Command) + return e.handleHelmCommand(ctx, helmCmd.Get.Manifest, cfg, wasHelpRequested, in.Command, kubeConfigPath) case helmCmd.Get.Notes != nil: - return e.handleHelmCommand(ctx, helmCmd.Get.Notes, cfg, wasHelpRequested, in.Command) + return e.handleHelmCommand(ctx, helmCmd.Get.Notes, cfg, wasHelpRequested, in.Command, kubeConfigPath) case helmCmd.Get.Values != nil: - return e.handleHelmCommand(ctx, helmCmd.Get.Values, cfg, wasHelpRequested, in.Command) + return e.handleHelmCommand(ctx, helmCmd.Get.Values, cfg, wasHelpRequested, in.Command, kubeConfigPath) default: return executor.ExecuteOutput{ Data: helmCmd.Get.Help(), @@ -153,7 +164,7 @@ func (*Executor) Help(context.Context) (api.Message, error) { } // handleHelmList construct a Helm CLI command and run it. -func (e *Executor) handleHelmCommand(ctx context.Context, cmd command, cfg Config, wasHelpRequested bool, rawCmd string) (executor.ExecuteOutput, error) { +func (e *Executor) handleHelmCommand(ctx context.Context, cmd command, cfg Config, wasHelpRequested bool, rawCmd, kubeConfig string) (executor.ExecuteOutput, error) { if wasHelpRequested { return executor.ExecuteOutput{ Data: cmd.Help(), @@ -169,6 +180,7 @@ func (e *Executor) handleHelmCommand(ctx context.Context, cmd command, cfg Confi "HELM_DRIVER": cfg.HelmDriver, "HELM_CACHE_HOME": cfg.HelmCacheDir, "HELM_CONFIG_HOME": cfg.HelmConfigDir, + "KUBECONFIG": kubeConfig, } out, err := e.executeCommandWithEnvs(ctx, rawCmd, envs) diff --git a/internal/executor/helm/executor_test.go b/internal/executor/helm/executor_test.go index 04178d820..ce00bae9b 100644 --- a/internal/executor/helm/executor_test.go +++ b/internal/executor/helm/executor_test.go @@ -13,6 +13,8 @@ import ( "github.com/kubeshop/botkube/pkg/api/executor" ) +const kc = "KUBECONFIG" + func TestExecutorHelmInstall(t *testing.T) { tests := []struct { name string @@ -60,6 +62,9 @@ func TestExecutorHelmInstall(t *testing.T) { // when out, err := hExec.Execute(context.Background(), executor.ExecuteInput{ Command: tc.inputCommand, + Context: executor.ExecuteInputContext{ + KubeConfig: []byte("not empty"), + }, }) // then @@ -68,6 +73,10 @@ func TestExecutorHelmInstall(t *testing.T) { assert.Equal(t, execOutput, out.Data) assert.Equal(t, tc.expCommand, gotCmd) + + _, ok := gotEnvs[kc] + assert.Equal(t, true, ok) + delete(gotEnvs, kc) assert.Equal(t, map[string]string{ "HELM_DRIVER": "secret", "HELM_CACHE_HOME": "/tmp/helm/.cache", @@ -108,6 +117,9 @@ func TestExecutorHelmInstallFlagsErrors(t *testing.T) { // when out, err := hExec.Execute(context.Background(), executor.ExecuteInput{ Command: tc.inputCommand, + Context: executor.ExecuteInputContext{ + KubeConfig: []byte("not empty"), + }, }) // then @@ -145,6 +157,9 @@ func TestExecutorHelmInstallHelp(t *testing.T) { // when out, err := hExec.Execute(context.Background(), executor.ExecuteInput{ Command: tc.inputCommand, + Context: executor.ExecuteInputContext{ + KubeConfig: []byte("not empty"), + }, }) // then @@ -181,11 +196,17 @@ func TestExecutorConfigMerging(t *testing.T) { RawYAML: mustYAMLMarshal(t, configB), }, }, + Context: executor.ExecuteInputContext{ + KubeConfig: []byte("not empty"), + }, }) // then require.NoError(t, err) + _, ok := gotEnvs[kc] + assert.Equal(t, true, ok) + delete(gotEnvs, kc) assert.Equal(t, map[string]string{ "HELM_DRIVER": "secret", "HELM_CACHE_HOME": "/tmp/helm/.cache", diff --git a/internal/executor/kubectl/builder/deps.go b/internal/executor/kubectl/builder/deps.go index 745f3d58f..8b831bc1d 100644 --- a/internal/executor/kubectl/builder/deps.go +++ b/internal/executor/kubectl/builder/deps.go @@ -17,7 +17,7 @@ type ( // KubectlRunner provides an option to run a given kubectl command. KubectlRunner interface { - RunKubectlCommand(ctx context.Context, defaultNamespace, cmd string) (string, error) + RunKubectlCommand(ctx context.Context, kubeConfigPath, defaultNamespace, cmd string) (string, error) } // CommandGuard is an interface that allows to check if a given command is allowed to be executed. diff --git a/internal/executor/kubectl/builder/kubectl.go b/internal/executor/kubectl/builder/kubectl.go index 0bedc2d6a..91e54d3b5 100644 --- a/internal/executor/kubectl/builder/kubectl.go +++ b/internal/executor/kubectl/builder/kubectl.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "os" "strings" "github.com/google/uuid" @@ -284,7 +285,7 @@ func (e *Kubectl) tryToGetResourceNamesSelect(ctx context.Context, state stateDe } e.log.Infof("Run cmd %q", cmd) - out, err := e.kcRunner.RunKubectlCommand(ctx, e.defaultNamespace, cmd) + out, err := e.kcRunner.RunKubectlCommand(ctx, os.Getenv("KUBECONFIG"), e.defaultNamespace, cmd) if err != nil { e.log.WithField("error", err.Error()).Error("Cannot fetch resource names. Returning empty resource name dropdown.") return EmptyResourceNameDropdown() diff --git a/internal/executor/kubectl/builder/kubectl_test.go b/internal/executor/kubectl/builder/kubectl_test.go index 3365309a3..e3a92f03e 100644 --- a/internal/executor/kubectl/builder/kubectl_test.go +++ b/internal/executor/kubectl/builder/kubectl_test.go @@ -543,7 +543,7 @@ type fakeKcExecutor struct { defaultNamespace string } -func (r *fakeKcExecutor) RunKubectlCommand(_ context.Context, defaultNamespace, cmd string) (string, error) { +func (r *fakeKcExecutor) RunKubectlCommand(_ context.Context, kubeConfigPath, defaultNamespace, cmd string) (string, error) { r.defaultNamespace = defaultNamespace r.command = cmd @@ -552,7 +552,7 @@ func (r *fakeKcExecutor) RunKubectlCommand(_ context.Context, defaultNamespace, type fakeErrorKcExecutor struct{} -func (r *fakeErrorKcExecutor) RunKubectlCommand(context.Context, string, string) (string, error) { +func (r *fakeErrorKcExecutor) RunKubectlCommand(context.Context, string, string, string) (string, error) { return "", errors.New("fake error") } diff --git a/internal/executor/kubectl/executor.go b/internal/executor/kubectl/executor.go index 41372fb9a..36b3414f0 100644 --- a/internal/executor/kubectl/executor.go +++ b/internal/executor/kubectl/executor.go @@ -16,6 +16,7 @@ import ( "github.com/kubeshop/botkube/internal/loggerx" "github.com/kubeshop/botkube/pkg/api" "github.com/kubeshop/botkube/pkg/api/executor" + "github.com/kubeshop/botkube/pkg/pluginx" ) const ( @@ -40,7 +41,7 @@ var _ executor.Executor = &Executor{} type ( kcRunner interface { - RunKubectlCommand(ctx context.Context, defaultNamespace, cmd string) (string, error) + RunKubectlCommand(ctx context.Context, kubeConfigPath, defaultNamespace, cmd string) (string, error) } ) @@ -107,7 +108,17 @@ func (e *Executor) Execute(ctx context.Context, in executor.ExecuteInput) (execu }, nil } - out, err := e.kcRunner.RunKubectlCommand(ctx, cfg.DefaultNamespace, cmd) + kubeConfigPath, deleteFn, err := pluginx.PersistKubeConfig(ctx, in.Context.KubeConfig) + if err != nil { + return executor.ExecuteOutput{}, fmt.Errorf("while writing kubeConfig file: %w", err) + } + defer func() { + if deleteErr := deleteFn(ctx); deleteErr != nil { + log.Errorf("failed to delete cube config file %s: %w", kubeConfigPath, deleteErr) + } + }() + + out, err := e.kcRunner.RunKubectlCommand(ctx, kubeConfigPath, cfg.DefaultNamespace, cmd) if err != nil { return executor.ExecuteOutput{}, err } diff --git a/internal/executor/kubectl/executor_test.go b/internal/executor/kubectl/executor_test.go index b1634e165..416e8d41c 100644 --- a/internal/executor/kubectl/executor_test.go +++ b/internal/executor/kubectl/executor_test.go @@ -65,6 +65,9 @@ func TestSetDefaultNamespace(t *testing.T) { RawYAML: []byte(tc.givenConfig), }, }, + Context: executor.ExecuteInputContext{ + KubeConfig: []byte("not empty"), + }, }) // then @@ -107,6 +110,9 @@ func TestSetOptionsCommand(t *testing.T) { // when out, err := exec.Execute(context.Background(), executor.ExecuteInput{ Command: tc.givenCommand, + Context: executor.ExecuteInputContext{ + KubeConfig: []byte("not empty"), + }, }) // then @@ -153,6 +159,9 @@ func TestNotSupportedCommandsAndFlags(t *testing.T) { // when out, err := exec.Execute(context.Background(), executor.ExecuteInput{ Command: tc.givenCommand, + Context: executor.ExecuteInputContext{ + KubeConfig: []byte("not empty"), + }, }) // then diff --git a/internal/executor/kubectl/kc_runner.go b/internal/executor/kubectl/kc_runner.go index 2550f8e3b..33785ad19 100644 --- a/internal/executor/kubectl/kc_runner.go +++ b/internal/executor/kubectl/kc_runner.go @@ -3,7 +3,6 @@ package kubectl import ( "context" "fmt" - "os" "strings" "github.com/gookit/color" @@ -27,7 +26,7 @@ func NewBinaryRunner() *BinaryRunner { } // RunKubectlCommand runs a Kubectl CLI command and run output. -func (e *BinaryRunner) RunKubectlCommand(ctx context.Context, defaultNamespace, cmd string) (string, error) { +func (e *BinaryRunner) RunKubectlCommand(ctx context.Context, kubeConfigPath, defaultNamespace, cmd string) (string, error) { if err := detectNotSupportedCommands(cmd); err != nil { return "", err } @@ -51,8 +50,7 @@ func (e *BinaryRunner) RunKubectlCommand(ctx context.Context, defaultNamespace, } envs := map[string]string{ - // TODO: take it from the execute context. - "KUBECONFIG": os.Getenv("KUBECONFIG"), + "KUBECONFIG": kubeConfigPath, } runCmd := fmt.Sprintf("%s %s", binaryName, cmd) diff --git a/internal/plugin/kubeconfig.go b/internal/plugin/kubeconfig.go new file mode 100644 index 000000000..bd13ec819 --- /dev/null +++ b/internal/plugin/kubeconfig.go @@ -0,0 +1,83 @@ +package plugin + +import ( + "k8s.io/client-go/rest" + clientcmdapi "k8s.io/client-go/tools/clientcmd/api/v1" + "sigs.k8s.io/yaml" + + "github.com/kubeshop/botkube/pkg/config" +) + +const ( + kubeconfigDefaultValue = "default" +) + +type KubeConfigInput struct { +} + +func GenerateKubeConfig(restCfg *rest.Config, pluginCtx config.PluginContext, input KubeConfigInput) ([]byte, error) { + rbac := pluginCtx.RBAC + if rbac == nil { + return nil, nil + } + apiCfg := clientcmdapi.Config{ + Kind: "Config", + APIVersion: "v1", + Clusters: []clientcmdapi.NamedCluster{ + { + Name: kubeconfigDefaultValue, + Cluster: clientcmdapi.Cluster{ + Server: restCfg.Host, + CertificateAuthority: restCfg.CAFile, + }, + }, + }, + Contexts: []clientcmdapi.NamedContext{ + { + Name: kubeconfigDefaultValue, + Context: clientcmdapi.Context{ + Cluster: kubeconfigDefaultValue, + Namespace: pluginCtx.DefaultNamespace, + AuthInfo: kubeconfigDefaultValue, + }, + }, + }, + CurrentContext: kubeconfigDefaultValue, + AuthInfos: []clientcmdapi.NamedAuthInfo{ + { + Name: kubeconfigDefaultValue, + AuthInfo: clientcmdapi.AuthInfo{ + Token: restCfg.BearerToken, + TokenFile: restCfg.BearerTokenFile, + Impersonate: generateUserSubject(rbac.User), + ImpersonateGroups: generateGroupSubject(rbac.Group), + }, + }, + }, + } + + yamlKubeConfig, err := yaml.Marshal(apiCfg) + if err != nil { + return nil, err + } + + return yamlKubeConfig, nil +} + +func generateUserSubject(rbac config.UserPolicySubject) (user string) { + switch rbac.Type { + case config.StaticPolicySubjectType: + user = rbac.Prefix + rbac.Static.Value + } + return +} + +func generateGroupSubject(rbac config.GroupPolicySubject) (group []string) { + switch rbac.Type { + case config.StaticPolicySubjectType: + for _, value := range rbac.Static.Values { + group = append(group, rbac.Prefix+value) + } + } + return +} diff --git a/internal/source/dispatcher.go b/internal/source/dispatcher.go index 468bcc6b6..7b01840bd 100644 --- a/internal/source/dispatcher.go +++ b/internal/source/dispatcher.go @@ -6,6 +6,7 @@ import ( "time" "github.com/sirupsen/logrus" + "k8s.io/client-go/rest" "github.com/kubeshop/botkube/internal/analytics" "github.com/kubeshop/botkube/internal/audit" @@ -30,6 +31,7 @@ type Dispatcher struct { markdownNotifiers []notifier.Bot interactiveNotifiers []notifier.Bot sinkNotifiers []notifier.Sink + restCfg *rest.Config } // ActionProvider defines a provider that is responsible for automated actions. @@ -54,7 +56,7 @@ type AnalyticsReporter interface { } // NewDispatcher create a new Dispatcher instance. -func NewDispatcher(log logrus.FieldLogger, notifiers map[string]bot.Bot, sinkNotifiers []notifier.Sink, manager *plugin.Manager, actionProvider ActionProvider, reporter AnalyticsReporter, auditReporter audit.AuditReporter) *Dispatcher { +func NewDispatcher(log logrus.FieldLogger, notifiers map[string]bot.Bot, sinkNotifiers []notifier.Sink, manager *plugin.Manager, actionProvider ActionProvider, reporter AnalyticsReporter, auditReporter audit.AuditReporter, restCfg *rest.Config) *Dispatcher { var ( interactiveNotifiers []notifier.Bot markdownNotifiers []notifier.Bot @@ -77,6 +79,7 @@ func NewDispatcher(log logrus.FieldLogger, notifiers map[string]bot.Bot, sinkNot interactiveNotifiers: interactiveNotifiers, markdownNotifiers: markdownNotifiers, sinkNotifiers: sinkNotifiers, + restCfg: restCfg, } } @@ -96,13 +99,18 @@ func (d *Dispatcher) Dispatch(dispatch PluginDispatch) error { return fmt.Errorf("while getting source client for %s: %w", dispatch.pluginName, err) } + kubeconfig, err := plugin.GenerateKubeConfig(d.restCfg, dispatch.pluginContext, plugin.KubeConfigInput{}) + if err != nil { + return fmt.Errorf("while generating kube config for %s: %w", dispatch.pluginName, err) + } + ctx := dispatch.ctx out, err := sourceClient.Stream(ctx, source.StreamInput{ Configs: dispatch.pluginConfigs, Context: source.StreamInputContext{ IsInteractivitySupported: dispatch.isInteractivitySupported, ClusterName: dispatch.cfg.Settings.ClusterName, - KubeConfig: dispatch.cfg.Settings.Kubeconfig, + KubeConfig: kubeconfig, }, }) if err != nil { diff --git a/internal/source/kubernetes/client.go b/internal/source/kubernetes/client.go index 420bea22e..31f135bab 100644 --- a/internal/source/kubernetes/client.go +++ b/internal/source/kubernetes/client.go @@ -11,7 +11,6 @@ import ( "k8s.io/client-go/rest" "k8s.io/client-go/restmapper" "k8s.io/client-go/tools/clientcmd" - "k8s.io/client-go/tools/clientcmd/api" ) // Client Kubernetes client @@ -23,23 +22,10 @@ type Client struct { } // NewClient initializes Kubernetes client -func NewClient(kubeConfigPath string) (*Client, error) { - var kubeConfig *rest.Config - if kubeConfigPath == "" { - config, err := rest.InClusterConfig() - if err != nil { - return nil, fmt.Errorf("while loading in cluster config. %v", err) - } - kubeConfig = config - } else { - config, err := clientcmd.NewNonInteractiveDeferredLoadingClientConfig( - &clientcmd.ClientConfigLoadingRules{ExplicitPath: kubeConfigPath}, - &clientcmd.ConfigOverrides{ClusterInfo: api.Cluster{}}, - ).ClientConfig() - if err != nil { - return nil, fmt.Errorf("while loading dynamic config. %v", err) - } - kubeConfig = config +func NewClient(kubeConfigBytes []byte) (*Client, error) { + kubeConfig, err := clientcmd.RESTConfigFromKubeConfig(kubeConfigBytes) + if err != nil { + return nil, fmt.Errorf("while reading kube config. %v", err) } dynamicCli, discoveryCli, mapper, err := getK8sClients(kubeConfig) if err != nil { diff --git a/internal/source/kubernetes/source.go b/internal/source/kubernetes/source.go index 25bd9b034..f85155e0a 100644 --- a/internal/source/kubernetes/source.go +++ b/internal/source/kubernetes/source.go @@ -50,7 +50,7 @@ type Source struct { commandGuard *command.CommandGuard filterEngine filterengine.FilterEngine clusterName string - kubeConfig string + kubeConfig []byte messageBuilder *MessageBuilder isInteractivitySupported bool } diff --git a/internal/source/scheduler.go b/internal/source/scheduler.go index ab4e4ceaa..7d2eabff6 100644 --- a/internal/source/scheduler.go +++ b/internal/source/scheduler.go @@ -22,6 +22,7 @@ type PluginDispatch struct { sourceName string isInteractivitySupported bool cfg *config.Config + pluginContext config.PluginContext } // Scheduler analyzes the provided configuration and based on that schedules plugin sources. @@ -145,11 +146,12 @@ func (d *Scheduler) schedulePlugin(ctx context.Context, isInteractivitySupported sourcePluginConfigs := map[string][]*source.Config{} plugins := d.cfg.Sources[sourceName].Plugins + var pluginContext config.PluginContext for pluginName, pluginCfg := range plugins { if !pluginCfg.Enabled { continue } - + pluginContext = pluginCfg.Context // Unfortunately we need marshal it to get the raw data: // https://github.com/go-yaml/yaml/issues/13 rawYAML, err := yaml.Marshal(pluginCfg.Config) @@ -169,6 +171,7 @@ func (d *Scheduler) schedulePlugin(ctx context.Context, isInteractivitySupported isInteractivitySupported: isInteractivitySupported, sourceName: sourceName, cfg: d.cfg, + pluginContext: pluginContext, }) if err != nil { return fmt.Errorf("while starting plugin source %s: %w", pluginName, err) diff --git a/pkg/api/executor/executor.pb.go b/pkg/api/executor/executor.pb.go index 273702a8a..449347e05 100644 --- a/pkg/api/executor/executor.pb.go +++ b/pkg/api/executor/executor.pb.go @@ -142,6 +142,7 @@ type ExecuteContext struct { IsInteractivitySupported bool `protobuf:"varint,1,opt,name=isInteractivitySupported,proto3" json:"isInteractivitySupported,omitempty"` SlackState []byte `protobuf:"bytes,2,opt,name=slackState,proto3" json:"slackState,omitempty"` + KubeConfig []byte `protobuf:"bytes,3,opt,name=kubeConfig,proto3" json:"kubeConfig,omitempty"` } func (x *ExecuteContext) Reset() { @@ -190,6 +191,13 @@ func (x *ExecuteContext) GetSlackState() []byte { return nil } +func (x *ExecuteContext) GetKubeConfig() []byte { + if x != nil { + return x.KubeConfig + } + return nil +} + type ExecuteResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -489,65 +497,67 @@ var file_executor_proto_rawDesc = []byte{ 0x66, 0x69, 0x67, 0x73, 0x12, 0x32, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, - 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x22, 0x6c, 0x0a, 0x0e, 0x45, 0x78, 0x65, 0x63, - 0x75, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x3a, 0x0a, 0x18, 0x69, 0x73, - 0x49, 0x6e, 0x74, 0x65, 0x72, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x53, 0x75, 0x70, - 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x18, 0x69, 0x73, - 0x49, 0x6e, 0x74, 0x65, 0x72, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x53, 0x75, 0x70, - 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x12, 0x1e, 0x0a, 0x0a, 0x73, 0x6c, 0x61, 0x63, 0x6b, 0x53, - 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x73, 0x6c, 0x61, 0x63, - 0x6b, 0x53, 0x74, 0x61, 0x74, 0x65, 0x22, 0x3f, 0x0a, 0x0f, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, - 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, - 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x18, 0x0a, - 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, - 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0xae, 0x02, 0x0a, 0x10, 0x4d, 0x65, 0x74, 0x61, - 0x64, 0x61, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, - 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, - 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, - 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x35, 0x0a, 0x0b, 0x6a, 0x73, 0x6f, 0x6e, - 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, - 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x4a, 0x53, 0x4f, 0x4e, 0x53, 0x63, 0x68, - 0x65, 0x6d, 0x61, 0x52, 0x0a, 0x6a, 0x73, 0x6f, 0x6e, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, - 0x50, 0x0a, 0x0c, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x18, - 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, - 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x2e, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x45, 0x6e, - 0x74, 0x72, 0x79, 0x52, 0x0c, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x69, 0x65, - 0x73, 0x1a, 0x55, 0x0a, 0x11, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x69, 0x65, - 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2a, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, - 0x6f, 0x72, 0x2e, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x3b, 0x0a, 0x0a, 0x4a, 0x53, 0x4f, 0x4e, - 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x17, 0x0a, 0x07, - 0x72, 0x65, 0x66, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, - 0x65, 0x66, 0x55, 0x72, 0x6c, 0x22, 0x79, 0x0a, 0x0a, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, - 0x6e, 0x63, 0x79, 0x12, 0x32, 0x0a, 0x04, 0x75, 0x72, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x1e, 0x2e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x44, 0x65, 0x70, - 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x2e, 0x55, 0x72, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, - 0x79, 0x52, 0x04, 0x75, 0x72, 0x6c, 0x73, 0x1a, 0x37, 0x0a, 0x09, 0x55, 0x72, 0x6c, 0x73, 0x45, - 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, - 0x22, 0x22, 0x0a, 0x0c, 0x48, 0x65, 0x6c, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x12, 0x0a, 0x04, 0x68, 0x65, 0x6c, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, - 0x68, 0x65, 0x6c, 0x70, 0x32, 0xc8, 0x01, 0x0a, 0x08, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, - 0x72, 0x12, 0x40, 0x0a, 0x07, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x12, 0x18, 0x2e, 0x65, - 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, - 0x72, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x00, 0x12, 0x40, 0x0a, 0x08, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, - 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1a, 0x2e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, - 0x6f, 0x72, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x38, 0x0a, 0x04, 0x48, 0x65, 0x6c, 0x70, 0x12, 0x16, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, - 0x2e, 0x48, 0x65, 0x6c, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, - 0x12, 0x5a, 0x10, 0x70, 0x6b, 0x67, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x65, 0x78, 0x65, 0x63, 0x75, - 0x74, 0x6f, 0x72, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x22, 0x8c, 0x01, 0x0a, 0x0e, 0x45, 0x78, 0x65, + 0x63, 0x75, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x3a, 0x0a, 0x18, 0x69, + 0x73, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x53, 0x75, + 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x18, 0x69, + 0x73, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x53, 0x75, + 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x12, 0x1e, 0x0a, 0x0a, 0x73, 0x6c, 0x61, 0x63, 0x6b, + 0x53, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x73, 0x6c, 0x61, + 0x63, 0x6b, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x6b, 0x75, 0x62, 0x65, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x6b, 0x75, 0x62, + 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0x3f, 0x0a, 0x0f, 0x45, 0x78, 0x65, 0x63, 0x75, + 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, + 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x18, + 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0xae, 0x02, 0x0a, 0x10, 0x4d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, + 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, + 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, + 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x35, 0x0a, 0x0b, 0x6a, 0x73, 0x6f, + 0x6e, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, + 0x2e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x4a, 0x53, 0x4f, 0x4e, 0x53, 0x63, + 0x68, 0x65, 0x6d, 0x61, 0x52, 0x0a, 0x6a, 0x73, 0x6f, 0x6e, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, + 0x12, 0x50, 0x0a, 0x0c, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, + 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, + 0x72, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x2e, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x45, + 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0c, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x69, + 0x65, 0x73, 0x1a, 0x55, 0x0a, 0x11, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x69, + 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2a, 0x0a, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x65, 0x78, 0x65, 0x63, 0x75, + 0x74, 0x6f, 0x72, 0x2e, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x3b, 0x0a, 0x0a, 0x4a, 0x53, 0x4f, + 0x4e, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x17, 0x0a, + 0x07, 0x72, 0x65, 0x66, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, + 0x72, 0x65, 0x66, 0x55, 0x72, 0x6c, 0x22, 0x79, 0x0a, 0x0a, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, + 0x65, 0x6e, 0x63, 0x79, 0x12, 0x32, 0x0a, 0x04, 0x75, 0x72, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x44, 0x65, + 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x2e, 0x55, 0x72, 0x6c, 0x73, 0x45, 0x6e, 0x74, + 0x72, 0x79, 0x52, 0x04, 0x75, 0x72, 0x6c, 0x73, 0x1a, 0x37, 0x0a, 0x09, 0x55, 0x72, 0x6c, 0x73, + 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, + 0x01, 0x22, 0x22, 0x0a, 0x0c, 0x48, 0x65, 0x6c, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x65, 0x6c, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x04, 0x68, 0x65, 0x6c, 0x70, 0x32, 0xc8, 0x01, 0x0a, 0x08, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, + 0x6f, 0x72, 0x12, 0x40, 0x0a, 0x07, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x12, 0x18, 0x2e, + 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, + 0x6f, 0x72, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x00, 0x12, 0x40, 0x0a, 0x08, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, + 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1a, 0x2e, 0x65, 0x78, 0x65, 0x63, 0x75, + 0x74, 0x6f, 0x72, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x38, 0x0a, 0x04, 0x48, 0x65, 0x6c, 0x70, 0x12, 0x16, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, + 0x72, 0x2e, 0x48, 0x65, 0x6c, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, + 0x42, 0x12, 0x5a, 0x10, 0x70, 0x6b, 0x67, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x65, 0x78, 0x65, 0x63, + 0x75, 0x74, 0x6f, 0x72, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/pkg/api/executor/grpc_adapter.go b/pkg/api/executor/grpc_adapter.go index db0489e0e..afe95cc03 100644 --- a/pkg/api/executor/grpc_adapter.go +++ b/pkg/api/executor/grpc_adapter.go @@ -36,6 +36,9 @@ type ( // IsInteractivitySupported is set to true only if communication platform supports interactive Messages. IsInteractivitySupported bool + // KubeConfig is the slice of byte representation of kubeconfig file content + KubeConfig []byte + // SlackState represents modal state. It's available only if: // - IsInteractivitySupported is set to true, // - and interactive actions were used in the response Message. @@ -115,6 +118,7 @@ func (p *grpcClient) Execute(ctx context.Context, in ExecuteInput) (ExecuteOutpu Configs: in.Configs, Context: &ExecuteContext{ IsInteractivitySupported: in.Context.IsInteractivitySupported, + KubeConfig: in.Context.KubeConfig, }, } @@ -192,6 +196,7 @@ func (p *grpcServer) Execute(ctx context.Context, request *ExecuteRequest) (*Exe Context: ExecuteInputContext{ SlackState: &slackState, IsInteractivitySupported: request.Context.IsInteractivitySupported, + KubeConfig: request.Context.KubeConfig, }, }) if err != nil { diff --git a/pkg/api/source/grpc_adapter.go b/pkg/api/source/grpc_adapter.go index 77ff1abd2..c0c05a43e 100644 --- a/pkg/api/source/grpc_adapter.go +++ b/pkg/api/source/grpc_adapter.go @@ -35,7 +35,7 @@ type ( IsInteractivitySupported bool // KubeConfig is the path to kubectl configuration file. - KubeConfig string + KubeConfig []byte // ClusterName is the name of underlying Kubernetes cluster which is provided by end user. ClusterName string diff --git a/pkg/api/source/source.pb.go b/pkg/api/source/source.pb.go index 9bc8f4fa5..903dcddee 100644 --- a/pkg/api/source/source.pb.go +++ b/pkg/api/source/source.pb.go @@ -131,9 +131,10 @@ type StreamContext struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - IsInteractivitySupported bool `protobuf:"varint,1,opt,name=isInteractivitySupported,proto3" json:"isInteractivitySupported,omitempty"` - KubeConfig string `protobuf:"bytes,2,opt,name=kubeConfig,proto3" json:"kubeConfig,omitempty"` - ClusterName string `protobuf:"bytes,3,opt,name=clusterName,proto3" json:"clusterName,omitempty"` + IsInteractivitySupported bool `protobuf:"varint,1,opt,name=isInteractivitySupported,proto3" json:"isInteractivitySupported,omitempty"` + // kubeConfig is is kubeConfig represented in bytes + KubeConfig []byte `protobuf:"bytes,2,opt,name=kubeConfig,proto3" json:"kubeConfig,omitempty"` + ClusterName string `protobuf:"bytes,3,opt,name=clusterName,proto3" json:"clusterName,omitempty"` } func (x *StreamContext) Reset() { @@ -175,11 +176,11 @@ func (x *StreamContext) GetIsInteractivitySupported() bool { return false } -func (x *StreamContext) GetKubeConfig() string { +func (x *StreamContext) GetKubeConfig() []byte { if x != nil { return x.KubeConfig } - return "" + return nil } func (x *StreamContext) GetClusterName() string { @@ -446,7 +447,7 @@ var file_source_proto_rawDesc = []byte{ 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x18, 0x69, 0x73, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x12, 0x1e, 0x0a, 0x0a, 0x6b, 0x75, 0x62, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6b, 0x75, 0x62, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x6b, 0x75, 0x62, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x20, 0x0a, 0x0b, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x3e, 0x0a, 0x0e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x73, diff --git a/pkg/bot/mattermost.go b/pkg/bot/mattermost.go index 3da4a1bf2..a952197bd 100644 --- a/pkg/bot/mattermost.go +++ b/pkg/bot/mattermost.go @@ -376,6 +376,7 @@ func (b *Mattermost) listen(ctx context.Context) { if post.UserId == b.getUser().Id { continue } + mm := &mattermostMessage{ Event: event, IsAuthChannel: false, diff --git a/pkg/bot/socketslack.go b/pkg/bot/socketslack.go index be7b9c7dd..f2e0fdd3a 100644 --- a/pkg/bot/socketslack.go +++ b/pkg/bot/socketslack.go @@ -149,6 +149,7 @@ func (b *SocketSlack) Start(ctx context.Context) error { User: ev.User, CommandOrigin: command.TypedOrigin, } + if err := b.handleMessage(ctx, msg); err != nil { b.log.Errorf("Message handling error: %s", err.Error()) } diff --git a/pkg/config/config.go b/pkg/config/config.go index 3c7333266..cee84708c 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -302,7 +302,8 @@ type Plugin struct { // PluginContext defines the context for given plugin. type PluginContext struct { // RBAC defines the RBAC rules for given plugin. - RBAC PolicyRule `yaml:"rbac"` + RBAC *PolicyRule `yaml:"rbac,omitempty"` + DefaultNamespace string `yaml:"defaultNamespace,omitempty"` } // PolicyRule is the RBAC rule. diff --git a/pkg/config/testdata/TestLoadConfigSuccess/config.golden.yaml b/pkg/config/testdata/TestLoadConfigSuccess/config.golden.yaml index 682ff5ab4..1b9bf5d9d 100644 --- a/pkg/config/testdata/TestLoadConfigSuccess/config.golden.yaml +++ b/pkg/config/testdata/TestLoadConfigSuccess/config.golden.yaml @@ -330,18 +330,7 @@ sources: enabled: true config: field: value - context: - rbac: - user: - type: "" - static: - value: "" - prefix: "" - group: - type: "" - static: - values: [] - prefix: "" + context: {} executors: kubectl-read-only: kubectl: @@ -382,18 +371,7 @@ executors: enabled: true config: changeResponseToUpperCase: true - context: - rbac: - user: - type: "" - static: - value: "" - prefix: "" - group: - type: "" - static: - values: [] - prefix: "" + context: {} aliases: {} communications: default-workspace: diff --git a/pkg/config/validator.go b/pkg/config/validator.go index af3603b20..fe903b497 100644 --- a/pkg/config/validator.go +++ b/pkg/config/validator.go @@ -359,6 +359,10 @@ func validatePluginRBAC[P pluginProvider](sl validator.StructLevel, pluginConfig if !reflect.DeepEqual(firstRBAC, nextCfg.Context.RBAC) { sl.ReportError(bindings, p1, p1, invalidPluginRBACTag, nextIdx) } + + if p1Cfg.Context.DefaultNamespace != nextCfg.Context.DefaultNamespace { + sl.ReportError(bindings, p1, p1, invalidPluginDefaultNSTag, nextIdx) + } } } } diff --git a/pkg/execute/factory.go b/pkg/execute/factory.go index 64324a6be..1a116a585 100644 --- a/pkg/execute/factory.go +++ b/pkg/execute/factory.go @@ -5,6 +5,7 @@ import ( "github.com/sirupsen/logrus" "github.com/slack-go/slack" + "k8s.io/client-go/rest" "github.com/kubeshop/botkube/internal/audit" guard "github.com/kubeshop/botkube/internal/command" @@ -50,6 +51,7 @@ type DefaultExecutorFactoryParams struct { NamespaceLister NamespaceLister CommandGuard CommandGuard PluginManager *plugin.Manager + RestCfg *rest.Config BotKubeVersion string AuditReporter audit.AuditReporter } @@ -160,6 +162,7 @@ func NewExecutorFactory(params DefaultExecutorFactoryParams) (*DefaultExecutorFa params.Log.WithField("component", "Botkube Plugin Executor"), params.Cfg, params.PluginManager, + params.RestCfg, ), sourceBindingExecutor: sourceBindingExecutor, actionExecutor: actionExecutor, diff --git a/pkg/execute/plugin_executor.go b/pkg/execute/plugin_executor.go index 0fb6bc331..b694ec4ac 100644 --- a/pkg/execute/plugin_executor.go +++ b/pkg/execute/plugin_executor.go @@ -7,7 +7,8 @@ import ( "github.com/sirupsen/logrus" "github.com/slack-go/slack" "google.golang.org/grpc/status" - "gopkg.in/yaml.v3" + "k8s.io/client-go/rest" + "sigs.k8s.io/yaml" "github.com/kubeshop/botkube/internal/plugin" "github.com/kubeshop/botkube/pkg/api" @@ -21,14 +22,16 @@ type PluginExecutor struct { log logrus.FieldLogger cfg config.Config pluginManager *plugin.Manager + restCfg *rest.Config } // NewPluginExecutor creates a new instance of PluginExecutor. -func NewPluginExecutor(log logrus.FieldLogger, cfg config.Config, manager *plugin.Manager) *PluginExecutor { +func NewPluginExecutor(log logrus.FieldLogger, cfg config.Config, manager *plugin.Manager, restCfg *rest.Config) *PluginExecutor { return &PluginExecutor{ log: log, cfg: cfg, pluginManager: manager, + restCfg: restCfg, } } @@ -61,7 +64,7 @@ func (e *PluginExecutor) Execute(ctx context.Context, bindings []string, slackSt e.log.WithFields(logrus.Fields{ "bindings": bindings, "command": cmdCtx.CleanCmd, - }).Debugf("Handling plugin command...") + }).Debug("Handling plugin command...") cmdName := cmdCtx.Args[0] plugins, fullPluginName := e.getEnabledPlugins(bindings, cmdName) @@ -71,6 +74,12 @@ func (e *PluginExecutor) Execute(ctx context.Context, bindings []string, slackSt return interactive.CoreMessage{}, fmt.Errorf("while collecting configs: %w", err) } + input := plugin.KubeConfigInput{} + kubeconfig, err := plugin.GenerateKubeConfig(e.restCfg, plugins[0].Context, input) + if err != nil { + return interactive.CoreMessage{}, fmt.Errorf("while generating kube config: %w", err) + } + cli, err := e.pluginManager.GetExecutor(fullPluginName) if err != nil { return interactive.CoreMessage{}, fmt.Errorf("while getting concrete plugin client: %w", err) @@ -82,6 +91,7 @@ func (e *PluginExecutor) Execute(ctx context.Context, bindings []string, slackSt Context: executor.ExecuteInputContext{ IsInteractivitySupported: cmdCtx.Platform.IsInteractive(), SlackState: slackState, + KubeConfig: kubeconfig, }, }) if err != nil { diff --git a/pkg/pluginx/kubeconfig.go b/pkg/pluginx/kubeconfig.go new file mode 100644 index 000000000..98f6ac9b4 --- /dev/null +++ b/pkg/pluginx/kubeconfig.go @@ -0,0 +1,36 @@ +package pluginx + +import ( + "context" + "fmt" + "os" + "path/filepath" + + "github.com/pkg/errors" +) + +func PersistKubeConfig(ctx context.Context, kc []byte) (string, func(context.Context) error, error) { + if len(kc) == 0 { + return "", nil, fmt.Errorf("received empty kube config") + } + + file, err := os.CreateTemp("", "kubeconfig-") + if err != nil { + return "", nil, errors.Wrap(err, "while writing kube config to file") + } + + abs, err := filepath.Abs(file.Name()) + if err != nil { + return "", nil, errors.Wrap(err, "while writing kube config to file") + } + + if _, err = file.Write(kc); err != nil { + return "", nil, errors.Wrap(err, "while writing kube config to file") + } + + deleteFn := func(context.Context) error { + return os.RemoveAll(abs) + } + + return abs, deleteFn, nil +} diff --git a/proto/executor.proto b/proto/executor.proto index 9847037a4..675c651c0 100644 --- a/proto/executor.proto +++ b/proto/executor.proto @@ -23,6 +23,7 @@ message ExecuteRequest { message ExecuteContext { bool isInteractivitySupported = 1; bytes slackState = 2; + bytes kubeConfig = 3; } message ExecuteResponse { diff --git a/proto/source.proto b/proto/source.proto index 236aa5e09..16686f9f5 100644 --- a/proto/source.proto +++ b/proto/source.proto @@ -20,7 +20,8 @@ message StreamRequest { message StreamContext { bool isInteractivitySupported = 1; - string kubeConfig = 2; + // kubeConfig is is kubeConfig represented in bytes + bytes kubeConfig = 2; string clusterName = 3; }