forked from External/mediamtx
This commit is contained in:
parent
39ae1269ad
commit
9554fc4ba0
4 changed files with 124 additions and 67 deletions
|
|
@ -247,16 +247,14 @@ func TestConfigPathDefaultsPatch(t *testing.T) {
|
||||||
|
|
||||||
httpRequest(t, hc, http.MethodPatch, "http://localhost:9997/v3/config/pathdefaults/patch",
|
httpRequest(t, hc, http.MethodPatch, "http://localhost:9997/v3/config/pathdefaults/patch",
|
||||||
map[string]interface{}{
|
map[string]interface{}{
|
||||||
"readUser": "myuser",
|
"recordFormat": "fmp4",
|
||||||
"readPass": "mypass",
|
|
||||||
}, nil)
|
}, nil)
|
||||||
|
|
||||||
time.Sleep(500 * time.Millisecond)
|
time.Sleep(500 * time.Millisecond)
|
||||||
|
|
||||||
var out map[string]interface{}
|
var out map[string]interface{}
|
||||||
httpRequest(t, hc, http.MethodGet, "http://localhost:9997/v3/config/pathdefaults/get", nil, &out)
|
httpRequest(t, hc, http.MethodGet, "http://localhost:9997/v3/config/pathdefaults/get", nil, &out)
|
||||||
require.Equal(t, "myuser", out["readUser"])
|
require.Equal(t, "fmp4", out["recordFormat"])
|
||||||
require.Equal(t, "mypass", out["readPass"])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestConfigPathsList(t *testing.T) {
|
func TestConfigPathsList(t *testing.T) {
|
||||||
|
|
|
||||||
|
|
@ -94,24 +94,25 @@ func mustParseCIDR(v string) net.IPNet {
|
||||||
return *ne
|
return *ne
|
||||||
}
|
}
|
||||||
|
|
||||||
func credentialIsNotEmpty(c *Credential) bool {
|
func anyPathHasDeprecatedCredentials(pathDefaults Path, paths map[string]*OptionalPath) bool {
|
||||||
return c != nil && *c != ""
|
if pathDefaults.PublishUser != nil ||
|
||||||
}
|
pathDefaults.PublishPass != nil ||
|
||||||
|
pathDefaults.PublishIPs != nil ||
|
||||||
|
pathDefaults.ReadUser != nil ||
|
||||||
|
pathDefaults.ReadPass != nil ||
|
||||||
|
pathDefaults.ReadIPs != nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
func ipNetworkIsNotEmpty(i *IPNetworks) bool {
|
|
||||||
return i != nil && len(*i) != 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func anyPathHasDeprecatedCredentials(paths map[string]*OptionalPath) bool {
|
|
||||||
for _, pa := range paths {
|
for _, pa := range paths {
|
||||||
if pa != nil {
|
if pa != nil {
|
||||||
rva := reflect.ValueOf(pa.Values).Elem()
|
rva := reflect.ValueOf(pa.Values).Elem()
|
||||||
if credentialIsNotEmpty(rva.FieldByName("PublishUser").Interface().(*Credential)) ||
|
if rva.FieldByName("PublishUser").Interface().(*Credential) != nil ||
|
||||||
credentialIsNotEmpty(rva.FieldByName("PublishPass").Interface().(*Credential)) ||
|
rva.FieldByName("PublishPass").Interface().(*Credential) != nil ||
|
||||||
ipNetworkIsNotEmpty(rva.FieldByName("PublishIPs").Interface().(*IPNetworks)) ||
|
rva.FieldByName("PublishIPs").Interface().(*IPNetworks) != nil ||
|
||||||
credentialIsNotEmpty(rva.FieldByName("ReadUser").Interface().(*Credential)) ||
|
rva.FieldByName("ReadUser").Interface().(*Credential) != nil ||
|
||||||
credentialIsNotEmpty(rva.FieldByName("ReadPass").Interface().(*Credential)) ||
|
rva.FieldByName("ReadPass").Interface().(*Credential) != nil ||
|
||||||
ipNetworkIsNotEmpty(rva.FieldByName("ReadIPs").Interface().(*IPNetworks)) {
|
rva.FieldByName("ReadIPs").Interface().(*IPNetworks) != nil {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -119,6 +120,40 @@ func anyPathHasDeprecatedCredentials(paths map[string]*OptionalPath) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var defaultAuthInternalUsers = AuthInternalUsers{
|
||||||
|
{
|
||||||
|
User: "any",
|
||||||
|
Pass: "",
|
||||||
|
Permissions: []AuthInternalUserPermission{
|
||||||
|
{
|
||||||
|
Action: AuthActionPublish,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Action: AuthActionRead,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Action: AuthActionPlayback,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
User: "any",
|
||||||
|
Pass: "",
|
||||||
|
IPs: IPNetworks{mustParseCIDR("127.0.0.1/32"), mustParseCIDR("::1/128")},
|
||||||
|
Permissions: []AuthInternalUserPermission{
|
||||||
|
{
|
||||||
|
Action: AuthActionAPI,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Action: AuthActionMetrics,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Action: AuthActionPprof,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
// Conf is a configuration.
|
// Conf is a configuration.
|
||||||
// WARNING: Avoid using slices directly due to https://github.com/golang/go/issues/21092
|
// WARNING: Avoid using slices directly due to https://github.com/golang/go/issues/21092
|
||||||
type Conf struct {
|
type Conf struct {
|
||||||
|
|
@ -276,39 +311,7 @@ func (conf *Conf) setDefaults() {
|
||||||
conf.UDPMaxPayloadSize = 1472
|
conf.UDPMaxPayloadSize = 1472
|
||||||
|
|
||||||
// Authentication
|
// Authentication
|
||||||
conf.AuthInternalUsers = []AuthInternalUser{
|
conf.AuthInternalUsers = defaultAuthInternalUsers
|
||||||
{
|
|
||||||
User: "any",
|
|
||||||
Pass: "",
|
|
||||||
Permissions: []AuthInternalUserPermission{
|
|
||||||
{
|
|
||||||
Action: AuthActionPublish,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Action: AuthActionRead,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Action: AuthActionPlayback,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
User: "any",
|
|
||||||
Pass: "",
|
|
||||||
IPs: IPNetworks{mustParseCIDR("127.0.0.1/32"), mustParseCIDR("::1/128")},
|
|
||||||
Permissions: []AuthInternalUserPermission{
|
|
||||||
{
|
|
||||||
Action: AuthActionAPI,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Action: AuthActionMetrics,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Action: AuthActionPprof,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
conf.AuthHTTPExclude = []AuthInternalUserPermission{
|
conf.AuthHTTPExclude = []AuthInternalUserPermission{
|
||||||
{
|
{
|
||||||
Action: AuthActionAPI,
|
Action: AuthActionAPI,
|
||||||
|
|
@ -501,7 +504,6 @@ func (conf *Conf) Validate() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Authentication
|
// Authentication
|
||||||
|
|
||||||
if conf.ExternalAuthenticationURL != nil {
|
if conf.ExternalAuthenticationURL != nil {
|
||||||
conf.AuthMethod = AuthMethodHTTP
|
conf.AuthMethod = AuthMethodHTTP
|
||||||
conf.AuthHTTPAddress = *conf.ExternalAuthenticationURL
|
conf.AuthHTTPAddress = *conf.ExternalAuthenticationURL
|
||||||
|
|
@ -517,17 +519,15 @@ func (conf *Conf) Validate() error {
|
||||||
return fmt.Errorf("'authJWTJWKS' must be a HTTP URL")
|
return fmt.Errorf("'authJWTJWKS' must be a HTTP URL")
|
||||||
}
|
}
|
||||||
deprecatedCredentialsMode := false
|
deprecatedCredentialsMode := false
|
||||||
if credentialIsNotEmpty(conf.PathDefaults.PublishUser) ||
|
if anyPathHasDeprecatedCredentials(conf.PathDefaults, conf.OptionalPaths) {
|
||||||
credentialIsNotEmpty(conf.PathDefaults.PublishPass) ||
|
if conf.AuthInternalUsers != nil && !reflect.DeepEqual(conf.AuthInternalUsers, defaultAuthInternalUsers) {
|
||||||
ipNetworkIsNotEmpty(conf.PathDefaults.PublishIPs) ||
|
return fmt.Errorf("authInternalUsers and legacy credentials " +
|
||||||
credentialIsNotEmpty(conf.PathDefaults.ReadUser) ||
|
"(publishUser, publishPass, publishIPs, readUser, readPass, readIPs) cannot be used together")
|
||||||
credentialIsNotEmpty(conf.PathDefaults.ReadPass) ||
|
}
|
||||||
ipNetworkIsNotEmpty(conf.PathDefaults.ReadIPs) ||
|
|
||||||
anyPathHasDeprecatedCredentials(conf.OptionalPaths) {
|
|
||||||
conf.AuthInternalUsers = []AuthInternalUser{
|
conf.AuthInternalUsers = []AuthInternalUser{
|
||||||
{
|
{
|
||||||
User: "any",
|
User: "any",
|
||||||
Pass: "",
|
|
||||||
Permissions: []AuthInternalUserPermission{
|
Permissions: []AuthInternalUserPermission{
|
||||||
{
|
{
|
||||||
Action: AuthActionPlayback,
|
Action: AuthActionPlayback,
|
||||||
|
|
@ -536,7 +536,6 @@ func (conf *Conf) Validate() error {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
User: "any",
|
User: "any",
|
||||||
Pass: "",
|
|
||||||
IPs: IPNetworks{mustParseCIDR("127.0.0.1/32"), mustParseCIDR("::1/128")},
|
IPs: IPNetworks{mustParseCIDR("127.0.0.1/32"), mustParseCIDR("::1/128")},
|
||||||
Permissions: []AuthInternalUserPermission{
|
Permissions: []AuthInternalUserPermission{
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -192,6 +192,66 @@ func TestConfEncryption(t *testing.T) {
|
||||||
require.Equal(t, true, ok)
|
require.Equal(t, true, ok)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestConfDeprecatedAuth(t *testing.T) {
|
||||||
|
tmpf, err := createTempFile([]byte(
|
||||||
|
"paths:\n" +
|
||||||
|
" cam:\n" +
|
||||||
|
" readUser: myuser\n" +
|
||||||
|
" readPass: mypass\n"))
|
||||||
|
require.NoError(t, err)
|
||||||
|
defer os.Remove(tmpf)
|
||||||
|
|
||||||
|
conf, _, err := Load(tmpf, nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
require.Equal(t, AuthInternalUsers{
|
||||||
|
{
|
||||||
|
User: "any",
|
||||||
|
Permissions: []AuthInternalUserPermission{
|
||||||
|
{
|
||||||
|
Action: AuthActionPlayback,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
User: "any",
|
||||||
|
IPs: IPNetworks{mustParseCIDR("127.0.0.1/32"), mustParseCIDR("::1/128")},
|
||||||
|
Permissions: []AuthInternalUserPermission{
|
||||||
|
{
|
||||||
|
Action: AuthActionAPI,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Action: AuthActionMetrics,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Action: AuthActionPprof,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
User: "any",
|
||||||
|
IPs: IPNetworks{mustParseCIDR("0.0.0.0/0")},
|
||||||
|
Permissions: []AuthInternalUserPermission{
|
||||||
|
{
|
||||||
|
Action: AuthActionPublish,
|
||||||
|
Path: "cam",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
User: "myuser",
|
||||||
|
Pass: "mypass",
|
||||||
|
IPs: IPNetworks{mustParseCIDR("0.0.0.0/0")},
|
||||||
|
Permissions: []AuthInternalUserPermission{
|
||||||
|
{
|
||||||
|
Action: AuthActionRead,
|
||||||
|
Path: "cam",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}, conf.AuthInternalUsers)
|
||||||
|
}
|
||||||
|
|
||||||
func TestConfErrors(t *testing.T) {
|
func TestConfErrors(t *testing.T) {
|
||||||
for _, ca := range []struct {
|
for _, ca := range []struct {
|
||||||
name string
|
name string
|
||||||
|
|
|
||||||
|
|
@ -399,17 +399,17 @@ func (pconf *Path) validate(
|
||||||
if deprecatedCredentialsMode {
|
if deprecatedCredentialsMode {
|
||||||
func() {
|
func() {
|
||||||
var user Credential = "any"
|
var user Credential = "any"
|
||||||
if credentialIsNotEmpty(pconf.PublishUser) {
|
if pconf.PublishUser != nil && *pconf.PublishUser != "" {
|
||||||
user = *pconf.PublishUser
|
user = *pconf.PublishUser
|
||||||
}
|
}
|
||||||
|
|
||||||
var pass Credential
|
var pass Credential
|
||||||
if credentialIsNotEmpty(pconf.PublishPass) {
|
if pconf.PublishPass != nil && *pconf.PublishPass != "" {
|
||||||
pass = *pconf.PublishPass
|
pass = *pconf.PublishPass
|
||||||
}
|
}
|
||||||
|
|
||||||
ips := IPNetworks{mustParseCIDR("0.0.0.0/0")}
|
ips := IPNetworks{mustParseCIDR("0.0.0.0/0")}
|
||||||
if ipNetworkIsNotEmpty(pconf.PublishIPs) {
|
if pconf.PublishIPs != nil && len(*pconf.PublishIPs) != 0 {
|
||||||
ips = *pconf.PublishIPs
|
ips = *pconf.PublishIPs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -431,17 +431,17 @@ func (pconf *Path) validate(
|
||||||
|
|
||||||
func() {
|
func() {
|
||||||
var user Credential = "any"
|
var user Credential = "any"
|
||||||
if credentialIsNotEmpty(pconf.ReadUser) {
|
if pconf.ReadUser != nil && *pconf.ReadUser != "" {
|
||||||
user = *pconf.ReadUser
|
user = *pconf.ReadUser
|
||||||
}
|
}
|
||||||
|
|
||||||
var pass Credential
|
var pass Credential
|
||||||
if credentialIsNotEmpty(pconf.ReadPass) {
|
if pconf.ReadPass != nil && *pconf.ReadPass != "" {
|
||||||
pass = *pconf.ReadPass
|
pass = *pconf.ReadPass
|
||||||
}
|
}
|
||||||
|
|
||||||
ips := IPNetworks{mustParseCIDR("0.0.0.0/0")}
|
ips := IPNetworks{mustParseCIDR("0.0.0.0/0")}
|
||||||
if ipNetworkIsNotEmpty(pconf.ReadIPs) {
|
if pconf.ReadIPs != nil && len(*pconf.ReadIPs) != 0 {
|
||||||
ips = *pconf.ReadIPs
|
ips = *pconf.ReadIPs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue