mirror of
https://github.com/projectcapsule/capsule.git
synced 2026-08-22 14:07:10 +00:00
239 lines
6.0 KiB
Go
239 lines
6.0 KiB
Go
// Copyright 2020-2026 Project Capsule Authors
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package v1beta2_test
|
|
|
|
import (
|
|
"reflect"
|
|
"testing"
|
|
|
|
rbacv1 "k8s.io/api/rbac/v1"
|
|
|
|
capsulev1beta2 "github.com/projectcapsule/capsule/api/v1beta2"
|
|
capsulerbac "github.com/projectcapsule/capsule/pkg/api/rbac"
|
|
)
|
|
|
|
func testTenant() *capsulev1beta2.Tenant {
|
|
return &capsulev1beta2.Tenant{
|
|
Spec: capsulev1beta2.TenantSpec{
|
|
AdditionalRoleBindings: []capsulerbac.AdditionalRoleBindingsSpec{
|
|
{
|
|
ClusterRoleName: "developer",
|
|
Subjects: []rbacv1.Subject{
|
|
{Kind: "User", Name: "user2"},
|
|
{Kind: "Group", Name: "group1"},
|
|
},
|
|
},
|
|
{
|
|
ClusterRoleName: "cluster-admin",
|
|
Subjects: []rbacv1.Subject{
|
|
{Kind: "User", Name: "user3"},
|
|
{Kind: "Group", Name: "group1"},
|
|
},
|
|
},
|
|
{
|
|
ClusterRoleName: "deployer",
|
|
Subjects: []rbacv1.Subject{
|
|
{Kind: "ServiceAccount", Name: "system:serviceaccount:argocd:argo-operator"},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
Status: capsulev1beta2.TenantStatus{
|
|
Owners: capsulerbac.OwnerStatusListSpec{
|
|
{
|
|
UserSpec: capsulerbac.UserSpec{
|
|
Kind: capsulerbac.UserOwner,
|
|
Name: "user1",
|
|
},
|
|
ClusterRoles: []string{"cluster-admin", "read-only"},
|
|
},
|
|
{
|
|
UserSpec: capsulerbac.UserSpec{
|
|
Kind: capsulerbac.GroupOwner,
|
|
Name: "group1",
|
|
},
|
|
ClusterRoles: []string{"edit"},
|
|
},
|
|
{
|
|
UserSpec: capsulerbac.UserSpec{
|
|
Kind: capsulerbac.ServiceAccountOwner,
|
|
Name: "service",
|
|
},
|
|
ClusterRoles: []string{"read-only"},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
}
|
|
|
|
func TestGetSubjectsByClusterRoles(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
tenant := testTenant()
|
|
|
|
expected := map[string][]rbacv1.Subject{
|
|
"cluster-admin": {
|
|
{Kind: "User", Name: "user1"},
|
|
{Kind: "User", Name: "user3"},
|
|
{Kind: "Group", Name: "group1"},
|
|
},
|
|
"read-only": {
|
|
{Kind: "User", Name: "user1"},
|
|
{Kind: "ServiceAccount", Name: "service"},
|
|
},
|
|
"edit": {
|
|
{Kind: "Group", Name: "group1"},
|
|
},
|
|
"developer": {
|
|
{Kind: "User", Name: "user2"},
|
|
{Kind: "Group", Name: "group1"},
|
|
},
|
|
"deployer": {
|
|
{Kind: "ServiceAccount", Name: "system:serviceaccount:argocd:argo-operator"},
|
|
},
|
|
}
|
|
|
|
got := tenant.GetSubjectsByClusterRoles(nil)
|
|
if !reflect.DeepEqual(got, expected) {
|
|
t.Fatalf("expected %#v\n got %#v", expected, got)
|
|
}
|
|
|
|
expectedIgnored := map[string][]rbacv1.Subject{
|
|
"cluster-admin": {
|
|
{Kind: "User", Name: "user1"},
|
|
{Kind: "User", Name: "user3"},
|
|
{Kind: "Group", Name: "group1"},
|
|
},
|
|
"read-only": {
|
|
{Kind: "User", Name: "user1"},
|
|
},
|
|
"edit": {
|
|
{Kind: "Group", Name: "group1"},
|
|
},
|
|
"developer": {
|
|
{Kind: "User", Name: "user2"},
|
|
{Kind: "Group", Name: "group1"},
|
|
},
|
|
}
|
|
|
|
gotIgnored := tenant.GetSubjectsByClusterRoles([]capsulerbac.OwnerKind{capsulerbac.ServiceAccountOwner})
|
|
if !reflect.DeepEqual(gotIgnored, expectedIgnored) {
|
|
t.Fatalf("expected %#v\n got %#v", expectedIgnored, gotIgnored)
|
|
}
|
|
}
|
|
|
|
func TestGetClusterRolesBySubjectSorted(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
tenant := &capsulev1beta2.Tenant{
|
|
Spec: capsulev1beta2.TenantSpec{
|
|
AdditionalRoleBindings: []capsulerbac.AdditionalRoleBindingsSpec{
|
|
{
|
|
ClusterRoleName: "deployer",
|
|
Subjects: []rbacv1.Subject{
|
|
{
|
|
Kind: "ServiceAccount",
|
|
Name: "system:serviceaccount:argocd:argo-operator",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
ClusterRoleName: "developer",
|
|
Subjects: []rbacv1.Subject{
|
|
{
|
|
Kind: "Group",
|
|
Name: "group1",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
Status: capsulev1beta2.TenantStatus{
|
|
Owners: capsulerbac.OwnerStatusListSpec{
|
|
{
|
|
UserSpec: capsulerbac.UserSpec{
|
|
Kind: capsulerbac.UserOwner,
|
|
Name: "user1",
|
|
},
|
|
ClusterRoles: []string{"cluster-admin", "read-only"},
|
|
},
|
|
{
|
|
UserSpec: capsulerbac.UserSpec{
|
|
Kind: capsulerbac.UserOwner,
|
|
Name: "user2",
|
|
},
|
|
ClusterRoles: []string{"developer"},
|
|
},
|
|
{
|
|
UserSpec: capsulerbac.UserSpec{
|
|
Kind: capsulerbac.UserOwner,
|
|
Name: "user3",
|
|
},
|
|
ClusterRoles: []string{"cluster-admin"},
|
|
},
|
|
{
|
|
UserSpec: capsulerbac.UserSpec{
|
|
Kind: capsulerbac.GroupOwner,
|
|
Name: "group1",
|
|
},
|
|
ClusterRoles: []string{"edit", "developer", "cluster-admin"},
|
|
},
|
|
{
|
|
UserSpec: capsulerbac.UserSpec{
|
|
Kind: capsulerbac.ServiceAccountOwner,
|
|
Name: "service",
|
|
},
|
|
ClusterRoles: []string{"read-only"},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
expected := []capsulerbac.SubjectRoles{
|
|
{Kind: "Group", Name: "group1", Roles: []string{"cluster-admin", "developer", "edit"}},
|
|
{Kind: "ServiceAccount", Name: "service", Roles: []string{"read-only"}},
|
|
{Kind: "ServiceAccount", Name: "system:serviceaccount:argocd:argo-operator", Roles: []string{"deployer"}},
|
|
{Kind: "User", Name: "user1", Roles: []string{"cluster-admin", "read-only"}},
|
|
{Kind: "User", Name: "user2", Roles: []string{"developer"}},
|
|
{Kind: "User", Name: "user3", Roles: []string{"cluster-admin"}},
|
|
}
|
|
|
|
t.Run("includes all kinds and is deterministic, deduped and sorted", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
got := tenant.GetClusterRolesBySubject(nil)
|
|
if !reflect.DeepEqual(got, expected) {
|
|
t.Fatalf("expected %#v\n got %#v", expected, got)
|
|
}
|
|
})
|
|
|
|
t.Run("ignores ServiceAccount kind", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
got := tenant.GetClusterRolesBySubject([]capsulerbac.OwnerKind{capsulerbac.ServiceAccountOwner})
|
|
|
|
expectedIgnored := []capsulerbac.SubjectRoles{
|
|
{Kind: "Group", Name: "group1", Roles: []string{"cluster-admin", "developer", "edit"}},
|
|
{Kind: "User", Name: "user1", Roles: []string{"cluster-admin", "read-only"}},
|
|
{Kind: "User", Name: "user2", Roles: []string{"developer"}},
|
|
{Kind: "User", Name: "user3", Roles: []string{"cluster-admin"}},
|
|
}
|
|
|
|
if !reflect.DeepEqual(got, expectedIgnored) {
|
|
t.Fatalf("expected %#v\n got %#v", expectedIgnored, got)
|
|
}
|
|
})
|
|
|
|
t.Run("empty tenant yields empty slice", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
empty := &capsulev1beta2.Tenant{}
|
|
got := empty.GetClusterRolesBySubject(nil)
|
|
if len(got) != 0 {
|
|
t.Fatalf("expected empty, got %#v", got)
|
|
}
|
|
})
|
|
}
|