Skip to content

Commit

Permalink
move group role grants to group grants to avoid listing groups and gr…
Browse files Browse the repository at this point in the history
…oup roles for each role
  • Loading branch information
laurenleach committed Nov 18, 2024
1 parent 21b180f commit 2636db0
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 153 deletions.
119 changes: 90 additions & 29 deletions pkg/connector/group.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,48 +117,109 @@ func (o *groupResourceType) Grants(
resource *v2.Resource,
token *pagination.Token,
) ([]*v2.Grant, string, annotations.Annotations, error) {
bag, page, err := parsePageToken(token.Token, &v2.ResourceId{ResourceType: resourceTypeGroup.Id})
var rv []*v2.Grant
bag := &pagination.Bag{}
err := bag.Unmarshal(token.Token)
if err != nil {
return nil, "", nil, fmt.Errorf("okta-connectorv2: failed to parse page token: %w", err)
return nil, "", nil, err
}

var rv []*v2.Grant
qp := queryParams(token.Size, page)
if bag.Current() == nil {
bag.Push(pagination.PageState{
ResourceTypeID: resourceTypeRole.Id,
})
bag.Push(pagination.PageState{
ResourceTypeID: resourceTypeUser.Id,
})
}

page := bag.PageToken()

groupID := resource.Id.GetResource()

users, respCtx, err := o.listGroupUsers(ctx, groupID, token, qp)
if err != nil {
return nil, "", nil, fmt.Errorf("okta-connectorv2: failed to list group users: %w", err)
}
switch bag.ResourceTypeID() {
case resourceTypeUser.Id:
qp := queryParams(token.Size, page)

nextPage, annos, err := parseResp(respCtx.OktaResponse)
if err != nil {
return nil, "", nil, fmt.Errorf("okta-connectorv2: failed to parse response: %w", err)
}
users, respCtx, err := o.listGroupUsers(ctx, groupID, token, qp)
if err != nil {
return nil, "", nil, fmt.Errorf("okta-connectorv2: failed to list group users: %w", err)
}

err = bag.Next(nextPage)
if err != nil {
return nil, "", nil, fmt.Errorf("okta-connectorv2: failed to fetch bag.Next: %w", err)
}
nextPage, annos, err := parseResp(respCtx.OktaResponse)
if err != nil {
return nil, "", nil, fmt.Errorf("okta-connectorv2: failed to parse response: %w", err)
}

for _, user := range users {
rv = append(rv, groupGrant(resource, user))
}
err = bag.Next(nextPage)
if err != nil {
return nil, "", nil, fmt.Errorf("okta-connectorv2: failed to fetch bag.Next: %w", err)
}

pageToken, err := bag.Marshal()
if err != nil {
return nil, "", nil, err
}
for _, user := range users {
rv = append(rv, groupGrant(resource, user))
}
pageToken, err := bag.Marshal()
if err != nil {
return nil, "", nil, err
}

if pageToken == "" {
etag := &v2.ETag{
Value: time.Now().UTC().Format(time.RFC3339Nano),
if pageToken == "" {
etag := &v2.ETag{
Value: time.Now().UTC().Format(time.RFC3339Nano),
}
annos.Update(etag)
}
annos.Update(etag)
}

return rv, pageToken, annos, nil
return rv, pageToken, annos, nil
case resourceTypeRole.Id:
roles, resp, err := listGroupAssignedRoles(ctx, o.connector.client, groupID, nil)
if err != nil {
return nil, "", nil, err
}

for _, role := range roles {
if role.Status == roleStatusInactive || role.AssignmentType != "GROUP" || role.Type == roleTypeCustom {
continue
}

// TODO(lauren) convert model helper
roleResource, err := roleResource(ctx, &okta.Role{
Id: role.Id,
Label: role.Label,
Type: role.Type,
}, resourceTypeRole)
if err != nil {
return nil, "", nil, err
}
rv = append(rv, roleGroupGrant(groupID, roleResource))
}

// TODO(lauren) Move this to list method like other methods do
respCtx, err := responseToContext(token, resp)
if err != nil {
return nil, "", nil, err
}

nextPage, annos, err := parseResp(respCtx.OktaResponse)
if err != nil {
return nil, "", nil, fmt.Errorf("okta-connectorv2: failed to parse response: %w", err)
}

err = bag.Next(nextPage)
if err != nil {
return nil, "", nil, fmt.Errorf("okta-connectorv2: failed to fetch bag.Next: %w", err)
}

pageToken, err := bag.Marshal()
if err != nil {
return nil, "", nil, err
}

return rv, pageToken, annos, nil
default:
return nil, "", nil, fmt.Errorf("okta-connector: invalid grant resource type: %s", bag.ResourceTypeID())
}
}

func (o *groupResourceType) listGroups(ctx context.Context, token *pagination.Token, qp *query.Params) ([]*okta.Group, *responseContext, error) {
Expand Down
125 changes: 1 addition & 124 deletions pkg/connector/role.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,143 +131,20 @@ func (o *roleResourceType) Grants(
token *pagination.Token,
) ([]*v2.Grant, string, annotations.Annotations, error) {
var rv []*v2.Grant
_, page, err := parsePageToken(token.Token, resource.Id)
if err != nil {
return nil, "", nil, fmt.Errorf("okta-connectorv2: failed to parse page token: %w", err)
}

bag, err := unmarshalRolesToken(token)
bag, page, err := parsePageToken(token.Token, &v2.ResourceId{ResourceType: resourceTypeRole.Id})
if err != nil {
return nil, "", nil, err
}

if bag.Current() == nil {
// Push onto stack in reverse
bag.Push(pagination.PageState{
ResourceTypeID: resourceTypeGroup.Id,
})
bag.Push(pagination.PageState{
ResourceTypeID: resourceTypeUser.Id,
})
}

adminFlags, respCtx, err := listAdministratorRoleFlags(ctx, o.client, token, page)
if err != nil {
// We don't have permissions to fetch role assignments, so return an empty list
if errors.Is(err, errMissingRolePermissions) {
return nil, "", nil, nil
}

return nil, "", nil, fmt.Errorf("okta-connectorv2: failed to list users: %w", err)
}

switch bag.ResourceTypeID() {
case resourceTypeGroup.Id:
pageGroupToken := "{}"
for pageGroupToken != "" {
groupToken := &pagination.Token{
Token: pageGroupToken,
}
bagGroups, pageGroups, err := parsePageToken(groupToken.Token, resource.Id)
if err != nil {
return nil, "", nil, fmt.Errorf("okta-connectorv2: failed to parse page token: %w", err)
}

qp := queryParams(groupToken.Size, pageGroups)
groups, respGroupCtx, err := listGroups(ctx, o.client, groupToken, qp)
if err != nil {
return nil, "", nil, fmt.Errorf("okta-connectorv2: failed to list groups: %w", err)
}

nextGroupPage, _, err := parseResp(respGroupCtx.OktaResponse)
if err != nil {
return nil, "", nil, fmt.Errorf("okta-connectorv2: failed to parse response: %w", err)
}

err = bagGroups.Next(nextGroupPage)
if err != nil {
return nil, "", nil, fmt.Errorf("okta-connectorv2: failed to fetch bag.Next: %w", err)
}

for _, group := range groups {
groupId := group.Id
roles, _, err := listGroupAssignedRoles(ctx, o.client, groupId, nil)
if err != nil {
return nil, "", nil, err
}

for _, role := range roles {
if role.Status == roleStatusInactive || role.AssignmentType != "GROUP" || role.Type == roleTypeCustom {
continue
}

// It's a custom role. We need to match the label to the display name
if role.Label == resource.GetDisplayName() {
rv = append(rv, roleGroupGrant(groupId, resource))
}
}
}

pageGroupToken, err = bagGroups.Marshal()
if err != nil {
return nil, "", nil, err
}
}
case resourceTypeUser.Id:
pageUserToken := "{}"
for pageUserToken != "" {
userToken := &pagination.Token{
Token: pageUserToken,
}
bagUsers, pageUsers, err := parsePageToken(userToken.Token, resource.Id)
if err != nil {
return nil, "", nil, fmt.Errorf("okta-connectorv2: failed to parse page token: %w", err)
}

qp := queryParams(userToken.Size, pageUsers)
users, respUserCtx, err := listUsers(ctx, o.client, userToken, qp)
if err != nil {
return nil, "", nil, fmt.Errorf("okta-connectorv2: failed to list users: %w", err)
}

nextUserPage, _, err := parseResp(respUserCtx.OktaResponse)
if err != nil {
return nil, "", nil, fmt.Errorf("okta-connectorv2: failed to parse response: %w", err)
}

err = bagUsers.Next(nextUserPage)
if err != nil {
return nil, "", nil, fmt.Errorf("okta-connectorv2: failed to fetch bag.Next: %w", err)
}

for _, user := range users {
userId := user.Id
roles, _, err := o.client.User.ListAssignedRolesForUser(ctx, userId, nil)
if err != nil {
return nil, "", nil, err
}

for _, role := range roles {
if role.Status == roleStatusInactive || role.AssignmentType != "USER" || role.Type != roleTypeCustom {
continue
}

// It's a custom role. We need to match the label to the display name
if role.Label == resource.GetDisplayName() {
rv = append(rv, roleGrant(userId, resource))
}
}
}

pageUserToken, err = bagUsers.Marshal()
if err != nil {
return nil, "", nil, err
}
}
default:
return nil, "", nil, fmt.Errorf("okta-connector: invalid grant resource type: %s", bag.ResourceTypeID())
}

nextPage, annos, err := parseAdminListResp(respCtx.OktaResponse)
if err != nil {
return nil, "", nil, fmt.Errorf("okta-connectorv2: failed to parse response: %w", err)
Expand Down

0 comments on commit 2636db0

Please sign in to comment.