From d33c5545c1aad29e1eb6cf165510893b68b3281b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20MICHEL?= Date: Tue, 17 Dec 2024 13:27:19 +0100 Subject: [PATCH 1/3] V1.7.4 --- EasyPIM/EasyPIM.psd1 | 5 +- ...opy-PIMAzureResourceEligibleAssignment.ps1 | 103 ++++++++++++++++++ ...Get-PIMAzureResourceEligibleAssignment.ps1 | 25 ++++- 3 files changed, 129 insertions(+), 4 deletions(-) create mode 100644 EasyPIM/functions/Copy-PIMAzureResourceEligibleAssignment.ps1 diff --git a/EasyPIM/EasyPIM.psd1 b/EasyPIM/EasyPIM.psd1 index e25f0b9..ca02148 100644 --- a/EasyPIM/EasyPIM.psd1 +++ b/EasyPIM/EasyPIM.psd1 @@ -4,7 +4,7 @@ RootModule = 'EasyPIM.psm1' # Version number of this module. -ModuleVersion = '1.7.3' +ModuleVersion = '1.7.4' # Supported PSEditions # CompatiblePSEditions = @() @@ -103,7 +103,8 @@ FunctionsToExport = @( 'Deny-PIMEntraRolePendingApproval', 'Get-PIMGroupPendingApproval', 'Approve-PIMGroupPendingApproval', - 'Deny-PIMGroupPendingApproval' + 'Deny-PIMGroupPendingApproval', + 'Copy-PIMAzureResourceEligibleAssignment' ) # Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export. diff --git a/EasyPIM/functions/Copy-PIMAzureResourceEligibleAssignment.ps1 b/EasyPIM/functions/Copy-PIMAzureResourceEligibleAssignment.ps1 new file mode 100644 index 0000000..254dd7b --- /dev/null +++ b/EasyPIM/functions/Copy-PIMAzureResourceEligibleAssignment.ps1 @@ -0,0 +1,103 @@ +<# + .Synopsis + Copy eligible assignement from one user to another + .Description + https://learn.microsoft.com/en-us/entra/id-governance/privileged-identity-management/pim-resource-roles-assign-roles + .Parameter tenantID + EntraID tenant ID + .Parameter subscriptionID + subscription ID + .Parameter scope + use scope parameter if you want to work at other scope than a subscription + .PARAMETER from + userprincipalname or objectID of the source object + .Parameter to + userprincipalname or objectID of the destination object + + .Example + PS> Copy-PIMAzureResourceEligibleAssignment -tenantID $tid -subscriptionID -subscription $subscription -from user1@contoso.com -to user2@contoso.com + + Copy eligible assignement from user1 to user2 + + + .Link + https://learn.microsoft.com/en-us/entra/id-governance/privileged-identity-management/pim-resource-roles-assign-roles + .Notes + Author: Loïc MICHEL + Homepage: https://github.com/kayasax/EasyPIM +#> + +function Copy-PIMAzureResourceEligibleAssignment { + [CmdletBinding()] + param ( + [Parameter(Position = 0, Mandatory = $true)] + [String] + $tenantID, + [Parameter(Position = 1)] + [String] + $subscriptionID, + [Parameter()] + [String] + $scope, + [Parameter(Mandatory = $true)] + [String] + $from, + [Parameter(Mandatory = $true)] + [String] + $to + ) + + try { + + $script:tenantID = $tenantID + + if (!($PSBoundParameters.Keys.Contains('scope'))) { + $scope = "/subscriptions/$subscriptionID" + } + # issue #23: due to a bug with the API regarding the membertype, we will use RoleEligibilitySchedulesInstance instead of RoleEligibilitySchedule + # the downside is we will not get assignment with a future start date + if ($PSBoundParameters.Keys.Contains('includeFutureAssignments')) { + $restURI = "https://management.azure.com/$scope/providers/Microsoft.Authorization/roleEligibilitySchedules?api-version=2020-10-01" + } + else { + $restURI = "https://management.azure.com/$scope/providers/Microsoft.Authorization/roleEligibilityScheduleInstances?api-version=2020-10-01" + } + + #convert UPN to objectID + if ($from -match ".+@.*\..+") { + #if this is a upn we will use graph to get the objectID + try { + $resu = invoke-graph -endpoint "users/$from" -Method GET -version "beta" + $from = $resu.id + } + catch { + Write-Warning "User $from not found in the tenant" + return + } + + } + + if ($to -match ".+@.*\..+") { + #if this is a upn we will use graph to get the objectID + try { + $resu = invoke-graph -endpoint "users/$to" -Method GET -version "beta" + $to = $resu.id + } + catch { + Write-Warning "User $to not found in the tenant" + return + } + + } + + $assignments=get-PIMAzureResourceEligibleAssignment -tenantID $tenantID -scope $scope -assignee $from + $assignments | ForEach-Object { + Write-Verbose "Copying assignment from $from to $to at scope $($_.scopeId) with role $($_.rolename)" + New-PIMAzureResourceEligibleAssignment -tenantID $tenantID -subscriptionID $subscriptionID -scope $_.scopeId -rolename $_.rolename -principalID $to + } + + } + catch { + MyCatch $_ + } +} \ No newline at end of file diff --git a/EasyPIM/functions/Get-PIMAzureResourceEligibleAssignment.ps1 b/EasyPIM/functions/Get-PIMAzureResourceEligibleAssignment.ps1 index d30fc70..ec2cc0b 100644 --- a/EasyPIM/functions/Get-PIMAzureResourceEligibleAssignment.ps1 +++ b/EasyPIM/functions/Get-PIMAzureResourceEligibleAssignment.ps1 @@ -9,6 +9,8 @@ subscription ID .Parameter scope use scope parameter if you want to work at other scope than a subscription + .PARAMETER assignee + Filter assignment using userprincipalname or objectID .Parameter summary When enabled will return the most useful information only .Parameter atBellowScope @@ -39,6 +41,8 @@ function Get-PIMAzureResourceEligibleAssignment { [Parameter()] [String] $scope, + [String] + $assignee, [switch] # when enable we will use the roleEligibilitySchedules API which also list the future assignments $includeFutureAssignments, @@ -51,6 +55,9 @@ function Get-PIMAzureResourceEligibleAssignment { ) try { + + $script:tenantID = $tenantID + if (!($PSBoundParameters.Keys.Contains('scope'))) { $scope = "/subscriptions/$subscriptionID" } @@ -63,10 +70,24 @@ function Get-PIMAzureResourceEligibleAssignment { $restURI = "https://management.azure.com/$scope/providers/Microsoft.Authorization/roleEligibilityScheduleInstances?api-version=2020-10-01" } - + #issue #70 filter assignment of a specific user + if ($PSBoundParameters.Keys.Contains('assignee')) { + if($assignee -match ".+@.*\..+") { #if this is a upn we will use graph to get the objectID + try{ + $resu=invoke-graph -endpoint "users/$assignee" -Method GET -version "beta" + $assignee = $resu.id + } + catch { + Write-Warning "User $assignee not found in the tenant" + return + } + + } + + $restURI += "&`$filter=assignedto('"+$assignee+"')" + } - $script:tenantID = $tenantID $response = Invoke-ARM -restURI $restURI -method get From 345b66cbee3652d55dc2ade9435ba0e85be4bb2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20MICHEL?= Date: Tue, 17 Dec 2024 13:29:58 +0100 Subject: [PATCH 2/3] V1.7.4 --- EasyPIM/functions/Copy-PIMAzureResourceEligibleAssignment.ps1 | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/EasyPIM/functions/Copy-PIMAzureResourceEligibleAssignment.ps1 b/EasyPIM/functions/Copy-PIMAzureResourceEligibleAssignment.ps1 index 254dd7b..6693eb5 100644 --- a/EasyPIM/functions/Copy-PIMAzureResourceEligibleAssignment.ps1 +++ b/EasyPIM/functions/Copy-PIMAzureResourceEligibleAssignment.ps1 @@ -19,9 +19,7 @@ Copy eligible assignement from user1 to user2 - .Link - https://learn.microsoft.com/en-us/entra/id-governance/privileged-identity-management/pim-resource-roles-assign-roles .Notes Author: Loïc MICHEL Homepage: https://github.com/kayasax/EasyPIM @@ -95,7 +93,7 @@ function Copy-PIMAzureResourceEligibleAssignment { Write-Verbose "Copying assignment from $from to $to at scope $($_.scopeId) with role $($_.rolename)" New-PIMAzureResourceEligibleAssignment -tenantID $tenantID -subscriptionID $subscriptionID -scope $_.scopeId -rolename $_.rolename -principalID $to } - + } catch { MyCatch $_ From 0c23c2411f06e1af293483c22434fd51e74c335a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20MICHEL?= Date: Tue, 17 Dec 2024 13:36:25 +0100 Subject: [PATCH 3/3] remove unused code --- .../functions/Copy-PIMAzureResourceEligibleAssignment.ps1 | 8 -------- 1 file changed, 8 deletions(-) diff --git a/EasyPIM/functions/Copy-PIMAzureResourceEligibleAssignment.ps1 b/EasyPIM/functions/Copy-PIMAzureResourceEligibleAssignment.ps1 index 6693eb5..e47107e 100644 --- a/EasyPIM/functions/Copy-PIMAzureResourceEligibleAssignment.ps1 +++ b/EasyPIM/functions/Copy-PIMAzureResourceEligibleAssignment.ps1 @@ -52,14 +52,6 @@ function Copy-PIMAzureResourceEligibleAssignment { if (!($PSBoundParameters.Keys.Contains('scope'))) { $scope = "/subscriptions/$subscriptionID" } - # issue #23: due to a bug with the API regarding the membertype, we will use RoleEligibilitySchedulesInstance instead of RoleEligibilitySchedule - # the downside is we will not get assignment with a future start date - if ($PSBoundParameters.Keys.Contains('includeFutureAssignments')) { - $restURI = "https://management.azure.com/$scope/providers/Microsoft.Authorization/roleEligibilitySchedules?api-version=2020-10-01" - } - else { - $restURI = "https://management.azure.com/$scope/providers/Microsoft.Authorization/roleEligibilityScheduleInstances?api-version=2020-10-01" - } #convert UPN to objectID if ($from -match ".+@.*\..+") {