Skip to content

Commit

Permalink
feat: add http basic auth for receive
Browse files Browse the repository at this point in the history
Signed-off-by: Sergey Lanzman <[email protected]>
  • Loading branch information
sergeylanzman committed Dec 20, 2024
1 parent 4a84785 commit e574c6a
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 5 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ We use *breaking :warning:* to mark changes that are not backward compatible (re
- [#7907](https://github.com/thanos-io/thanos/pull/7907) Receive: Add `--receive.grpc-service-config` flag to configure gRPC service config for the receivers.
- [#7961](https://github.com/thanos-io/thanos/pull/7961) Store Gateway: Add `--store.posting-group-max-keys` flag to mark posting group as lazy if it exceeds number of keys limit. Added `thanos_bucket_store_lazy_expanded_posting_groups_total` for total number of lazy posting groups and corresponding reasons.
- [#8000](https://github.com/thanos-io/thanos/pull/8000) Query: Bump promql-engine, pass partial response through options
- [#8012](https://github.com/thanos-io/thanos/pull/8012) Receive: Add optional HTTP Basic Auth checks for incoming write requests via `--receive.basic-auth-username` and `--receive.basic-auth-password` flags.


### Changed

Expand Down
8 changes: 8 additions & 0 deletions cmd/thanos/receive.go
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,8 @@ func runReceive(
Registry: reg,
Endpoint: conf.endpoint,
TenantHeader: conf.tenantHeader,
BasicAuthUsername: conf.basicAuthUsername,
BasicAuthPassword: conf.basicAuthPassword,
TenantField: conf.tenantField,
DefaultTenantID: conf.defaultTenantID,
ReplicaHeader: conf.replicaHeader,
Expand Down Expand Up @@ -851,6 +853,8 @@ type receiveConfig struct {
refreshInterval *model.Duration
endpoint string
tenantHeader string
basicAuthUsername string
basicAuthPassword string
tenantField string
tenantLabelName string
defaultTenantID string
Expand Down Expand Up @@ -952,6 +956,10 @@ func (rc *receiveConfig) registerFlag(cmd extkingpin.FlagClause) {

cmd.Flag("receive.tenant-header", "HTTP header to determine tenant for write requests.").Default(tenancy.DefaultTenantHeader).StringVar(&rc.tenantHeader)

cmd.Flag("receive.basic-auth-username", "HTTP Basic Auth username for write requests.").Default("").StringVar(&rc.basicAuthUsername)

cmd.Flag("receive.basic-auth-password", "HTTP Basic Auth password for write requests.").Default("").StringVar(&rc.basicAuthPassword)

cmd.Flag("receive.tenant-certificate-field", "Use TLS client's certificate field to determine tenant for write requests. Must be one of "+tenancy.CertificateFieldOrganization+", "+tenancy.CertificateFieldOrganizationalUnit+" or "+tenancy.CertificateFieldCommonName+". This setting will cause the receive.tenant-header flag value to be ignored.").Default("").EnumVar(&rc.tenantField, "", tenancy.CertificateFieldOrganization, tenancy.CertificateFieldOrganizationalUnit, tenancy.CertificateFieldCommonName)

cmd.Flag("receive.default-tenant-id", "Default tenant ID to use when none is provided via a header.").Default(tenancy.DefaultTenant).StringVar(&rc.defaultTenantID)
Expand Down
16 changes: 11 additions & 5 deletions pkg/receive/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ type Options struct {
ListenAddress string
Registry *prometheus.Registry
TenantHeader string
BasicAuthUsername string
BasicAuthPassword string
TenantField string
DefaultTenantID string
ReplicaHeader string
Expand Down Expand Up @@ -262,16 +264,20 @@ func NewHandler(logger log.Logger, o *Options) *Handler {
}
return next
}
handler := http.HandlerFunc(h.receiveHTTP)

// Conditionally apply BasicAuth
if o.BasicAuthUsername != "" && o.BasicAuthPassword != "" {
level.Info(logger).Log("msg", "Basic Auth enabled for incoming requests")
handler = middleware.BasicAuth(handler, o.BasicAuthUsername, o.BasicAuthPassword)
}
handler = middleware.RequestID(handler)

h.router.Post(
"/api/v1/receive",
instrf(
"receive",
readyf(
middleware.RequestID(
http.HandlerFunc(h.receiveHTTP),
),
),
readyf(handler),
),
)

Expand Down
20 changes: 20 additions & 0 deletions pkg/server/http/middleware/basic_auth.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package middleware

import (
"net/http"
)

// BasicAuth returns a middleware that checks HTTP Basic Authentication.
// If the username or password do not match the expected credentials,
// a 401 Unauthorized response is returned. Otherwise, the wrapped handler
// is invoked.
func BasicAuth(next http.HandlerFunc, expectedUser, expectedPassword string) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
user, pass, ok := r.BasicAuth()
if !ok || user != expectedUser || pass != expectedPassword {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}
next(w, r)
}
}

0 comments on commit e574c6a

Please sign in to comment.