mirror of
https://github.com/minio/minio.git
synced 2024-12-24 06:05:55 -05:00
[IDP:LDAP] Cleanup creds for removed LDAP user entries (#12759)
This commit is contained in:
parent
e7a4967726
commit
0db1c94e7d
60
cmd/iam.go
60
cmd/iam.go
@ -650,14 +650,22 @@ func (sys *IAMSys) Init(ctx context.Context, objAPI ObjectLayer) {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
if globalOpenIDConfig.ProviderEnabled() {
|
// Set up polling for expired accounts and credentials purging.
|
||||||
|
switch {
|
||||||
|
case globalOpenIDConfig.ProviderEnabled():
|
||||||
go func() {
|
go func() {
|
||||||
// Purge expired credentials
|
|
||||||
for {
|
for {
|
||||||
time.Sleep(globalRefreshIAMInterval)
|
time.Sleep(globalRefreshIAMInterval)
|
||||||
sys.purgeExpiredCredentialsForExternalSSO(ctx)
|
sys.purgeExpiredCredentialsForExternalSSO(ctx)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
case globalLDAPConfig.EnabledWithLookupBind():
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
time.Sleep(globalRefreshIAMInterval)
|
||||||
|
sys.purgeExpiredCredentialsForLDAP(ctx)
|
||||||
|
}
|
||||||
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
go sys.store.watch(ctx, sys)
|
go sys.store.watch(ctx, sys)
|
||||||
@ -1571,6 +1579,54 @@ func (sys *IAMSys) purgeExpiredCredentialsForExternalSSO(ctx context.Context) {
|
|||||||
sys.store.unlock()
|
sys.store.unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// purgeExpiredCredentialsForLDAP - validates if local credentials are still
|
||||||
|
// valid by checking LDAP server if the relevant users are still present.
|
||||||
|
func (sys *IAMSys) purgeExpiredCredentialsForLDAP(ctx context.Context) {
|
||||||
|
sys.store.lock()
|
||||||
|
parentUsersMap := make(map[string][]auth.Credentials, len(sys.iamUsersMap))
|
||||||
|
parentUsers := make([]string, 0, len(sys.iamUsersMap))
|
||||||
|
for _, cred := range sys.iamUsersMap {
|
||||||
|
if cred.IsServiceAccount() || cred.IsTemp() {
|
||||||
|
if globalLDAPConfig.IsLDAPUserDN(cred.ParentUser) {
|
||||||
|
if _, ok := parentUsersMap[cred.ParentUser]; !ok {
|
||||||
|
parentUsers = append(parentUsers, cred.ParentUser)
|
||||||
|
}
|
||||||
|
parentUsersMap[cred.ParentUser] = append(parentUsersMap[cred.ParentUser], cred)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sys.store.unlock()
|
||||||
|
|
||||||
|
expiredUsers, err := globalLDAPConfig.GetNonExistentUserDNS(parentUsers)
|
||||||
|
if err != nil {
|
||||||
|
// Log and return on error - perhaps it'll work the next time.
|
||||||
|
logger.LogIf(GlobalContext, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, expiredUser := range expiredUsers {
|
||||||
|
for _, cred := range parentUsersMap[expiredUser] {
|
||||||
|
userType := regUser
|
||||||
|
if cred.IsServiceAccount() {
|
||||||
|
userType = svcUser
|
||||||
|
} else if cred.IsTemp() {
|
||||||
|
userType = stsUser
|
||||||
|
}
|
||||||
|
sys.store.deleteIAMConfig(ctx, getUserIdentityPath(cred.AccessKey, userType))
|
||||||
|
sys.store.deleteIAMConfig(ctx, getMappedPolicyPath(cred.AccessKey, userType, false))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sys.store.lock()
|
||||||
|
for _, user := range expiredUsers {
|
||||||
|
for _, cred := range parentUsersMap[user] {
|
||||||
|
delete(sys.iamUsersMap, cred.AccessKey)
|
||||||
|
delete(sys.iamUserPolicyMap, cred.AccessKey)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sys.store.unlock()
|
||||||
|
}
|
||||||
|
|
||||||
// GetUser - get user credentials
|
// GetUser - get user credentials
|
||||||
func (sys *IAMSys) GetUser(accessKey string) (cred auth.Credentials, ok bool) {
|
func (sys *IAMSys) GetUser(accessKey string) (cred auth.Credentials, ok bool) {
|
||||||
if !sys.Initialized() {
|
if !sys.Initialized() {
|
||||||
|
@ -452,6 +452,62 @@ func (l Config) testConnection() error {
|
|||||||
return fmt.Errorf("LDAP connection test error: %w", err)
|
return fmt.Errorf("LDAP connection test error: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsLDAPUserDN determines if the given string could be a user DN from LDAP.
|
||||||
|
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) {
|
||||||
|
if !l.isUsingLookupBind {
|
||||||
|
return nil, errors.New("current LDAP configuration does not permit looking for expired user accounts")
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
nonExistentUsers := []string{}
|
||||||
|
for _, dn := range userDNS {
|
||||||
|
searchRequest := ldap.NewSearchRequest(
|
||||||
|
dn,
|
||||||
|
ldap.ScopeBaseObject, ldap.NeverDerefAliases, 0, 0, false,
|
||||||
|
"(objectclass=*)",
|
||||||
|
[]string{}, // only need DN, so no pass no attributes here
|
||||||
|
nil,
|
||||||
|
)
|
||||||
|
|
||||||
|
searchResult, err := conn.Search(searchRequest)
|
||||||
|
if err != nil {
|
||||||
|
// Object does not exist error?
|
||||||
|
if ldap.IsErrorWithCode(err, 32) {
|
||||||
|
nonExistentUsers = append(nonExistentUsers, dn)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(searchResult.Entries) == 0 {
|
||||||
|
// DN was not found - this means this user account is
|
||||||
|
// expired.
|
||||||
|
nonExistentUsers = append(nonExistentUsers, dn)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nonExistentUsers, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// EnabledWithLookupBind - checks if ldap IDP is enabled in lookup bind mode.
|
||||||
|
func (l Config) EnabledWithLookupBind() bool {
|
||||||
|
return l.Enabled && l.isUsingLookupBind
|
||||||
|
}
|
||||||
|
|
||||||
// Enabled returns if jwks is enabled.
|
// Enabled returns if jwks is enabled.
|
||||||
func Enabled(kvs config.KVS) bool {
|
func Enabled(kvs config.KVS) bool {
|
||||||
return kvs.Get(ServerAddr) != ""
|
return kvs.Get(ServerAddr) != ""
|
||||||
|
Loading…
Reference in New Issue
Block a user