160 lines
4.6 KiB
Go
160 lines
4.6 KiB
Go
package restrict
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
|
|
"git.yeij.top/AskaEth/Cyrene_v2/internal/capability/registry"
|
|
)
|
|
|
|
// toolStub is a mock Tool used only to register a capability by name.
|
|
type toolStub struct{ name string }
|
|
|
|
func (t toolStub) Name() string { return t.name }
|
|
func (t toolStub) Description() string { return "desc " + t.name }
|
|
func (t toolStub) Parameters() (map[string]any, error) { return map[string]any{}, nil }
|
|
func (t toolStub) Execute(_ context.Context, _ any) (any, error) { return nil, nil }
|
|
|
|
func mustRegTool(t *testing.T, r *registry.Registry, name string) {
|
|
t.Helper()
|
|
if err := r.RegisterTool(toolStub{name: name}); err != nil {
|
|
t.Fatalf("RegisterTool(%s): %v", name, err)
|
|
}
|
|
}
|
|
|
|
func TestSetContext_OwnerAllowsAll(t *testing.T) {
|
|
t.Parallel()
|
|
r := registry.New()
|
|
mustRegTool(t, r, "calc")
|
|
p := SetContext(r, ActorOwner)
|
|
if !p.Allow("calc") {
|
|
t.Fatal("owner should allow an owner-only tool")
|
|
}
|
|
if !p.Allow("missing") {
|
|
t.Fatal("owner should allow a tool that is not registered")
|
|
}
|
|
}
|
|
|
|
func TestAllow_GroupAndStrangerMarkers(t *testing.T) {
|
|
t.Parallel()
|
|
r := registry.New()
|
|
mustRegTool(t, r, "groupOnly")
|
|
mustRegTool(t, r, "strangerOnly")
|
|
mustRegTool(t, r, "both")
|
|
mustRegTool(t, r, "ownerOnly")
|
|
if err := r.SetPolicy("groupOnly", registry.ToolPolicy{AllowInGroup: true}); err != nil {
|
|
t.Fatalf("SetPolicy groupOnly: %v", err)
|
|
}
|
|
if err := r.SetPolicy("strangerOnly", registry.ToolPolicy{AllowInStranger: true}); err != nil {
|
|
t.Fatalf("SetPolicy strangerOnly: %v", err)
|
|
}
|
|
if err := r.SetPolicy("both", registry.ToolPolicy{AllowInGroup: true, AllowInStranger: true}); err != nil {
|
|
t.Fatalf("SetPolicy both: %v", err)
|
|
}
|
|
|
|
group := SetContext(r, ActorGroupMember)
|
|
stranger := SetContext(r, ActorStranger)
|
|
|
|
if !group.Allow("groupOnly") || !group.Allow("both") {
|
|
t.Fatal("group member should be allowed groupOnly and both")
|
|
}
|
|
if group.Allow("strangerOnly") {
|
|
t.Fatal("group member should be denied strangerOnly")
|
|
}
|
|
if group.Allow("ownerOnly") {
|
|
t.Fatal("group member should be denied ownerOnly")
|
|
}
|
|
|
|
if !stranger.Allow("strangerOnly") || !stranger.Allow("both") {
|
|
t.Fatal("stranger should be allowed strangerOnly and both")
|
|
}
|
|
if stranger.Allow("groupOnly") {
|
|
t.Fatal("stranger should be denied groupOnly")
|
|
}
|
|
if stranger.Allow("ownerOnly") {
|
|
t.Fatal("stranger should be denied ownerOnly")
|
|
}
|
|
}
|
|
|
|
func TestAllow_FailClosed(t *testing.T) {
|
|
t.Parallel()
|
|
// A nil registry denies every tool in a non-owner environment.
|
|
if p := SetContext(nil, ActorStranger); p.Allow("x") {
|
|
t.Fatal("nil reg should deny in stranger env")
|
|
}
|
|
if p := SetContext(nil, ActorGroupMember); p.Allow("x") {
|
|
t.Fatal("nil reg should deny in group env")
|
|
}
|
|
|
|
r := registry.New()
|
|
mustRegTool(t, r, "t")
|
|
|
|
// An unknown environment denies even a registered tool.
|
|
if p := SetContext(r, ActorEnv("bogus")); p.Allow("t") {
|
|
t.Fatal("unknown env should deny")
|
|
}
|
|
// An unregistered tool denies.
|
|
if p := SetContext(r, ActorGroupMember); p.Allow("unknown") {
|
|
t.Fatal("unknown tool should deny")
|
|
}
|
|
// A nil Policy receiver denies.
|
|
var nilPolicy *Policy
|
|
if nilPolicy.Allow("t") {
|
|
t.Fatal("nil Policy receiver should deny")
|
|
}
|
|
}
|
|
|
|
func TestDeny_IsInverse(t *testing.T) {
|
|
t.Parallel()
|
|
r := registry.New()
|
|
mustRegTool(t, r, "yes")
|
|
if err := r.SetAllowInGroup("yes", true); err != nil {
|
|
t.Fatalf("SetAllowInGroup: %v", err)
|
|
}
|
|
mustRegTool(t, r, "no")
|
|
|
|
p := SetContext(r, ActorGroupMember)
|
|
if p.Allow("yes") != !p.Deny("yes") {
|
|
t.Fatal("Allow and Deny are not inverses for an allowed tool")
|
|
}
|
|
if !p.Deny("no") {
|
|
t.Fatal("Deny(no) should be true because no is owner-only")
|
|
}
|
|
}
|
|
|
|
func TestActorEnv_Valid(t *testing.T) {
|
|
t.Parallel()
|
|
for _, env := range []ActorEnv{ActorOwner, ActorGroupMember, ActorStranger} {
|
|
if !env.Valid() {
|
|
t.Fatalf("%q should be valid", env)
|
|
}
|
|
}
|
|
if ActorEnv("bogus").Valid() {
|
|
t.Fatal("bogus env should be invalid")
|
|
}
|
|
}
|
|
|
|
func TestPolicy_EnvAndWithLogger(t *testing.T) {
|
|
t.Parallel()
|
|
r := registry.New()
|
|
mustRegTool(t, r, "t")
|
|
|
|
p := SetContext(r, ActorStranger)
|
|
if p.Env() != ActorStranger {
|
|
t.Fatalf("Env() = %q, want stranger", p.Env())
|
|
}
|
|
// WithLogger returns a copy and leaves the original unflagged, so the
|
|
// original's discarding logger still admits no output.
|
|
cp := p.WithLogger(nil)
|
|
if cp == nil {
|
|
t.Fatal("WithLogger(nil) returned nil")
|
|
}
|
|
if cp.Env() != ActorStranger {
|
|
t.Fatalf("copy Env() = %q, want stranger", cp.Env())
|
|
}
|
|
// The copy still denies and reports the same decision.
|
|
if cp.Allow("t") {
|
|
t.Fatal("stranger t should be denied without allow_in_stranger")
|
|
}
|
|
}
|