Add basic auth for metrics endpoint

This commit is contained in:
kolaente 2021-02-28 11:29:53 +01:00
parent c71a1fea82
commit 3999580fe6
No known key found for this signature in database
GPG key ID: F40E70337AB24C9B
4 changed files with 71 additions and 19 deletions

View file

@ -13,9 +13,6 @@ service:
rootpath: <rootpath>
# The max number of items which can be returned per page
maxitemsperpage: 50
# If set to true, enables a /metrics endpoint for prometheus to collect metrics about the system
# You'll need to use redis for this in order to enable common metrics over multiple nodes
enablemetrics: false
# Enable the caldav endpoint, see the docs for more details
enablecaldav: true
# Set the motd message, available from the /info endpoint
@ -283,3 +280,12 @@ auth:
clientid:
# The client secret used to authenticate Vikunja at the OpenID Connect provider.
clientsecret:
# Prometheus metrics endpoint
metrics:
# If set to true, enables a /metrics endpoint for prometheus to collect metrics about Vikunja.
enabled: false
# If set to a non-empty value the /metrics endpoint will require this as a username via basic auth in combination with the password below.
username:
# If set to a non-empty value the /metrics endpoint will require this as a password via basic auth in combination with the username below.
password:

View file

@ -100,13 +100,6 @@ The max number of items which can be returned per page
Default: `50`
### enablemetrics
If set to true, enables a /metrics endpoint for prometheus to collect metrics about the system
You'll need to use redis for this in order to enable common metrics over multiple nodes
Default: `false`
### enablecaldav
Enable the caldav endpoint, see the docs for more details
@ -623,3 +616,29 @@ Take a look at the [default config file](https://kolaente.dev/vikunja/api/src/br
Default: `<empty>`
---
## metrics
Prometheus metrics endpoint
### enabled
If set to true, enables a /metrics endpoint for prometheus to collect metrics about Vikunja.
Default: `false`
### username
If set to a non-empty value the /metrics endpoint will require this as a username via basic auth in combination with the password below.
Default: `<empty>`
### password
If set to a non-empty value the /metrics endpoint will require this as a password via basic auth in combination with the username below.
Default: `<empty>`

View file

@ -36,12 +36,13 @@ type Key string
// These constants hold all config value keys
const (
// #nosec
ServiceJWTSecret Key = `service.JWTSecret`
ServiceInterface Key = `service.interface`
ServiceFrontendurl Key = `service.frontendurl`
ServiceEnableCaldav Key = `service.enablecaldav`
ServiceRootpath Key = `service.rootpath`
ServiceMaxItemsPerPage Key = `service.maxitemsperpage`
ServiceJWTSecret Key = `service.JWTSecret`
ServiceInterface Key = `service.interface`
ServiceFrontendurl Key = `service.frontendurl`
ServiceEnableCaldav Key = `service.enablecaldav`
ServiceRootpath Key = `service.rootpath`
ServiceMaxItemsPerPage Key = `service.maxitemsperpage`
// Deprecated. Use metrics.enabled
ServiceEnableMetrics Key = `service.enablemetrics`
ServiceMotd Key = `service.motd`
ServiceEnableLinkSharing Key = `service.enablelinksharing`
@ -142,6 +143,10 @@ const (
BackgroundsUnsplashApplicationID Key = `backgrounds.providers.unsplash.applicationid`
KeyvalueType Key = `keyvalue.type`
MetricsEnabled Key = `metrics.enabled`
MetricsUsername Key = `metrics.username`
MetricsPassword Key = `metrics.password`
)
// GetString returns a string config value
@ -311,6 +316,8 @@ func InitDefaultConfig() {
BackgroundsUnsplashEnabled.setDefault(false)
// Key Value
KeyvalueType.setDefault("memory")
// Metrics
MetricsEnabled.setDefault(false)
}
// InitConfig initializes the config, sets defaults etc.
@ -364,6 +371,11 @@ func InitConfig() {
MigrationMicrosoftTodoRedirectURL.Set(ServiceFrontendurl.GetString() + "migrate/microsoft-todo")
}
if ServiceEnableMetrics.GetBool() {
log.Println("WARNING: service.enablemetrics is deprecated and will be removed in a future release. Please use metrics.enable.")
MetricsEnabled.Set(true)
}
log.Printf("Using config file: %s", viper.ConfigFileUsed())
}

View file

@ -17,6 +17,8 @@
package routes
import (
"crypto/subtle"
"code.vikunja.io/api/pkg/config"
"code.vikunja.io/api/pkg/log"
"code.vikunja.io/api/pkg/metrics"
@ -24,11 +26,12 @@ import (
auth2 "code.vikunja.io/api/pkg/modules/auth"
"code.vikunja.io/api/pkg/user"
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
func setupMetrics(a *echo.Group) {
if !config.ServiceEnableMetrics.GetBool() {
if !config.MetricsEnabled.GetBool() {
return
}
@ -71,11 +74,23 @@ func setupMetrics(a *echo.Group) {
}
}
a.GET("/metrics", echo.WrapHandler(promhttp.HandlerFor(metrics.GetRegistry(), promhttp.HandlerOpts{})))
r := a.Group("/metrics")
if config.MetricsUsername.GetString() != "" && config.MetricsPassword.GetString() != "" {
r.Use(middleware.BasicAuth(func(username, password string, c echo.Context) (bool, error) {
if subtle.ConstantTimeCompare([]byte(username), []byte(config.MetricsUsername.GetString())) == 1 &&
subtle.ConstantTimeCompare([]byte(password), []byte(config.MetricsPassword.GetString())) == 1 {
return true, nil
}
return false, nil
}))
}
r.GET("", echo.WrapHandler(promhttp.HandlerFor(metrics.GetRegistry(), promhttp.HandlerOpts{})))
}
func setupMetricsMiddleware(a *echo.Group) {
if !config.ServiceEnableMetrics.GetBool() {
if !config.MetricsEnabled.GetBool() {
return
}