command_test.go 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. package cli
  2. import (
  3. "path/filepath"
  4. "reflect"
  5. "strings"
  6. "testing"
  7. "proxmox-router/internal/aerotun"
  8. "proxmox-router/internal/auth"
  9. "proxmox-router/internal/vpn"
  10. )
  11. func TestQuotedCommandArguments(t *testing.T) {
  12. got, err := splitCommand(`/interface aerotun set test comment="office uplink" psk='literal $\\key' name=""`)
  13. want := []string{"/interface", "aerotun", "set", "test", "comment=office uplink", `psk=literal $\\key`, "name="}
  14. if err != nil || !reflect.DeepEqual(got, want) {
  15. t.Fatalf("%q %v", got, err)
  16. }
  17. if _, err := splitCommand(`comment="unfinished`); err == nil {
  18. t.Fatal("accepted unterminated quote")
  19. }
  20. }
  21. func TestBareLogAndHandlerRecovery(t *testing.T) {
  22. e := &Executor{}
  23. user := &auth.PublicUser{Role: auth.RoleFull}
  24. output, _ := e.Execute("/log", user)
  25. if commandExitStatus(output) != 0 {
  26. t.Fatal(output)
  27. }
  28. output, _ = e.Execute("/interface print", user) // absent manager simulates a handler failure
  29. if commandExitStatus(output) == 0 || !strings.Contains(output, "still running") {
  30. t.Fatal(output)
  31. }
  32. output, _ = e.Execute("nonsense", user)
  33. if commandExitStatus(output) == 0 {
  34. t.Fatal("unknown command returned success")
  35. }
  36. output, _ = e.Execute("/help", user)
  37. if commandExitStatus(output) != 0 {
  38. t.Fatal("help returned failure")
  39. }
  40. }
  41. func TestAeroTUNCLIConfigurationAndPermissions(t *testing.T) {
  42. m := aerotun.NewManagerWithPath(filepath.Join(t.TempDir(), "aerotun.json"))
  43. defer m.StopAll()
  44. e := &Executor{vpnMgr: &vpn.Manager{AeroTUN: m}}
  45. admin := &auth.PublicUser{Role: auth.RoleFull}
  46. psk := strings.Repeat("12", 32)
  47. command := `/interface aerotun add name=atest mode=server local-address=10.90.0.1/30 peer-address=10.90.0.2/32 allowed-ips=10.90.0.2/32 psk=` + psk + ` comment="office uplink"`
  48. output, _ := e.Execute(command, admin)
  49. if commandExitStatus(output) != 0 {
  50. t.Fatal(output)
  51. }
  52. inst := m.List()[0]
  53. if !inst.Disabled || inst.PublicKey == "" || inst.Comment != "office uplink" {
  54. t.Fatal("draft configuration not retained")
  55. }
  56. for _, role := range []auth.Role{auth.RoleRead, auth.RoleWrite} {
  57. output, _ = e.Execute("/interface aerotun remove atest", &auth.PublicUser{Role: role})
  58. if commandExitStatus(output) == 0 {
  59. t.Fatal("non-admin removed tunnel")
  60. }
  61. }
  62. output, _ = e.Execute("/interface aerotun print detail=yes", admin)
  63. if strings.Contains(output, psk) || strings.Contains(output, inst.PrivateKey) || !strings.Contains(output, inst.PublicKey) {
  64. t.Fatal("secret disclosure or missing public identity")
  65. }
  66. output, _ = e.Execute(`/interface aerotun set atest comment="updated uplink"`, admin)
  67. if commandExitStatus(output) != 0 {
  68. t.Fatal(output)
  69. }
  70. updated, _ := m.Get(inst.ID)
  71. if updated.PSK != psk || updated.PublicKey != inst.PublicKey {
  72. t.Fatal("edit changed identity")
  73. }
  74. output, _ = e.Execute("/interface aerotun remove atest", admin)
  75. if commandExitStatus(output) != 0 || len(m.List()) != 0 {
  76. t.Fatal(output)
  77. }
  78. }