Skip to content

Commit 8bb0a6f

Browse files
zeripathtechknowlogick
authored andcommitted
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
1 parent 2058c36 commit 8bb0a6f

File tree

4 files changed

+39
-18
lines changed

4 files changed

+39
-18
lines changed

models/login_source.go

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -393,7 +393,13 @@ func LoginViaLDAP(user *User, login, password string, source *LoginSource, autoR
393393
return nil, ErrUserNotExist{0, login, 0}
394394
}
395395

396+
var isAttributeSSHPublicKeySet = len(strings.TrimSpace(source.LDAP().AttributeSSHPublicKey)) > 0
397+
396398
if !autoRegister {
399+
if isAttributeSSHPublicKeySet && synchronizeLdapSSHPublicKeys(user, source, sr.SSHPublicKey) {
400+
RewriteAllPublicKeys()
401+
}
402+
397403
return user, nil
398404
}
399405

@@ -421,7 +427,14 @@ func LoginViaLDAP(user *User, login, password string, source *LoginSource, autoR
421427
IsActive: true,
422428
IsAdmin: sr.IsAdmin,
423429
}
424-
return user, CreateUser(user)
430+
431+
err := CreateUser(user)
432+
433+
if err == nil && isAttributeSSHPublicKeySet && addLdapSSHPublicKeys(user, source, sr.SSHPublicKey) {
434+
RewriteAllPublicKeys()
435+
}
436+
437+
return user, err
425438
}
426439

427440
// _________ __________________________

models/ssh_key.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -451,11 +451,9 @@ func GetPublicKeyByID(keyID int64) (*PublicKey, error) {
451451
return key, nil
452452
}
453453

