Add DecodeDN and QuickNormalizeDN functions to LDAP config (#20076)

This commit is contained in:
Taran Pelkey
2024-07-11 21:04:53 -04:00
committed by GitHub
parent e139673969
commit f5d2fbc84c
6 changed files with 88 additions and 36 deletions

View File

@@ -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)

View File

@@ -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
}

View File

@@ -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