pkg/auth/cloud_role_test.go
Rama main · réplica de lectura del repositorio original.
package auth
import (
"context"
"testing"
)
func TestCloudRoleFromGroupsRadarVocabulary(t *testing.T) {
cases := []struct {
name string
groups []string
want CloudRole
}{
{"radar canonical", []string{"radar:member", "radar:org:o1", "radar:user:u1"}, RoleMember},
{"dual-emit picks tier once", []string{"radar:viewer", "radar:org:o1", "cloud:viewer", "cloud:org:o1"}, RoleViewer},
{"legacy cloud only (old hub)", []string{"cloud:owner", "cloud:org:o1"}, RoleOwner},
{"idp groups are not tiers", []string{"radar:idp:owner", "radar:idp:member"}, RoleNone},
{"highest rank wins across vocabularies", []string{"cloud:viewer", "radar:owner"}, RoleOwner},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
if got := CloudRoleFromGroups(tc.groups); got != tc.want {
t.Errorf("CloudRoleFromGroups(%v) = %q, want %q", tc.groups, got, tc.want)
}
})
}
}
func TestCloudRoleFromGroups(t *testing.T) {
cases := []struct {
name string
groups []string
want CloudRole
}{
{"empty groups", nil, RoleNone},
{"no Radar prefix", []string{"developers", "sre"}, RoleNone},
{"viewer", []string{"radar:viewer"}, RoleViewer},
{"member", []string{"radar:member"}, RoleMember},
{"owner", []string{"radar:owner"}, RoleOwner},
{"unknown Radar tier", []string{"radar:superuser"}, RoleNone},
{"viewer + unrelated group", []string{"radar:viewer", "team:platform"}, RoleViewer},
// Cloud injects multiple radar:* groups (radar:<tier>, radar:org:<id>,
// radar:user:<id>). Only the tier should drive the role.
{"multiple Radar groups", []string{"radar:viewer", "radar:org:abc", "radar:user:xyz"}, RoleViewer},
// If two tiers are present (shouldn't happen in practice), prefer
// the highest. Defensive: a header-stuffing attempt to downgrade
// shouldn't succeed by adding a lower-tier alongside.
{"two tiers — pick highest", []string{"radar:viewer", "radar:owner"}, RoleOwner},
{"member + viewer", []string{"radar:member", "radar:viewer"}, RoleMember},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
got := CloudRoleFromGroups(tc.groups)
if got != tc.want {
t.Errorf("CloudRoleFromGroups(%v) = %q, want %q", tc.groups, got, tc.want)
}
})
}
}
func TestCloudRole_AtLeast(t *testing.T) {
cases := []struct {
role CloudRole
min CloudRole
want bool
}{
// RoleNone bypasses — non-Cloud deploys must not be gated.
{RoleNone, RoleViewer, true},
{RoleNone, RoleMember, true},
{RoleNone, RoleOwner, true},
{RoleViewer, RoleViewer, true},
{RoleViewer, RoleMember, false},
{RoleViewer, RoleOwner, false},
{RoleMember, RoleViewer, true},
{RoleMember, RoleMember, true},
{RoleMember, RoleOwner, false},
{RoleOwner, RoleViewer, true},
{RoleOwner, RoleMember, true},
{RoleOwner, RoleOwner, true},
}
for _, tc := range cases {
got := tc.role.AtLeast(tc.min)
if got != tc.want {
t.Errorf("CloudRole(%q).AtLeast(%q) = %v, want %v", tc.role, tc.min, got, tc.want)
}
}
}
func TestCloudRoleFromContext(t *testing.T) {
t.Run("no user in context", func(t *testing.T) {
if got := CloudRoleFromContext(context.Background()); got != RoleNone {
t.Errorf("CloudRoleFromContext(empty) = %q, want RoleNone", got)
}
})
t.Run("user with Cloud groups", func(t *testing.T) {
ctx := ContextWithUser(context.Background(), &User{
Username: "alice",
Groups: []string{"radar:member", "radar:org:abc"},
})
if got := CloudRoleFromContext(ctx); got != RoleMember {
t.Errorf("CloudRoleFromContext = %q, want member", got)
}
})
t.Run("user without Cloud groups (OSS proxy/oidc)", func(t *testing.T) {
ctx := ContextWithUser(context.Background(), &User{
Username: "bob",
Groups: []string{"sre", "platform-team"},
})
if got := CloudRoleFromContext(ctx); got != RoleNone {
t.Errorf("CloudRoleFromContext = %q, want RoleNone (no radar: prefix)", got)
}
})
}