Add support for self signed ntfy certificates
A fingerprint can be specified in the configuration file. If it matches the one from the server certificate, it will be accepted. Closes: https://todo.xenrox.net/~xenrox/ntfy-alertmanager/22
This commit is contained in:
parent
1bfb814f14
commit
25e65db8bd
4 changed files with 51 additions and 7 deletions
|
@ -51,6 +51,9 @@ ntfy {
|
|||
# ntfy authentication via access tokens (https://docs.ntfy.sh/publish/#access-tokens)
|
||||
# Either access-token or a user/password combination can be used - not both.
|
||||
access-token foobar
|
||||
# When using (self signed) certificates that cannot be verified, you can instead specify
|
||||
# the SHA512 fingerprint.
|
||||
certificate-fingerprint 136d2b889c5736d081b4b29c7909276292cfb86a6bd3ad4635cb7017eb996e28082ab8c6794bf62e817941981d53c807b35c245fb18eb6fb66b5ddb4d05c299
|
||||
# Forward all messages to the specified email address.
|
||||
email-address foo@bar.com
|
||||
# Call the specified number for all alerts. Use `yes` to pick the first of your verified numbers.
|
||||
|
|
|
@ -36,12 +36,13 @@ type Config struct {
|
|||
}
|
||||
|
||||
type ntfyConfig struct {
|
||||
Topic string
|
||||
User string
|
||||
Password string
|
||||
AccessToken string
|
||||
EmailAddress string
|
||||
Call string
|
||||
Topic string
|
||||
User string
|
||||
Password string
|
||||
AccessToken string
|
||||
CertFingerprint string
|
||||
EmailAddress string
|
||||
Call string
|
||||
}
|
||||
|
||||
type labels struct {
|
||||
|
@ -277,6 +278,13 @@ func ReadConfig(path string) (*Config, error) {
|
|||
return nil, errors.New("ntfy: cannot use both an access-token and a user/password at the same time")
|
||||
}
|
||||
|
||||
d = ntfyDir.Children.Get("certificate-fingerprint")
|
||||
if d != nil {
|
||||
if err := d.ParseParams(&config.Ntfy.CertFingerprint); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
d = ntfyDir.Children.Get("email-address")
|
||||
if d != nil {
|
||||
if err := d.ParseParams(&config.Ntfy.EmailAddress); err != nil {
|
||||
|
|
|
@ -45,6 +45,7 @@ resolved {
|
|||
|
||||
ntfy {
|
||||
topic https://ntfy.sh/alertmanager-alerts
|
||||
certificate-fingerprint 136d2b889c5736d081b4b29c7909276292cfb86a6bd3ad4635cb7017eb996e28082ab8c6794bf62e817941981d53c807b35c245fb18eb6fb66b5ddb4d05c299
|
||||
user user
|
||||
password pass
|
||||
}
|
||||
|
@ -71,7 +72,12 @@ cache {
|
|||
AlertMode: Multi,
|
||||
User: "webhookUser",
|
||||
Password: "webhookPass",
|
||||
Ntfy: ntfyConfig{Topic: "https://ntfy.sh/alertmanager-alerts", User: "user", Password: "pass"},
|
||||
Ntfy: ntfyConfig{
|
||||
Topic: "https://ntfy.sh/alertmanager-alerts",
|
||||
User: "user",
|
||||
Password: "pass",
|
||||
CertFingerprint: "136d2b889c5736d081b4b29c7909276292cfb86a6bd3ad4635cb7017eb996e28082ab8c6794bf62e817941981d53c807b35c245fb18eb6fb66b5ddb4d05c299",
|
||||
},
|
||||
Labels: labels{Order: []string{"severity", "instance"},
|
||||
Label: map[string]labelConfig{
|
||||
"severity:critical": {
|
||||
|
|
27
main.go
27
main.go
|
@ -5,9 +5,13 @@ import (
|
|||
"context"
|
||||
"crypto/sha512"
|
||||
"crypto/subtle"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
_ "embed"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
|
@ -329,6 +333,29 @@ func (br *bridge) publish(n *notification) error {
|
|||
req.Header.Set("Actions", fmt.Sprintf("http, Silence, %s, method=POST, body=%s%s", url, n.silenceBody, authString))
|
||||
}
|
||||
|
||||
configFingerprint := br.cfg.Ntfy.CertFingerprint
|
||||
if configFingerprint != "" {
|
||||
tlsCfg := &tls.Config{}
|
||||
tlsCfg.VerifyPeerCertificate = func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
|
||||
for _, rawCert := range rawCerts {
|
||||
hash := sha512.Sum512(rawCert)
|
||||
if hex.EncodeToString(hash[:]) == configFingerprint {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
if len(rawCerts) == 0 {
|
||||
return errors.New("the ntfy server does not offer a certificate")
|
||||
}
|
||||
|
||||
hash := sha512.Sum512(rawCerts[0])
|
||||
return fmt.Errorf("ntfy certificate fingerprint does not match: expected %q, got %q", hex.EncodeToString(hash[:]), configFingerprint)
|
||||
}
|
||||
|
||||
tlsCfg.InsecureSkipVerify = true
|
||||
br.client.Transport = &http.Transport{TLSClientConfig: tlsCfg}
|
||||
}
|
||||
|
||||
resp, err := br.client.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
Loading…
Reference in a new issue