@@ -42,6 +42,16 @@ type IdentityClient interface {
4242 GetUserRoles (ctx context.Context , userID string ) ([]ThunderRole , error )
4343 InviteUser (ctx context.Context , email string , ouID string ) (string , error )
4444
45+ // Agents (identity, not the AMP agent resource)
46+ // GetAgentRoles returns the roles assigned to an agent identity, by
47+ // fanning out over every role and checking its assignees — Thunder has no
48+ // reverse-lookup endpoint for this (mirrors GetUserRoles/GetGroupRoles).
49+ GetAgentRoles (ctx context.Context , agentID string ) ([]ThunderRole , error )
50+ // GetAgentGroups returns the groups an agent identity belongs to, by
51+ // fanning out over every group in ouID and checking its members —
52+ // Thunder has no reverse-lookup endpoint for this.
53+ GetAgentGroups (ctx context.Context , ouID , agentID string ) ([]ThunderGroup , error )
54+
4555 // Groups
4656 ListGroups (ctx context.Context , ouID string , offset , limit int ) ([]ThunderGroup , int , error )
4757 ListGroupsByOUId (ctx context.Context , ouID string , offset , limit int ) ([]ThunderGroup , int , error )
@@ -482,14 +492,20 @@ func (c *thunderClient) listRoleAssignmentEntries(ctx context.Context, roleID st
482492 return resp .Assignments , nil
483493}
484494
485- func (c * thunderClient ) GetGroupRoles (ctx context.Context , groupID string ) ([]ThunderRole , error ) {
495+ // rolesForAssignee returns every role that has an assignment entry matching
496+ // assigneeType/assigneeID (e.g. "group"/groupID, "user"/userID, "agent"/
497+ // agentID). Thunder has no reverse-lookup endpoint for "roles assigned to
498+ // this assignee", so this pages through every role in the instance and
499+ // checks its assignment entries client-side. Shared by GetGroupRoles,
500+ // GetUserRoles, and GetAgentRoles.
501+ func (c * thunderClient ) rolesForAssignee (ctx context.Context , assigneeType , assigneeID string ) ([]ThunderRole , error ) {
486502 const pageSize = 50
487503 var allRoles []ThunderRole
488504 offset := 0
489505 for {
490506 page , total , err := c .ListRoles (ctx , "" , offset , pageSize )
491507 if err != nil {
492- return nil , fmt .Errorf ("thunder get group roles (list): %w" , err )
508+ return nil , fmt .Errorf ("thunder get %s roles (list): %w" , assigneeType , err )
493509 }
494510 allRoles = append (allRoles , page ... )
495511 offset += len (page )
@@ -498,52 +514,83 @@ func (c *thunderClient) GetGroupRoles(ctx context.Context, groupID string) ([]Th
498514 }
499515 }
500516
501- var groupRoles []ThunderRole
517+ var assigneeRoles []ThunderRole
502518 for _ , role := range allRoles {
503519 entries , err := c .listRoleAssignmentEntries (ctx , role .ID )
504520 if err != nil {
505- return nil , fmt .Errorf ("thunder get group roles (assignments for role %s): %w" , role .ID , err )
521+ return nil , fmt .Errorf ("thunder get %s roles (assignments for role %s): %w" , assigneeType , role .ID , err )
506522 }
507523 for _ , e := range entries {
508- if e .Type == "group" && e .ID == groupID {
509- groupRoles = append (groupRoles , role )
524+ if e .Type == assigneeType && e .ID == assigneeID {
525+ assigneeRoles = append (assigneeRoles , role )
510526 break
511527 }
512528 }
513529 }
514- return groupRoles , nil
530+ return assigneeRoles , nil
531+ }
532+
533+ func (c * thunderClient ) GetGroupRoles (ctx context.Context , groupID string ) ([]ThunderRole , error ) {
534+ return c .rolesForAssignee (ctx , "group" , groupID )
515535}
516536
517537func (c * thunderClient ) GetUserRoles (ctx context.Context , userID string ) ([]ThunderRole , error ) {
538+ return c .rolesForAssignee (ctx , "user" , userID )
539+ }
540+
541+ // GetAgentRoles returns the roles assigned to an agent identity. Same
542+ // fan-out-and-filter approach as GetUserRoles/GetGroupRoles, since Thunder has
543+ // no reverse-lookup endpoint for "roles assigned to this assignee".
544+ func (c * thunderClient ) GetAgentRoles (ctx context.Context , agentID string ) ([]ThunderRole , error ) {
545+ return c .rolesForAssignee (ctx , "agent" , agentID )
546+ }
547+
548+ // GetAgentGroups returns the groups an agent identity belongs to, by fanning
549+ // out over every group in ouID and checking its member entries — Thunder has
550+ // no reverse-lookup endpoint for "groups this assignee belongs to".
551+ func (c * thunderClient ) GetAgentGroups (ctx context.Context , ouID , agentID string ) ([]ThunderGroup , error ) {
518552 const pageSize = 50
519- var allRoles []ThunderRole
553+ var allGroups []ThunderGroup
520554 offset := 0
521555 for {
522- page , total , err := c .ListRoles (ctx , "" , offset , pageSize )
556+ page , total , err := c .ListGroupsByOUId (ctx , ouID , offset , pageSize )
523557 if err != nil {
524- return nil , fmt .Errorf ("thunder get user roles (list): %w" , err )
558+ return nil , fmt .Errorf ("thunder get agent groups (list): %w" , err )
525559 }
526- allRoles = append (allRoles , page ... )
560+ allGroups = append (allGroups , page ... )
527561 offset += len (page )
528562 if offset >= total || len (page ) == 0 {
529563 break
530564 }
531565 }
532566
533- var userRoles []ThunderRole
534- for _ , role := range allRoles {
535- entries , err := c .listRoleAssignmentEntries (ctx , role .ID )
536- if err != nil {
537- return nil , fmt .Errorf ("thunder get user roles (assignments for role %s): %w" , role .ID , err )
538- }
539- for _ , e := range entries {
540- if e .Type == "user" && e .ID == userID {
541- userRoles = append (userRoles , role )
567+ var agentGroups []ThunderGroup
568+ for _ , group := range allGroups {
569+ const memberPageSize = 100
570+ memberOffset := 0
571+ for {
572+ members , total , err := c .ListGroupMemberEntries (ctx , group .ID , memberOffset , memberPageSize )
573+ if err != nil {
574+ return nil , fmt .Errorf ("thunder get agent groups (members for group %s): %w" , group .ID , err )
575+ }
576+ matched := false
577+ for _ , m := range members {
578+ if m .Type == "agent" && m .ID == agentID {
579+ matched = true
580+ break
581+ }
582+ }
583+ if matched {
584+ agentGroups = append (agentGroups , group )
585+ break
586+ }
587+ memberOffset += len (members )
588+ if memberOffset >= total || len (members ) == 0 {
542589 break
543590 }
544591 }
545592 }
546- return userRoles , nil
593+ return agentGroups , nil
547594}
548595
549596// --- Roles ---
0 commit comments