mirror of
https://github.com/kyverno/policy-reporter.git
synced 2024-12-14 11:57:32 +00:00
Merge pull request #342 from kyverno/google-chat
google chat notifications
This commit is contained in:
commit
cf4655643c
9 changed files with 903 additions and 588 deletions
|
@ -177,6 +177,31 @@ telegram:
|
|||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
|
||||
googleChat:
|
||||
webhook: {{ .Values.target.googleChat.webhook | quote }}
|
||||
certificate: {{ .Values.target.googleChat.certificate | quote }}
|
||||
skipTLS: {{ .Values.target.googleChat.skipTLS }}
|
||||
secretRef: {{ .Values.target.googleChat.secretRef | quote }}
|
||||
mountedSecret: {{ .Values.target.googleChat.mountedSecret | quote }}
|
||||
minimumPriority: {{ .Values.target.googleChat.minimumPriority | quote }}
|
||||
skipExistingOnStartup: {{ .Values.target.googleChat.skipExistingOnStartup }}
|
||||
{{- with .Values.target.googleChat.sources }}
|
||||
sources:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
{{- with .Values.target.googleChat.customFields }}
|
||||
customFields:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
{{- with .Values.target.googleChat.filter }}
|
||||
filter:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
{{- with .Values.target.googleChat.channels }}
|
||||
channels:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
|
||||
ui:
|
||||
host: {{ include "policyreporter.uihost" . }}
|
||||
certificate: {{ .Values.target.ui.certificate | quote }}
|
||||
|
|
|
@ -514,6 +514,33 @@ target:
|
|||
# add additional telegram channels with different configurations and filters
|
||||
channels: []
|
||||
|
||||
googleChat:
|
||||
# GoogleChat webhook
|
||||
webhook: ""
|
||||
# path to your custom certificate
|
||||
# can be added under extraVolumes
|
||||
certificate: ""
|
||||
# skip TLS verification if necessary
|
||||
skipTLS: false
|
||||
# receive the host and/or token from an existing secret, the token is added as Authorization header
|
||||
secretRef: ""
|
||||
# Mounted secret path by Secrets Controller, secret should be in json format
|
||||
mountedSecret: ""
|
||||
# additional http headers
|
||||
headers: {}
|
||||
# minimum priority "" < info < warning < critical < error
|
||||
minimumPriority: ""
|
||||
# list of sources which should send to telegram
|
||||
sources: []
|
||||
# Skip already existing PolicyReportResults on startup
|
||||
skipExistingOnStartup: true
|
||||
# Added as additional properties to each notification
|
||||
customFields: {}
|
||||
# filter results send by namespaces, policies and priorities
|
||||
filter: {}
|
||||
# add additional telegram channels with different configurations and filters
|
||||
channels: []
|
||||
|
||||
s3:
|
||||
# S3 access key
|
||||
accessKeyID: ""
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package config
|
||||
|
||||
import "github.com/kyverno/policy-reporter/pkg/target"
|
||||
|
||||
type ValueFilter struct {
|
||||
Include []string `mapstructure:"include"`
|
||||
Exclude []string `mapstructure:"exclude"`
|
||||
|
@ -37,6 +39,54 @@ type TargetBaseOptions struct {
|
|||
SkipExisting bool `mapstructure:"skipExistingOnStartup"`
|
||||
}
|
||||
|
||||
func (config *TargetBaseOptions) MapBaseParent(parent TargetBaseOptions) {
|
||||
if config.MinimumPriority == "" {
|
||||
config.MinimumPriority = parent.MinimumPriority
|
||||
}
|
||||
|
||||
if !config.SkipExisting {
|
||||
config.SkipExisting = parent.SkipExisting
|
||||
}
|
||||
}
|
||||
|
||||
func (config *TargetBaseOptions) ClientOptions() target.ClientOptions {
|
||||
return target.ClientOptions{
|
||||
Name: config.Name,
|
||||
SkipExistingOnStartup: config.SkipExisting,
|
||||
ResultFilter: createResultFilter(config.Filter, config.MinimumPriority, config.Sources),
|
||||
ReportFilter: createReportFilter(config.Filter),
|
||||
}
|
||||
}
|
||||
|
||||
type AWSConfig struct {
|
||||
AccessKeyID string `mapstructure:"accessKeyID"`
|
||||
SecretAccessKey string `mapstructure:"secretAccessKey"`
|
||||
Region string `mapstructure:"region"`
|
||||
Endpoint string `mapstructure:"endpoint"`
|
||||
}
|
||||
|
||||
func (config *AWSConfig) MapAWSParent(parent AWSConfig) {
|
||||
if config.Endpoint == "" {
|
||||
config.Endpoint = parent.Endpoint
|
||||
}
|
||||
|
||||
if config.AccessKeyID == "" {
|
||||
config.AccessKeyID = parent.AccessKeyID
|
||||
}
|
||||
|
||||
if config.SecretAccessKey == "" {
|
||||
config.SecretAccessKey = parent.SecretAccessKey
|
||||
}
|
||||
|
||||
if config.Region == "" {
|
||||
config.Region = parent.Region
|
||||
}
|
||||
}
|
||||
|
||||
type TargetOption interface {
|
||||
BaseOptions() *TargetBaseOptions
|
||||
}
|
||||
|
||||
// Loki configuration
|
||||
type Loki struct {
|
||||
TargetBaseOptions `mapstructure:",squash"`
|
||||
|
@ -45,44 +95,44 @@ type Loki struct {
|
|||
SkipTLS bool `mapstructure:"skipTLS"`
|
||||
Certificate string `mapstructure:"certificate"`
|
||||
Path string `mapstructure:"path"`
|
||||
Channels []Loki `mapstructure:"channels"`
|
||||
Channels []*Loki `mapstructure:"channels"`
|
||||
}
|
||||
|
||||
// Elasticsearch configuration
|
||||
type Elasticsearch struct {
|
||||
TargetBaseOptions `mapstructure:",squash"`
|
||||
Host string `mapstructure:"host"`
|
||||
SkipTLS bool `mapstructure:"skipTLS"`
|
||||
Certificate string `mapstructure:"certificate"`
|
||||
Index string `mapstructure:"index"`
|
||||
Rotation string `mapstructure:"rotation"`
|
||||
Username string `mapstructure:"username"`
|
||||
Password string `mapstructure:"password"`
|
||||
Channels []Elasticsearch `mapstructure:"channels"`
|
||||
Host string `mapstructure:"host"`
|
||||
SkipTLS bool `mapstructure:"skipTLS"`
|
||||
Certificate string `mapstructure:"certificate"`
|
||||
Index string `mapstructure:"index"`
|
||||
Rotation string `mapstructure:"rotation"`
|
||||
Username string `mapstructure:"username"`
|
||||
Password string `mapstructure:"password"`
|
||||
Channels []*Elasticsearch `mapstructure:"channels"`
|
||||
}
|
||||
|
||||
// Slack configuration
|
||||
type Slack struct {
|
||||
TargetBaseOptions `mapstructure:",squash"`
|
||||
Webhook string `mapstructure:"webhook"`
|
||||
Channel string `mapstructure:"channel"`
|
||||
Channels []Slack `mapstructure:"channels"`
|
||||
Webhook string `mapstructure:"webhook"`
|
||||
Channel string `mapstructure:"channel"`
|
||||
Channels []*Slack `mapstructure:"channels"`
|
||||
}
|
||||
|
||||
// Discord configuration
|
||||
type Discord struct {
|
||||
TargetBaseOptions `mapstructure:",squash"`
|
||||
Webhook string `mapstructure:"webhook"`
|
||||
Channels []Discord `mapstructure:"channels"`
|
||||
Webhook string `mapstructure:"webhook"`
|
||||
Channels []*Discord `mapstructure:"channels"`
|
||||
}
|
||||
|
||||
// Teams configuration
|
||||
type Teams struct {
|
||||
TargetBaseOptions `mapstructure:",squash"`
|
||||
Webhook string `mapstructure:"webhook"`
|
||||
SkipTLS bool `mapstructure:"skipTLS"`
|
||||
Certificate string `mapstructure:"certificate"`
|
||||
Channels []Teams `mapstructure:"channels"`
|
||||
Webhook string `mapstructure:"webhook"`
|
||||
SkipTLS bool `mapstructure:"skipTLS"`
|
||||
Certificate string `mapstructure:"certificate"`
|
||||
Channels []*Teams `mapstructure:"channels"`
|
||||
}
|
||||
|
||||
// UI configuration
|
||||
|
@ -100,7 +150,7 @@ type Webhook struct {
|
|||
SkipTLS bool `mapstructure:"skipTLS"`
|
||||
Certificate string `mapstructure:"certificate"`
|
||||
Headers map[string]string `mapstructure:"headers"`
|
||||
Channels []Webhook `mapstructure:"channels"`
|
||||
Channels []*Webhook `mapstructure:"channels"`
|
||||
}
|
||||
|
||||
// Telegram configuration
|
||||
|
@ -112,14 +162,17 @@ type Telegram struct {
|
|||
SkipTLS bool `mapstructure:"skipTLS"`
|
||||
Certificate string `mapstructure:"certificate"`
|
||||
Headers map[string]string `mapstructure:"headers"`
|
||||
Channels []Telegram `mapstructure:"channels"`
|
||||
Channels []*Telegram `mapstructure:"channels"`
|
||||
}
|
||||
|
||||
type AWSConfig struct {
|
||||
AccessKeyID string `mapstructure:"accessKeyID"`
|
||||
SecretAccessKey string `mapstructure:"secretAccessKey"`
|
||||
Region string `mapstructure:"region"`
|
||||
Endpoint string `mapstructure:"endpoint"`
|
||||
// GoogleChat configuration
|
||||
type GoogleChat struct {
|
||||
TargetBaseOptions `mapstructure:",squash"`
|
||||
Webhook string `mapstructure:"webhook"`
|
||||
SkipTLS bool `mapstructure:"skipTLS"`
|
||||
Certificate string `mapstructure:"certificate"`
|
||||
Headers map[string]string `mapstructure:"headers"`
|
||||
Channels []*GoogleChat `mapstructure:"channels"`
|
||||
}
|
||||
|
||||
// S3 configuration
|
||||
|
@ -132,23 +185,23 @@ type S3 struct {
|
|||
KmsKeyID string `mapstructure:"kmsKeyId"`
|
||||
ServerSideEncryption string `mapstructure:"serverSideEncryption"`
|
||||
PathStyle bool `mapstructure:"pathStyle"`
|
||||
Channels []S3 `mapstructure:"channels"`
|
||||
Channels []*S3 `mapstructure:"channels"`
|
||||
}
|
||||
|
||||
// Kinesis configuration
|
||||
type Kinesis struct {
|
||||
TargetBaseOptions `mapstructure:",squash"`
|
||||
AWSConfig `mapstructure:",squash"`
|
||||
StreamName string `mapstructure:"streamName"`
|
||||
Channels []Kinesis `mapstructure:"channels"`
|
||||
StreamName string `mapstructure:"streamName"`
|
||||
Channels []*Kinesis `mapstructure:"channels"`
|
||||
}
|
||||
|
||||
// SecurityHub configuration
|
||||
type SecurityHub struct {
|
||||
TargetBaseOptions `mapstructure:",squash"`
|
||||
AWSConfig `mapstructure:",squash"`
|
||||
AccountID string `mapstructure:"accountId"`
|
||||
Channels []SecurityHub `mapstructure:"channels"`
|
||||
AccountID string `mapstructure:"accountId"`
|
||||
Channels []*SecurityHub `mapstructure:"channels"`
|
||||
}
|
||||
|
||||
// GCS configuration
|
||||
|
@ -158,7 +211,7 @@ type GCS struct {
|
|||
Prefix string `mapstructure:"prefix"`
|
||||
Bucket string `mapstructure:"bucket"`
|
||||
Sources []string `mapstructure:"sources"`
|
||||
Channels []GCS `mapstructure:"channels"`
|
||||
Channels []*GCS `mapstructure:"channels"`
|
||||
}
|
||||
|
||||
// SMTP configuration
|
||||
|
@ -283,18 +336,19 @@ type Database struct {
|
|||
type Config struct {
|
||||
Version string
|
||||
Namespace string `mapstructure:"namespace"`
|
||||
Loki Loki `mapstructure:"loki"`
|
||||
Elasticsearch Elasticsearch `mapstructure:"elasticsearch"`
|
||||
Slack Slack `mapstructure:"slack"`
|
||||
Discord Discord `mapstructure:"discord"`
|
||||
Teams Teams `mapstructure:"teams"`
|
||||
S3 S3 `mapstructure:"s3"`
|
||||
Kinesis Kinesis `mapstructure:"kinesis"`
|
||||
SecurityHub SecurityHub `mapstructure:"securityHub"`
|
||||
GCS GCS `mapstructure:"gcs"`
|
||||
UI UI `mapstructure:"ui"`
|
||||
Webhook Webhook `mapstructure:"webhook"`
|
||||
Telegram Telegram `mapstructure:"telegram"`
|
||||
Loki *Loki `mapstructure:"loki"`
|
||||
Elasticsearch *Elasticsearch `mapstructure:"elasticsearch"`
|
||||
Slack *Slack `mapstructure:"slack"`
|
||||
Discord *Discord `mapstructure:"discord"`
|
||||
Teams *Teams `mapstructure:"teams"`
|
||||
S3 *S3 `mapstructure:"s3"`
|
||||
Kinesis *Kinesis `mapstructure:"kinesis"`
|
||||
SecurityHub *SecurityHub `mapstructure:"securityHub"`
|
||||
GCS *GCS `mapstructure:"gcs"`
|
||||
UI *UI `mapstructure:"ui"`
|
||||
Webhook *Webhook `mapstructure:"webhook"`
|
||||
Telegram *Telegram `mapstructure:"telegram"`
|
||||
GoogleChat *GoogleChat `mapstructure:"googleChat"`
|
||||
API API `mapstructure:"api"`
|
||||
WorkerCount int `mapstructure:"worker"`
|
||||
DBFile string `mapstructure:"dbfile"`
|
||||
|
|
|
@ -280,6 +280,7 @@ func (r *Resolver) TargetClients() []target.Client {
|
|||
clients = append(clients, factory.WebhookClients(r.config.Webhook)...)
|
||||
clients = append(clients, factory.GCSClients(r.config.GCS)...)
|
||||
clients = append(clients, factory.TelegramClients(r.config.Telegram)...)
|
||||
clients = append(clients, factory.GoogleChatClients(r.config.GoogleChat)...)
|
||||
|
||||
if ui := factory.UIClient(r.config.UI); ui != nil {
|
||||
clients = append(clients, ui)
|
||||
|
|
|
@ -12,7 +12,7 @@ import (
|
|||
)
|
||||
|
||||
var testConfig = &config.Config{
|
||||
Loki: config.Loki{
|
||||
Loki: &config.Loki{
|
||||
Host: "http://localhost:3100",
|
||||
TargetBaseOptions: config.TargetBaseOptions{
|
||||
SkipExisting: true,
|
||||
|
@ -20,7 +20,7 @@ var testConfig = &config.Config{
|
|||
CustomFields: map[string]string{"field": "value"},
|
||||
},
|
||||
SkipTLS: true,
|
||||
Channels: []config.Loki{
|
||||
Channels: []*config.Loki{
|
||||
{
|
||||
TargetBaseOptions: config.TargetBaseOptions{
|
||||
CustomFields: map[string]string{"label2": "value2"},
|
||||
|
@ -28,7 +28,7 @@ var testConfig = &config.Config{
|
|||
},
|
||||
},
|
||||
},
|
||||
Elasticsearch: config.Elasticsearch{
|
||||
Elasticsearch: &config.Elasticsearch{
|
||||
Host: "http://localhost:9200",
|
||||
Index: "policy-reporter",
|
||||
Rotation: "daily",
|
||||
|
@ -38,33 +38,33 @@ var testConfig = &config.Config{
|
|||
CustomFields: map[string]string{"field": "value"},
|
||||
},
|
||||
SkipTLS: true,
|
||||
Channels: []config.Elasticsearch{{}},
|
||||
Channels: []*config.Elasticsearch{{}},
|
||||
},
|
||||
Slack: config.Slack{
|
||||
Slack: &config.Slack{
|
||||
Webhook: "http://hook.slack:80",
|
||||
TargetBaseOptions: config.TargetBaseOptions{
|
||||
SkipExisting: true,
|
||||
MinimumPriority: "debug",
|
||||
CustomFields: map[string]string{"field": "value"},
|
||||
},
|
||||
Channels: []config.Slack{{
|
||||
Channels: []*config.Slack{{
|
||||
Webhook: "http://localhost:9200",
|
||||
}, {
|
||||
Channel: "general",
|
||||
}},
|
||||
},
|
||||
Discord: config.Discord{
|
||||
Discord: &config.Discord{
|
||||
Webhook: "http://hook.discord:80",
|
||||
TargetBaseOptions: config.TargetBaseOptions{
|
||||
SkipExisting: true,
|
||||
MinimumPriority: "debug",
|
||||
CustomFields: map[string]string{"field": "value"},
|
||||
},
|
||||
Channels: []config.Discord{{
|
||||
Channels: []*config.Discord{{
|
||||
Webhook: "http://localhost:9200",
|
||||
}},
|
||||
},
|
||||
Teams: config.Teams{
|
||||
Teams: &config.Teams{
|
||||
TargetBaseOptions: config.TargetBaseOptions{
|
||||
SkipExisting: true,
|
||||
MinimumPriority: "debug",
|
||||
|
@ -72,18 +72,18 @@ var testConfig = &config.Config{
|
|||
},
|
||||
Webhook: "http://hook.teams:80",
|
||||
SkipTLS: true,
|
||||
Channels: []config.Teams{{
|
||||
Channels: []*config.Teams{{
|
||||
Webhook: "http://localhost:9200",
|
||||
}},
|
||||
},
|
||||
UI: config.UI{
|
||||
UI: &config.UI{
|
||||
TargetBaseOptions: config.TargetBaseOptions{
|
||||
SkipExisting: true,
|
||||
MinimumPriority: "debug",
|
||||
},
|
||||
Host: "http://localhost:8080",
|
||||
},
|
||||
Webhook: config.Webhook{
|
||||
Webhook: &config.Webhook{
|
||||
Host: "http://localhost:8080",
|
||||
Headers: map[string]string{
|
||||
"X-Custom": "Header",
|
||||
|
@ -94,14 +94,14 @@ var testConfig = &config.Config{
|
|||
CustomFields: map[string]string{"field": "value"},
|
||||
},
|
||||
SkipTLS: true,
|
||||
Channels: []config.Webhook{{
|
||||
Channels: []*config.Webhook{{
|
||||
Host: "http://localhost:8081",
|
||||
Headers: map[string]string{
|
||||
"X-Custom-2": "Header",
|
||||
},
|
||||
}},
|
||||
},
|
||||
S3: config.S3{
|
||||
S3: &config.S3{
|
||||
TargetBaseOptions: config.TargetBaseOptions{
|
||||
SkipExisting: true,
|
||||
MinimumPriority: "debug",
|
||||
|
@ -119,9 +119,9 @@ var testConfig = &config.Config{
|
|||
ServerSideEncryption: "",
|
||||
PathStyle: true,
|
||||
Prefix: "prefix",
|
||||
Channels: []config.S3{{}},
|
||||
Channels: []*config.S3{{}},
|
||||
},
|
||||
Kinesis: config.Kinesis{
|
||||
Kinesis: &config.Kinesis{
|
||||
TargetBaseOptions: config.TargetBaseOptions{
|
||||
SkipExisting: true,
|
||||
MinimumPriority: "debug",
|
||||
|
@ -134,9 +134,9 @@ var testConfig = &config.Config{
|
|||
Region: "ru-central1",
|
||||
},
|
||||
StreamName: "policy-reporter",
|
||||
Channels: []config.Kinesis{{}},
|
||||
Channels: []*config.Kinesis{{}},
|
||||
},
|
||||
SecurityHub: config.SecurityHub{
|
||||
SecurityHub: &config.SecurityHub{
|
||||
TargetBaseOptions: config.TargetBaseOptions{
|
||||
SkipExisting: true,
|
||||
MinimumPriority: "debug",
|
||||
|
@ -149,9 +149,9 @@ var testConfig = &config.Config{
|
|||
Region: "ru-central1",
|
||||
},
|
||||
AccountID: "AccountID",
|
||||
Channels: []config.SecurityHub{{}},
|
||||
Channels: []*config.SecurityHub{{}},
|
||||
},
|
||||
GCS: config.GCS{
|
||||
GCS: &config.GCS{
|
||||
TargetBaseOptions: config.TargetBaseOptions{
|
||||
SkipExisting: true,
|
||||
MinimumPriority: "debug",
|
||||
|
@ -160,7 +160,7 @@ var testConfig = &config.Config{
|
|||
Credentials: `{"token": "token", "type": "authorized_user"}`,
|
||||
Bucket: "test",
|
||||
Prefix: "prefix",
|
||||
Channels: []config.GCS{{}},
|
||||
Channels: []*config.GCS{{}},
|
||||
},
|
||||
EmailReports: config.EmailReports{
|
||||
Templates: config.EmailTemplates{
|
||||
|
@ -175,22 +175,26 @@ var testConfig = &config.Config{
|
|||
Encryption: "ssl/tls",
|
||||
},
|
||||
},
|
||||
Telegram: config.Telegram{
|
||||
Telegram: &config.Telegram{
|
||||
Token: "XXX",
|
||||
ChatID: "123456",
|
||||
Channels: []config.Telegram{
|
||||
Channels: []*config.Telegram{
|
||||
{
|
||||
ChatID: "1234567",
|
||||
},
|
||||
},
|
||||
},
|
||||
GoogleChat: &config.GoogleChat{
|
||||
Webhook: "http://localhost:900/webhook",
|
||||
Channels: []*config.GoogleChat{{}},
|
||||
},
|
||||
}
|
||||
|
||||
func Test_ResolveTargets(t *testing.T) {
|
||||
resolver := config.NewResolver(testConfig, &rest.Config{})
|
||||
|
||||
if count := len(resolver.TargetClients()); count != 24 {
|
||||
t.Errorf("Expected 24 Clients, got %d", count)
|
||||
if count := len(resolver.TargetClients()); count != 26 {
|
||||
t.Errorf("Expected 26 Clients, got %d", count)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -204,14 +208,14 @@ func Test_ResolveHasTargets(t *testing.T) {
|
|||
|
||||
func Test_ResolveSkipExistingOnStartup(t *testing.T) {
|
||||
testConfig := &config.Config{
|
||||
Loki: config.Loki{
|
||||
Loki: &config.Loki{
|
||||
Host: "http://localhost:3100",
|
||||
TargetBaseOptions: config.TargetBaseOptions{
|
||||
SkipExisting: true,
|
||||
MinimumPriority: "debug",
|
||||
},
|
||||
},
|
||||
Elasticsearch: config.Elasticsearch{
|
||||
Elasticsearch: &config.Elasticsearch{
|
||||
Host: "http://localhost:9200",
|
||||
TargetBaseOptions: config.TargetBaseOptions{
|
||||
SkipExisting: true,
|
||||
|
@ -554,7 +558,7 @@ func Test_ResolveEnableLeaderElection(t *testing.T) {
|
|||
t.Run("general disabled", func(t *testing.T) {
|
||||
resolver := config.NewResolver(&config.Config{
|
||||
LeaderElection: config.LeaderElection{Enabled: false},
|
||||
Loki: config.Loki{Host: "localhost:3100"},
|
||||
Loki: &config.Loki{Host: "localhost:3100"},
|
||||
Database: config.Database{Type: database.MySQL},
|
||||
}, &rest.Config{})
|
||||
|
||||
|
@ -579,7 +583,7 @@ func Test_ResolveEnableLeaderElection(t *testing.T) {
|
|||
resolver := config.NewResolver(&config.Config{
|
||||
LeaderElection: config.LeaderElection{Enabled: true},
|
||||
Database: config.Database{Type: database.SQLite},
|
||||
Loki: config.Loki{Host: "localhost:3100"},
|
||||
Loki: &config.Loki{Host: "localhost:3100"},
|
||||
DBFile: "test.db",
|
||||
}, &rest.Config{})
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -108,6 +108,12 @@ func Test_ResolveTarget(t *testing.T) {
|
|||
t.Errorf("Expected 2 Client, got %d clients", len(clients))
|
||||
}
|
||||
})
|
||||
t.Run("GoogleChat", func(t *testing.T) {
|
||||
clients := factory.GoogleChatClients(testConfig.GoogleChat)
|
||||
if len(clients) != 2 {
|
||||
t.Errorf("Expected 2 Client, got %d clients", len(clients))
|
||||
}
|
||||
})
|
||||
t.Run("S3", func(t *testing.T) {
|
||||
clients := factory.S3Clients(testConfig.S3)
|
||||
if len(clients) != 2 {
|
||||
|
@ -138,137 +144,142 @@ func Test_ResolveTargetWithoutHost(t *testing.T) {
|
|||
factory := config.NewTargetFactory(nil)
|
||||
|
||||
t.Run("Loki", func(t *testing.T) {
|
||||
if len(factory.LokiClients(config.Loki{})) != 0 {
|
||||
if len(factory.LokiClients(&config.Loki{})) != 0 {
|
||||
t.Error("Expected Client to be nil if no host is configured")
|
||||
}
|
||||
})
|
||||
t.Run("Elasticsearch", func(t *testing.T) {
|
||||
if len(factory.ElasticsearchClients(config.Elasticsearch{})) != 0 {
|
||||
if len(factory.ElasticsearchClients(&config.Elasticsearch{})) != 0 {
|
||||
t.Error("Expected Client to be nil if no host is configured")
|
||||
}
|
||||
})
|
||||
t.Run("Slack", func(t *testing.T) {
|
||||
if len(factory.SlackClients(config.Slack{})) != 0 {
|
||||
if len(factory.SlackClients(&config.Slack{})) != 0 {
|
||||
t.Error("Expected Client to be nil if no host is configured")
|
||||
}
|
||||
})
|
||||
t.Run("Discord", func(t *testing.T) {
|
||||
if len(factory.DiscordClients(config.Discord{})) != 0 {
|
||||
if len(factory.DiscordClients(&config.Discord{})) != 0 {
|
||||
t.Error("Expected Client to be nil if no host is configured")
|
||||
}
|
||||
})
|
||||
t.Run("Teams", func(t *testing.T) {
|
||||
if len(factory.TeamsClients(config.Teams{})) != 0 {
|
||||
if len(factory.TeamsClients(&config.Teams{})) != 0 {
|
||||
t.Error("Expected Client to be nil if no host is configured")
|
||||
}
|
||||
})
|
||||
t.Run("Webhook", func(t *testing.T) {
|
||||
if len(factory.WebhookClients(config.Webhook{})) != 0 {
|
||||
if len(factory.WebhookClients(&config.Webhook{})) != 0 {
|
||||
t.Error("Expected Client to be nil if no host is configured")
|
||||
}
|
||||
})
|
||||
t.Run("Telegram", func(t *testing.T) {
|
||||
if len(factory.TelegramClients(config.Telegram{})) != 0 {
|
||||
if len(factory.TelegramClients(&config.Telegram{})) != 0 {
|
||||
t.Error("Expected Client to be nil if no chatID is configured")
|
||||
}
|
||||
})
|
||||
t.Run("GoogleChat", func(t *testing.T) {
|
||||
if len(factory.GoogleChatClients(&config.GoogleChat{})) != 0 {
|
||||
t.Error("Expected Client to be nil if no webhook is configured")
|
||||
}
|
||||
})
|
||||
t.Run("S3.Endoint", func(t *testing.T) {
|
||||
if len(factory.S3Clients(config.S3{})) != 0 {
|
||||
if len(factory.S3Clients(&config.S3{})) != 0 {
|
||||
t.Error("Expected Client to be nil if no endpoint is configured")
|
||||
}
|
||||
})
|
||||
t.Run("S3.AccessKey", func(t *testing.T) {
|
||||
if len(factory.S3Clients(config.S3{AWSConfig: config.AWSConfig{Endpoint: "https://storage.yandexcloud.net"}})) != 0 {
|
||||
if len(factory.S3Clients(&config.S3{AWSConfig: config.AWSConfig{Endpoint: "https://storage.yandexcloud.net"}})) != 0 {
|
||||
t.Error("Expected Client to be nil if no accessKey is configured")
|
||||
}
|
||||
})
|
||||
t.Run("S3.SecretAccessKey", func(t *testing.T) {
|
||||
if len(factory.S3Clients(config.S3{AWSConfig: config.AWSConfig{Endpoint: "https://storage.yandexcloud.net", AccessKeyID: "access"}})) != 0 {
|
||||
if len(factory.S3Clients(&config.S3{AWSConfig: config.AWSConfig{Endpoint: "https://storage.yandexcloud.net", AccessKeyID: "access"}})) != 0 {
|
||||
t.Error("Expected Client to be nil if no secretAccessKey is configured")
|
||||
}
|
||||
})
|
||||
t.Run("S3.Region", func(t *testing.T) {
|
||||
if len(factory.S3Clients(config.S3{AWSConfig: config.AWSConfig{Endpoint: "https://storage.yandexcloud.net", AccessKeyID: "access", SecretAccessKey: "secret"}})) != 0 {
|
||||
if len(factory.S3Clients(&config.S3{AWSConfig: config.AWSConfig{Endpoint: "https://storage.yandexcloud.net", AccessKeyID: "access", SecretAccessKey: "secret"}})) != 0 {
|
||||
t.Error("Expected Client to be nil if no region is configured")
|
||||
}
|
||||
})
|
||||
t.Run("S3.Bucket", func(t *testing.T) {
|
||||
if len(factory.S3Clients(config.S3{AWSConfig: config.AWSConfig{Endpoint: "https://storage.yandexcloud.net", AccessKeyID: "access", SecretAccessKey: "secret", Region: "ru-central1"}})) != 0 {
|
||||
if len(factory.S3Clients(&config.S3{AWSConfig: config.AWSConfig{Endpoint: "https://storage.yandexcloud.net", AccessKeyID: "access", SecretAccessKey: "secret", Region: "ru-central1"}})) != 0 {
|
||||
t.Error("Expected Client to be nil if no bucket is configured")
|
||||
}
|
||||
})
|
||||
t.Run("S3.SSE-S3", func(t *testing.T) {
|
||||
if len(factory.S3Clients(config.S3{AWSConfig: config.AWSConfig{Endpoint: "https://storage.yandexcloud.net", AccessKeyID: "access", SecretAccessKey: "secret", Region: "ru-central1"}, ServerSideEncryption: "AES256"})) != 0 {
|
||||
if len(factory.S3Clients(&config.S3{AWSConfig: config.AWSConfig{Endpoint: "https://storage.yandexcloud.net", AccessKeyID: "access", SecretAccessKey: "secret", Region: "ru-central1"}, ServerSideEncryption: "AES256"})) != 0 {
|
||||
t.Error("Expected Client to be nil if server side encryption is not configured")
|
||||
}
|
||||
})
|
||||
t.Run("S3.SSE-KMS", func(t *testing.T) {
|
||||
if len(factory.S3Clients(config.S3{AWSConfig: config.AWSConfig{Endpoint: "https://storage.yandexcloud.net", AccessKeyID: "access", SecretAccessKey: "secret", Region: "ru-central1"}, ServerSideEncryption: "aws:kms"})) != 0 {
|
||||
if len(factory.S3Clients(&config.S3{AWSConfig: config.AWSConfig{Endpoint: "https://storage.yandexcloud.net", AccessKeyID: "access", SecretAccessKey: "secret", Region: "ru-central1"}, ServerSideEncryption: "aws:kms"})) != 0 {
|
||||
t.Error("Expected Client to be nil if server side encryption is not configured")
|
||||
}
|
||||
})
|
||||
t.Run("S3.SSE-KMS-S3-KEY", func(t *testing.T) {
|
||||
if len(factory.S3Clients(config.S3{AWSConfig: config.AWSConfig{Endpoint: "https://storage.yandexcloud.net", AccessKeyID: "access", SecretAccessKey: "secret", Region: "ru-central1"}, BucketKeyEnabled: true, ServerSideEncryption: "aws:kms"})) != 0 {
|
||||
if len(factory.S3Clients(&config.S3{AWSConfig: config.AWSConfig{Endpoint: "https://storage.yandexcloud.net", AccessKeyID: "access", SecretAccessKey: "secret", Region: "ru-central1"}, BucketKeyEnabled: true, ServerSideEncryption: "aws:kms"})) != 0 {
|
||||
t.Error("Expected Client to be nil if server side encryption is not configured")
|
||||
}
|
||||
})
|
||||
t.Run("S3.SSE-KMS-KEY-ID", func(t *testing.T) {
|
||||
if len(factory.S3Clients(config.S3{AWSConfig: config.AWSConfig{Endpoint: "https://storage.yandexcloud.net", AccessKeyID: "access", SecretAccessKey: "secret", Region: "ru-central1"}, ServerSideEncryption: "aws:kms", KmsKeyID: "kmsKeyId"})) != 0 {
|
||||
if len(factory.S3Clients(&config.S3{AWSConfig: config.AWSConfig{Endpoint: "https://storage.yandexcloud.net", AccessKeyID: "access", SecretAccessKey: "secret", Region: "ru-central1"}, ServerSideEncryption: "aws:kms", KmsKeyID: "kmsKeyId"})) != 0 {
|
||||
t.Error("Expected Client to be nil if server side encryption is not configured")
|
||||
}
|
||||
})
|
||||
t.Run("Kinesis.Endpoint", func(t *testing.T) {
|
||||
if len(factory.KinesisClients(config.Kinesis{})) != 0 {
|
||||
if len(factory.KinesisClients(&config.Kinesis{})) != 0 {
|
||||
t.Error("Expected Client to be nil if no endpoint is configured")
|
||||
}
|
||||
})
|
||||
t.Run("Kinesis.AccessKey", func(t *testing.T) {
|
||||
if len(factory.KinesisClients(config.Kinesis{AWSConfig: config.AWSConfig{Endpoint: "https://yds.serverless.yandexcloud.net"}})) != 0 {
|
||||
if len(factory.KinesisClients(&config.Kinesis{AWSConfig: config.AWSConfig{Endpoint: "https://yds.serverless.yandexcloud.net"}})) != 0 {
|
||||
t.Error("Expected Client to be nil if no accessKey is configured")
|
||||
}
|
||||
})
|
||||
t.Run("Kinesis.SecretAccessKey", func(t *testing.T) {
|
||||
if len(factory.KinesisClients(config.Kinesis{AWSConfig: config.AWSConfig{Endpoint: "https://yds.serverless.yandexcloud.net", AccessKeyID: "access"}})) != 0 {
|
||||
if len(factory.KinesisClients(&config.Kinesis{AWSConfig: config.AWSConfig{Endpoint: "https://yds.serverless.yandexcloud.net", AccessKeyID: "access"}})) != 0 {
|
||||
t.Error("Expected Client to be nil if no secretAccessKey is configured")
|
||||
}
|
||||
})
|
||||
t.Run("Kinesis.Region", func(t *testing.T) {
|
||||
if len(factory.KinesisClients(config.Kinesis{AWSConfig: config.AWSConfig{Endpoint: "https://yds.serverless.yandexcloud.net", AccessKeyID: "access", SecretAccessKey: "secret"}})) != 0 {
|
||||
if len(factory.KinesisClients(&config.Kinesis{AWSConfig: config.AWSConfig{Endpoint: "https://yds.serverless.yandexcloud.net", AccessKeyID: "access", SecretAccessKey: "secret"}})) != 0 {
|
||||
t.Error("Expected Client to be nil if no region is configured")
|
||||
}
|
||||
})
|
||||
t.Run("Kinesis.StreamName", func(t *testing.T) {
|
||||
if len(factory.KinesisClients(config.Kinesis{AWSConfig: config.AWSConfig{Endpoint: "https://yds.serverless.yandexcloud.net", AccessKeyID: "access", SecretAccessKey: "secret", Region: "ru-central1"}})) != 0 {
|
||||
if len(factory.KinesisClients(&config.Kinesis{AWSConfig: config.AWSConfig{Endpoint: "https://yds.serverless.yandexcloud.net", AccessKeyID: "access", SecretAccessKey: "secret", Region: "ru-central1"}})) != 0 {
|
||||
t.Error("Expected Client to be nil if no stream name is configured")
|
||||
}
|
||||
})
|
||||
t.Run("SecurityHub.AccountID", func(t *testing.T) {
|
||||
if len(factory.SecurityHubs(config.SecurityHub{})) != 0 {
|
||||
if len(factory.SecurityHubs(&config.SecurityHub{})) != 0 {
|
||||
t.Error("Expected Client to be nil if no accountID is configured")
|
||||
}
|
||||
})
|
||||
t.Run("SecurityHub.AccessKey", func(t *testing.T) {
|
||||
if len(factory.SecurityHubs(config.SecurityHub{AccountID: "accountID"})) != 0 {
|
||||
if len(factory.SecurityHubs(&config.SecurityHub{AccountID: "accountID"})) != 0 {
|
||||
t.Error("Expected Client to be nil if no accessKey is configured")
|
||||
}
|
||||
})
|
||||
t.Run("SecurityHub.SecretAccessKey", func(t *testing.T) {
|
||||
if len(factory.SecurityHubs(config.SecurityHub{AccountID: "accountID", AWSConfig: config.AWSConfig{AccessKeyID: "access"}})) != 0 {
|
||||
if len(factory.SecurityHubs(&config.SecurityHub{AccountID: "accountID", AWSConfig: config.AWSConfig{AccessKeyID: "access"}})) != 0 {
|
||||
t.Error("Expected Client to be nil if no secretAccessKey is configured")
|
||||
}
|
||||
})
|
||||
t.Run("SecurityHub.Region", func(t *testing.T) {
|
||||
if len(factory.SecurityHubs(config.SecurityHub{AccountID: "accountID", AWSConfig: config.AWSConfig{AccessKeyID: "access", SecretAccessKey: "secret"}})) != 0 {
|
||||
if len(factory.SecurityHubs(&config.SecurityHub{AccountID: "accountID", AWSConfig: config.AWSConfig{AccessKeyID: "access", SecretAccessKey: "secret"}})) != 0 {
|
||||
t.Error("Expected Client to be nil if no region is configured")
|
||||
}
|
||||
})
|
||||
t.Run("GCS.Bucket", func(t *testing.T) {
|
||||
if len(factory.GCSClients(config.GCS{})) != 0 {
|
||||
if len(factory.GCSClients(&config.GCS{})) != 0 {
|
||||
t.Error("Expected Client to be nil if no bucket is configured")
|
||||
}
|
||||
})
|
||||
t.Run("GCS.Credentials", func(t *testing.T) {
|
||||
if len(factory.GCSClients(config.GCS{Bucket: "policy-reporter"})) != 0 {
|
||||
if len(factory.GCSClients(&config.GCS{Bucket: "policy-reporter"})) != 0 {
|
||||
t.Error("Expected Client to be nil if no accessKey is configured")
|
||||
}
|
||||
})
|
||||
|
@ -278,9 +289,9 @@ func Test_GetValuesFromSecret(t *testing.T) {
|
|||
factory := config.NewTargetFactory(secrets.NewClient(newFakeClient()))
|
||||
|
||||
t.Run("Get Loki values from Secret", func(t *testing.T) {
|
||||
clients := factory.LokiClients(config.Loki{TargetBaseOptions: config.TargetBaseOptions{SecretRef: secretName}})
|
||||
clients := factory.LokiClients(&config.Loki{TargetBaseOptions: config.TargetBaseOptions{SecretRef: secretName}})
|
||||
if len(clients) != 1 {
|
||||
t.Error("Expected one client created")
|
||||
t.Fatal("Expected one client created")
|
||||
}
|
||||
|
||||
fv := reflect.ValueOf(clients[0]).Elem().FieldByName("host")
|
||||
|
@ -290,9 +301,9 @@ func Test_GetValuesFromSecret(t *testing.T) {
|
|||
})
|
||||
|
||||
t.Run("Get Elasticsearch values from Secret", func(t *testing.T) {
|
||||
clients := factory.ElasticsearchClients(config.Elasticsearch{TargetBaseOptions: config.TargetBaseOptions{SecretRef: secretName}})
|
||||
clients := factory.ElasticsearchClients(&config.Elasticsearch{TargetBaseOptions: config.TargetBaseOptions{SecretRef: secretName}})
|
||||
if len(clients) != 1 {
|
||||
t.Error("Expected one client created")
|
||||
t.Fatal("Expected one client created")
|
||||
}
|
||||
|
||||
client := reflect.ValueOf(clients[0]).Elem()
|
||||
|
@ -307,6 +318,16 @@ func Test_GetValuesFromSecret(t *testing.T) {
|
|||
t.Errorf("Expected username from secret, got %s", username)
|
||||
}
|
||||
|
||||
rotation := client.FieldByName("rotation").String()
|
||||
if rotation != "daily" {
|
||||
t.Errorf("Expected rotation from secret, got %s", rotation)
|
||||
}
|
||||
|
||||
index := client.FieldByName("index").String()
|
||||
if index != "policy-reporter" {
|
||||
t.Errorf("Expected rotation from secret, got %s", index)
|
||||
}
|
||||
|
||||
password := client.FieldByName("password").String()
|
||||
if password != "password" {
|
||||
t.Errorf("Expected password from secret, got %s", password)
|
||||
|
@ -314,7 +335,7 @@ func Test_GetValuesFromSecret(t *testing.T) {
|
|||
})
|
||||
|
||||
t.Run("Get Discord values from Secret", func(t *testing.T) {
|
||||
clients := factory.DiscordClients(config.Discord{TargetBaseOptions: config.TargetBaseOptions{SecretRef: secretName}})
|
||||
clients := factory.DiscordClients(&config.Discord{TargetBaseOptions: config.TargetBaseOptions{SecretRef: secretName}})
|
||||
if len(clients) != 1 {
|
||||
t.Error("Expected one client created")
|
||||
}
|
||||
|
@ -328,7 +349,7 @@ func Test_GetValuesFromSecret(t *testing.T) {
|
|||
})
|
||||
|
||||
t.Run("Get MS Teams values from Secret", func(t *testing.T) {
|
||||
clients := factory.TeamsClients(config.Teams{TargetBaseOptions: config.TargetBaseOptions{SecretRef: secretName}})
|
||||
clients := factory.TeamsClients(&config.Teams{TargetBaseOptions: config.TargetBaseOptions{SecretRef: secretName}})
|
||||
if len(clients) != 1 {
|
||||
t.Error("Expected one client created")
|
||||
}
|
||||
|
@ -342,7 +363,7 @@ func Test_GetValuesFromSecret(t *testing.T) {
|
|||
})
|
||||
|
||||
t.Run("Get Slack values from Secret", func(t *testing.T) {
|
||||
clients := factory.SlackClients(config.Slack{TargetBaseOptions: config.TargetBaseOptions{SecretRef: secretName}})
|
||||
clients := factory.SlackClients(&config.Slack{TargetBaseOptions: config.TargetBaseOptions{SecretRef: secretName}})
|
||||
if len(clients) != 1 {
|
||||
t.Error("Expected one client created")
|
||||
}
|
||||
|
@ -356,7 +377,7 @@ func Test_GetValuesFromSecret(t *testing.T) {
|
|||
})
|
||||
|
||||
t.Run("Get Webhook Authentication Token from Secret", func(t *testing.T) {
|
||||
clients := factory.WebhookClients(config.Webhook{TargetBaseOptions: config.TargetBaseOptions{SecretRef: secretName}})
|
||||
clients := factory.WebhookClients(&config.Webhook{TargetBaseOptions: config.TargetBaseOptions{SecretRef: secretName}})
|
||||
if len(clients) != 1 {
|
||||
t.Error("Expected one client created")
|
||||
}
|
||||
|
@ -370,7 +391,7 @@ func Test_GetValuesFromSecret(t *testing.T) {
|
|||
})
|
||||
|
||||
t.Run("Get Telegram Token from Secret", func(t *testing.T) {
|
||||
clients := factory.TelegramClients(config.Telegram{TargetBaseOptions: config.TargetBaseOptions{SecretRef: secretName}, ChatID: "1234"})
|
||||
clients := factory.TelegramClients(&config.Telegram{TargetBaseOptions: config.TargetBaseOptions{SecretRef: secretName}, ChatID: "1234"})
|
||||
if len(clients) != 1 {
|
||||
t.Error("Expected one client created")
|
||||
}
|
||||
|
@ -382,44 +403,57 @@ func Test_GetValuesFromSecret(t *testing.T) {
|
|||
t.Errorf("Expected host with token from secret, got %s", host)
|
||||
}
|
||||
})
|
||||
t.Run("Get GoogleChat Webhook from Secret", func(t *testing.T) {
|
||||
clients := factory.GoogleChatClients(&config.GoogleChat{TargetBaseOptions: config.TargetBaseOptions{SecretRef: secretName}})
|
||||
if len(clients) != 1 {
|
||||
t.Error("Expected one client created")
|
||||
}
|
||||
|
||||
client := reflect.ValueOf(clients[0]).Elem()
|
||||
|
||||
host := client.FieldByName("webhook").String()
|
||||
if host != "http://localhost:9200/webhook" {
|
||||
t.Errorf("Expected host with token from secret, got %s", host)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Get S3 values from Secret", func(t *testing.T) {
|
||||
clients := factory.S3Clients(config.S3{TargetBaseOptions: config.TargetBaseOptions{SecretRef: secretName}, AWSConfig: config.AWSConfig{Endpoint: "endoint", Region: "region"}, Bucket: "bucket"})
|
||||
clients := factory.S3Clients(&config.S3{TargetBaseOptions: config.TargetBaseOptions{SecretRef: secretName}, AWSConfig: config.AWSConfig{Endpoint: "endoint", Region: "region"}, Bucket: "bucket"})
|
||||
if len(clients) != 1 {
|
||||
t.Error("Expected one client created")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Get S3 values from Secret with KMS", func(t *testing.T) {
|
||||
clients := factory.S3Clients(config.S3{TargetBaseOptions: config.TargetBaseOptions{SecretRef: secretName}, AWSConfig: config.AWSConfig{Endpoint: "endoint", Region: "region"}, Bucket: "bucket", BucketKeyEnabled: true, ServerSideEncryption: "aws:kms"})
|
||||
clients := factory.S3Clients(&config.S3{TargetBaseOptions: config.TargetBaseOptions{SecretRef: secretName}, AWSConfig: config.AWSConfig{Endpoint: "endoint", Region: "region"}, Bucket: "bucket", BucketKeyEnabled: true, ServerSideEncryption: "aws:kms"})
|
||||
if len(clients) != 1 {
|
||||
t.Error("Expected one client created")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Get Kinesis values from Secret", func(t *testing.T) {
|
||||
clients := factory.KinesisClients(config.Kinesis{TargetBaseOptions: config.TargetBaseOptions{SecretRef: secretName}, AWSConfig: config.AWSConfig{Endpoint: "endpoint", Region: "region"}, StreamName: "stream"})
|
||||
clients := factory.KinesisClients(&config.Kinesis{TargetBaseOptions: config.TargetBaseOptions{SecretRef: secretName}, AWSConfig: config.AWSConfig{Endpoint: "endpoint", Region: "region"}, StreamName: "stream"})
|
||||
if len(clients) != 1 {
|
||||
t.Error("Expected one client created")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Get GCS values from Secret", func(t *testing.T) {
|
||||
clients := factory.GCSClients(config.GCS{TargetBaseOptions: config.TargetBaseOptions{SecretRef: secretName}, Bucket: "bucket"})
|
||||
clients := factory.GCSClients(&config.GCS{TargetBaseOptions: config.TargetBaseOptions{SecretRef: secretName}, Bucket: "bucket"})
|
||||
if len(clients) != 1 {
|
||||
t.Error("Expected one client created")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Get none existing secret skips target", func(t *testing.T) {
|
||||
clients := factory.LokiClients(config.Loki{TargetBaseOptions: config.TargetBaseOptions{SecretRef: "no-exist"}})
|
||||
clients := factory.LokiClients(&config.Loki{TargetBaseOptions: config.TargetBaseOptions{SecretRef: "no-exist"}})
|
||||
if len(clients) != 0 {
|
||||
t.Error("Expected client are skipped")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Get CustomFields from Slack", func(t *testing.T) {
|
||||
clients := factory.SlackClients(config.Slack{TargetBaseOptions: config.TargetBaseOptions{CustomFields: map[string]string{"field": "value"}}, Webhook: "http://localhost"})
|
||||
clients := factory.SlackClients(&config.Slack{TargetBaseOptions: config.TargetBaseOptions{CustomFields: map[string]string{"field": "value"}}, Webhook: "http://localhost"})
|
||||
if len(clients) != 1 {
|
||||
t.Error("Expected one client created")
|
||||
}
|
||||
|
@ -432,7 +466,7 @@ func Test_GetValuesFromSecret(t *testing.T) {
|
|||
}
|
||||
})
|
||||
t.Run("Get CustomFields from Discord", func(t *testing.T) {
|
||||
clients := factory.DiscordClients(config.Discord{TargetBaseOptions: config.TargetBaseOptions{CustomFields: map[string]string{"field": "value"}}, Webhook: "http://localhost"})
|
||||
clients := factory.DiscordClients(&config.Discord{TargetBaseOptions: config.TargetBaseOptions{CustomFields: map[string]string{"field": "value"}}, Webhook: "http://localhost"})
|
||||
if len(clients) != 1 {
|
||||
t.Error("Expected one client created")
|
||||
}
|
||||
|
@ -445,7 +479,7 @@ func Test_GetValuesFromSecret(t *testing.T) {
|
|||
}
|
||||
})
|
||||
t.Run("Get CustomFields from MS Teams", func(t *testing.T) {
|
||||
clients := factory.TeamsClients(config.Teams{TargetBaseOptions: config.TargetBaseOptions{CustomFields: map[string]string{"field": "value"}}, Webhook: "http://localhost"})
|
||||
clients := factory.TeamsClients(&config.Teams{TargetBaseOptions: config.TargetBaseOptions{CustomFields: map[string]string{"field": "value"}}, Webhook: "http://localhost"})
|
||||
if len(clients) != 1 {
|
||||
t.Error("Expected one client created")
|
||||
}
|
||||
|
@ -458,7 +492,7 @@ func Test_GetValuesFromSecret(t *testing.T) {
|
|||
}
|
||||
})
|
||||
t.Run("Get CustomFields from Elasticsearch", func(t *testing.T) {
|
||||
clients := factory.ElasticsearchClients(config.Elasticsearch{TargetBaseOptions: config.TargetBaseOptions{CustomFields: map[string]string{"field": "value"}}, Host: "http://localhost"})
|
||||
clients := factory.ElasticsearchClients(&config.Elasticsearch{TargetBaseOptions: config.TargetBaseOptions{CustomFields: map[string]string{"field": "value"}}, Host: "http://localhost"})
|
||||
if len(clients) != 1 {
|
||||
t.Error("Expected one client created")
|
||||
}
|
||||
|
@ -471,7 +505,7 @@ func Test_GetValuesFromSecret(t *testing.T) {
|
|||
}
|
||||
})
|
||||
t.Run("Get CustomFields from Webhook", func(t *testing.T) {
|
||||
clients := factory.WebhookClients(config.Webhook{TargetBaseOptions: config.TargetBaseOptions{CustomFields: map[string]string{"field": "value"}}, Host: "http://localhost"})
|
||||
clients := factory.WebhookClients(&config.Webhook{TargetBaseOptions: config.TargetBaseOptions{CustomFields: map[string]string{"field": "value"}}, Host: "http://localhost"})
|
||||
if len(clients) != 1 {
|
||||
t.Error("Expected one client created")
|
||||
}
|
||||
|
@ -484,7 +518,20 @@ func Test_GetValuesFromSecret(t *testing.T) {
|
|||
}
|
||||
})
|
||||
t.Run("Get CustomFields from Telegram", func(t *testing.T) {
|
||||
clients := factory.TelegramClients(config.Telegram{TargetBaseOptions: config.TargetBaseOptions{CustomFields: map[string]string{"field": "value"}}, Token: "XXX", ChatID: "1234"})
|
||||
clients := factory.TelegramClients(&config.Telegram{TargetBaseOptions: config.TargetBaseOptions{CustomFields: map[string]string{"field": "value"}}, Token: "XXX", ChatID: "1234"})
|
||||
if len(clients) != 1 {
|
||||
t.Error("Expected one client created")
|
||||
}
|
||||
|
||||
client := reflect.ValueOf(clients[0]).Elem()
|
||||
|
||||
customFields := client.FieldByName("customFields").MapKeys()
|
||||
if customFields[0].String() != "field" {
|
||||
t.Errorf("Expected customFields are added")
|
||||
}
|
||||
})
|
||||
t.Run("Get CustomFields from GoogleChat", func(t *testing.T) {
|
||||
clients := factory.GoogleChatClients(&config.GoogleChat{TargetBaseOptions: config.TargetBaseOptions{CustomFields: map[string]string{"field": "value"}}, Webhook: "http;//googlechat.webhook"})
|
||||
if len(clients) != 1 {
|
||||
t.Error("Expected one client created")
|
||||
}
|
||||
|
@ -523,7 +570,7 @@ func Test_GetValuesFromSecret(t *testing.T) {
|
|||
}
|
||||
})
|
||||
t.Run("Get CustomLabels from Loki", func(t *testing.T) {
|
||||
clients := factory.LokiClients(config.Loki{
|
||||
clients := factory.LokiClients(&config.Loki{
|
||||
CustomLabels: map[string]string{"label": "value"},
|
||||
Host: "http://localhost",
|
||||
})
|
||||
|
@ -559,7 +606,7 @@ func Test_GetValuesFromMountedSecret(t *testing.T) {
|
|||
defer os.Remove(mountedSecret)
|
||||
|
||||
t.Run("Get Loki values from MountedSecret", func(t *testing.T) {
|
||||
clients := factory.LokiClients(config.Loki{TargetBaseOptions: config.TargetBaseOptions{MountedSecret: mountedSecret}})
|
||||
clients := factory.LokiClients(&config.Loki{TargetBaseOptions: config.TargetBaseOptions{MountedSecret: mountedSecret}})
|
||||
if len(clients) != 1 {
|
||||
t.Error("Expected one client created")
|
||||
}
|
||||
|
@ -571,7 +618,7 @@ func Test_GetValuesFromMountedSecret(t *testing.T) {
|
|||
})
|
||||
|
||||
t.Run("Get Elasticsearch values from MountedSecret", func(t *testing.T) {
|
||||
clients := factory.ElasticsearchClients(config.Elasticsearch{TargetBaseOptions: config.TargetBaseOptions{MountedSecret: mountedSecret}})
|
||||
clients := factory.ElasticsearchClients(&config.Elasticsearch{TargetBaseOptions: config.TargetBaseOptions{MountedSecret: mountedSecret}})
|
||||
if len(clients) != 1 {
|
||||
t.Error("Expected one client created")
|
||||
}
|
||||
|
@ -595,7 +642,7 @@ func Test_GetValuesFromMountedSecret(t *testing.T) {
|
|||
})
|
||||
|
||||
t.Run("Get Discord values from MountedSecret", func(t *testing.T) {
|
||||
clients := factory.DiscordClients(config.Discord{TargetBaseOptions: config.TargetBaseOptions{MountedSecret: mountedSecret}})
|
||||
clients := factory.DiscordClients(&config.Discord{TargetBaseOptions: config.TargetBaseOptions{MountedSecret: mountedSecret}})
|
||||
if len(clients) != 1 {
|
||||
t.Error("Expected one client created")
|
||||
}
|
||||
|
@ -609,7 +656,7 @@ func Test_GetValuesFromMountedSecret(t *testing.T) {
|
|||
})
|
||||
|
||||
t.Run("Get MS Teams values from MountedSecret", func(t *testing.T) {
|
||||
clients := factory.TeamsClients(config.Teams{TargetBaseOptions: config.TargetBaseOptions{MountedSecret: mountedSecret}})
|
||||
clients := factory.TeamsClients(&config.Teams{TargetBaseOptions: config.TargetBaseOptions{MountedSecret: mountedSecret}})
|
||||
if len(clients) != 1 {
|
||||
t.Error("Expected one client created")
|
||||
}
|
||||
|
@ -623,7 +670,7 @@ func Test_GetValuesFromMountedSecret(t *testing.T) {
|
|||
})
|
||||
|
||||
t.Run("Get Slack values from MountedSecret", func(t *testing.T) {
|
||||
clients := factory.SlackClients(config.Slack{TargetBaseOptions: config.TargetBaseOptions{MountedSecret: mountedSecret}})
|
||||
clients := factory.SlackClients(&config.Slack{TargetBaseOptions: config.TargetBaseOptions{MountedSecret: mountedSecret}})
|
||||
if len(clients) != 1 {
|
||||
t.Error("Expected one client created")
|
||||
}
|
||||
|
@ -637,7 +684,7 @@ func Test_GetValuesFromMountedSecret(t *testing.T) {
|
|||
})
|
||||
|
||||
t.Run("Get Webhook Authentication Token from MountedSecret", func(t *testing.T) {
|
||||
clients := factory.WebhookClients(config.Webhook{TargetBaseOptions: config.TargetBaseOptions{MountedSecret: mountedSecret}})
|
||||
clients := factory.WebhookClients(&config.Webhook{TargetBaseOptions: config.TargetBaseOptions{MountedSecret: mountedSecret}})
|
||||
if len(clients) != 1 {
|
||||
t.Error("Expected one client created")
|
||||
}
|
||||
|
@ -651,7 +698,7 @@ func Test_GetValuesFromMountedSecret(t *testing.T) {
|
|||
})
|
||||
|
||||
t.Run("Get Telegram Token from MountedSecret", func(t *testing.T) {
|
||||
clients := factory.TelegramClients(config.Telegram{TargetBaseOptions: config.TargetBaseOptions{MountedSecret: mountedSecret}, ChatID: "123"})
|
||||
clients := factory.TelegramClients(&config.Telegram{TargetBaseOptions: config.TargetBaseOptions{MountedSecret: mountedSecret}, ChatID: "123"})
|
||||
if len(clients) != 1 {
|
||||
t.Error("Expected one client created")
|
||||
}
|
||||
|
@ -664,36 +711,50 @@ func Test_GetValuesFromMountedSecret(t *testing.T) {
|
|||
}
|
||||
})
|
||||
|
||||
t.Run("Get GoogleChat Webhook from MountedSecret", func(t *testing.T) {
|
||||
clients := factory.GoogleChatClients(&config.GoogleChat{TargetBaseOptions: config.TargetBaseOptions{MountedSecret: mountedSecret}})
|
||||
if len(clients) != 1 {
|
||||
t.Error("Expected one client created")
|
||||
}
|
||||
|
||||
client := reflect.ValueOf(clients[0]).Elem()
|
||||
|
||||
token := client.FieldByName("webhook").String()
|
||||
if token != "http://localhost:9200/webhook" {
|
||||
t.Errorf("Expected token from mounted secret, got %s", token)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Get S3 values from MountedSecret", func(t *testing.T) {
|
||||
clients := factory.S3Clients(config.S3{TargetBaseOptions: config.TargetBaseOptions{MountedSecret: mountedSecret}, AWSConfig: config.AWSConfig{Endpoint: "endpoint", Region: "region"}, Bucket: "bucket"})
|
||||
clients := factory.S3Clients(&config.S3{TargetBaseOptions: config.TargetBaseOptions{MountedSecret: mountedSecret}, AWSConfig: config.AWSConfig{Endpoint: "endpoint", Region: "region"}, Bucket: "bucket"})
|
||||
if len(clients) != 1 {
|
||||
t.Error("Expected one client created")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Get S3 values from MountedSecret with KMS", func(t *testing.T) {
|
||||
clients := factory.S3Clients(config.S3{TargetBaseOptions: config.TargetBaseOptions{MountedSecret: mountedSecret}, AWSConfig: config.AWSConfig{Endpoint: "endpoint", Region: "region"}, Bucket: "bucket", BucketKeyEnabled: true, ServerSideEncryption: "aws:kms"})
|
||||
clients := factory.S3Clients(&config.S3{TargetBaseOptions: config.TargetBaseOptions{MountedSecret: mountedSecret}, AWSConfig: config.AWSConfig{Endpoint: "endpoint", Region: "region"}, Bucket: "bucket", BucketKeyEnabled: true, ServerSideEncryption: "aws:kms"})
|
||||
if len(clients) != 1 {
|
||||
t.Error("Expected one client created")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Get Kinesis values from MountedSecret", func(t *testing.T) {
|
||||
clients := factory.KinesisClients(config.Kinesis{TargetBaseOptions: config.TargetBaseOptions{MountedSecret: mountedSecret}, AWSConfig: config.AWSConfig{Endpoint: "endpoint", Region: "region"}, StreamName: "stream"})
|
||||
clients := factory.KinesisClients(&config.Kinesis{TargetBaseOptions: config.TargetBaseOptions{MountedSecret: mountedSecret}, AWSConfig: config.AWSConfig{Endpoint: "endpoint", Region: "region"}, StreamName: "stream"})
|
||||
if len(clients) != 1 {
|
||||
t.Error("Expected one client created")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Get GCS values from MountedSecret", func(t *testing.T) {
|
||||
clients := factory.GCSClients(config.GCS{TargetBaseOptions: config.TargetBaseOptions{MountedSecret: mountedSecret}, Bucket: "bucket"})
|
||||
clients := factory.GCSClients(&config.GCS{TargetBaseOptions: config.TargetBaseOptions{MountedSecret: mountedSecret}, Bucket: "bucket"})
|
||||
if len(clients) != 1 {
|
||||
t.Error("Expected one client created")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Get none existing mounted secret skips target", func(t *testing.T) {
|
||||
clients := factory.LokiClients(config.Loki{TargetBaseOptions: config.TargetBaseOptions{MountedSecret: "no-exists"}})
|
||||
clients := factory.LokiClients(&config.Loki{TargetBaseOptions: config.TargetBaseOptions{MountedSecret: "no-exists"}})
|
||||
if len(clients) != 0 {
|
||||
t.Error("Expected client are skipped")
|
||||
}
|
||||
|
|
228
pkg/target/googlechat/googlechat.go
Normal file
228
pkg/target/googlechat/googlechat.go
Normal file
|
@ -0,0 +1,228 @@
|
|||
package googlechat
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"text/template"
|
||||
"time"
|
||||
|
||||
"github.com/kyverno/policy-reporter/pkg/crd/api/policyreport/v1alpha2"
|
||||
"github.com/kyverno/policy-reporter/pkg/target"
|
||||
"github.com/kyverno/policy-reporter/pkg/target/http"
|
||||
"go.uber.org/zap"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
)
|
||||
|
||||
const messageTempl string = `[{{ .Priority }}] {{ or .Result.Policy .Result.Rule }}`
|
||||
const resourceTempl string = `{{ if .Namespace }}[{{ .Namespace }}] {{ end }} {{ .APIVersion }}/{{ .Kind }} {{ .Name }}`
|
||||
|
||||
type values struct {
|
||||
Result v1alpha2.PolicyReportResult
|
||||
Priority string
|
||||
Resource *corev1.ObjectReference
|
||||
}
|
||||
|
||||
type header struct {
|
||||
Title string `json:"title"`
|
||||
SubTitle string `json:"subtitle"`
|
||||
}
|
||||
|
||||
type decoratedText struct {
|
||||
TopLabel string `json:"topLabel"`
|
||||
Text string `json:"text"`
|
||||
}
|
||||
|
||||
type column struct {
|
||||
Widgets []widget `json:"widgets"`
|
||||
}
|
||||
|
||||
type columns struct {
|
||||
ColumnItems []column `json:"columnItems"`
|
||||
}
|
||||
|
||||
type textParagraph struct {
|
||||
Text string `json:"text"`
|
||||
}
|
||||
|
||||
type widget struct {
|
||||
DecoratedText *decoratedText `json:"decoratedText,omitempty"`
|
||||
TextParagraph *textParagraph `json:"textParagraph,omitempty"`
|
||||
Columns *columns `json:"columns,omitempty"`
|
||||
}
|
||||
|
||||
type section struct {
|
||||
Header string `json:"header,omitempty"`
|
||||
Collapsible bool `json:"collapsible,omitempty"`
|
||||
Widgets []widget `json:"widgets,omitempty"`
|
||||
}
|
||||
|
||||
type card struct {
|
||||
Header *header `json:"header,omitempty"`
|
||||
Sections []section `json:"sections,omitempty"`
|
||||
}
|
||||
|
||||
type cardsV2 struct {
|
||||
CardID string `json:"cardId,omitempty"`
|
||||
Card card `json:"card,omitempty"`
|
||||
}
|
||||
|
||||
type Payload struct {
|
||||
CardsV2 []cardsV2 `json:"cardsV2,omitempty"`
|
||||
}
|
||||
|
||||
// Options to configure the Discord target
|
||||
type Options struct {
|
||||
target.ClientOptions
|
||||
Webhook string
|
||||
Headers map[string]string
|
||||
CustomFields map[string]string
|
||||
HTTPClient http.Client
|
||||
}
|
||||
|
||||
type client struct {
|
||||
target.BaseClient
|
||||
webhook string
|
||||
headers map[string]string
|
||||
customFields map[string]string
|
||||
client http.Client
|
||||
}
|
||||
|
||||
func mapPayload(result v1alpha2.PolicyReportResult) (*Payload, error) {
|
||||
widgets := []widget{{TextParagraph: &textParagraph{Text: result.Message}}}
|
||||
|
||||
ttmpl, err := template.New("googlechat").Parse(messageTempl)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var prio = result.Priority.String()
|
||||
if prio == "" {
|
||||
prio = v1alpha2.DebugPriority.String()
|
||||
}
|
||||
|
||||
var textBuffer bytes.Buffer
|
||||
err = ttmpl.Execute(&textBuffer, values{Result: result, Priority: prio, Resource: result.GetResource()})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
subtitle := ""
|
||||
|
||||
if result.HasResource() {
|
||||
res := result.GetResource()
|
||||
|
||||
widgets = append(widgets, widget{
|
||||
Columns: &columns{
|
||||
ColumnItems: []column{
|
||||
{
|
||||
Widgets: []widget{
|
||||
{DecoratedText: &decoratedText{TopLabel: "Kind", Text: res.Kind}},
|
||||
{DecoratedText: &decoratedText{TopLabel: "Namespace", Text: res.Namespace}},
|
||||
{DecoratedText: &decoratedText{"Status", string(result.Result)}},
|
||||
},
|
||||
},
|
||||
{
|
||||
Widgets: []widget{
|
||||
{DecoratedText: &decoratedText{TopLabel: "APIVersion", Text: res.APIVersion}},
|
||||
{DecoratedText: &decoratedText{TopLabel: "Name", Text: res.Name}},
|
||||
{DecoratedText: &decoratedText{"Source", result.Source}},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
stmpl, err := template.New("googlechat:resource").Parse(resourceTempl)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var subTitleBuffer bytes.Buffer
|
||||
err = stmpl.Execute(&subTitleBuffer, res)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
subtitle = subTitleBuffer.String()
|
||||
}
|
||||
|
||||
header := header{
|
||||
Title: textBuffer.String(),
|
||||
SubTitle: subtitle,
|
||||
}
|
||||
|
||||
if result.Policy != "" {
|
||||
widgets = append(widgets, widget{DecoratedText: &decoratedText{"Rule", result.Rule}})
|
||||
}
|
||||
if result.Category != "" {
|
||||
widgets = append(widgets, widget{DecoratedText: &decoratedText{"Category", result.Category}})
|
||||
}
|
||||
|
||||
for key, value := range result.Properties {
|
||||
widgets = append(widgets, widget{DecoratedText: &decoratedText{TopLabel: key, Text: value}})
|
||||
}
|
||||
|
||||
widgets = append(widgets, widget{DecoratedText: &decoratedText{"time", time.Now().Format("02 Jan 06 15:04 MST")}})
|
||||
|
||||
return &Payload{
|
||||
CardsV2: []cardsV2{
|
||||
{
|
||||
CardID: result.ID,
|
||||
Card: card{
|
||||
Header: &header,
|
||||
Sections: []section{
|
||||
{
|
||||
Header: "Details",
|
||||
Collapsible: true,
|
||||
Widgets: widgets,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (e *client) Send(result v1alpha2.PolicyReportResult) {
|
||||
if len(e.customFields) > 0 {
|
||||
props := make(map[string]string, 0)
|
||||
|
||||
for property, value := range e.customFields {
|
||||
props[property] = value
|
||||
}
|
||||
|
||||
for property, value := range result.Properties {
|
||||
props[property] = value
|
||||
}
|
||||
|
||||
result.Properties = props
|
||||
}
|
||||
|
||||
payload, err := mapPayload(result)
|
||||
if err != nil {
|
||||
zap.L().Error(e.Name()+": PUSH FAILED", zap.Error(err))
|
||||
return
|
||||
}
|
||||
|
||||
req, err := http.CreateJSONRequest(e.Name(), "POST", e.webhook, payload)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
for header, value := range e.headers {
|
||||
req.Header.Set(header, value)
|
||||
}
|
||||
|
||||
resp, err := e.client.Do(req)
|
||||
http.ProcessHTTPResponse(e.Name(), resp, err)
|
||||
}
|
||||
|
||||
// NewClient creates a new loki.client to send Results to Elasticsearch
|
||||
func NewClient(options Options) target.Client {
|
||||
return &client{
|
||||
target.NewBaseClient(options.ClientOptions),
|
||||
options.Webhook,
|
||||
options.Headers,
|
||||
options.CustomFields,
|
||||
options.HTTPClient,
|
||||
}
|
||||
}
|
79
pkg/target/googlechat/googlechat_test.go
Normal file
79
pkg/target/googlechat/googlechat_test.go
Normal file
|
@ -0,0 +1,79 @@
|
|||
package googlechat_test
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/kyverno/policy-reporter/pkg/fixtures"
|
||||
"github.com/kyverno/policy-reporter/pkg/target"
|
||||
"github.com/kyverno/policy-reporter/pkg/target/googlechat"
|
||||
)
|
||||
|
||||
type testClient struct {
|
||||
callback func(req *http.Request) error
|
||||
statusCode int
|
||||
}
|
||||
|
||||
func (c testClient) Do(req *http.Request) (*http.Response, error) {
|
||||
err := c.callback(req)
|
||||
|
||||
return &http.Response{
|
||||
StatusCode: c.statusCode,
|
||||
Body: io.NopCloser(strings.NewReader("")),
|
||||
}, err
|
||||
}
|
||||
|
||||
func Test_GoogleChatTarget(t *testing.T) {
|
||||
t.Run("Send", func(t *testing.T) {
|
||||
callback := func(req *http.Request) error {
|
||||
if contentType := req.Header.Get("Content-Type"); contentType != "application/json; charset=utf-8" {
|
||||
t.Errorf("Unexpected Content-Type: %s", contentType)
|
||||
}
|
||||
|
||||
if agend := req.Header.Get("User-Agent"); agend != "Policy-Reporter" {
|
||||
t.Errorf("Unexpected Host: %s", agend)
|
||||
}
|
||||
|
||||
if url := req.URL.String(); url != "https://googlechat.webhook" {
|
||||
t.Errorf("Unexpected Host: %s", url)
|
||||
}
|
||||
|
||||
if value := req.Header.Get("X-Code"); value != "1234" {
|
||||
t.Errorf("Unexpected Header X-Code: %s", value)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
client := googlechat.NewClient(googlechat.Options{
|
||||
ClientOptions: target.ClientOptions{
|
||||
Name: "GoogleChat",
|
||||
},
|
||||
Webhook: "https://googlechat.webhook",
|
||||
Headers: map[string]string{"X-Code": "1234"},
|
||||
CustomFields: map[string]string{"cluster": "name"},
|
||||
HTTPClient: testClient{callback, 200},
|
||||
})
|
||||
client.Send(fixtures.CompleteTargetSendResult)
|
||||
|
||||
if len(fixtures.CompleteTargetSendResult.Properties) > 1 || fixtures.CompleteTargetSendResult.Properties["cluster"] != "" {
|
||||
t.Error("expected customFields are not added to the actuel result")
|
||||
}
|
||||
})
|
||||
t.Run("Name", func(t *testing.T) {
|
||||
client := googlechat.NewClient(googlechat.Options{
|
||||
ClientOptions: target.ClientOptions{
|
||||
Name: "GoogleChat",
|
||||
},
|
||||
Webhook: "https://googlechat.webhook",
|
||||
Headers: map[string]string{"X-Code": "1234"},
|
||||
HTTPClient: testClient{},
|
||||
})
|
||||
|
||||
if client.Name() != "GoogleChat" {
|
||||
t.Errorf("Unexpected Name %s", client.Name())
|
||||
}
|
||||
})
|
||||
}
|
Loading…
Reference in a new issue