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

Add rudimentary LDAP group support #8814

Closed
wants to merge 33 commits into from
Closed
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
50002c6
Removed function attribute sshKeyAttribute from LDAP test
stertingen Jun 26, 2019
ad80909
Added config options for LDAP groups and filters
stertingen Jun 26, 2019
bfdc279
Rudimentary group support
stertingen Jun 27, 2019
d9673e5
LDAP: Special case for using DN as user attribute in group
stertingen Jul 3, 2019
27bfd7a
LDAP: Small template improvements
stertingen Jul 3, 2019
1c59987
LDAP: Added text for the new configuration features
stertingen Jul 3, 2019
f71752f
LDAP: Added some comments
stertingen Jul 3, 2019
53d8c1d
LDAP: Added new group search to SearchEntries()
stertingen Jul 3, 2019
7a122c0
Revert "Removed function attribute sshKeyAttribute from LDAP test"
stertingen Jul 7, 2019
89256fb
Removed german translations for LDAP group configuration
stertingen Jul 7, 2019
66ccdd0
LDAP: Added tests for simple login
stertingen Jul 14, 2019
62f54f8
Fixed LDAP test for Hermes Conrad.
stertingen Jul 14, 2019
1846719
Added test for LDAP admin filter
stertingen Jul 14, 2019
41f0eac
LDAP: Added CLI arguments for LDAP groups (incl. tests)
stertingen Nov 3, 2019
2df2271
LDAP: Reduced code duplication by indroducing ProcessUserEntry function
stertingen Nov 3, 2019
e5c7d5c
LDAP: Added test for userAttributeInGroup='cn'
stertingen Nov 12, 2019
11acb53
LDAP: Preallocate results array
stertingen Jan 7, 2020
93e03cd
Merge branch 'master' into ldap_groups
stertingen Jan 18, 2020
b8ecb98
LDAP: Apply suggestions from code review
stertingen Jan 19, 2020
cc007e5
Merge branch 'master' into ldap_groups
zeripath Mar 30, 2020
2bcd3ca
Only request ls.UserAttributeInGroup if it is set
zeripath Mar 30, 2020
0ed167e
Merge branch 'master' into ldap_groups
zeripath Mar 30, 2020
1b2674e
Update cmd/admin_auth_ldap.go
zeripath Mar 30, 2020
b4ef85d
Merge branch 'master' into ldap_groups
zeripath Apr 3, 2020
6c95d6a
fix misplaced divs
zeripath Apr 9, 2020
e958a5b
Apply suggestions from code review
zeripath Apr 12, 2020
6c8d75b
Apply suggestions from code review
zeripath Apr 12, 2020
74851d5
Merge branch 'master' into ldap_groups
zeripath Apr 13, 2020
9e4e003
Merge branch 'master' into ldap_groups
stertingen May 2, 2020
6e8e615
Rework admin and restricted checks with LDAP groups
stertingen May 2, 2020
e8a4465
Added some helping notes on LDAP groups for admins
stertingen May 2, 2020
f3fe882
Fixed formatting in ldap.go
stertingen May 2, 2020
dcc7872
Merge branch 'master' into ldap_groups
lafriks Aug 23, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions cmd/admin_auth_ldap.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,30 @@ var (
Name: "user-search-base",
Usage: "The LDAP base at which user accounts will be searched for.",
},
cli.StringFlag{
Name: "group-search-base",
Usage: "The LDAP base at which groups will be searched for.",
},
cli.StringFlag{
Name: "group-search-filter",
Usage: "An LDAP filter declaring how to find the groups a user is member of.",
},
cli.StringFlag{
Name: "user-attribute-in-group",
Usage: "The LDAP attribute of a user referenced by groups.",
},
cli.StringFlag{
Name: "member-group-filter",
Usage: "An LDAP filter specifying if a group should be allowed to login.",
},
cli.StringFlag{
Name: "admin-group-filter",
Usage: "An LDAP filter specifying an admin user group.",
},
cli.StringFlag{
Name: "restricted-group-filter",
Usage: "An LDAP filter specifying a restricted user group.",
},
cli.StringFlag{
Name: "user-filter",
Usage: "An LDAP filter declaring how to find the user record that is attempting to authenticate.",
Expand Down Expand Up @@ -212,6 +236,24 @@ func parseLdapConfig(c *cli.Context, config *models.LDAPConfig) error {
if c.IsSet("user-search-base") {
config.Source.UserBase = c.String("user-search-base")
}
if c.IsSet("group-search-base") {
config.Source.GroupSearchBase = c.String("group-search-base")
}
if c.IsSet("group-search-filter") {
config.Source.GroupSearchFilter = c.String("group-search-filter")
}
if c.IsSet("user-attribute-in-group") {
config.Source.UserAttributeInGroup = c.String("user-attribute-in-group")
}
if c.IsSet("member-group-filter") {
config.Source.MemberGroupFilter = c.String("member-group-filter")
}
if c.IsSet("admin-group-filter") {
config.Source.AdminGroupFilter = c.String("admin-group-filter")
}
if c.IsSet("restricted-group-filter") {
config.Source.RestrictedGroupFilter = c.String("restricted-group-filter")
}
if c.IsSet("username-attribute") {
config.Source.AttributeUsername = c.String("username-attribute")
}
Expand Down
240 changes: 240 additions & 0 deletions cmd/admin_auth_ldap_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ func TestAddLdapBindDn(t *testing.T) {
"--attributes-in-bind",
"--synchronize-users",
"--page-size", "99",
"--group-search-base", "ou=Groups,dc=full-domain-bind,dc=org",
"--group-search-filter", "(&(objectClass=groupOfNames)(member=%s))",
"--user-attribute-in-group", "uid",
"--member-group-filter", "(cn=user-group)",
"--admin-group-filter", "(cn=admin-group)",
"--restricted-group-filter", "(cn=restricted-group)",
},
loginSource: &models.LoginSource{
Type: models.LoginLDAP,
Expand All @@ -66,6 +72,12 @@ func TestAddLdapBindDn(t *testing.T) {
BindDN: "cn=readonly,dc=full-domain-bind,dc=org",
BindPassword: "secret-bind-full",
UserBase: "ou=Users,dc=full-domain-bind,dc=org",
GroupSearchBase: "ou=Groups,dc=full-domain-bind,dc=org",
GroupSearchFilter: "(&(objectClass=groupOfNames)(member=%s))",
UserAttributeInGroup: "uid",
MemberGroupFilter: "(cn=user-group)",
AdminGroupFilter: "(cn=admin-group)",
RestrictedGroupFilter: "(cn=restricted-group)",
AttributeUsername: "uid-bind full",
AttributeName: "givenName-bind full",
AttributeSurname: "sn-bind full",
Expand Down Expand Up @@ -274,6 +286,12 @@ func TestAddLdapSimpleAuth(t *testing.T) {
"--email-attribute", "mail-simple full",
"--public-ssh-key-attribute", "publickey-simple full",
"--user-dn", "cn=%s,ou=Users,dc=full-domain-simple,dc=org",
"--group-search-base", "ou=Groups,dc=full-domain-bind,dc=org",
"--group-search-filter", "(&(objectClass=groupOfNames)(member=%s))",
"--user-attribute-in-group", "uid",
"--member-group-filter", "(cn=user-group)",
"--admin-group-filter", "(cn=admin-group)",
"--restricted-group-filter", "(cn=restricted-group)",
},
loginSource: &models.LoginSource{
Type: models.LoginDLDAP,
Expand All @@ -288,6 +306,12 @@ func TestAddLdapSimpleAuth(t *testing.T) {
SkipVerify: true,
UserDN: "cn=%s,ou=Users,dc=full-domain-simple,dc=org",
UserBase: "ou=Users,dc=full-domain-simple,dc=org",
GroupSearchBase: "ou=Groups,dc=full-domain-bind,dc=org",
GroupSearchFilter: "(&(objectClass=groupOfNames)(member=%s))",
UserAttributeInGroup: "uid",
MemberGroupFilter: "(cn=user-group)",
AdminGroupFilter: "(cn=admin-group)",
RestrictedGroupFilter: "(cn=restricted-group)",
AttributeUsername: "uid-simple full",
AttributeName: "givenName-simple full",
AttributeSurname: "sn-simple full",
Expand Down Expand Up @@ -513,6 +537,12 @@ func TestUpdateLdapBindDn(t *testing.T) {
"--bind-password", "secret-bind-full",
"--synchronize-users",
"--page-size", "99",
"--group-search-base", "ou=Groups,dc=full-domain-bind,dc=org",
"--group-search-filter", "(&(objectClass=groupOfNames)(member=%s))",
"--user-attribute-in-group", "uid",
"--member-group-filter", "(cn=user-group)",
"--admin-group-filter", "(cn=admin-group)",
"--restricted-group-filter", "(cn=restricted-group)",
},
id: 23,
existingLoginSource: &models.LoginSource{
Expand All @@ -539,6 +569,12 @@ func TestUpdateLdapBindDn(t *testing.T) {
BindDN: "cn=readonly,dc=full-domain-bind,dc=org",
BindPassword: "secret-bind-full",
UserBase: "ou=Users,dc=full-domain-bind,dc=org",
GroupSearchBase: "ou=Groups,dc=full-domain-bind,dc=org",
GroupSearchFilter: "(&(objectClass=groupOfNames)(member=%s))",
UserAttributeInGroup: "uid",
MemberGroupFilter: "(cn=user-group)",
AdminGroupFilter: "(cn=admin-group)",
RestrictedGroupFilter: "(cn=restricted-group)",
AttributeUsername: "uid-bind full",
AttributeName: "givenName-bind full",
AttributeSurname: "sn-bind full",
Expand Down Expand Up @@ -907,6 +943,102 @@ func TestUpdateLdapBindDn(t *testing.T) {
},
errMsg: "Invalid authentication type. expected: LDAP (via BindDN), actual: OAuth2",
},
// case 24
{
args: []string{
"ldap-test",
"--id", "1",
"--group-search-base", "ou=Groups,dc=full-domain-bind,dc=org",
},
loginSource: &models.LoginSource{
Type: models.LoginLDAP,
Cfg: &models.LDAPConfig{
Source: &ldap.Source{
GroupSearchBase: "ou=Groups,dc=full-domain-bind,dc=org",
},
},
},
},
// case 25
{
args: []string{
"ldap-test",
"--id", "1",
"--group-search-filter", "(&(objectClass=groupOfNames)(member=%s))",
},
loginSource: &models.LoginSource{
Type: models.LoginLDAP,
Cfg: &models.LDAPConfig{
Source: &ldap.Source{
GroupSearchFilter: "(&(objectClass=groupOfNames)(member=%s))",
},
},
},
},
// case 26
{
args: []string{
"ldap-test",
"--id", "1",
"--user-attribute-in-group", "uid",
},
loginSource: &models.LoginSource{
Type: models.LoginLDAP,
Cfg: &models.LDAPConfig{
Source: &ldap.Source{
UserAttributeInGroup: "uid",
},
},
},
},
// case 27
{
args: []string{
"ldap-test",
"--id", "1",
"--member-group-filter", "(cn=user-group)",
},
loginSource: &models.LoginSource{
Type: models.LoginLDAP,
Cfg: &models.LDAPConfig{
Source: &ldap.Source{
MemberGroupFilter: "(cn=user-group)",
},
},
},
},
// case 28
{
args: []string{
"ldap-test",
"--id", "1",
"--admin-group-filter", "(cn=admin-group)",
},
loginSource: &models.LoginSource{
Type: models.LoginLDAP,
Cfg: &models.LDAPConfig{
Source: &ldap.Source{
AdminGroupFilter: "(cn=admin-group)",
},
},
},
},
// case 29
{
args: []string{
"ldap-test",
"--id", "1",
"--restricted-group-filter", "(cn=restricted-group)",
},
loginSource: &models.LoginSource{
Type: models.LoginLDAP,
Cfg: &models.LDAPConfig{
Source: &ldap.Source{
RestrictedGroupFilter: "(cn=restricted-group)",
},
},
},
},
}

for n, c := range cases {
Expand Down Expand Up @@ -991,6 +1123,12 @@ func TestUpdateLdapSimpleAuth(t *testing.T) {
"--email-attribute", "mail-simple full",
"--public-ssh-key-attribute", "publickey-simple full",
"--user-dn", "cn=%s,ou=Users,dc=full-domain-simple,dc=org",
"--group-search-base", "ou=Groups,dc=full-domain-bind,dc=org",
"--group-search-filter", "(&(objectClass=groupOfNames)(member=%s))",
"--user-attribute-in-group", "uid",
"--member-group-filter", "(cn=user-group)",
"--admin-group-filter", "(cn=admin-group)",
"--restricted-group-filter", "(cn=restricted-group)",
},
id: 7,
loginSource: &models.LoginSource{
Expand All @@ -1006,6 +1144,12 @@ func TestUpdateLdapSimpleAuth(t *testing.T) {
SkipVerify: true,
UserDN: "cn=%s,ou=Users,dc=full-domain-simple,dc=org",
UserBase: "ou=Users,dc=full-domain-simple,dc=org",
GroupSearchBase: "ou=Groups,dc=full-domain-bind,dc=org",
GroupSearchFilter: "(&(objectClass=groupOfNames)(member=%s))",
UserAttributeInGroup: "uid",
MemberGroupFilter: "(cn=user-group)",
AdminGroupFilter: "(cn=admin-group)",
RestrictedGroupFilter: "(cn=restricted-group)",
AttributeUsername: "uid-simple full",
AttributeName: "givenName-simple full",
AttributeSurname: "sn-simple full",
Expand Down Expand Up @@ -1308,6 +1452,102 @@ func TestUpdateLdapSimpleAuth(t *testing.T) {
},
errMsg: "Invalid authentication type. expected: LDAP (simple auth), actual: PAM",
},
// case 20
{
args: []string{
"ldap-test",
"--id", "1",
"--group-search-base", "ou=Groups,dc=full-domain-bind,dc=org",
},
loginSource: &models.LoginSource{
Type: models.LoginDLDAP,
Cfg: &models.LDAPConfig{
Source: &ldap.Source{
GroupSearchBase: "ou=Groups,dc=full-domain-bind,dc=org",
},
},
},
},
// case 21
{
args: []string{
"ldap-test",
"--id", "1",
"--group-search-filter", "(&(objectClass=groupOfNames)(member=%s))",
},
loginSource: &models.LoginSource{
Type: models.LoginDLDAP,
Cfg: &models.LDAPConfig{
Source: &ldap.Source{
GroupSearchFilter: "(&(objectClass=groupOfNames)(member=%s))",
},
},
},
},
// case 22
{
args: []string{
"ldap-test",
"--id", "1",
"--user-attribute-in-group", "uid",
},
loginSource: &models.LoginSource{
Type: models.LoginDLDAP,
Cfg: &models.LDAPConfig{
Source: &ldap.Source{
UserAttributeInGroup: "uid",
},
},
},
},
// case 23
{
args: []string{
"ldap-test",
"--id", "1",
"--member-group-filter", "(cn=user-group)",
},
loginSource: &models.LoginSource{
Type: models.LoginDLDAP,
Cfg: &models.LDAPConfig{
Source: &ldap.Source{
MemberGroupFilter: "(cn=user-group)",
},
},
},
},
// case 24
{
args: []string{
"ldap-test",
"--id", "1",
"--admin-group-filter", "(cn=admin-group)",
},
loginSource: &models.LoginSource{
Type: models.LoginDLDAP,
Cfg: &models.LDAPConfig{
Source: &ldap.Source{
AdminGroupFilter: "(cn=admin-group)",
},
},
},
},
// case 25
{
args: []string{
"ldap-test",
"--id", "1",
"--restricted-group-filter", "(cn=restricted-group)",
},
loginSource: &models.LoginSource{
Type: models.LoginDLDAP,
Cfg: &models.LDAPConfig{
Source: &ldap.Source{
RestrictedGroupFilter: "(cn=restricted-group)",
},
},
},
},
}

for n, c := range cases {
Expand Down
Loading