diff --git a/authority/provisioner/controller.go b/authority/provisioner/controller.go index 6d92961a..09f6a6bb 100644 --- a/authority/provisioner/controller.go +++ b/authority/provisioner/controller.go @@ -4,7 +4,6 @@ import ( "context" "crypto/x509" "net/http" - "regexp" "strings" "time" @@ -117,20 +116,18 @@ func DefaultIdentityFunc(_ context.Context, p Interface, email string) (*Identit switch k := p.(type) { case *OIDC: // OIDC principals would be: - // ~~1. Preferred usernames.~~ Note: Under discussion, currently disabled - // 2. Sanitized local. - // 3. Raw local (if different). - // 4. Email address. + // ~~1. Preferred usernames.~~ Note: Under discussion, currently disabled + // 2. Sanitized local. + // 3. Raw local (if different). + // 4. Email address. name := SanitizeSSHUserPrincipal(email) - if !sshUserRegex.MatchString(name) { - return nil, errors.Errorf("invalid principal '%s' from email '%s'", name, email) - } usernames := []string{name} if i := strings.LastIndex(email, "@"); i >= 0 { usernames = append(usernames, email[:i]) } usernames = append(usernames, email) return &Identity{ + // Remove duplicated and empty usernames. Usernames: SanitizeStringSlices(usernames), }, nil default: @@ -180,8 +177,6 @@ func DefaultAuthorizeSSHRenew(_ context.Context, p *Controller, cert *ssh.Certif return nil } -var sshUserRegex = regexp.MustCompile("^[a-z][-a-z0-9_]*$") - // SanitizeStringSlices removes duplicated an empty strings. func SanitizeStringSlices(original []string) []string { output := []string{} diff --git a/authority/provisioner/controller_test.go b/authority/provisioner/controller_test.go index 3bab7c4e..cddfb635 100644 --- a/authority/provisioner/controller_test.go +++ b/authority/provisioner/controller_test.go @@ -170,6 +170,12 @@ func TestController_GetIdentity(t *testing.T) { }}, args{ctx, "jane@doe.org"}, &Identity{ Usernames: []string{"jane"}, }, false}, + {"ok badname", fields{&OIDC{}, nil}, args{ctx, "1000@doe.org"}, &Identity{ + Usernames: []string{"1000", "1000@doe.org"}, + }, false}, + {"ok sanitized badname", fields{&OIDC{}, nil}, args{ctx, "1000+10@doe.org"}, &Identity{ + Usernames: []string{"1000_10", "1000+10", "1000+10@doe.org"}, + }, false}, {"fail provisioner", fields{&JWK{}, nil}, args{ctx, "jane@doe.org"}, nil, true}, {"fail custom", fields{&OIDC{}, func(ctx context.Context, p Interface, email string) (*Identity, error) { return nil, fmt.Errorf("an error") diff --git a/authority/provisioner/provisioner_test.go b/authority/provisioner/provisioner_test.go index 65fb8e1d..865e5291 100644 --- a/authority/provisioner/provisioner_test.go +++ b/authority/provisioner/provisioner_test.go @@ -76,13 +76,6 @@ func TestDefaultIdentityFunc(t *testing.T) { err: errors.New("provisioner type '*provisioner.X5C' not supported by identity function"), } }, - "fail/bad-ssh-regex": func(t *testing.T) test { - return test{ - p: &OIDC{}, - email: "$%^#_>@smallstep.com", - err: errors.New("invalid principal '______' from email '$%^#_>@smallstep.com'"), - } - }, "ok": func(t *testing.T) test { return test{ p: &OIDC{}, @@ -142,6 +135,13 @@ func TestDefaultIdentityFunc(t *testing.T) { identity: &Identity{Usernames: []string{"john", "john@smallstep.com"}}, } }, + "ok/badname": func(t *testing.T) test { + return test{ + p: &OIDC{}, + email: "$%^#_>@smallstep.com", + identity: &Identity{Usernames: []string{"______", "$%^#_>", "$%^#_>@smallstep.com"}}, + } + }, } for name, get := range tests { t.Run(name, func(t *testing.T) {