Skip to content

Commit b9c3159

Browse files
Merge pull request KelvinTegelaar#1452 from KelvinTegelaar/dev
Dev to release
2 parents ada0f46 + b579ef9 commit b9c3159

File tree

166 files changed

+10121
-6655
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

166 files changed

+10121
-6655
lines changed

Cache_SAMSetup/PermissionsTranslator.json

Lines changed: 5350 additions & 5350 deletions
Large diffs are not rendered by default.

Cache_SAMSetup/SAMManifest.json

Lines changed: 193 additions & 194 deletions
Large diffs are not rendered by default.
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
function Convert-QuarantinePermissionsValue {
2+
[CmdletBinding(DefaultParameterSetName = 'DecimalValue')]
3+
param (
4+
[Parameter(Mandatory, Position = 0, ParameterSetName = "StringValue")]
5+
[ValidateNotNullOrEmpty()]
6+
[string]$InputObject,
7+
8+
[Parameter(Position = 0, ParameterSetName = "DecimalValue")]
9+
[int]$PermissionToViewHeader = 0,
10+
[Parameter(Position = 1, ParameterSetName = "DecimalValue")]
11+
[int]$PermissionToDownload = 0,
12+
[Parameter(Mandatory, Position = 2, ParameterSetName = "DecimalValue")]
13+
[int]$PermissionToAllowSender,
14+
[Parameter(Mandatory, Position = 3, ParameterSetName = "DecimalValue")]
15+
[int]$PermissionToBlockSender,
16+
[Parameter(Mandatory, Position = 4, ParameterSetName = "DecimalValue")]
17+
[int]$PermissionToRequestRelease,
18+
[Parameter(Mandatory, Position = 5, ParameterSetName = "DecimalValue")]
19+
[int]$PermissionToRelease,
20+
[Parameter(Mandatory, Position = 6, ParameterSetName = "DecimalValue")]
21+
[int]$PermissionToPreview,
22+
[Parameter(Mandatory, Position = 7, ParameterSetName = "DecimalValue")]
23+
[int]$PermissionToDelete
24+
)
25+
26+
#Converts string value with EndUserQuarantinePermissions received from Get-QuarantinePolicy
27+
if (($PSCmdlet.ParameterSetName) -eq "StringValue") {
28+
try {
29+
# Remove square brackets and split into lines
30+
$InputObject = $InputObject.Trim('[', ']')
31+
$hashtable = @{}
32+
$InputObject -split "`n" | ForEach-Object {
33+
$key, $value = $_ -split ":\s*"
34+
$hashtable[$key.Trim()] = [System.Convert]::ToBoolean($value.Trim())
35+
}
36+
return $hashtable
37+
}
38+
catch {
39+
throw "Convert-QuarantinePermissionsValue: Failed to convert string to hashtable."
40+
}
41+
}
42+
43+
#Converts selected end user quarantine permissions to decimal value used by EndUserQuarantinePermissionsValue property in New-QuarantinePolicy and Set-QuarantinePolicy
44+
elseif (($PSCmdlet.ParameterSetName) -eq "DecimalValue") {
45+
try {
46+
# both PermissionToRequestRelease and PermissionToRelease cannot be set to true at the same time
47+
if($PermissionToRequestRelease -eq 1 -and $PermissionToRelease -eq 1) {
48+
throw "PermissionToRequestRelease and PermissionToRelease cannot both be set to true."
49+
}
50+
51+
# Convert each permission to a binary string
52+
$BinaryValue = [string]@(
53+
$PermissionToViewHeader,
54+
$PermissionToDownload,
55+
$PermissionToAllowSender,
56+
$PermissionToBlockSender,
57+
$PermissionToRequestRelease,
58+
$PermissionToRelease,
59+
$PermissionToPreview,
60+
$PermissionToDelete
61+
) -replace '\s',''
62+
63+
# Convert the binary string to an Decimal value
64+
return [convert]::ToInt32($BinaryValue,2)
65+
}
66+
catch {
67+
$ErrorMessage = Get-NormalizedError -Message $_.Exception.Message
68+
throw "Convert-QuarantinePermissionsValue: Failed to convert QuarantinePermissions to QuarantinePermissionsValue. Error: $ErrorMessage"
69+
}
70+
}
71+
}

