From b752f2bedee008dbf0642e4aa384bfa707532e87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20MICHEL?= Date: Thu, 7 Mar 2024 20:56:21 +0100 Subject: [PATCH 1/3] add get-PIMGroupPolicy --- EasyPIM/functions/Get-PIMGroupPolicy.ps1 | 88 +++++++++++ EasyPIM/internal/functions/Invoke-graph.ps1 | 2 +- .../internal/functions/get-GroupConfig.ps1 | 143 ++++++++++++++++++ 3 files changed, 232 insertions(+), 1 deletion(-) create mode 100644 EasyPIM/functions/Get-PIMGroupPolicy.ps1 create mode 100644 EasyPIM/internal/functions/get-GroupConfig.ps1 diff --git a/EasyPIM/functions/Get-PIMGroupPolicy.ps1 b/EasyPIM/functions/Get-PIMGroupPolicy.ps1 new file mode 100644 index 0000000..785cf71 --- /dev/null +++ b/EasyPIM/functions/Get-PIMGroupPolicy.ps1 @@ -0,0 +1,88 @@ +<# +.Synopsis +EASYPIM +Powershell module to manage PIM Azure Resource Role settings with simplicity in mind +Get-PIMGroupPolicy 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-PIMGroupPolicy will use the Microsoft Graph APIs to retrieve the PIM settings of the role $rolename + +.PARAMETER tenantID +Tenant ID + +.PARAMETER GroupID +Id of the group to check + +.PARAMETER GroupName +Search for the group by name + +.Example + PS> Get-PIMGroupPolicy -tenantID $tenantID -rolename "Global Administrator","Global Reader" + + show curent config for the roles global administrator and global reader + +.Link + https://learn.microsoft.com/en-us/azure/governance/resource-graph/first-query-rest-api + https://learn.microsoft.com/en-us/graph/identity-governance-pim-rules-overview + Duration ref https://en.wikipedia.org/wiki/ISO_8601#Durations +.Notes + Homepage: https://github.com/kayasax/easyPIM + Author: MICHEL, Loic + Changelog: + Todo: + * allow other scopes +#> +function Get-PIMGroupPolicy { + [CmdletBinding()] + [OutputType([PSCustomObject])] + param ( + + [Parameter(Position = 0, Mandatory = $true)] + [System.String] + # Tenant ID + $tenantID, + + [Parameter(Position = 1)] + [System.String[]] + # Array of role name + $groupID, + + [Parameter(Position = 2)] + [System.String] + # Array of role name + $groupName, + + [Parameter(Mandatory = $true)] + [System.String] + #owner or member + $type + + + ) + try { + $script:tenantID = $tenantID + + if ($PSBoundParameters.ContainsKey('groupname')) { + $endpoint="/groups?`$filter=startswith(displayName,'$($groupName)')" + $response=invoke-graph -Endpoint $endpoint + $groupID+=$response.value.id + + } + + + $out = @() + $groupID | ForEach-Object { + + #get curent config + $config = get-GroupConfig $_ $type + $out += $config + } + Write-Output $out -NoEnumerate + } + 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 11cb0a3..3500510 100644 --- a/EasyPIM/internal/functions/Invoke-graph.ps1 +++ b/EasyPIM/internal/functions/Invoke-graph.ps1 @@ -41,7 +41,7 @@ function invoke-graph { if ( $null -eq (get-mgcontext) -or ( (get-mgcontext).TenantId -ne $script:tenantID ) ) { Write-Verbose ">> Connecting to Azure with tenantID $script:tenantID" - Connect-MgGraph -Tenant $script:tenantID -Scopes RoleManagementPolicy.ReadWrite.Directory, RoleManagement.ReadWrite.Directory + Connect-MgGraph -Tenant $script:tenantID -Scopes RoleManagementPolicy.ReadWrite.Directory, RoleManagement.ReadWrite.Directory, RoleManagementPolicy.ReadWrite.AzureADGroup } <# # Authenticate and get the access token diff --git a/EasyPIM/internal/functions/get-GroupConfig.ps1 b/EasyPIM/internal/functions/get-GroupConfig.ps1 new file mode 100644 index 0000000..027eb27 --- /dev/null +++ b/EasyPIM/internal/functions/get-GroupConfig.ps1 @@ -0,0 +1,143 @@ +<#Get-PIMGroupPolicyGet-PIMGroupPolicy + .Synopsis + Get rules for the group $groupID + .Description + will convert the json rules to a PSCustomObject + .Parameter id + Id of the group to check + .Example + PS> get-config -scope $scop -rolename role1 + + Get the policy of the role role1 at the specified scope + + .Notes + Author: Loïc MICHEL + Homepage: https://github.com/kayasax/EasyPIM + #> +function get-Groupconfig ( $id, $type) { + + try { + + $endpoint = "policies/roleManagementPolicyAssignments?`$filter=scopeId eq '$id' and scopeType eq 'Group' and roleDefinitionId eq '$type'&`$expand=policy(`$expand=rules)" + $response = invoke-graph -Endpoint $endpoint + + $policyId=$response.value.id + #$response + # Get config values in a new object: + + # Maximum end user activation duration in Hour (PT24H) // Max 24H in portal but can be greater + $_activationDuration = $response.value.policy.rules | Where-Object { $_.id -eq "Expiration_EndUser_Assignment" } | Select-Object -ExpandProperty maximumduration + # End user enablement rule (MultiFactorAuthentication, Justification, Ticketing) + $_enablementRules = $response.value.policy.rules | Where-Object { $_.id -eq "Enablement_EndUser_Assignment" } | Select-Object -expand enabledRules + # approval required + $_approvalrequired = $($response.value.policy.rules | Where-Object { $_.id -eq "Approval_EndUser_Assignment" }).setting.isapprovalrequired + # approvers + $approvers = $($response.value.policy.rules | Where-Object { $_.id -eq "Approval_EndUser_Assignment" }).setting.approvalStages.primaryApprovers + if(( $approvers | Measure-Object | Select-Object -ExpandProperty Count) -gt 0){ + $approvers | ForEach-Object { + if($_."@odata.type" -eq "#microsoft.graph.groupMembers"){ + $_.userType = "group" + $_.id=$_.groupID + } + else{ #"@odata.type": "#microsoft.graph.singleUser", + $_.userType = "user" + $_.id=$_.userID + } + + $_approvers += '@{"id"="' + $_.id + '";"description"="' + $_.description + '";"userType"="' + $_.userType + '"},' + } + } + + # permanent assignmnent eligibility + $_eligibilityExpirationRequired = $response.value.policy.rules | Where-Object { $_.id -eq "Expiration_Admin_Eligibility" } | Select-Object -expand isExpirationRequired + if ($_eligibilityExpirationRequired -eq "true") { + $_permanantEligibility = "false" + } + else { + $_permanantEligibility = "true" + } + # maximum assignment eligibility duration + $_maxAssignmentDuration = $response.value.policy.rules | Where-Object { $_.id -eq "Expiration_Admin_Eligibility" } | Select-Object -expand maximumDuration + + # pemanent activation + $_activeExpirationRequired = $response.value.policy.rules | Where-Object { $_.id -eq "Expiration_Admin_Assignment" } | Select-Object -expand isExpirationRequired + if ($_activeExpirationRequired -eq "true") { + $_permanantActiveAssignment = "false" + } + else { + $_permanantActiveAssignment = "true" + } + # maximum activation duration + $_maxActiveAssignmentDuration = $response.value.policy.rules | Where-Object { $_.id -eq "Expiration_Admin_Assignment" } | Select-Object -expand maximumDuration + + ################# + # Notifications # + ################# + + # Notification Eligibility Alert (Send notifications when members are assigned as eligible to this role) + $_Notification_Admin_Admin_Eligibility = $response.value.policy.rules | Where-Object { $_.id -eq "Notification_Admin_Admin_Eligibility" } + # Notification Eligibility Assignee (Send notifications when members are assigned as eligible to this role: Notification to the assigned user (assignee)) + $_Notification_Eligibility_Assignee = $response.value.policy.rules | Where-Object { $_.id -eq "Notification_Requestor_Admin_Eligibility" } + # Notification Eligibility Approvers (Send notifications when members are assigned as eligible to this role: request to approve a role assignment renewal/extension) + $_Notification_Eligibility_Approvers = $response.value.policy.rules | Where-Object { $_.id -eq "Notification_Approver_Admin_Eligibility" } + + # Notification Active Assignment Alert (Send notifications when members are assigned as active to this role) + $_Notification_Active_Alert = $response.value.policy.rules | Where-Object { $_.id -eq "Notification_Admin_Admin_Assignment" } + # Notification Active Assignment Assignee (Send notifications when members are assigned as active to this role: Notification to the assigned user (assignee)) + $_Notification_Active_Assignee = $response.value.policy.rules | Where-Object { $_.id -eq "Notification_Requestor_Admin_Assignment" } + # Notification Active Assignment Approvers (Send notifications when members are assigned as active to this role: Request to approve a role assignment renewal/extension) + $_Notification_Active_Approvers = $response.value.policy.rules | Where-Object { $_.id -eq "Notification_Approver_Admin_Assignment" } + + # Notification Role Activation Alert (Send notifications when eligible members activate this role: Role activation alert) + $_Notification_Activation_Alert = $response.value.policy.rules | Where-Object { $_.id -eq "Notification_Admin_EndUser_Assignment" } + # Notification Role Activation Assignee (Send notifications when eligible members activate this role: Notification to activated user (requestor)) + $_Notification_Activation_Assignee = $response.value.policy.rules | Where-Object { $_.id -eq "Notification_Requestor_EndUser_Assignment" } + # Notification Role Activation Approvers (Send notifications when eligible members activate this role: Request to approve an activation) + $_Notification_Activation_Approver = $response.value.policy.rules | Where-Object { $_.id -eq "Notification_Approver_EndUser_Assignment" } + + + $config = [PSCustomObject]@{ + + PolicyID = $policyId + ActivationDuration = $_activationDuration + EnablementRules = $_enablementRules -join ',' + ApprovalRequired = $_approvalrequired + Approvers = $_approvers -join ',' + AllowPermanentEligibleAssignment = $_permanantEligibility + MaximumEligibleAssignmentDuration = $_maxAssignmentDuration + AllowPermanentActiveAssignment = $_permanantActiveAssignment + MaximumActiveAssignmentDuration = $_maxActiveAssignmentDuration + Notification_Eligibility_Alert_isDefaultRecipientEnabled = $($_Notification_Admin_Admin_Eligibility.isDefaultRecipientsEnabled) + Notification_Eligibility_Alert_NotificationLevel = $($_Notification_Admin_Admin_Eligibility.notificationLevel) + Notification_Eligibility_Alert_Recipients = $($_Notification_Admin_Admin_Eligibility.notificationRecipients) -join ',' + Notification_Eligibility_Assignee_isDefaultRecipientEnabled = $($_Notification_Eligibility_Assignee.isDefaultRecipientsEnabled) + Notification_Eligibility_Assignee_NotificationLevel = $($_Notification_Eligibility_Assignee.NotificationLevel) + Notification_Eligibility_Assignee_Recipients = $($_Notification_Eligibility_Assignee.notificationRecipients) -join ',' + Notification_Eligibility_Approvers_isDefaultRecipientEnabled = $($_Notification_Eligibility_Approvers.isDefaultRecipientsEnabled) + Notification_Eligibility_Approvers_NotificationLevel = $($_Notification_Eligibility_Approvers.NotificationLevel) + Notification_Eligibility_Approvers_Recipients = $($_Notification_Eligibility_Approvers.notificationRecipients -join ',') + Notification_Active_Alert_isDefaultRecipientEnabled = $($_Notification_Active_Alert.isDefaultRecipientsEnabled) + Notification_Active_Alert_NotificationLevel = $($_Notification_Active_Alert.notificationLevel) + Notification_Active_Alert_Recipients = $($_Notification_Active_Alert.notificationRecipients -join ',') + Notification_Active_Assignee_isDefaultRecipientEnabled = $($_Notification_Active_Assignee.isDefaultRecipientsEnabled) + Notification_Active_Assignee_NotificationLevel = $($_Notification_Active_Assignee.notificationLevel) + Notification_Active_Assignee_Recipients = $($_Notification_Active_Assignee.notificationRecipients -join ',') + Notification_Active_Approvers_isDefaultRecipientEnabled = $($_Notification_Active_Approvers.isDefaultRecipientsEnabled) + Notification_Active_Approvers_NotificationLevel = $($_Notification_Active_Approvers.notificationLevel) + Notification_Active_Approvers_Recipients = $($_Notification_Active_Approvers.notificationRecipients -join ',') + Notification_Activation_Alert_isDefaultRecipientEnabled = $($_Notification_Activation_Alert.isDefaultRecipientsEnabled) + Notification_Activation_Alert_NotificationLevel = $($_Notification_Activation_Alert.NotificationLevel) + Notification_Activation_Alert_Recipients = $($_Notification_Activation_Alert.NotificationRecipients -join ',') + Notification_Activation_Assignee_isDefaultRecipientEnabled = $($_Notification_Activation_Assignee.isDefaultRecipientsEnabled) + Notification_Activation_Assignee_NotificationLevel = $($_Notification_Activation_Assignee.NotificationLevel) + Notification_Activation_Assignee_Recipients = $($_Notification_Activation_Assignee.NotificationRecipients -join ',') + Notification_Activation_Approver_isDefaultRecipientEnabled = $($_Notification_Activation_Approver.isDefaultRecipientsEnabled) + Notification_Activation_Approver_NotificationLevel = $($_Notification_Activation_Approver.NotificationLevel) + Notification_Activation_Approver_Recipients = $($_Notification_Activation_Approver.NotificationRecipients -join ',') + } + return $config + } + catch { + Mycatch $_ + } +} \ No newline at end of file From 6909e30e2646abf3112d543747329c4572e11374 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20MICHEL?= Date: Fri, 8 Mar 2024 15:48:48 +0100 Subject: [PATCH 2/3] V1.5 --- EasyPIM/EasyPIM.psd1 | 12 +- .../Get-PIMGroupActiveAssignment.ps1 | 91 ++++++ .../Get-PIMGroupEligibleAssignment.ps1 | 91 ++++++ .../New-PIMEntraRoleActiveAssignment.ps1 | 4 +- .../New-PIMGroupActiveAssignment.ps1 | 146 ++++++++++ .../New-PIMGroupEligibleAssignment.ps1 | 148 ++++++++++ .../Remove-PIMGroupActiveAssignment.ps1 | 146 ++++++++++ .../Remove-PIMGroupEligibleAssignment.ps1 | 146 ++++++++++ EasyPIM/functions/Set-PIMGroupPolicy.ps1 | 264 ++++++++++++++++++ .../internal/functions/get-GroupConfig.ps1 | 4 +- 10 files changed, 1047 insertions(+), 5 deletions(-) create mode 100644 EasyPIM/functions/Get-PIMGroupActiveAssignment.ps1 create mode 100644 EasyPIM/functions/Get-PIMGroupEligibleAssignment.ps1 create mode 100644 EasyPIM/functions/New-PIMGroupActiveAssignment.ps1 create mode 100644 EasyPIM/functions/New-PIMGroupEligibleAssignment.ps1 create mode 100644 EasyPIM/functions/Remove-PIMGroupActiveAssignment.ps1 create mode 100644 EasyPIM/functions/Remove-PIMGroupEligibleAssignment.ps1 create mode 100644 EasyPIM/functions/Set-PIMGroupPolicy.ps1 diff --git a/EasyPIM/EasyPIM.psd1 b/EasyPIM/EasyPIM.psd1 index de3613a..91d40a0 100644 --- a/EasyPIM/EasyPIM.psd1 +++ b/EasyPIM/EasyPIM.psd1 @@ -4,7 +4,7 @@ RootModule = 'EasyPIM.psm1' # Version number of this module. -ModuleVersion = '1.4.0' +ModuleVersion = '1.5.0' # Supported PSEditions # CompatiblePSEditions = @() @@ -85,7 +85,15 @@ FunctionsToExport = @( "New-PIMEntraRoleActiveAssignment", "New-PIMEntraRoleEligibleAssignment", 'Remove-PIMEntraRoleActiveAssignment', - 'Remove-PIMEntraRoleEligibleAssignment' + 'Remove-PIMEntraRoleEligibleAssignment', + "Get-PIMGroupPolicy", + "Set-PIMGroupPolicy", + "Get-PIMGroupActiveAssignment", + "Get-PIMGroupEligibleAssignment", + 'New-PIMGroupActiveAssignment', + 'New-PIMGroupEligibleAssignment', + 'Remove-PIMGroupActiveAssignment', + 'Remove-PIMGroupEligibleAssignment' ) # 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/Get-PIMGroupActiveAssignment.ps1 b/EasyPIM/functions/Get-PIMGroupActiveAssignment.ps1 new file mode 100644 index 0000000..f67a7a5 --- /dev/null +++ b/EasyPIM/functions/Get-PIMGroupActiveAssignment.ps1 @@ -0,0 +1,91 @@ +<# + .Synopsis + List of PIM Entra Role active assignement + .Description + Active assignment does not require to activate their role. https://learn.microsoft.com/en-us/graph/api/rbacapplication-list-roleeligibilityscheduleinstances?view=graph-rest-1.0&tabs=http + .Parameter tenantID + EntraID tenant ID + .Parameter summary + When enabled will return the most useful information only + .PARAMETER rolename + Filter by rolename + .PARAMETER principalid + Filter by principalid + .PARAMETER principalName + Filter by principalName + + .Example + PS> Get-PIMEntraRoleActiveAssignment -tenantID $tid + + List active assignement + + + .Link + .Notes + Author: Loïc MICHEL + Homepage: https://github.com/kayasax/EasyPIM +#> + +function Get-PIMGroupActiveAssignment { + [CmdletBinding()] + param ( + [Parameter(Position = 0, Mandatory = $true)] + [String] + $tenantID, + # select the most usefull info only + [switch]$summary, + [string]$groupID, + [string]$rolename, + [string]$principalName + ) + + try { + $script:tenantID = $tenantID + + $endpoint = "identityGovernance/privilegedAccess/group/assignmentSchedules?`$filter=groupId eq '$groupID'&`$expand=principal + " + $response = invoke-graph -Endpoint $endpoint + $resu = @() + $response.value | ForEach-Object { + + $r = @{ + #"rolename" = $_.roledefinition.displayName + #"roleid" = $_.roledefinition.id + "principalname" = $_.principal.displayName + "principalid" = $_.principal.id + "principalEmail" = $_.principal.mail + "startDateTime" = $_.scheduleInfo.startDateTime + "endDateTime" = $_.scheduleInfo.expiration.endDateTime + #"directoryScopeId" = $_.directoryScopeId + "memberType" = $_.accessId + "assignmentType" = $_.memberType + #"activatedUsing"=$_.activatedUsing + "principaltype" = $_.principal."@odata.type" + "id" = $_.id + } + $resu += New-Object PSObject -Property $r + + + } + + if ($PSBoundParameters.Keys.Contains('summary')) { + $resu = $resu | Select-Object rolename, roleid, principalid, principalName, principalEmail, PrincipalType, startDateTime, endDateTime, directoryScopeId + } + + if ($PSBoundParameters.Keys.Contains('principalid')) { + $resu = $resu | Where-Object { $_.principalid -eq $principalid } + } + + if ($PSBoundParameters.Keys.Contains('rolename')) { + $resu = $resu | Where-Object { $_.rolename -eq $rolename } + } + if($PSBoundParameters.Keys.Contains('principalName')){ + $resu = $resu | Where-Object { $_.principalName -match $principalName } + } + + return $resu + } + catch { + MyCatch $_ + } +} \ No newline at end of file diff --git a/EasyPIM/functions/Get-PIMGroupEligibleAssignment.ps1 b/EasyPIM/functions/Get-PIMGroupEligibleAssignment.ps1 new file mode 100644 index 0000000..fc674b1 --- /dev/null +++ b/EasyPIM/functions/Get-PIMGroupEligibleAssignment.ps1 @@ -0,0 +1,91 @@ +<# + .Synopsis + List of PIM Entra Role active assignement + .Description + Active assignment does not require to activate their role. https://learn.microsoft.com/en-us/graph/api/rbacapplication-list-roleeligibilityscheduleinstances?view=graph-rest-1.0&tabs=http + .Parameter tenantID + EntraID tenant ID + .Parameter summary + When enabled will return the most useful information only + .PARAMETER rolename + Filter by rolename + .PARAMETER principalid + Filter by principalid + .PARAMETER principalName + Filter by principalName + + .Example + PS> Get-PIMEntraRoleActiveAssignment -tenantID $tid + + List active assignement + + + .Link + .Notes + Author: Loïc MICHEL + Homepage: https://github.com/kayasax/EasyPIM +#> + +function Get-PIMGroupEligibleAssignment { + [CmdletBinding()] + param ( + [Parameter(Position = 0, Mandatory = $true)] + [String] + $tenantID, + # select the most usefull info only + [switch]$summary, + [string]$groupID, + [string]$rolename, + [string]$principalName + ) + + try { + $script:tenantID = $tenantID + + $endpoint = "identityGovernance/privilegedAccess/group/eligibilitySchedules?`$filter=groupId eq '$groupID'&`$expand=principal + " + $response = invoke-graph -Endpoint $endpoint + $resu = @() + $response.value | ForEach-Object { + + $r = @{ + #"rolename" = $_.roledefinition.displayName + ##"roleid" = $_.roledefinition.id + "principalname" = $_.principal.displayName + "principalid" = $_.principal.id + "principalEmail" = $_.principal.mail + "startDateTime" = $_.scheduleInfo.startDateTime + "endDateTime" = $_.scheduleInfo.expiration.endDateTime + #"directoryScopeId" = $_.directoryScopeId + "memberType" = $_.accessId + "assignmentType" = $_.memberType + #"activatedUsing"=$_.activatedUsing + "principaltype" = $_.principal."@odata.type" + "id" = $_.id + } + $resu += New-Object PSObject -Property $r + + + } + + if ($PSBoundParameters.Keys.Contains('summary')) { + $resu = $resu | Select-Object rolename, roleid, principalid, principalName, principalEmail, PrincipalType, startDateTime, endDateTime, directoryScopeId + } + + if ($PSBoundParameters.Keys.Contains('principalid')) { + $resu = $resu | Where-Object { $_.principalid -eq $principalid } + } + + if ($PSBoundParameters.Keys.Contains('rolename')) { + $resu = $resu | Where-Object { $_.rolename -eq $rolename } + } + if($PSBoundParameters.Keys.Contains('principalName')){ + $resu = $resu | Where-Object { $_.principalName -match $principalName } + } + + return $resu + } + catch { + MyCatch $_ + } +} \ No newline at end of file diff --git a/EasyPIM/functions/New-PIMEntraRoleActiveAssignment.ps1 b/EasyPIM/functions/New-PIMEntraRoleActiveAssignment.ps1 index b823574..5d40480 100644 --- a/EasyPIM/functions/New-PIMEntraRoleActiveAssignment.ps1 +++ b/EasyPIM/functions/New-PIMEntraRoleActiveAssignment.ps1 @@ -136,8 +136,8 @@ function New-PIMEntraRoleActiveAssignment { } }, "ticketInfo": { - "ticketNumber": "CONTOSO:Normal-67890", - "ticketSystem": "MS Project" + "ticketNumber": "EasyPIM", + "ticketSystem": "EasyPIM" } } diff --git a/EasyPIM/functions/New-PIMGroupActiveAssignment.ps1 b/EasyPIM/functions/New-PIMGroupActiveAssignment.ps1 new file mode 100644 index 0000000..b36a87d --- /dev/null +++ b/EasyPIM/functions/New-PIMGroupActiveAssignment.ps1 @@ -0,0 +1,146 @@ +<# + .Synopsis + Create an active assignement at the provided scope + .Description + Active assignment does not require users to activate their role. 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 principalID + objectID of the principal (user, group or service principal) + .Parameter rolename + name of the role to assign + .Parameter duration + duration of the assignment, if not set we will use the maximum allowed value from the role policy + .Parameter startDateTime + When the assignment wil begin, if not set we will use current time + .Parameter permanent + Use this parameter if you want a permanent assignement (no expiration) + .Parameter justification + justification + + + .Example + PS> New-PIMEntraRoleEligibleAssignment -tenantID $tenantID -subscriptionID $subscriptionId -rolename "AcrPush" -principalID 3604fe63-cb67-4b60-99c9-707d46ab9092 -startDateTime "2/2/2024 18:20" + + Create an active assignment fot the role Arcpush, starting at a specific date and using default duration + + PS> New-PIMEntraRoleEligibleAssignment -tenantID $tenantID -subscriptionID $subscriptionId -rolename "webmaster" -principalID 3604fe63-cb67-4b60-99c9-707d46ab9092 -justification 'TEST' -permanent + + Create a permanent active assignement for the role webmaster + + .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 New-PIMGroupActiveAssignment { + [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingWriteHost", "")] + [CmdletBinding()] + param ( + [Parameter(Position = 0, Mandatory = $true)] + [String] + # Entra ID tenantID + $tenantID, + + [Parameter(Position = 1, Mandatory = $true)] + [String] + # Entra ID tenantID + $groupID, + + [Parameter(Mandatory = $true)] + [String] + # Principal ID + $principalID, + + [Parameter(Mandatory = $true)] + [string] + # the rolename for which we want to create an assigment + $type, + + [string] + # duration of the assignment, if not set we will use the maximum allowed value from the role policy + $duration, + + [string] + # stat date of assignment if not provided we will use curent time + $startDateTime, + + [string] + # justification (will be auto generated if not provided) + $justification, + + [switch] + # the assignment will not expire + $permanent + + ) + + try { + $script:tenantID = $tenantID + + if ($PSBoundParameters.Keys.Contains('startDateTime')) { + $startDateTime = get-date ([datetime]::Parse($startDateTime)).touniversaltime().addseconds(30) -f "yyyy-MM-ddTHH:mm:ssZ" + } + else { + $startDateTime = get-date (get-date).touniversaltime().addseconds(30) -f "yyyy-MM-ddTHH:mm:ssZ" #we get the date as UTC (remember to add a Z at the end or it will be translated to US timezone on import) + } + + write-verbose "Calculated date time start is $startDateTime" + # 2 get role settings: + $config = Get-PIMgroupPolicy -tenantID $tenantID -groupID $groupID -type $type + + #if permanent assignement is requested check this is allowed in the rule + if ($permanent) { + if ( $config.AllowPermanentActiveAssignment -eq "false") { + throw "ERROR : The role $rolename does not allow permanent eligible assignement, exiting" + } + } + + # if Duration is not provided we will take the maxium value from the role setting + if (!($PSBoundParameters.Keys.Contains('duration'))) { + $duration = $config.MaximumActiveAssignmentDuration + } + write-verbose "assignement duration will be : $duration" + + if (!($PSBoundParameters.Keys.Contains('justification'))) { + $justification = "Approved from EasyPIM module by $($(get-azcontext).account)" + } + + + $exptype = "AfterDuration" + #$type="afterDateTime" + if ($permanent) { + $exptype = "NoExpiration" + } + + $body = ' +{ + "action": "adminAssign", + "accessID":"'+$type+'", + "groupID":"'+$groupID+'", + "justification": "'+ $justification + '", + "principalId": "'+ $principalID + '", + "scheduleInfo": { + "startDateTime": "'+ $startDateTime + '", + "expiration": { + "type": "'+ $exptype + '", + "duration": "'+ $duration + '" + } + } +} + +' + $endpoint = "/identityGovernance/privilegedAccess/group/assignmentScheduleRequests" + write-verbose "patch body : $body" + $null = invoke-graph -Endpoint $endpoint -Method "POST" -body $body + } + catch { + MyCatch $_ + } + +} diff --git a/EasyPIM/functions/New-PIMGroupEligibleAssignment.ps1 b/EasyPIM/functions/New-PIMGroupEligibleAssignment.ps1 new file mode 100644 index 0000000..4821ea0 --- /dev/null +++ b/EasyPIM/functions/New-PIMGroupEligibleAssignment.ps1 @@ -0,0 +1,148 @@ +<# + .Synopsis + Create an active assignement at the provided scope + .Description + Active assignment does not require users to activate their role. 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 principalID + objectID of the principal (user, group or service principal) + .Parameter rolename + name of the role to assign + .Parameter duration + duration of the assignment, if not set we will use the maximum allowed value from the role policy + .Parameter startDateTime + When the assignment wil begin, if not set we will use current time + .Parameter permanent + Use this parameter if you want a permanent assignement (no expiration) + .Parameter justification + justification + + + .Example + PS> New-PIMEntraRoleEligibleAssignment -tenantID $tenantID -subscriptionID $subscriptionId -rolename "AcrPush" -principalID 3604fe63-cb67-4b60-99c9-707d46ab9092 -startDateTime "2/2/2024 18:20" + + Create an active assignment fot the role Arcpush, starting at a specific date and using default duration + + PS> New-PIMEntraRoleEligibleAssignment -tenantID $tenantID -subscriptionID $subscriptionId -rolename "webmaster" -principalID 3604fe63-cb67-4b60-99c9-707d46ab9092 -justification 'TEST' -permanent + + Create a permanent active assignement for the role webmaster + + .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 New-PIMGroupActiveAssignment { + [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingWriteHost", "")] + [CmdletBinding()] + param ( + [Parameter(Position = 0, Mandatory = $true)] + [String] + # Entra ID tenantID + $tenantID, + + [Parameter(Position = 1, Mandatory = $true)] + [String] + # Entra ID tenantID + $groupID, + + [Parameter(Mandatory = $true)] + [String] + # Principal ID + $principalID, + + [Parameter(Mandatory = $true)] + [string] + # the rolename for which we want to create an assigment + $type, + + [string] + # duration of the assignment, if not set we will use the maximum allowed value from the role policy + $duration, + + [string] + # stat date of assignment if not provided we will use curent time + $startDateTime, + + [string] + # justification (will be auto generated if not provided) + $justification, + + [switch] + # the assignment will not expire + $permanent + + ) + + try { + $script:tenantID = $tenantID + + + if ($PSBoundParameters.Keys.Contains('startDateTime')) { + $startDateTime = get-date ([datetime]::Parse($startDateTime)).touniversaltime().addseconds(30) -f "yyyy-MM-ddTHH:mm:ssZ" + } + else { + $startDateTime = get-date (get-date).touniversaltime().addseconds(30) -f "yyyy-MM-ddTHH:mm:ssZ" #we get the date as UTC (remember to add a Z at the end or it will be translated to US timezone on import) + } + + write-verbose "Calculated date time start is $startDateTime" + # 2 get role settings: + $config = Get-PIMgroupPolicy -tenantID $tenantID -groupID $groupID -type $type + + #if permanent assignement is requested check this is allowed in the rule + if ($permanent) { + if ( $config.AllowPermanentActiveAssignment -eq "false") { + throw "ERROR : The role $rolename does not allow permanent actove assignement, exiting" + } + } + + # if Duration is not provided we will take the maxium value from the role setting + if (!($PSBoundParameters.Keys.Contains('duration'))) { + $duration = $config.MaximumEligibleAssignmentDuration + } + write-verbose "assignement duration will be : $duration" + + if (!($PSBoundParameters.Keys.Contains('justification'))) { + $justification = "Approved from EasyPIM module by $($(get-azcontext).account)" + } + + + $exptype = "AfterDuration" + #$type="afterDateTime" + if ($permanent) { + $exptype = "NoExpiration" + } + + $body = ' +{ + "action": "adminAssign", + "accessID":"'+$type+'", + "groupID":"'+$groupID+'", + "justification": "'+ $justification + '", + "principalId": "'+ $principalID + '", + "scheduleInfo": { + "startDateTime": "'+ $startDateTime + '", + "expiration": { + "type": "'+ $exptype + '", + "endDateTime": null, + "duration": "'+ $duration + '" + } + } +} + +' + $endpoint = "/identityGovernance/privilegedAccess/group/AssignmentScheduleRequests" + write-verbose "patch body : $body" + $null = invoke-graph -Endpoint $endpoint -Method "POST" -body $body + } + catch { + MyCatch $_ + } + +} diff --git a/EasyPIM/functions/Remove-PIMGroupActiveAssignment.ps1 b/EasyPIM/functions/Remove-PIMGroupActiveAssignment.ps1 new file mode 100644 index 0000000..ded917b --- /dev/null +++ b/EasyPIM/functions/Remove-PIMGroupActiveAssignment.ps1 @@ -0,0 +1,146 @@ +<# + .Synopsis + Create an active assignement at the provided scope + .Description + Active assignment does not require users to activate their role. 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 principalID + objectID of the principal (user, group or service principal) + .Parameter rolename + name of the role to assign + .Parameter duration + duration of the assignment, if not set we will use the maximum allowed value from the role policy + .Parameter startDateTime + When the assignment wil begin, if not set we will use current time + .Parameter permanent + Use this parameter if you want a permanent assignement (no expiration) + .Parameter justification + justification + + + .Example + PS> New-PIMEntraRoleEligibleAssignment -tenantID $tenantID -subscriptionID $subscriptionId -rolename "AcrPush" -principalID 3604fe63-cb67-4b60-99c9-707d46ab9092 -startDateTime "2/2/2024 18:20" + + Create an active assignment fot the role Arcpush, starting at a specific date and using default duration + + PS> New-PIMEntraRoleEligibleAssignment -tenantID $tenantID -subscriptionID $subscriptionId -rolename "webmaster" -principalID 3604fe63-cb67-4b60-99c9-707d46ab9092 -justification 'TEST' -permanent + + Create a permanent active assignement for the role webmaster + + .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 Remove-PIMGroupActiveAssignment { + [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingWriteHost", "")] + [CmdletBinding()] + param ( + [Parameter(Position = 0, Mandatory = $true)] + [String] + # Entra ID tenantID + $tenantID, + + [Parameter(Mandatory = $true)] + [String] + # Principal ID + $principalID, + + [Parameter(Mandatory = $true)] + [string] + # the group ID + $groupID, + + [Parameter(Mandatory = $true)] + [string] + # member or owner + $type, + + + [string] + # duration of the assignment, if not set we will use the maximum allowed value from the role policy + $duration, + + [string] + # stat date of assignment if not provided we will use curent time + $startDateTime, + + [string] + # justification (will be auto generated if not provided) + $justification, + + [switch] + # the assignment will not expire + $permanent + + ) + + try { + $script:tenantID = $tenantID + + + if ($PSBoundParameters.Keys.Contains('startDateTime')) { + $startDateTime = get-date ([datetime]::Parse($startDateTime)).touniversaltime().addseconds(30) -f "yyyy-MM-ddTHH:mm:ssZ" + } + else { + $startDateTime = get-date (get-date).touniversaltime().addseconds(30) -f "yyyy-MM-ddTHH:mm:ssZ" #we get the date as UTC (remember to add a Z at the end or it will be translated to US timezone on import) + } + + write-verbose "Calculated date time start is $startDateTime" + # 2 get role settings: + $config = Get-PIMGroupPolicy -tenantID $tenantID -groupID $groupid -type $type + + #if permanent assignement is requested check this is allowed in the rule + if ($permanent) { + if ( $config.AllowPermanentActiveAssignment -eq "false") { + throw "ERROR : The role $rolename does not allow permanent eligible assignement, exiting" + } + } + + # if Duration is not provided we will take the maxium value from the role setting + if (!($PSBoundParameters.Keys.Contains('duration'))) { + $duration = $config.MaximumActiveAssignmentDuration + } + write-verbose "assignement duration will be : $duration" + + if (!($PSBoundParameters.Keys.Contains('justification'))) { + $justification = "Approved from EasyPIM module by $($(get-azcontext).account)" + } + + + $exptype = "AfterDuration" + #$type="afterDateTime" + if ($permanent) { + $exptype = "NoExpiration" + } + + $body = ' +{ + "action": "adminRemove", + "accessID":"'+$type+'", + "groupID":"'+$groupID+'", + "justification": "'+ $justification + '", + "principalId": "'+ $principalID + '", + "scheduleInfo": { + "startDateTime": "'+ $startDateTime + '", + "expiration": { + "type": "'+ $exptype + '", + "duration": "'+ $duration + '" + } + } +} + +' + $endpoint = "/identityGovernance/privilegedAccess/group/assignmentScheduleRequests" + write-verbose "patch body : $body" + $null = invoke-graph -Endpoint $endpoint -Method "POST" -body $body + Write-Host "SUCCESS : Assignment removed!" + } + catch { Mycatch $_ } +} diff --git a/EasyPIM/functions/Remove-PIMGroupEligibleAssignment.ps1 b/EasyPIM/functions/Remove-PIMGroupEligibleAssignment.ps1 new file mode 100644 index 0000000..a448945 --- /dev/null +++ b/EasyPIM/functions/Remove-PIMGroupEligibleAssignment.ps1 @@ -0,0 +1,146 @@ +<# + .Synopsis + Create an active assignement at the provided scope + .Description + Active assignment does not require users to activate their role. 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 principalID + objectID of the principal (user, group or service principal) + .Parameter rolename + name of the role to assign + .Parameter duration + duration of the assignment, if not set we will use the maximum allowed value from the role policy + .Parameter startDateTime + When the assignment wil begin, if not set we will use current time + .Parameter permanent + Use this parameter if you want a permanent assignement (no expiration) + .Parameter justification + justification + + + .Example + PS> New-PIMEntraRoleEligibleAssignment -tenantID $tenantID -subscriptionID $subscriptionId -rolename "AcrPush" -principalID 3604fe63-cb67-4b60-99c9-707d46ab9092 -startDateTime "2/2/2024 18:20" + + Create an active assignment fot the role Arcpush, starting at a specific date and using default duration + + PS> New-PIMEntraRoleEligibleAssignment -tenantID $tenantID -subscriptionID $subscriptionId -rolename "webmaster" -principalID 3604fe63-cb67-4b60-99c9-707d46ab9092 -justification 'TEST' -permanent + + Create a permanent active assignement for the role webmaster + + .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 Remove-PIMGroupEligibleAssignment { + [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingWriteHost", "")] + [CmdletBinding()] + param ( + [Parameter(Position = 0, Mandatory = $true)] + [String] + # Entra ID tenantID + $tenantID, + + [Parameter(Mandatory = $true)] + [String] + # Principal ID + $principalID, + + [Parameter(Mandatory = $true)] + [string] + # the group ID + $groupID, + + [Parameter(Mandatory = $true)] + [string] + # member or owner + $type, + + + [string] + # duration of the assignment, if not set we will use the maximum allowed value from the role policy + $duration, + + [string] + # stat date of assignment if not provided we will use curent time + $startDateTime, + + [string] + # justification (will be auto generated if not provided) + $justification, + + [switch] + # the assignment will not expire + $permanent + + ) + + try { + $script:tenantID = $tenantID + + + if ($PSBoundParameters.Keys.Contains('startDateTime')) { + $startDateTime = get-date ([datetime]::Parse($startDateTime)).touniversaltime().addseconds(30) -f "yyyy-MM-ddTHH:mm:ssZ" + } + else { + $startDateTime = get-date (get-date).touniversaltime().addseconds(30) -f "yyyy-MM-ddTHH:mm:ssZ" #we get the date as UTC (remember to add a Z at the end or it will be translated to US timezone on import) + } + + write-verbose "Calculated date time start is $startDateTime" + # 2 get role settings: + $config = Get-PIMGroupPolicy -tenantID $tenantID -groupID $groupid -type $type + + #if permanent assignement is requested check this is allowed in the rule + if ($permanent) { + if ( $config.AllowPermanentEligibleAssignment -eq "false") { + throw "ERROR : The role $rolename does not allow permanent eligible assignement, exiting" + } + } + + # if Duration is not provided we will take the maxium value from the role setting + if (!($PSBoundParameters.Keys.Contains('duration'))) { + $duration = $config.MaximumEligibleAssignmentDuration + } + write-verbose "assignement duration will be : $duration" + + if (!($PSBoundParameters.Keys.Contains('justification'))) { + $justification = "Approved from EasyPIM module by $($(get-azcontext).account)" + } + + + $exptype = "AfterDuration" + #$type="afterDateTime" + if ($permanent) { + $exptype = "NoExpiration" + } + + $body = ' +{ + "action": "adminRemove", + "accessID":"'+$type+'", + "groupID":"'+$groupID+'", + "justification": "'+ $justification + '", + "principalId": "'+ $principalID + '", + "scheduleInfo": { + "startDateTime": "'+ $startDateTime + '", + "expiration": { + "type": "'+ $exptype + '", + "duration": "'+ $duration + '" + } + } +} + +' + $endpoint = "/identityGovernance/privilegedAccess/group/eligibilityScheduleRequests" + write-verbose "patch body : $body" + $null = invoke-graph -Endpoint $endpoint -Method "POST" -body $body + Write-Host "SUCCESS : Assignment removed!" + } + catch { Mycatch $_ } +} diff --git a/EasyPIM/functions/Set-PIMGroupPolicy.ps1 b/EasyPIM/functions/Set-PIMGroupPolicy.ps1 new file mode 100644 index 0000000..5a44471 --- /dev/null +++ b/EasyPIM/functions/Set-PIMGroupPolicy.ps1 @@ -0,0 +1,264 @@ +<# + .Synopsis + Set the setting of the role $rolename + .Description + Set the setting of the role $rolename + .Example + PS> Set-PIMEntraRolePolicy -tenantID $tenantID -rolename webmaster -ActivationDuration "PT8H" + + Limit the maximum PIM activation duration to 8h + .EXAMPLE + PS> Set-PIMGroupPolicy -tenantID $tenantID -groupID "ba6af9bf-6b28-4799-976e-ff71aed3a1bd" -type owner -ActivationDuration "P1D" -ApprovalRequired $true -Approvers @(@{"Id"="25f3deb5-1c8d-4035-942d-b3cbbad98b8e";"Name"="God";"Type"="user"}) -Notification_EligibleAssignment_Alert @{"isDefaultRecipientEnabled"="true"; "notificationLevel"="All";"Recipients" = @("email1@domain.com","email2@domain.com")} + + Require activation approval and set John as an approver + + .Link + + .Notes + Author: Loïc MICHEL + Homepage: https://github.com/kayasax/EasyPIM + #> +function Set-PIMGroupPolicy { + [CmdletBinding(DefaultParameterSetName='Default',SupportsShouldProcess = $true)] + [OutputType([bool])] + param ( + [Parameter(Position = 0, Mandatory = $true)] + [System.String] + # Tenant ID + $tenantID, + + [Parameter(Position = 1, Mandatory = $true)] + [System.String[]] + #list of group to update + $groupID, + + [Parameter(Position = 2, Mandatory = $true)] + [System.String] + # type of role (owner or member) + $type, + + [System.String] + # Maximum activation duration + $ActivationDuration, + + [Parameter(HelpMessage = "Accepted values: 'None' or any combination of these options (Case SENSITIVE): 'Justification, 'MultiFactorAuthentication', 'Ticketing'")] + [ValidateScript({ + # accepted values: "None","Justification", "MultiFactorAuthentication", "Ticketing" + # WARNING: options are CASE SENSITIVE + $script:valid = $true + $acceptedValues = @("None", "Justification", "MultiFactorAuthentication", "Ticketing") + $_ | ForEach-Object { if (!( $acceptedValues -Ccontains $_)) { $script:valid = $false } } + return $script:valid + })] + [System.String[]] + # Activation requirement + $ActivationRequirement, + + [Parameter()] + [Bool] + # Is approval required to activate a role? ($true|$false) + $ApprovalRequired, + + [Parameter()] + # Array of approvers in the format: @(@{"Id"=;"Name"="John":"Type"="user|group"}, .... ) + $Approvers, + + [Parameter()] + [System.String] + # Maximum Eligility Duration + $MaximumEligibilityDuration = $null, + + [Parameter()] + [Bool] + # Allow permanent eligibility? ($true|$false) + $AllowPermanentEligibility, + + [Parameter()] + [System.String] + # Maximum active assignment duration # Duration ref https://en.wikipedia.org/wiki/ISO_8601#Durations + $MaximumActiveAssignmentDuration = $null, + + [Parameter()] + [Bool] + # Allow permanent active assignement? ($true|$false) + $AllowPermanentActiveAssignment, + + [Parameter()] + [System.Collections.Hashtable] + # Admin Notification when eligible role is assigned + # Format: @{"isDefaultRecipientEnabled"="true|false"; "notificationLevel"="All|Critical"};"Recipients" = @("email1@domain.com","email2@domain.com")} + $Notification_EligibleAssignment_Alert, + + [Parameter()] + [System.Collections.Hashtable] + # End user notification when eligible role is assigned + # Format: @{"isDefaultRecipientEnabled"="true|false"; "notificationLevel"="All|Critical"};"Recipients" = @("email1@domain.com","email2@domain.com")} + $Notification_EligibleAssignment_Assignee, + + [Parameter()] + [System.Collections.Hashtable] + # Approver notification when eligible role is assigned + # Format: @{"isDefaultRecipientEnabled"="true|false"; "notificationLevel"="All|Critical"};"Recipients" = @("email1@domain.com","email2@domain.com")} + $Notification_EligibleAssignment_Approver, + + [Parameter()] + [System.Collections.Hashtable] + # Admin Notification when an active role is assigned + # Format: @{"isDefaultRecipientEnabled"="true|false"; "notificationLevel"="All|Critical"};"Recipients" = @("email1@domain.com","email2@domain.com")} + $Notification_ActiveAssignment_Alert, + + [Parameter()] + [System.Collections.Hashtable] + # End user Notification when an active role is assigned + # Format: @{"isDefaultRecipientEnabled"="true|false"; "notificationLevel"="All|Critical"};"Recipients" = @("email1@domain.com","email2@domain.com")} + $Notification_ActiveAssignment_Assignee, + + [Parameter()] + [System.Collections.Hashtable] + # Approver Notification when an active role is assigned + # Format: @{"isDefaultRecipientEnabled"="true|false"; "notificationLevel"="All|Critical"};"Recipients" = @("email1@domain.com","email2@domain.com")} + $Notification_ActiveAssignment_Approver, + + [Parameter()] + [System.Collections.Hashtable] + # Admin Notification when a is activated + # Format: @{"isDefaultRecipientEnabled"="true|false"; "notificationLevel"="All|Critical"};"Recipients" = @("email1@domain.com","email2@domain.com")} + $Notification_Activation_Alert, + + [Parameter()] + [System.Collections.Hashtable] + # End user Notification when a role is activated + # Format: @{"isDefaultRecipientEnabled"="true|false"; "notificationLevel"="All|Critical"};"Recipients" = @("email1@domain.com","email2@domain.com")} + $Notification_Activation_Assignee, + + [Parameter()] + [System.Collections.Hashtable] + # Approvers Notification when a role is activated + # Format: @{"isDefaultRecipientEnabled"="true|false"; "notificationLevel"="All|Critical"};"Recipients" = @("email1@domain.com","email2@domain.com")} + $Notification_Activation_Approver + + ) + try { + $p = @() + $PSBoundParameters.Keys | ForEach-Object { + $p += "$_ =>" + $PSBoundParameters[$_] + } + $p = $p -join ', ' + + log "Function Set-PIMGroupPolicy is starting with parameters: $p" -noEcho + + $script:tenantID=$tenantID + + #at least one approver required if approval is enable + # todo chech if a parameterset would be better + if ($ApprovalRequired -eq $true -and $null -eq $Approvers ) { throw "`n /!\ At least one approver is required if approval is enable, please set -Approvers parameter`n`n" } + + $groupID | ForEach-Object { + $script:config = get-Groupconfig $_ -type $type + $rules = @() + + if ($PSBoundParameters.Keys.Contains('ActivationDuration')) { + $rules += Set-ActivationDuration $ActivationDuration -EntraRole + } + + if ($PSBoundParameters.Keys.Contains('ActivationRequirement')) { + $rules += Set-ActivationRequirement $ActivationRequirement -EntraRole + } + + # Approval and approvers + if ( ($PSBoundParameters.Keys.Contains('ApprovalRequired')) -or ($PSBoundParameters.Keys.Contains('Approvers'))) { + $rules += Set-Approval $ApprovalRequired $Approvers -EntraRole + } + + # eligibility assignement + if ( $PSBoundParameters.ContainsKey('MaximumEligibilityDuration') -or ( $PSBoundParameters.ContainsKey('AllowPermanentEligibility'))) { + #if values are not set, use the ones from the curent config + write-verbose "Maximum Eligibiliy duration from curent config: $($script:config.MaximumEligibleAssignmentDuration)" + if (!( $PSBoundParameters.ContainsKey('MaximumEligibilityDuration'))) { $MaximumEligibilityDuration = $script:config.MaximumEligibleAssignmentDuration } + if (!( $PSBoundParameters.ContainsKey('AllowPermanentEligibility'))) { $AllowPermanentEligibility = $script:config.AllowPermanentEligibleAssignment } + if ( ($false -eq $AllowPermanentEligibility) -and ( ($MaximumEligibilityDuration -eq "") -or ($null -eq $MaximumEligibilityDuration) )){ + throw "ERROR: you requested the assignement to expire but the maximum duration is not defined, please use the MaximumEligibilityDuration parameter" + } + $rules += Set-EligibilityAssignment $MaximumEligibilityDuration $AllowPermanentEligibility -entraRole + } + + #active assignement limits + if ( $PSBoundParameters.ContainsKey('MaximumActiveAssignmentDuration') -or ( $PSBoundParameters.ContainsKey('AllowPermanentActiveAssignment'))) { + #if values are not set, use the ones from the curent config + write-verbose "Maximum Active duration from curent config: $($script:config.MaximumActiveAssignmentDuration)" + if (!( $PSBoundParameters.ContainsKey('MaximumActiveAssignmentDuration'))) { $MaximumActiveAssignmentDuration = $script:config.MaximumActiveAssignmentDuration } + if (!( $PSBoundParameters.ContainsKey('AllowPermanentActiveAssignment'))) { $AllowPermanentActiveAssignment = $script:config.AllowPermanentActiveAssignment } + if ( ($false -eq $AllowPermanentActiveAssignment) -and ( ($MaximumActiveAssignmentDuration -eq "") -or ($null -eq $MaximumActiveAssignmentDuration) )){ + throw "ERROR: you requested the assignement to expire but the maximum duration is not defined, please use the MaximumActiveAssignmentDuration parameter" + } + $rules += Set-ActiveAssignment $MaximumActiveAssignmentDuration $AllowPermanentActiveAssignment -entraRole + } + + ################# + # Notifications # + ################# + + # Notif Eligibility assignment Alert + if ($PSBoundParameters.Keys.Contains('Notification_EligibleAssignment_Alert')) { + $rules += Set-Notification_EligibleAssignment_Alert $Notification_EligibleAssignment_Alert -entraRole + } + + # Notif elligibility assignee + if ($PSBoundParameters.Keys.Contains('Notification_EligibleAssignment_Assignee')) { + $rules += Set-Notification_EligibleAssignment_Assignee $Notification_EligibleAssignment_Assignee -entraRole + } + + # Notif elligibility approver + if ($PSBoundParameters.Keys.Contains('Notification_EligibleAssignment_Approver')) { + $rules += Set-Notification_EligibleAssignment_Approver $Notification_EligibleAssignment_Approver -entraRole + } + + # Notif Active Assignment Alert + if ($PSBoundParameters.Keys.Contains('Notification_ActiveAssignment_Alert')) { + $rules += Set-Notification_ActiveAssignment_Alert $Notification_ActiveAssignment_Alert -entraRole + } + + # Notif Active Assignment Assignee + if ($PSBoundParameters.Keys.Contains('Notification_ActiveAssignment_Assignee')) { + $rules += Set-Notification_ActiveAssignment_Assignee $Notification_ActiveAssignment_Assignee -entraRole + } + + # Notif Active Assignment Approvers + if ($PSBoundParameters.Keys.Contains('Notification_ActiveAssignment_Approver')) { + $rules += Set-Notification_ActiveAssignment_Approver $Notification_ActiveAssignment_Approver -entraRole + } + + # Notification Activation alert + if ($PSBoundParameters.Keys.Contains('Notification_Activation_Alert')) { + $rules += Set-Notification_Activation_Alert $Notification_Activation_Alert -entraRole + } + + # Notification Activation Assignee + if ($PSBoundParameters.Keys.Contains('Notification_Activation_Assignee')) { + + $rules += Set-Notification_Activation_Assignee $Notification_Activation_Assignee -entraRole + } + + # Notification Activation Approvers + if ($PSBoundParameters.Keys.Contains('Notification_Activation_Approver')) { + $rules += Set-Notification_Activation_Approver $Notification_Activation_Approver -entraRole + } + + # Bringing all the rules together and patch the policy + $allrules = $rules -join ',' + #Write-Verbose "All rules: $allrules" + + #Patching the policy + if ($PSCmdlet.ShouldProcess($_, "Udpdating policy")) { + $null = Update-EntraRolePolicy $script:config.policyID $allrules + } + + } + log "Success, policy updated" + return + } + catch { + MyCatch $_ + } + +} \ No newline at end of file diff --git a/EasyPIM/internal/functions/get-GroupConfig.ps1 b/EasyPIM/internal/functions/get-GroupConfig.ps1 index 027eb27..29995ee 100644 --- a/EasyPIM/internal/functions/get-GroupConfig.ps1 +++ b/EasyPIM/internal/functions/get-GroupConfig.ps1 @@ -5,6 +5,8 @@ will convert the json rules to a PSCustomObject .Parameter id Id of the group to check + .Parameter type + type of role (owner or member) .Example PS> get-config -scope $scop -rolename role1 @@ -21,7 +23,7 @@ function get-Groupconfig ( $id, $type) { $endpoint = "policies/roleManagementPolicyAssignments?`$filter=scopeId eq '$id' and scopeType eq 'Group' and roleDefinitionId eq '$type'&`$expand=policy(`$expand=rules)" $response = invoke-graph -Endpoint $endpoint - $policyId=$response.value.id + $policyId=$response.value.policyid #$response # Get config values in a new object: From 2e0428e39fb8b8daa015de8708604227cb82e9c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20MICHEL?= Date: Fri, 8 Mar 2024 15:52:39 +0100 Subject: [PATCH 3/3] V1.5 --- EasyPIM/functions/New-PIMGroupEligibleAssignment.ps1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/EasyPIM/functions/New-PIMGroupEligibleAssignment.ps1 b/EasyPIM/functions/New-PIMGroupEligibleAssignment.ps1 index 4821ea0..b649767 100644 --- a/EasyPIM/functions/New-PIMGroupEligibleAssignment.ps1 +++ b/EasyPIM/functions/New-PIMGroupEligibleAssignment.ps1 @@ -38,7 +38,7 @@ Author: Loïc MICHEL Homepage: https://github.com/kayasax/EasyPIM #> -function New-PIMGroupActiveAssignment { +function New-PIMGroupEligibleAssignment { [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingWriteHost", "")] [CmdletBinding()] param ( @@ -137,7 +137,7 @@ function New-PIMGroupActiveAssignment { } ' - $endpoint = "/identityGovernance/privilegedAccess/group/AssignmentScheduleRequests" + $endpoint = "/identityGovernance/privilegedAccess/group/EligibilityScheduleRequests" write-verbose "patch body : $body" $null = invoke-graph -Endpoint $endpoint -Method "POST" -body $body }