mirror of
https://github.com/grafana/grafana.git
synced 2025-02-20 11:48:34 -06:00
* Decode auth proxy headers using URL encoding * Header encoding configuration via settings file * Rename configuration setting to headers_encoded * Quoted-printable encoding * Tests for AuthProxy * Fix encoding name * Remove authproxy init
220 lines
5.5 KiB
Go
220 lines
5.5 KiB
Go
package authproxy
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"net/http"
|
|
"testing"
|
|
|
|
"github.com/grafana/grafana/pkg/bus"
|
|
"github.com/grafana/grafana/pkg/infra/log"
|
|
"github.com/grafana/grafana/pkg/infra/remotecache"
|
|
"github.com/grafana/grafana/pkg/models"
|
|
"github.com/grafana/grafana/pkg/services/ldap"
|
|
"github.com/grafana/grafana/pkg/services/multildap"
|
|
"github.com/grafana/grafana/pkg/setting"
|
|
"github.com/grafana/grafana/pkg/web"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
const hdrName = "markelog"
|
|
|
|
func prepareMiddleware(t *testing.T, remoteCache *remotecache.RemoteCache, configureReq func(*http.Request, *setting.Cfg)) *AuthProxy {
|
|
t.Helper()
|
|
|
|
req, err := http.NewRequest("POST", "http://example.com", nil)
|
|
require.NoError(t, err)
|
|
|
|
cfg := setting.NewCfg()
|
|
|
|
if configureReq != nil {
|
|
configureReq(req, cfg)
|
|
} else {
|
|
cfg.AuthProxyHeaderName = "X-Killa"
|
|
req.Header.Set(cfg.AuthProxyHeaderName, hdrName)
|
|
}
|
|
|
|
ctx := &models.ReqContext{
|
|
Context: &web.Context{Req: req},
|
|
}
|
|
|
|
auth := New(cfg, &Options{
|
|
RemoteCache: remoteCache,
|
|
Ctx: ctx,
|
|
OrgID: 4,
|
|
})
|
|
|
|
return auth
|
|
}
|
|
|
|
func TestMiddlewareContext(t *testing.T) {
|
|
logger := log.New("test")
|
|
cache := remotecache.NewFakeStore(t)
|
|
|
|
t.Run("When the cache only contains the main header with a simple cache key", func(t *testing.T) {
|
|
const id int64 = 33
|
|
// Set cache key
|
|
h, err := HashCacheKey(hdrName)
|
|
require.NoError(t, err)
|
|
key := fmt.Sprintf(CachePrefix, h)
|
|
err = cache.Set(context.Background(), key, id, 0)
|
|
require.NoError(t, err)
|
|
// Set up the middleware
|
|
auth := prepareMiddleware(t, cache, nil)
|
|
gotKey, err := auth.getKey()
|
|
require.NoError(t, err)
|
|
assert.Equal(t, key, gotKey)
|
|
|
|
gotID, err := auth.Login(logger, false)
|
|
require.NoError(t, err)
|
|
|
|
assert.Equal(t, id, gotID)
|
|
})
|
|
|
|
t.Run("When the cache key contains additional headers", func(t *testing.T) {
|
|
const id int64 = 33
|
|
const group = "grafana-core-team"
|
|
const role = "Admin"
|
|
|
|
h, err := HashCacheKey(hdrName + "-" + group + "-" + role)
|
|
require.NoError(t, err)
|
|
key := fmt.Sprintf(CachePrefix, h)
|
|
err = cache.Set(context.Background(), key, id, 0)
|
|
require.NoError(t, err)
|
|
|
|
auth := prepareMiddleware(t, cache, func(req *http.Request, cfg *setting.Cfg) {
|
|
cfg.AuthProxyHeaderName = "X-Killa"
|
|
cfg.AuthProxyHeaders = map[string]string{"Groups": "X-WEBAUTH-GROUPS", "Role": "X-WEBAUTH-ROLE"}
|
|
req.Header.Set(cfg.AuthProxyHeaderName, hdrName)
|
|
req.Header.Set("X-WEBAUTH-GROUPS", group)
|
|
req.Header.Set("X-WEBAUTH-ROLE", role)
|
|
})
|
|
assert.Equal(t, "auth-proxy-sync-ttl:f5acfffd56daac98d502ef8c8b8c5d56", key)
|
|
|
|
gotID, err := auth.Login(logger, false)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, id, gotID)
|
|
})
|
|
}
|
|
|
|
func TestMiddlewareContext_ldap(t *testing.T) {
|
|
logger := log.New("test")
|
|
|
|
t.Run("Logs in via LDAP", func(t *testing.T) {
|
|
const id int64 = 42
|
|
|
|
bus.AddHandler("test", func(ctx context.Context, cmd *models.UpsertUserCommand) error {
|
|
cmd.Result = &models.User{
|
|
Id: id,
|
|
}
|
|
|
|
return nil
|
|
})
|
|
|
|
origIsLDAPEnabled := isLDAPEnabled
|
|
origGetLDAPConfig := getLDAPConfig
|
|
origNewLDAP := newLDAP
|
|
t.Cleanup(func() {
|
|
newLDAP = origNewLDAP
|
|
isLDAPEnabled = origIsLDAPEnabled
|
|
getLDAPConfig = origGetLDAPConfig
|
|
})
|
|
|
|
isLDAPEnabled = func(*setting.Cfg) bool {
|
|
return true
|
|
}
|
|
|
|
stub := &multildap.MultiLDAPmock{
|
|
ID: id,
|
|
}
|
|
|
|
getLDAPConfig = func(*setting.Cfg) (*ldap.Config, error) {
|
|
config := &ldap.Config{
|
|
Servers: []*ldap.ServerConfig{
|
|
{
|
|
SearchBaseDNs: []string{"BaseDNHere"},
|
|
},
|
|
},
|
|
}
|
|
return config, nil
|
|
}
|
|
|
|
newLDAP = func(servers []*ldap.ServerConfig) multildap.IMultiLDAP {
|
|
return stub
|
|
}
|
|
|
|
cache := remotecache.NewFakeStore(t)
|
|
|
|
auth := prepareMiddleware(t, cache, nil)
|
|
|
|
gotID, err := auth.Login(logger, false)
|
|
require.NoError(t, err)
|
|
|
|
assert.Equal(t, id, gotID)
|
|
assert.True(t, stub.UserCalled)
|
|
})
|
|
|
|
t.Run("Gets nice error if LDAP is enabled, but not configured", func(t *testing.T) {
|
|
const id int64 = 42
|
|
origIsLDAPEnabled := isLDAPEnabled
|
|
origNewLDAP := newLDAP
|
|
origGetLDAPConfig := getLDAPConfig
|
|
t.Cleanup(func() {
|
|
isLDAPEnabled = origIsLDAPEnabled
|
|
newLDAP = origNewLDAP
|
|
getLDAPConfig = origGetLDAPConfig
|
|
})
|
|
|
|
isLDAPEnabled = func(*setting.Cfg) bool {
|
|
return true
|
|
}
|
|
|
|
getLDAPConfig = func(*setting.Cfg) (*ldap.Config, error) {
|
|
return nil, errors.New("something went wrong")
|
|
}
|
|
|
|
cache := remotecache.NewFakeStore(t)
|
|
|
|
auth := prepareMiddleware(t, cache, nil)
|
|
|
|
stub := &multildap.MultiLDAPmock{
|
|
ID: id,
|
|
}
|
|
|
|
newLDAP = func(servers []*ldap.ServerConfig) multildap.IMultiLDAP {
|
|
return stub
|
|
}
|
|
|
|
gotID, err := auth.Login(logger, false)
|
|
require.EqualError(t, err, "failed to get the user")
|
|
|
|
assert.NotEqual(t, id, gotID)
|
|
assert.False(t, stub.LoginCalled)
|
|
})
|
|
}
|
|
|
|
func TestDecodeHeader(t *testing.T) {
|
|
cache := remotecache.NewFakeStore(t)
|
|
t.Run("should not decode header if not enabled in settings", func(t *testing.T) {
|
|
auth := prepareMiddleware(t, cache, func(req *http.Request, cfg *setting.Cfg) {
|
|
cfg.AuthProxyHeaderName = "X-WEBAUTH-USER"
|
|
cfg.AuthProxyHeadersEncoded = false
|
|
req.Header.Set(cfg.AuthProxyHeaderName, "M=C3=BCnchen")
|
|
})
|
|
|
|
assert.Equal(t, "M=C3=BCnchen", auth.header)
|
|
})
|
|
|
|
t.Run("should decode header if enabled in settings", func(t *testing.T) {
|
|
auth := prepareMiddleware(t, cache, func(req *http.Request, cfg *setting.Cfg) {
|
|
cfg.AuthProxyHeaderName = "X-WEBAUTH-USER"
|
|
cfg.AuthProxyHeadersEncoded = true
|
|
req.Header.Set(cfg.AuthProxyHeaderName, "M=C3=BCnchen")
|
|
})
|
|
|
|
assert.Equal(t, "München", auth.header)
|
|
})
|
|
}
|