Skip to content

Commit

Permalink
chore: Use common data structures (#9)
Browse files Browse the repository at this point in the history
  • Loading branch information
gruyaume authored Feb 3, 2024
1 parent d72319d commit 16cddc4
Show file tree
Hide file tree
Showing 11 changed files with 141 additions and 93 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,5 @@ docker run -it ghcr.io/dot-5g/sepp:latest

## Reference

- [5G Public Land Mobile Network (PLMN) Interconnection](https://www.etsi.org/deliver/etsi_ts/129500_129599/129573/15.04.00_60/ts_129573v150400p.pdf)
- [5G Security architecture and procedures for 5G System](https://www.etsi.org/deliver/etsi_ts/133500_133599/133501/16.03.00_60/ts_133501v160300p.pdf)
- [3GPP TS 29.573 - Public Land Mobile Network (PLMN) Interconnection](https://www.etsi.org/deliver/etsi_ts/129500_129599/129573/16.03.00_60/ts_129573v160300p.pdf)
- [3GPP TS 33.501 - Security architecture and procedures for 5G System](https://www.etsi.org/deliver/etsi_ts/133500_133599/133501/16.03.00_60/ts_133501v160300p.pdf)
71 changes: 43 additions & 28 deletions cmd/sepp/sepp.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import (
"flag"
"log"
"sync"
"time"

"github.com/dot-5g/sepp/config"
"github.com/dot-5g/sepp/internal/model"
"github.com/dot-5g/sepp/internal/n32"
"github.com/dot-5g/sepp/internal/sbi"
)
Expand All @@ -20,44 +20,59 @@ func init() {
func main() {
flag.Parse()
var wg sync.WaitGroup
seppContext := &model.SEPPContext{}

conf, err := config.LoadConfiguration(configFilePath)
if err != nil {
log.Fatalf("Failed to read config file: %s", err)
log.Fatalf("failed to read config file: %s", err)
}
wg.Add(1)
go func() {
defer wg.Done()
n32.StartServer(conf.SEPP.Local.N32.GetAddress(), conf.SEPP.Local.N32.TLS.Cert, conf.SEPP.Local.N32.TLS.Key, conf.SEPP.Local.N32.TLS.CA, conf.SEPP.Local.N32.FQDN)
}()
startN32Server(&wg, conf.SEPP.Local.N32)
remoteURL := conf.SEPP.Remote.URL
if remoteURL != "" {
exchangeCapability(remoteURL, conf.SEPP.Remote.TLS)
wg.Add(1)
go func() {
defer wg.Done()
sbi.StartServer(conf)
}()
secNegotiateRspData, err := exchangeCapability(remoteURL, conf.SEPP.Local.N32.FQDN, conf.SEPP.SecurityCapability, conf.SEPP.Remote.TLS)
if err != nil {
log.Fatalf("failed to exchange capability: %s", err)
}
seppContext.Mu.Lock()
seppContext.RemoteFQDN = model.FQDN(secNegotiateRspData.Sender)
seppContext.SecurityCapability = model.SecurityCapability(secNegotiateRspData.SelectedSecCapability)
seppContext.Mu.Unlock()
}
startSBIServer(&wg, remoteURL, conf.SEPP.Local.SBI)
wg.Wait()
}

func exchangeCapability(remoteURL string, n32TLSConf config.TLS) {
func startN32Server(wg *sync.WaitGroup, n32Config config.N32) {
wg.Add(1)
go func() {
defer wg.Done()
n32.StartServer(n32Config.GetAddress(), n32Config.TLS.Cert, n32Config.TLS.Key, n32Config.TLS.CA, n32Config.FQDN)
}()
}

func startSBIServer(wg *sync.WaitGroup, remoteURL string, sbiConfig config.SBI) {
wg.Add(1)
go func() {
defer wg.Done()
sbi.StartServer(remoteURL, sbiConfig.GetAddress(), sbiConfig.TLS)
}()
}

func exchangeCapability(remoteURL string, fqdn string, securityCapability string, n32TLSConf config.TLS) (n32.SecNegotiateRspData, error) {
seppClient := n32.NewClient(n32TLSConf.Cert, n32TLSConf.Key, n32TLSConf.CA)
reqData := n32.SecNegotiateReqData{
Sender: n32.FQDN("testSender"),
SupportedSecCapabilityList: []n32.SecurityCapability{n32.TLS},
Sender: model.FQDN(fqdn),
SupportedSecCapabilityList: []model.SecurityCapability{model.SecurityCapability(securityCapability)},
}
for {
cap, err := seppClient.POSTExchangeCapability(remoteURL, reqData)
if err == nil && cap.SelectedSecCapability == n32.TLS {
log.Printf("Successfully exchanged capability: %s", cap.SelectedSecCapability)
break
}
if err != nil {
log.Printf("Failed to exchange capability: %s", err)
} else {
log.Printf("Failed to exchange capability: expected %s, got %s", n32.TLS, cap)
}
time.Sleep(30 * time.Second)
secNegotiateRspData, err := seppClient.POSTExchangeCapability(remoteURL, reqData)
if err != nil {
log.Printf("failed to exchange capability: %s", err)
return secNegotiateRspData, err
}
if secNegotiateRspData.SelectedSecCapability != model.TLS {
log.Printf("failed to exchange capability: expected %s, got %s", model.TLS, secNegotiateRspData)
return secNegotiateRspData, err
}
log.Printf("successfully exchanged capability %s with remote SEPP %s", secNegotiateRspData.SelectedSecCapability, remoteURL)
return secNegotiateRspData, nil
}
7 changes: 4 additions & 3 deletions config.yaml
Original file line number Diff line number Diff line change
@@ -1,23 +1,24 @@
sepp:
securityCapability: "TLS"
local:
n32:
fqdn: "local-sepp.example.com"
host: "localhost"
port: "1236"
port: "1238"
tls:
cert: "certs/n32Server.crt"
key: "certs/n32Server.key"
ca: "certs/ca.crt"
sbi:
fqdn: "local-sbi.example.com"
host: "localhost"
port: "1237"
port: "1239"
tls:
cert: "certs/sbiServer.crt"
key: "certs/sbiServer.key"
ca: "certs/ca.crt"
remote:
url: "https://127.0.0.1:1235"
url: "https://127.0.0.1:1236"
tls:
cert: "certs/client.crt"
key: "certs/client.key"
Expand Down
52 changes: 34 additions & 18 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,23 +27,34 @@ type SBI struct {
TLS TLS `yaml:"tls"`
}

type Local struct {
N32 N32 `yaml:"n32"`
SBI SBI `yaml:"sbi"`
}

type Remote struct {
URL string `yaml:"url"`
TLS TLS `yaml:"tls"`
}

type SEPP struct {
SecurityCapability string `yaml:"securityCapability"`
Local Local `yaml:"local"`
Remote Remote `yaml:"remote"`
}

type Config struct {
SEPP struct {
Local struct {
N32 N32 `yaml:"n32"`
SBI SBI `yaml:"sbi"`
} `yaml:"local"`
Remote struct {
URL string `yaml:"url"`
TLS TLS `yaml:"tls"`
} `yaml:"remote"`
} `yaml:"sepp"`
SEPP SEPP `yaml:"sepp"`
}

func (n32 N32) GetAddress() string {
return n32.Host + ":" + n32.Port
}

func (sbi SBI) GetAddress() string {
return sbi.Host + ":" + sbi.Port
}

func ReadConfig(reader io.Reader) (*Config, error) {
var config Config

Expand All @@ -65,41 +76,46 @@ func ReadConfig(reader io.Reader) (*Config, error) {
}

func validateConfig(config *Config) error {

if config.SEPP.SecurityCapability != "TLS" {
return fmt.Errorf("unsupported security capability, only TLS is supported")
}

if config.SEPP.Local.N32.FQDN == "" {
return fmt.Errorf("missing FQDN")
return fmt.Errorf("missing Local N32 FQDN")
}

if config.SEPP.Local.N32.Host == "" {
return fmt.Errorf("missing host")
return fmt.Errorf("missing Local N32 Host")
}

if config.SEPP.Local.N32.Port == "" {
return fmt.Errorf("missing port")
}

if config.SEPP.Local.N32.TLS.Cert == "" {
return fmt.Errorf("missing TLS cert")
return fmt.Errorf("missing Local N32 TLS Cert")
}

if config.SEPP.Local.N32.TLS.Key == "" {
return fmt.Errorf("missing TLS key")
return fmt.Errorf("missing Local N32 TLS Key")
}

if config.SEPP.Local.N32.TLS.CA == "" {
return fmt.Errorf("missing TLS CA")
return fmt.Errorf("missing Local N32 TLS CA")
}

if config.SEPP.Remote.URL != "" {
if config.SEPP.Remote.TLS.Cert == "" {
return fmt.Errorf("missing remote TLS cert")
return fmt.Errorf("missing Remote TLS Cert")
}

if config.SEPP.Remote.TLS.Key == "" {
return fmt.Errorf("missing remote TLS key")
return fmt.Errorf("missing Remote TLS Key")
}

if config.SEPP.Remote.TLS.CA == "" {
return fmt.Errorf("missing remote TLS CA")
return fmt.Errorf("missing Remote TLS CA")
}
}
return nil
Expand Down
16 changes: 8 additions & 8 deletions config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,12 @@ func TestConfig(t *testing.T) {
t.Errorf("Expected port '1234', got '%s'", conf.SEPP.Local.N32.Port)
}

if conf.SEPP.Local.N32.TLS.Cert != "/etc/sepp/certs/server.crt" {
t.Errorf("Expected TLS cert '/etc/sepp/certs/server.crt', got '%s'", conf.SEPP.Local.N32.TLS.Cert)
if conf.SEPP.Local.N32.TLS.Cert != "/etc/sepp/certs/n32Server.crt" {
t.Errorf("Expected TLS cert '/etc/sepp/certs/n32Server.crt', got '%s'", conf.SEPP.Local.N32.TLS.Cert)
}

if conf.SEPP.Local.N32.TLS.Key != "/etc/sepp/certs/server.key" {
t.Errorf("Expected TLS key '/etc/sepp/certs/server.key', got '%s'", conf.SEPP.Local.N32.TLS.Key)
if conf.SEPP.Local.N32.TLS.Key != "/etc/sepp/certs/n32Server.key" {
t.Errorf("Expected TLS key '/etc/sepp/certs/n32Server.key', got '%s'", conf.SEPP.Local.N32.TLS.Key)
}

if conf.SEPP.Local.N32.TLS.CA != "/etc/sepp/certs/ca.crt" {
Expand All @@ -51,12 +51,12 @@ func TestConfig(t *testing.T) {
t.Errorf("Expected port '1235', got '%s'", conf.SEPP.Local.SBI.Port)
}

if conf.SEPP.Local.SBI.TLS.Cert != "/etc/sepp/certs/server.crt" {
t.Errorf("Expected TLS cert '/etc/sepp/certs/server.crt', got '%s'", conf.SEPP.Local.SBI.TLS.Cert)
if conf.SEPP.Local.SBI.TLS.Cert != "/etc/sepp/certs/sbiServer.crt" {
t.Errorf("Expected TLS cert '/etc/sepp/certs/sbiServer.crt', got '%s'", conf.SEPP.Local.SBI.TLS.Cert)
}

if conf.SEPP.Local.SBI.TLS.Key != "/etc/sepp/certs/server.key" {
t.Errorf("Expected TLS key '/etc/sepp/certs/server.key', got '%s'", conf.SEPP.Local.SBI.TLS.Key)
if conf.SEPP.Local.SBI.TLS.Key != "/etc/sepp/certs/sbiServer.key" {
t.Errorf("Expected TLS key '/etc/sepp/certs/sbiServer.key', got '%s'", conf.SEPP.Local.SBI.TLS.Key)
}

if conf.SEPP.Local.SBI.TLS.CA != "/etc/sepp/certs/ca.crt" {
Expand Down
9 changes: 5 additions & 4 deletions config/config_test.yaml
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
sepp:
securityCapability: "TLS"
local:
n32:
fqdn: "local-sepp.example.com"
host: "localhost"
port: "1234"
tls:
cert: "/etc/sepp/certs/server.crt"
key: "/etc/sepp/certs/server.key"
cert: "/etc/sepp/certs/n32Server.crt"
key: "/etc/sepp/certs/n32Server.key"
ca: "/etc/sepp/certs/ca.crt"
sbi:
fqdn: "local-sbi.example.com"
host: "localhost"
port: "1235"
tls:
cert: "/etc/sepp/certs/server.crt"
key: "/etc/sepp/certs/server.key"
cert: "/etc/sepp/certs/sbiServer.crt"
key: "/etc/sepp/certs/sbiServer.key"
ca: "/etc/sepp/certs/ca.crt"
remote:
url: "https://remote-sepp.example.com"
Expand Down
19 changes: 19 additions & 0 deletions internal/model/model.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package model

import (
"sync"
)

type FQDN string

type SecurityCapability string

const TLS = SecurityCapability("TLS")
const ALS = SecurityCapability("ALS")

type SEPPContext struct {
LocalFQDN FQDN
RemoteFQDN FQDN
SecurityCapability SecurityCapability
Mu sync.Mutex
}
19 changes: 8 additions & 11 deletions internal/n32/post_exchange_capability.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,18 @@ import (
"log"
"net/http"
"slices"
)

type SecurityCapability string

const TLS = SecurityCapability("TLS")
const ALS = SecurityCapability("ALS")
"github.com/dot-5g/sepp/internal/model"
)

type SecNegotiateReqData struct {
Sender FQDN
SupportedSecCapabilityList []SecurityCapability
Sender model.FQDN
SupportedSecCapabilityList []model.SecurityCapability
}

type SecNegotiateRspData struct {
Sender FQDN
SelectedSecCapability SecurityCapability
Sender model.FQDN
SelectedSecCapability model.SecurityCapability
}

func (n32c *N32C) HandlePostExchangeCapability(w http.ResponseWriter, r *http.Request) {
Expand All @@ -43,7 +40,7 @@ func (n32c *N32C) HandlePostExchangeCapability(w http.ResponseWriter, r *http.Re
return
}

containsTLS := slices.Contains(reqData.SupportedSecCapabilityList, TLS)
containsTLS := slices.Contains(reqData.SupportedSecCapabilityList, model.TLS)
if !containsTLS {
http.Error(w, "Bad SecurityCapability - Only TLS is supported", http.StatusBadRequest)
log.Printf("Bad SecurityCapability - Only TLS is supported")
Expand All @@ -52,7 +49,7 @@ func (n32c *N32C) HandlePostExchangeCapability(w http.ResponseWriter, r *http.Re

rspData := SecNegotiateRspData{
Sender: n32c.FQDN,
SelectedSecCapability: TLS,
SelectedSecCapability: model.TLS,
}

w.Header().Set("Content-Type", "application/json")
Expand Down
Loading

0 comments on commit 16cddc4

Please sign in to comment.