121 lines
3.8 KiB
Go
121 lines
3.8 KiB
Go
package vaultwarden
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestNewClient_withState(t *testing.T) {
|
|
items := map[string]DecryptedItem{
|
|
"c1": {ID: "c1", Name: "db-password", Password: "pw"},
|
|
}
|
|
nameMaps := SyncNameMaps{
|
|
Organizations: map[string]string{testOrgID: "Acme"},
|
|
Folders: map[string]string{},
|
|
Collections: map[string]string{},
|
|
}
|
|
|
|
c := NewClient(nil, 0, 0, WithState(items, nameMaps))
|
|
|
|
val, err := c.GetSecret("db-password", SecretFilter{})
|
|
if err != nil || val != "pw" {
|
|
t.Fatalf("GetSecret() = (%q, %v), want (pw, nil)", val, err)
|
|
}
|
|
if got := c.NameMaps().Organizations[testOrgID]; got != "Acme" {
|
|
t.Errorf("NameMaps org = %q, want Acme", got)
|
|
}
|
|
}
|
|
|
|
func TestMatchesSecretFilter(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
base := DecryptedItem{
|
|
ID: "item-1",
|
|
OrganizationID: testOrgID,
|
|
CollectionIDs: []string{testCollectionID, "66666666-6666-4666-8666-666666666666"},
|
|
FolderID: testFolderID,
|
|
}
|
|
|
|
tests := []struct {
|
|
name string
|
|
filter SecretFilter
|
|
want bool
|
|
}{
|
|
{"empty filter", SecretFilter{}, true},
|
|
{"org match", SecretFilter{OrganizationID: testOrgID}, true},
|
|
{"org case insensitive", SecretFilter{OrganizationID: strings.ToUpper(testOrgID)}, true},
|
|
{"org mismatch", SecretFilter{OrganizationID: testOrgID2}, false},
|
|
{"collection match", SecretFilter{CollectionID: testCollectionID}, true},
|
|
{"collection case insensitive", SecretFilter{CollectionID: strings.ToUpper(testCollectionID)}, true},
|
|
{"collection missing", SecretFilter{CollectionID: "77777777-7777-4777-8777-777777777777"}, false},
|
|
{"folder match", SecretFilter{FolderID: testFolderID}, true},
|
|
{"folder mismatch", SecretFilter{FolderID: "88888888-8888-4888-8888-888888888888"}, false},
|
|
{
|
|
"all dimensions match",
|
|
SecretFilter{
|
|
OrganizationID: testOrgID,
|
|
CollectionID: testCollectionID,
|
|
FolderID: testFolderID,
|
|
},
|
|
true,
|
|
},
|
|
{
|
|
"org ok collection fail",
|
|
SecretFilter{OrganizationID: testOrgID, CollectionID: "77777777-7777-4777-8777-777777777777"},
|
|
false,
|
|
},
|
|
// Server-side scope (plural fields).
|
|
{"scope org in set", SecretFilter{OrganizationIDs: []string{testOrgID2, testOrgID}}, true},
|
|
{"scope org not in set", SecretFilter{OrganizationIDs: []string{testOrgID2}}, false},
|
|
{"scope collection intersects", SecretFilter{CollectionIDs: []string{testCollectionID}}, true},
|
|
{
|
|
"scope collection disjoint",
|
|
SecretFilter{CollectionIDs: []string{"77777777-7777-4777-8777-777777777777"}},
|
|
false,
|
|
},
|
|
{
|
|
"scope org and collection both match",
|
|
SecretFilter{OrganizationIDs: []string{testOrgID}, CollectionIDs: []string{testCollectionID}},
|
|
true,
|
|
},
|
|
{
|
|
"scope org ok but collection disjoint",
|
|
SecretFilter{OrganizationIDs: []string{testOrgID}, CollectionIDs: []string{"77777777-7777-4777-8777-777777777777"}},
|
|
false,
|
|
},
|
|
{
|
|
"scope narrowed further by client filter",
|
|
SecretFilter{OrganizationID: testOrgID, OrganizationIDs: []string{testOrgID}},
|
|
true,
|
|
},
|
|
{
|
|
"client filter cannot widen beyond scope",
|
|
SecretFilter{OrganizationID: testOrgID, OrganizationIDs: []string{testOrgID2}},
|
|
false,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
if got := matchesSecretFilter(base, tt.filter); got != tt.want {
|
|
t.Errorf("matchesSecretFilter() = %v, want %v", got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestMatchesSecretFilter_PersonalItemExcludedByOrgScope(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
// A personal (no-org) item must be excluded once a key scopes to organizations.
|
|
personal := DecryptedItem{ID: "personal-1", Name: "personal-secret"}
|
|
|
|
if matchesSecretFilter(personal, SecretFilter{OrganizationIDs: []string{testOrgID}}) {
|
|
t.Error("personal item should be excluded by an org scope")
|
|
}
|
|
if !matchesSecretFilter(personal, SecretFilter{}) {
|
|
t.Error("personal item should match an empty (full-access) scope")
|
|
}
|
|
}
|