Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LDAP Public SSH Keys synchronization #1844

Merged
merged 50 commits into from May 24, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
64312ab
Add LDAP Key Synchronization feature
dnmgns May 31, 2017
d17981b
Move block: user data has changed
dnmgns Jun 25, 2017
cc046c7
Add LDAP Key Synchronization feature
dnmgns May 31, 2017
26a9205
Move block: user data has changed
dnmgns Jun 25, 2017
d005086
Merge branch 'master' of https://github.com/dnmgns/gitea
Oct 15, 2017
e0da1d7
Oops
Oct 15, 2017
b6e2985
Fix space
Oct 15, 2017
a20d4f1
Merge branch 'master' of https://github.com/go-gitea/gitea
Nov 5, 2017
1d4dbed
null def null not needed
Nov 5, 2017
55424bf
move existsInSlice and IsEqualSlice to compare
Nov 5, 2017
922e76c
revert just whitespace
Nov 5, 2017
03690de
Make compare funcs exported
Nov 5, 2017
ec95606
Fix typo in comment
Nov 5, 2017
71cd39d
Change comment, try to make lint happy
Nov 5, 2017
eddb932
Add migration: add login source id column for public_key table
Nov 5, 2017
ab9f88b
Only update keys if needed
Nov 5, 2017
056734f
Make lint happy
Nov 5, 2017
83cd353
Trigger a build.
Nov 6, 2017
56453ac
Merge remote-tracking branch 'upstream/master'
dnmgns Dec 6, 2017
027c832
Simple validity check for ssh key
Dec 6, 2017
9915566
Merge remote-tracking branch 'upstream/master'
Dec 19, 2017
23b343d
Move migration to resolve conflict
Dec 19, 2017
98a8083
Only update columns which needs update
Dec 24, 2017
934223d
Merge remote-tracking branch 'upstream/master'
Jan 9, 2018
615e9c5
Do not always update all columns
Jan 21, 2018
45439fd
Add function to only list pubkey synchronized from ldap
Jan 21, 2018
a199541
Only list pub ssh keys synchronized from ldap. Do not sort strings as…
Jan 21, 2018
93f11ea
Merge remote-tracking branch 'upstream/master'
Jan 21, 2018
8b6f96c
Only get keys belonging to current login source id
Jan 25, 2018
0d8d954
Merge remote-tracking branch 'upstream/master'
Jan 25, 2018
cf6ba93
Merge remote-tracking branch 'upstream/master'
Feb 15, 2018
68a1dc7
login source, not ldap source
Feb 15, 2018
68e206a
A better argument name
Feb 15, 2018
3f3ab5e
Merge remote-tracking branch 'upstream/master'
dnmgns Mar 4, 2018
aff1346
Remove unused line
dnmgns Mar 4, 2018
b4876d3
Merge remote-tracking branch 'upstream/master'
Mar 22, 2018
dc85ddc
Merge remote-tracking branch 'upstream/master'
Apr 10, 2018
3ff65c7
Fix import
Apr 10, 2018
3181cb9
empty
Apr 10, 2018
f05fe63
Merge remote-tracking branch 'upstream/master'
Apr 19, 2018
ee1fcd9
Merge branch 'master' into master
dnmgns Apr 20, 2018
3b75a05
Merge remote-tracking branch 'upstream/master'
May 3, 2018
9f10f71
Merge remote-tracking branch 'upstream/master'
May 19, 2018
237ae23
Set default login source id to 0
May 19, 2018
f3b4b31
Fixes spacing for LDAPConfig
May 19, 2018
32d8e0f
empty
May 19, 2018
47cab1d
Merge branch 'master' into master
lafriks May 23, 2018
bc32826
Some minor cleanup. Add integration tests (updete dep testify)
lafriks May 24, 2018
cb13880
Revert to update only needed user columns
lafriks May 24, 2018
8a56bf3
Merge branch 'master' into master
lafriks May 24, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 4 additions & 2 deletions Gopkg.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