454-
// SearchPublicKeyByContent searches content as prefix (leak e-mail part)
455-
// and returns public key found.
456-
func SearchPublicKeyByContent(content string) (*PublicKey, error) {
454+
func searchPublicKeyByContentWithEngine(e Engine, content string) (*PublicKey, error) {
457455
key := new(PublicKey)
458-
has, err := x.
456+
has, err := e.
459457
Where("content like ?", content+"%").
460458
Get(key)
461459
if err != nil {
@@ -466,6 +464,12 @@ func SearchPublicKeyByContent(content string) (*PublicKey, error) {
466464
return key, nil
467465
}
468466

467+
// SearchPublicKeyByContent searches content as prefix (leak e-mail part)
468+
// and returns public key found.
469+
func SearchPublicKeyByContent(content string) (*PublicKey, error) {
470+
return searchPublicKeyByContentWithEngine(x, content)
471+
}
472+
469473
// SearchPublicKey returns a list of public keys matching the provided arguments.
470474
func SearchPublicKey(uid int64, fingerprint string) ([]*PublicKey, error) {
471475
keys := make([]*PublicKey, 0, 5)

models/user.go

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1402,7 +1402,7 @@ func deleteKeysMarkedForDeletion(keys []string) (bool, error) {
14021402
// Delete keys marked for deletion
14031403
var sshKeysNeedUpdate bool
14041404
for _, KeyToDelete := range keys {
1405-
key, err := SearchPublicKeyByContent(KeyToDelete)
1405+
key, err := searchPublicKeyByContentWithEngine(sess, KeyToDelete)
14061406
if err != nil {
14071407
log.Error(4, "SearchPublicKeyByContent: %v", err)
14081408
continue
@@ -1421,7 +1421,8 @@ func deleteKeysMarkedForDeletion(keys []string) (bool, error) {
14211421
return sshKeysNeedUpdate, nil
14221422
}
14231423

1424-
func addLdapSSHPublicKeys(s *LoginSource, usr *User, SSHPublicKeys []string) bool {
1424+
// addLdapSSHPublicKeys add a users public keys. Returns true if there are changes.
1425+
func addLdapSSHPublicKeys(usr *User, s *LoginSource, SSHPublicKeys []string) bool {
14251426
var sshKeysNeedUpdate bool
14261427
for _, sshKey := range SSHPublicKeys {
14271428
_, _, _, _, err := ssh.ParseAuthorizedKey([]byte(sshKey))
@@ -1440,7 +1441,8 @@ func addLdapSSHPublicKeys(s *LoginSource, usr *User, SSHPublicKeys []string) boo
14401441
return sshKeysNeedUpdate
14411442
}
14421443

1443-
func synchronizeLdapSSHPublicKeys(s *LoginSource, SSHPublicKeys []string, usr *User) bool {
1444+
// synchronizeLdapSSHPublicKeys updates a users public keys. Returns true if there are changes.
1445+
func synchronizeLdapSSHPublicKeys(usr *User, s *LoginSource, SSHPublicKeys []string) bool {
14441446
var sshKeysNeedUpdate bool
14451447

14461448
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
14791481
newLdapSSHKeys = append(newLdapSSHKeys, LDAPPublicSSHKey)
14801482
}
14811483
}
1482-
if addLdapSSHPublicKeys(s, usr, newLdapSSHKeys) {
1484+
if addLdapSSHPublicKeys(usr, s, newLdapSSHKeys) {
14831485
sshKeysNeedUpdate = true
14841486
}
14851487

@@ -1581,15 +1583,15 @@ func SyncExternalUsers() {
15811583
log.Error(4, "SyncExternalUsers[%s]: Error creating user %s: %v", s.Name, su.Username, err)
15821584
} else if isAttributeSSHPublicKeySet {
15831585
log.Trace("SyncExternalUsers[%s]: Adding LDAP Public SSH Keys for user %s", s.Name, usr.Name)
1584-
if addLdapSSHPublicKeys(s, usr, su.SSHPublicKey) {
1586+
if addLdapSSHPublicKeys(usr, s, su.SSHPublicKey) {
15851587
sshKeysNeedUpdate = true
15861588
}
15871589
}
15881590
} else if updateExisting {
15891591
existingUsers = append(existingUsers, usr.ID)
15901592

15911593
// Synchronize SSH Public Key if that attribute is set
1592-
if isAttributeSSHPublicKeySet && synchronizeLdapSSHPublicKeys(s, su.SSHPublicKey, usr) {
1594+
if isAttributeSSHPublicKeySet && synchronizeLdapSSHPublicKeys(usr, s, su.SSHPublicKey) {
15931595
sshKeysNeedUpdate = true
15941596
}
15951597

modules/auth/ldap/ldap.go

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -247,10 +247,10 @@ func (ls *Source) SearchEntry(name, passwd string, directBind bool) *SearchResul
247247
return nil
248248
}
249249

250-
log.Trace("Fetching attributes '%v', '%v', '%v', '%v' with filter %s and base %s", ls.AttributeUsername, ls.AttributeName, ls.AttributeSurname, ls.AttributeMail, userFilter, userDN)
250+
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)
251251
search := ldap.NewSearchRequest(
252252
userDN, ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false, userFilter,
253-
[]string{ls.AttributeUsername, ls.AttributeName, ls.AttributeSurname, ls.AttributeMail},
253+
[]string{ls.AttributeUsername, ls.AttributeName, ls.AttributeSurname, ls.AttributeMail, ls.AttributeSSHPublicKey},
254254
nil)
255255

256256
sr, err := l.Search(search)
@@ -271,6 +271,7 @@ func (ls *Source) SearchEntry(name, passwd string, directBind bool) *SearchResul
271271
firstname := sr.Entries[0].GetAttributeValue(ls.AttributeName)
272272
surname := sr.Entries[0].GetAttributeValue(ls.AttributeSurname)
273273
mail := sr.Entries[0].GetAttributeValue(ls.AttributeMail)
274+
sshPublicKey := sr.Entries[0].GetAttributeValues(ls.AttributeSSHPublicKey)
274275
isAdmin := checkAdmin(l, ls, userDN)
275276

276277
if !directBind && ls.AttributesInBind {
@@ -282,11 +283,12 @@ func (ls *Source) SearchEntry(name, passwd string, directBind bool) *SearchResul
282283
}
283284

284285
return &SearchResult{
285-
Username: username,
286-
Name: firstname,
287-
Surname: surname,
288-
Mail: mail,
289-
IsAdmin: isAdmin,
286+
Username: username,
287+
Name: firstname,
288+
Surname: surname,
289+
Mail: mail,
290+
SSHPublicKey: sshPublicKey,
291+
IsAdmin: isAdmin,
290292
}
291293
}
292294

0 commit comments

Comments
 (0)