-
Notifications
You must be signed in to change notification settings - Fork 28
Enganga/update entra invited user sponsors from invited by #1354
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
emmanuel-karanja
wants to merge
25
commits into
main
Choose a base branch
from
enganga/Update-EntraInvitedUserSponsorsFromInvitedBy
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 18 commits
Commits
Show all changes
25 commits
Select commit
Hold shift + click to select a range
a141b1b
initial commit
emmanuel-karanja 9c6b79b
initial commit
emmanuel-karanja 6edf624
added beta cmdlet port
emmanuel-karanja d758558
Tests refactors, docs creation and cmdlet update to remove prerequisites
emmanuel-karanja d1d5563
Fixes
emmanuel-karanja 3b242b9
Changed to use -Select
emmanuel-karanja 1be86fb
Implement Get-ObjectPropertyValue function
emmanuel-karanja 954cf72
Updated to -Select for Beta
emmanuel-karanja e49b3e3
Only better version is supported
emmanuel-karanja a6a6587
Updates
emmanuel-karanja b8db6c5
Inlined functioned
emmanuel-karanja 54b8374
Beta updates
emmanuel-karanja 61194f2
added examples to ocs
emmanuel-karanja d043f9e
added examples to ocs
emmanuel-karanja 564adae
Removed Get-ObjectPropertyValue since we are only checking for the 'i…
emmanuel-karanja 79e3157
Delete module/Entra/Microsoft.Entra/Reports/Get-EntraCrossTenantAcces…
emmanuel-karanja c624de3
Delete module/EntraBeta/Microsoft.Entra.Beta/Users/Test-EntraBetaComm…
emmanuel-karanja 33627e4
Merge branch 'main' into enganga/Update-EntraInvitedUserSponsorsFromI…
emmanuel-karanja 9c667ee
Merge branch 'main' into enganga/Update-EntraInvitedUserSponsorsFromI…
SteveMutungi254 2fff099
compute once
emmanuel-karanja 7ae84d4
Migrate to use Graph API
emmanuel-karanja dd7c32f
update to use Graph API and update to tests
emmanuel-karanja d757cd7
cleanup tests
emmanuel-karanja 2220b91
Merge branch 'main' into enganga/Update-EntraInvitedUserSponsorsFromI…
emmanuel-karanja 330a446
Merge branch 'main' of https://github.com/microsoftgraph/entra-powers…
emmanuel-karanja File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
100 changes: 100 additions & 0 deletions
100
...EntraBeta/Microsoft.Entra.Beta/Users/Update-EntraBetaInvitedUserSponsorsFromInvitedBy.ps1
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
# ------------------------------------------------------------------------------ | ||
# Copyright (c) Microsoft Corporation. All Rights Reserved. | ||
# Licensed under the MIT License. See License in the project root for license information. | ||
# ------------------------------------------------------------------------------ | ||
function Update-EntraBetaInvitedUserSponsorsFromInvitedBy { | ||
[CmdletBinding(SupportsShouldProcess, | ||
ConfirmImpact = 'High', | ||
DefaultParameterSetName = 'AllInvitedGuests')] | ||
param ( | ||
|
||
# UserId of Guest User | ||
[Parameter(ParameterSetName = 'ByUsers', HelpMessage = "The Unique ID of the User (User ID).")] | ||
[String[]] | ||
$UserId, | ||
|
||
# Enumerate and Update All Guest Users. | ||
[Parameter(ParameterSetName = 'AllInvitedGuests', HelpMessage = "A Flag indicating whether to include all invited guests.")] | ||
[switch] | ||
$All | ||
) | ||
|
||
begin { | ||
$guestFilter = "(CreationType eq 'Invitation')" | ||
} | ||
|
||
process { | ||
|
||
$customHeaders = New-EntraBetaCustomHeaders -Command $MyInvocation.MyCommand | ||
|
||
if ((-not $UserId -or $UserId.Count -eq 0) -and -not $All) { | ||
throw "Please specify either -UserId or -All" | ||
} | ||
$invitedUsers=@() | ||
if ($All) { | ||
#TODO: Change to Get-EntraBetaUser when -ExpandProperty is implemented | ||
$invitedUsers = Get-MgBetaUser -Filter $guestFilter -All -ExpandProperty Sponsors | ||
} | ||
else { | ||
foreach ($user in $UserId) { | ||
#TODO: Change to Get-EntraBetaUser when -ExpandProperty is implemented | ||
$invitedUsers += Get-MgBetaUser -UserId $user -ExpandProperty Sponsors | ||
} | ||
} | ||
|
||
if ($null -eq $invitedUsers) { | ||
Write-Error "No guest users to process" | ||
} | ||
else { | ||
foreach ($invitedUser in $invitedUsers) { | ||
$invitedBy = $null | ||
$environment=(Get-EntraContext).Environment | ||
$baseUri=(Get-EntraEnvironment -Name $environment).GraphEndpoint | ||
$splatArgumentsGetInvitedBy = @{ | ||
Method = 'Get' | ||
Uri = $baseUri +"/beta/users/" + $invitedUser.id + "/invitedBy" | ||
} | ||
|
||
$invitedBy = Invoke-GraphRequest @splatArgumentsGetInvitedBy -Headers $customHeaders | ||
|
||
Write-Verbose ($invitedBy | ConvertTo-Json -Depth 10) | ||
|
||
if ($null -ne $invitedBy -and $null -ne $invitedBy.value -and $null -ne $invitedBy.value.id) { | ||
Write-Verbose ("InvitedBy for Guest User {0}: {1}" -f $invitedUser.displayName, $invitedBy.value.id) | ||
|
||
if (($null -like $invitedUser.sponsors) -or ($invitedUser.sponsors.id -notcontains $invitedBy.value.id)) { | ||
Write-Verbose "Sponsors does not contain the user who invited them!" | ||
|
||
if ($PSCmdlet.ShouldProcess(("$($invitedUser.displayName) ($($invitedUser.userPrincipalName) - $($invitedUser.id))"), "Update Sponsors")) { | ||
try { | ||
$sponsorUrl = ("https://graph.microsoft.com/beta/users/{0}" -f $invitedBy.value.id) | ||
$dirObj = @{"[email protected]" = @($sponsorUrl) } | ||
$sponsorsRequestBody = $dirObj | ConvertTo-Json | ||
|
||
Update-MgBetaUser -UserId $invitedUser.id -BodyParameter $sponsorsRequestBody -Header $customHeaders | ||
Write-Output "$($invitedUser.userPrincipalName) - Sponsor updated successfully for this user." | ||
} | ||
catch { | ||
Write-Output "$($invitedUser.userPrincipalName) - Failed updating sponsor for this user." | ||
Write-Error $_ | ||
} | ||
} | ||
} | ||
else { | ||
Write-Output "$($invitedUser.userPrincipalName) - Sponsor already exists for this user." | ||
} | ||
} | ||
else { | ||
Write-Output "$($invitedUser.userPrincipalName) - Invited user information not available for this user." | ||
} | ||
} | ||
} | ||
} | ||
|
||
end { | ||
Write-Verbose "Complete!" | ||
} | ||
} | ||
|
||
|
||
|
158 changes: 158 additions & 0 deletions
158
...entra-powershell-beta/Users/Update-EntraBetaInvitedUserSponsorsFromInvitedBy.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,158 @@ | ||
--- | ||
title: Update-EntraBetaInvitedUserSponsorsFromInvitedBy | ||
description: This article provides details on the Update-EntraBetaInvitedUserSponsorsFromInvitedBy command. | ||
|
||
ms.topic: reference | ||
ms.date: 02/11/2025 | ||
ms.author: eunicewaweru | ||
ms.reviewer: stevemutungi | ||
manager: CelesteDG | ||
author: msewaweru | ||
|
||
external help file: Microsoft.Entra.Beta.Users-Help.xml | ||
Module Name: Microsoft.Entra.Beta | ||
online version: https://learn.microsoft.com/powershell/module/Microsoft.Beta.Entra/Update-EntraBetaInvitedUserSponsorsFromInvitedBy | ||
|
||
schema: 2.0.0 | ||
--- | ||
|
||
# Update-EntraBetaInvitedUserSponsorsFromInvitedBy | ||
|
||
## Synopsis | ||
|
||
Update the Sponsors attribute to include the user who initially invited them to the tenant using the InvitedBy property. While new guests are sponsored automatically, the feature was only rolled out last year and did not backfill the sponsor info for previous guests that were invited. | ||
|
||
## Syntax | ||
|
||
```powershell | ||
Update-EntraBetaInvitedUserSponsorsFromInvitedBy | ||
[-UserId <String[]>] | ||
[-All] | ||
[<CommonParameters>] | ||
``` | ||
|
||
## Description | ||
|
||
The `Update-EntraBetaInvitedUserSponsorsFromInvitedBy` cmdlet updates the Sponsors attribute to include the user who initially invited them to the tenant using the InvitedBy property. This script can be used to backfill Sponsors attribute for existing users. | ||
|
||
The calling user must be assigned at least one of the following Microsoft Entra roles: | ||
|
||
- User Administrator | ||
- Privileged Authentication Administrator | ||
|
||
## Examples | ||
|
||
### Example 1: Enumerate all invited users in the Tenant and update Sponsors using InvitedBy value | ||
|
||
```powershell | ||
Connect-Entra -Scopes 'User.ReadWrite.All' | ||
Update-EntraBetaInvitedUserSponsorsFromInvitedBy | ||
``` | ||
|
||
```Output | ||
Confirm | ||
Are you sure you want to perform this action? | ||
Performing the operation "Update Sponsors" on target "externaluser_externaldomain.com" | ||
(externaluser_externaldomain.com#EXT#@contoso.com - 00aa00aa-bb11-cc22-dd33-44ee44ee44ee)". | ||
[Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "Y"): A | ||
|
||
externaluser1_externaldomain.com#EXT#@contoso.com - Sponsor updated successfully for this user. | ||
externaluser1_externaldomain#EXT#@contoso - Sponsor updated successfully for this user. | ||
externaluser1_externaldomain#EXT#@contoso - Sponsor updated successfully for this user. | ||
``` | ||
|
||
Enumerate all invited users in the Tenant and update Sponsors using InvitedBy value | ||
|
||
### Example 2: Update sponsors for a specific guest user | ||
|
||
```powershell | ||
Connect-Entra -Scopes 'User.ReadWrite.All' | ||
Update-EntraBetaInvitedUserSponsorsFromInvitedBy -UserId 'externaluser1_externaldomain.com','externaluser1_externaldomain.com' | ||
``` | ||
|
||
```Output | ||
Confirm | ||
Are you sure you want to perform this action? | ||
Performing the operation "Update Sponsors" on target "externaluser_externaldomain.com" | ||
(externaluser_externaldomain.com#EXT#@contoso.com - 00aa00aa-bb11-cc22-dd33-44ee44ee44ee)". | ||
[Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "Y"): A | ||
|
||
externaluser1_externaldomain.com#EXT#@contoso.com - Sponsor updated successfully for this user. | ||
``` | ||
|
||
This command updates the sponsors for the specified guest user in Microsoft Entra ID. | ||
|
||
### Example 3: Update sponsors for all invited guest users | ||
|
||
```powershell | ||
Connect-Entra -Scopes 'User.ReadWrite.All' | ||
Update-EntraBetaInvitedUserSponsorsFromInvitedBy -All | ||
``` | ||
|
||
```Output | ||
Confirm | ||
Are you sure you want to perform this action? | ||
Performing the operation "Update Sponsors" on target "externaluser_externaldomain.com" | ||
(externaluser_externaldomain.com#EXT#@contoso.com - 00aa00aa-bb11-cc22-dd33-44ee44ee44ee)". | ||
[Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "Y"): A | ||
|
||
externaluser1_externaldomain.com#EXT#@contoso.com - Sponsor updated successfully for this user. | ||
externaluser1_externaldomain#EXT#@contoso - Sponsor updated successfully for this user. | ||
externaluser1_externaldomain#EXT#@contoso - Sponsor updated successfully for this user. | ||
``` | ||
|
||
This command updates the sponsors for all invited guest users in Microsoft Entra ID. | ||
|
||
## Parameters | ||
|
||
### -UserId | ||
|
||
Specifies the ID of one or more guest users (as UPNs or User IDs) in Microsoft Entra ID. | ||
|
||
```yaml | ||
Type: System.String[] | ||
Parameter Sets: ByUsers | ||
Aliases: None | ||
|
||
Required: False | ||
Position: Named | ||
Default value: None | ||
Accept pipeline input: False | ||
Accept wildcard characters: False | ||
``` | ||
|
||
### -All | ||
|
||
Specifies that the cmdlet should update sponsors for all invited guest users. | ||
|
||
```yaml | ||
Type: SwitchParameter | ||
Parameter Sets: AllInvitedGuests | ||
Aliases: None | ||
|
||
Required: False | ||
Position: Named | ||
Default value: False | ||
Accept pipeline input: False | ||
Accept wildcard characters: False | ||
``` | ||
|
||
### CommonParameters | ||
|
||
This cmdlet supports the common parameters: `-Debug`, `-ErrorAction`, `-ErrorVariable`, `-InformationAction`, `-InformationVariable`, `-OutVariable`, `-OutBuffer`, `-PipelineVariable`, `-Verbose`, `-WarningAction`, and `-WarningVariable`. For more information, see [about_CommonParameters](https://go.microsoft.com/fwlink/?LinkID=113216). | ||
|
||
## Inputs | ||
|
||
## Outputs | ||
|
||
## Notes | ||
|
||
- If neither `-UserId` nor `-All` is specified, the cmdlet returns an error. | ||
- The cmdlet retrieves invited users and their inviter information before updating the sponsors. | ||
- The `-All` switch processes all guest users in the tenant. | ||
|
||
## Related Links | ||
|
||
[Get-EntraUser](Get-EntraBetaUser.md) | ||
|
||
[Set-EntraUser](Set-EntraBetaUser.md) |
71 changes: 71 additions & 0 deletions
71
test/EntraBeta/Users/Update-EntraBetaInvitedUserSponsorsFromInvitedBy.Tests.ps1
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
# ------------------------------------------------------------------------------ | ||
# Copyright (c) Microsoft Corporation. All Rights Reserved. | ||
# Licensed under the MIT License. See License in the project root for license information. | ||
# ------------------------------------------------------------------------------ | ||
|
||
BeforeAll { | ||
if ((Get-Module -Name Microsoft.Entra.Beta.Users) -eq $null) { | ||
Import-Module Microsoft.Entra.Beta.Users | ||
} | ||
Import-Module (Join-Path $PSScriptRoot "..\..\Common-Functions.ps1") -Force | ||
|
||
Mock -CommandName Get-EntraContext -MockWith { return @{ Environment = "Public" } } -ModuleName Microsoft.Entra.Beta.Users | ||
|
||
Mock -CommandName Get-EntraEnvironment -MockWith { return @{ GraphEndpoint = "https://graph.microsoft.com" } } -ModuleName Microsoft.Entra.Beta.Users | ||
|
||
Mock -CommandName Get-MgBetaUser -MockWith { | ||
[PSCustomObject]@{ | ||
Id = "123" | ||
DisplayName = "Test Guest" | ||
UserPrincipalName = "[email protected]" | ||
Sponsors = $null | ||
} | ||
} -ModuleName Microsoft.Entra.Beta.Users | ||
|
||
Mock -CommandName Invoke-GraphRequest -MockWith { | ||
return @{ value = @{ id = "456" } } | ||
} -ModuleName Microsoft.Entra.Beta.Users | ||
|
||
Mock -CommandName Set-EntraBetaUser -MockWith { $true } -ModuleName Microsoft.Entra.Beta.Users | ||
|
||
Mock -CommandName Update-MgBetaUser -MockWith {"Sponsor updated successfully for user 123"} -ModuleName Microsoft.Entra.Beta.Users | ||
} | ||
|
||
Describe "Update-EntraBetaInvitedUserSponsorsFromInvitedBy" { | ||
Context "Valid Inputs" { | ||
It "Should update sponsor for a single user" { | ||
Update-EntraBetaInvitedUserSponsorsFromInvitedBy -UserId "123" -Confirm:$false | Should -Match "Sponsor updated successfully" | ||
} | ||
|
||
It "Should process all invited users when -All is specified" { | ||
Update-EntraBetaInvitedUserSponsorsFromInvitedBy -All -Confirm:$false | Should -Match "Sponsor updated successfully" | ||
} | ||
} | ||
|
||
Context "Invalid Inputs" { | ||
It "Should throw an error when neither -UserId nor -All is provided" { | ||
{ Update-EntraBetaInvitedUserSponsorsFromInvitedBy -Confirm:$false} | Should -Throw "Please specify either -UserId or -All" | ||
} | ||
} | ||
|
||
Context "Edge Cases" { | ||
It "Should handle missing invitedBy information" { | ||
Mock -CommandName Invoke-GraphRequest -MockWith { @{ value = $null } } -ModuleName Microsoft.Entra.Beta.Users | ||
|
||
Update-EntraBetaInvitedUserSponsorsFromInvitedBy -UserId "123" -Confirm:$false | Should -Match "Invited user information not available" | ||
} | ||
} | ||
|
||
Context "User-Agent Header" { | ||
It "Should contain 'User-Agent' header" { | ||
$userAgentHeaderValue = "PowerShell/$psVersion EntraPowershell/$entraVersion Update-EntraBetaInvitedUserSponsorsFromInvitedBy" | ||
|
||
Update-EntraBetaInvitedUserSponsorsFromInvitedBy -UserId "123" -Confirm:$false | ||
|
||
Should -Invoke -CommandName Invoke-GraphRequest -ModuleName Microsoft.Entra.Beta.Users -Times 1 -ParameterFilter { | ||
$Headers.'User-Agent' | Should -Be $userAgentHeaderValue | ||
$true | ||
} | ||
} | ||
} | ||
} |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.