85 lines
2.5 KiB
Go
85 lines
2.5 KiB
Go
package identity
|
|
|
|
import (
|
|
"bytes"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"remlink/internal/model"
|
|
)
|
|
|
|
type testProtector struct{}
|
|
|
|
func (testProtector) Protect(value []byte) ([]byte, error) {
|
|
result := append([]byte("protected:"), value...)
|
|
for left, right := 0, len(result)-1; left < right; left, right = left+1, right-1 {
|
|
result[left], result[right] = result[right], result[left]
|
|
}
|
|
return result, nil
|
|
}
|
|
|
|
func (testProtector) Unprotect(value []byte) ([]byte, error) {
|
|
result := append([]byte(nil), value...)
|
|
for left, right := 0, len(result)-1; left < right; left, right = left+1, right-1 {
|
|
result[left], result[right] = result[right], result[left]
|
|
}
|
|
return bytes.TrimPrefix(result, []byte("protected:")), nil
|
|
}
|
|
|
|
func TestIdentityRoundTripWithoutPlaintextSecrets(t *testing.T) {
|
|
path := filepath.Join(t.TempDir(), "Engineer", "identity.json")
|
|
store, err := NewStore(path, testProtector{})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
value, err := New(model.NodeTypeEngineer, "Engineer-A", "http://203.0.113.1:8080/")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
value.NodeToken = "plain-node-token-that-must-not-appear"
|
|
value.ConfigVersion = 7
|
|
value.OwnedRoutes = []string{"192.168.13.0/24"}
|
|
if err := store.Save(value); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
raw, err := os.ReadFile(path)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if bytes.Contains(raw, []byte(value.NodeToken)) || bytes.Contains(raw, []byte(value.PrivateKey.String())) {
|
|
t.Fatalf("identity file contains a plaintext secret: %s", raw)
|
|
}
|
|
loaded, err := store.Load()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if loaded.NodeID != value.NodeID || loaded.PrivateKey != value.PrivateKey || loaded.NodeToken != value.NodeToken ||
|
|
loaded.ConfigVersion != 7 || len(loaded.OwnedRoutes) != 1 {
|
|
t.Fatalf("loaded identity differs: %+v", loaded)
|
|
}
|
|
|
|
value.NodeName = "Engineer-Renamed"
|
|
if err := store.Save(value); err != nil {
|
|
t.Fatalf("replace identity: %v", err)
|
|
}
|
|
loaded, err = store.Load()
|
|
if err != nil || loaded.NodeName != value.NodeName {
|
|
t.Fatalf("replaced identity = %+v, %v", loaded, err)
|
|
}
|
|
}
|
|
|
|
func TestIdentityValidation(t *testing.T) {
|
|
if _, err := New(model.NodeType("server"), "x", "http://example.test"); err == nil {
|
|
t.Fatal("invalid Node type accepted")
|
|
}
|
|
if _, err := New(model.NodeTypeSite, "x", "not-a-url"); err == nil {
|
|
t.Fatal("invalid Server URL accepted")
|
|
}
|
|
for _, raw := range []string{"http://user:secret@example.test", "http://example.test/api", "http://example.test?redirect=elsewhere"} {
|
|
if _, err := New(model.NodeTypeSite, "x", raw); err == nil {
|
|
t.Errorf("unsafe Server URL %q accepted", raw)
|
|
}
|
|
}
|
|
}
|