Synchronize SSH keys on login with LDAP + Fix SQLite deadlock on ldap ssh key deletion (#5557)
* Synchronize SSH keys on login with LDAP * BUG: Fix hang on sqlite during LDAP key deletion
This commit is contained in:
		
							parent
							
								
									2058c362a8
								
							
						
					
					
						commit
						8bb0a6f425
					
				
					 4 changed files with 39 additions and 18 deletions
				
			
		|  | @ -393,7 +393,13 @@ func LoginViaLDAP(user *User, login, password string, source *LoginSource, autoR | |||
| 		return nil, ErrUserNotExist{0, login, 0} | ||||
| 	} | ||||
| 
 | ||||
| 	var isAttributeSSHPublicKeySet = len(strings.TrimSpace(source.LDAP().AttributeSSHPublicKey)) > 0 | ||||
| 
 | ||||
| 	if !autoRegister { | ||||
| 		if isAttributeSSHPublicKeySet && synchronizeLdapSSHPublicKeys(user, source, sr.SSHPublicKey) { | ||||
| 			RewriteAllPublicKeys() | ||||
| 		} | ||||
| 
 | ||||
| 		return user, nil | ||||
| 	} | ||||
| 
 | ||||
|  | @ -421,7 +427,14 @@ func LoginViaLDAP(user *User, login, password string, source *LoginSource, autoR | |||
| 		IsActive:    true, | ||||
| 		IsAdmin:     sr.IsAdmin, | ||||
| 	} | ||||
| 	return user, CreateUser(user) | ||||
| 
 | ||||
| 	err := CreateUser(user) | ||||
| 
 | ||||
| 	if err == nil && isAttributeSSHPublicKeySet && addLdapSSHPublicKeys(user, source, sr.SSHPublicKey) { | ||||
| 		RewriteAllPublicKeys() | ||||
| 	} | ||||
| 
 | ||||
| 	return user, err | ||||
| } | ||||
| 
 | ||||
| //   _________   __________________________
 | ||||
|  |  | |||
|  | @ -451,11 +451,9 @@ func GetPublicKeyByID(keyID int64) (*PublicKey, error) { | |||
| 	return key, nil | ||||
| } | ||||
| 
 | ||||
| // SearchPublicKeyByContent searches content as prefix (leak e-mail part)
 | ||||
| // and returns public key found.
 | ||||
