101 lines
3.6 KiB
Go
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)
|
|
}
|
|
}
|