-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Add Pushover notifications support (#3693) #3976
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from 3 commits
39a1d23
cc5aee4
f745f6d
b9d6567
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -20,11 +20,12 @@ var templates embed.FS | |
|
|
||
| // Alert represents an alert that will be templated and sent to the appropriate service | ||
| type Alert struct { | ||
| Name string | ||
| Author string | ||
| Color string | ||
| Task alertTask | ||
| Chat alertChat | ||
| Name string | ||
| Author string | ||
| Color string | ||
| Task alertTask | ||
| Chat alertChat | ||
| Pushover alertPushover | ||
| } | ||
|
|
||
| type alertTask struct { | ||
|
|
@@ -39,6 +40,11 @@ type alertChat struct { | |
| ID string | ||
| } | ||
|
|
||
| type alertPushover struct { | ||
| Token string // application/API token | ||
| User string // global user OR target group key | ||
| } | ||
|
|
||
| func (t *TaskRunner) sendMailAlert() { | ||
| if !util.Config.EmailAlert || !t.alert { | ||
| return | ||
|
|
@@ -190,6 +196,82 @@ func (t *TaskRunner) sendTelegramAlert() { | |
| } | ||
| } | ||
|
|
||
| func (t *TaskRunner) sendPushoverAlert() { | ||
| if !util.Config.PushoverAlert || !t.alert { | ||
| return | ||
| } | ||
|
|
||
| if t.Template.SuppressSuccessAlerts && t.Task.Status == task_logger.TaskSuccessStatus { | ||
| return | ||
| } | ||
|
|
||
| // Token: per-project GUI override wins over global config. | ||
| token := util.Config.PushoverAPIToken | ||
| if t.alertPushoverToken != nil && *t.alertPushoverToken != "" { | ||
| token = *t.alertPushoverToken | ||
| } | ||
|
|
||
| user := util.Config.PushoverUserGroupKey | ||
|
|
||
| if token == "" || user == "" { | ||
| return | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we should put a |
||
| } | ||
|
|
||
| body := bytes.NewBufferString("") | ||
| author, version := t.alertInfos() | ||
|
|
||
| alert := Alert{ | ||
| Name: t.Template.Name, | ||
| Author: author, | ||
| Color: t.alertColor("pushover"), | ||
| Task: alertTask{ | ||
| ID: strconv.Itoa(t.Task.ID), | ||
| URL: t.taskLink(), | ||
| Result: t.Task.Status.Format(), | ||
| Version: version, | ||
| Desc: t.Task.Message, | ||
| }, | ||
| Pushover: alertPushover{Token: token, User: user}, | ||
| } | ||
|
|
||
| tpl, err := template.ParseFS(templates, "templates/pushover.tmpl") | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since the pushover message is sent as JSON body, i don't recommend using a template for various reasons, from a practical to a security perspective
JSON-marshall it and pass it to the request body. Another thing is the Since the value also expects input from the user, it's a security-aware practice to sanitize the input first: |
||
|
|
||
| if err != nil { | ||
| t.Log("Can't parse pushover alert template!") | ||
| panic(err) | ||
| } | ||
|
|
||
| if err := tpl.Execute(body, alert); err != nil { | ||
| t.Log("Can't generate pushover alert template!") | ||
| panic(err) | ||
| } | ||
|
|
||
| if body.Len() == 0 { | ||
| t.Log("Buffer for pushover alert is empty") | ||
| return | ||
| } | ||
|
|
||
| t.Log("Attempting to send pushover alert") | ||
|
|
||
| resp, err := http.Post( | ||
| "https://api.pushover.net/1/messages.json", | ||
| "application/json", | ||
| body, | ||
| ) | ||
|
|
||
| if err != nil { | ||
| t.Log("Can't send pushover alert! Error: " + err.Error()) | ||
| } else if resp.StatusCode != 200 { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i'm being nitpicky here, but i think we can change hardcoded |
||
| t.Log("Can't send pushover alert! Response code: " + strconv.Itoa(resp.StatusCode)) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can use |
||
| } else { | ||
| t.Log("Sent successfully pushover alert") | ||
| } | ||
|
|
||
| if resp != nil { | ||
| defer resp.Body.Close() //nolint:errcheck | ||
| } | ||
| } | ||
|
|
||
| func (t *TaskRunner) sendSlackAlert() { | ||
| if !util.Config.SlackAlert || !t.alert { | ||
| return | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| { | ||
| "token": "{{ .Pushover.Token }}", | ||
| "user": "{{ .Pushover.User }}", | ||
| "title": "{{ .Name }} #{{ .Task.ID }}: {{ .Task.Result }}", | ||
| "html": 1, | ||
| "message": "<b>{{ .Task.Result }}</b> {{ .Task.Version }} - {{ .Task.Desc }}\nby {{ .Author }}", | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Severity: Medium — JSON injection / alert manipulation This template builds JSON with Attack path: start a task with a crafted Impact: redirect operational alerts to an attacker-controlled Pushover account (information disclosure) or manipulate notification metadata; phishing via injected There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Severity: Medium — JSON injection / alert hijacking This template builds JSON with Attack path: start a task with a crafted Impact: operational alert hijacking (information disclosure) and possible phishing via injected Fix: build the request with |
||
| "url": "{{ .Task.URL }}", | ||
| "url_title": "View task in Semaphore" | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.