Skip to content

Commit a15612c

Browse files
Merge pull request #1271 from KelvinTegelaar/dev
Dev to release
2 parents 8789480 + ec88e81 commit a15612c

File tree

188 files changed

+1389
-568
lines changed

Some content is hidden

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

188 files changed

+1389
-568
lines changed

.github/workflows/PR_Branch_Check.yml

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
name: PR Branch Check
2+
3+
on:
4+
# Using pull_request_target instead of pull_request for secure handling of fork PRs
5+
pull_request_target:
6+
# Only run on these PR events
7+
types: [opened, synchronize, reopened]
8+
# Only check PRs targeting these branches
9+
branches:
10+
- main
11+
- master
12+
13+
permissions:
14+
pull-requests: write
15+
issues: write
16+
17+
jobs:
18+
check-branch:
19+
runs-on: ubuntu-latest
20+
steps:
21+
- name: Check and Comment on PR
22+
# Only process fork PRs with specific branch conditions
23+
# Must be a fork AND (source is main/master OR target is main/master)
24+
if: |
25+
github.event.pull_request.head.repo.fork == true &&
26+
((github.event.pull_request.head.ref == 'main' || github.event.pull_request.head.ref == 'master') ||
27+
(github.event.pull_request.base.ref == 'main' || github.event.pull_request.base.ref == 'master'))
28+
uses: actions/github-script@v7
29+
with:
30+
github-token: ${{ secrets.GITHUB_TOKEN }}
31+
script: |
32+
let message = '';
33+
34+
message += '🔄 If you are attempting to update your CIPP repo please follow the instructions at: https://docs.cipp.app/setup/self-hosting-guide/updating ';
35+
message += '\n\n';
36+
37+
// Check if PR is targeting main/master
38+
if (context.payload.pull_request.base.ref === 'main' || context.payload.pull_request.base.ref === 'master') {
39+
message += '⚠️ PRs cannot target the main branch directly. If you are attempting to contribute code please PR to the dev branch.\n\n';
40+
}
41+
42+
// Check if PR is from a fork's main/master branch
43+
if (context.payload.pull_request.head.repo.fork &&
44+
(context.payload.pull_request.head.ref === 'main' || context.payload.pull_request.head.ref === 'master')) {
45+
message += '⚠️ This PR cannot be merged because it originates from your fork\'s main/master branch. If you are attempting to contribute code please PR from your dev branch or another non-main/master branch.\n\n';
46+
}
47+
48+
message += '🔒 This PR will now be automatically closed due to the above violation(s).';
49+
50+
// Post the comment
51+
await github.rest.issues.createComment({
52+
...context.repo,
53+
issue_number: context.issue.number,
54+
body: message
55+
});
56+
57+
// Close the PR
58+
await github.rest.pulls.update({
59+
...context.repo,
60+
pull_number: context.issue.number,
61+
state: 'closed'
62+
});

.github/workflows/dev_cippbcaom.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,4 @@ jobs:
2727
app-name: 'cippbcaom'
2828
slot-name: 'Production'
2929
package: ${{ env.AZURE_FUNCTIONAPP_PACKAGE_PATH }}
30-
publish-profile: ${{ secrets.AZUREAPPSERVICE_PUBLISHPROFILE_56AD4FDD49354D0CAB4D9A9E868D2015 }}
30+
publish-profile: ${{ secrets.AZUREAPPSERVICE_PUBLISHPROFILE_0FE8CACBBF7D409DAAF132988BECEC4B }}

.github/workflows/dev_cippjta72.yml

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Docs for the Azure Web Apps Deploy action: https://github.com/azure/functions-action
2+
# More GitHub Actions for Azure: https://github.com/Azure/actions
3+
4+
name: Build and deploy Powershell project to Azure Function App - cippjta72
5+
6+
on:
7+
push:
8+
branches:
9+
- dev
10+
workflow_dispatch:
11+
12+
env:
13+
AZURE_FUNCTIONAPP_PACKAGE_PATH: '.' # set this to the path to your web app project, defaults to the repository root
14+
15+
jobs:
16+
deploy:
17+
runs-on: windows-latest
18+
19+
steps:
20+
- name: 'Checkout GitHub Action'
21+
uses: actions/checkout@v4
22+
23+
- name: 'Run Azure Functions Action'
24+
uses: Azure/functions-action@v1
25+
id: fa
26+
with:
27+
app-name: 'cippjta72'
28+
slot-name: 'Production'
29+
package: ${{ env.AZURE_FUNCTIONAPP_PACKAGE_PATH }}
30+
publish-profile: ${{ secrets.AZUREAPPSERVICE_PUBLISHPROFILE_5B44448119C645C099EE192346D7433A }}

