Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 13 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ Main features:

### Configuration

Whether running manually or via the Docker image, the configuration is set
Whether running manually or via the Docker image, the configuration is set
via environment variables. When running manually, copy `.env.default`
into `.env`, set the values and they will be loaded automatically.
When using the Docker image, set the environment variables when running
into `.env`, set the values and they will be loaded automatically.
When using the Docker image, set the environment variables when running
the container.

### Docker
Expand All @@ -37,11 +37,20 @@ You will need to configure a webhook receiver in Alertmanager. It should looks s
receivers:
- name: 'myreceiver'
webhook_configs:
- url: 'https://my-matrix-alertmanager.tld/alerts?secret=veryverysecretkeyhere'
- url: 'https://my-matrix-alertmanager.tld/alerts'
http_config:
authorization:
type: Bearer
credentials: 'veryverysecretkeyhere'
```

The secret key obviously should match the one in the alertmanager configuration.

The configuration above will pass the secret as an Authorization
header bearer token, alternatively you can pass it as a query
parameter `secret`, but if you do it that way then it is not redacted
from the Alertmanager web UI so this is not really recommended.

### Prometheus rules

Add some styling to your prometheus rules
Expand Down
27 changes: 25 additions & 2 deletions src/routes.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,39 @@
const client = require('./client')
const utils = require('./utils')

const crypto = require('crypto')

const passwordsEqual = (a, b) => {
return a && b && a.length === b.length && crypto.timingSafeEqual(Buffer.from(a), Buffer.from(b))
}

const routes = {
getRoot: (req, res) => {
res.send('Hey 👋')
},
postAlerts: async (req, res) => {
const secret = req.query.secret
if (secret !== process.env.APP_ALERTMANAGER_SECRET) {
let authorized = false
let expectedSecret = process.env.APP_ALERTMANAGER_SECRET

if (!expectedSecret) {
console.error("APP_ALERTMANAGER_SECRET is not configured, unable to authenticate requests")
res.status(500).end()
return
}

if (passwordsEqual(req.query.secret, expectedSecret)) {
authorized = true
}

if (passwordsEqual(req.get('authorization'), `Bearer ${expectedSecret}`)) {
authorized = true
}

if (!authorized) {
res.status(403).end()
return
}

const alerts = utils.parseAlerts(req.body)

if (!alerts) {
Expand Down
Loading