mirror of
https://github.com/datarhei/core.git
synced 2025-10-05 07:57:13 +08:00
Fix basic auth, disable localhost, replace template func
This commit is contained in:
@@ -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)
|
||||
|
@@ -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()),
|
||||
|
@@ -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)
|
||||
|
||||
|
@@ -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
|
||||
}
|
||||
|
||||
|
@@ -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)
|
||||
|
@@ -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) {
|
||||
|
Reference in New Issue
Block a user