mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2024-11-04 09:19:06 +01:00
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}
|
return nil, ErrUserNotExist{0, login, 0}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var isAttributeSSHPublicKeySet = len(strings.TrimSpace(source.LDAP().AttributeSSHPublicKey)) > 0
|
||||||
|
|
||||||
if !autoRegister {
|
if !autoRegister {
|
||||||
|
if isAttributeSSHPublicKeySet && synchronizeLdapSSHPublicKeys(user, source, sr.SSHPublicKey) {
|
||||||
|
RewriteAllPublicKeys()
|
||||||
|
}
|
||||||
|
|
||||||
return user, nil
|
return user, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -421,7 +427,14 @@ func LoginViaLDAP(user *User, login, password string, source *LoginSource, autoR
|
||||||
IsActive: true,
|
IsActive: true,
|
||||||
IsAdmin: sr.IsAdmin,
|
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
|
return key, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SearchPublicKeyByContent searches content as prefix (leak e-mail part)
|
func searchPublicKeyByContentWithEngine(e Engine, content string) (*PublicKey, error) {
|
||||||
// and returns public key found.
|
|
||||||
func SearchPublicKeyByContent(content string) (*PublicKey, error) {
|
|
||||||
key := new(PublicKey)
|
key := new(PublicKey)
|
||||||
has, err := x.
|
has, err := e.
|
||||||
Where("content like ?", content+"%").
|
Where("content like ?", content+"%").
|
||||||
Get(key)
|
Get(key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -466,6 +464,12 @@ func SearchPublicKeyByContent(content string) (*PublicKey, error) {
|
||||||
return key, nil
|
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.
|
// SearchPublicKey returns a list of public keys matching the provided arguments.
|
||||||
func SearchPublicKey(uid int64, fingerprint string) ([]*PublicKey, error) {
|
func SearchPublicKey(uid int64, fingerprint string) ([]*PublicKey, error) {
|
||||||
keys := make([]*PublicKey, 0, 5)
|
keys := make([]*PublicKey, 0, 5)
|
||||||
|
|
|
@ -1402,7 +1402,7 @@ func deleteKeysMarkedForDeletion(keys []string) (bool, error) {
|
||||||
// Delete keys marked for deletion
|
// Delete keys marked for deletion
|
||||||
var sshKeysNeedUpdate bool
|
var sshKeysNeedUpdate bool
|
||||||
for _, KeyToDelete := range keys {
|
for _, KeyToDelete := range keys {
|
||||||
key, err := SearchPublicKeyByContent(KeyToDelete)
|
key, err := searchPublicKeyByContentWithEngine(sess, KeyToDelete)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error(4, "SearchPublicKeyByContent: %v", err)
|
log.Error(4, "SearchPublicKeyByContent: %v", err)
|
||||||
continue
|
continue
|
||||||
|
@ -1421,7 +1421,8 @@ func deleteKeysMarkedForDeletion(keys []string) (bool, error) {
|
||||||
return sshKeysNeedUpdate, nil
|
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
|
var sshKeysNeedUpdate bool
|
||||||
for _, sshKey := range SSHPublicKeys {
|
for _, sshKey := range SSHPublicKeys {
|
||||||
_, _, _, _, err := ssh.ParseAuthorizedKey([]byte(sshKey))
|
_, _, _, _, err := ssh.ParseAuthorizedKey([]byte(sshKey))
|
||||||
|
@ -1440,7 +1441,8 @@ func addLdapSSHPublicKeys(s *LoginSource, usr *User, SSHPublicKeys []string) boo
|
||||||
return sshKeysNeedUpdate
|
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
|
var sshKeysNeedUpdate bool
|
||||||
|
|
||||||
log.Trace("synchronizeLdapSSHPublicKeys[%s]: Handling LDAP Public SSH Key synchronization for user %s", s.Name, usr.Name)
|
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)
|
newLdapSSHKeys = append(newLdapSSHKeys, LDAPPublicSSHKey)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if addLdapSSHPublicKeys(s, usr, newLdapSSHKeys) {
|
if addLdapSSHPublicKeys(usr, s, newLdapSSHKeys) {
|
||||||
sshKeysNeedUpdate = true
|
sshKeysNeedUpdate = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1581,7 +1583,7 @@ func SyncExternalUsers() {
|
||||||
log.Error(4, "SyncExternalUsers[%s]: Error creating user %s: %v", s.Name, su.Username, err)
|
log.Error(4, "SyncExternalUsers[%s]: Error creating user %s: %v", s.Name, su.Username, err)
|
||||||
} else if isAttributeSSHPublicKeySet {
|
} else if isAttributeSSHPublicKeySet {
|
||||||
log.Trace("SyncExternalUsers[%s]: Adding LDAP Public SSH Keys for user %s", s.Name, usr.Name)
|
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
|
sshKeysNeedUpdate = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1589,7 +1591,7 @@ func SyncExternalUsers() {
|
||||||
existingUsers = append(existingUsers, usr.ID)
|
existingUsers = append(existingUsers, usr.ID)
|
||||||
|
|
||||||
// Synchronize SSH Public Key if that attribute is set
|
// 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
|
sshKeysNeedUpdate = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -247,10 +247,10 @@ func (ls *Source) SearchEntry(name, passwd string, directBind bool) *SearchResul
|
||||||
return nil
|
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(
|
search := ldap.NewSearchRequest(
|
||||||
userDN, ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false, userFilter,
|
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)
|
nil)
|
||||||
|
|
||||||
sr, err := l.Search(search)
|
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)
|
firstname := sr.Entries[0].GetAttributeValue(ls.AttributeName)
|
||||||
surname := sr.Entries[0].GetAttributeValue(ls.AttributeSurname)
|
surname := sr.Entries[0].GetAttributeValue(ls.AttributeSurname)
|
||||||
mail := sr.Entries[0].GetAttributeValue(ls.AttributeMail)
|
mail := sr.Entries[0].GetAttributeValue(ls.AttributeMail)
|
||||||
|
sshPublicKey := sr.Entries[0].GetAttributeValues(ls.AttributeSSHPublicKey)
|
||||||
isAdmin := checkAdmin(l, ls, userDN)
|
isAdmin := checkAdmin(l, ls, userDN)
|
||||||
|
|
||||||
if !directBind && ls.AttributesInBind {
|
if !directBind && ls.AttributesInBind {
|
||||||
|
@ -282,11 +283,12 @@ func (ls *Source) SearchEntry(name, passwd string, directBind bool) *SearchResul
|
||||||
}
|
}
|
||||||
|
|
||||||
return &SearchResult{
|
return &SearchResult{
|
||||||
Username: username,
|
Username: username,
|
||||||
Name: firstname,
|
Name: firstname,
|
||||||
Surname: surname,
|
Surname: surname,
|
||||||
Mail: mail,
|
Mail: mail,
|
||||||
IsAdmin: isAdmin,
|
SSHPublicKey: sshPublicKey,
|
||||||
|
IsAdmin: isAdmin,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue