Fix basic auth, disable localhost, replace template func

This commit is contained in:
Ingo Oppermann
2023-02-17 17:27:39 +01:00
parent 2df83c8032
commit 8215c20ae6
6 changed files with 118 additions and 52 deletions

View File

@@ -459,23 +459,23 @@ func (a *api) start() error {
iam.AddPolicy("$anon", "$none", "process:*", "ANY")
iam.AddPolicy("$localhost", "$none", "api:/api/**", "ANY")
iam.AddPolicy("$localhost", "$none", "process:*", "ANY")
}
} else {
if cfg.API.Auth.DisableLocalhost {
iam.AddPolicy("$localhost", "$none", "api:/api/**", "ANY")
iam.AddPolicy("$localhost", "$none", "process:*", "ANY")
}
}
if !cfg.Storage.Memory.Auth.Enable {
iam.AddPolicy("$anon", "$none", "fs:/memfs/**", "ANY")
}
if cfg.RTMP.Enable && len(cfg.RTMP.Token) == 0 {
iam.AddPolicy("$anon", "$none", "rtmp:/**", "PUBLISH|PLAY")
iam.AddPolicy("$anon", "$none", "rtmp:/**", "ANY")
}
if cfg.SRT.Enable && len(cfg.SRT.Token) == 0 {
iam.AddPolicy("$anon", "$none", "srt:**", "PUBLISH|PLAY")
iam.AddPolicy("$anon", "$none", "srt:**", "ANY")
}
a.iam = iam
@@ -669,7 +669,15 @@ func (a *api) start() error {
}
template += "/{name}"
if identity, _ := a.iam.GetIdentity(config.Owner); identity != nil {
var identity iam.IdentityVerifier = nil
if len(config.Owner) == 0 {
identity, _ = a.iam.GetDefaultIdentity()
} else {
identity, _ = a.iam.GetIdentity(config.Owner)
}
if identity != nil {
template += "/" + identity.GetServiceToken()
}
@@ -687,7 +695,15 @@ func (a *api) start() error {
template += ",mode:publish"
}
if identity, _ := a.iam.GetIdentity(config.Owner); identity != nil {
var identity iam.IdentityVerifier = nil
if len(config.Owner) == 0 {
identity, _ = a.iam.GetDefaultIdentity()
} else {
identity, _ = a.iam.GetIdentity(config.Owner)
}
if identity != nil {
template += ",token:" + identity.GetServiceToken()
}
@@ -1109,6 +1125,7 @@ func (a *api) start() error {
Router: router,
ReadOnly: cfg.API.ReadOnly,
IAM: a.iam,
IAMDisableLocalhost: cfg.API.Auth.DisableLocalhost,
}
mainserverhandler, err := http.NewServer(serverConfig)

View File

@@ -15,11 +15,11 @@ import (
// about the API version and build infos.
type AboutHandler struct {
restream restream.Restreamer
auths []string
auths func() []string
}
// NewAbout returns a new About type
func NewAbout(restream restream.Restreamer, auths []string) *AboutHandler {
func NewAbout(restream restream.Restreamer, auths func() []string) *AboutHandler {
return &AboutHandler{
restream: restream,
auths: auths,
@@ -36,11 +36,12 @@ func NewAbout(restream restream.Restreamer, auths []string) *AboutHandler {
// @Router /api [get]
func (p *AboutHandler) About(c echo.Context) error {
user, _ := c.Get("user").(string)
disablelocalhost, _ := c.Get("disablelocalhost").(bool)
if user == "$anon" {
if user == "$anon" || (user == "$localhost" && !disablelocalhost) {
return c.JSON(http.StatusOK, api.MinimalAbout{
App: app.Name,
Auths: p.auths,
Auths: p.auths(),
Version: api.VersionMinimal{
Number: app.Version.MajorString(),
},
@@ -52,7 +53,7 @@ func (p *AboutHandler) About(c echo.Context) error {
about := api.About{
App: app.Name,
Name: p.restream.Name(),
Auths: p.auths,
Auths: p.auths(),
ID: p.restream.ID(),
CreatedAt: createdAt.Format(time.RFC3339),
Uptime: uint64(time.Since(createdAt).Seconds()),

View File

@@ -19,7 +19,7 @@ func getDummyAboutRouter() (*echo.Echo, error) {
return nil, err
}
handler := NewAbout(rs, []string{})
handler := NewAbout(rs, func() []string { return []string{} })
router.Add("GET", "/", handler.About)

View File

@@ -33,6 +33,7 @@ package iam
import (
"encoding/base64"
"errors"
"fmt"
"net/http"
"path/filepath"
@@ -55,6 +56,7 @@ type Config struct {
Skipper middleware.Skipper
Mounts []string
IAM iam.IAM
DisableLocalhost bool
Logger log.Logger
}
@@ -62,6 +64,7 @@ var DefaultConfig = Config{
Skipper: middleware.DefaultSkipper,
Mounts: []string{},
IAM: nil,
DisableLocalhost: false,
Logger: nil,
}
@@ -95,6 +98,9 @@ func NewWithConfig(config Config) echo.MiddlewareFunc {
return func(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
c.Set("disablelocalhost", config.DisableLocalhost)
if config.Skipper(c) {
c.Set("user", "$anon")
return next(c)
@@ -159,6 +165,11 @@ func NewWithConfig(config Config) echo.MiddlewareFunc {
} else {
identity, err = mw.findIdentityFromBasicAuth(c)
if err != nil {
if err == ErrUnauthorized {
c.Response().Header().Set(echo.HeaderWWWAuthenticate, "Basic realm=datarhei-core")
return api.Err(http.StatusUnauthorized, "Unauthorized", "%s", err)
}
return api.Err(http.StatusForbidden, "Forbidden", "%s", err)
}
@@ -187,12 +198,30 @@ func NewWithConfig(config Config) echo.MiddlewareFunc {
}
}
var ErrUnauthorized = errors.New("unauthorized")
func (m *iammiddleware) findIdentityFromBasicAuth(c echo.Context) (iam.IdentityVerifier, error) {
basic := "basic"
auth := c.Request().Header.Get(echo.HeaderAuthorization)
l := len(basic)
if len(auth) == 0 {
method := c.Request().Method
if method == http.MethodGet || method == http.MethodHead || method == http.MethodOptions {
return nil, nil
}
path := c.Request().URL.Path
for _, m := range m.mounts {
if m == "/" {
continue
}
if strings.HasPrefix(path, m+"/") {
return nil, ErrUnauthorized
}
}
return nil, nil
}

View File

@@ -93,6 +93,7 @@ type Config struct {
Router router.Router
ReadOnly bool
IAM iam.IAM
IAMDisableLocalhost bool
}
type CorsConfig struct {
@@ -223,12 +224,13 @@ func NewServer(config Config) (Server, error) {
s.middleware.iam = mwiam.NewWithConfig(mwiam.Config{
IAM: config.IAM,
Mounts: mounts,
DisableLocalhost: config.IAMDisableLocalhost,
Logger: s.logger.WithComponent("IAM"),
})
s.handler.about = api.NewAbout(
config.Restream,
config.IAM.Validators(),
func() []string { return config.IAM.Validators() },
)
s.handler.jwt = api.NewJWT(config.IAM)

View File

@@ -71,6 +71,23 @@ func TestIdentity(t *testing.T) {
require.False(t, identity.IsSuperuser())
identity.user.Superuser = true
require.True(t, identity.IsSuperuser())
dummyfs, err := fs.NewMemFilesystem(fs.MemConfig{})
require.NoError(t, err)
im, err := NewIdentityManager(IdentityConfig{
FS: dummyfs,
Superuser: User{Name: "foobar"},
JWTRealm: "test-realm",
JWTSecret: "abc123",
Logger: nil,
})
require.NoError(t, err)
require.NotNil(t, im)
id, err := im.GetVerifier("unknown")
require.Error(t, err)
require.Nil(t, id)
}
func TestDefaultIdentity(t *testing.T) {