| func SearchPublicKeyByContent(content string) (*PublicKey, error) { | ||||
| func searchPublicKeyByContentWithEngine(e Engine, content string) (*PublicKey, error) { | ||||
| 	key := new(PublicKey) | ||||
| 	has, err := x. | ||||
| 	has, err := e. | ||||
| 		Where("content like ?", content+"%"). | ||||
| 		Get(key) | ||||
| 	if err != nil { | ||||
|  | @ -466,6 +464,12 @@ func SearchPublicKeyByContent(content string) (*PublicKey, error) { | |||
| 	return key, nil | ||||
| } | ||||
| 
 | ||||
| // SearchPublicKeyByContent searches content as prefix (leak e-mail part)
 | ||||
| // and returns public key found.
 | ||||
| func SearchPublicKeyByContent(content string) (*PublicKey, error) { | ||||
| 	return searchPublicKeyByContentWithEngine(x, content) | ||||
| } | ||||
| 
 | ||||
| // SearchPublicKey returns a list of public keys matching the provided arguments.
 | ||||
| func SearchPublicKey(uid int64, fingerprint string) ([]*PublicKey, error) { | ||||
| 	keys := make([]*PublicKey, 0, 5) | ||||
|  |  | |||
|  | @ -1402,7 +1402,7 @@ func deleteKeysMarkedForDeletion(keys []string) (bool, error) { | |||
| 	// Delete keys marked for deletion
 | ||||
| 	var sshKeysNeedUpdate bool | ||||
| 	for _, KeyToDelete := range keys { | ||||
| 		key, err := SearchPublicKeyByContent(KeyToDelete) | ||||
| 		key, err := searchPublicKeyByContentWithEngine(sess, KeyToDelete) | ||||
| 		if err != nil { | ||||
| 			log.Error(4, "SearchPublicKeyByContent: %v", err) | ||||
| 			continue | ||||
|  | @ -1421,7 +1421,8 @@ func deleteKeysMarkedForDeletion(keys []string) (bool, error) { | |||
| 	return sshKeysNeedUpdate, nil | ||||
| } | ||||
| 
 | ||||
| func addLdapSSHPublicKeys(s *LoginSource, usr *User, SSHPublicKeys []string) bool { | ||||
| // addLdapSSHPublicKeys add a users public keys. Returns true if there are changes.
 | ||||
| func addLdapSSHPublicKeys(usr *User, s *LoginSource, SSHPublicKeys []string) bool { | ||||
| 	var sshKeysNeedUpdate bool | ||||
| 	for _, sshKey := range SSHPublicKeys { | ||||
| 		_, _, _, _, err := ssh.ParseAuthorizedKey([]byte(sshKey)) | ||||
|  | @ -1440,7 +1441,8 @@ func addLdapSSHPublicKeys(s *LoginSource, usr *User, SSHPublicKeys []string) boo | |||
| 	return sshKeysNeedUpdate | ||||
| } | ||||
| 
 | ||||
| func synchronizeLdapSSHPublicKeys(s *LoginSource, SSHPublicKeys []string, usr *User) bool { | ||||
| // synchronizeLdapSSHPublicKeys updates a users public keys. Returns true if there are changes.
 | ||||
| func synchronizeLdapSSHPublicKeys(usr *User, s *LoginSource, SSHPublicKeys []string) bool { | ||||
| 	var sshKeysNeedUpdate bool | ||||
| 
 | ||||
| 	log.Trace("synchronizeLdapSSHPublicKeys[%s]: Handling LDAP Public SSH Key synchronization for user %s", s.Name, usr.Name) | ||||
|  | @ -1479,7 +1481,7 @@ func synchronizeLdapSSHPublicKeys(s *LoginSource, SSHPublicKeys []string, usr *U | |||
| 			newLdapSSHKeys = append(newLdapSSHKeys, LDAPPublicSSHKey) | ||||
| 		} | ||||
| 	} | ||||
| 	if addLdapSSHPublicKeys(s, usr, newLdapSSHKeys) { | ||||
| 	if addLdapSSHPublicKeys(usr, s, newLdapSSHKeys) { | ||||
| 		sshKeysNeedUpdate = true | ||||
| 	} | ||||
| 
 | ||||
|  | @ -1581,7 +1583,7 @@ func SyncExternalUsers() { | |||
| 						log.Error(4, "SyncExternalUsers[%s]: Error creating user %s: %v", s.Name, su.Username, err) | ||||
| 					} else if isAttributeSSHPublicKeySet { | ||||
| 						log.Trace("SyncExternalUsers[%s]: Adding LDAP Public SSH Keys for user %s", s.Name, usr.Name) | ||||
| 						if addLdapSSHPublicKeys(s, usr, su.SSHPublicKey) { | ||||
| 						if addLdapSSHPublicKeys(usr, s, su.SSHPublicKey) { | ||||
| 							sshKeysNeedUpdate = true | ||||
| 						} | ||||
| 					} | ||||
|  | @ -1589,7 +1591,7 @@ func SyncExternalUsers() { | |||
| 					existingUsers = append(existingUsers, usr.ID) | ||||
| 
 | ||||
| 					// Synchronize SSH Public Key if that attribute is set
 | ||||
| 					if isAttributeSSHPublicKeySet && synchronizeLdapSSHPublicKeys(s, su.SSHPublicKey, usr) { | ||||
| 					if isAttributeSSHPublicKeySet && synchronizeLdapSSHPublicKeys(usr, s, su.SSHPublicKey) { | ||||
| 						sshKeysNeedUpdate = true | ||||
| 					} | ||||
| 
 | ||||
|  |  | |||
|  | @ -247,10 +247,10 @@ func (ls *Source) SearchEntry(name, passwd string, directBind bool) *SearchResul | |||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	log.Trace("Fetching attributes '%v', '%v', '%v', '%v' with filter %s and base %s", ls.AttributeUsername, ls.AttributeName, ls.AttributeSurname, ls.AttributeMail, userFilter, userDN) | ||||
| 	log.Trace("Fetching attributes '%v', '%v', '%v', '%v', '%v' with filter %s and base %s", ls.AttributeUsername, ls.AttributeName, ls.AttributeSurname, ls.AttributeMail, ls.AttributeSSHPublicKey, userFilter, userDN) | ||||
| 	search := ldap.NewSearchRequest( | ||||
| 		userDN, ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false, userFilter, | ||||
| 		[]string{ls.AttributeUsername, ls.AttributeName, ls.AttributeSurname, ls.AttributeMail}, | ||||
| 		[]string{ls.AttributeUsername, ls.AttributeName, ls.AttributeSurname, ls.AttributeMail, ls.AttributeSSHPublicKey}, | ||||
| 		nil) | ||||
| 
 | ||||
| 	sr, err := l.Search(search) | ||||
|  | @ -271,6 +271,7 @@ func (ls *Source) SearchEntry(name, passwd string, directBind bool) *SearchResul | |||
| 	firstname := sr.Entries[0].GetAttributeValue(ls.AttributeName) | ||||
| 	surname := sr.Entries[0].GetAttributeValue(ls.AttributeSurname) | ||||
| 	mail := sr.Entries[0].GetAttributeValue(ls.AttributeMail) | ||||
| 	sshPublicKey := sr.Entries[0].GetAttributeValues(ls.AttributeSSHPublicKey) | ||||
| 	isAdmin := checkAdmin(l, ls, userDN) | ||||
| 
 | ||||
| 	if !directBind && ls.AttributesInBind { | ||||
|  | @ -282,11 +283,12 @@ func (ls *Source) SearchEntry(name, passwd string, directBind bool) *SearchResul | |||
| 	} | ||||
| 
 | ||||
| 	return &SearchResult{ | ||||
| 		Username: username, | ||||
| 		Name:     firstname, | ||||
| 		Surname:  surname, | ||||
| 		Mail:     mail, | ||||
| 		IsAdmin:  isAdmin, | ||||
| 		Username:     username, | ||||
| 		Name:         firstname, | ||||
| 		Surname:      surname, | ||||
| 		Mail:         mail, | ||||
| 		SSHPublicKey: sshPublicKey, | ||||
| 		IsAdmin:      isAdmin, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue