aboutsummaryrefslogtreecommitdiffstats
path: root/models/user.go
diff options
context:
space:
mode:
Diffstat (limited to 'models/user.go')
-rw-r--r--models/user.go134
1 files changed, 133 insertions, 1 deletions
diff --git a/models/user.go b/models/user.go
index d642054979..1497eef44d 100644
--- a/models/user.go
+++ b/models/user.go
@@ -1356,6 +1356,119 @@ func GetWatchedRepos(userID int64, private bool) ([]*Repository, error) {
return repos, nil
}
+// deleteKeysMarkedForDeletion returns true if ssh keys needs update
+func deleteKeysMarkedForDeletion(keys []string) (bool, error) {
+ // Start session
+ sess := x.NewSession()
+ defer sess.Close()
+ if err := sess.Begin(); err != nil {
+ return false, err
+ }
+
+ // Delete keys marked for deletion
+ var sshKeysNeedUpdate bool
+ for _, KeyToDelete := range keys {
+ key, err := SearchPublicKeyByContent(KeyToDelete)
+ if err != nil {
+ log.Error(4, "SearchPublicKeyByContent: %v", err)
+ continue
+ }
+ if err = deletePublicKeys(sess, key.ID); err != nil {
+ log.Error(4, "deletePublicKeys: %v", err)
+ continue
+ }
+ sshKeysNeedUpdate = true
+ }
+
+ if err := sess.Commit(); err != nil {
+ return false, err
+ }
+
+ return sshKeysNeedUpdate, nil
+}
+
+func addLdapSSHPublicKeys(s *LoginSource, usr *User, SSHPublicKeys []string) bool {
+ var sshKeysNeedUpdate bool
+ for _, sshKey := range SSHPublicKeys {
+ if strings.HasPrefix(strings.ToLower(sshKey), "ssh") {
+ sshKeyName := fmt.Sprintf("%s-%s", s.Name, sshKey[0:40])
+ if _, err := AddPublicKey(usr.ID, sshKeyName, sshKey, s.ID); err != nil {
+ log.Error(4, "addLdapSSHPublicKeys[%s]: Error adding LDAP Public SSH Key for user %s: %v", s.Name, usr.Name, err)
+ } else {
+ log.Trace("addLdapSSHPublicKeys[%s]: Added LDAP Public SSH Key for user %s", s.Name, usr.Name)
+ sshKeysNeedUpdate = true
+ }
+ } else {
+ log.Warn("addLdapSSHPublicKeys[%s]: Skipping invalid LDAP Public SSH Key for user %s: %v", s.Name, usr.Name, sshKey)
+ }
+ }
+ return sshKeysNeedUpdate
+}
+
+func synchronizeLdapSSHPublicKeys(s *LoginSource, SSHPublicKeys []string, usr *User) bool {
+ var sshKeysNeedUpdate bool
+
+ log.Trace("synchronizeLdapSSHPublicKeys[%s]: Handling LDAP Public SSH Key synchronization for user %s", s.Name, usr.Name)
+
+ // Get Public Keys from DB with current LDAP source
+ var giteaKeys []string
+ keys, err := ListPublicLdapSSHKeys(usr.ID, s.ID)
+ if err != nil {
+ log.Error(4, "synchronizeLdapSSHPublicKeys[%s]: Error listing LDAP Public SSH Keys for user %s: %v", s.Name, usr.Name, err)
+ }
+
+ for _, v := range keys {
+ giteaKeys = append(giteaKeys, v.OmitEmail())
+ }
+
+ // Get Public Keys from LDAP and skip duplicate keys
+ var ldapKeys []string
+ for _, v := range SSHPublicKeys {
+ ldapKey := strings.Join(strings.Split(v, " ")[:2], " ")
+ if !util.ExistsInSlice(ldapKey, ldapKeys) {
+ ldapKeys = append(ldapKeys, ldapKey)
+ }
+ }
+
+ // Check if Public Key sync is needed
+ if util.IsEqualSlice(giteaKeys, ldapKeys) {
+ log.Trace("synchronizeLdapSSHPublicKeys[%s]: LDAP Public Keys are already in sync for %s (LDAP:%v/DB:%v)", s.Name, usr.Name, len(ldapKeys), len(giteaKeys))
+ return false
+ }
+ log.Trace("synchronizeLdapSSHPublicKeys[%s]: LDAP Public Key needs update for user %s (LDAP:%v/DB:%v)", s.Name, usr.Name, len(ldapKeys), len(giteaKeys))
+
+ // Add LDAP Public SSH Keys that doesn't already exist in DB
+ var newLdapSSHKeys []string
+ for _, LDAPPublicSSHKey := range ldapKeys {
+ if !util.ExistsInSlice(LDAPPublicSSHKey, giteaKeys) {
+ newLdapSSHKeys = append(newLdapSSHKeys, LDAPPublicSSHKey)
+ }
+ }
+ if addLdapSSHPublicKeys(s, usr, newLdapSSHKeys) {
+ sshKeysNeedUpdate = true
+ }
+
+ // Mark LDAP keys from DB that doesn't exist in LDAP for deletion
+ var giteaKeysToDelete []string
+ for _, giteaKey := range giteaKeys {
+ if !util.ExistsInSlice(giteaKey, ldapKeys) {
+ log.Trace("synchronizeLdapSSHPublicKeys[%s]: Marking LDAP Public SSH Key for deletion for user %s: %v", s.Name, usr.Name, giteaKey)
+ giteaKeysToDelete = append(giteaKeysToDelete, giteaKey)
+ }
+ }
+
+ // Delete LDAP keys from DB that doesn't exist in LDAP
+ needUpd, err := deleteKeysMarkedForDeletion(giteaKeysToDelete)
+ if err != nil {
+ log.Error(4, "synchronizeLdapSSHPublicKeys[%s]: Error deleting LDAP Public SSH Keys marked for deletion for user %s: %v", s.Name, usr.Name, err)
+ }
+ if needUpd {
+ sshKeysNeedUpdate = true
+ }
+
+ return sshKeysNeedUpdate
+}
+
// SyncExternalUsers is used to synchronize users with external authorization source
func SyncExternalUsers() {
if !taskStatusTable.StartIfNotRunning(syncExternalUsers) {
@@ -1377,10 +1490,13 @@ func SyncExternalUsers() {
if !s.IsActived || !s.IsSyncEnabled {
continue
}
+
if s.IsLDAP() {
log.Trace("Doing: SyncExternalUsers[%s]", s.Name)
var existingUsers []int64
+ var isAttributeSSHPublicKeySet = len(strings.TrimSpace(s.LDAP().AttributeSSHPublicKey)) > 0
+ var sshKeysNeedUpdate bool
// Find all users with this login type
var users []User
@@ -1389,7 +1505,6 @@ func SyncExternalUsers() {
Find(&users)
sr := s.LDAP().SearchEntries()
-
for _, su := range sr {
if len(su.Username) == 0 {
continue
@@ -1426,11 +1541,23 @@ func SyncExternalUsers() {
}
err = CreateUser(usr)
+
if err != nil {
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) {
+ sshKeysNeedUpdate = true
+ }
}
} else if updateExisting {
existingUsers = append(existingUsers, usr.ID)
+
+ // Synchronize SSH Public Key if that attribute is set
+ if isAttributeSSHPublicKeySet && synchronizeLdapSSHPublicKeys(s, su.SSHPublicKey, usr) {
+ sshKeysNeedUpdate = true
+ }
+
// Check if user data has changed
if (len(s.LDAP().AdminFilter) > 0 && usr.IsAdmin != su.IsAdmin) ||
strings.ToLower(usr.Email) != strings.ToLower(su.Mail) ||
@@ -1455,6 +1582,11 @@ func SyncExternalUsers() {
}
}
+ // Rewrite authorized_keys file if LDAP Public SSH Key attribute is set and any key was added or removed
+ if sshKeysNeedUpdate {
+ RewriteAllPublicKeys()
+ }
+
// Deactivate users not present in LDAP
if updateExisting {
for _, usr := range users {