diff --git a/pkg/connector/group.go b/pkg/connector/group.go index d736b85e..abbdd1d5 100644 --- a/pkg/connector/group.go +++ b/pkg/connector/group.go @@ -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) { diff --git a/pkg/connector/role.go b/pkg/connector/role.go index 1bd6d54d..ef619e1c 100644 --- a/pkg/connector/role.go +++ b/pkg/connector/role.go @@ -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)