forked from TrueCloudLab/certificates
Make SanitizeSSHPrincipal a public function.
This commit is contained in:
parent
f01286bb48
commit
48c98dea2a
3 changed files with 30 additions and 21 deletions
|
@ -309,7 +309,7 @@ func (o *OIDC) authorizeSSHSign(claims *openIDPayload) ([]SignOption, error) {
|
||||||
if o.IsAdmin(claims.Email) {
|
if o.IsAdmin(claims.Email) {
|
||||||
signOptions = append(signOptions, &sshCertificateOptionsValidator{})
|
signOptions = append(signOptions, &sshCertificateOptionsValidator{})
|
||||||
} else {
|
} else {
|
||||||
name := principalFromEmail(claims.Email)
|
name := SanitizeSSHPrincipal(claims.Email)
|
||||||
if !sshUserRegex.MatchString(name) {
|
if !sshUserRegex.MatchString(name) {
|
||||||
return nil, errors.Errorf("invalid principal '%s' from email address '%s'", name, claims.Email)
|
return nil, errors.Errorf("invalid principal '%s' from email address '%s'", name, claims.Email)
|
||||||
}
|
}
|
||||||
|
@ -338,21 +338,3 @@ func getAndDecode(uri string, v interface{}) error {
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func principalFromEmail(email string) string {
|
|
||||||
if i := strings.LastIndex(email, "@"); i >= 0 {
|
|
||||||
email = email[:i]
|
|
||||||
}
|
|
||||||
return strings.Map(func(r rune) rune {
|
|
||||||
switch {
|
|
||||||
case r >= 'a' && r <= 'z':
|
|
||||||
return r
|
|
||||||
case r >= '0' && r <= '9':
|
|
||||||
return r
|
|
||||||
case r == '.': // drop dots
|
|
||||||
return -1
|
|
||||||
default:
|
|
||||||
return '_'
|
|
||||||
}
|
|
||||||
}, strings.ToLower(email))
|
|
||||||
}
|
|
||||||
|
|
|
@ -11,8 +11,6 @@ import (
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
var sshUserRegex = regexp.MustCompile("^[a-z][-a-z0-9_]*$")
|
|
||||||
|
|
||||||
// Interface is the interface that all provisioner types must implement.
|
// Interface is the interface that all provisioner types must implement.
|
||||||
type Interface interface {
|
type Interface interface {
|
||||||
GetID() string
|
GetID() string
|
||||||
|
@ -164,3 +162,29 @@ func (l *List) UnmarshalJSON(data []byte) error {
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var sshUserRegex = regexp.MustCompile("^[a-z][-a-z0-9_]*$")
|
||||||
|
|
||||||
|
// SanitizeSSHPrincipal grabs an email or a string with the format local@domain
|
||||||
|
// and returns a sanitized version of the local, valid to be used as a user
|
||||||
|
// name. If the email starts with a letter between a and z, the resulting string
|
||||||
|
// will match the regular expression `^[a-z][-a-z0-9_]*$`.
|
||||||
|
func SanitizeSSHPrincipal(email string) string {
|
||||||
|
if i := strings.LastIndex(email, "@"); i >= 0 {
|
||||||
|
email = email[:i]
|
||||||
|
}
|
||||||
|
return strings.Map(func(r rune) rune {
|
||||||
|
switch {
|
||||||
|
case r >= 'a' && r <= 'z':
|
||||||
|
return r
|
||||||
|
case r >= '0' && r <= '9':
|
||||||
|
return r
|
||||||
|
case r == '-':
|
||||||
|
return '-'
|
||||||
|
case r == '.': // drop dots
|
||||||
|
return -1
|
||||||
|
default:
|
||||||
|
return '_'
|
||||||
|
}
|
||||||
|
}, strings.ToLower(email))
|
||||||
|
}
|
||||||
|
|
|
@ -211,6 +211,9 @@ type sshCertificateOptionsValidator struct {
|
||||||
// Valid implements SSHCertificateOptionsValidator and returns nil if both
|
// Valid implements SSHCertificateOptionsValidator and returns nil if both
|
||||||
// SSHOptions match.
|
// SSHOptions match.
|
||||||
func (v *sshCertificateOptionsValidator) Valid(got SSHOptions) error {
|
func (v *sshCertificateOptionsValidator) Valid(got SSHOptions) error {
|
||||||
|
if v.Want == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
return v.Want.match(got)
|
return v.Want.match(got)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue