From 78666aa39c3cf436910054ef873ec1b9f0f51c08 Mon Sep 17 00:00:00 2001 From: adjivas Date: Mon, 26 May 2025 19:42:09 +0200 Subject: [PATCH 1/3] fix: add RegisterIP and BindingIP fields --- internal/context/context.go | 104 ++++++++++++++++++--------- internal/sbi/api_sanity_test.go | 2 +- internal/sbi/consumer/nrf_service.go | 6 +- internal/sbi/server.go | 26 ++++--- internal/util/init_context.go | 55 ++++++++------ pkg/factory/config.go | 68 +++++++++++++++--- 6 files changed, 181 insertions(+), 80 deletions(-) diff --git a/internal/context/context.go b/internal/context/context.go index 0c8d615..376239d 100644 --- a/internal/context/context.go +++ b/internal/context/context.go @@ -4,6 +4,8 @@ import ( "context" "fmt" "math/rand" + "net" + "net/netip" "os" "strconv" "strings" @@ -41,7 +43,7 @@ func Init() { serviceName := []models.ServiceName{ models.ServiceName_NUDR_DR, } - udrContext.NrfUri = fmt.Sprintf("%s://%s:%d", models.UriScheme_HTTPS, udrContext.RegisterIPv4, 29510) + udrContext.NrfUri = fmt.Sprintf("%s", udrContext.GetIPUriWithPort(29510)) initUdrContext() config := factory.UdrConfig @@ -51,10 +53,10 @@ func Init() { type UDRContext struct { Name string UriScheme models.UriScheme - BindingIPv4 string + BindingIP netip.Addr + RegisterIP netip.Addr // IP register to NRF SBIPort int NfService map[models.ServiceName]models.NrfNfManagementNfService - RegisterIPv4 string // IP register to NRF HttpIPv6Address string NfId string NrfUri string @@ -128,28 +130,24 @@ func initUdrContext() { logger.UtilLog.Infof("udrconfig Info: Version[%s] Description[%s]", config.Info.Version, config.Info.Description) configuration := config.Configuration udrContext.NfId = uuid.New().String() - udrContext.RegisterIPv4 = factory.UDR_DEFAULT_IPV4 // default localhost - udrContext.SBIPort = factory.UDR_DEFAULT_PORT_INT // default port - if sbi := configuration.Sbi; sbi != nil { - udrContext.UriScheme = models.UriScheme(sbi.Scheme) - if sbi.RegisterIPv4 != "" { - udrContext.RegisterIPv4 = sbi.RegisterIPv4 - } - if sbi.Port != 0 { - udrContext.SBIPort = sbi.Port - } - udrContext.BindingIPv4 = os.Getenv(sbi.BindingIPv4) - if udrContext.BindingIPv4 != "" { - logger.UtilLog.Info("Parsing ServerIPv4 address from ENV Variable.") - } else { - udrContext.BindingIPv4 = sbi.BindingIPv4 - if udrContext.BindingIPv4 == "" { - logger.UtilLog.Warn("Error parsing ServerIPv4 address as string. Using the 0.0.0.0 address as default.") - udrContext.BindingIPv4 = "0.0.0.0" - } - } - } + sbi := configuration.Sbi + + udrContext.SBIPort = sbi.Port + + udrContext.UriScheme = models.UriScheme(sbi.Scheme) + + if bindingIP := os.Getenv(sbi.BindingIP); bindingIP != "" { + logger.UtilLog.Info("Parsing BindingIP address from ENV Variable.") + sbi.BindingIP = bindingIP + } + if registerIP := os.Getenv(sbi.RegisterIP); registerIP != "" { + logger.UtilLog.Info("Parsing RegisterIP address from ENV Variable.") + sbi.RegisterIP = registerIP + } + udrContext.BindingIP = resolveIP(sbi.BindingIP) + udrContext.RegisterIP = resolveIP(sbi.RegisterIP) + if configuration.NrfUri != "" { udrContext.NrfUri = configuration.NrfUri } else { @@ -159,6 +157,46 @@ func initUdrContext() { udrContext.NrfCertPem = configuration.NrfCertPem } +func resolveIP(ip string) netip.Addr { + resolvedIPs, err := net.DefaultResolver.LookupNetIP(context.Background(), "ip", ip) + if err != nil { + logger.InitLog.Errorf("Lookup failed with %s: %+v", ip, err) + } + resolvedIP := resolvedIPs[0].Unmap() + if resolvedIP := resolvedIP.String(); resolvedIP != ip { + logger.UtilLog.Infof("Lookup revolved %s into %s", ip, resolvedIP) + } + return resolvedIP +} + +func (c *UDRContext) GetIPUri() string { + addr := c.RegisterIP + port := c.SBIPort + + return fmt.Sprintf("%s://%s", c.UriScheme, netip.AddrPortFrom(addr, uint16(port)).String()) +} + +func (c *UDRContext) GetIpEndPoint() []models.IpEndPoint { + if c.RegisterIP.Is6() { + return []models.IpEndPoint{ + { + Ipv6Address: c.RegisterIP.String(), + Transport: models.NrfNfManagementTransportProtocol_TCP, + Port: int32(c.SBIPort), + }, + } + } else if c.RegisterIP.Is4() { + return []models.IpEndPoint{ + { + Ipv4Address: c.RegisterIP.String(), + Transport: models.NrfNfManagementTransportProtocol_TCP, + Port: int32(c.SBIPort), + }, + } + } + return nil +} + func initNfService(serviceName []models.ServiceName, version string) ( nfService map[models.ServiceName]models.NrfNfManagementNfService, ) { @@ -176,22 +214,18 @@ func initNfService(serviceName []models.ServiceName, version string) ( }, Scheme: udrContext.UriScheme, NfServiceStatus: models.NfServiceStatus_REGISTERED, - ApiPrefix: GetIPv4Uri(), - IpEndPoints: []models.IpEndPoint{ - { - Ipv4Address: udrContext.RegisterIPv4, - Transport: models.NrfNfManagementTransportProtocol_TCP, - Port: int32(udrContext.SBIPort), - }, - }, + ApiPrefix: udrContext.GetIPUri(), + IpEndPoints: udrContext.GetIpEndPoint(), } } return } -func GetIPv4Uri() string { - return fmt.Sprintf("%s://%s:%d", udrContext.UriScheme, udrContext.RegisterIPv4, udrContext.SBIPort) +func (context *UDRContext) GetIPUriWithPort(port int) string { + addr := context.RegisterIP + + return fmt.Sprintf("%s://%s", context.UriScheme, netip.AddrPortFrom(addr, uint16(port)).String()) } func (context *UDRContext) GetIPv4GroupUri(udrServiceType UDRServiceType) string { @@ -204,7 +238,7 @@ func (context *UDRContext) GetIPv4GroupUri(udrServiceType UDRServiceType) string serviceUri = "" } - return fmt.Sprintf("%s://%s:%d%s", context.UriScheme, context.RegisterIPv4, context.SBIPort, serviceUri) + return fmt.Sprintf("%s%s", context.GetIPUri(), serviceUri) } // Create new UDR context diff --git a/internal/sbi/api_sanity_test.go b/internal/sbi/api_sanity_test.go index 040bf1e..7cc0c83 100644 --- a/internal/sbi/api_sanity_test.go +++ b/internal/sbi/api_sanity_test.go @@ -228,7 +228,7 @@ func TestUDR_GetSubs2Notify_CreateThenGet(t *testing.T) { require.Equal(t, http.StatusCreated, rsp.Code) require.Equal(t, string(bjson), rsp.Body.String()) // require.True(t, strings.Contains(location, baseUri+"/")) - // require.True(t, strings.HasPrefix(location, udr_context.GetSelf().GetIPv4Uri()+baseUri+"/")) + // require.True(t, strings.HasPrefix(location, udr_context.GetSelf().GetIPUri()+baseUri+"/")) }) // Get success diff --git a/internal/sbi/consumer/nrf_service.go b/internal/sbi/consumer/nrf_service.go index 42dc549..4b887cb 100644 --- a/internal/sbi/consumer/nrf_service.go +++ b/internal/sbi/consumer/nrf_service.go @@ -51,7 +51,6 @@ func (ns *NrfService) buildNFProfile(context *udr_context.UDRContext) (models.Nr NfInstanceId: context.NfId, NfType: models.NrfNfManagementNfType_UDR, NfStatus: models.NrfNfManagementNfStatus_REGISTERED, - Ipv4Addresses: []string{context.RegisterIPv4}, UdrInfo: &models.UdrInfo{ SupportedDataSets: []models.DataSetId{ // models.DataSetId_APPLICATION, @@ -61,6 +60,11 @@ func (ns *NrfService) buildNFProfile(context *udr_context.UDRContext) (models.Nr }, }, } + if context.RegisterIP.Is6() { + profile.Ipv6Addresses = append(profile.Ipv6Addresses, context.RegisterIP.String()) + } else if context.RegisterIP.Is4() { + profile.Ipv4Addresses = append(profile.Ipv4Addresses, context.RegisterIP.String()) + } var services []models.NrfNfManagementNfService for _, nfService := range context.NfService { diff --git a/internal/sbi/server.go b/internal/sbi/server.go index 6c19911..a415ceb 100644 --- a/internal/sbi/server.go +++ b/internal/sbi/server.go @@ -3,11 +3,14 @@ package sbi import ( "context" "fmt" + "log" "net/http" + "net/netip" "sync" "time" "github.com/gin-gonic/gin" + "github.com/sirupsen/logrus" "github.com/free5gc/openapi/models" "github.com/free5gc/udr/internal/logger" @@ -38,14 +41,22 @@ func NewServer(udr UDR, tlsKeyLogPath string) *Server { UDR: udr, } + s.router = newRouter(s) - server, err := bindRouter(udr, s.router, tlsKeyLogPath) - s.httpServer = server + + addr := s.Context().RegisterIP + port := uint16(s.Context().SBIPort) - if err != nil { - logger.SBILog.Errorf("bind Router Error: %+v", err) + bind := netip.AddrPortFrom(addr, port).String() + bindAddr := fmt.Sprintf("%s", bind) + + logger.SBILog.Infof("Binding addr: [%s]", bindAddr) + var err error + if s.httpServer, err = httpwrapper.NewHttp2Server(bindAddr, tlsKeyLogPath, s.router); err != nil { + logger.InitLog.Errorf("Initialize HTTP server failed: %v", err) panic("Server initialization failed") } + s.httpServer.ErrorLog = log.New(logger.SBILog.WriterLevel(logrus.ErrorLevel), "HTTP2: ", 0) return s } @@ -85,13 +96,6 @@ func (s *Server) shutdownHttpServer() { } } -func bindRouter(udr app.App, router *gin.Engine, tlsKeyLogPath string) (*http.Server, error) { - sbiConfig := udr.Config().Configuration.Sbi - bindAddr := fmt.Sprintf("%s:%d", sbiConfig.BindingIPv4, sbiConfig.Port) - - return httpwrapper.NewHttp2Server(bindAddr, tlsKeyLogPath, router) -} - func newRouter(s *Server) *gin.Engine { router := logger_util.NewGinWithLogrus(logger.GinLog) router.Use(metrics.InboundMetrics()) diff --git a/internal/util/init_context.go b/internal/util/init_context.go index f1f6a3d..c61118b 100644 --- a/internal/util/init_context.go +++ b/internal/util/init_context.go @@ -1,7 +1,10 @@ package util import ( + "context" "fmt" + "net" + "net/netip" "os" "github.com/google/uuid" @@ -17,28 +20,24 @@ func InitUdrContext(context *udr_context.UDRContext) { logger.UtilLog.Infof("udrconfig Info: Version[%s] Description[%s]", config.Info.Version, config.Info.Description) configuration := config.Configuration context.NfId = uuid.New().String() - context.RegisterIPv4 = factory.UDR_DEFAULT_IPV4 // default localhost - context.SBIPort = factory.UDR_DEFAULT_PORT_INT // default port - if sbi := configuration.Sbi; sbi != nil { - context.UriScheme = models.UriScheme(sbi.Scheme) - if sbi.RegisterIPv4 != "" { - context.RegisterIPv4 = sbi.RegisterIPv4 - } - if sbi.Port != 0 { - context.SBIPort = sbi.Port - } - - context.BindingIPv4 = os.Getenv(sbi.BindingIPv4) - if context.BindingIPv4 != "" { - logger.UtilLog.Info("Parsing ServerIPv4 address from ENV Variable.") - } else { - context.BindingIPv4 = sbi.BindingIPv4 - if context.BindingIPv4 == "" { - logger.UtilLog.Warn("Error parsing ServerIPv4 address as string. Using the 0.0.0.0 address as default.") - context.BindingIPv4 = "0.0.0.0" - } - } - } + + sbi := configuration.Sbi + + context.SBIPort = sbi.Port + + context.UriScheme = models.UriScheme(sbi.Scheme) + + if bindingIP := os.Getenv(sbi.BindingIP); bindingIP != "" { + logger.UtilLog.Info("Parsing BindingIP address from ENV Variable.") + sbi.BindingIP = bindingIP + } + if registerIP := os.Getenv(sbi.RegisterIP); registerIP != "" { + logger.UtilLog.Info("Parsing RegisterIP address from ENV Variable.") + sbi.RegisterIP = registerIP + } + context.BindingIP = resolveIP(sbi.BindingIP) + context.RegisterIP = resolveIP(sbi.RegisterIP) + if configuration.NrfUri != "" { context.NrfUri = configuration.NrfUri } else { @@ -46,3 +45,15 @@ func InitUdrContext(context *udr_context.UDRContext) { context.NrfUri = fmt.Sprintf("%s://%s:%d", context.UriScheme, "127.0.0.1", 29510) } } + +func resolveIP(ip string) netip.Addr { + resolvedIPs, err := net.DefaultResolver.LookupNetIP(context.Background(), "ip", ip) + if err != nil { + logger.InitLog.Errorf("Lookup failed with %s: %+v", ip, err) + } + resolvedIP := resolvedIPs[0].Unmap() + if resolvedIP := resolvedIP.String(); resolvedIP != ip { + logger.UtilLog.Infof("Lookup revolved %s into %s", ip, resolvedIP) + } + return resolvedIP +} diff --git a/pkg/factory/config.go b/pkg/factory/config.go index 747f869..db20c1f 100644 --- a/pkg/factory/config.go +++ b/pkg/factory/config.go @@ -20,7 +20,7 @@ const ( UdrDefaultCertPemPath = "./cert/udr.pem" UdrDefaultPrivateKeyPath = "./cert/udr.key" UdrDefaultConfigPath = "./config/udrcfg.yaml" - UdrSbiDefaultIPv4 = "127.0.0.9" + UdrSbiDefaultIP = "127.0.0.9" UdrSbiDefaultPort = 8000 UdrSbiDefaultScheme = "https" UdrMetricsDefaultEnabled = false @@ -59,7 +59,7 @@ type Info struct { } const ( - UDR_DEFAULT_IPV4 = "127.0.0.4" + UDR_DEFAULT_IP = "127.0.0.4" UDR_DEFAULT_PORT = "8000" UDR_DEFAULT_PORT_INT = 8000 ) @@ -84,15 +84,21 @@ func (c *Configuration) validate() (bool, error) { return str == "https" || str == "http" }) + if c.Sbi != nil { + if _, err := c.Sbi.validate(); err != nil { + return false, err + } + } + if c.Metrics != nil { if _, err := c.Metrics.validate(); err != nil { return false, err } - if c.Sbi != nil && c.Metrics.Port == c.Sbi.Port && c.Sbi.BindingIPv4 == c.Metrics.BindingIPv4 { + if c.Metrics.Port == c.Sbi.Port && c.Sbi.BindingIP == c.Metrics.BindingIP { var errs govalidator.Errors - err := fmt.Errorf("sbi and metrics bindings IPv4: %s and port: %d cannot be the same, "+ - "please provide at least another port for the metrics", c.Sbi.BindingIPv4, c.Sbi.Port) + err := fmt.Errorf("sbi and metrics bindings: %s and port: %d cannot be the same, "+ + "please provide at least another port for the metrics", c.Sbi.BindingIP, c.Sbi.Port) errs = append(errs, err) return false, error(errs) } @@ -103,12 +109,54 @@ func (c *Configuration) validate() (bool, error) { } type Sbi struct { - Scheme string `yaml:"scheme" valid:"scheme,required"` + Scheme string `yaml:"scheme" valid:"in(http|https),optional"` RegisterIPv4 string `yaml:"registerIPv4,omitempty" valid:"host,optional"` // IP that is registered at NRF. - // IPv6Addr string `yaml:"ipv6Addr,omitempty"` - BindingIPv4 string `yaml:"bindingIPv4,omitempty" valid:"host,optional"` // IP used to run the server in the node. - Port int `yaml:"port" valid:"port,required"` - Tls *Tls `yaml:"tls,omitempty" valid:"optional"` + RegisterIP string `yaml:"registerIP,omitempty" valid:"host,optional"` // IP that is registered at NRF. + BindingIPv4 string `yaml:"bindingIPv4,omitempty" valid:"host,optional"` // IP used to run the server in the node. + BindingIP string `yaml:"bindingIP,omitempty" valid:"host,optional"` // IP used to run the server in the node. + Port int `yaml:"port,omitempty" valid:"port,optional"` + Tls *Tls `yaml:"tls,omitempty" valid:"optional"` +} + +func (s *Sbi) validate() (bool, error) { + // Set a default Schme if the Configuration does not provides one + if s.Scheme == "" { + s.Scheme = UdrSbiDefaultScheme + } + + // Set BindingIP/RegisterIP from deprecated BindingIPv4/RegisterIPv4 + if s.BindingIP == "" && s.BindingIPv4 != "" { + s.BindingIP = s.BindingIPv4 + } + if s.RegisterIP == "" && s.RegisterIPv4 != "" { + s.RegisterIP = s.RegisterIPv4 + } + + // Set a default BindingIP/RegisterIP if the Configuration does not provides them + if s.BindingIP == "" && s.RegisterIP == "" { + s.BindingIP = UdrSbiDefaultIP + s.RegisterIP = UdrSbiDefaultIP + } else { + // Complete any missing BindingIP/RegisterIP from RegisterIP/BindingIP + if s.BindingIP == "" { + s.BindingIP = s.RegisterIP + } else if s.RegisterIP == "" { + s.RegisterIP = s.BindingIP + } + } + + // Set a default Port if the Configuration does not provides one + if s.Port == 0 { + s.Port = UdrSbiDefaultPort + } + + if tls := s.Tls; tls != nil { + if result, err := tls.validate(); err != nil { + return result, err + } + } + + return govalidator.ValidateStruct(s) } type Tls struct { From 478f210e052620ce4f294b73995b00ddd4ed5b22 Mon Sep 17 00:00:00 2001 From: adjivas Date: Thu, 5 Jun 2025 17:22:05 +0200 Subject: [PATCH 2/3] fix: add IPV6 configuration test --- internal/context/context_test.go | 293 +++++++++++++++++++++++++++++++ 1 file changed, 293 insertions(+) create mode 100644 internal/context/context_test.go diff --git a/internal/context/context_test.go b/internal/context/context_test.go new file mode 100644 index 0000000..8e68471 --- /dev/null +++ b/internal/context/context_test.go @@ -0,0 +1,293 @@ +package context + +import ( + "errors" + "net/netip" + "os" + "testing" + + "github.com/free5gc/openapi/models" + "github.com/free5gc/udr/pkg/factory" + "github.com/stretchr/testify/assert" +) + +func createConfigFile(t *testing.T, postContent []byte) *os.File { + content := []byte(`info: + version: "1.1.0" + description: UDR initial local configuration + +logger: + enable: true + level: debug + +configuration: + nrfUri: http://[2001:db8::1:0:0:10]:8000 + dbConnectorType: mongodb + mongodb: + name: free5gc + url: mongodb://localhost:27017`) + + configFile, err := os.CreateTemp("", "") + if err != nil { + t.Errorf("can't create temp file: %+v", err) + } + + if _, err := configFile.Write(content); err != nil { + t.Errorf("can't write content of temp file: %+v", err) + } + if _, err := configFile.Write(postContent); err != nil { + t.Errorf("can't write content of temp file: %+v", err) + } + if err := configFile.Close(); err != nil { + t.Fatal(err) + } + return configFile +} + +func TestInitUdrContextWithConfigIPv6(t *testing.T) { + postContent := []byte(` + sbi: + scheme: http + registerIP: "2001:db8::1:0:0:4" + bindingIP: "2001:db8::1:0:0:4" + port: 8313`) + + configFile := createConfigFile(t, postContent) + + // Test the initialization with the config file + cfg, err := factory.ReadConfig(configFile.Name()) + if err != nil { + t.Errorf("invalid read config: %+v %+v", err, cfg) + return + } + factory.UdrConfig = cfg + + Init() + + assert.Equal(t, udrContext.SBIPort, 8313) + assert.Equal(t, udrContext.RegisterIP.String(), "2001:db8::1:0:0:4") + assert.Equal(t, udrContext.BindingIP.String(), "2001:db8::1:0:0:4") + assert.Equal(t, udrContext.UriScheme, models.UriScheme("http")) + + // Close the config file + t.Cleanup(func() { + if err := os.RemoveAll(configFile.Name()); err != nil { + t.Fatal(err) + } + }) +} + +func TestInitUdrContextWithConfigIPv4(t *testing.T) { + postContent := []byte(` + sbi: + scheme: http + registerIP: "127.0.0.4" + bindingIP: "127.0.0.4" + port: 8131`) + + configFile := createConfigFile(t, postContent) + + // Test the initialization with the config file + cfg, err := factory.ReadConfig(configFile.Name()) + if err != nil { + t.Errorf("invalid read config: %+v %+v", err, cfg) + } + factory.UdrConfig = cfg + + Init() + + assert.Equal(t, udrContext.SBIPort, 8131) + assert.Equal(t, udrContext.RegisterIP.String(), "127.0.0.4") + assert.Equal(t, udrContext.BindingIP.String(), "127.0.0.4") + assert.Equal(t, udrContext.UriScheme, models.UriScheme("http")) + + // Close the config file + t.Cleanup(func() { + if err := os.RemoveAll(configFile.Name()); err != nil { + t.Fatal(err) + } + }) +} + +func TestInitUdrContextWithConfigDeprecated(t *testing.T) { + postContent := []byte(` + sbi: + scheme: http + registerIPv4: "127.0.0.30" + bindingIPv4: "127.0.0.30" + port: 8003`) + + configFile := createConfigFile(t, postContent) + + // Test the initialization with the config file + cfg, err := factory.ReadConfig(configFile.Name()) + if err != nil { + t.Errorf("invalid read config: %+v %+v", err, cfg) + } + factory.UdrConfig = cfg + + Init() + + assert.Equal(t, udrContext.SBIPort, 8003) + assert.Equal(t, udrContext.RegisterIP.String(), "127.0.0.30") + assert.Equal(t, udrContext.BindingIP.String(), "127.0.0.30") + assert.Equal(t, udrContext.UriScheme, models.UriScheme("http")) + + // Close the config file + t.Cleanup(func() { + if err := os.RemoveAll(configFile.Name()); err != nil { + t.Fatal(err) + } + }) +} + +func TestInitUdrContextWithConfigEmptySBI(t *testing.T) { + postContent := []byte(``) + + configFile := createConfigFile(t, postContent) + + // Test the initialization with the config file fails + _, err := factory.ReadConfig(configFile.Name()) + assert.Equal(t, err, errors.New("Config validate Error")) + + // Close the config file + t.Cleanup(func() { + if err := os.RemoveAll(configFile.Name()); err != nil { + t.Fatal(err) + } + }) +} + +func TestInitUdrContextWithConfigMissingRegisterIP(t *testing.T) { + postContent := []byte(` + sbi: + bindingIP: "2001:db8::1:0:0:130"`) + + configFile := createConfigFile(t, postContent) + + // Test the initialization with the config file + cfg, err := factory.ReadConfig(configFile.Name()) + if err != nil { + t.Errorf("invalid read config: %+v %+v", err, cfg) + } + factory.UdrConfig = cfg + + Init() + + assert.Equal(t, udrContext.SBIPort, 8000) + assert.Equal(t, udrContext.BindingIP.String(), "2001:db8::1:0:0:130") + assert.Equal(t, udrContext.RegisterIP.String(), "2001:db8::1:0:0:130") + assert.Equal(t, udrContext.UriScheme, models.UriScheme("https")) + + // Close the config file + t.Cleanup(func() { + if err := os.RemoveAll(configFile.Name()); err != nil { + t.Fatal(err) + } + }) +} + +func TestInitUdrContextWithConfigMissingBindingIP(t *testing.T) { + postContent := []byte(` + sbi: + registerIP: "2001:db8::1:0:0:131"`) + + configFile := createConfigFile(t, postContent) + + // Test the initialization with the config file + cfg, err := factory.ReadConfig(configFile.Name()) + if err != nil { + t.Errorf("invalid read config: %+v %+v", err, cfg) + } + factory.UdrConfig = cfg + + Init() + + assert.Equal(t, udrContext.SBIPort, 8000) + assert.Equal(t, udrContext.BindingIP.String(), "2001:db8::1:0:0:131") + assert.Equal(t, udrContext.RegisterIP.String(), "2001:db8::1:0:0:131") + assert.Equal(t, udrContext.UriScheme, models.UriScheme("https")) + + // Close the config file + t.Cleanup(func() { + if err := os.RemoveAll(configFile.Name()); err != nil { + t.Fatal(err) + } + }) +} + +func TestInitUdrContextWithConfigIPv6FromEnv(t *testing.T) { + postContent := []byte(` + sbi: + scheme: http + registerIP: "MY_REGISTER_IP" + bindingIP: "MY_BINDING_IP" + port: 8313`) + + configFile := createConfigFile(t, postContent) + + if err := os.Setenv("MY_REGISTER_IP", "2001:db8::1:0:0:130"); err != nil { + t.Errorf("Can't set MY_BINDING_IP variable environnement: %+v", err) + } + if err := os.Setenv("MY_BINDING_IP", "2001:db8::1:0:0:130"); err != nil { + t.Errorf("Can't set MY_BINDING_IP variable environnement: %+v", err) + } + + // Test the initialization with the config file + cfg, err := factory.ReadConfig(configFile.Name()) + if err != nil { + t.Errorf("invalid read config: %+v %+v", err, cfg) + } + factory.UdrConfig = cfg + + Init() + + assert.Equal(t, udrContext.SBIPort, 8313) + assert.Equal(t, udrContext.RegisterIP.String(), "2001:db8::1:0:0:130") + assert.Equal(t, udrContext.BindingIP.String(), "2001:db8::1:0:0:130") + assert.Equal(t, udrContext.UriScheme, models.UriScheme("http")) + + // Close the config file + t.Cleanup(func() { + if err := os.RemoveAll(configFile.Name()); err != nil { + t.Fatal(err) + } + }) +} + +func TestResolveIPLocalhost(t *testing.T) { + expectedAddr, err := netip.ParseAddr("::1") + if err != nil { + t.Errorf("invalid expected IP: %+v", expectedAddr) + } + + addr := resolveIP("localhost") + if addr != expectedAddr { + t.Errorf("invalid IP: %+v", addr) + } + assert.Equal(t, addr, expectedAddr) +} + +func TestResolveIPv4(t *testing.T) { + expectedAddr, err := netip.ParseAddr("127.0.0.1") + if err != nil { + t.Errorf("invalid expected IP: %+v", expectedAddr) + } + + addr := resolveIP("127.0.0.1") + if addr != expectedAddr { + t.Errorf("invalid IP: %+v", addr) + } +} + +func TestResolveIPv6(t *testing.T) { + expectedAddr, err := netip.ParseAddr("2001:db8::1:0:0:1") + if err != nil { + t.Errorf("invalid expected IP: %+v", expectedAddr) + } + + addr := resolveIP("2001:db8::1:0:0:1") + if addr != expectedAddr { + t.Errorf("invalid IP: %+v", addr) + } +} From 67668570e7be29fb3584585b3518c3ee5be9efe1 Mon Sep 17 00:00:00 2001 From: adjivas Date: Mon, 18 Aug 2025 15:42:13 +0200 Subject: [PATCH 3/3] fix: pass golang-lint --- internal/context/context.go | 94 ++++++++++++------------- internal/context/context_test.go | 3 +- internal/sbi/consumer/nrf_service.go | 6 +- internal/sbi/server.go | 10 +-- internal/util/init_context.go | 32 ++++----- internal/util/router_auth_check_test.go | 5 +- pkg/factory/config.go | 2 +- 7 files changed, 75 insertions(+), 77 deletions(-) diff --git a/internal/context/context.go b/internal/context/context.go index 376239d..b42e2c4 100644 --- a/internal/context/context.go +++ b/internal/context/context.go @@ -43,7 +43,7 @@ func Init() { serviceName := []models.ServiceName{ models.ServiceName_NUDR_DR, } - udrContext.NrfUri = fmt.Sprintf("%s", udrContext.GetIPUriWithPort(29510)) + udrContext.NrfUri = udrContext.GetIPUriWithPort(29510) initUdrContext() config := factory.UdrConfig @@ -133,20 +133,20 @@ func initUdrContext() { sbi := configuration.Sbi - udrContext.SBIPort = sbi.Port + udrContext.SBIPort = sbi.Port - udrContext.UriScheme = models.UriScheme(sbi.Scheme) + udrContext.UriScheme = models.UriScheme(sbi.Scheme) - if bindingIP := os.Getenv(sbi.BindingIP); bindingIP != "" { - logger.UtilLog.Info("Parsing BindingIP address from ENV Variable.") - sbi.BindingIP = bindingIP - } - if registerIP := os.Getenv(sbi.RegisterIP); registerIP != "" { - logger.UtilLog.Info("Parsing RegisterIP address from ENV Variable.") - sbi.RegisterIP = registerIP - } - udrContext.BindingIP = resolveIP(sbi.BindingIP) - udrContext.RegisterIP = resolveIP(sbi.RegisterIP) + if bindingIP := os.Getenv(sbi.BindingIP); bindingIP != "" { + logger.UtilLog.Info("Parsing BindingIP address from ENV Variable.") + sbi.BindingIP = bindingIP + } + if registerIP := os.Getenv(sbi.RegisterIP); registerIP != "" { + logger.UtilLog.Info("Parsing RegisterIP address from ENV Variable.") + sbi.RegisterIP = registerIP + } + udrContext.BindingIP = resolveIP(sbi.BindingIP) + udrContext.RegisterIP = resolveIP(sbi.RegisterIP) if configuration.NrfUri != "" { udrContext.NrfUri = configuration.NrfUri @@ -158,43 +158,43 @@ func initUdrContext() { } func resolveIP(ip string) netip.Addr { - resolvedIPs, err := net.DefaultResolver.LookupNetIP(context.Background(), "ip", ip) - if err != nil { - logger.InitLog.Errorf("Lookup failed with %s: %+v", ip, err) - } - resolvedIP := resolvedIPs[0].Unmap() - if resolvedIP := resolvedIP.String(); resolvedIP != ip { - logger.UtilLog.Infof("Lookup revolved %s into %s", ip, resolvedIP) - } - return resolvedIP + resolvedIPs, err := net.DefaultResolver.LookupNetIP(context.Background(), "ip", ip) + if err != nil { + logger.InitLog.Errorf("Lookup failed with %s: %+v", ip, err) + } + resolvedIP := resolvedIPs[0].Unmap() + if resolvedIP := resolvedIP.String(); resolvedIP != ip { + logger.UtilLog.Infof("Lookup revolved %s into %s", ip, resolvedIP) + } + return resolvedIP } func (c *UDRContext) GetIPUri() string { - addr := c.RegisterIP - port := c.SBIPort + addr := c.RegisterIP + port := c.SBIPort - return fmt.Sprintf("%s://%s", c.UriScheme, netip.AddrPortFrom(addr, uint16(port)).String()) + return fmt.Sprintf("%s://%s", c.UriScheme, netip.AddrPortFrom(addr, uint16(port)).String()) } func (c *UDRContext) GetIpEndPoint() []models.IpEndPoint { - if c.RegisterIP.Is6() { - return []models.IpEndPoint{ - { - Ipv6Address: c.RegisterIP.String(), - Transport: models.NrfNfManagementTransportProtocol_TCP, - Port: int32(c.SBIPort), - }, - } - } else if c.RegisterIP.Is4() { - return []models.IpEndPoint{ - { - Ipv4Address: c.RegisterIP.String(), - Transport: models.NrfNfManagementTransportProtocol_TCP, - Port: int32(c.SBIPort), - }, - } - } - return nil + if c.RegisterIP.Is6() { + return []models.IpEndPoint{ + { + Ipv6Address: c.RegisterIP.String(), + Transport: models.NrfNfManagementTransportProtocol_TCP, + Port: int32(c.SBIPort), + }, + } + } else if c.RegisterIP.Is4() { + return []models.IpEndPoint{ + { + Ipv4Address: c.RegisterIP.String(), + Transport: models.NrfNfManagementTransportProtocol_TCP, + Port: int32(c.SBIPort), + }, + } + } + return nil } func initNfService(serviceName []models.ServiceName, version string) ( @@ -214,8 +214,8 @@ func initNfService(serviceName []models.ServiceName, version string) ( }, Scheme: udrContext.UriScheme, NfServiceStatus: models.NfServiceStatus_REGISTERED, - ApiPrefix: udrContext.GetIPUri(), - IpEndPoints: udrContext.GetIpEndPoint(), + ApiPrefix: udrContext.GetIPUri(), + IpEndPoints: udrContext.GetIpEndPoint(), } } @@ -223,9 +223,9 @@ func initNfService(serviceName []models.ServiceName, version string) ( } func (context *UDRContext) GetIPUriWithPort(port int) string { - addr := context.RegisterIP + addr := context.RegisterIP - return fmt.Sprintf("%s://%s", context.UriScheme, netip.AddrPortFrom(addr, uint16(port)).String()) + return fmt.Sprintf("%s://%s", context.UriScheme, netip.AddrPortFrom(addr, uint16(port)).String()) } func (context *UDRContext) GetIPv4GroupUri(udrServiceType UDRServiceType) string { diff --git a/internal/context/context_test.go b/internal/context/context_test.go index 8e68471..972b906 100644 --- a/internal/context/context_test.go +++ b/internal/context/context_test.go @@ -6,9 +6,10 @@ import ( "os" "testing" + "github.com/stretchr/testify/assert" + "github.com/free5gc/openapi/models" "github.com/free5gc/udr/pkg/factory" - "github.com/stretchr/testify/assert" ) func createConfigFile(t *testing.T, postContent []byte) *os.File { diff --git a/internal/sbi/consumer/nrf_service.go b/internal/sbi/consumer/nrf_service.go index 4b887cb..e1f1447 100644 --- a/internal/sbi/consumer/nrf_service.go +++ b/internal/sbi/consumer/nrf_service.go @@ -48,9 +48,9 @@ func (ns *NrfService) buildNFProfile(context *udr_context.UDRContext) (models.Nr // config := factory.UdrConfig profile := models.NrfNfManagementNfProfile{ - NfInstanceId: context.NfId, - NfType: models.NrfNfManagementNfType_UDR, - NfStatus: models.NrfNfManagementNfStatus_REGISTERED, + NfInstanceId: context.NfId, + NfType: models.NrfNfManagementNfType_UDR, + NfStatus: models.NrfNfManagementNfStatus_REGISTERED, UdrInfo: &models.UdrInfo{ SupportedDataSets: []models.DataSetId{ // models.DataSetId_APPLICATION, diff --git a/internal/sbi/server.go b/internal/sbi/server.go index a415ceb..f7e1797 100644 --- a/internal/sbi/server.go +++ b/internal/sbi/server.go @@ -10,7 +10,7 @@ import ( "time" "github.com/gin-gonic/gin" - "github.com/sirupsen/logrus" + "github.com/sirupsen/logrus" "github.com/free5gc/openapi/models" "github.com/free5gc/udr/internal/logger" @@ -41,18 +41,14 @@ func NewServer(udr UDR, tlsKeyLogPath string) *Server { UDR: udr, } - s.router = newRouter(s) - addr := s.Context().RegisterIP port := uint16(s.Context().SBIPort) - bind := netip.AddrPortFrom(addr, port).String() - bindAddr := fmt.Sprintf("%s", bind) - logger.SBILog.Infof("Binding addr: [%s]", bindAddr) + logger.SBILog.Infof("Binding addr: [%s]", bind) var err error - if s.httpServer, err = httpwrapper.NewHttp2Server(bindAddr, tlsKeyLogPath, s.router); err != nil { + if s.httpServer, err = httpwrapper.NewHttp2Server(bind, tlsKeyLogPath, s.router); err != nil { logger.InitLog.Errorf("Initialize HTTP server failed: %v", err) panic("Server initialization failed") } diff --git a/internal/util/init_context.go b/internal/util/init_context.go index c61118b..fb270bc 100644 --- a/internal/util/init_context.go +++ b/internal/util/init_context.go @@ -21,22 +21,22 @@ func InitUdrContext(context *udr_context.UDRContext) { configuration := config.Configuration context.NfId = uuid.New().String() - sbi := configuration.Sbi - - context.SBIPort = sbi.Port - - context.UriScheme = models.UriScheme(sbi.Scheme) - - if bindingIP := os.Getenv(sbi.BindingIP); bindingIP != "" { - logger.UtilLog.Info("Parsing BindingIP address from ENV Variable.") - sbi.BindingIP = bindingIP - } - if registerIP := os.Getenv(sbi.RegisterIP); registerIP != "" { - logger.UtilLog.Info("Parsing RegisterIP address from ENV Variable.") - sbi.RegisterIP = registerIP - } - context.BindingIP = resolveIP(sbi.BindingIP) - context.RegisterIP = resolveIP(sbi.RegisterIP) + sbi := configuration.Sbi + + context.SBIPort = sbi.Port + + context.UriScheme = models.UriScheme(sbi.Scheme) + + if bindingIP := os.Getenv(sbi.BindingIP); bindingIP != "" { + logger.UtilLog.Info("Parsing BindingIP address from ENV Variable.") + sbi.BindingIP = bindingIP + } + if registerIP := os.Getenv(sbi.RegisterIP); registerIP != "" { + logger.UtilLog.Info("Parsing RegisterIP address from ENV Variable.") + sbi.RegisterIP = registerIP + } + context.BindingIP = resolveIP(sbi.BindingIP) + context.RegisterIP = resolveIP(sbi.RegisterIP) if configuration.NrfUri != "" { context.NrfUri = configuration.NrfUri diff --git a/internal/util/router_auth_check_test.go b/internal/util/router_auth_check_test.go index 25dca0c..4940079 100644 --- a/internal/util/router_auth_check_test.go +++ b/internal/util/router_auth_check_test.go @@ -1,6 +1,7 @@ package util import ( + "context" "net/http" "net/http/httptest" "testing" @@ -36,7 +37,7 @@ func TestRouterAuthorizationCheck_Check(t *testing.T) { c, _ := gin.CreateTestContext(w) var err error - c.Request, err = http.NewRequest("GET", "/", nil) + c.Request, err = http.NewRequestWithContext(context.Background(), "GET", "/", nil) if err != nil { t.Errorf("error on http request: %+v", err) } @@ -77,7 +78,7 @@ func TestRouterAuthorizationCheck_Check(t *testing.T) { t.Run(tt.name, func(t *testing.T) { w = httptest.NewRecorder() c, _ = gin.CreateTestContext(w) - c.Request, err = http.NewRequest("GET", "/", nil) + c.Request, err = http.NewRequestWithContext(context.Background(), "GET", "/", nil) if err != nil { t.Errorf("error on http request: %+v", err) } diff --git a/pkg/factory/config.go b/pkg/factory/config.go index db20c1f..64bc42b 100644 --- a/pkg/factory/config.go +++ b/pkg/factory/config.go @@ -95,7 +95,7 @@ func (c *Configuration) validate() (bool, error) { return false, err } - if c.Metrics.Port == c.Sbi.Port && c.Sbi.BindingIP == c.Metrics.BindingIP { + if c.Metrics.Port == c.Sbi.Port && c.Sbi.BindingIP == c.Metrics.BindingIPv4 { var errs govalidator.Errors err := fmt.Errorf("sbi and metrics bindings: %s and port: %d cannot be the same, "+ "please provide at least another port for the metrics", c.Sbi.BindingIP, c.Sbi.Port)