Modules/CIPPCore/Public/Add-CIPPApplicationPermission.ps1

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ function Add-CIPPApplicationPermission {
22
[CmdletBinding()]
33
param(
44
$RequiredResourceAccess,
5+
$TemplateId,
56
$ApplicationId,
67
$Tenantfilter
78
)
@@ -31,7 +32,34 @@ function Add-CIPPApplicationPermission {
3132

3233
$RequiredResourceAccess.Add($Resource)
3334
}
35+
} else {
36+
if (!$RequiredResourceAccess -and $TemplateId) {
37+
Write-Information "Adding application permissions for template $TemplateId"
38+
$TemplateTable = Get-CIPPTable -TableName 'templates'
39+
$Filter = "RowKey eq '$TemplateId' and PartitionKey eq 'AppApprovalTemplate'"
40+
$Template = (Get-CIPPAzDataTableEntity @TemplateTable -Filter $Filter).JSON | ConvertFrom-Json -ErrorAction SilentlyContinue
41+
$ApplicationId = $Template.AppId
42+
$Permissions = $Template.Permissions
43+
$RequiredResourceAccess = [System.Collections.Generic.List[object]]::new()
44+
foreach ($AppId in $Permissions.PSObject.Properties.Name) {
45+
$AppPermissions = @($Permissions.$AppId.applicationPermissions)
46+
$Resource = @{
47+
resourceAppId = $AppId
48+
resourceAccess = [System.Collections.Generic.List[object]]::new()
49+
}
50+
foreach ($Permission in $AppPermissions) {
51+
$Resource.ResourceAccess.Add(@{
52+
id = $Permission.id
53+
type = 'Role'
54+
})
55+
}
56+
57+
$RequiredResourceAccess.Add($Resource)
58+
}
59+
}
3460
}
61+
62+
3563
$ServicePrincipalList = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/servicePrincipals?`$select=AppId,id,displayName&`$top=999" -skipTokenCache $true -tenantid $Tenantfilter -NoAuthCheck $true
3664
$ourSVCPrincipal = $ServicePrincipalList | Where-Object -Property AppId -EQ $ApplicationId
3765
if (!$ourSVCPrincipal) {
@@ -59,7 +87,7 @@ function Add-CIPPApplicationPermission {
5987
}
6088
}
6189
foreach ($SingleResource in $App.ResourceAccess | Where-Object -Property Type -EQ 'Role') {
62-
if ($SingleResource.id -In $CurrentRoles.appRoleId) { continue }
90+
if ($SingleResource.id -in $CurrentRoles.appRoleId) { continue }
6391
[pscustomobject]@{
6492
principalId = $($ourSVCPrincipal.id)
6593
resourceId = $($svcPrincipalId.id)

Modules/CIPPCore/Public/Add-CIPPDelegatedPermission.ps1

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ function Add-CIPPDelegatedPermission {
22
[CmdletBinding()]
33
param(
44
$RequiredResourceAccess,
5+
$TemplateId,
56
$ApplicationId,
67
$NoTranslateRequired,
78
$Tenantfilter
@@ -40,7 +41,34 @@ function Add-CIPPDelegatedPermission {
4041
# remove the partner center permission if not pushing to partner tenant
4142
$RequiredResourceAccess = $RequiredResourceAccess | Where-Object { $_.resourceAppId -ne 'fa3d9a0c-3fb0-42cc-9193-47c7ecd2edbd' }
4243
}
44+
} else {
45+
if (!$RequiredResourceAccess -and $TemplateId) {
46+
Write-Information "Adding delegated permissions for template $TemplateId"
47+
$TemplateTable = Get-CIPPTable -TableName 'templates'
48+
$Filter = "RowKey eq '$TemplateId' and PartitionKey eq 'AppApprovalTemplate'"
49+
$Template = (Get-CIPPAzDataTableEntity @TemplateTable -Filter $Filter).JSON | ConvertFrom-Json -ErrorAction SilentlyContinue
50+
$ApplicationId = $Template.AppId
51+
$Permissions = $Template.Permissions
52+
$NoTranslateRequired = $true
53+
$RequiredResourceAccess = [System.Collections.Generic.List[object]]::new()
54+
foreach ($AppId in $Permissions.PSObject.Properties.Name) {
55+
$DelegatedPermissions = @($Permissions.$AppId.delegatedPermissions)
56+
$ResourceAccess = [System.Collections.Generic.List[object]]::new()
57+
foreach ($Permission in $DelegatedPermissions) {
58+
$ResourceAccess.Add(@{
59+
id = $Permission.value
60+
type = 'Scope'
61+
})
62+
}
63+
$Resource = @{
64+
resourceAppId = $AppId
65+
resourceAccess = @($ResourceAccess)
66+
}
67+
$RequiredResourceAccess.Add($Resource)
68+
}
69+
}
4370
}
71+
4472
$Translator = Get-Content '.\PermissionsTranslator.json' | ConvertFrom-Json
4573
$ServicePrincipalList = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/servicePrincipals?`$select=appId,id,displayName&`$top=999" -tenantid $Tenantfilter -skipTokenCache $true -NoAuthCheck $true
4674
$ourSVCPrincipal = $ServicePrincipalList | Where-Object -Property appId -EQ $ApplicationId
@@ -66,6 +94,7 @@ function Add-CIPPDelegatedPermission {
6694
}
6795

6896
$DelegatedScopes = $App.resourceAccess | Where-Object -Property type -EQ 'Scope'
97+
6998
if ($NoTranslateRequired) {
7099
$NewScope = @($DelegatedScopes | ForEach-Object { $_.id } | Sort-Object -Unique) -join ' '
71100
} else {
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
2+
function Get-CIPPAlertEntraConnectSyncStatus {
3+
<#
4+
.FUNCTIONALITY
5+
Entrypoint
6+
#>
7+
[CmdletBinding()]
8+
param(
9+
[Parameter(Mandatory = $false)]
10+
[Alias('input')]
11+
$InputValue,
12+
$TenantFilter
13+
)
14+
try {
15+
# Set Hours with fallback to 72 hours
16+
$Hours = if ($InputValue) { [int]$InputValue } else { 72 }
17+
$ConnectSyncStatus = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/organization?$select=onPremisesLastPasswordSyncDateTime,onPremisesLastSyncDateTime,onPremisesSyncEnabled' -tenantid $TenantFilter
18+
19+
if ($ConnectSyncStatus.onPremisesSyncEnabled -eq $true) {
20+
$LastPasswordSync = $ConnectSyncStatus.onPremisesLastPasswordSyncDateTime
21+
$SyncDateTime = $ConnectSyncStatus.onPremisesLastSyncDateTime
22+
# Get the older of the two sync times
23+
$LastSync = if ($SyncDateTime -lt $LastPasswordSync) { $SyncDateTime } else { $LastPasswordSync }
24+
25+
if ($LastSync -lt (Get-Date).AddHours(-$Hours).ToUniversalTime()) {
26+
$AlertData = "Entra Connect Sync for $($TenantFilter) has not run for over $Hours hours. Last sync was at $($LastSync.ToString('o'))"
27+
Write-AlertTrace -cmdletName $MyInvocation.MyCommand -tenantFilter $TenantFilter -data $AlertData
28+
}
29+
}
30+
} catch {
31+
Write-AlertMessage -tenant $($TenantFilter) -message "Could not get Entra Connect Sync Status for $($TenantFilter): $(Get-NormalizedError -message $_.Exception.message)"
32+
}
33+
}

Modules/CIPPCore/Public/Alerts/Get-CIPPAlertMFAAdmins.ps1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ function Get-CIPPAlertMFAAdmins {
1818
}
1919
}
2020
if (!$DuoActive) {
21-
$users = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/reports/authenticationMethods/userRegistrationDetails?`$top=999&filter=IsAdmin eq true and isMfaRegistered eq false and userType eq 'member'&`$select=userPrincipalName,lastUpdatedDateTime,isMfaRegistered,IsAdmin" -tenantid $($TenantFilter) -AsApp $true | Where-Object { $_.userDisplayName -ne 'On-Premises Directory Synchronization Service Account' }
21+
$users = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/reports/authenticationMethods/userRegistrationDetails?`$top=999&filter=IsAdmin eq true and isMfaRegistered eq false and userType eq 'member'&`$select=userDisplayName,userPrincipalName,lastUpdatedDateTime,isMfaRegistered,IsAdmin" -tenantid $($TenantFilter) -AsApp $true | Where-Object { $_.userDisplayName -ne 'On-Premises Directory Synchronization Service Account' }
2222
if ($users.UserPrincipalName) {
2323
$AlertData = "The following admins do not have MFA registered: $($users.UserPrincipalName -join ', ')"
2424
Write-AlertTrace -cmdletName $MyInvocation.MyCommand -tenantFilter $TenantFilter -data $AlertData

Modules/CIPPCore/Public/Alerts/Get-CIPPAlertMFAAlertUsers.ps1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ function Get-CIPPAlertMFAAlertUsers {
1212
)
1313
try {
1414

15-
$users = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/reports/authenticationMethods/userRegistrationDetails?`$top=999&filter=IsAdmin eq false and isMfaRegistered eq false and userType eq 'member'&`$select=userPrincipalName,lastUpdatedDateTime,isMfaRegistered,IsAdmin" -tenantid $($TenantFilter) -AsApp $true | Where-Object { $_.userDisplayName -ne 'On-Premises Directory Synchronization Service Account' }
15+
$users = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/reports/authenticationMethods/userRegistrationDetails?`$top=999&filter=IsAdmin eq false and isMfaRegistered eq false and userType eq 'member'&`$select=userDisplayName,userPrincipalName,lastUpdatedDateTime,isMfaRegistered,IsAdmin" -tenantid $($TenantFilter) -AsApp $true | Where-Object { $_.userDisplayName -ne 'On-Premises Directory Synchronization Service Account' }
1616
if ($users.UserPrincipalName) {
1717
$AlertData = "The following $($users.Count) users do not have MFA registered: $($users.UserPrincipalName -join ', ')"
1818
Write-AlertTrace -cmdletName $MyInvocation.MyCommand -tenantFilter $TenantFilter -data $AlertData
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
function Get-CIPPAccessRole {
2+
<#
3+
.SYNOPSIS
4+
Get the access role for the current user
5+
6+
.DESCRIPTION
7+
Get the access role for the current user
8+
9+
.PARAMETER TenantID
10+
The tenant ID to check the access role for
11+
12+
.EXAMPLE
13+
Get-CippAccessRole -UserId $UserId
14+
15+
.FUNCTIONALITY
16+
Internal
17+
#>
18+
[CmdletBinding()]
19+
param($Request)
20+
21+
$CacheAccessUserRoleTable = Get-CIPPTable -tablename 'cacheAccessUserRole'
22+
$CachedRoles = Get-CIPPAzDataTableEntity @CacheAccessUserRoleTable -Filter "PartitionKey eq 'AccessUser' and RowKey eq '$($Request.Headers.'x-ms-client-principal-name')'" | Select-Object -ExpandProperty Role | ConvertFrom-Json
23+
24+
$SwaCreds = ([System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($request.headers.'x-ms-client-principal')) | ConvertFrom-Json)
25+
$SwaRoles = $SwaCreds.userRoles
26+
27+
# Combine SWA roles and cached roles into a single deduplicated list
28+
$AllRoles = [System.Collections.Generic.List[string]]::new()
29+
if ($null -ne $SwaRoles) {
30+
$AllRoles.AddRange($SwaRoles)
31+
}
32+
if ($null -ne $CachedRoles) {
33+
$AllRoles.AddRange($CachedRoles)
34+
}
35+
36+
# Remove duplicates and ensure we have a clean array
37+
$CombinedRoles = $AllRoles | Select-Object -Unique
38+
39+
# For debugging
40+
Write-Information "Combined Roles: $($CombinedRoles -join ', ')"
41+
return $CombinedRoles
42+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
function Set-CIPPAccessRole {
2+
<#
3+
.SYNOPSIS
4+
Set the access role mappings
5+
6+
.DESCRIPTION
7+
Set the access role mappings for Entra groups
8+
9+
.PARAMETER Role
10+
The role to set (e.g. 'superadmin','admin','editor','readonly','customrole')
11+
12+
.PARAMETER Group
13+
The Entra group to set the role for
14+
15+
.FUNCTIONALITY
16+
Internal
17+
#>
18+
[CmdletBinding(SupportsShouldProcess = $true)]
19+
Param(
20+
[Parameter(Mandatory = $true)]
21+
[string]$Role,
22+
[Parameter(Mandatory = $true)]
23+
[string]$Group
24+
)
25+
26+
$BlacklistedRoles = @('authenticated', 'anonymous')
27+
28+
if ($BlacklistedRoles -contains $Role) {
29+
throw 'Role group cannot be set for authenticated or anonymous roles'
30+
}
31+
32+
if (!$Group.id -or !$Group.displayName) {
33+
throw 'Group is not valid'
34+
}
35+
36+
$Role = $Role.ToLower().Trim() -replace ' ', ''
37+
38+
$Table = Get-CippTable -TableName AccessRoleGroups
39+
$AccessGroup = Get-CIPPAzDataTableEntity @Table -Filter "RowKey = '$Role'"
40+
41+
$AccessGroup = [PSCustomObject]@{
42+
PartitionKey = [string]'AccessRole'
43+
RowKey = [string]$Role
44+
GroupId = [string]$Group.id
45+
GroupName = [string]$Group.displayName
46+
}
47+
48+
if ($PSCmdlet.ShouldProcess("Setting access role $Role for group $($Group.displayName)")) {
49+
Add-CIPPAzDataTableEntity -Table $Table -Entity $AccessGroup -Force
50+
}
51+
}

0 commit comments

Comments
 (0)