Skip to content

Commit f1b1ffd

Browse files
authored
Merge branch 'KelvinTegelaar:master' into master
2 parents c5ce9a4 + 578f421 commit f1b1ffd

453 files changed

Lines changed: 20384 additions & 8328 deletions

File tree

Some content is hidden

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

CIPP-Permissions.json

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

CIPPTimers.json

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -80,14 +80,6 @@
8080
"RunOnProcessor": true,
8181
"PreferredProcessor": "standards"
8282
},
83-
{
84-
"Id": "5113c66d-c040-42df-9565-39dff90ddd55",
85-
"Command": "Start-CIPPGraphSubscriptionCleanupTimer",
86-
"Description": "Orchestrator to cleanup old Graph subscriptions",
87-
"Cron": "0 0 0 * * *",
88-
"Priority": 5,
89-
"RunOnProcessor": true
90-
},
9183
{
9284
"Id": "97145a1d-28f0-4bb2-b929-5a43517d23cc",
9385
"Command": "Start-SchedulerOrchestrator",

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.

Config/standards.json

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1722,6 +1722,35 @@
17221722
"powershellEquivalent": "New-ProtectionAlert and Set-ProtectionAlert",
17231723
"recommendedBy": []
17241724
},
1725+
{
1726+
"name": "standards.SafeLinksTemplatePolicy",
1727+
"label": "SafeLinks Policy Template",
1728+
"cat": "Templates",
1729+
"multiple": false,
1730+
"disabledFeatures": {
1731+
"report": false,
1732+
"warn": false,
1733+
"remediate": false
1734+
},
1735+
"impact": "Medium Impact",
1736+
"addedDate": "2025-04-29",
1737+
"helpText": "Deploy and manage SafeLinks policy templates to protect against malicious URLs in emails and Office documents.",
1738+
"addedComponent": [
1739+
{
1740+
"type": "autoComplete",
1741+
"multiple": true,
1742+
"creatable": false,
1743+
"name": "standards.SafeLinksTemplatePolicy.TemplateIds",
1744+
"label": "Select SafeLinks Policy Templates",
1745+
"api": {
1746+
"url": "/api/ListSafeLinksPolicyTemplates",
1747+
"labelField": "TemplateName",
1748+
"valueField": "GUID",
1749+
"queryKey": "ListSafeLinksPolicyTemplates"
1750+
}
1751+
}
1752+
]
1753+
},
17251754
{
17261755
"name": "standards.SafeLinksPolicy",
17271756
"cat": "Defender Standards",

ConversionTable.csv

Lines changed: 122 additions & 1 deletion
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: 40 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 {
@@ -85,6 +114,10 @@ function Add-CIPPDelegatedPermission {
85114
$OldScope = ($CurrentDelegatedScopes | Where-Object -Property Resourceid -EQ $svcPrincipalId.id)
86115

87116
if (!$OldScope) {
117+
if ([string]::IsNullOrEmpty($NewScope) -or $NewScope -eq ' ') {
118+
$Results.add("No delegated permissions to add for $($svcPrincipalId.displayName)")
119+
continue
120+
}
88121
try {
89122
$Createbody = @{
90123
clientId = $ourSVCPrincipal.id
@@ -118,6 +151,13 @@ function Add-CIPPDelegatedPermission {
118151
$Results.add("All delegated permissions exist for $($svcPrincipalId.displayName)")
119152
continue
120153
}
154+
155+
if ([string]::IsNullOrEmpty($NewScope) -or $NewScope -eq ' ') {
156+
# No permissions to update
157+
$Results.add("No delegated permissions to update for $($svcPrincipalId.displayName)")
158+
continue
159+
}
160+
121161
$Patchbody = @{
122162
scope = "$NewScope"
123163
} | ConvertTo-Json -Compress

Modules/CIPPCore/Public/Add-CIPPGroupMember.ps1

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,22 @@ function Add-CIPPGroupMember(
77
[string]$APIName = 'Add Group Member'
88
) {
99
try {
10-
if ($member -like '*#EXT#*') { $member = [System.Web.HttpUtility]::UrlEncode($member) }
11-
$MemberIDs = 'https://graph.microsoft.com/v1.0/directoryObjects/' + (New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users/$($member)" -tenantid $TenantFilter).id
12-
$addmemberbody = "{ `"members@odata.bind`": $(ConvertTo-Json @($MemberIDs)) }"
10+
if ($Member -like '*#EXT#*') { $Member = [System.Web.HttpUtility]::UrlEncode($Member) }
11+
$MemberIDs = 'https://graph.microsoft.com/v1.0/directoryObjects/' + (New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users/$($Member)" -tenantid $TenantFilter).id
12+
$AddMemberBody = "{ `"members@odata.bind`": $(ConvertTo-Json @($MemberIDs)) }"
1313
if ($GroupType -eq 'Distribution list' -or $GroupType -eq 'Mail-Enabled Security') {
14-
$Params = @{ Identity = $GroupId; Member = $member; BypassSecurityGroupManagerCheck = $true }
15-
$null = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Add-DistributionGroupMember' -cmdParams $params -UseSystemMailbox $true
14+
$Params = @{ Identity = $GroupId; Member = $Member; BypassSecurityGroupManagerCheck = $true }
15+
$null = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Add-DistributionGroupMember' -cmdParams $Params -UseSystemMailbox $true
1616
} else {
17-
$null = New-GraphPostRequest -uri "https://graph.microsoft.com/beta/groups/$($GroupId)" -tenantid $TenantFilter -type patch -body $addmemberbody -Verbose
17+
$null = New-GraphPostRequest -uri "https://graph.microsoft.com/beta/groups/$($GroupId)" -tenantid $TenantFilter -type patch -body $AddMemberBody -Verbose
1818
}
19-
$Message = "Successfully added user $($Member) to $($GroupId)."
20-
Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $Message -Sev 'Info'
21-
return $message
19+
$Results = "Successfully added user $($Member) to $($GroupId)."
20+
Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $Results -Sev 'Info'
21+
return $Results
2222
} catch {
23-
$message = "Failed to add user $($Member) to $($GroupId) - $($_.Exception.Message)"
24-
Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $message -Sev 'error' -LogData (Get-CippException -Exception $_)
25-
return $message
23+
$ErrorMessage = Get-CippException -Exception $_
24+
$Results = "Failed to add user $($Member) to $($GroupId) - $($ErrorMessage.NormalizedError)"
25+
Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $Results -Sev 'error' -LogData $ErrorMessage
26+
throw $Results
2627
}
2728
}

0 commit comments

Comments
 (0)