From 2fde6548fcae5459f6d9aa4775405d16bf59bebe Mon Sep 17 00:00:00 2001 From: CrazyMax <1951866+crazy-max@users.noreply.github.com> Date: Mon, 16 Dec 2024 02:28:25 +0100 Subject: [PATCH] notif: support webhook url as secret --- docs/notif/discord.md | 4 +++- docs/notif/slack.md | 4 +++- docs/notif/teams.md | 4 +++- internal/model/notif_discord.go | 11 ++++++----- internal/model/notif_slack.go | 7 ++++--- internal/model/notif_teams.go | 7 ++++--- internal/notif/discord/client.go | 8 +++++++- internal/notif/slack/client.go | 9 ++++++++- internal/notif/teams/client.go | 9 ++++++++- 9 files changed, 46 insertions(+), 17 deletions(-) diff --git a/docs/notif/discord.md b/docs/notif/discord.md index 17ee5da2d..b4f5afbee 100644 --- a/docs/notif/discord.md +++ b/docs/notif/discord.md @@ -23,7 +23,8 @@ Allow sending notifications to your Discord channel. | Name | Default | Description | |--------------------|------------------------------------|-----------------------------------------------------------------------------------------------------------| -| `webhookURL`[^1] | | Discord [incoming webhook URL](https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks) | +| `webhookURL` | | Discord [incoming webhook URL](https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks) | +| `webhookURLFile` | | Use content of secret file as webhook URL if `webhookURL` is not defined | | `mentions` | | List of users or roles to notify | | `renderFields` | `true` | Render [field objects](https://discordjs.guide/popular-topics/embeds.html) | | `timeout` | `10s` | Timeout specifies a time limit for the request to be made | @@ -31,6 +32,7 @@ Allow sending notifications to your Discord channel. !!! abstract "Environment variables" * `DIUN_NOTIF_DISCORD_WEBHOOKURL` + * `DIUN_NOTIF_DISCORD_WEBHOOKURLFILE` * `DIUN_NOTIF_DISCORD_MENTIONS` (comma separated) * `DIUN_NOTIF_DISCORD_RENDERFIELDS` * `DIUN_NOTIF_DISCORD_TIMEOUT` diff --git a/docs/notif/slack.md b/docs/notif/slack.md index ed8f9fc32..5aec92a31 100644 --- a/docs/notif/slack.md +++ b/docs/notif/slack.md @@ -19,12 +19,14 @@ You can send notifications to your Slack channel using an [incoming webhook URL] | Name | Default | Description | |--------------------|------------------------------------|-------------------------------------------------------------------------------------------| -| `webhookURL`[^1] | | Slack [incoming webhook URL](https://api.slack.com/messaging/webhooks) | +| `webhookURL` | | Slack [incoming webhook URL](https://api.slack.com/messaging/webhooks) | +| `webhookURLFile` | | Use content of secret file as webhook URL if `webhookURL` is not defined | | `renderFields` | `true` | Render [field objects](https://api.slack.com/messaging/composing/layouts#stack_of_blocks) | | `templateBody`[^1] | See [below](#default-templatebody) | [Notification template](../faq.md#notification-template) for message body | !!! abstract "Environment variables" * `DIUN_NOTIF_SLACK_WEBHOOKURL` + * `DIUN_NOTIF_SLACK_WEBHOOKURLFILE` * `DIUN_NOTIF_SLACK_RENDERFIELDS` * `DIUN_NOTIF_SLACK_TEMPLATEBODY` diff --git a/docs/notif/teams.md b/docs/notif/teams.md index 0a48217d6..ae6044b73 100644 --- a/docs/notif/teams.md +++ b/docs/notif/teams.md @@ -16,12 +16,14 @@ You can send notifications to your Teams team-channel using an [incoming webhook | Name | Default | Description | |--------------------|------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------| -| `webhookURL`[^1] | | Teams [incoming webhook URL](https://docs.microsoft.com/en-us/microsoftteams/platform/webhooks-and-connectors/what-are-webhooks-and-connectors) | +| `webhookURL` | | Teams [incoming webhook URL](https://docs.microsoft.com/en-us/microsoftteams/platform/webhooks-and-connectors/what-are-webhooks-and-connectors) | +| `webhookURLFile` | | Use content of secret file as webhook URL if `webhookURL` is not defined | | `renderFacts` | `true` | Render fact objects | | `templateBody`[^1] | See [below](#default-templatebody) | [Notification template](../faq.md#notification-template) for message body | !!! abstract "Environment variables" * `DIUN_NOTIF_TEAMS_WEBHOOKURL` + * `DIUN_NOTIF_TEAMS_WEBHOOKURLFILE` * `DIUN_NOTIF_TEAMS_RENDERFACTS` * `DIUN_NOTIF_TEAMS_TEMPLATEBODY` diff --git a/internal/model/notif_discord.go b/internal/model/notif_discord.go index 81627eef3..6ecae20dd 100644 --- a/internal/model/notif_discord.go +++ b/internal/model/notif_discord.go @@ -8,11 +8,12 @@ import ( // NotifDiscord holds Discord notification configuration details type NotifDiscord struct { - WebhookURL string `yaml:"webhookURL,omitempty" json:"webhookURL,omitempty" validate:"required"` - Mentions []string `yaml:"mentions,omitempty" json:"mentions,omitempty"` - RenderFields *bool `yaml:"renderFields,omitempty" json:"renderFields,omitempty" validate:"required"` - Timeout *time.Duration `yaml:"timeout,omitempty" json:"timeout,omitempty" validate:"required"` - TemplateBody string `yaml:"templateBody,omitempty" json:"templateBody,omitempty" validate:"required"` + WebhookURL string `yaml:"webhookURL,omitempty" json:"webhookURL,omitempty" validate:"omitempty"` + WebhookURLFile string `yaml:"webhookURLFile,omitempty" json:"webhookURLFile,omitempty" validate:"omitempty,file"` + Mentions []string `yaml:"mentions,omitempty" json:"mentions,omitempty"` + RenderFields *bool `yaml:"renderFields,omitempty" json:"renderFields,omitempty" validate:"required"` + Timeout *time.Duration `yaml:"timeout,omitempty" json:"timeout,omitempty" validate:"required"` + TemplateBody string `yaml:"templateBody,omitempty" json:"templateBody,omitempty" validate:"required"` } // GetDefaults gets the default values diff --git a/internal/model/notif_slack.go b/internal/model/notif_slack.go index 958f5c20f..c1ba57b26 100644 --- a/internal/model/notif_slack.go +++ b/internal/model/notif_slack.go @@ -7,9 +7,10 @@ const NotifSlackDefaultTemplateBody = " Docker tag {{ if .Entry.Image. // NotifSlack holds slack notification configuration details type NotifSlack struct { - WebhookURL string `yaml:"webhookURL,omitempty" json:"webhookURL,omitempty" validate:"required"` - RenderFields *bool `yaml:"renderFields,omitempty" json:"renderFields,omitempty" validate:"required"` - TemplateBody string `yaml:"templateBody,omitempty" json:"templateBody,omitempty" validate:"required"` + WebhookURL string `yaml:"webhookURL,omitempty" json:"webhookURL,omitempty" validate:"omitempty"` + WebhookURLFile string `yaml:"webhookURLFile,omitempty" json:"webhookURLFile,omitempty" validate:"omitempty,file"` + RenderFields *bool `yaml:"renderFields,omitempty" json:"renderFields,omitempty" validate:"required"` + TemplateBody string `yaml:"templateBody,omitempty" json:"templateBody,omitempty" validate:"required"` } // GetDefaults gets the default values diff --git a/internal/model/notif_teams.go b/internal/model/notif_teams.go index 1a047eb87..792f5528d 100644 --- a/internal/model/notif_teams.go +++ b/internal/model/notif_teams.go @@ -7,9 +7,10 @@ const NotifTeamsDefaultTemplateBody = "Docker tag {{ if .Entry.Image.HubLink }}[ // NotifTeams holds Teams notification configuration details type NotifTeams struct { - WebhookURL string `yaml:"webhookURL,omitempty" json:"webhookURL,omitempty" validate:"required"` - RenderFacts *bool `yaml:"renderFacts,omitempty" json:"renderFacts,omitempty" validate:"required"` - TemplateBody string `yaml:"templateBody,omitempty" json:"templateBody,omitempty" validate:"required"` + WebhookURL string `yaml:"webhookURL,omitempty" json:"webhookURL,omitempty" validate:"omitempty"` + WebhookURLFile string `yaml:"webhookURLFile,omitempty" json:"webhookURLFile,omitempty" validate:"omitempty,file"` + RenderFacts *bool `yaml:"renderFacts,omitempty" json:"renderFacts,omitempty" validate:"required"` + TemplateBody string `yaml:"templateBody,omitempty" json:"templateBody,omitempty" validate:"required"` } // GetDefaults gets the default values diff --git a/internal/notif/discord/client.go b/internal/notif/discord/client.go index bb07b5a8b..5b5fd1576 100644 --- a/internal/notif/discord/client.go +++ b/internal/notif/discord/client.go @@ -12,6 +12,7 @@ import ( "github.com/crazy-max/diun/v4/internal/model" "github.com/crazy-max/diun/v4/internal/msg" "github.com/crazy-max/diun/v4/internal/notif/notifier" + "github.com/crazy-max/diun/v4/pkg/utl" "github.com/pkg/errors" ) @@ -42,6 +43,11 @@ func (c *Client) Name() string { func (c *Client) Send(entry model.NotifEntry) error { var content bytes.Buffer + webhookURL, err := utl.GetSecret(c.cfg.WebhookURL, c.cfg.WebhookURLFile) + if err != nil { + return errors.Wrap(err, "cannot retrieve webhook URL for Discord notifier") + } + message, err := msg.New(msg.Options{ Meta: c.meta, Entry: entry, @@ -117,7 +123,7 @@ func (c *Client) Send(entry model.NotifEntry) error { return err } - u, err := url.Parse(c.cfg.WebhookURL) + u, err := url.Parse(webhookURL) if err != nil { return err } diff --git a/internal/notif/slack/client.go b/internal/notif/slack/client.go index 31e22a539..13005d957 100644 --- a/internal/notif/slack/client.go +++ b/internal/notif/slack/client.go @@ -9,7 +9,9 @@ import ( "github.com/crazy-max/diun/v4/internal/model" "github.com/crazy-max/diun/v4/internal/msg" "github.com/crazy-max/diun/v4/internal/notif/notifier" + "github.com/crazy-max/diun/v4/pkg/utl" "github.com/nlopes/slack" + "github.com/pkg/errors" ) // Client represents an active slack notification object @@ -36,6 +38,11 @@ func (c *Client) Name() string { // Send creates and sends a slack notification with an entry func (c *Client) Send(entry model.NotifEntry) error { + webhookURL, err := utl.GetSecret(c.cfg.WebhookURL, c.cfg.WebhookURLFile) + if err != nil { + return errors.Wrap(err, "cannot retrieve webhook URL for Slack notifier") + } + message, err := msg.New(msg.Options{ Meta: c.meta, Entry: entry, @@ -93,7 +100,7 @@ func (c *Client) Send(entry model.NotifEntry) error { color = "#0054ca" } - return slack.PostWebhook(c.cfg.WebhookURL, &slack.WebhookMessage{ + return slack.PostWebhook(webhookURL, &slack.WebhookMessage{ Attachments: []slack.Attachment{ { Color: color, diff --git a/internal/notif/teams/client.go b/internal/notif/teams/client.go index bbaa5470d..200bbec01 100644 --- a/internal/notif/teams/client.go +++ b/internal/notif/teams/client.go @@ -11,6 +11,8 @@ import ( "github.com/crazy-max/diun/v4/internal/model" "github.com/crazy-max/diun/v4/internal/msg" "github.com/crazy-max/diun/v4/internal/notif/notifier" + "github.com/crazy-max/diun/v4/pkg/utl" + "github.com/pkg/errors" ) // Client represents an active webhook notification object @@ -50,6 +52,11 @@ type Fact struct { // Send creates and sends a webhook notification with an entry func (c *Client) Send(entry model.NotifEntry) error { + webhookURL, err := utl.GetSecret(c.cfg.WebhookURL, c.cfg.WebhookURLFile) + if err != nil { + return errors.Wrap(err, "cannot retrieve webhook URL for Teams notifier") + } + message, err := msg.New(msg.Options{ Meta: c.meta, Entry: entry, @@ -107,7 +114,7 @@ func (c *Client) Send(entry model.NotifEntry) error { ctx, cancel := context.WithTimeout(context.Background(), time.Duration(10)*time.Second) defer cancel() - req, err := http.NewRequestWithContext(ctx, "POST", c.cfg.WebhookURL, bytes.NewBuffer(jsonBody)) + req, err := http.NewRequestWithContext(ctx, "POST", webhookURL, bytes.NewBuffer(jsonBody)) if err != nil { return err }