Draft: adding usernames to GetIdentityFunc

This commit is contained in:
Cristian Le 2021-04-30 09:14:28 +09:00
parent 79eec83f3e
commit 48666792c7
4 changed files with 9 additions and 12 deletions

View file

@ -47,7 +47,7 @@ func WithDatabase(db db.AuthDB) Option {
// WithGetIdentityFunc sets a custom function to retrieve the identity from
// an external resource.
func WithGetIdentityFunc(fn func(ctx context.Context, p provisioner.Interface, email string) (*provisioner.Identity, error)) Option {
func WithGetIdentityFunc(fn func(ctx context.Context, p provisioner.Interface, email string, usernames ...string) (*provisioner.Identity, error)) Option {
return func(a *Authority) error {
a.getIdentityFunc = fn
return nil

View file

@ -389,15 +389,10 @@ func (o *OIDC) AuthorizeSSHSign(ctx context.Context, token string) ([]SignOption
// Get the identity using either the default identityFunc or one injected
// externally.
iden, err := o.getIdentityFunc(ctx, o, claims.Email)
iden, err := o.getIdentityFunc(ctx, o, claims.Email, claims.PreferredUsername)
if err != nil {
return nil, errs.Wrap(http.StatusInternalServerError, err, "oidc.AuthorizeSSHSign")
}
// Reuse the contains function provided for simplicity
if !containsAllMembers(iden.Usernames, []string{claims.PreferredUsername}) {
// Add preferred_username to the identity's Username
iden.Usernames = append(iden.Usernames, claims.PreferredUsername)
}
// Certificate templates.
data := sshutil.CreateTemplateData(sshutil.UserCert, claims.Email, iden.Usernames)

View file

@ -500,12 +500,13 @@ func TestOIDC_AuthorizeSSHSign(t *testing.T) {
assert.FatalError(t, p4.Init(config))
assert.FatalError(t, p5.Init(config))
p4.getIdentityFunc = func(ctx context.Context, p Interface, email string) (*Identity, error) {
p4.getIdentityFunc = func(ctx context.Context, p Interface, email string, usernames ...string) (*Identity, error) {
return &Identity{Usernames: []string{"max", "mariano"}}, nil
}
p5.getIdentityFunc = func(ctx context.Context, p Interface, email string) (*Identity, error) {
p5.getIdentityFunc = func(ctx context.Context, p Interface, email string, usernames ...string) (*Identity, error) {
return nil, errors.New("force")
}
// Additional test needed for empty usernames and duplicate email and usernames
t1, err := generateSimpleToken("the-issuer", p1.ClientID, &keys.Keys[0])
assert.FatalError(t, err)

View file

@ -337,10 +337,10 @@ type Permissions struct {
}
// GetIdentityFunc is a function that returns an identity.
type GetIdentityFunc func(ctx context.Context, p Interface, email string) (*Identity, error)
type GetIdentityFunc func(ctx context.Context, p Interface, email string, usernames ...string) (*Identity, error)
// DefaultIdentityFunc return a default identity depending on the provisioner type.
func DefaultIdentityFunc(ctx context.Context, p Interface, email string) (*Identity, error) {
func DefaultIdentityFunc(ctx context.Context, p Interface, email string, usernames ...string) (*Identity, error) {
switch k := p.(type) {
case *OIDC:
// OIDC principals would be:
@ -351,13 +351,14 @@ func DefaultIdentityFunc(ctx context.Context, p Interface, email string) (*Ident
if !sshUserRegex.MatchString(name) {
return nil, errors.Errorf("invalid principal '%s' from email '%s'", name, email)
}
usernames := []string{name}
usernames := append(usernames, name)
if i := strings.LastIndex(email, "@"); i >= 0 {
if local := email[:i]; !strings.EqualFold(local, name) {
usernames = append(usernames, local)
}
}
usernames = append(usernames, email)
// Some remove duplicate function should be added
return &Identity{
Usernames: usernames,
}, nil