Skip to content

Commit

Permalink
refactor: add UDM service consumer
Browse files Browse the repository at this point in the history
  • Loading branch information
andy89923 committed Jun 21, 2024
1 parent ca00f22 commit 60a2dde
Show file tree
Hide file tree
Showing 6 changed files with 164 additions and 102 deletions.
8 changes: 8 additions & 0 deletions internal/sbi/consumer/consumer.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"github.com/free5gc/ausf/pkg/app"
"github.com/free5gc/openapi/Nnrf_NFDiscovery"
"github.com/free5gc/openapi/Nnrf_NFManagement"
"github.com/free5gc/openapi/Nudm_UEAuthentication"
)

var consumer *Consumer
Expand All @@ -16,6 +17,7 @@ type Consumer struct {
ConsumerAusf

*nnrfService
*nudmService
}

func GetConsumer() *Consumer {
Expand All @@ -32,6 +34,12 @@ func NewConsumer(ausf ConsumerAusf) (*Consumer, error) {
nfMngmntClients: make(map[string]*Nnrf_NFManagement.APIClient),
nfDiscClients: make(map[string]*Nnrf_NFDiscovery.APIClient),
}

c.nudmService = &nudmService{
consumer: c,
ueauClients: make(map[string]*Nudm_UEAuthentication.APIClient),
}

consumer = c
return c, nil
}
28 changes: 28 additions & 0 deletions internal/sbi/consumer/nrf_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ import (
"context"
"fmt"
"net/http"
"strconv"
"strings"
"sync"
"time"

"github.com/antihax/optional"
"github.com/pkg/errors"

ausf_context "github.com/free5gc/ausf/internal/context"
Expand Down Expand Up @@ -221,3 +223,29 @@ func (s *nnrfService) buildNfProfile(ausfContext *ausf_context.AUSFContext) (pro
}
return
}

func (s *nnrfService) GetUdmUrl(nrfUri string) string {
udmUrl := "https://localhost:29503" // default
nfDiscoverParam := &Nnrf_NFDiscovery.SearchNFInstancesParamOpts{
ServiceNames: optional.NewInterface([]models.ServiceName{models.ServiceName_NUDM_UEAU}),
}
res, err := s.SendSearchNFInstances(
nrfUri,
models.NfType_UDM,
models.NfType_AUSF,
nfDiscoverParam,
)
if err != nil {
logger.ConsumerLog.Errorln("[Search UDM UEAU] ", err.Error(), "use defalt udmUrl", udmUrl)
} else if len(res.NfInstances) > 0 {
udmInstance := res.NfInstances[0]
if len(udmInstance.Ipv4Addresses) > 0 && udmInstance.NfServices != nil {
ueauService := (*udmInstance.NfServices)[0]
ueauEndPoint := (*ueauService.IpEndPoints)[0]
udmUrl = string(ueauService.Scheme) + "://" + ueauEndPoint.Ipv4Address + ":" + strconv.Itoa(int(ueauEndPoint.Port))
}
} else {
logger.ConsumerLog.Errorln("[Search UDM UEAU] len(NfInstances) = 0")
}
return udmUrl
}
107 changes: 107 additions & 0 deletions internal/sbi/consumer/udm_service.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package consumer

import (
"sync"
"time"

ausf_context "github.com/free5gc/ausf/internal/context"
"github.com/free5gc/ausf/internal/logger"
Nudm_UEAU "github.com/free5gc/openapi/Nudm_UEAuthentication"
"github.com/free5gc/openapi/models"
)

type nudmService struct {
consumer *Consumer

ueauMu sync.RWMutex

ueauClients map[string]*Nudm_UEAU.APIClient
}

func (s *nudmService) getUdmUeauClient(uri string) *Nudm_UEAU.APIClient {
if uri == "" {
return nil
}
s.ueauMu.RLock()
client, ok := s.ueauClients[uri]
if ok {
s.ueauMu.RUnlock()
return client
}

configuration := Nudm_UEAU.NewConfiguration()
configuration.SetBasePath(uri)
client = Nudm_UEAU.NewAPIClient(configuration)

s.ueauMu.RUnlock()
s.ueauMu.Lock()
defer s.ueauMu.Unlock()
s.ueauClients[uri] = client
return client
}

func (s *nudmService) SendAuthResultToUDM(
id string,
authType models.AuthType,
success bool,
servingNetworkName, udmUrl string,
) error {
timeNow := time.Now()
timePtr := &timeNow

self := s.consumer.Context()

authEvent := models.AuthEvent{
TimeStamp: timePtr,
AuthType: authType,
Success: success,
ServingNetworkName: servingNetworkName,
NfInstanceId: self.GetSelfID(),
}

client := s.getUdmUeauClient(udmUrl)

ctx, _, err := ausf_context.GetSelf().GetTokenCtx(models.ServiceName_NUDM_UEAU, models.NfType_UDM)
if err != nil {
return err
}

_, rsp, confirmAuthErr := client.ConfirmAuthApi.ConfirmAuth(ctx, id, authEvent)
defer func() {
if rspCloseErr := rsp.Body.Close(); rspCloseErr != nil {
logger.ConsumerLog.Errorf("ConfirmAuth Response cannot close: %v", rspCloseErr)
}
}()
return confirmAuthErr
}

func (s *nudmService) GenerateAuthDataApi(
udmUrl string,
supiOrSuci string,
authInfoReq models.AuthenticationInfoRequest,
) (*models.AuthenticationInfoResult, error, *models.ProblemDetails) {
client := s.getUdmUeauClient(udmUrl)

ctx, pd, err := ausf_context.GetSelf().GetTokenCtx(models.ServiceName_NUDM_UEAU, models.NfType_UDM)
if err != nil {
return nil, err, pd
}

authInfoResult, rsp, err := client.GenerateAuthDataApi.GenerateAuthData(ctx, supiOrSuci, authInfoReq)
if err != nil {
var problemDetails models.ProblemDetails
if authInfoResult.AuthenticationVector == nil {
problemDetails.Cause = "AV_GENERATION_PROBLEM"
} else {
problemDetails.Cause = "UPSTREAM_SERVER_ERROR"
}
problemDetails.Status = int32(rsp.StatusCode)
return nil, err, &problemDetails
}
defer func() {
if rspCloseErr := rsp.Body.Close(); rspCloseErr != nil {
logger.UeAuthLog.Errorf("GenerateAuthDataApi response body cannot close: %+v", rspCloseErr)
}
}()
return &authInfoResult, nil, nil
}
7 changes: 6 additions & 1 deletion internal/sbi/processor/processor.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
package processor

import "github.com/free5gc/ausf/pkg/app"
import (
"github.com/free5gc/ausf/internal/sbi/consumer"
"github.com/free5gc/ausf/pkg/app"
)

type ProcessorAusf interface {
app.App

Consumer() *consumer.Consumer
}

