diff --git a/EasyPIM/EasyPIM.psd1 b/EasyPIM/EasyPIM.psd1 index edf4792..5411dc5 100644 --- a/EasyPIM/EasyPIM.psd1 +++ b/EasyPIM/EasyPIM.psd1 @@ -94,7 +94,13 @@ FunctionsToExport = @( 'New-PIMGroupEligibleAssignment', 'Remove-PIMGroupActiveAssignment', 'Remove-PIMGroupEligibleAssignment', - 'Show-PIMReport' + 'Show-PIMReport', + 'Get-PIMAzureResourcePendingApproval', + 'Approve-PIMAzureResourcePendingApproval', + 'Deny-PIMAzureResourcePendingApproval', + 'Get-PIMEntraRolePendingApproval', + 'Approve-PIMEntraRolePendingApproval', + 'Deny-PIMEntraRolePendingApproval' ) # 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/Approve-PIMAzureResourcePendingApproval.ps1 b/EasyPIM/functions/Approve-PIMAzureResourcePendingApproval.ps1 new file mode 100644 index 0000000..13d137b --- /dev/null +++ b/EasyPIM/functions/Approve-PIMAzureResourcePendingApproval.ps1 @@ -0,0 +1,74 @@ +<# +.Synopsis +EASYPIM +Powershell module to manage PIM Azure Resource Role settings with simplicity in mind +Get-PIMEntraRolePolicy will return the policy rules (like require MFA on activation) of the selected rolename at the subscription level +Support querrying multi roles at once + +.Description + +Get-PIMAzureResourcePendingApproval will use the Microsoft Graph APIs to retrieve the requests pending your approval + +.PARAMETER approvalID +approval ID from get-PIMAzureResourcePendingApproval + +.PARAMETER justification +justification for the approval + +.Example + PS> approve-PIMAzureResourcePendingApproval -approvalID $approvalID -justification "I approve this request" + + Approve a pending request + +.Link + +.Notes + Homepage: https://github.com/kayasax/easyPIM + Author: MICHEL, Loic + Changelog: + Todo: + * allow other scopes +#> +function Approve-PIMAzureResourcePendingApproval { + [CmdletBinding()] + [OutputType([String])] + param ( + + [Parameter(Position = 0, Mandatory = $true,ValueFromPipeline = $true, + ValueFromPipelineByPropertyName = $true)] + [System.String] + # Tenant ID + $approvalID, + + [Parameter(Position = 1, Mandatory = $true)] + [System.String] + # justification + $justification + + ) + process{ + try { + $script:tenantID = $tenantID + + Write-Verbose "approve-PIMAzureResourcePendingApproval start with parameters: approvalid => $approvalID, justification => $justification" + + #Get the stages: + #Role Assignment Approval Steps - List - REST API (Azure Authorization) | Microsoft Learn + $stages=Invoke-AzRestMethod -Uri "https://management.azure.com/$approvalID/stages?api-version=2021-01-01-preview" -Method GET + + $stageid=($stages.Content | convertfrom-json).value.id + + #approve the request + #Role Assignment Approval Step - Patch - REST API (Azure Authorization) | Microsoft Learn + + $body='{"properties":{"justification":"'+$justification+'","reviewResult":"Approve"}}' + + Invoke-AzRestMethod -Uri "https://management.azure.com/$stageid/?api-version=2021-01-01-preview" -Payload $body -Method PUT + return "Success, request approved" + + } + catch { + MyCatch $_ + } +} +} \ No newline at end of file diff --git a/EasyPIM/functions/Approve-PIMEntraRolePendingApproval.ps1 b/EasyPIM/functions/Approve-PIMEntraRolePendingApproval.ps1 new file mode 100644 index 0000000..9e33122 --- /dev/null +++ b/EasyPIM/functions/Approve-PIMEntraRolePendingApproval.ps1 @@ -0,0 +1,74 @@ +<# +.Synopsis +EASYPIM +Powershell module to manage PIM Azure Resource Role settings with simplicity in mind +Get-PIMEntraRolePolicy will return the policy rules (like require MFA on activation) of the selected rolename at the subscription level +Support querrying multi roles at once + +.Description + +Approve-PIMEntraRolePendingApprovall will use the Microsoft Graph APIs to retrieve the requests pending your approval + +.PARAMETER approvalID +approval ID from get-PIMAzureResourcePendingApproval + +.PARAMETER justification +justification for the approval + +.Example + PS> approve-PIMAzureResourcePendingApproval -approvalID $approvalID -justification "I approve this request" + + Approve a pending request + +.Link + +.Notes + Homepage: https://github.com/kayasax/easyPIM + Author: MICHEL, Loic + Changelog: + Todo: + * allow other scopes +#> +function Approve-PIMEntraRolePendingApproval { + [CmdletBinding()] + [OutputType([String])] + param ( + + [Parameter(Position = 0, Mandatory = $true, ValueFromPipeline = $true, + ValueFromPipelineByPropertyName = $true)] + [System.String] + # Approval ID + $approvalID, + + [Parameter(Position = 1, Mandatory = $true)] + [System.String] + # justification + $justification + + ) + process { + try { + #$script:tenantID = $tenantID + + Write-Verbose "approve-PIMEntraRolePendingApproval start with parameters: approvalid => $approvalID, justification => $justification" + + #Get the stages: + #Role Assignment Approval Steps - List - REST API (Azure Authorization) | Microsoft Learn + $stages = Invoke-graph -endpoint "roleManagement/directory/roleAssignmentApprovals/$approvalID/" -Method GET -version "beta" + + $stageid = $stages.id + + #approve the request + #Role Assignment Approval Step - Patch - REST API (Azure Authorization) | Microsoft Learn + + $body = '{"justification":"' + $justification + '","reviewResult":"Approve"}' + + Invoke-graph -endpoint "roleManagement/directory/roleAssignmentApprovals/$approvalID/steps/$stageID" -body $body -version "beta" -Method PATCH + return "Success, request approved" + + } + catch { + MyCatch $_ + } + } +} \ No newline at end of file diff --git a/EasyPIM/functions/Deny-PIMAzureResourcePendingApproval.ps1 b/EasyPIM/functions/Deny-PIMAzureResourcePendingApproval.ps1 new file mode 100644 index 0000000..86ac9f1 --- /dev/null +++ b/EasyPIM/functions/Deny-PIMAzureResourcePendingApproval.ps1 @@ -0,0 +1,73 @@ +<# +.Synopsis +EASYPIM +Powershell module to manage PIM Azure Resource Role settings with simplicity in mind +Get-PIMEntraRolePolicy will return the policy rules (like require MFA on activation) of the selected rolename at the subscription level +Support querrying multi roles at once + +.Description + +Deny-PIMAzureResourcePendingApproval will deny request + +.PARAMETER approvalID +approval ID from get-PIMAzureResourcePendingApproval + +.PARAMETER justification +justification for the deny + +.Example + PS> Deny-PIMAzureResourcePendingApproval -approvalID $approvalID -justification "You don't need this role" + + Deny a pending request + +.Link + +.Notes + Homepage: https://github.com/kayasax/easyPIM + Author: MICHEL, Loic + Changelog: + Todo: + * allow other scopes +#> +function Deny-PIMAzureResourcePendingApproval { + [CmdletBinding()] + [OutputType([String])] + param ( + [Parameter(Position = 0, Mandatory = $true, ValueFromPipeline = $true, + ValueFromPipelineByPropertyName = $true)] + [System.String] + # Tenant ID + $approvalID, + + [Parameter(Position = 1, Mandatory = $true)] + [System.String] + # justification + $justification + + ) + process{ + try { + $script:tenantID = $tenantID + + Write-Verbose "approve-PIMAzureResourcePendingApproval start with parameters: approvalid => $approvalID, justification => $justification" + + #Get the stages: + #Role Assignment Approval Steps - List - REST API (Azure Authorization) | Microsoft Learn + $stages = Invoke-AzRestMethod -Uri "https://management.azure.com/$approvalID/stages?api-version=2021-01-01-preview" -Method GET + + $stageid = ($stages.Content | convertfrom-json).value.id + + #approve the request + #Role Assignment Approval Step - Patch - REST API (Azure Authorization) | Microsoft Learn + + $body = '{"properties":{"justification":"' + $justification + '","reviewResult":"Deny"}}' + + Invoke-AzRestMethod -Uri "https://management.azure.com/$stageid/?api-version=2021-01-01-preview" -Payload $body -Method PUT + return "Success, request denied" + + } + catch { + MyCatch $_ + } + +}} \ No newline at end of file diff --git a/EasyPIM/functions/Deny-PIMEntraRolePendingApproval.ps1 b/EasyPIM/functions/Deny-PIMEntraRolePendingApproval.ps1 new file mode 100644 index 0000000..eec90c5 --- /dev/null +++ b/EasyPIM/functions/Deny-PIMEntraRolePendingApproval.ps1 @@ -0,0 +1,74 @@ +<# +.Synopsis +EASYPIM +Powershell module to manage PIM Azure Resource Role settings with simplicity in mind +Get-PIMEntraRolePolicy will return the policy rules (like require MFA on activation) of the selected rolename at the subscription level +Support querrying multi roles at once + +.Description + +Deny-PIMEntraRolePendingApprovall will use the Microsoft Graph APIs to retrieve the requests pending your approval + +.PARAMETER approvalID +approval ID from get-PIMAzureResourcePendingApproval + +.PARAMETER justification +justification for the approval + +.Example + PS> Deny-PIMAzureResourcePendingApproval -approvalID $approvalID -justification "I Deny this request" + + Deny a pending request + +.Link + +.Notes + Homepage: https://github.com/kayasax/easyPIM + Author: MICHEL, Loic + Changelog: + Todo: + * allow other scopes +#> +function Deny-PIMEntraRolePendingApproval { + [CmdletBinding()] + [OutputType([String])] + param ( + + [Parameter(Position = 0, Mandatory = $true,ValueFromPipeline = $true, + ValueFromPipelineByPropertyName = $true)] + [System.String] + # Approval ID + $approvalID, + + [Parameter(Position = 1, Mandatory = $true)] + [System.String] + # justification + $justification + + ) + process{ + try { + #$script:tenantID = $tenantID + + Write-Verbose "Deny-PIMEntraRolePendingApproval start with parameters: approvalid => $approvalID, justification => $justification" + + #Get the stages: + #Role Assignment Approval Steps - List - REST API (Azure Authorization) | Microsoft Learn + $stages=Invoke-graph -endpoint "roleManagement/directory/roleAssignmentApprovals/$approvalID/" -Method GET -version "beta" + + $stageid=$stages.id + + #Deny the request + #Role Assignment Approval Step - Patch - REST API (Azure Authorization) | Microsoft Learn + + $body='{"justification":"'+$justification+'","reviewResult":"Deny"}' + + Invoke-graph -endpoint "roleManagement/directory/roleAssignmentApprovals/$approvalID/steps/$stageID" -body $body -version "beta" -Method PATCH + return "Success, request Denyd" + + } + catch { + MyCatch $_ + } + +}} \ No newline at end of file diff --git a/EasyPIM/functions/Get-PIMAzureResourcePendingApproval.ps1 b/EasyPIM/functions/Get-PIMAzureResourcePendingApproval.ps1 new file mode 100644 index 0000000..ba2187b --- /dev/null +++ b/EasyPIM/functions/Get-PIMAzureResourcePendingApproval.ps1 @@ -0,0 +1,80 @@ +<# +.Synopsis +EASYPIM +Powershell module to manage PIM Azure Resource Role settings with simplicity in mind +Get-PIMEntraRolePolicy will return the policy rules (like require MFA on activation) of the selected rolename at the subscription level +Support querrying multi roles at once + +.Description + +Get-PIMAzureResourcePendingApproval will use the Microsoft Graph APIs to retrieve the requests pending your approval + +.PARAMETER tenantID +Tenant ID + +.Example + PS> Get-PIMAzureResourcePendingApproval -tenantID $tenantID + + show pending request you can approve + +.Link + +.Notes + Homepage: https://github.com/kayasax/easyPIM + Author: MICHEL, Loic + Changelog: + Todo: + * allow other scopes +#> +function Get-PIMAzureResourcePendingApproval { + [CmdletBinding()] + [OutputType([PSCustomObject])] + param ( + + [Parameter(Position = 0, Mandatory = $true)] + [System.String] + # Tenant ID + $tenantID + + ) + try { + $script:tenantID = $tenantID + + Write-Verbose "Get-PIMAzureResourcePendingApproval start with parameters: tenantID => $tenantID" + + $out = @() + $response = invoke-AzRestMethod -Uri "https://management.azure.com/providers/Microsoft.Authorization/roleAssignmentScheduleRequests?api-version=2020-10-01&`$filter=asApprover()" + $pendingApproval = $response.Content | convertfrom-json + if ($null -ne $pendingApproval.value.properties) { + $pendingApproval.value.properties | ForEach-Object { + $request = @{ + "principalType" = $_.principalType; + "principalId" = $_.expandedProperties.Principal.id; + "principalDisplayname" = $_.expandedProperties.Principal.displayName; + "roleId" = $_.expandedProperties.RoleDefinition.id; + "roleDisplayname" = $_.expandedProperties.RoleDefinition.displayName; + "status" = $_.status; + "startDateTime" = $_.scheduleInfo.startDateTime; + "ticketInfo" = $_.ticketInfo; + "justification" = $_.justification; + "scope" = $_.Scope; + "approvalId" = $_.approvalId; + "requestType" = $_.requestType; + "createdOn" = $_.createdOn; + } + $o = New-Object -TypeName PSObject -Property $request + $out += $o + } + } + if ($out.length -eq 0) { + #write-host "No pending approval" + return $null + } + return $out + + } + catch { + MyCatch $_ + } + +} \ No newline at end of file diff --git a/EasyPIM/functions/Get-PIMEntraRolePendingApproval.ps1 b/EasyPIM/functions/Get-PIMEntraRolePendingApproval.ps1 new file mode 100644 index 0000000..a32bcd2 --- /dev/null +++ b/EasyPIM/functions/Get-PIMEntraRolePendingApproval.ps1 @@ -0,0 +1,85 @@ +<# +.Synopsis +EASYPIM +Powershell module to manage PIM Azure Resource Role settings with simplicity in mind +Get-PIMEntraRolePolicy will return the policy rules (like require MFA on activation) of the selected rolename at the subscription level +Support querrying multi roles at once + +.Description + +Get-PIMEntraRolePendingApproval will use the Microsoft Graph APIs to retrieve the requests pending your approval + +.PARAMETER tenantID +Tenant ID + +.Example + PS> Get-PIMEntraRolePendingApproval -tenantID $tenantID + + show pending request you can approve + +.Link + +.Notes + Homepage: https://github.com/kayasax/easyPIM + Author: MICHEL, Loic + Changelog: + Todo: + * allow other scopes +#> +function Get-PIMEntraRolePendingApproval{ + [CmdletBinding()] + [OutputType([PSCustomObject])] + param ( + + [Parameter(Position = 0, Mandatory = $true)] + [System.String] + # Tenant ID + $tenantID + + ) + try { + $script:tenantID = $tenantID + + Write-Verbose "Get-PIMAzureResourcePendingApproval start with parameters: tenantID => $tenantID" + + $endpoint="/roleManagement/directory/roleAssignmentScheduleRequests/filterByCurrentUser(on='approver')?$filter=status eq 'PendingApproval'" + $response = Invoke-Graph -Endpoint $endpoint -Method "GET" + + $out = @() + + $pendingApproval = $response.value + + if ($null -ne $pendingApproval) { + $pendingApproval | ForEach-Object { + $role=invoke-mgGraphRequest $("https://graph.microsoft.com/v1.0/directoryRoles(roletemplateid ='"+$_.roledefinitionid+"')") -Method get + $principalDisplayName = invoke-mgGraphRequest $("https://graph.microsoft.com/v1.0/directoryobjects/"+$_.Principalid+"/") -Method get + $request = @{ + "principalId" = $_.Principalid; + "principalDisplayname" = $principalDisplayName.displayName; + "roleId" = $_.RoleDefinitionid; + + "roleDisplayname" = $role.displayname; + "status" = $_.status; + "startDateTime" = $_.CreatedDateTime; + "ticketInfo" = $_.ticketInfo; + "justification" = $_.justification; + "scope" = "/"; + "approvalId" = $_.approvalId; + "createdOn" = $_.createdDateTime; + } + $o = New-Object -TypeName PSObject -Property $request + $out += $o + } + } + if ($out.length -eq 0) { + #write-host "No pending approval" + return $null + } + return $out + + } + catch { + MyCatch $_ + } + +} \ No newline at end of file diff --git a/EasyPIM/internal/functions/Invoke-graph.ps1 b/EasyPIM/internal/functions/Invoke-graph.ps1 index 7c1f137..e45ceb5 100644 --- a/EasyPIM/internal/functions/Invoke-graph.ps1 +++ b/EasyPIM/internal/functions/Invoke-graph.ps1 @@ -44,6 +44,7 @@ function invoke-graph { Write-Verbose ">> Connecting to Azure with tenantID $script:tenantID" $scopes = @( "RoleManagementPolicy.ReadWrite.Directory", + "PrivilegedAccess.ReadWrite.AzureAD", "RoleManagement.ReadWrite.Directory", "RoleManagementPolicy.ReadWrite.AzureADGroup", "PrivilegedEligibilitySchedule.ReadWrite.AzureADGroup", @@ -52,7 +53,7 @@ function invoke-graph { "AuditLog.Read.All", "Directory.Read.All") - Connect-MgGraph -Tenant $script:tenantID -Scopes $scopes + Connect-MgGraph -Tenant $script:tenantID -Scopes $scopes -NoWelcome } if ( $body -ne "") {