Modules/CIPPCore/Public/Add-CIPPAzDataTableEntity.ps1

+18-16
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,14 @@ function Add-CIPPAzDataTableEntity {
1919
} catch [System.Exception] {
2020
if ($_.Exception.ErrorCode -eq 'PropertyValueTooLarge' -or $_.Exception.ErrorCode -eq 'EntityTooLarge' -or $_.Exception.ErrorCode -eq 'RequestBodyTooLarge') {
2121
try {
22+
Write-Host 'Entity is too large. Splitting entity into multiple parts.'
23+
Write-Information ($SingleEnt | ConvertTo-Json)
2224
$largePropertyNames = [System.Collections.Generic.List[string]]::new()
2325
$entitySize = 0
2426

2527
# Convert $SingleEnt to hashtable if it is a PSObject
2628
if ($SingleEnt -is [System.Management.Automation.PSCustomObject]) {
27-
$SingleEnt = $SingleEnt | ConvertTo-Json -Depth 100 | ConvertFrom-Json -AsHashtable
29+
$SingleEnt = $SingleEnt | ConvertTo-Json -Depth 100 -Compress | ConvertFrom-Json -AsHashtable
2830
}
2931

3032
foreach ($key in $SingleEnt.Keys) {
@@ -35,7 +37,7 @@ function Add-CIPPAzDataTableEntity {
3537
}
3638
}
3739

38-
if ($largePropertyNames.Count -gt 0) {
40+
if (($largePropertyNames | Measure-Object).Count -gt 0) {
3941
$splitInfoList = [System.Collections.Generic.List[object]]::new()
4042
foreach ($largePropertyName in $largePropertyNames) {
4143
$dataString = $SingleEnt[$largePropertyName]
@@ -45,20 +47,20 @@ function Add-CIPPAzDataTableEntity {
4547
$start = $i * $MaxSize
4648
$splitData.Add($dataString.Substring($start, [Math]::Min($MaxSize, $dataString.Length - $start))) > $null
4749
}
48-
50+
$splitDataCount = ($splitData | Measure-Object).Count
4951
$splitPropertyNames = [System.Collections.Generic.List[object]]::new()
50-
for ($i = 0; $i -lt $splitData.Count; $i++) {
51-
$splitPropertyNames.Add("${largePropertyName}_Part$i") > $null
52+
for ($i = 0; $i -lt $splitDataCount; $i++) {
53+
$splitPropertyNames.Add("${largePropertyName}_Part$i")
5254
}
5355

5456
$splitInfo = @{
5557
OriginalHeader = $largePropertyName
5658
SplitHeaders = $splitPropertyNames
5759
}
58-
$splitInfoList.Add($splitInfo) > $null
60+
$splitInfoList.Add($splitInfo)
5961
$SingleEnt.Remove($largePropertyName)
6062

61-
for ($i = 0; $i -lt $splitData.Count; $i++) {
63+
for ($i = 0; $i -lt $splitDataCount; $i++) {
6264
$SingleEnt[$splitPropertyNames[$i]] = $splitData[$i]
6365
}
6466
}
@@ -67,7 +69,7 @@ function Add-CIPPAzDataTableEntity {
6769
}
6870

6971
# Check if the entity is still too large
70-
$entitySize = [System.Text.Encoding]::UTF8.GetByteCount($($SingleEnt | ConvertTo-Json))
72+
$entitySize = [System.Text.Encoding]::UTF8.GetByteCount($($SingleEnt | ConvertTo-Json -Compress))
7173
if ($entitySize -gt $MaxRowSize) {
7274
$rows = [System.Collections.Generic.List[object]]::new()
7375
$originalPartitionKey = $SingleEnt.PartitionKey
@@ -89,7 +91,7 @@ function Add-CIPPAzDataTableEntity {
8991

9092
$propertiesToRemove = [System.Collections.Generic.List[object]]::new()
9193
foreach ($key in $SingleEnt.Keys) {
92-
$newEntitySize = [System.Text.Encoding]::UTF8.GetByteCount($($newEntity | ConvertTo-Json))
94+
$newEntitySize = [System.Text.Encoding]::UTF8.GetByteCount($($newEntity | ConvertTo-Json -Compress))
9395
if ($newEntitySize -lt $MaxRowSize) {
9496
$propertySize = [System.Text.Encoding]::UTF8.GetByteCount($SingleEnt[$key].ToString())
9597
if ($propertySize -gt $MaxRowSize) {
@@ -103,7 +105,7 @@ function Add-CIPPAzDataTableEntity {
103105

104106
$splitPropertyNames = [System.Collections.Generic.List[object]]::new()
105107
for ($i = 0; $i -lt $splitData.Count; $i++) {
106-
$splitPropertyNames.Add("${key}_Part$i") > $null
108+
$splitPropertyNames.Add("${key}_Part$i")
107109
}
108110

109111
for ($i = 0; $i -lt $splitData.Count; $i++) {
@@ -112,29 +114,29 @@ function Add-CIPPAzDataTableEntity {
112114
} else {
113115
$newEntity[$key] = $SingleEnt[$key]
114116
}
115-
$propertiesToRemove.Add($key) > $null
117+
$propertiesToRemove.Add($key)
116118
}
117119
}
118120

119121
foreach ($prop in $propertiesToRemove) {
120122
$SingleEnt.Remove($prop)
121123
}
122124

123-
$rows.Add($newEntity) > $null
124-
$entitySize = [System.Text.Encoding]::UTF8.GetByteCount($($SingleEnt | ConvertTo-Json))
125+
$rows.Add($newEntity)
126+
$entitySize = [System.Text.Encoding]::UTF8.GetByteCount($($SingleEnt | ConvertTo-Json -Compress))
125127
}
126128

127-
if ($SingleEnt.Count -gt 0) {
129+
if (($SingleEnt | Measure-Object).Count -gt 0) {
128130
$SingleEnt['RowKey'] = "$($originalRowKey)-part$entityIndex"
129131
$SingleEnt['OriginalEntityId'] = $originalRowKey
130132
$SingleEnt['PartIndex'] = $entityIndex
131133
$SingleEnt['PartitionKey'] = $originalPartitionKey
132134

133-
$rows.Add($SingleEnt) > $null
135+
$rows.Add($SingleEnt)
134136
}
135137

136138
foreach ($row in $rows) {
137-
Write-Information "current entity is $($row.RowKey) with $($row.PartitionKey). Our size is $([System.Text.Encoding]::UTF8.GetByteCount($($row | ConvertTo-Json)))"
139+
Write-Information "current entity is $($row.RowKey) with $($row.PartitionKey). Our size is $([System.Text.Encoding]::UTF8.GetByteCount($($row | ConvertTo-Json -Compress)))"
138140
Add-AzDataTableEntity -Context $Context -Force:$Force -CreateTableIfNotExists:$CreateTableIfNotExists -Entity $row
139141
}
140142
} else {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
function Get-CIPPAlertAppCertificateExpiry {
2+
<#
3+
.FUNCTIONALITY
4+
Entrypoint
5+
#>
6+
[CmdletBinding()]
7+
Param (
8+
[Parameter(Mandatory = $false)]
9+
[Alias('input')]
10+
$InputValue,
11+
$TenantFilter
12+
)
13+
14+
try {
15+
Write-Host "Checking app expire for $($TenantFilter)"
16+
$appList = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/applications?`$select=appId,displayName,keyCredentials" -tenantid $TenantFilter
17+
} catch {
18+
return
19+
}
20+
21+
$AlertData = foreach ($App in $applist) {
22+
Write-Host "checking $($App.displayName)"
23+
if ($App.keyCredentials) {
24+
foreach ($Credential in $App.keyCredentials) {
25+
if ($Credential.endDateTime -lt (Get-Date).AddDays(30) -and $Credential.endDateTime -gt (Get-Date).AddDays(-7)) {
26+
Write-Host ("Application '{0}' has certificates expiring on {1}" -f $App.displayName, $Credential.endDateTime)
27+
@{ DisplayName = $App.displayName; Expires = $Credential.endDateTime }
28+
}
29+
}
30+
}
31+
}
32+
Write-AlertTrace -cmdletName $MyInvocation.MyCommand -tenantFilter $TenantFilter -data $AlertData
33+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
function Get-CIPPAlertAppleTerms {
2+
<#
3+
.FUNCTIONALITY
4+
Entrypoint
5+
#>
6+
[CmdletBinding()]
7+
Param (
8+
[Parameter(Mandatory = $false)]
9+
[Alias('input')]
10+
$InputValue,
11+
$TenantFilter
12+
)
13+
14+
# 0 = Expired
15+
# 1 = expired?
16+
# 2 = unknown
17+
# 3 = Terms & Conditions
18+
# 4 = Warning
19+
20+
try {
21+
$appleterms = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/deviceManagement/depOnboardingSettings" -tenantid $TenantFilter
22+
} catch {
23+
return
24+
}
25+
26+
if ($appleterms.lastSyncErrorCode -eq 3) {
27+
$AlertData = "New Apple Business Manager terms are ready to accept."
28+
Write-AlertTrace -cmdletName $MyInvocation.MyCommand -tenantFilter $TenantFilter -data $AlertData
29+
}
30+
}

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

+1-3
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,7 @@ function Get-CIPPAlertDeviceCompliance {
1212
$TenantFilter
1313
)
1414
try {
15-
$AlertData = New-GraphGETRequest -uri "https://graph.microsoft.com/v1.0/deviceManagement/managedDevices?`$top=999" -tenantid $TenantFilter | Where-Object -Property complianceState -NE 'compliant' | ForEach-Object {
16-
$_ | Select-Object -Property id, deviceName, deviceType, complianceState, lastReportedDateTime
17-
}
15+
$AlertData = New-GraphGETRequest -uri "https://graph.microsoft.com/v1.0/deviceManagement/managedDevices?`$filter=complianceState eq 'noncompliant'&`$select=id,deviceName,managedDeviceOwnerType,complianceState,lastSyncDateTime&`$top=999" -tenantid $TenantFilter
1816
Write-AlertTrace -cmdletName $MyInvocation.MyCommand -tenantFilter $TenantFilter -data $AlertData
1917
} catch {
2018
Write-AlertMessage -tenant $($TenantFilter) -message "Could not get compliance state for $($TenantFilter): $(Get-NormalizedError -message $_.Exception.message)"

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

+6-2
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,14 @@ function Get-CIPPAlertInactiveLicensedUsers {
1515
try {
1616

1717
$Lookup = (Get-Date).AddDays(-90).ToUniversalTime().ToString('o')
18-
$GraphRequest = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users?`$filter=(signInActivity/lastNonInteractiveSignInDateTime le $Lookup)&`$select=id,UserPrincipalName,signInActivity,mail,userType,accountEnabled,assignedLicenses" -scope 'https://graph.microsoft.com/.default' -tenantid $TenantFilter | Where-Object { $_.assignedLicenses.skuId -ne $null }
18+
$GraphRequest = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users?`$filter=(signInActivity/lastNonInteractiveSignInDateTime le $Lookup)&`$select=id,UserPrincipalName,signInActivity,mail,userType,accountEnabled,assignedLicenses" -scope 'https://graph.microsoft.com/.default' -tenantid $TenantFilter |
19+
Where-Object { $null -ne $_.assignedLicenses.skuId }
20+
21+
# true = only active users
22+
if ($InputValue -eq $true) { $GraphRequest = $GraphRequest | Where-Object { $_.accountEnabled -eq $true } }
1923
$AlertData = foreach ($user in $GraphRequest) {
2024
$Message = 'User {0} has been inactive for 90 days, but still has a license assigned.' -f $user.UserPrincipalName
21-
$user | Select-Object -Property userPrincipalname, signInActivity, @{Name = 'Message'; Expression = { $Message } }
25+
$user | Select-Object -Property UserPrincipalName, signInActivity, @{Name = 'Message'; Expression = { $Message } }
2226

2327
}
2428
Write-AlertTrace -cmdletName $MyInvocation.MyCommand -tenantFilter $TenantFilter -data $AlertData

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ function Get-CIPPAlertNewAppApproval {
1313
)
1414
try {
1515
$Approvals = New-GraphGetRequest -Uri "https://graph.microsoft.com/v1.0/identityGovernance/appConsent/appConsentRequests?`$filter=userConsentRequests/any (u:u/status eq 'InProgress')" -tenantid $TenantFilter
16-
if ($Approvals.count -gt 1) {
16+
if ($Approvals.count -gt 0) {
1717
$AlertData = "There are $($Approvals.count) App Approval(s) pending."
1818
Write-AlertTrace -cmdletName $MyInvocation.MyCommand -tenantFilter $TenantFilter -data $AlertData
1919
}

Modules/CIPPCore/Public/Authentication/Get-CIPPRolePermissions.ps1

+5-3
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,15 @@ function Get-CIPPRolePermissions {
1818
$Role = Get-CIPPAzDataTableEntity @Table -Filter $Filter
1919
if ($Role) {
2020
$Permissions = $Role.Permissions | ConvertFrom-Json
21+
$AllowedTenants = if ($Role.AllowedTenants) { $Role.AllowedTenants | ConvertFrom-Json } else { @() }
22+
$BlockedTenants = if ($Role.BlockedTenants) { $Role.BlockedTenants | ConvertFrom-Json } else { @() }
2123
[PSCustomObject]@{
2224
Role = $Role.RowKey
2325
Permissions = $Permissions.PSObject.Properties.Value
24-
AllowedTenants = if ($Role.AllowedTenants) { $Role.AllowedTenants | ConvertFrom-Json } else { @() }
25-
BlockedTenants = if ($Role.BlockedTenants) { $Role.BlockedTenants | ConvertFrom-Json } else { @() }
26+
AllowedTenants = @($AllowedTenants)
27+
BlockedTenants = @($BlockedTenants)
2628
}
2729
} else {
2830
throw "Role $RoleName not found."
2931
}
30-
}
32+
}

Modules/CIPPCore/Public/Authentication/Test-CIPPAccess.ps1

+3-3
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,8 @@ function Test-CIPPAccess {
6969
if ($PermissionsFound) {
7070
if ($TenantList.IsPresent) {
7171
$LimitedTenantList = foreach ($Permission in $PermissionSet) {
72-
if (($Permission.AllowedTenants | Measure-Object).Count -eq 0 -and ($Permission.BlockedTenants | Measure-Object).Count -eq 0) {
73-
return @('AllTenants')
72+
if ((($Permission.AllowedTenants | Measure-Object).Count -eq 0 -or $Permission.AllowedTenants -contains 'AllTenants') -and (($Permission.BlockedTenants | Measure-Object).Count -eq 0)) {
73+
@('AllTenants')
7474
} else {
7575
if ($Permission.AllowedTenants -contains 'AllTenants') {
7676
$Permission.AllowedTenants = $Tenants.customerId
@@ -135,4 +135,4 @@ function Test-CIPPAccess {
135135
} else {
136136
return $true
137137
}
138-
}
138+
}

Modules/CIPPCore/Public/Entrypoints/Activity Triggers/BPA/Push-BPACollectData.ps1

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ function Push-BPACollectData {
2121
$Table = Get-CippTable -tablename 'cachebpav2'
2222
$Rerun = Test-CIPPRerun -Type 'BPA' -Tenant $TenantName.defaultDomainName -API $Item.Template
2323
if ($Rerun) {
24-
Write-Host 'Detected rerun. Exiting cleanly'
24+
Write-Host 'Detected rerun for BPA. Exiting cleanly'
2525
exit 0
2626
}
2727
Write-Host "Working on BPA for $($TenantName.defaultDomainName) with GUID $($TenantName.customerId) - Report ID $($Item.Template)"

Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-ListMailboxRulesQueue.ps1

+5-5
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ function Push-ListMailboxRulesQueue {
2121
}
2222
}
2323
if (($Rules | Measure-Object).Count -gt 0) {
24-
foreach ($Rule in $Rules) {
25-
$GraphRequest = [PSCustomObject]@{
24+
$GraphRequest = foreach ($Rule in $Rules) {
25+
[PSCustomObject]@{
2626
Rules = [string]($Rule | ConvertTo-Json)
2727
RowKey = [string](New-Guid).guid
2828
Tenant = [string]$domainName
@@ -31,9 +31,9 @@ function Push-ListMailboxRulesQueue {
3131

3232
}
3333
} else {
34-
$Rules = @{
35-
Name = 'No rules found'
36-
} | ConvertTo-Json
34+
$Rules = @(@{
35+
Name = 'No rules found'
36+
}) | ConvertTo-Json
3737
$GraphRequest = [PSCustomObject]@{
3838
Rules = [string]$Rules
3939
RowKey = [string]$domainName

0 commit comments

Comments
 (0)