Skip to content

Commit

Permalink
jitsubase: separate RAW_AUTH_TOKENS from AUTH_TOKENS
Browse files Browse the repository at this point in the history
  • Loading branch information
absorbb committed Jan 31, 2024
1 parent baed078 commit 434fb69
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 42 deletions.
20 changes: 16 additions & 4 deletions .docs/server-config.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,17 +47,29 @@ reused on next restart.

*Optional, default value: `''`*

A list of auth tokens that authorizes user in HTTP interface separated by comma. Each token can be either:
* `${token}` un-encrypted token value
* `${salt}.${hash}` hashed token. `${salt}` should be random string. Hash is `base64(sha512($token + $salt + $BULKER_TOKEN_SECRET)`.
* Token is `[0-9a-zA-Z_\-]` (only letters, digits, underscore and dash)
A list of hashed auth tokens that authorizes user in HTTP interface separated by comma. Each must have format:

`${salt}.${hash}` where `${salt}` should be random string. Hash is `base64(sha512($token + $salt + BULKER_TOKEN_SECRET)`.

`$token` must consist only of letters, digits, underscore and dash

### `BULKER_TOKEN_SECRET`

*Optional, default value: empty string*

See above. A secret that is used for hashing tokens.

### `BULKER_RAW_AUTH_TOKENS`

*Optional, default value: `''`*

A list of plain non hashed tokens separated by comma. Each token must consist only of letters, digits, underscore and dash

Can be used instead of `BULKER_AUTH_TOKENS`,`BULKER_TOKEN_SECRET` pair. It offers simplicity at cost of lower security.

Not recommended for production.



## Connection to Kafka

Expand Down
4 changes: 1 addition & 3 deletions bulkerapp/app/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,7 @@ type Router struct {
}

