mirror of
https://github.com/minio/minio.git
synced 2024-12-24 06:05:55 -05:00
Add DecodeDN and QuickNormalizeDN functions to LDAP config (#20076)
This commit is contained in:
parent
e139673969
commit
f5d2fbc84c
@ -552,7 +552,7 @@ func (a adminAPIHandlers) ListAccessKeysLDAPBulk(w http.ResponseWriter, r *http.
|
||||
dnList = append(dnList, selfDN)
|
||||
}
|
||||
|
||||
accessKeyMap := make(map[string]madmin.ListAccessKeysLDAPResp)
|
||||
var ldapUserList []string
|
||||
if isAll {
|
||||
ldapUsers, err := globalIAMSys.ListLDAPUsers(ctx)
|
||||
if err != nil {
|
||||
@ -560,7 +560,7 @@ func (a adminAPIHandlers) ListAccessKeysLDAPBulk(w http.ResponseWriter, r *http.
|
||||
return
|
||||
}
|
||||
for user := range ldapUsers {
|
||||
accessKeyMap[user] = madmin.ListAccessKeysLDAPResp{}
|
||||
ldapUserList = append(ldapUserList, user)
|
||||
}
|
||||
} else {
|
||||
for _, userDN := range dnList {
|
||||
@ -573,7 +573,7 @@ func (a adminAPIHandlers) ListAccessKeysLDAPBulk(w http.ResponseWriter, r *http.
|
||||
if foundResult == nil {
|
||||
continue
|
||||
}
|
||||
accessKeyMap[foundResult.NormDN] = madmin.ListAccessKeysLDAPResp{}
|
||||
ldapUserList = append(ldapUserList, foundResult.NormDN)
|
||||
}
|
||||
}
|
||||
|
||||
@ -598,9 +598,12 @@ func (a adminAPIHandlers) ListAccessKeysLDAPBulk(w http.ResponseWriter, r *http.
|
||||
return
|
||||
}
|
||||
|
||||
for dn, accessKeys := range accessKeyMap {
|
||||
accessKeyMap := make(map[string]madmin.ListAccessKeysLDAPResp)
|
||||
for _, internalDN := range ldapUserList {
|
||||
externalDN := globalIAMSys.LDAPConfig.DecodeDN(internalDN)
|
||||
accessKeys := madmin.ListAccessKeysLDAPResp{}
|
||||
if listSTSKeys {
|
||||
stsKeys, err := globalIAMSys.ListSTSAccounts(ctx, dn)
|
||||
stsKeys, err := globalIAMSys.ListSTSAccounts(ctx, internalDN)
|
||||
if err != nil {
|
||||
writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL)
|
||||
return
|
||||
@ -614,13 +617,12 @@ func (a adminAPIHandlers) ListAccessKeysLDAPBulk(w http.ResponseWriter, r *http.
|
||||
}
|
||||
// if only STS keys, skip if user has no STS keys
|
||||
if !listServiceAccounts && len(stsKeys) == 0 {
|
||||
delete(accessKeyMap, dn)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if listServiceAccounts {
|
||||
serviceAccounts, err := globalIAMSys.ListServiceAccounts(ctx, dn)
|
||||
serviceAccounts, err := globalIAMSys.ListServiceAccounts(ctx, internalDN)
|
||||
if err != nil {
|
||||
writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL)
|
||||
return
|
||||
@ -634,11 +636,10 @@ func (a adminAPIHandlers) ListAccessKeysLDAPBulk(w http.ResponseWriter, r *http.
|
||||
}
|
||||
// if only service accounts, skip if user has no service accounts
|
||||
if !listSTSKeys && len(serviceAccounts) == 0 {
|
||||
delete(accessKeyMap, dn)
|
||||
continue
|
||||
}
|
||||
}
|
||||
accessKeyMap[dn] = accessKeys
|
||||
accessKeyMap[externalDN] = accessKeys
|
||||
}
|
||||
|
||||
data, err := json.Marshal(accessKeyMap)
|
||||
|
@ -2090,7 +2090,7 @@ func (store *IAMStoreSys) GetAllSTSUserMappings(userPredicate func(string) bool)
|
||||
|
||||
// Assumes store is locked by caller. If userMap is empty, returns all user mappings.
|
||||
func (store *IAMStoreSys) listUserPolicyMappings(cache *iamCache, userMap map[string]set.StringSet,
|
||||
userPredicate func(string) bool,
|
||||
userPredicate func(string) bool, decodeFunc func(string) string,
|
||||
) []madmin.UserPolicyEntities {
|
||||
stsMap := xsync.NewMapOf[string, MappedPolicy]()
|
||||
resMap := make(map[string]madmin.UserPolicyEntities, len(userMap))
|
||||
@ -2098,9 +2098,13 @@ func (store *IAMStoreSys) listUserPolicyMappings(cache *iamCache, userMap map[st
|
||||
for user, groupSet := range userMap {
|
||||
// Attempt to load parent user mapping for STS accounts
|
||||
store.loadMappedPolicy(context.TODO(), user, stsUser, false, stsMap)
|
||||
blankEntities := madmin.UserPolicyEntities{User: user}
|
||||
decodeUser := user
|
||||
if decodeFunc != nil {
|
||||
decodeUser = decodeFunc(user)
|
||||
}
|
||||
blankEntities := madmin.UserPolicyEntities{User: decodeUser}
|
||||
if !groupSet.IsEmpty() {
|
||||
blankEntities.MemberOfMappings = store.listGroupPolicyMappings(cache, groupSet, nil)
|
||||
blankEntities.MemberOfMappings = store.listGroupPolicyMappings(cache, groupSet, nil, decodeFunc)
|
||||
}
|
||||
resMap[user] = blankEntities
|
||||
}
|
||||
@ -2116,7 +2120,11 @@ func (store *IAMStoreSys) listUserPolicyMappings(cache *iamCache, userMap map[st
|
||||
if len(userMap) > 0 {
|
||||
return true
|
||||
}
|
||||
entitiesWithMemberOf = madmin.UserPolicyEntities{User: user}
|
||||
decodeUser := user
|
||||
if decodeFunc != nil {
|
||||
decodeUser = decodeFunc(user)
|
||||
}
|
||||
entitiesWithMemberOf = madmin.UserPolicyEntities{User: decodeUser}
|
||||
}
|
||||
|
||||
ps := mappedPolicy.toSlice()
|
||||
@ -2155,7 +2163,7 @@ func (store *IAMStoreSys) listUserPolicyMappings(cache *iamCache, userMap map[st
|
||||
|
||||
// Assumes store is locked by caller. If groups is empty, returns all group mappings.
|
||||
func (store *IAMStoreSys) listGroupPolicyMappings(cache *iamCache, groupsSet set.StringSet,
|
||||
groupPredicate func(string) bool,
|
||||
groupPredicate func(string) bool, decodeFunc func(string) string,
|
||||
) []madmin.GroupPolicyEntities {
|
||||
var r []madmin.GroupPolicyEntities
|
||||
|
||||
@ -2168,10 +2176,15 @@ func (store *IAMStoreSys) listGroupPolicyMappings(cache *iamCache, groupsSet set
|
||||
return true
|
||||
}
|
||||
|
||||
decodeGroup := group
|
||||
if decodeFunc != nil {
|
||||
decodeGroup = decodeFunc(group)
|
||||
}
|
||||
|
||||
ps := mappedPolicy.toSlice()
|
||||
sort.Strings(ps)
|
||||
r = append(r, madmin.GroupPolicyEntities{
|
||||
Group: group,
|
||||
Group: decodeGroup,
|
||||
Policies: ps,
|
||||
})
|
||||
return true
|
||||
@ -2186,7 +2199,7 @@ func (store *IAMStoreSys) listGroupPolicyMappings(cache *iamCache, groupsSet set
|
||||
|
||||
// Assumes store is locked by caller. If policies is empty, returns all policy mappings.
|
||||
func (store *IAMStoreSys) listPolicyMappings(cache *iamCache, queryPolSet set.StringSet,
|
||||
userPredicate, groupPredicate func(string) bool,
|
||||
userPredicate, groupPredicate func(string) bool, decodeFunc func(string) string,
|
||||
) []madmin.PolicyEntities {
|
||||
policyToUsersMap := make(map[string]set.StringSet)
|
||||
cache.iamUserPolicyMap.Range(func(user string, mappedPolicy MappedPolicy) bool {
|
||||
@ -2194,6 +2207,11 @@ func (store *IAMStoreSys) listPolicyMappings(cache *iamCache, queryPolSet set.St
|
||||
return true
|
||||
}
|
||||
|
||||
decodeUser := user
|
||||
if decodeFunc != nil {
|
||||
decodeUser = decodeFunc(user)
|
||||
}
|
||||
|
||||
commonPolicySet := mappedPolicy.policySet()
|
||||
if !queryPolSet.IsEmpty() {
|
||||
commonPolicySet = commonPolicySet.Intersection(queryPolSet)
|
||||
@ -2201,9 +2219,9 @@ func (store *IAMStoreSys) listPolicyMappings(cache *iamCache, queryPolSet set.St
|
||||
for _, policy := range commonPolicySet.ToSlice() {
|
||||
s, ok := policyToUsersMap[policy]
|
||||
if !ok {
|
||||
policyToUsersMap[policy] = set.CreateStringSet(user)
|
||||
policyToUsersMap[policy] = set.CreateStringSet(decodeUser)
|
||||
} else {
|
||||
s.Add(user)
|
||||
s.Add(decodeUser)
|
||||
policyToUsersMap[policy] = s
|
||||
}
|
||||
}
|
||||
@ -2217,6 +2235,11 @@ func (store *IAMStoreSys) listPolicyMappings(cache *iamCache, queryPolSet set.St
|
||||
continue
|
||||
}
|
||||
|
||||
decodeUser := user
|
||||
if decodeFunc != nil {
|
||||
decodeUser = decodeFunc(user)
|
||||
}
|
||||
|
||||
var mappedPolicy MappedPolicy
|
||||
store.loadIAMConfig(context.Background(), &mappedPolicy, getMappedPolicyPath(user, stsUser, false))
|
||||
|
||||
@ -2227,9 +2250,9 @@ func (store *IAMStoreSys) listPolicyMappings(cache *iamCache, queryPolSet set.St
|
||||
for _, policy := range commonPolicySet.ToSlice() {
|
||||
s, ok := policyToUsersMap[policy]
|
||||
if !ok {
|
||||
policyToUsersMap[policy] = set.CreateStringSet(user)
|
||||
policyToUsersMap[policy] = set.CreateStringSet(decodeUser)
|
||||
} else {
|
||||
s.Add(user)
|
||||
s.Add(decodeUser)
|
||||
policyToUsersMap[policy] = s
|
||||
}
|
||||
}
|
||||
@ -2244,6 +2267,11 @@ func (store *IAMStoreSys) listPolicyMappings(cache *iamCache, queryPolSet set.St
|
||||
return true
|
||||
}
|
||||
|
||||
decodeUser := user
|
||||
if decodeFunc != nil {
|
||||
decodeUser = decodeFunc(user)
|
||||
}
|
||||
|
||||
commonPolicySet := mappedPolicy.policySet()
|
||||
if !queryPolSet.IsEmpty() {
|
||||
commonPolicySet = commonPolicySet.Intersection(queryPolSet)
|
||||
@ -2251,9 +2279,9 @@ func (store *IAMStoreSys) listPolicyMappings(cache *iamCache, queryPolSet set.St
|
||||
for _, policy := range commonPolicySet.ToSlice() {
|
||||
s, ok := policyToUsersMap[policy]
|
||||
if !ok {
|
||||
policyToUsersMap[policy] = set.CreateStringSet(user)
|
||||
policyToUsersMap[policy] = set.CreateStringSet(decodeUser)
|
||||
} else {
|
||||
s.Add(user)
|
||||
s.Add(decodeUser)
|
||||
policyToUsersMap[policy] = s
|
||||
}
|
||||
}
|
||||
@ -2268,6 +2296,11 @@ func (store *IAMStoreSys) listPolicyMappings(cache *iamCache, queryPolSet set.St
|
||||
return true
|
||||
}
|
||||
|
||||
decodeGroup := group
|
||||
if decodeFunc != nil {
|
||||
decodeGroup = decodeFunc(group)
|
||||
}
|
||||
|
||||
commonPolicySet := mappedPolicy.policySet()
|
||||
if !queryPolSet.IsEmpty() {
|
||||
commonPolicySet = commonPolicySet.Intersection(queryPolSet)
|
||||
@ -2275,9 +2308,9 @@ func (store *IAMStoreSys) listPolicyMappings(cache *iamCache, queryPolSet set.St
|
||||
for _, policy := range commonPolicySet.ToSlice() {
|
||||
s, ok := policyToGroupsMap[policy]
|
||||
if !ok {
|
||||
policyToGroupsMap[policy] = set.CreateStringSet(group)
|
||||
policyToGroupsMap[policy] = set.CreateStringSet(decodeGroup)
|
||||
} else {
|
||||
s.Add(group)
|
||||
s.Add(decodeGroup)
|
||||
policyToGroupsMap[policy] = s
|
||||
}
|
||||
}
|
||||
@ -2318,7 +2351,7 @@ func (store *IAMStoreSys) listPolicyMappings(cache *iamCache, queryPolSet set.St
|
||||
|
||||
// ListPolicyMappings - return users/groups mapped to policies.
|
||||
func (store *IAMStoreSys) ListPolicyMappings(q cleanEntitiesQuery,
|
||||
userPredicate, groupPredicate func(string) bool,
|
||||
userPredicate, groupPredicate func(string) bool, decodeFunc func(string) string,
|
||||
) madmin.PolicyEntitiesResult {
|
||||
cache := store.rlock()
|
||||
defer store.runlock()
|
||||
@ -2328,13 +2361,13 @@ func (store *IAMStoreSys) ListPolicyMappings(q cleanEntitiesQuery,
|
||||
isAllPoliciesQuery := len(q.Users) == 0 && len(q.Groups) == 0 && len(q.Policies) == 0
|
||||
|
||||
if len(q.Users) > 0 {
|
||||
result.UserMappings = store.listUserPolicyMappings(cache, q.Users, userPredicate)
|
||||
result.UserMappings = store.listUserPolicyMappings(cache, q.Users, userPredicate, decodeFunc)
|
||||
}
|
||||
if len(q.Groups) > 0 {
|
||||
result.GroupMappings = store.listGroupPolicyMappings(cache, q.Groups, groupPredicate)
|
||||
result.GroupMappings = store.listGroupPolicyMappings(cache, q.Groups, groupPredicate, decodeFunc)
|
||||
}
|
||||
if len(q.Policies) > 0 || isAllPoliciesQuery {
|
||||
result.PolicyMappings = store.listPolicyMappings(cache, q.Policies, userPredicate, groupPredicate)
|
||||
result.PolicyMappings = store.listPolicyMappings(cache, q.Policies, userPredicate, groupPredicate, decodeFunc)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
10
cmd/iam.go
10
cmd/iam.go
@ -841,7 +841,7 @@ func (sys *IAMSys) createCleanEntitiesQuery(q madmin.PolicyEntitiesQuery, ldap b
|
||||
// Validate and normalize groups.
|
||||
for _, group := range q.Groups {
|
||||
lookupRes, underDN, _ := sys.LDAPConfig.GetValidatedGroupDN(nil, group)
|
||||
if lookupRes != nil && !underDN {
|
||||
if lookupRes != nil && underDN {
|
||||
cleanQ.Groups.Add(lookupRes.NormDN)
|
||||
}
|
||||
}
|
||||
@ -871,7 +871,7 @@ func (sys *IAMSys) QueryLDAPPolicyEntities(ctx context.Context, q madmin.PolicyE
|
||||
select {
|
||||
case <-sys.configLoaded:
|
||||
cleanQuery := sys.createCleanEntitiesQuery(q, true)
|
||||
pe := sys.store.ListPolicyMappings(cleanQuery, sys.LDAPConfig.IsLDAPUserDN, sys.LDAPConfig.IsLDAPGroupDN)
|
||||
pe := sys.store.ListPolicyMappings(cleanQuery, sys.LDAPConfig.IsLDAPUserDN, sys.LDAPConfig.IsLDAPGroupDN, sys.LDAPConfig.DecodeDN)
|
||||
pe.Timestamp = UTCNow()
|
||||
return &pe, nil
|
||||
case <-ctx.Done():
|
||||
@ -955,7 +955,7 @@ func (sys *IAMSys) QueryPolicyEntities(ctx context.Context, q madmin.PolicyEntit
|
||||
return !sys.LDAPConfig.IsLDAPGroupDN(s)
|
||||
}
|
||||
}
|
||||
pe := sys.store.ListPolicyMappings(cleanQuery, userPredicate, groupPredicate)
|
||||
pe := sys.store.ListPolicyMappings(cleanQuery, userPredicate, groupPredicate, nil)
|
||||
pe.Timestamp = UTCNow()
|
||||
return &pe, nil
|
||||
case <-ctx.Done():
|
||||
@ -2027,7 +2027,7 @@ func (sys *IAMSys) PolicyDBUpdateLDAP(ctx context.Context, isAttach bool,
|
||||
if dnResult == nil {
|
||||
// dn not found - still attempt to detach if provided user is a DN.
|
||||
if !isAttach && sys.LDAPConfig.IsLDAPUserDN(r.User) {
|
||||
dn = r.User
|
||||
dn = sys.LDAPConfig.QuickNormalizeDN(r.User)
|
||||
} else {
|
||||
err = errNoSuchUser
|
||||
return
|
||||
@ -2044,7 +2044,7 @@ func (sys *IAMSys) PolicyDBUpdateLDAP(ctx context.Context, isAttach bool,
|
||||
}
|
||||
if dnResult == nil || !underBaseDN {
|
||||
if !isAttach {
|
||||
dn = r.Group
|
||||
dn = sys.LDAPConfig.QuickNormalizeDN(r.Group)
|
||||
} else {
|
||||
err = errNoSuchGroup
|
||||
return
|
||||
|
2
go.mod
2
go.mod
@ -55,7 +55,7 @@ require (
|
||||
github.com/minio/madmin-go/v3 v3.0.58
|
||||
github.com/minio/minio-go/v7 v7.0.73
|
||||
github.com/minio/mux v1.9.0
|
||||
github.com/minio/pkg/v3 v3.0.3
|
||||
github.com/minio/pkg/v3 v3.0.7
|
||||
github.com/minio/selfupdate v0.6.0
|
||||
github.com/minio/simdjson-go v0.4.5
|
||||
github.com/minio/sio v0.4.0
|
||||
|
4
go.sum
4
go.sum
@ -471,8 +471,8 @@ github.com/minio/mux v1.9.0 h1:dWafQFyEfGhJvK6AwLOt83bIG5bxKxKJnKMCi0XAaoA=
|
||||
github.com/minio/mux v1.9.0/go.mod h1:1pAare17ZRL5GpmNL+9YmqHoWnLmMZF9C/ioUCfy0BQ=
|
||||
github.com/minio/pkg/v2 v2.0.19 h1:r187/k/oVH9H0DDwvLY5WipkJaZ4CLd4KI3KgIUExR0=
|
||||
github.com/minio/pkg/v2 v2.0.19/go.mod h1:luK9LAhQlAPzSuF6F326XSCKjMc1G3Tbh+a9JYwqh8M=
|
||||
github.com/minio/pkg/v3 v3.0.3 h1:PUJVi5a6Hdn5mIhffC24koFMQwucvTyBHsIOjsisI+U=
|
||||
github.com/minio/pkg/v3 v3.0.3/go.mod h1:53gkSUVHcfYoskOs5YAJ3D99nsd2SKru90rdE9whlXU=
|
||||
github.com/minio/pkg/v3 v3.0.7 h1:1I2CbFKO+brioB6Pbnw0jLlFxo+YPy6hCTTXTSitgI8=
|
||||
github.com/minio/pkg/v3 v3.0.7/go.mod h1:njlf539caYrgXqn/CXewqvkqBIMDTQo9oBBEL34LzY0=
|
||||
github.com/minio/selfupdate v0.6.0 h1:i76PgT0K5xO9+hjzKcacQtO7+MjJ4JKA8Ak8XQ9DDwU=
|
||||
github.com/minio/selfupdate v0.6.0/go.mod h1:bO02GTIPCMQFTEvE5h4DjYB58bCoZ35XLeBf0buTDdM=
|
||||
github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM=
|
||||
|
@ -402,3 +402,21 @@ func (l *Config) LookupGroupMemberships(userDistNames []string, userDNToUsername
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// QuickNormalizeDN - normalizes the given DN without checking if it is valid or
|
||||
// exists in the LDAP directory. Returns input if error
|
||||
func (l Config) QuickNormalizeDN(dn string) string {
|
||||
if normDN, err := xldap.NormalizeDN(dn); err == nil {
|
||||
return normDN
|
||||
}
|
||||
return dn
|
||||
}
|
||||
|
||||
// DecodeDN - denormalizes the given DN by unescaping any escaped characters.
|
||||
// Returns input if error
|
||||
func (l Config) DecodeDN(dn string) string {
|
||||
if decodedDN, err := xldap.DecodeDN(dn); err == nil {
|
||||
return decodedDN
|
||||
}
|
||||
return dn
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user