From 575d3585fedd1ddffd0cba1769a10361b49900b3 Mon Sep 17 00:00:00 2001 From: Alessandro Ros Date: Sat, 4 May 2024 10:12:43 +0200 Subject: [PATCH] fix unexpected behavior of authInternalUsers or authHTTPExclude (#3316) when some subfields of authInternalUsers or authHTTPExclude were not set explicitly in the configuration file, default values were used in their place. This is caused by a strange behavior of Go (https://github.com/golang/go/issues/21092) --- internal/conf/auth_internal_users.go | 26 +++++++++++++++ internal/conf/conf.go | 49 ++++++++++++++-------------- internal/conf/conf_test.go | 28 ++++++++++++++++ internal/conf/path.go | 1 + internal/conf/webrtc_ice_server.go | 13 ++++++++ 5 files changed, 93 insertions(+), 24 deletions(-) diff --git a/internal/conf/auth_internal_users.go b/internal/conf/auth_internal_users.go index 76cdc959ecd..4370d6cb4ce 100644 --- a/internal/conf/auth_internal_users.go +++ b/internal/conf/auth_internal_users.go @@ -1,5 +1,9 @@ package conf +import ( + "encoding/json" +) + // AuthInternalUserPermission is a permission of a user. type AuthInternalUserPermission struct { Action AuthAction `json:"action"` @@ -13,3 +17,25 @@ type AuthInternalUser struct { IPs IPNetworks `json:"ips"` Permissions []AuthInternalUserPermission `json:"permissions"` } + +// AuthInternalUsers is a list of AuthInternalUser +type AuthInternalUsers []AuthInternalUser + +// UnmarshalJSON implements json.Unmarshaler. +func (s *AuthInternalUsers) UnmarshalJSON(b []byte) error { + // remove default value before loading new value + // https://github.com/golang/go/issues/21092 + *s = nil + return json.Unmarshal(b, (*[]AuthInternalUser)(s)) +} + +// AuthInternalUserPermissions is a list of AuthInternalUserPermission +type AuthInternalUserPermissions []AuthInternalUserPermission + +// UnmarshalJSON implements json.Unmarshaler. +func (s *AuthInternalUserPermissions) UnmarshalJSON(b []byte) error { + // remove default value before loading new value + // https://github.com/golang/go/issues/21092 + *s = nil + return json.Unmarshal(b, (*[]AuthInternalUserPermission)(s)) +} diff --git a/internal/conf/conf.go b/internal/conf/conf.go index 36a709e6ab4..8ca17bf7041 100644 --- a/internal/conf/conf.go +++ b/internal/conf/conf.go @@ -120,6 +120,7 @@ func anyPathHasDeprecatedCredentials(paths map[string]*OptionalPath) bool { } // Conf is a configuration. +// WARNING: Avoid using slices directly due to https://github.com/golang/go/issues/21092 type Conf struct { // General LogLevel LogLevel `json:"logLevel"` @@ -135,12 +136,12 @@ type Conf struct { RunOnDisconnect string `json:"runOnDisconnect"` // Authentication - AuthMethod AuthMethod `json:"authMethod"` - AuthInternalUsers []AuthInternalUser `json:"authInternalUsers"` - AuthHTTPAddress string `json:"authHTTPAddress"` - ExternalAuthenticationURL *string `json:"externalAuthenticationURL,omitempty"` // deprecated - AuthHTTPExclude []AuthInternalUserPermission `json:"authHTTPExclude"` - AuthJWTJWKS string `json:"authJWTJWKS"` + AuthMethod AuthMethod `json:"authMethod"` + AuthInternalUsers AuthInternalUsers `json:"authInternalUsers"` + AuthHTTPAddress string `json:"authHTTPAddress"` + ExternalAuthenticationURL *string `json:"externalAuthenticationURL,omitempty"` // deprecated + AuthHTTPExclude AuthInternalUserPermissions `json:"authHTTPExclude"` + AuthJWTJWKS string `json:"authJWTJWKS"` // Control API API bool `json:"api"` @@ -222,24 +223,24 @@ type Conf struct { HLSDirectory string `json:"hlsDirectory"` // WebRTC server - WebRTC bool `json:"webrtc"` - WebRTCDisable *bool `json:"webrtcDisable,omitempty"` // deprecated - WebRTCAddress string `json:"webrtcAddress"` - WebRTCEncryption bool `json:"webrtcEncryption"` - WebRTCServerKey string `json:"webrtcServerKey"` - WebRTCServerCert string `json:"webrtcServerCert"` - WebRTCAllowOrigin string `json:"webrtcAllowOrigin"` - WebRTCTrustedProxies IPNetworks `json:"webrtcTrustedProxies"` - WebRTCLocalUDPAddress string `json:"webrtcLocalUDPAddress"` - WebRTCLocalTCPAddress string `json:"webrtcLocalTCPAddress"` - WebRTCIPsFromInterfaces bool `json:"webrtcIPsFromInterfaces"` - WebRTCIPsFromInterfacesList []string `json:"webrtcIPsFromInterfacesList"` - WebRTCAdditionalHosts []string `json:"webrtcAdditionalHosts"` - WebRTCICEServers2 []WebRTCICEServer `json:"webrtcICEServers2"` - WebRTCICEUDPMuxAddress *string `json:"webrtcICEUDPMuxAddress,omitempty"` // deprecated - WebRTCICETCPMuxAddress *string `json:"webrtcICETCPMuxAddress,omitempty"` // deprecated - WebRTCICEHostNAT1To1IPs *[]string `json:"webrtcICEHostNAT1To1IPs,omitempty"` // deprecated - WebRTCICEServers *[]string `json:"webrtcICEServers,omitempty"` // deprecated + WebRTC bool `json:"webrtc"` + WebRTCDisable *bool `json:"webrtcDisable,omitempty"` // deprecated + WebRTCAddress string `json:"webrtcAddress"` + WebRTCEncryption bool `json:"webrtcEncryption"` + WebRTCServerKey string `json:"webrtcServerKey"` + WebRTCServerCert string `json:"webrtcServerCert"` + WebRTCAllowOrigin string `json:"webrtcAllowOrigin"` + WebRTCTrustedProxies IPNetworks `json:"webrtcTrustedProxies"` + WebRTCLocalUDPAddress string `json:"webrtcLocalUDPAddress"` + WebRTCLocalTCPAddress string `json:"webrtcLocalTCPAddress"` + WebRTCIPsFromInterfaces bool `json:"webrtcIPsFromInterfaces"` + WebRTCIPsFromInterfacesList []string `json:"webrtcIPsFromInterfacesList"` + WebRTCAdditionalHosts []string `json:"webrtcAdditionalHosts"` + WebRTCICEServers2 WebRTCICEServers `json:"webrtcICEServers2"` + WebRTCICEUDPMuxAddress *string `json:"webrtcICEUDPMuxAddress,omitempty"` // deprecated + WebRTCICETCPMuxAddress *string `json:"webrtcICETCPMuxAddress,omitempty"` // deprecated + WebRTCICEHostNAT1To1IPs *[]string `json:"webrtcICEHostNAT1To1IPs,omitempty"` // deprecated + WebRTCICEServers *[]string `json:"webrtcICEServers,omitempty"` // deprecated // SRT server SRT bool `json:"srt"` diff --git a/internal/conf/conf_test.go b/internal/conf/conf_test.go index 669415b5ad6..81289aa72d5 100644 --- a/internal/conf/conf_test.go +++ b/internal/conf/conf_test.go @@ -324,3 +324,31 @@ func TestSampleConfFile(t *testing.T) { require.Equal(t, conf1.Paths, conf2.Paths) }() } + +// needed due to https://github.com/golang/go/issues/21092 +func TestConfOverrideDefaultSlices(t *testing.T) { + tmpf, err := createTempFile([]byte( + "authInternalUsers:\n" + + " - user: user1\n" + + " - user: user2\n" + + "authHTTPExclude:\n" + + " - path: ''\n")) + require.NoError(t, err) + defer os.Remove(tmpf) + + conf, _, err := Load(tmpf, nil) + require.NoError(t, err) + + require.Equal(t, AuthInternalUsers{ + { + User: "user1", + }, + { + User: "user2", + }, + }, conf.AuthInternalUsers) + + require.Equal(t, AuthInternalUserPermissions{ + {}, + }, conf.AuthHTTPExclude) +} diff --git a/internal/conf/path.go b/internal/conf/path.go index 5722a21fe72..93a7eefd677 100644 --- a/internal/conf/path.go +++ b/internal/conf/path.go @@ -81,6 +81,7 @@ func FindPathConf(pathConfs map[string]*Path, name string) (string, *Path, []str } // Path is a path configuration. +// WARNING: Avoid using slices directly due to https://github.com/golang/go/issues/21092 type Path struct { Regexp *regexp.Regexp `json:"-"` // filled by Check() Name string `json:"name"` // filled by Check() diff --git a/internal/conf/webrtc_ice_server.go b/internal/conf/webrtc_ice_server.go index a1258f6e5fc..c8eb3187fb4 100644 --- a/internal/conf/webrtc_ice_server.go +++ b/internal/conf/webrtc_ice_server.go @@ -1,5 +1,7 @@ package conf +import "encoding/json" + // WebRTCICEServer is a WebRTC ICE Server. type WebRTCICEServer struct { URL string `json:"url"` @@ -7,3 +9,14 @@ type WebRTCICEServer struct { Password string `json:"password"` ClientOnly bool `json:"clientOnly"` } + +// WebRTCICEServers is a list of WebRTCICEServer +type WebRTCICEServers []WebRTCICEServer + +// UnmarshalJSON implements json.Unmarshaler. +func (s *WebRTCICEServers) UnmarshalJSON(b []byte) error { + // remove default value before loading new value + // https://github.com/golang/go/issues/21092 + *s = nil + return json.Unmarshal(b, (*[]WebRTCICEServer)(s)) +}