Files
go-sip/internal/asterisk/loader_test.go
T

101 lines
3.6 KiB
Go

package asterisk
import (
"context"
"encoding/json"
"os"
"path/filepath"
"strings"
"testing"
)
func TestLoaderPersistsOnlyVerifiedNativeReload(t *testing.T) {
dir := t.TempDir()
if err := os.WriteFile(filepath.Join(dir, "pjsip.conf"), []byte("[go-sip-udp]\ntype=transport\nprotocol=udp\nbind=0.0.0.0:5060\n#tryinclude go-sip-managed.conf\n"), 0600); err != nil {
t.Fatal(err)
}
fake := filepath.Join(dir, "asterisk")
script := `#!/bin/sh
case "$*" in
*"pjsip show transports"*) echo 'Transport: go-sip-udp udp 0 0 0.0.0.0:5060' ;;
*"pjsip show endpoints"*) echo 'Endpoint: <Endpoint/CID> <State> <Channels>'; echo 'Endpoint: trunk-shuqi Not in use' ;;
*"pjsip show endpoint trunk-shuqi"*) echo 'Aor: trunk-shuqi-aor allow: alaw transport: go-sip-udp context: go-sip-no-inbound' ;;
*"pjsip show aor trunk-shuqi-aor"*) echo 'Contact: sip:61.132.228.221:5060' ;;
*) exit 9 ;;
esac
`
if err := os.WriteFile(fake, []byte(script), 0700); err != nil {
t.Fatal(err)
}
bin := filepath.Join(dir, "bin")
if err := os.Mkdir(bin, 0700); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(filepath.Join(bin, "systemctl"), []byte("#!/bin/sh\n[ \"$*\" = '--user reload go-sip-asterisk.service' ]\n"), 0700); err != nil {
t.Fatal(err)
}
t.Setenv("PATH", bin+":"+os.Getenv("PATH"))
loader := Loader{ConfigDir: dir, Asterisk: fake, LibraryDir: dir}
sip := testSIP(t)
body, err := json.Marshal(sip)
if err != nil {
t.Fatal(err)
}
// Recover an interrupted first apply only when the approved file and
// native PJSIP objects both agree with the complete snapshot.
rendered, err := Render(sip)
if err != nil {
t.Fatal(err)
}
if err := os.WriteFile(filepath.Join(dir, "go-sip-managed.conf"), []byte(rendered), 0600); err != nil {
t.Fatal(err)
}
loaded, err := loader.Apply(context.Background(), body)
if err != nil || loaded["trunk-shuqi"] != 9 {
t.Fatalf("real command path did not verify SIP revision: %v %v", loaded, err)
}
if _, err := loader.Apply(context.Background(), body); err != nil {
t.Fatalf("same revision should observe without rewriting: %v", err)
}
if err := os.WriteFile(fake, []byte(strings.Replace(script, "Transport: go-sip-udp udp", "Transport: go-sip-udp tcp", 1)), 0700); err != nil {
t.Fatal(err)
}
if _, err := loader.LoadedSIP(context.Background()); err == nil {
t.Fatal("accepted native TCP transport as approved UDP")
}
if err := os.WriteFile(fake, []byte(script), 0700); err != nil {
t.Fatal(err)
}
changed := testSIP(t)
changed.Trunks = []byte(strings.Replace(string(changed.Trunks), "BD93205882", "BD93205883", 1))
changedBody, err := json.Marshal(changed)
if err != nil {
t.Fatal(err)
}
if _, err := loader.Apply(context.Background(), changedBody); err == nil {
t.Fatal("same revision changed non-rendered caller authorization")
}
p := filepath.Join(dir, "go-sip-managed.conf")
if err := os.WriteFile(p, []byte("[tampered]"), 0600); err != nil {
t.Fatal(err)
}
if _, err := loader.LoadedSIP(context.Background()); err == nil || !strings.Contains(err.Error(), "no longer matches") {
t.Fatalf("tampered config was accepted: %v", err)
}
}
func TestLoaderFailsClosedWithoutApprovedStaticTransport(t *testing.T) {
dir := t.TempDir()
loader := Loader{ConfigDir: dir, Asterisk: "/bin/true", LibraryDir: dir}
body, err := json.Marshal(testSIP(t))
if err != nil {
t.Fatal(err)
}
if _, err := loader.Apply(context.Background(), body); err == nil {
t.Fatal("applied SIP without management-owned base transport")
}
if _, err := os.Stat(filepath.Join(dir, "go-sip-managed.conf")); !os.IsNotExist(err) {
t.Fatalf("mutated disk before static transport check: %v", err)
}
}