Get rid of $localhost pseudo user

This commit is contained in:
Ingo Oppermann
2023-03-09 21:10:04 +01:00
parent a0ef3ab5ee
commit 6e93c1d5a1
7 changed files with 68 additions and 78 deletions

View File

@@ -444,27 +444,11 @@ func (a *api) start() error {
// Create default policies for anonymous users in order to mimic the behaviour before IAM // Create default policies for anonymous users in order to mimic the behaviour before IAM
iam.RemovePolicy("$anon", "$none", "", nil) iam.RemovePolicy("$anon", "$none", "", nil)
iam.RemovePolicy("$localhost", "$none", "", nil)
iam.AddPolicy("$anon", "$none", "fs:/**", []string{"GET", "HEAD", "OPTIONS"}) iam.AddPolicy("$anon", "$none", "fs:/**", []string{"GET", "HEAD", "OPTIONS"})
iam.AddPolicy("$anon", "$none", "api:/api", []string{"GET", "HEAD", "OPTIONS"}) iam.AddPolicy("$anon", "$none", "api:/api", []string{"GET", "HEAD", "OPTIONS"})
iam.AddPolicy("$anon", "$none", "api:/api/v3/widget/process/**", []string{"GET", "HEAD", "OPTIONS"}) iam.AddPolicy("$anon", "$none", "api:/api/v3/widget/process/**", []string{"GET", "HEAD", "OPTIONS"})
if !cfg.API.Auth.Enable {
iam.AddPolicy("$anon", "$none", "api:/api/**", []string{"ANY"})
iam.AddPolicy("$anon", "$none", "process:*", []string{"ANY"})
iam.AddPolicy("$anon", "$none", "iam:*", []string{"ANY"})
} else {
if cfg.API.Auth.DisableLocalhost {
iam.AddPolicy("$localhost", "$none", "api:/api", []string{"GET", "HEAD", "OPTIONS"})
iam.AddPolicy("$localhost", "$none", "api:/api/v3/widget/process/**", []string{"GET", "HEAD", "OPTIONS"})
iam.AddPolicy("$localhost", "$none", "api:/api/**", []string{"ANY"})
iam.AddPolicy("$localhost", "$none", "process:*", []string{"ANY"})
iam.AddPolicy("$localhost", "$none", "iam:*", []string{"ANY"})
}
}
if !cfg.Storage.Memory.Auth.Enable { if !cfg.Storage.Memory.Auth.Enable {
iam.AddPolicy("$anon", "$none", "fs:/memfs/**", []string{"ANY"}) iam.AddPolicy("$anon", "$none", "fs:/memfs/**", []string{"ANY"})
} }
@@ -671,7 +655,7 @@ func (a *api) start() error {
var identity iam.IdentityVerifier = nil var identity iam.IdentityVerifier = nil
if len(config.Owner) == 0 { if len(config.Owner) == 0 {
identity, _ = a.iam.GetDefaultVerifier() identity = a.iam.GetDefaultVerifier()
} else { } else {
identity, _ = a.iam.GetVerifier(config.Owner) identity, _ = a.iam.GetVerifier(config.Owner)
} }
@@ -697,7 +681,7 @@ func (a *api) start() error {
var identity iam.IdentityVerifier = nil var identity iam.IdentityVerifier = nil
if len(config.Owner) == 0 { if len(config.Owner) == 0 {
identity, _ = a.iam.GetDefaultVerifier() identity = a.iam.GetDefaultVerifier()
} else { } else {
identity, _ = a.iam.GetVerifier(config.Owner) identity, _ = a.iam.GetVerifier(config.Owner)
} }
@@ -1117,14 +1101,29 @@ func (a *api) start() error {
Cors: http.CorsConfig{ Cors: http.CorsConfig{
Origins: cfg.Storage.CORS.Origins, Origins: cfg.Storage.CORS.Origins,
}, },
RTMP: a.rtmpserver, RTMP: a.rtmpserver,
SRT: a.srtserver, SRT: a.srtserver,
Config: a.config.store, Config: a.config.store,
Sessions: a.sessions, Sessions: a.sessions,
Router: router, Router: router,
ReadOnly: cfg.API.ReadOnly, ReadOnly: cfg.API.ReadOnly,
IAM: a.iam, IAM: a.iam,
IAMDisableLocalhost: cfg.API.Auth.Enable && cfg.API.Auth.DisableLocalhost, IAMSkipper: func(ip string) bool {
if !cfg.API.Auth.Enable {
return true
} else {
isLocalhost := false
if ip == "127.0.0.1" || ip == "::1" {
isLocalhost = true
}
if isLocalhost && cfg.API.Auth.DisableLocalhost {
return true
}
}
return false
},
} }
mainserverhandler, err := http.NewServer(serverConfig) mainserverhandler, err := http.NewServer(serverConfig)

View File

@@ -17,9 +17,8 @@
// only allow JWT as authentication method. // only allow JWT as authentication method.
// //
// If the identity can't be detected, the identity of "$anon" is given, representing // If the identity can't be detected, the identity of "$anon" is given, representing
// an anonmyous user. If the request originates from localhost and DisableLocalhost // an anonmyous user. If the Skipper function returns true for the request and the
// is configured, the identity will be $localhost, representing an anonymous user from // API is accessed, the username will be the one of the IAM superuser.
// localhost.
// //
// The domain is provided as query parameter "group" for all API requests or the // The domain is provided as query parameter "group" for all API requests or the
// first path element after a mountpoint for filesystem requests. // first path element after a mountpoint for filesystem requests.
@@ -57,7 +56,6 @@ type Config struct {
Skipper middleware.Skipper Skipper middleware.Skipper
Mounts []string Mounts []string
IAM iam.IAM IAM iam.IAM
DisableLocalhost bool
WaitAfterFailedLogin bool WaitAfterFailedLogin bool
Logger log.Logger Logger log.Logger
} }
@@ -66,7 +64,6 @@ var DefaultConfig = Config{
Skipper: middleware.DefaultSkipper, Skipper: middleware.DefaultSkipper,
Mounts: []string{}, Mounts: []string{},
IAM: nil, IAM: nil,
DisableLocalhost: false,
WaitAfterFailedLogin: false, WaitAfterFailedLogin: false,
Logger: nil, Logger: nil,
} }
@@ -111,15 +108,15 @@ func NewWithConfig(config Config) echo.MiddlewareFunc {
return func(next echo.HandlerFunc) echo.HandlerFunc { return func(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error { return func(c echo.Context) error {
if config.Skipper(c) {
c.Set("user", "$anon")
return next(c)
}
if config.IAM == nil { if config.IAM == nil {
return api.Err(http.StatusForbidden, "Forbidden", "IAM is not provided") return api.Err(http.StatusForbidden, "Forbidden", "IAM is not provided")
} }
isAPISuperuser := false
if config.Skipper(c) {
isAPISuperuser = true
}
var identity iam.IdentityVerifier = nil var identity iam.IdentityVerifier = nil
var err error var err error
@@ -173,11 +170,8 @@ func NewWithConfig(config Config) echo.MiddlewareFunc {
} }
} }
if config.DisableLocalhost { if isAPISuperuser {
ip := c.RealIP() username = config.IAM.GetDefaultVerifier().Name()
if ip == "127.0.0.1" || ip == "::1" {
username = "$localhost"
}
} }
domain = c.QueryParam("group") domain = c.QueryParam("group")

View File

@@ -75,25 +75,25 @@ import (
var ListenAndServe = http.ListenAndServe var ListenAndServe = http.ListenAndServe
type Config struct { type Config struct {
Logger log.Logger Logger log.Logger
LogBuffer log.BufferWriter LogBuffer log.BufferWriter
Restream restream.Restreamer Restream restream.Restreamer
Metrics monitor.HistoryReader Metrics monitor.HistoryReader
Prometheus prometheus.Reader Prometheus prometheus.Reader
MimeTypesFile string MimeTypesFile string
Filesystems []fs.FS Filesystems []fs.FS
IPLimiter net.IPLimiter IPLimiter net.IPLimiter
Profiling bool Profiling bool
Cors CorsConfig Cors CorsConfig
RTMP rtmp.Server RTMP rtmp.Server
SRT srt.Server SRT srt.Server
Config cfgstore.Store Config cfgstore.Store
Cache cache.Cacher Cache cache.Cacher
Sessions session.RegistryReader Sessions session.RegistryReader
Router router.Router Router router.Router
ReadOnly bool ReadOnly bool
IAM iam.IAM IAM iam.IAM
IAMDisableLocalhost bool IAMSkipper func(ip string) bool
} }
type CorsConfig struct { type CorsConfig struct {
@@ -132,8 +132,6 @@ type server struct {
middleware struct { middleware struct {
iplimit echo.MiddlewareFunc iplimit echo.MiddlewareFunc
log echo.MiddlewareFunc log echo.MiddlewareFunc
accessJWT echo.MiddlewareFunc
refreshJWT echo.MiddlewareFunc
cors echo.MiddlewareFunc cors echo.MiddlewareFunc
cache echo.MiddlewareFunc cache echo.MiddlewareFunc
session echo.MiddlewareFunc session echo.MiddlewareFunc
@@ -223,9 +221,11 @@ func NewServer(config Config) (Server, error) {
} }
s.middleware.iam = mwiam.NewWithConfig(mwiam.Config{ s.middleware.iam = mwiam.NewWithConfig(mwiam.Config{
Skipper: func(c echo.Context) bool {
return config.IAMSkipper(c.RealIP())
},
IAM: config.IAM, IAM: config.IAM,
Mounts: mounts, Mounts: mounts,
DisableLocalhost: config.IAMDisableLocalhost,
WaitAfterFailedLogin: true, WaitAfterFailedLogin: true,
Logger: s.logger.WithComponent("IAM"), Logger: s.logger.WithComponent("IAM"),
}) })

View File

@@ -28,7 +28,7 @@ type IAM interface {
GetVerifier(name string) (IdentityVerifier, error) GetVerifier(name string) (IdentityVerifier, error)
GetVerfierFromAuth0(name string) (IdentityVerifier, error) GetVerfierFromAuth0(name string) (IdentityVerifier, error)
GetDefaultVerifier() (IdentityVerifier, error) GetDefaultVerifier() IdentityVerifier
CreateJWT(name string) (string, string, error) CreateJWT(name string) (string, string, error)
@@ -107,10 +107,6 @@ func (i *iam) Enforce(name, domain, resource, action string) bool {
} }
} }
//if name == "$localhost" {
// superuser = true
//}
l := i.logger.Debug().WithFields(log.Fields{ l := i.logger.Debug().WithFields(log.Fields{
"subject": name, "subject": name,
"domain": domain, "domain": domain,
@@ -128,6 +124,10 @@ func (i *iam) Enforce(name, domain, resource, action string) bool {
if !ok { if !ok {
l.Log("no match") l.Log("no match")
} else { } else {
if name == "$superuser" {
rule = ""
}
l.WithField("rule", rule).Log("match") l.WithField("rule", rule).Log("match")
} }
@@ -166,8 +166,10 @@ func (i *iam) GetVerfierFromAuth0(name string) (IdentityVerifier, error) {
return i.im.GetVerifierFromAuth0(name) return i.im.GetVerifierFromAuth0(name)
} }
func (i *iam) GetDefaultVerifier() (IdentityVerifier, error) { func (i *iam) GetDefaultVerifier() IdentityVerifier {
return i.im.GetDefaultVerifier() v, _ := i.im.GetDefaultVerifier()
return v
} }
func (i *iam) CreateJWT(name string) (string, string, error) { func (i *iam) CreateJWT(name string) (string, string, error) {

View File

@@ -424,12 +424,7 @@ func (r *restream) enforce(name, group, processid, action string) bool {
if len(name) == 0 { if len(name) == 0 {
// This is for backwards compatibility. Existing processes don't have an owner. // This is for backwards compatibility. Existing processes don't have an owner.
// All processes that will be added later will have an owner ($anon, ...). // All processes that will be added later will have an owner ($anon, ...).
identity, err := r.iam.GetDefaultVerifier() name = r.iam.GetDefaultVerifier().Name()
if err != nil {
name = "$anon"
} else {
name = identity.Name()
}
} }
if len(group) == 0 { if len(group) == 0 {

View File

@@ -428,7 +428,7 @@ func (s *server) findIdentityFromStreamKey(key string) (string, error) {
elements := strings.Split(key, ":") elements := strings.Split(key, ":")
if len(elements) == 1 { if len(elements) == 1 {
identity, err = s.iam.GetDefaultVerifier() identity = s.iam.GetDefaultVerifier()
token = elements[0] token = elements[0]
} else { } else {
identity, err = s.iam.GetVerifier(elements[0]) identity, err = s.iam.GetVerifier(elements[0])

View File

@@ -387,7 +387,7 @@ func (s *server) findIdentityFromToken(key string) (string, error) {
elements := strings.Split(key, ":") elements := strings.Split(key, ":")
if len(elements) == 1 { if len(elements) == 1 {
identity, err = s.iam.GetDefaultVerifier() identity = s.iam.GetDefaultVerifier()
token = elements[0] token = elements[0]
} else { } else {
identity, err = s.iam.GetVerifier(elements[0]) identity, err = s.iam.GetVerifier(elements[0])