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

Support multiple LDAP servers in a auth source #31649

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
12 changes: 6 additions & 6 deletions cmd/admin_auth_ldap.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ var (
Usage: "Disable TLS verification.",
},
&cli.StringFlag{
Name: "host",
Usage: "The address where the LDAP server can be reached.",
Name: "host-list",
Usage: "List of addresses where the LDAP server(s) can be reached.",
},
&cli.IntFlag{
Name: "port",
Expand Down Expand Up @@ -206,8 +206,8 @@ func parseLdapConfig(c *cli.Context, config *ldap.Source) error {
if c.IsSet("name") {
config.Name = c.String("name")
}
if c.IsSet("host") {
config.Host = c.String("host")
if c.IsSet("host-list") {
config.HostList = c.String("host-list")
}
if c.IsSet("port") {
config.Port = c.Int("port")
Expand Down Expand Up @@ -308,7 +308,7 @@ func (a *authService) getAuthSource(ctx context.Context, c *cli.Context, authTyp

// addLdapBindDn adds a new LDAP via Bind DN authentication source.
func (a *authService) addLdapBindDn(c *cli.Context) error {
if err := argsSet(c, "name", "security-protocol", "host", "port", "user-search-base", "user-filter", "email-attribute"); err != nil {
if err := argsSet(c, "name", "security-protocol", "host-list", "port", "user-search-base", "user-filter", "email-attribute"); err != nil {
return err
}

Expand Down Expand Up @@ -359,7 +359,7 @@ func (a *authService) updateLdapBindDn(c *cli.Context) error {

// addLdapSimpleAuth adds a new LDAP (simple auth) authentication source.
func (a *authService) addLdapSimpleAuth(c *cli.Context) error {
if err := argsSet(c, "name", "security-protocol", "host", "port", "user-dn", "user-filter", "email-attribute"); err != nil {
if err := argsSet(c, "name", "security-protocol", "host-list", "port", "user-dn", "user-filter", "email-attribute"); err != nil {
return err
}

Expand Down
62 changes: 31 additions & 31 deletions cmd/admin_auth_ldap_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ func TestAddLdapBindDn(t *testing.T) {
"--not-active",
"--security-protocol", "ldaps",
"--skip-tls-verify",
"--host", "ldap-bind-server full",
"--host-list", "ldap-bind-server full",
"--port", "9876",
"--user-search-base", "ou=Users,dc=full-domain-bind,dc=org",
"--user-filter", "(memberOf=cn=user-group,ou=example,dc=full-domain-bind,dc=org)",
Expand All @@ -59,7 +59,7 @@ func TestAddLdapBindDn(t *testing.T) {
IsSyncEnabled: true,
Cfg: &ldap.Source{
Name: "ldap (via Bind DN) source full",
Host: "ldap-bind-server full",
HostList: "ldap-bind-server full",
Port: 9876,
SecurityProtocol: ldap.SecurityProtocol(1),
SkipVerify: true,
Expand Down Expand Up @@ -87,7 +87,7 @@ func TestAddLdapBindDn(t *testing.T) {
"ldap-test",
"--name", "ldap (via Bind DN) source min",
"--security-protocol", "unencrypted",
"--host", "ldap-bind-server min",
"--host-list", "ldap-bind-server min",
"--port", "1234",
"--user-search-base", "ou=Users,dc=min-domain-bind,dc=org",
"--user-filter", "(memberOf=cn=user-group,ou=example,dc=min-domain-bind,dc=org)",
Expand All @@ -99,7 +99,7 @@ func TestAddLdapBindDn(t *testing.T) {
IsActive: true,
Cfg: &ldap.Source{
Name: "ldap (via Bind DN) source min",
Host: "ldap-bind-server min",
HostList: "ldap-bind-server min",
Port: 1234,
SecurityProtocol: ldap.SecurityProtocol(0),
UserBase: "ou=Users,dc=min-domain-bind,dc=org",
Expand All @@ -115,7 +115,7 @@ func TestAddLdapBindDn(t *testing.T) {
"ldap-test",
"--name", "ldap (via Bind DN) source",
"--security-protocol", "zzzzz",
"--host", "ldap-server",
"--host-list", "ldap-server",
"--port", "1234",
"--user-search-base", "ou=Users,dc=domain,dc=org",
"--user-filter", "(memberOf=cn=user-group,ou=example,dc=domain,dc=org)",
Expand All @@ -128,7 +128,7 @@ func TestAddLdapBindDn(t *testing.T) {
args: []string{
"ldap-test",
"--security-protocol", "unencrypted",
"--host", "ldap-server",
"--host-list", "ldap-server",
"--port", "1234",
"--user-search-base", "ou=Users,dc=domain,dc=org",
"--user-filter", "(memberOf=cn=user-group,ou=example,dc=domain,dc=org)",
Expand All @@ -141,7 +141,7 @@ func TestAddLdapBindDn(t *testing.T) {
args: []string{
"ldap-test",
"--name", "ldap (via Bind DN) source",
"--host", "ldap-server",
"--host-list", "ldap-server",
"--port", "1234",
"--user-search-base", "ou=Users,dc=domain,dc=org",
"--user-filter", "(memberOf=cn=user-group,ou=example,dc=domain,dc=org)",
Expand All @@ -160,15 +160,15 @@ func TestAddLdapBindDn(t *testing.T) {
"--user-filter", "(memberOf=cn=user-group,ou=example,dc=domain,dc=org)",
"--email-attribute", "mail",
},
errMsg: "host is not set",
errMsg: "host-list is not set",
},
// case 6
{
args: []string{
"ldap-test",
"--name", "ldap (via Bind DN) source",
"--security-protocol", "unencrypted",
"--host", "ldap-server",
"--host-list", "ldap-server",
"--user-search-base", "ou=Users,dc=domain,dc=org",
"--user-filter", "(memberOf=cn=user-group,ou=example,dc=domain,dc=org)",
"--email-attribute", "mail",
Expand All @@ -181,7 +181,7 @@ func TestAddLdapBindDn(t *testing.T) {
"ldap-test",
"--name", "ldap (via Bind DN) source",
"--security-protocol", "unencrypted",
"--host", "ldap-server",
"--host-list", "ldap-server",
"--port", "1234",
"--user-search-base", "ou=Users,dc=domain,dc=org",
"--email-attribute", "mail",
Expand All @@ -194,7 +194,7 @@ func TestAddLdapBindDn(t *testing.T) {
"ldap-test",
"--name", "ldap (via Bind DN) source",
"--security-protocol", "unencrypted",
"--host", "ldap-server",
"--host-list", "ldap-server",
"--port", "1234",
"--user-search-base", "ou=Users,dc=domain,dc=org",
"--user-filter", "(memberOf=cn=user-group,ou=example,dc=domain,dc=org)",
Expand Down Expand Up @@ -260,7 +260,7 @@ func TestAddLdapSimpleAuth(t *testing.T) {
"--not-active",
"--security-protocol", "starttls",
"--skip-tls-verify",
"--host", "ldap-simple-server full",
"--host-list", "ldap-simple-server full",
"--port", "987",
"--user-search-base", "ou=Users,dc=full-domain-simple,dc=org",
"--user-filter", "(&(objectClass=posixAccount)(full-simple-cn=%s))",
Expand All @@ -280,7 +280,7 @@ func TestAddLdapSimpleAuth(t *testing.T) {
IsActive: false,
Cfg: &ldap.Source{
Name: "ldap (simple auth) source full",
Host: "ldap-simple-server full",
HostList: "ldap-simple-server full",
Port: 987,
SecurityProtocol: ldap.SecurityProtocol(2),
SkipVerify: true,
Expand All @@ -305,7 +305,7 @@ func TestAddLdapSimpleAuth(t *testing.T) {
"ldap-test",
"--name", "ldap (simple auth) source min",
"--security-protocol", "unencrypted",
"--host", "ldap-simple-server min",
"--host-list", "ldap-simple-server min",
"--port", "123",
"--user-filter", "(&(objectClass=posixAccount)(min-simple-cn=%s))",
"--email-attribute", "mail-simple min",
Expand All @@ -317,7 +317,7 @@ func TestAddLdapSimpleAuth(t *testing.T) {
IsActive: true,
Cfg: &ldap.Source{
Name: "ldap (simple auth) source min",
Host: "ldap-simple-server min",
HostList: "ldap-simple-server min",
Port: 123,
SecurityProtocol: ldap.SecurityProtocol(0),
UserDN: "cn=%s,ou=Users,dc=min-domain-simple,dc=org",
Expand All @@ -333,7 +333,7 @@ func TestAddLdapSimpleAuth(t *testing.T) {
"ldap-test",
"--name", "ldap (simple auth) source",
"--security-protocol", "zzzzz",
"--host", "ldap-server",
"--host-list", "ldap-server",
"--port", "123",
"--user-filter", "(&(objectClass=posixAccount)(cn=%s))",
"--email-attribute", "mail",
Expand All @@ -346,7 +346,7 @@ func TestAddLdapSimpleAuth(t *testing.T) {
args: []string{
"ldap-test",
"--security-protocol", "unencrypted",
"--host", "ldap-server",
"--host-list", "ldap-server",
"--port", "123",
"--user-filter", "(&(objectClass=posixAccount)(cn=%s))",
"--email-attribute", "mail",
Expand All @@ -359,7 +359,7 @@ func TestAddLdapSimpleAuth(t *testing.T) {
args: []string{
"ldap-test",
"--name", "ldap (simple auth) source",
"--host", "ldap-server",
"--host-list", "ldap-server",
"--port", "123",
"--user-filter", "(&(objectClass=posixAccount)(cn=%s))",
"--email-attribute", "mail",
Expand All @@ -378,15 +378,15 @@ func TestAddLdapSimpleAuth(t *testing.T) {
"--email-attribute", "mail",
"--user-dn", "cn=%s,ou=Users,dc=domain,dc=org",
},
errMsg: "host is not set",
errMsg: "host-list is not set",
},
// case 6
{
args: []string{
"ldap-test",
"--name", "ldap (simple auth) source",
"--security-protocol", "unencrypted",
"--host", "ldap-server",
"--host-list", "ldap-server",
"--user-filter", "(&(objectClass=posixAccount)(cn=%s))",
"--email-attribute", "mail",
"--user-dn", "cn=%s,ou=Users,dc=domain,dc=org",
Expand All @@ -399,7 +399,7 @@ func TestAddLdapSimpleAuth(t *testing.T) {
"ldap-test",
"--name", "ldap (simple auth) source",
"--security-protocol", "unencrypted",
"--host", "ldap-server",
"--host-list", "ldap-server",
"--port", "123",
"--email-attribute", "mail",
"--user-dn", "cn=%s,ou=Users,dc=domain,dc=org",
Expand All @@ -412,7 +412,7 @@ func TestAddLdapSimpleAuth(t *testing.T) {
"ldap-test",
"--name", "ldap (simple auth) source",
"--security-protocol", "unencrypted",
"--host", "ldap-server",
"--host-list", "ldap-server",
"--port", "123",
"--user-filter", "(&(objectClass=posixAccount)(cn=%s))",
"--user-dn", "cn=%s,ou=Users,dc=domain,dc=org",
Expand All @@ -425,7 +425,7 @@ func TestAddLdapSimpleAuth(t *testing.T) {
"ldap-test",
"--name", "ldap (simple auth) source",
"--security-protocol", "unencrypted",
"--host", "ldap-server",
"--host-list", "ldap-server",
"--port", "123",
"--user-filter", "(&(objectClass=posixAccount)(cn=%s))",
"--email-attribute", "mail",
Expand Down Expand Up @@ -494,7 +494,7 @@ func TestUpdateLdapBindDn(t *testing.T) {
"--not-active",
"--security-protocol", "LDAPS",
"--skip-tls-verify",
"--host", "ldap-bind-server full",
"--host-list", "ldap-bind-server full",
"--port", "9876",
"--user-search-base", "ou=Users,dc=full-domain-bind,dc=org",
"--user-filter", "(memberOf=cn=user-group,ou=example,dc=full-domain-bind,dc=org)",
Expand Down Expand Up @@ -526,7 +526,7 @@ func TestUpdateLdapBindDn(t *testing.T) {
IsSyncEnabled: true,
Cfg: &ldap.Source{
Name: "ldap (via Bind DN) source full",
Host: "ldap-bind-server full",
HostList: "ldap-bind-server full",
Port: 9876,
SecurityProtocol: ldap.SecurityProtocol(1),
SkipVerify: true,
Expand Down Expand Up @@ -625,12 +625,12 @@ func TestUpdateLdapBindDn(t *testing.T) {
args: []string{
"ldap-test",
"--id", "1",
"--host", "ldap-server",
"--host-list", "ldap-server",
},
authSource: &auth.Source{
Type: auth.LDAP,
Cfg: &ldap.Source{
Host: "ldap-server",
HostList: "ldap-server",
},
},
},
Expand Down Expand Up @@ -957,7 +957,7 @@ func TestUpdateLdapSimpleAuth(t *testing.T) {
"--not-active",
"--security-protocol", "starttls",
"--skip-tls-verify",
"--host", "ldap-simple-server full",
"--host-list", "ldap-simple-server full",
"--port", "987",
"--user-search-base", "ou=Users,dc=full-domain-simple,dc=org",
"--user-filter", "(&(objectClass=posixAccount)(full-simple-cn=%s))",
Expand All @@ -978,7 +978,7 @@ func TestUpdateLdapSimpleAuth(t *testing.T) {
IsActive: false,
Cfg: &ldap.Source{
Name: "ldap (simple auth) source full",
Host: "ldap-simple-server full",
HostList: "ldap-simple-server full",
Port: 987,
SecurityProtocol: ldap.SecurityProtocol(2),
SkipVerify: true,
Expand Down Expand Up @@ -1073,12 +1073,12 @@ func TestUpdateLdapSimpleAuth(t *testing.T) {
args: []string{
"ldap-test",
"--id", "1",
"--host", "ldap-server",
"--host-list", "ldap-server",
},
authSource: &auth.Source{
Type: auth.DLDAP,
Cfg: &ldap.Source{
Host: "ldap-server",
HostList: "ldap-server",
},
},
},
Expand Down
2 changes: 1 addition & 1 deletion routers/web/admin/auths.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ func parseLDAPConfig(form forms.AuthenticationForm) *ldap.Source {
}
return &ldap.Source{
Name: form.Name,
Host: form.Host,
HostList: form.Host,
Port: form.Port,
SecurityProtocol: ldap.SecurityProtocol(form.SecurityProtocol),
SkipVerify: form.SkipVerify,
Expand Down
3 changes: 2 additions & 1 deletion services/auth/source/ldap/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,9 @@ share the following fields:
* A name to assign to the new method of authorization.

* Host **(required)**
* The address where the LDAP server can be reached.
* The list of addresses where the LDAP server(s) can be reached.
* Example: mydomain.com
* Example (with multiple server hosts): mydomain.com, myotherdomain.com, mytempdomain.com

* Port **(required)**
* The port to use when connecting to the server.
Expand Down
2 changes: 1 addition & 1 deletion services/auth/source/ldap/source.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import (
// Source Basic LDAP authentication service
type Source struct {
Name string // canonical name (ie. corporate.ad)
Host string // LDAP host
HostList string // list containing LDAP host(s)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So all these hosts should have the same port?

Copy link
Author

@abhishek818 abhishek818 Sep 27, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lunny damnn, thats a big miss on my part.

Can you help with if we should keep the config for each ldap host as below?

// HostConfig represents the configuration for a single LDAP host
type HostConfig struct {
	Host              string            // Hostname or IP address
	Port              uint16            // Port number
	SecurityProtocol  SecurityProtocol  // Security protocol (LDAP, LDAPS, StartTLS)
	SkipVerify        bool              // Whether to skip TLS certificate verification
	BindDN            string            // Bind DN
	BindPassword      string            // Bind password
	UserBase          string            // User search base
	GroupBase         string            // Group search base
	SearchPageSize    uint32            // Search page size
	Filter            string            // User search filter
	AdminFilter       string            // Admin filter
	RestrictedFilter  string            // Restricted user filter
}

// Source represents the overall LDAP service configuration
type Source struct {
	Name               string        // Canonical name (e.g., corporate.ad)
	Hosts              []HostConfig  // List of host configurations    <-----------------------------
	AttributeUsername  string        // Username attribute
	AttributeName      string        // First name attribute
	AttributeSurname   string        // Surname attribute
	AttributeMail      string        // Email attribute
	AttributeSSHPublicKey string     // SSH Public Key attribute
	AttributeAvatar    string        // Avatar attribute
	AttributesInBind   bool          // Fetch attributes in bind context
	GroupMemberUID     string        // Group attribute containing array of UserUID
	GroupTeamMap       string        // Map LDAP groups to teams
	GroupTeamMapRemoval bool         // Remove user from teams not in corresponding LDAP group
	UserUID            string        // User attribute listed in group
	SkipLocalTwoFA     bool          // Skip 2FA for this source
	authSource         *auth.Source  // Reference to the authSource
}

Further should we go the same approach for each config input value as a list of string separated commas for both cli and web (same as host address currently) ?

Port int // port number
SecurityProtocol SecurityProtocol
SkipVerify bool
Expand Down
Loading
Loading