type Processor struct {
Expand Down
111 changes: 15 additions & 96 deletions internal/sbi/processor/ue_authentication.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,14 @@ import (
"strings"
"time"

"github.com/antihax/optional"
"github.com/bronze1man/radius"
"github.com/gin-gonic/gin"
"github.com/google/gopacket"
"github.com/google/gopacket/layers"

ausf_context "github.com/free5gc/ausf/internal/context"
"github.com/free5gc/ausf/internal/logger"
"github.com/free5gc/ausf/internal/sbi/consumer"
"github.com/free5gc/ausf/pkg/factory"
"github.com/free5gc/openapi/Nnrf_NFDiscovery"
Nudm_UEAU "github.com/free5gc/openapi/Nudm_UEAuthentication"
"github.com/free5gc/openapi/models"
"github.com/free5gc/util/ueauth"
)
Expand Down Expand Up @@ -132,31 +128,14 @@ func (p *Processor) UeAuthPostRequestProcedure(
lastEapID = ausfCurrentContext.EapID
}

udmUrl := getUdmUrl(self.NrfUri)
client := createClientToUdmUeau(udmUrl)
udmUrl := p.Consumer().GetUdmUrl(self.NrfUri)

ctx, _, err := ausf_context.GetSelf().GetTokenCtx(models.ServiceName_NUDM_UEAU, models.NfType_UDM)
result, err, pd := p.Consumer().GenerateAuthDataApi(udmUrl, supiOrSuci, authInfoReq)
if err != nil {
return nil, "", nil
logger.UeAuthLog.Infof("GenerateAuthDataApi error: %+v", err)
return nil, "", pd
}

authInfoResult, rsp, err := client.GenerateAuthDataApi.GenerateAuthData(ctx, supiOrSuci, authInfoReq)
if err != nil {
logger.UeAuthLog.Infoln(err.Error())
var problemDetails models.ProblemDetails
if authInfoResult.AuthenticationVector == nil {
problemDetails.Cause = "AV_GENERATION_PROBLEM"
} else {
problemDetails.Cause = "UPSTREAM_SERVER_ERROR"
}
problemDetails.Status = int32(rsp.StatusCode)
return nil, "", &problemDetails
}
defer func() {
if rspCloseErr := rsp.Body.Close(); rspCloseErr != nil {
logger.UeAuthLog.Errorf("GenerateAuthDataApi response body cannot close: %+v", rspCloseErr)
}
}()
authInfoResult := *result

ueid := authInfoResult.Supi
ausfUeContext := ausf_context.NewAusfUeContext(ueid)
Expand Down Expand Up @@ -376,11 +355,11 @@ func (p *Processor) Auth5gAkaComfirmRequestProcedure(updateConfirmationData mode
} else {
ausfCurrentContext.AuthStatus = models.AuthResult_FAILURE
responseBody.AuthResult = models.AuthResult_FAILURE
logConfirmFailureAndInformUDM(ConfirmationDataResponseID, models.AuthType__5_G_AKA, servingNetworkName,
p.logConfirmFailureAndInformUDM(ConfirmationDataResponseID, models.AuthType__5_G_AKA, servingNetworkName,
"5G AKA confirmation failed", ausfCurrentContext.UdmUeauUrl)
}

if sendErr := sendAuthResultToUDM(currentSupi, models.AuthType__5_G_AKA, success, servingNetworkName,
if sendErr := p.Consumer().SendAuthResultToUDM(currentSupi, models.AuthType__5_G_AKA, success, servingNetworkName,
ausfCurrentContext.UdmUeauUrl); sendErr != nil {
logger.Auth5gAkaLog.Infoln(sendErr.Error())
var problemDetails models.ProblemDetails
Expand Down Expand Up @@ -474,7 +453,7 @@ func (p *Processor) EapAuthComfirmRequestProcedure(
eapSuccPkt := ConstructEapNoTypePkt(radius.EapCodeSuccess, eapContent.Id)
responseBody.EapPayload = eapSuccPkt
udmUrl := ausfCurrentContext.UdmUeauUrl
if sendErr := sendAuthResultToUDM(
if sendErr := p.Consumer().SendAuthResultToUDM(
eapSessionID,
models.AuthType_EAP_AKA_PRIME,
true,
Expand Down Expand Up @@ -528,7 +507,7 @@ func (p *Processor) EapAuthComfirmRequestProcedure(

if !eapOK {
logger.AuthELog.Warnf("EAP-AKA' failure: %s", eapErrStr)
if sendErr := sendAuthResultToUDM(eapSessionID, models.AuthType_EAP_AKA_PRIME, false, servingNetworkName,
if sendErr := p.Consumer().SendAuthResultToUDM(eapSessionID, models.AuthType_EAP_AKA_PRIME, false, servingNetworkName,
ausfCurrentContext.UdmUeauUrl); sendErr != nil {
logger.AuthELog.Infoln(sendErr.Error())
var problemDetails models.ProblemDetails
Expand All @@ -548,7 +527,7 @@ func (p *Processor) EapAuthComfirmRequestProcedure(
responseBody.Links = make(map[string]models.LinksValueSchema)
responseBody.Links["eap-session"] = linksValue
} else if ausfCurrentContext.AuthStatus == models.AuthResult_FAILURE {
if sendErr := sendAuthResultToUDM(eapSessionID, models.AuthType_EAP_AKA_PRIME, false, servingNetworkName,
if sendErr := p.Consumer().SendAuthResultToUDM(eapSessionID, models.AuthType_EAP_AKA_PRIME, false, servingNetworkName,
ausfCurrentContext.UdmUeauUrl); sendErr != nil {
logger.AuthELog.Infoln(sendErr.Error())
var problemDetails models.ProblemDetails
Expand Down Expand Up @@ -873,77 +852,17 @@ func ConstructEapNoTypePkt(code radius.EapCode, pktID uint8) string {
return base64.StdEncoding.EncodeToString(b)
}

func getUdmUrl(nrfUri string) string {
udmUrl := "https://localhost:29503" // default
nfDiscoverParam := Nnrf_NFDiscovery.SearchNFInstancesParamOpts{
ServiceNames: optional.NewInterface([]models.ServiceName{models.ServiceName_NUDM_UEAU}),
}
res, err := consumer.GetConsumer().SendSearchNFInstances(
nrfUri,
models.NfType_UDM,
models.NfType_AUSF,
&nfDiscoverParam,
)
if err != nil {
logger.UeAuthLog.Errorln("[Search UDM UEAU] ", err.Error())
} else if len(res.NfInstances) > 0 {
udmInstance := res.NfInstances[0]
if len(udmInstance.Ipv4Addresses) > 0 && udmInstance.NfServices != nil {
ueauService := (*udmInstance.NfServices)[0]
ueauEndPoint := (*ueauService.IpEndPoints)[0]
udmUrl = string(ueauService.Scheme) + "://" + ueauEndPoint.Ipv4Address + ":" + strconv.Itoa(int(ueauEndPoint.Port))
}
} else {
logger.UeAuthLog.Errorln("[Search UDM UEAU] len(NfInstances) = 0")
}
return udmUrl
}

func createClientToUdmUeau(udmUrl string) *Nudm_UEAU.APIClient {
cfg := Nudm_UEAU.NewConfiguration()
cfg.SetBasePath(udmUrl)
clientAPI := Nudm_UEAU.NewAPIClient(cfg)
return clientAPI
}

func sendAuthResultToUDM(id string, authType models.AuthType, success bool, servingNetworkName, udmUrl string) error {
timeNow := time.Now()
timePtr := &timeNow

self := ausf_context.GetSelf()

var authEvent models.AuthEvent
authEvent.TimeStamp = timePtr
authEvent.AuthType = authType
authEvent.Success = success
authEvent.ServingNetworkName = servingNetworkName
authEvent.NfInstanceId = self.GetSelfID()

client := createClientToUdmUeau(udmUrl)

ctx, _, err := ausf_context.GetSelf().GetTokenCtx(models.ServiceName_NUDM_UEAU, models.NfType_UDM)
if err != nil {
return err
}

_, rsp, confirmAuthErr := client.ConfirmAuthApi.ConfirmAuth(ctx, id, authEvent)
defer func() {
if rspCloseErr := rsp.Body.Close(); rspCloseErr != nil {
logger.ConsumerLog.Errorf("ConfirmAuth Response cannot close: %v", rspCloseErr)
}
}()
return confirmAuthErr
}

func logConfirmFailureAndInformUDM(id string, authType models.AuthType, servingNetworkName, errStr, udmUrl string) {
func (p *Processor) logConfirmFailureAndInformUDM(
id string, authType models.AuthType, servingNetworkName, errStr, udmUrl string,
) {
if authType == models.AuthType__5_G_AKA {
logger.Auth5gAkaLog.Infoln(errStr)
if sendErr := sendAuthResultToUDM(id, authType, false, "", udmUrl); sendErr != nil {
if sendErr := p.Consumer().SendAuthResultToUDM(id, authType, false, "", udmUrl); sendErr != nil {
logger.Auth5gAkaLog.Infoln(sendErr.Error())
}
} else if authType == models.AuthType_EAP_AKA_PRIME {
logger.AuthELog.Infoln(errStr)
if sendErr := sendAuthResultToUDM(id, authType, false, "", udmUrl); sendErr != nil {
if sendErr := p.Consumer().SendAuthResultToUDM(id, authType, false, "", udmUrl); sendErr != nil {
logger.AuthELog.Infoln(sendErr.Error())
}
}
Expand Down
5 changes: 0 additions & 5 deletions pkg/service/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,6 @@ var AUSF *AusfApp
var _ app.App = &AusfApp{}

type AusfApp struct {
app.App
consumer.ConsumerAusf
processor.ProcessorAusf
sbi.ServerAusf

ausfCtx *ausf_context.AUSFContext
cfg *factory.Config

Expand Down

0 comments on commit 60a2dde

Please sign in to comment.