unistore: check namespace (#102020)
* check namespace in unistore * fix tests * fix trace status * Use capital letter --------- Co-authored-by: Karl Persson <23356117+kalleep@users.noreply.github.com>
This commit is contained in:
co-authored by
Karl Persson
parent
00d9916113
commit
1f637d07eb
@@ -5,9 +5,12 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
authlib "github.com/grafana/authlib/types"
|
||||
"github.com/grafana/grafana/pkg/apimachinery/identity"
|
||||
"github.com/grafana/grafana/pkg/apimachinery/utils"
|
||||
"github.com/grafana/grafana/pkg/services/authn/grpcutils"
|
||||
)
|
||||
|
||||
func TestAuthzLimitedClient_Check(t *testing.T) {
|
||||
@@ -26,11 +29,12 @@ func TestAuthzLimitedClient_Check(t *testing.T) {
|
||||
|
||||
for _, test := range tests {
|
||||
req := authlib.CheckRequest{
|
||||
Group: test.group,
|
||||
Resource: test.resource,
|
||||
Verb: utils.VerbGet,
|
||||
Group: test.group,
|
||||
Resource: test.resource,
|
||||
Verb: utils.VerbGet,
|
||||
Namespace: "stacks-1",
|
||||
}
|
||||
resp, err := client.Check(context.Background(), nil, req)
|
||||
resp, err := client.Check(context.Background(), &identity.StaticRequester{Namespace: "stacks-1"}, req)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, test.expected, resp.Allowed)
|
||||
}
|
||||
@@ -52,11 +56,12 @@ func TestAuthzLimitedClient_Compile(t *testing.T) {
|
||||
|
||||
for _, test := range tests {
|
||||
req := authlib.ListRequest{
|
||||
Group: test.group,
|
||||
Resource: test.resource,
|
||||
Verb: utils.VerbGet,
|
||||
Group: test.group,
|
||||
Resource: test.resource,
|
||||
Verb: utils.VerbGet,
|
||||
Namespace: "stacks-1",
|
||||
}
|
||||
checker, err := client.Compile(context.Background(), nil, req)
|
||||
checker, err := client.Compile(context.Background(), &identity.StaticRequester{Namespace: "stacks-1"}, req)
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, checker)
|
||||
|
||||
@@ -64,3 +69,156 @@ func TestAuthzLimitedClient_Compile(t *testing.T) {
|
||||
assert.Equal(t, test.expected, result)
|
||||
}
|
||||
}
|
||||
|
||||
// TestNamespaceMatching tests namespace matching in Check and Compile methods
|
||||
func TestNamespaceMatching(t *testing.T) {
|
||||
// Create a mock client that always returns allowed=true
|
||||
mockClient := authlib.FixedAccessClient(true)
|
||||
client := NewAuthzLimitedClient(mockClient, AuthzOptions{})
|
||||
|
||||
// Create a context with fallback disabled
|
||||
ctx := context.Background()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
authNamespace string
|
||||
reqNamespace string
|
||||
expectError bool
|
||||
}{
|
||||
{
|
||||
name: "matching namespaces",
|
||||
authNamespace: "ns1",
|
||||
reqNamespace: "ns1",
|
||||
expectError: false,
|
||||
},
|
||||
{
|
||||
name: "mismatched namespaces",
|
||||
authNamespace: "ns1",
|
||||
reqNamespace: "ns2",
|
||||
expectError: true,
|
||||
},
|
||||
{
|
||||
name: "empty request namespace",
|
||||
authNamespace: "ns1",
|
||||
reqNamespace: "",
|
||||
expectError: true,
|
||||
},
|
||||
{
|
||||
name: "empty auth namespace",
|
||||
authNamespace: "",
|
||||
reqNamespace: "ns1",
|
||||
expectError: true,
|
||||
},
|
||||
{
|
||||
name: "wildcard auth namespace",
|
||||
authNamespace: "*",
|
||||
reqNamespace: "ns1",
|
||||
expectError: false,
|
||||
},
|
||||
{
|
||||
name: "both empty namespaces",
|
||||
authNamespace: "",
|
||||
reqNamespace: "",
|
||||
expectError: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
// Test Check method with namespace matching
|
||||
checkReq := authlib.CheckRequest{
|
||||
Group: "unknown.group", // Use unknown group to bypass RBAC check
|
||||
Resource: "unknown.resource",
|
||||
Verb: utils.VerbGet,
|
||||
Namespace: tt.reqNamespace,
|
||||
}
|
||||
// Create a mock auth info with the specified namespace
|
||||
// Test Check method
|
||||
user := &identity.StaticRequester{Namespace: tt.authNamespace}
|
||||
_, checkErr := client.Check(ctx, user, checkReq)
|
||||
|
||||
// Test Compile method
|
||||
compileReq := authlib.ListRequest{
|
||||
Group: "unknown.group", // Use unknown group to bypass RBAC check
|
||||
Resource: "unknown.resource",
|
||||
Verb: utils.VerbGet,
|
||||
Namespace: tt.reqNamespace,
|
||||
}
|
||||
_, compileErr := client.Compile(ctx, user, compileReq)
|
||||
|
||||
if tt.expectError {
|
||||
require.Error(t, checkErr, "Check should return error")
|
||||
require.Error(t, compileErr, "Compile should return error")
|
||||
assert.ErrorIs(t, checkErr, authlib.ErrNamespaceMissmatch, "Check should return namespace mismatch error")
|
||||
assert.ErrorIs(t, compileErr, authlib.ErrNamespaceMissmatch, "Compile should return namespace mismatch error")
|
||||
} else {
|
||||
assert.NoError(t, checkErr, "Check should not return error when namespaces match")
|
||||
assert.NoError(t, compileErr, "Compile should not return error when namespaces match")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestNamespaceMatchingFallback tests namespace matching in Check and Compile methods when fallback is used
|
||||
func TestNamespaceMatchingFallback(t *testing.T) {
|
||||
// Create a mock client that always returns allowed=true
|
||||
mockClient := authlib.FixedAccessClient(true)
|
||||
client := NewAuthzLimitedClient(mockClient, AuthzOptions{})
|
||||
|
||||
// Create a context with fallback disabled
|
||||
ctx := context.Background()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
authNamespace string
|
||||
reqNamespace string
|
||||
expectError bool
|
||||
}{
|
||||
{
|
||||
name: "with namespace fallback",
|
||||
reqNamespace: "ns1",
|
||||
expectError: false,
|
||||
},
|
||||
{
|
||||
name: "empty request namespace with fallback",
|
||||
reqNamespace: "",
|
||||
expectError: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
// Test Check method with namespace matching
|
||||
checkReq := authlib.CheckRequest{
|
||||
Group: "unknown.group", // Use unknown group to bypass RBAC check
|
||||
Resource: "unknown.resource",
|
||||
Verb: utils.VerbGet,
|
||||
Namespace: tt.reqNamespace,
|
||||
}
|
||||
ctx = grpcutils.WithFallback(ctx)
|
||||
// Create a mock auth info with the specified namespace
|
||||
// Test Check method
|
||||
user := &identity.StaticRequester{Namespace: tt.authNamespace}
|
||||
_, checkErr := client.Check(ctx, user, checkReq)
|
||||
|
||||
// Test Compile method
|
||||
compileReq := authlib.ListRequest{
|
||||
Group: "unknown.group", // Use unknown group to bypass RBAC check
|
||||
Resource: "unknown.resource",
|
||||
Verb: utils.VerbGet,
|
||||
Namespace: tt.reqNamespace,
|
||||
}
|
||||
_, compileErr := client.Compile(ctx, user, compileReq)
|
||||
|
||||
if tt.expectError {
|
||||
require.Error(t, checkErr, "Check should return error")
|
||||
require.Error(t, compileErr, "Compile should return error")
|
||||
assert.ErrorContains(t, checkErr, "namespace empty", "Check should return namespace mismatch error")
|
||||
assert.ErrorContains(t, compileErr, "namespace empty", "Compile should return namespace mismatch error")
|
||||
} else {
|
||||
assert.NoError(t, checkErr, "Check should not return error when namespaces match")
|
||||
assert.NoError(t, compileErr, "Compile should not return error when namespaces match")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user