Remove MS365 external user from access review
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
This commit is contained in:
@@ -4,6 +4,10 @@ All notable changes to `probod` (the server, including the bundled `@probo/conso
|
|||||||
|
|
||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Microsoft 365 access review driver now fetches only internal members from Microsoft Graph (`$filter=userType eq 'Member'`), so guest (B2B) accounts are no longer pulled into access review
|
||||||
|
|
||||||
## [0.184.0] - 2026-05-07
|
## [0.184.0] - 2026-05-07
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"go.probo.inc/probo/pkg/coredata"
|
"go.probo.inc/probo/pkg/coredata"
|
||||||
@@ -35,10 +37,13 @@ type Microsoft365Driver struct {
|
|||||||
var _ Driver = (*Microsoft365Driver)(nil)
|
var _ Driver = (*Microsoft365Driver)(nil)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
microsoft365GraphBaseURL = "https://graph.microsoft.com/v1.0"
|
microsoft365GraphBaseURL = "https://graph.microsoft.com/v1.0"
|
||||||
microsoft365UsersSelect = "id,userPrincipalName,mail,displayName,givenName,surname,accountEnabled,jobTitle,department,createdDateTime"
|
microsoft365UsersSelect = "id,userPrincipalName,mail,displayName,givenName,surname,accountEnabled,jobTitle,department,createdDateTime"
|
||||||
microsoft365UsersPageSize = 999
|
// microsoft365UserTypeMemberFilter restricts /users to internal members
|
||||||
microsoft365MaxPaginationOK = maxPaginationPages
|
// so guest (B2B) accounts are not pulled into access review.
|
||||||
|
microsoft365UserTypeMemberFilter = "userType eq 'Member'"
|
||||||
|
microsoft365UsersPageSize = 999
|
||||||
|
microsoft365MaxPaginationOK = maxPaginationPages
|
||||||
)
|
)
|
||||||
|
|
||||||
// adminRoleDisplayNames lists the directory role display names that the
|
// adminRoleDisplayNames lists the directory role display names that the
|
||||||
@@ -213,29 +218,42 @@ func pickHighestRole(roles []string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *Microsoft365Driver) listUsers(ctx context.Context) ([]microsoft365User, error) {
|
func (d *Microsoft365Driver) listUsers(ctx context.Context) ([]microsoft365User, error) {
|
||||||
url := fmt.Sprintf(
|
pageURL, err := buildMicrosoft365UsersURL()
|
||||||
"%s/users?$select=%s&$top=%d",
|
if err != nil {
|
||||||
microsoft365GraphBaseURL,
|
return nil, err
|
||||||
microsoft365UsersSelect,
|
}
|
||||||
microsoft365UsersPageSize,
|
|
||||||
)
|
|
||||||
|
|
||||||
var all []microsoft365User
|
var all []microsoft365User
|
||||||
for range microsoft365MaxPaginationOK {
|
for range microsoft365MaxPaginationOK {
|
||||||
var page microsoft365UsersPage
|
var page microsoft365UsersPage
|
||||||
if err := d.fetchJSON(ctx, url, &page); err != nil {
|
if err := d.fetchJSON(ctx, pageURL, &page); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
all = append(all, page.Value...)
|
all = append(all, page.Value...)
|
||||||
if page.NextLink == "" {
|
if page.NextLink == "" {
|
||||||
return all, nil
|
return all, nil
|
||||||
}
|
}
|
||||||
url = page.NextLink
|
pageURL = page.NextLink
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, fmt.Errorf("cannot list all microsoft 365 users: %w", ErrPaginationLimitReached)
|
return nil, fmt.Errorf("cannot list all microsoft 365 users: %w", ErrPaginationLimitReached)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func buildMicrosoft365UsersURL() (string, error) {
|
||||||
|
u, err := url.Parse(microsoft365GraphBaseURL + "/users")
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("cannot parse graph users URL: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
q := u.Query()
|
||||||
|
q.Set("$select", microsoft365UsersSelect)
|
||||||
|
q.Set("$filter", microsoft365UserTypeMemberFilter)
|
||||||
|
q.Set("$top", strconv.Itoa(microsoft365UsersPageSize))
|
||||||
|
u.RawQuery = q.Encode()
|
||||||
|
|
||||||
|
return u.String(), nil
|
||||||
|
}
|
||||||
|
|
||||||
func (d *Microsoft365Driver) listDirectoryRoles(ctx context.Context) ([]microsoft365DirectoryRole, error) {
|
func (d *Microsoft365Driver) listDirectoryRoles(ctx context.Context) ([]microsoft365DirectoryRole, error) {
|
||||||
url := fmt.Sprintf("%s/directoryRoles", microsoft365GraphBaseURL)
|
url := fmt.Sprintf("%s/directoryRoles", microsoft365GraphBaseURL)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user