79 changes: 58 additions & 21 deletions integrations/auth_ldap_test.go
Expand Up @@ -40,7 +40,11 @@ var gitLDAPUsers = []ldapUser{
Password: "hermes",
FullName: "Conrad Hermes",
Email: "hermes@planetexpress.com",
IsAdmin: true,
SSHKeys: []string{
"SHA256:qLY06smKfHoW/92yXySpnxFR10QFrLdRjf/GNPvwcW8",
"SHA256:QlVTuM5OssDatqidn2ffY+Lc4YA5Fs78U+0KOHI51jQ",
},
IsAdmin: true,
},
{
UserName: "fry",
Expand Down Expand Up @@ -89,26 +93,27 @@ func getLDAPServerHost() string {
return host
}

func addAuthSourceLDAP(t *testing.T) {
func addAuthSourceLDAP(t *testing.T, sshKeyAttribute string) {
session := loginUser(t, "user1")
csrf := GetCSRF(t, session, "/admin/auths/new")
req := NewRequestWithValues(t, "POST", "/admin/auths/new", map[string]string{
"_csrf": csrf,
"type": "2",
"name": "ldap",
"host": getLDAPServerHost(),
"port": "389",
"bind_dn": "uid=gitea,ou=service,dc=planetexpress,dc=com",
"bind_password": "password",
"user_base": "ou=people,dc=planetexpress,dc=com",
"filter": "(&(objectClass=inetOrgPerson)(memberOf=cn=git,ou=people,dc=planetexpress,dc=com)(uid=%s))",
"admin_filter": "(memberOf=cn=admin_staff,ou=people,dc=planetexpress,dc=com)",
"attribute_username": "uid",
"attribute_name": "givenName",
"attribute_surname": "sn",
"attribute_mail": "mail",
"is_sync_enabled": "on",
"is_active": "on",
"_csrf": csrf,
"type": "2",
"name": "ldap",
"host": getLDAPServerHost(),
"port": "389",
"bind_dn": "uid=gitea,ou=service,dc=planetexpress,dc=com",
"bind_password": "password",
"user_base": "ou=people,dc=planetexpress,dc=com",
"filter": "(&(objectClass=inetOrgPerson)(memberOf=cn=git,ou=people,dc=planetexpress,dc=com)(uid=%s))",
"admin_filter": "(memberOf=cn=admin_staff,ou=people,dc=planetexpress,dc=com)",
"attribute_username": "uid",
"attribute_name": "givenName",
"attribute_surname": "sn",
"attribute_mail": "mail",
"attribute_ssh_public_key": sshKeyAttribute,
"is_sync_enabled": "on",
"is_active": "on",
})
session.MakeRequest(t, req, http.StatusFound)
}
Expand All @@ -119,7 +124,7 @@ func TestLDAPUserSignin(t *testing.T) {
return
}
prepareTestEnv(t)
addAuthSourceLDAP(t)
addAuthSourceLDAP(t, "")

u := gitLDAPUsers[0]

Expand All @@ -140,7 +145,7 @@ func TestLDAPUserSync(t *testing.T) {
return
}
prepareTestEnv(t)
addAuthSourceLDAP(t)
addAuthSourceLDAP(t, "")
models.SyncExternalUsers()

session := loginUser(t, "user1")
Expand Down Expand Up @@ -186,9 +191,41 @@ func TestLDAPUserSigninFailed(t *testing.T) {
return
}
prepareTestEnv(t)
addAuthSourceLDAP(t)
addAuthSourceLDAP(t, "")

u := otherLDAPUsers[0]

testLoginFailed(t, u.UserName, u.Password, i18n.Tr("en", "form.username_password_incorrect"))
}

func TestLDAPUserSSHKeySync(t *testing.T) {
if skipLDAPTests() {
t.Skip()
return
}
prepareTestEnv(t)
addAuthSourceLDAP(t, "sshPublicKey")
models.SyncExternalUsers()

// Check if users has SSH keys synced
for _, u := range gitLDAPUsers {
if len(u.SSHKeys) == 0 {
continue
}
session := loginUserWithPassword(t, u.UserName, u.Password)

req := NewRequest(t, "GET", "/user/settings/keys")
resp := session.MakeRequest(t, req, http.StatusOK)

htmlDoc := NewHTMLParser(t, resp.Body)

divs := htmlDoc.doc.Find(".key.list .print.meta")

syncedKeys := make([]string, divs.Length())
for i := 0; i < divs.Length(); i++ {
syncedKeys[i] = strings.TrimSpace(divs.Eq(i).Text())
}

assert.ElementsMatch(t, u.SSHKeys, syncedKeys)
}
}
2 changes: 2 additions & 0 deletions models/migrations/migrations.go
Expand Up @@ -184,6 +184,8 @@ var migrations = []Migration{
NewMigration("add multiple assignees", addMultipleAssignees),
// v65 -> v66
NewMigration("add u2f", addU2FReg),
// v66 -> v67
NewMigration("add login source id column for public_key table", addLoginSourceIDToPublicKeyTable),
}

// Migrate database to current version
Expand Down
22 changes: 22 additions & 0 deletions models/migrations/v66.go
@@ -0,0 +1,22 @@
// Copyright 2017 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package migrations

import (
"fmt"

"github.com/go-xorm/xorm"
)

func addLoginSourceIDToPublicKeyTable(x *xorm.Engine) error {
type PublicKey struct {
LoginSourceID int64 `xorm:"NOT NULL DEFAULT 0"`
}

if err := x.Sync2(new(PublicKey)); err != nil {
return fmt.Errorf("Sync2: %v", err)
}
return nil
}
38 changes: 24 additions & 14 deletions models/ssh_key.go
Expand Up @@ -47,13 +47,14 @@ const (

// PublicKey represents a user or deploy SSH public key.
type PublicKey struct {
ID int64 `xorm:"pk autoincr"`
OwnerID int64 `xorm:"INDEX NOT NULL"`
Name string `xorm:"NOT NULL"`
Fingerprint string `xorm:"NOT NULL"`
Content string `xorm:"TEXT NOT NULL"`
Mode AccessMode `xorm:"NOT NULL DEFAULT 2"`
Type KeyType `xorm:"NOT NULL DEFAULT 1"`
ID int64 `xorm:"pk autoincr"`
OwnerID int64 `xorm:"INDEX NOT NULL"`
Name string `xorm:"NOT NULL"`
Fingerprint string `xorm:"NOT NULL"`
Content string `xorm:"TEXT NOT NULL"`
Mode AccessMode `xorm:"NOT NULL DEFAULT 2"`
Type KeyType `xorm:"NOT NULL DEFAULT 1"`
LoginSourceID int64 `xorm:"NOT NULL DEFAULT 0"`

CreatedUnix util.TimeStamp `xorm:"created"`
UpdatedUnix util.TimeStamp `xorm:"updated"`
Expand Down Expand Up @@ -391,7 +392,7 @@ func addKey(e Engine, key *PublicKey) (err error) {
}

// AddPublicKey adds new public key to database and authorized_keys file.
func AddPublicKey(ownerID int64, name, content string) (*PublicKey, error) {
func AddPublicKey(ownerID int64, name, content string, LoginSourceID int64) (*PublicKey, error) {
log.Trace(content)

fingerprint, err := calcFingerprint(content)
Expand Down Expand Up @@ -420,12 +421,13 @@ func AddPublicKey(ownerID int64, name, content string) (*PublicKey, error) {
}

key := &PublicKey{
OwnerID: ownerID,
Name: name,
Fingerprint: fingerprint,
Content: content,
Mode: AccessModeWrite,
Type: KeyTypeUser,
OwnerID: ownerID,
Name: name,
Fingerprint: fingerprint,
Content: content,
Mode: AccessModeWrite,
Type: KeyTypeUser,
LoginSourceID: LoginSourceID,
}
if err = addKey(sess, key); err != nil {
return nil, fmt.Errorf("addKey: %v", err)
Expand Down Expand Up @@ -471,6 +473,14 @@ func ListPublicKeys(uid int64) ([]*PublicKey, error) {
Find(&keys)
}

// ListPublicLdapSSHKeys returns a list of synchronized public ldap ssh keys belongs to given user and login source.
func ListPublicLdapSSHKeys(uid int64, LoginSourceID int64) ([]*PublicKey, error) {
keys := make([]*PublicKey, 0, 5)
return keys, x.
Where("owner_id = ? AND login_source_id = ?", uid, LoginSourceID).
Find(&keys)
}

// UpdatePublicKeyUpdated updates public key use time.
func UpdatePublicKeyUpdated(id int64) error {
// Check if key exists before update as affected rows count is unreliable
Expand Down