func NewRouter(appContext *Context) *Router {
authTokens := strings.Split(appContext.config.AuthTokens, ",")
tokenSecrets := strings.Split(appContext.config.TokenSecrets, ",")
base := appbase.NewRouterBase(authTokens, tokenSecrets, []string{"/ready", "/health"})
base := appbase.NewRouterBase(appContext.config.Config, []string{"/ready", "/health"})

router := &Router{
Router: base,
Expand Down
4 changes: 1 addition & 3 deletions ingest/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,7 @@ type StreamCredentials struct {
}

func NewRouter(appContext *Context) *Router {
authTokens := strings.Split(appContext.config.AuthTokens, ",")
tokenSecrets := strings.Split(appContext.config.TokenSecrets, ",")
base := appbase.NewRouterBase(authTokens, tokenSecrets, []string{
base := appbase.NewRouterBase(appContext.config.Config, []string{
"/health",
"/p.js",
"/v1/projects/:writeKey/settings",
Expand Down
10 changes: 6 additions & 4 deletions jitsubase/appbase/app_base.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,13 @@ type Config struct {

// # AUTH

// AuthTokens A list of auth tokens that authorizes user in HTTP interface separated by comma. Each token can be either:
// - `${token}` un-encrypted token value
// - `${salt}.${hash}` hashed token.` ${salt}` should be random string. Hash is `base64(sha512($token + $salt + TokenSecrets)`.
// - Token is `[0-9a-zA-Z_\-]` (only letters, digits, underscore and dash)
// AuthTokens A list of hashed auth tokens that authorizes user in HTTP interface separated by comma. Each must have format:
// `${salt}.${hash}` where `${salt}` should be random string. Hash is `base64(sha512($token + $salt + TokenSecrets)`.
// `$token` must consist only of letters, digits, underscore and dash
AuthTokens string `mapstructure:"AUTH_TOKENS"`
// RawAuthTokens plain non hashed tokens separated by comma. Each token must consist only of letters, digits, underscore and dash
RawAuthTokens string `mapstructure:"RAW_AUTH_TOKENS"`

// See AuthTokens
TokenSecrets string `mapstructure:"TOKEN_SECRET"`

Expand Down
61 changes: 37 additions & 24 deletions jitsubase/appbase/router_base.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,24 +17,39 @@ const ContextMessageId = "contextMessageId"

type Router struct {
Service
engine *gin.Engine
authTokens []string
tokenSecrets []string
noAuthPaths utils.Set[string]
engine *gin.Engine
authTokens []string
rawAuthTokens []string
tokenSecrets []string
noAuthPaths utils.Set[string]
}

func NewRouterBase(authTokens, tokenSecrets, noAuthPaths []string) *Router {
func NewRouterBase(config Config, noAuthPaths []string) *Router {
authTokens := strings.Split(config.AuthTokens, ",")
rawAuthTokens := strings.Split(config.RawAuthTokens, ",")
tokenSecrets := strings.Split(config.TokenSecrets, ",")
base := NewServiceBase("router")
if len(authTokens) == 1 && authTokens[0] == "" {
if config.AuthTokens == "" {
authTokens = nil
}
if config.RawAuthTokens == "" {
rawAuthTokens = nil
}
if authTokens == nil && rawAuthTokens == nil {
base.Warnf("⚠️ No auth tokens provided. All requests will be allowed")
}
for _, authToken := range authTokens {
if !strings.Contains(authToken, ".") {
base.Fatalf("Invalid auth token: %s Should be in format ${salt}.${hash} or %sRAW_AUTH_TOKENS config variable must be used instead", authToken, config.AppSetting.EnvPrefixWithUnderscore())
}
}

router := &Router{
Service: base,
authTokens: authTokens,
tokenSecrets: tokenSecrets,
noAuthPaths: utils.NewSet(noAuthPaths...),
Service: base,
authTokens: authTokens,
rawAuthTokens: rawAuthTokens,
tokenSecrets: tokenSecrets,
noAuthPaths: utils.NewSet(noAuthPaths...),
}
gin.SetMode(gin.ReleaseMode)
engine := gin.New()
Expand Down Expand Up @@ -64,23 +79,21 @@ func (r *Router) authMiddleware(c *gin.Context) {
return
}
for _, authToken := range r.authTokens {
if !strings.Contains(authToken, ".") {
if token == authToken {
hashedToken := strings.Split(authToken, ".")
salt := hashedToken[0]
hash := hashedToken[1]
for _, secret := range r.tokenSecrets {
//a := HashToken(token, salt, secret)
//logging.Debugf("Hashed token: %s. Hash: %s ", a, hash)
if HashToken(token, salt, secret) == hash {
//logging.Debugf("Token %s is valid", token)
return
}
} else {
hashedToken := strings.Split(authToken, ".")
salt := hashedToken[0]
hash := hashedToken[1]
for _, secret := range r.tokenSecrets {
//a := HashToken(token, salt, secret)
//logging.Debugf("Hashed token: %s. Hash: %s ", a, hash)
if HashToken(token, salt, secret) == hash {
//logging.Debugf("Token %s is valid", token)
return
}
}
}
}
for _, rawAuthToken := range r.rawAuthTokens {
if token == rawAuthToken {
return
}
}
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "Invalid token: " + token})
Expand Down
5 changes: 1 addition & 4 deletions sync-controller/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,14 @@ import (
"github.com/jitsucom/bulker/jitsubase/appbase"
"net/http"
"net/http/pprof"
"strings"
)

type Router struct {
*appbase.Router
}

func NewRouter(appContext *Context) *Router {
authTokens := strings.Split(appContext.config.AuthTokens, ",")
tokenSecrets := strings.Split(appContext.config.TokenSecrets, ",")
base := appbase.NewRouterBase(authTokens, tokenSecrets, []string{"/health"})
base := appbase.NewRouterBase(appContext.config.Config, []string{"/health"})

router := &Router{
Router: base,
Expand Down

0 comments on commit 434fb69

Please sign in to comment.