@@ -19,6 +19,17 @@ import (
1919 "golang.org/x/exp/slices"
2020)
2121
22+ var objectClassesToResourceTypes = map [string ]* v2.ResourceType {
23+ "group" : resourceTypeGroup ,
24+ "groupOfNames" : resourceTypeGroup ,
25+ "groupOfUniqueNames" : resourceTypeGroup ,
26+ "inetOrgPerson" : resourceTypeUser ,
27+ "posixGroup" : resourceTypeGroup ,
28+ "organizationalPerson" : resourceTypeUser ,
29+ "person" : resourceTypeUser ,
30+ "user" : resourceTypeUser ,
31+ }
32+
2233const (
2334 groupObjectClasses = "(objectClass=groupOfUniqueNames)(objectClass=groupOfNames)(objectClass=posixGroup)(objectClass=group)"
2435 groupFilter = "(|" + groupObjectClasses + ")"
@@ -146,22 +157,49 @@ func (g *groupResourceType) Entitlements(ctx context.Context, resource *v2.Resou
146157}
147158
148159// newGrantFromDN - create a `Grant` from a given group and user distinguished name.
149- func newGrantFromDN (resource * v2.Resource , userDN string ) * v2.Grant {
160+ func newGrantFromDN (groupResource * v2.Resource , dn string , resourceType * v2.ResourceType ) * v2.Grant {
161+ grantOpts := []grant.GrantOption {}
162+ if resourceType == resourceTypeGroup {
163+ grantOpts = append (grantOpts , grant .WithAnnotation (& v2.GrantExpandable {
164+ EntitlementIds : []string {
165+ fmt .Sprintf ("group:%s:member" , dn ),
166+ },
167+ }))
168+ }
150169 g := grant .NewGrant (
151170 // remove group profile from grant so we're not saving all group memberships in every grant
152171 & v2.Resource {
153- Id : resource .Id ,
172+ Id : groupResource .Id ,
154173 },
155174 groupMemberEntitlement ,
156175 // remove user profile from grant so we're not saving repetitive user info in every grant
157176 & v2.ResourceId {
158- ResourceType : resourceTypeUser .Id ,
159- Resource : userDN ,
177+ ResourceType : resourceType .Id ,
178+ Resource : dn ,
160179 },
180+ grantOpts ... ,
161181 )
162182 return g
163183}
164184
185+ func newGrantFromEntry (groupResource * v2.Resource , entry * ldap3.Entry ) * v2.Grant {
186+ var dn string
187+ parsedDN , err := ldap .CanonicalizeDN (entry .DN )
188+ if err == nil {
189+ dn = parsedDN .String ()
190+ } else {
191+ dn = entry .DN
192+ }
193+
194+ for _ , objectClass := range entry .GetAttributeValues ("objectClass" ) {
195+ if resourceType , ok := objectClassesToResourceTypes [objectClass ]; ok {
196+ return newGrantFromDN (groupResource , dn , resourceType )
197+ }
198+ }
199+
200+ return newGrantFromDN (groupResource , dn , resourceTypeUser )
201+ }
202+
165203func (g * groupResourceType ) Grants (ctx context.Context , resource * v2.Resource , token * pagination.Token ) ([]* v2.Grant , string , annotations.Annotations , error ) {
166204 l := ctxzap .Extract (ctx )
167205 groupDN , err := ldap .CanonicalizeDN (resource .Id .Resource )
@@ -196,7 +234,25 @@ func (g *groupResourceType) Grants(ctx context.Context, resource *v2.Resource, t
196234 for memberId := range memberIDs .Iter () {
197235 parsedDN , err := ldap .CanonicalizeDN (memberId )
198236 if err == nil {
199- g := newGrantFromDN (resource , parsedDN .String ())
237+ member , _ , err := g .client .LdapSearch (
238+ ctx ,
239+ ldap3 .ScopeWholeSubtree ,
240+ parsedDN ,
241+ "" ,
242+ nil ,
243+ "" ,
244+ 1 ,
245+ )
246+ if err != nil {
247+ l .Error ("ldap-connector: failed to get group member" , zap .String ("group" , groupDN .String ()), zap .String ("member_id" , memberId ), zap .Error (err ))
248+ }
249+ var g * v2.Grant
250+ if len (member ) == 1 {
251+ g = newGrantFromEntry (resource , member [0 ])
252+ } else {
253+ // Fall back to creating a grant and assuming it's for a user.
254+ g = newGrantFromDN (resource , parsedDN .String (), resourceTypeUser )
255+ }
200256 rv = append (rv , g )
201257 continue
202258 }
@@ -208,7 +264,7 @@ func (g *groupResourceType) Grants(ctx context.Context, resource *v2.Resource, t
208264 if memberDN == "" {
209265 continue
210266 }
211- g := newGrantFromDN (resource , memberDN )
267+ g := newGrantFromDN (resource , memberDN , resourceTypeUser )
212268 rv = append (rv , g )
213269 }
214270
@@ -238,7 +294,7 @@ func (g *groupResourceType) Grants(ctx context.Context, resource *v2.Resource, t
238294 l .Error ("ldap-connector: invalid user DN" , zap .String ("user_dn" , userEntry .DN ), zap .Error (err ))
239295 continue
240296 }
241- g := newGrantFromDN (resource , userDN .String ())
297+ g := newGrantFromDN (resource , userDN .String (), resourceTypeUser )
242298 rv = append (rv , g )
243299 }
244300 if nextPage == "" {
0 commit comments