[LDAP] Support syncing user-group memberships with LDAP service (#12785)

When configured in Lookup Bind mode, the server now periodically queries the
LDAP IDP service to find changes to a user's group memberships, and saves this
info to update the access policies for all temporary and service account
credentials belonging to LDAP users.
This commit is contained in:
Aditya Manthramurthy
2021-07-24 11:57:36 -07:00
committed by GitHub
parent e936871b83
commit de00b641da
3 changed files with 147 additions and 20 deletions

View File

@@ -29,6 +29,7 @@ import (
"time"
ldap "github.com/go-ldap/ldap/v3"
"github.com/minio/minio-go/v7/pkg/set"
"github.com/minio/minio/internal/auth"
"github.com/minio/minio/internal/config"
"github.com/minio/minio/internal/logger"
@@ -296,7 +297,7 @@ func (l *Config) searchForUserGroups(conn *ldap.Conn, username, bindDN string) (
return groups, nil
}
// LookupUserDN searches for the full DN ang groups of a given username
// LookupUserDN searches for the full DN and groups of a given username
func (l *Config) LookupUserDN(username string) (string, []string, error) {
if !l.isUsingLookupBind {
return "", nil, errors.New("current lookup mode does not support searching for User DN")
@@ -477,9 +478,9 @@ func (l Config) IsLDAPUserDN(user string) bool {
return strings.HasSuffix(user, ","+l.UserDNSearchBaseDN)
}
// GetNonExistentUserDNS - find user accounts that are no longer present in the
// LDAP server.
func (l *Config) GetNonExistentUserDNS(userDNS []string) ([]string, error) {
// GetNonExistentUserDistNames - find user accounts (DNs) that are no longer
// present in the LDAP server.
func (l *Config) GetNonExistentUserDistNames(userDistNames []string) ([]string, error) {
if !l.isUsingLookupBind {
return nil, errors.New("current LDAP configuration does not permit looking for expired user accounts")
}
@@ -496,7 +497,7 @@ func (l *Config) GetNonExistentUserDNS(userDNS []string) ([]string, error) {
}
nonExistentUsers := []string{}
for _, dn := range userDNS {
for _, dn := range userDistNames {
searchRequest := ldap.NewSearchRequest(
dn,
ldap.ScopeBaseObject, ldap.NeverDerefAliases, 0, 0, false,
@@ -523,6 +524,37 @@ func (l *Config) GetNonExistentUserDNS(userDNS []string) ([]string, error) {
return nonExistentUsers, nil
}
// LookupGroupMemberships - for each DN finds the set of LDAP groups they are a
// member of.
func (l *Config) LookupGroupMemberships(userDistNames []string, userDNToUsernameMap map[string]string) (map[string]set.StringSet, error) {
if !l.isUsingLookupBind {
return nil, errors.New("current LDAP configuration does not permit this lookup")
}
conn, err := l.Connect()
if err != nil {
return nil, err
}
defer conn.Close()
// Bind to the lookup user account
if err = l.lookupBind(conn); err != nil {
return nil, err
}
res := make(map[string]set.StringSet, len(userDistNames))
for _, userDistName := range userDistNames {
username := userDNToUsernameMap[userDistName]
groups, err := l.searchForUserGroups(conn, username, userDistName)
if err != nil {
return nil, err
}
res[userDistName] = set.CreateStringSet(groups...)
}
return res, nil
}
// EnabledWithLookupBind - checks if ldap IDP is enabled in lookup bind mode.
func (l Config) EnabledWithLookupBind() bool {
return l.Enabled && l.isUsingLookupBind