mirror of
https://github.com/hashicorp/vault.git
synced 2026-05-05 04:16:31 +02:00
also flush nilNamespace when a namespace is flushed in the identity/oidc backend (#7203)
* also flush nilNamespace when a namespace is flushed * adds test cases with nilNamespace.ID * adds a test case * adds a test for oidcCache.Flush * fixed a typo in an error message
This commit is contained in:
parent
d177fc7dd1
commit
5a24bbb138
@ -1564,14 +1564,15 @@ func (c *oidcCache) SetDefault(ns *namespace.Namespace, key string, obj interfac
|
||||
|
||||
func (c *oidcCache) Flush(ns *namespace.Namespace) {
|
||||
for itemKey := range c.c.Items() {
|
||||
if isNamespacedKey(itemKey, ns.ID) {
|
||||
if isTargetNamespacedKey(itemKey, []string{nilNamespace.ID, ns.ID}) {
|
||||
c.c.Delete(itemKey)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// isNamespacedKey returns true for a properly constructed namespaced key (<version>:<nsID>:<key>) where <nsID> is nsID
|
||||
func isNamespacedKey(nskey, nsID string) bool {
|
||||
// isTargetNamespacedKey returns true for a properly constructed namespaced key (<version>:<nsID>:<key>)
|
||||
// where <nsID> matches any targeted nsID
|
||||
func isTargetNamespacedKey(nskey string, nsTargets []string) bool {
|
||||
split := strings.Split(nskey, ":")
|
||||
return len(split) >= 3 && split[1] == nsID
|
||||
return len(split) >= 3 && strutil.StrListContains(nsTargets, split[1])
|
||||
}
|
||||
|
||||
@ -14,6 +14,7 @@ import (
|
||||
"github.com/hashicorp/vault/helper/namespace"
|
||||
"github.com/hashicorp/vault/sdk/framework"
|
||||
"github.com/hashicorp/vault/sdk/logical"
|
||||
gocache "github.com/patrickmn/go-cache"
|
||||
"gopkg.in/square/go-jose.v2"
|
||||
"gopkg.in/square/go-jose.v2/jwt"
|
||||
)
|
||||
@ -971,36 +972,97 @@ func TestOIDC_Path_Introspect(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestOIDC_isNamespacedKey(t *testing.T) {
|
||||
func TestOIDC_isTargetNamespacedKey(t *testing.T) {
|
||||
tests := []struct {
|
||||
nsid string
|
||||
nskey string
|
||||
expected bool
|
||||
nsTargets []string
|
||||
nskey string
|
||||
expected bool
|
||||
}{
|
||||
{"nsid", "v0:nsid:key", true},
|
||||
{"nsid", "v0:nsid:", true},
|
||||
{"nsid", "v0:nsid", false},
|
||||
{"nsid", "v0:", false},
|
||||
{"nsid", "v0", false},
|
||||
{"nsid", "", false},
|
||||
{"nsid1", "v0:nsid2:key", false},
|
||||
{"nsid1", "nsid1:nsid2:nsid1", false},
|
||||
{"nsid1", "nsid1:nsid1:nsid1", true},
|
||||
{"nsid", "nsid:nsid:nsid:nsid:nsid:nsid", true},
|
||||
{"nsid", ":::", false},
|
||||
{"", ":::", true}, // "" is a valid key for cache.Set/Get
|
||||
{"nsid1", "nsid0:nsid1:nsid0:nsid1:nsid0:nsid1", true},
|
||||
{"nsid0", "nsid0:nsid1:nsid0:nsid1:nsid0:nsid1", false},
|
||||
{[]string{"nsid"}, "v0:nsid:key", true},
|
||||
{[]string{"nsid"}, "v0:nsid:", true},
|
||||
{[]string{"nsid"}, "v0:nsid", false},
|
||||
{[]string{"nsid"}, "v0:", false},
|
||||
{[]string{"nsid"}, "v0", false},
|
||||
{[]string{"nsid"}, "", false},
|
||||
{[]string{"nsid1"}, "v0:nsid2:key", false},
|
||||
{[]string{"nsid1"}, "nsid1:nsid2:nsid1", false},
|
||||
{[]string{"nsid1"}, "nsid1:nsid1:nsid1", true},
|
||||
{[]string{"nsid"}, "nsid:nsid:nsid:nsid:nsid:nsid", true},
|
||||
{[]string{"nsid"}, ":::", false},
|
||||
{[]string{""}, ":::", true}, // "" is a valid key for cache.Set/Get
|
||||
{[]string{"nsid1"}, "nsid0:nsid1:nsid0:nsid1:nsid0:nsid1", true},
|
||||
{[]string{"nsid0"}, "nsid0:nsid1:nsid0:nsid1:nsid0:nsid1", false},
|
||||
{[]string{"nsid0", "nsid1"}, "v0:nsid2:key", false},
|
||||
{[]string{"nsid0", "nsid1", "nsid2", "nsid3", "nsid4"}, "v0:nsid3:key", true},
|
||||
{[]string{"nsid0", "nsid1", "nsid2", "nsid3", "nsid4"}, "nsid0:nsid1:nsid2:nsid3:nsid4:nsid5", true},
|
||||
{[]string{"nsid0", "nsid1", "nsid2", "nsid3", "nsid4"}, "nsid4:nsid5:nsid6:nsid7:nsid8:nsid9", false},
|
||||
{[]string{"nsid0", "nsid0", "nsid0", "nsid0", "nsid0"}, "nsid0:nsid0:nsid0:nsid0:nsid0:nsid0", true},
|
||||
{[]string{"nsid1", "nsid1", "nsid2", "nsid2"}, "nsid0:nsid0:nsid0:nsid0:nsid0:nsid0", false},
|
||||
{[]string{"nsid1", "nsid1", "nsid2", "nsid2"}, "nsid0:nsid0:nsid0:nsid0:nsid0:nsid0", false},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
actual := isNamespacedKey(test.nskey, test.nsid)
|
||||
actual := isTargetNamespacedKey(test.nskey, test.nsTargets)
|
||||
if test.expected != actual {
|
||||
t.Fatalf("expected %t but got %t for nsid: %q and nskey: %q", test.expected, actual, test.nsid, test.nskey)
|
||||
t.Fatalf("expected %t but got %t for nstargets: %q and nskey: %q", test.expected, actual, test.nsTargets, test.nskey)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestOIDC_Flush(t *testing.T) {
|
||||
c := newOIDCCache()
|
||||
ns := []*namespace.Namespace{
|
||||
nilNamespace, //ns[0] is nilNamespace
|
||||
&namespace.Namespace{ID: "ns1"},
|
||||
&namespace.Namespace{ID: "ns2"},
|
||||
}
|
||||
|
||||
// populateNs populates cache by ns with some data
|
||||
populateNs := func() {
|
||||
for i := range ns {
|
||||
for _, val := range []string{"keyA", "keyB", "keyC"} {
|
||||
c.SetDefault(ns[i], val, struct{}{})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// validate verifies that cache items exist or do not exist based on their namespaced key
|
||||
verify := func(items map[string]gocache.Item, expect, doNotExpect []*namespace.Namespace) {
|
||||
for _, expectNs := range expect {
|
||||
found := false
|
||||
for i := range items {
|
||||
if isTargetNamespacedKey(i, []string{expectNs.ID}) {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
t.Fatalf("Expected cache to contain an entry with a namespaced key for namespace: %q but did not find one", expectNs.ID)
|
||||
}
|
||||
}
|
||||
|
||||
for _, doNotExpectNs := range doNotExpect {
|
||||
for i := range items {
|
||||
if isTargetNamespacedKey(i, []string{doNotExpectNs.ID}) {
|
||||
t.Fatalf("Did not expect cache to contain an entry with a namespaced key for namespace: %q but found the key: %q", doNotExpectNs.ID, i)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// flushing ns1 should flush ns1 and nilNamespace but not ns2
|
||||
populateNs()
|
||||
c.Flush(ns[1])
|
||||
items := c.c.Items()
|
||||
verify(items, []*namespace.Namespace{ns[2]}, []*namespace.Namespace{ns[0], ns[1]})
|
||||
|
||||
// flushing nilNamespace should flush nilNamespace but not ns1 or ns2
|
||||
populateNs()
|
||||
c.Flush(ns[0])
|
||||
items = c.c.Items()
|
||||
verify(items, []*namespace.Namespace{ns[1], ns[2]}, []*namespace.Namespace{ns[0]})
|
||||
}
|
||||
|
||||
// some helpers
|
||||
func expectSuccess(t *testing.T, resp *logical.Response, err error) {
|
||||
t.Helper()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user