From fbde51b3ead8dabd30ee83684b4cb43fa0830524 Mon Sep 17 00:00:00 2001 From: tannevaled Date: Fri, 29 Aug 2025 10:50:08 +0200 Subject: [PATCH] be able to debug LDAP queries; be consistent between GetUserAccount() and ListUserAccounts() on how to build the search filters; objectClasses were missing in GetUserAccount research filter leading to a bad result for example when a posixgGroup have the same name as a posixUser. --- auth/iam.go | 3 ++- auth/iam_ldap.go | 33 ++++++++++++++++++++++++++------- cmd/versitygw/main.go | 8 ++++++++ 3 files changed, 36 insertions(+), 8 deletions(-) diff --git a/auth/iam.go b/auth/iam.go index a702c65..1e66462 100644 --- a/auth/iam.go +++ b/auth/iam.go @@ -119,6 +119,7 @@ type Opts struct { LDAPRoleAtr string LDAPUserIdAtr string LDAPGroupIdAtr string + LDAPDebug bool VaultEndpointURL string VaultSecretStoragePath string VaultAuthMethod string @@ -158,7 +159,7 @@ func New(o *Opts) (IAMService, error) { case o.LDAPServerURL != "": svc, err = NewLDAPService(o.RootAccount, o.LDAPServerURL, o.LDAPBindDN, o.LDAPPassword, o.LDAPQueryBase, o.LDAPAccessAtr, o.LDAPSecretAtr, o.LDAPRoleAtr, o.LDAPUserIdAtr, - o.LDAPGroupIdAtr, o.LDAPObjClasses) + o.LDAPGroupIdAtr, o.LDAPObjClasses, o.LDAPDebug) fmt.Printf("initializing LDAP IAM with %q\n", o.LDAPServerURL) case o.S3Endpoint != "": svc, err = NewS3(o.RootAccount, o.S3Access, o.S3Secret, o.S3Region, o.S3Bucket, diff --git a/auth/iam_ldap.go b/auth/iam_ldap.go index 06b602f..cdda803 100644 --- a/auth/iam_ldap.go +++ b/auth/iam_ldap.go @@ -20,6 +20,7 @@ import ( "strings" "sync" + "github.com/davecgh/go-spew/spew" "github.com/go-ldap/ldap/v3" ) @@ -32,6 +33,7 @@ type LdapIAMService struct { roleAtr string groupIdAtr string userIdAtr string + debug bool rootAcc Account url string bindDN string @@ -41,7 +43,7 @@ type LdapIAMService struct { var _ IAMService = &LdapIAMService{} -func NewLDAPService(rootAcc Account, url, bindDN, pass, queryBase, accAtr, secAtr, roleAtr, userIdAtr, groupIdAtr, objClasses string) (IAMService, error) { +func NewLDAPService(rootAcc Account, url, bindDN, pass, queryBase, accAtr, secAtr, roleAtr, userIdAtr, groupIdAtr, objClasses string, debug bool) (IAMService, error) { if url == "" || bindDN == "" || pass == "" || queryBase == "" || accAtr == "" || secAtr == "" || roleAtr == "" || userIdAtr == "" || groupIdAtr == "" || objClasses == "" { return nil, fmt.Errorf("required parameters list not fully provided") @@ -63,6 +65,7 @@ func NewLDAPService(rootAcc Account, url, bindDN, pass, queryBase, accAtr, secAt secretAtr: secAtr, roleAtr: roleAtr, userIdAtr: userIdAtr, + debug: debug, groupIdAtr: groupIdAtr, rootAcc: rootAcc, url: url, @@ -126,6 +129,17 @@ func (ld *LdapIAMService) CreateAccount(account Account) error { return nil } +func (ld *LdapIAMService) BuildSearchFilter(access string) string { + searchFilter := "" + for _, el := range ld.objClasses { + searchFilter += fmt.Sprintf("(objectClass=%v)", el) + } + if access != "" { + searchFilter += fmt.Sprintf("(%v=%v)", ld.accessAtr, access) + } + return fmt.Sprintf("(&%v)", searchFilter) +} + func (ld *LdapIAMService) GetUserAccount(access string) (Account, error) { if access == ld.rootAcc.Access { return ld.rootAcc, nil @@ -138,16 +152,25 @@ func (ld *LdapIAMService) GetUserAccount(access string) (Account, error) { 0, 0, false, - fmt.Sprintf("(%v=%v)", ld.accessAtr, access), + ld.BuildSearchFilter(access), []string{ld.accessAtr, ld.secretAtr, ld.roleAtr, ld.userIdAtr, ld.groupIdAtr}, nil, ) + if ld.debug { + spew.Dump(searchRequest) + } + err := ld.execute(func(c *ldap.Conn) error { var err error result, err = c.Search(searchRequest) return err }) + + if ld.debug { + spew.Dump(result) + } + if err != nil { return Account{}, err } @@ -215,10 +238,6 @@ func (ld *LdapIAMService) DeleteUserAccount(access string) error { } func (ld *LdapIAMService) ListUserAccounts() ([]Account, error) { - searchFilter := "" - for _, el := range ld.objClasses { - searchFilter += fmt.Sprintf("(objectClass=%v)", el) - } var resp *ldap.SearchResult searchRequest := ldap.NewSearchRequest( ld.queryBase, @@ -227,7 +246,7 @@ func (ld *LdapIAMService) ListUserAccounts() ([]Account, error) { 0, 0, false, - fmt.Sprintf("(&%v)", searchFilter), + ld.BuildSearchFilter(""), []string{ld.accessAtr, ld.secretAtr, ld.roleAtr, ld.groupIdAtr, ld.userIdAtr}, nil, ) diff --git a/cmd/versitygw/main.go b/cmd/versitygw/main.go index 4f5c3a0..c38eb7f 100644 --- a/cmd/versitygw/main.go +++ b/cmd/versitygw/main.go @@ -63,6 +63,7 @@ var ( ldapQueryBase, ldapObjClasses string ldapAccessAtr, ldapSecAtr, ldapRoleAtr string ldapUserIdAtr, ldapGroupIdAtr string + ldapDebug bool vaultEndpointURL, vaultSecretStoragePath string vaultAuthMethod, vaultMountPath string vaultRootToken, vaultRoleId string @@ -398,6 +399,12 @@ func initFlags() []cli.Flag { EnvVars: []string{"VGW_IAM_LDAP_GROUP_ID_ATR"}, Destination: &ldapGroupIdAtr, }, + &cli.BoolFlag{ + Name: "iam-ldap-debug", + Usage: "ldap server debug output", + EnvVars: []string{"VGW_IAM_LDAP_DEBUG"}, + Destination: &ldapDebug, + }, &cli.StringFlag{ Name: "iam-vault-endpoint-url", Usage: "vault server url", @@ -668,6 +675,7 @@ func runGateway(ctx context.Context, be backend.Backend) error { LDAPRoleAtr: ldapRoleAtr, LDAPUserIdAtr: ldapUserIdAtr, LDAPGroupIdAtr: ldapGroupIdAtr, + LDAPDebug: ldapDebug, VaultEndpointURL: vaultEndpointURL, VaultSecretStoragePath: vaultSecretStoragePath, VaultAuthMethod: vaultAuthMethod,