Skip to content

Commit

Permalink
Make system roles case-insensitive in provision tokens (#33260)
Browse files Browse the repository at this point in the history
This change makes system roles set in a provision token
case-insensitive.
  • Loading branch information
atburke committed Oct 11, 2023
1 parent 5a493c3 commit b5022d3
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 10 deletions.
11 changes: 7 additions & 4 deletions api/types/provisioning.go
Expand Up @@ -183,15 +183,17 @@ func (p *ProvisionTokenV2) CheckAndSetDefaults() error {
if len(p.Spec.Roles) == 0 {
return trace.BadParameter("provisioning token is missing roles")
}
if err := SystemRoles(p.Spec.Roles).Check(); err != nil {
roles, err := NewTeleportRoles(SystemRoles(p.Spec.Roles).StringSlice())
if err != nil {
return trace.Wrap(err)
}
p.Spec.Roles = roles

if SystemRoles(p.Spec.Roles).Include(RoleBot) && p.Spec.BotName == "" {
if roles.Include(RoleBot) && p.Spec.BotName == "" {
return trace.BadParameter("token with role %q must set bot_name", RoleBot)
}

if p.Spec.BotName != "" && !SystemRoles(p.Spec.Roles).Include(RoleBot) {
if p.Spec.BotName != "" && !roles.Include(RoleBot) {
return trace.BadParameter("can only set bot_name on token with role %q", RoleBot)
}

Expand Down Expand Up @@ -324,7 +326,8 @@ func (p *ProvisionTokenV2) GetVersion() string {
// that will be granted to the user of the token
// in the crendentials
func (p *ProvisionTokenV2) GetRoles() SystemRoles {
return p.Spec.Roles
// Ensure that roles are case-insensitive.
return normalizedSystemRoles(SystemRoles(p.Spec.Roles).StringSlice())
}

// SetRoles sets teleport roles
Expand Down
17 changes: 17 additions & 0 deletions api/types/provisioning_test.go
Expand Up @@ -811,3 +811,20 @@ func TestProvisionTokenV2_GetSafeName(t *testing.T) {
require.Equal(t, "12345678", got)
})
}

func TestProvisionTokenV2_CaseInsensitiveRoles(t *testing.T) {
t.Parallel()
t.Run("via constructor", func(t *testing.T) {
tok, err := NewProvisionToken("token", SystemRoles{"nOde", "AuTh"}, time.Now())
require.NoError(t, err)
require.Equal(t, SystemRoles{RoleNode, RoleAuth}, tok.GetRoles())
})
t.Run("via struct", func(t *testing.T) {
tok := &ProvisionTokenV2{
Spec: ProvisionTokenSpecV2{
Roles: []SystemRole{"nOdE", "AuTh"},
},
}
require.Equal(t, SystemRoles{RoleNode, RoleAuth}, tok.GetRoles())
})
}
23 changes: 17 additions & 6 deletions api/types/system_role.go
Expand Up @@ -105,6 +105,21 @@ var roleMappings = map[string]SystemRole{
"mdm": RoleMDM,
}

func normalizedSystemRole(s string) SystemRole {
if role, ok := roleMappings[strings.ToLower(strings.TrimSpace(s))]; ok {
return role
}
return SystemRole(s)
}

func normalizedSystemRoles(s []string) []SystemRole {
roles := make([]SystemRole, 0, len(s))
for _, role := range s {
roles = append(roles, normalizedSystemRole(role))
}
return roles
}

// localServiceMappings is the subset of role mappings which happen to be true
// teleport services (e.g. db, kube, etc), excluding those which represent remote
// services (i.e. remoteproxy).
Expand Down Expand Up @@ -141,10 +156,7 @@ func LocalServiceMappings() SystemRoles {

// NewTeleportRoles return a list of teleport roles from slice of strings
func NewTeleportRoles(in []string) (SystemRoles, error) {
var roles SystemRoles
for _, val := range in {
roles = append(roles, SystemRole(val))
}
roles := SystemRoles(normalizedSystemRoles(in))
return roles, roles.Check()
}

Expand All @@ -153,8 +165,7 @@ func NewTeleportRoles(in []string) (SystemRoles, error) {
func ParseTeleportRoles(str string) (SystemRoles, error) {
var roles SystemRoles
for _, s := range strings.Split(str, ",") {
cleaned := strings.ToLower(strings.TrimSpace(s))
if r, ok := roleMappings[cleaned]; ok && r.Check() == nil {
if r := normalizedSystemRole(s); r.Check() == nil {
roles = append(roles, r)
continue
}
Expand Down
6 changes: 6 additions & 0 deletions api/types/system_role_test.go
Expand Up @@ -84,6 +84,12 @@ func TestParseTeleportRoles(t *testing.T) {
out: SystemRoles{RoleNode},
wantErr: false,
},
{
// case insensitive
in: "nOdE,prOXY",
out: SystemRoles{RoleNode, RoleProxy},
wantErr: false,
},
{
in: "windowsdesktop",
out: SystemRoles{RoleWindowsDesktop},
Expand Down

0 comments on commit b5022d3

Please sign in to comment.