grafana/pkg/registry/apis/iam/team/validate_test.go

438 lines
11 KiB
Go
Raw Normal View History

package team
import (
"context"
"testing"
"github.com/stretchr/testify/assert"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"github.com/grafana/authlib/types"
iamv0alpha1 "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1"
"github.com/grafana/grafana/pkg/apimachinery/identity"
)
func TestValidateOnCreate(t *testing.T) {
tests := []struct {
name string
requester *identity.StaticRequester
obj *iamv0alpha1.Team
want error
}{
{
name: "valid team - not provisioned",
requester: &identity.StaticRequester{
Type: types.TypeUser,
OrgRole: identity.RoleAdmin,
},
obj: &iamv0alpha1.Team{
Spec: iamv0alpha1.TeamSpec{
Title: "test",
Email: "test@test.com",
},
},
want: nil,
},
{
name: "valid team - provisioned",
requester: &identity.StaticRequester{
Type: types.TypeServiceAccount,
OrgRole: identity.RoleAdmin,
},
obj: &iamv0alpha1.Team{
Spec: iamv0alpha1.TeamSpec{
Title: "test",
Email: "test@test.com",
Provisioned: true,
ExternalUID: "test-uid",
},
},
want: nil,
},
{
name: "invalid team - no title",
requester: &identity.StaticRequester{
Type: types.TypeUser,
OrgRole: identity.RoleAdmin,
},
obj: &iamv0alpha1.Team{
Spec: iamv0alpha1.TeamSpec{
Title: "",
Email: "test@test.com",
},
},
want: apierrors.NewBadRequest("the team must have a title"),
},
{
name: "invalid team - it's provisioned but the requester is not a service account",
requester: &identity.StaticRequester{
Type: types.TypeUser,
OrgRole: identity.RoleAdmin,
},
obj: &iamv0alpha1.Team{
Spec: iamv0alpha1.TeamSpec{
Title: "test",
Email: "test@test.com",
Provisioned: true,
ExternalUID: "test-uid",
},
},
want: apierrors.NewBadRequest("provisioned teams are only allowed for service accounts"),
},
{
name: "invalid team - has externalUID but it's not provisioned",
requester: &identity.StaticRequester{
Type: types.TypeUser,
OrgRole: identity.RoleAdmin,
},
obj: &iamv0alpha1.Team{
Spec: iamv0alpha1.TeamSpec{
Title: "test",
Email: "test@test.com",
ExternalUID: "test-uid",
},
},
want: apierrors.NewBadRequest("externalUID is only allowed for provisioned teams"),
},
{
name: "invalid team - no requester in context",
requester: nil,
obj: &iamv0alpha1.Team{
Spec: iamv0alpha1.TeamSpec{
Title: "test",
Email: "test@test.com",
},
},
want: apierrors.NewUnauthorized("no identity found"),
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
ctx := identity.WithRequester(context.Background(), test.requester)
err := ValidateOnCreate(ctx, test.obj)
assert.Equal(t, test.want, err)
})
}
}
func TestValidateOnUpdate(t *testing.T) {
tests := []struct {
name string
requester *identity.StaticRequester
obj *iamv0alpha1.Team
old *iamv0alpha1.Team
want error
}{
{
name: "valid update - no changes to provisioned status",
requester: &identity.StaticRequester{
Type: types.TypeUser,
OrgRole: identity.RoleAdmin,
},
obj: &iamv0alpha1.Team{
Spec: iamv0alpha1.TeamSpec{
Title: "updated title",
Email: "updated@test.com",
},
},
old: &iamv0alpha1.Team{
Spec: iamv0alpha1.TeamSpec{
Title: "original title",
Email: "original@test.com",
},
},
want: nil,
},
{
name: "valid update - service account changing to provisioned",
requester: &identity.StaticRequester{
Type: types.TypeServiceAccount,
OrgRole: identity.RoleAdmin,
},
obj: &iamv0alpha1.Team{
Spec: iamv0alpha1.TeamSpec{
Title: "updated title",
Email: "updated@test.com",
Provisioned: true,
ExternalUID: "test-uid",
},
},
old: &iamv0alpha1.Team{
Spec: iamv0alpha1.TeamSpec{
Title: "original title",
Email: "original@test.com",
},
},
want: nil,
},
{
name: "valid update - already provisioned team",
requester: &identity.StaticRequester{
Type: types.TypeServiceAccount,
OrgRole: identity.RoleAdmin,
},
obj: &iamv0alpha1.Team{
Spec: iamv0alpha1.TeamSpec{
Title: "updated title",
Email: "updated@test.com",
Provisioned: true,
ExternalUID: "updated-uid",
},
},
old: &iamv0alpha1.Team{
Spec: iamv0alpha1.TeamSpec{
Title: "original title",
Email: "original@test.com",
Provisioned: true,
ExternalUID: "original-uid",
},
},
want: nil,
},
{
name: "invalid update - no title",
requester: &identity.StaticRequester{
Type: types.TypeUser,
OrgRole: identity.RoleAdmin,
},
obj: &iamv0alpha1.Team{
Spec: iamv0alpha1.TeamSpec{
Title: "",
Email: "updated@test.com",
},
},
old: &iamv0alpha1.Team{
Spec: iamv0alpha1.TeamSpec{
Title: "original title",
Email: "original@test.com",
},
},
want: apierrors.NewBadRequest("the team must have a title"),
},
{
name: "invalid update - user trying to change to provisioned",
requester: &identity.StaticRequester{
Type: types.TypeUser,
OrgRole: identity.RoleAdmin,
},
obj: &iamv0alpha1.Team{
Spec: iamv0alpha1.TeamSpec{
Title: "updated title",
Email: "updated@test.com",
Provisioned: true,
ExternalUID: "test-uid",
},
},
old: &iamv0alpha1.Team{
Spec: iamv0alpha1.TeamSpec{
Title: "original title",
Email: "original@test.com",
},
},
want: apierrors.NewBadRequest("provisioned teams are only allowed for service accounts"),
},
{
name: "invalid update - changing from provisioned to non-provisioned",
requester: &identity.StaticRequester{
Type: types.TypeServiceAccount,
OrgRole: identity.RoleAdmin,
},
obj: &iamv0alpha1.Team{
Spec: iamv0alpha1.TeamSpec{
Title: "updated title",
Email: "updated@test.com",
},
},
old: &iamv0alpha1.Team{
Spec: iamv0alpha1.TeamSpec{
Title: "original title",
Email: "original@test.com",
Provisioned: true,
ExternalUID: "original-uid",
},
},
want: apierrors.NewBadRequest("provisioned teams cannot be updated to non-provisioned teams"),
},
{
name: "invalid update - has externalUID but not provisioned",
requester: &identity.StaticRequester{
Type: types.TypeUser,
OrgRole: identity.RoleAdmin,
},
obj: &iamv0alpha1.Team{
Spec: iamv0alpha1.TeamSpec{
Title: "updated title",
Email: "updated@test.com",
ExternalUID: "test-uid",
},
},
old: &iamv0alpha1.Team{
Spec: iamv0alpha1.TeamSpec{
Title: "original title",
Email: "original@test.com",
},
},
want: apierrors.NewBadRequest("externalUID is only allowed for provisioned teams"),
},
{
name: "invalid update - no requester in context",
requester: nil,
obj: &iamv0alpha1.Team{
Spec: iamv0alpha1.TeamSpec{
Title: "updated title",
Email: "updated@test.com",
},
},
old: &iamv0alpha1.Team{
Spec: iamv0alpha1.TeamSpec{
Title: "original title",
Email: "original@test.com",
},
},
want: apierrors.NewUnauthorized("no identity found"),
},
{
name: "valid update - adding externalUID to provisioned team",
requester: &identity.StaticRequester{
Type: types.TypeServiceAccount,
OrgRole: identity.RoleAdmin,
},
obj: &iamv0alpha1.Team{
Spec: iamv0alpha1.TeamSpec{
Title: "updated title",
Email: "updated@test.com",
Provisioned: true,
ExternalUID: "new-uid",
},
},
old: &iamv0alpha1.Team{
Spec: iamv0alpha1.TeamSpec{
Title: "original title",
Email: "original@test.com",
Provisioned: true,
},
},
want: nil,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
ctx := identity.WithRequester(context.Background(), test.requester)
err := ValidateOnUpdate(ctx, test.obj, test.old)
assert.Equal(t, test.want, err)
})
}
}
2025-10-06 17:40:26 +08:00
func TestValidateOnBindingCreate(t *testing.T) {
tests := []struct {
name string
requester *identity.StaticRequester
obj *iamv0alpha1.TeamBinding
want error
}{
{
name: "valid team binding create",
requester: &identity.StaticRequester{
Type: types.TypeUser,
OrgRole: identity.RoleAdmin,
},
obj: &iamv0alpha1.TeamBinding{
Spec: iamv0alpha1.TeamBindingSpec{
Subject: iamv0alpha1.TeamBindingspecSubject{
Name: "test-user",
},
TeamRef: iamv0alpha1.TeamBindingTeamRef{
Name: "test-team",
},
Permission: iamv0alpha1.TeamBindingTeamPermissionAdmin,
},
},
want: nil,
},
{
name: "invalid team binding - invalid permission",
requester: &identity.StaticRequester{
Type: types.TypeUser,
OrgRole: identity.RoleAdmin,
},
obj: &iamv0alpha1.TeamBinding{
Spec: iamv0alpha1.TeamBindingSpec{
Subject: iamv0alpha1.TeamBindingspecSubject{
Name: "test-user",
},
TeamRef: iamv0alpha1.TeamBindingTeamRef{
Name: "test-team",
},
Permission: "invalid",
},
},
want: apierrors.NewBadRequest("invalid permission"),
},
{
name: "invalid team binding - no subject",
requester: &identity.StaticRequester{
Type: types.TypeUser,
OrgRole: identity.RoleAdmin,
},
obj: &iamv0alpha1.TeamBinding{
Spec: iamv0alpha1.TeamBindingSpec{
Subject: iamv0alpha1.TeamBindingspecSubject{
Name: "",
},
TeamRef: iamv0alpha1.TeamBindingTeamRef{
Name: "test-team",
},
2025-10-07 23:09:05 +08:00
Permission: iamv0alpha1.TeamBindingTeamPermissionAdmin,
},
},
want: apierrors.NewBadRequest("subject is required"),
},
{
name: "invalid team binding - no teamRef",
requester: &identity.StaticRequester{
Type: types.TypeUser,
OrgRole: identity.RoleAdmin,
},
obj: &iamv0alpha1.TeamBinding{
Spec: iamv0alpha1.TeamBindingSpec{
Subject: iamv0alpha1.TeamBindingspecSubject{
Name: "test-user",
},
TeamRef: iamv0alpha1.TeamBindingTeamRef{
Name: "",
},
2025-10-07 23:09:05 +08:00
Permission: iamv0alpha1.TeamBindingTeamPermissionAdmin,
},
},
want: apierrors.NewBadRequest("teamRef is required"),
},
{
name: "invalid team binding - no requester in context",
requester: nil,
obj: &iamv0alpha1.TeamBinding{
Spec: iamv0alpha1.TeamBindingSpec{
Subject: iamv0alpha1.TeamBindingspecSubject{
Name: "test-user",
},
TeamRef: iamv0alpha1.TeamBindingTeamRef{
Name: "test-team",
},
Permission: iamv0alpha1.TeamBindingTeamPermissionAdmin,
},
},
want: apierrors.NewUnauthorized("no identity found"),
},
2025-10-06 17:40:26 +08:00
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
ctx := identity.WithRequester(context.Background(), test.requester)
err := ValidateOnBindingCreate(ctx, test.obj)
assert.Equal(t, test.want, err)
})
}
}