func (p *provisioningIdentityMapper) userForWithRetries(info authapi.UserIdentityInfo, allowedRetries int) (kuser.Info, error) { ctx := kapi.NewContext() identity, err := p.identity.GetIdentity(ctx, info.GetIdentityName()) if kerrs.IsNotFound(err) { user, err := p.createIdentityAndMapping(ctx, info) // Only retry for the following types of errors: // AlreadyExists errors: // * The same user was created by another identity provider with the same preferred username // * The same user was created by another instance of this identity provider (e.g. double-clicked login button) // * The same identity was created by another instance of this identity provider (e.g. double-clicked login button) // Conflict errors: // * The same user was updated be another identity provider to add identity info if (kerrs.IsAlreadyExists(err) || kerrs.IsConflict(err)) && allowedRetries > 0 { return p.userForWithRetries(info, allowedRetries-1) } return user, err } if err != nil { return nil, err } return p.getMapping(ctx, identity) }
// createIdentityAndMapping creates an identity with a valid user reference for the given identity info func (p *provisioningIdentityMapper) createIdentityAndMapping(ctx kapi.Context, info authapi.UserIdentityInfo) (kuser.Info, error) { // Build the part of the identity we know about identity := &userapi.Identity{ ObjectMeta: kapi.ObjectMeta{ Name: info.GetIdentityName(), }, ProviderName: info.GetProviderName(), ProviderUserName: info.GetProviderUserName(), Extra: info.GetExtra(), } // Get or create a persisted user pointing to the identity persistedUser, err := p.provisioningStrategy.UserForNewIdentity(ctx, getPreferredUserName(identity), identity) if err != nil { return nil, err } // Create the identity pointing to the persistedUser identity.User = kapi.ObjectReference{ Name: persistedUser.Name, UID: persistedUser.UID, } if _, err := p.identity.CreateIdentity(ctx, identity); err != nil { return nil, err } return &kuser.DefaultInfo{ Name: persistedUser.Name, UID: string(persistedUser.UID), Groups: persistedUser.Groups, }, nil }
// UserFor returns info about the user for whom identity info has been provided func (p *lookupIdentityMapper) UserFor(info authapi.UserIdentityInfo) (kuser.Info, error) { ctx := kapi.NewContext() mapping, err := p.mappings.GetUserIdentityMapping(ctx, info.GetIdentityName()) if err != nil { return nil, err } u, err := p.users.GetUser(ctx, mapping.User.Name) if err != nil { return nil, err } return &kuser.DefaultInfo{ Name: u.Name, UID: string(u.UID), Groups: u.Groups, }, nil }
func (p *provisioningIdentityMapper) userForWithRetries(info authapi.UserIdentityInfo, allowedRetries int) (kuser.Info, error) { ctx := kapi.NewContext() identity, err := p.identity.GetIdentity(ctx, info.GetIdentityName()) if kerrs.IsNotFound(err) { user, err := p.createIdentityAndMapping(ctx, info) // Only retry for AlreadyExists errors, which can occur in the following cases: // * The same user was created by another identity provider with the same preferred username // * The same user was created by another instance of this identity provider // * The same identity was created by another instance of this identity provider if kerrs.IsAlreadyExists(err) && allowedRetries > 0 { return p.userForWithRetries(info, allowedRetries-1) } return user, err } if err != nil { return nil, err } return p.getMapping(ctx, identity) }