Skip to content

Commit f3ae71b

Browse files
authored
Merge pull request #960 from KelvinTegelaar/dev
[pull] dev from KelvinTegelaar:dev
2 parents ea2fe21 + 12d93fe commit f3ae71b

3 files changed

Lines changed: 48 additions & 17 deletions

File tree

.github/workflows/upload_dev.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ jobs:
2121
# Create version.json with version and commit hash
2222
- name: Create version.json
2323
run: |
24-
VERSION=$(cat version_latest.txt | tr -d '[:space:]')
24+
VERSION=$(cat ./Config/version_latest.txt | tr -d '[:space:]')
2525
SHORT_SHA="${GITHUB_SHA::7}"
2626
echo "{\"version\": \"${VERSION}\", \"commit\": \"${SHORT_SHA}\"}" > version.json
2727

Modules/CIPPCore/Public/Authentication/New-CIPPAPIConfig.ps1

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,8 @@ function New-CIPPAPIConfig {
7676

7777
Write-Information 'Creating password'
7878
$Step = 'Creating Application Password'
79-
$AppManagementPolicy = New-GraphGetRequest -uri "https://graph.microsoft.com/v1.0/policies/defaultAppManagementPolicy" -AsApp $true -NoAuthCheck $true
80-
$PasswordExpirationPolicy = $AppManagementPolicy.applicationRestrictions.passwordcredentials |
79+
$AppManagementPolicy = New-GraphGetRequest -uri 'https://graph.microsoft.com/v1.0/policies/defaultAppManagementPolicy' -AsApp $true -NoAuthCheck $true
80+
$PasswordExpirationPolicy = $AppManagementPolicy.applicationRestrictions.passwordcredentials |
8181
Where-Object { $_.restrictionType -eq 'passwordLifetime' }
8282
$PasswordBody = $null
8383
if (-not ($PasswordExpirationPolicy.state -eq 'disabled' -or $null -eq $PasswordExpirationPolicy.state)) {
@@ -93,7 +93,9 @@ function New-CIPPAPIConfig {
9393
$APIPassword = New-GraphPOSTRequest -uri "https://graph.microsoft.com/v1.0/applications/$($APIApp.id)/addPassword" -AsApp $true -NoAuthCheck $true -type POST -body $PasswordBody -maxRetries 3
9494
break
9595
} catch {
96+
$ExceptionMessage = $_.Exception.Message
9697
$IsNotReplicatedYet = $_.Exception.Message -match "Resource '.*' does not exist or one of its queried reference-property objects are not present"
98+
$IsCredentialPolicyBlocked = $ExceptionMessage -match 'Credential type not allowed as per assigned policy'
9799
if ($IsNotReplicatedYet -and $Attempt -lt 6) {
98100
$DelaySeconds = 3
99101
Write-Information "Application object not yet replicated for addPassword (attempt $Attempt of 6). Retrying in $DelaySeconds second(s)."
@@ -105,6 +107,14 @@ function New-CIPPAPIConfig {
105107
}
106108
continue
107109
}
110+
111+
if ($IsCredentialPolicyBlocked -and $Attempt -lt 6) {
112+
$DelaySeconds = [Math]::Min(30, 5 * $Attempt)
113+
Write-Information "Credential policy still blocks addPassword (attempt $Attempt of 6). Waiting for policy propagation and retrying in $DelaySeconds second(s)."
114+
Start-Sleep -Seconds $DelaySeconds
115+
continue
116+
}
117+
108118
throw
109119
}
110120
}
@@ -167,7 +177,7 @@ function New-CIPPAPIConfig {
167177
} catch {
168178
if ($Attempt -lt 6) {
169179
Start-Sleep -Seconds 3
170-
Write-Information "Retrying service principal creation for AppId $($APIApp.appId) (attempt $Attempt of 6) after failure: $($_.Exception.Message)"
180+
Write-Information "Retrying service principal creation for AppId $($APIApp.appId) (attempt $Attempt of 6) after failure: $($_.Exception.Message)"
171181
continue
172182
}
173183
throw

Modules/CIPPHTTP/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecApiClient.ps1

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ function Invoke-ExecApiClient {
2929
}
3030
}
3131
'AddUpdate' {
32+
$Results = [System.Collections.Generic.List[object]]::new()
3233
if ($Request.Body.ClientId -or $Request.Body.AppName) {
3334
$ClientId = $Request.Body.ClientId.value ?? $Request.Body.ClientId
3435
$AddUpdateSuccess = $false
@@ -75,21 +76,25 @@ function Invoke-ExecApiClient {
7576
}
7677
}
7778

79+
$IPValidationErrors = [System.Collections.Generic.List[string]]::new()
7880
if ($Request.Body.IpRange.value) {
7981
$IpRange = [System.Collections.Generic.List[string]]::new()
8082
$regexPattern = '^(?:(?:[0-9]{1,3}\.){3}[0-9]{1,3}(?:/\d{1,2})?|(?:[0-9A-Fa-f]{1,4}:){1,7}[0-9A-Fa-f]{1,4}(?:/\d{1,3})?)$'
8183
foreach ($IP in @($Request.Body.IPRange.value)) {
84+
$IP = $IP.Trim()
8285
if ($IP -match $regexPattern) {
8386
$IpRange.Add($IP)
87+
} else {
88+
$IPValidationErrors.Add("'$IP' is not a valid IP address or CIDR range.")
8489
}
8590
}
8691
} else {
8792
$IpRange = @()
8893
}
8994

9095
if (!$AddUpdateSuccess) {
91-
$Body = @{
92-
Results = @($AddedText)
96+
if ($AddedText) {
97+
$Results.Add($AddedText)
9398
}
9499
} else {
95100
$ExistingClient = Get-CIPPAzDataTableEntity @Table -Filter "RowKey eq '$($ClientId)'"
@@ -100,13 +105,13 @@ function Invoke-ExecApiClient {
100105
$Client.Enabled = $Request.Body.Enabled ?? $false
101106
Write-LogMessage -headers $Request.Headers -API 'ExecApiClient' -message "Updated API client $($Request.Body.ClientId)" -Sev 'Info'
102107
if ($APIConfig.ApplicationSecret) {
103-
$Results = @{
104-
resultText = "API client updated and application secret reset for '$($Client.AppName)'. Use the Copy to Clipboard button to retrieve the new secret."
105-
copyField = $APIConfig.ApplicationSecret
106-
state = 'success'
107-
}
108+
$Results.Add(@{
109+
resultText = "API client updated and application secret reset for '$($Client.AppName)'. Use the Copy to Clipboard button to retrieve the new secret."
110+
copyField = $APIConfig.ApplicationSecret
111+
state = 'success'
112+
})
108113
} else {
109-
$Results = 'API client updated'
114+
$Results.Add('API client updated')
110115
}
111116
} else {
112117
$Client = @{
@@ -117,14 +122,30 @@ function Invoke-ExecApiClient {
117122
'IPRange' = "$(@($IpRange) | ConvertTo-Json -Compress)"
118123
'Enabled' = $Request.Body.Enabled ?? $false
119124
}
120-
$Results = @{
121-
resultText = "API Client created with the name '$($Client.AppName)'. Use the Copy to Clipboard button to retrieve the secret."
122-
copyField = $APIConfig.ApplicationSecret
123-
state = 'success'
124-
}
125+
$Results.Add(@{
126+
resultText = "API Client created with the name '$($Client.AppName)'. Use the Copy to Clipboard button to retrieve the secret."
127+
copyField = $APIConfig.ApplicationSecret
128+
state = 'success'
129+
})
125130
}
126131

127132
Add-CIPPAzDataTableEntity @Table -Entity $Client -Force | Out-Null
133+
}
134+
135+
if ($IPValidationErrors.Count -gt 0) {
136+
foreach ($ValidationError in $IPValidationErrors) {
137+
$Results.Add(@{
138+
resultText = $ValidationError
139+
state = 'warning'
140+
})
141+
}
142+
}
143+
144+
if (!$AddUpdateSuccess) {
145+
$Body = @{
146+
Results = @($Results)
147+
}
148+
} else {
128149
$Body = @($Results)
129150
}
130151
}

0 commit comments

Comments
 (0)