Skip to content

Commit

Permalink
feat(notifiy): allow to store webhook credentials in an other configs…
Browse files Browse the repository at this point in the history
…tore item

Signed-off-by: Thomas Bétrancourt <[email protected]>
  • Loading branch information
rclsilver committed Apr 24, 2024
1 parent 58b3b77 commit b6254f0
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 24 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ Extending this basic authentication mechanism is possible by developing an "init
### Notification

Every task state change can be notified to a notification backend.
µTask implements three differents notification backends: Slack, [TaT](https://github.com/ovh/tat), and generic webhooks.
µTask implements three differents notification backends: Slack, Opsgenie, and generic webhooks.

Default payload that will be sent for generic webhooks are:

Expand Down
37 changes: 16 additions & 21 deletions config/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,27 +66,6 @@ postgres://user:pass@db/utask?sslmode=disable
"task_state_update": "failure_only"
}
},
"tat-internal": {
"type": "tat",
"config": {
"username": "foo",
"password": "very-secret",
"url": "http://localhost:9999/tat",
"topic": "utask.notifications"
},
"default_notification_strategy": {
"task_state_update": "silent",
"task_validation": "always"
},
"template_notification_strategies": {
"task_state_update": [
{
"templates": ["hello-world", "hello-world-2"],
"notification_strategy": "always"
}
]
}
},
"slack-webhook": {
"type": "slack",
"config": {
Expand All @@ -106,6 +85,22 @@ postgres://user:pass@db/utask?sslmode=disable
"X-Specific-Header": "foobar"
}
}
},
"webhook-secure.org": {
"type": "webhook",
"config": {
"webhook_url": "https://example.org/webhook/XXXXXXXXXXXXXXXXXXXX",
// username and password can be stored in another configstore item which must be aliases with "notify-webhook-credentials":
// {
// "credentials_name": "foobar",
// "username": "foo",
// "password": "very-secret"
// }
"credentials_name": "foobar",
"headers": {
"X-Specific-Header": "foobar"
}
}
}
},
// notify_actions specifies a notification config for existing events in µTask
Expand Down
39 changes: 39 additions & 0 deletions pkg/notify/init/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,45 @@ func Init(store *configstore.Store) error {
if err := json.Unmarshal(ncfg.Config, &f); err != nil {
return fmt.Errorf("%s: %s, %s: %s", errRetrieveCfg, ncfg.Type, name, err)
}

if f.CredentialsName != "" {
items, err := configstore.Filter().
Store(store).
Slice(utask.NotificationCredentialsSecretAlias).
Unmarshal(func() interface{} { return &utask.NotifyBackendWebhookCredentials{} }).
Rekey(func(s *configstore.Item) string {
i, err := s.Unmarshaled()
if err == nil {
return i.(*utask.NotifyBackendWebhookCredentials).CredentialsName
}
return s.Key()
}).
Slice(f.CredentialsName).
GetItemList()
if err != nil {
return fmt.Errorf("%s: %s, %s: %s", errRetrieveCfg, ncfg.Type, name, err)
}
if items.Len() == 0 {
return fmt.Errorf("%s: %s, %s: no credential found with name %q", errRetrieveCfg, ncfg.Type, name, f.CredentialsName)
}
if items.Len() > 1 {
return fmt.Errorf("%s: %s, %s: more than one credentials found with name %q", errRetrieveCfg, ncfg.Type, name, f.CredentialsName)
}

iValue, err := items.Items[0].Unmarshaled()
if err != nil {
return fmt.Errorf("%s: %s, %s: %s", errRetrieveCfg, ncfg.Type, name, err)
}

value, ok := iValue.(*utask.NotifyBackendWebhookCredentials)
if !ok {
return fmt.Errorf("%s: %s, %s: expected *utask.NotifyBackendWebhookCredentials, got %T", errRetrieveCfg, ncfg.Type, name, value)
}

f.Username = value.Username
f.Password = value.Password
}

sn := webhook.NewWebhookNotificationSender(f.WebhookURL, f.Username, f.Password, f.Headers)
notify.RegisterSender(name, sn, ncfg.DefaultNotificationStrategy, ncfg.TemplateNotificationStrategies)

Expand Down
15 changes: 13 additions & 2 deletions utask.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ const (
// UtaskCfgSecretAlias is the key for the config item containing global configuration data
UtaskCfgSecretAlias = "utask-cfg"

// NotificationCredentialsSecretAlias is the key for the config item containing notification backend credentials
NotificationCredentialsSecretAlias = "notify-webhook-credentials" // #nosec G101

// NotificationStrategySilent corresponds to the mode where notifications will never be sent for the given templates
NotificationStrategySilent = "silent"
// NotificationStrategyAlways corresponds to the mode where notifications will always be sent for the given templates
Expand Down Expand Up @@ -173,11 +176,19 @@ type NotifyBackendSlack struct {
WebhookURL string `json:"webhook_url"`
}

// NotifyBackendWebhookCredentials holds the credentials for instantiating a Webhook notify client
type NotifyBackendWebhookCredentials struct {
CredentialsName string `json:"credentials_name"`

Username string `json:"username"`
Password string `json:"password"`
}

// NotifyBackendWebhook holds configuration for instantiating a Webhook notify client
type NotifyBackendWebhook struct {
NotifyBackendWebhookCredentials

WebhookURL string `json:"webhook_url"`
Username string `json:"username"`
Password string `json:"password"`
Headers map[string]string `json:"headers"`
}

Expand Down

0 comments on commit b6254f0

Please sign in to comment.