157 lines
3.9 KiB
Go
157 lines
3.9 KiB
Go
package dht
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"chorus/pkg/config"
|
|
)
|
|
|
|
type securityTestCase struct {
|
|
name string
|
|
role string
|
|
address string
|
|
contentType string
|
|
expectSuccess bool
|
|
expectErrHint string
|
|
}
|
|
|
|
func newTestEncryptedStorage(cfg *config.Config) *EncryptedDHTStorage {
|
|
return &EncryptedDHTStorage{
|
|
ctx: context.Background(),
|
|
config: cfg,
|
|
nodeID: "test-node",
|
|
cache: make(map[string]*CachedEntry),
|
|
metrics: &StorageMetrics{LastUpdate: time.Now()},
|
|
}
|
|
}
|
|
|
|
func TestCheckStoreAccessPolicy(t *testing.T) {
|
|
cases := []securityTestCase{
|
|
{
|
|
name: "backend developer can store",
|
|
role: "backend_developer",
|
|
address: "agent1:backend_developer:api:endpoint",
|
|
contentType: "decision",
|
|
expectSuccess: true,
|
|
},
|
|
{
|
|
name: "project manager can store",
|
|
role: "project_manager",
|
|
address: "agent1:project_manager:plan:milestone",
|
|
contentType: "decision",
|
|
expectSuccess: true,
|
|
},
|
|
{
|
|
name: "read only user cannot store",
|
|
role: "readonly_user",
|
|
address: "agent1:readonly_user:note:observation",
|
|
contentType: "note",
|
|
expectSuccess: false,
|
|
expectErrHint: "read-only authority",
|
|
},
|
|
{
|
|
name: "unknown role rejected",
|
|
role: "ghost_role",
|
|
address: "agent1:ghost_role:context",
|
|
contentType: "decision",
|
|
expectSuccess: false,
|
|
expectErrHint: "unknown creator role",
|
|
},
|
|
}
|
|
|
|
cfg := &config.Config{Agent: config.AgentConfig{}}
|
|
eds := newTestEncryptedStorage(cfg)
|
|
|
|
for _, tc := range cases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
err := eds.checkStoreAccessPolicy(tc.role, tc.address, tc.contentType)
|
|
verifySecurityExpectation(t, tc.expectSuccess, tc.expectErrHint, err)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestCheckRetrieveAccessPolicy(t *testing.T) {
|
|
cases := []securityTestCase{
|
|
{
|
|
name: "qa engineer allowed",
|
|
role: "qa_engineer",
|
|
address: "agent1:backend_developer:api:tests",
|
|
expectSuccess: true,
|
|
},
|
|
{
|
|
name: "unknown role rejected",
|
|
role: "unknown",
|
|
address: "agent1:backend_developer:api:tests",
|
|
expectSuccess: false,
|
|
expectErrHint: "unknown current role",
|
|
},
|
|
}
|
|
|
|
cfg := &config.Config{Agent: config.AgentConfig{}}
|
|
eds := newTestEncryptedStorage(cfg)
|
|
|
|
for _, tc := range cases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
err := eds.checkRetrieveAccessPolicy(tc.role, tc.address)
|
|
verifySecurityExpectation(t, tc.expectSuccess, tc.expectErrHint, err)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestCheckAnnounceAccessPolicy(t *testing.T) {
|
|
cases := []securityTestCase{
|
|
{
|
|
name: "architect can announce",
|
|
role: "senior_software_architect",
|
|
address: "agent1:senior_software_architect:architecture:proposal",
|
|
expectSuccess: true,
|
|
},
|
|
{
|
|
name: "suggestion role cannot announce",
|
|
role: "suggestion_only_role",
|
|
address: "agent1:suggestion_only_role:idea",
|
|
expectSuccess: false,
|
|
expectErrHint: "lacks authority",
|
|
},
|
|
{
|
|
name: "unknown role rejected",
|
|
role: "mystery",
|
|
address: "agent1:mystery:topic",
|
|
expectSuccess: false,
|
|
expectErrHint: "unknown current role",
|
|
},
|
|
}
|
|
|
|
cfg := &config.Config{Agent: config.AgentConfig{}}
|
|
eds := newTestEncryptedStorage(cfg)
|
|
|
|
for _, tc := range cases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
err := eds.checkAnnounceAccessPolicy(tc.role, tc.address)
|
|
verifySecurityExpectation(t, tc.expectSuccess, tc.expectErrHint, err)
|
|
})
|
|
}
|
|
}
|
|
|
|
func verifySecurityExpectation(t *testing.T, expectSuccess bool, hint string, err error) {
|
|
t.Helper()
|
|
|
|
if expectSuccess {
|
|
if err != nil {
|
|
t.Fatalf("expected success, got error: %v", err)
|
|
}
|
|
return
|
|
}
|
|
|
|
if err == nil {
|
|
t.Fatal("expected error but got success")
|
|
}
|
|
|
|
if hint != "" && !strings.Contains(err.Error(), hint) {
|
|
t.Fatalf("expected error to contain %q, got %q", hint, err.Error())
|
|
}
|
|
}
|