Skip to content

Commit c7de828

Browse files
updates to new sam wizard
1 parent 0695179 commit c7de828

File tree

5 files changed

+163
-15
lines changed

5 files changed

+163
-15
lines changed

Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Setup/Invoke-ExecCreateSAMApp.ps1

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,28 +16,27 @@ Function Invoke-ExecCreateSAMApp {
1616
try {
1717
$Token = $Request.body
1818
if ($Token) {
19-
$URL = ($Request.headers.'x-ms-original-url').split('?') | Select-Object -First 1
19+
$URL = ($Request.headers.'x-ms-original-url').split('/api') | Select-Object -First 1
2020
$TenantId = (Invoke-RestMethod 'https://graph.microsoft.com/v1.0/organization' -Headers @{ authorization = "Bearer $($Token.access_token)" } -Method GET -ContentType 'application/json').value.id
2121
#Find Existing app registration
2222
$AppId = (Invoke-RestMethod 'https://graph.microsoft.com/v1.0/applications' -Headers @{ authorization = "Bearer $($Token.access_token)" } -Method GET -ContentType 'application/json' -Body "{ `"filter`": `"displayName eq 'CIPP-SAM'`" }").value | Select-Object -Last 1
2323
#Check if the appId has the redirect URI, if not, add it.
2424
if ($AppId) {
2525
Write-Host "Found existing app: $($AppId.id). Reusing."
2626
$state = 'updated'
27-
if ($AppId.web.redirectUris -notcontains $URL) {
28-
$ModuleBase = Get-Module -Name CIPPCore | Select-Object -ExpandProperty ModuleBase
29-
$SamManifestFile = Get-Item (Join-Path $ModuleBase 'Public\SAMManifest.json')
30-
$app = Get-Content $SamManifestFile.FullName | ConvertFrom-Json
31-
$App.web.redirectUris = @($App.web.redirectUris + $URL) #change to SPA URL.
32-
$app = $app | ConvertTo-Json -Depth 15
33-
Invoke-RestMethod "https://graph.microsoft.com/v1.0/applications/$($AppId.id)" -Headers @{ authorization = "Bearer $($Token.access_token)" } -Method PATCH -Body $app -ContentType 'application/json'
34-
}
27+
#remove the entire web object from the app registration
28+
$ModuleBase = Get-Module -Name CIPPCore | Select-Object -ExpandProperty ModuleBase
29+
$SamManifestFile = Get-Item (Join-Path $ModuleBase 'Public\SAMManifest.json')
30+
$app = Get-Content $SamManifestFile.FullName | ConvertFrom-Json
31+
$app.web.redirectUris = @("$($url)/authredirect")
32+
$app = ConvertTo-Json -Depth 15 -Compress -InputObject $app
33+
Invoke-RestMethod "https://graph.microsoft.com/v1.0/applications/$($AppId.id)" -Headers @{ authorization = "Bearer $($Token.access_token)" } -Method PATCH -Body $app -ContentType 'application/json'
3534
} else {
3635
$state = 'created'
3736
$ModuleBase = Get-Module -Name CIPPCore | Select-Object -ExpandProperty ModuleBase
3837
$SamManifestFile = Get-Item (Join-Path $ModuleBase 'Public\SAMManifest.json')
3938
$app = Get-Content $SamManifestFile.FullName | ConvertFrom-Json
40-
$App.web.redirectUris = @($App.web.redirectUris + $URL) #change to SPA URL.
39+
$app.web.redirectUris = @("$($url)/authredirect")
4140
$app = $app | ConvertTo-Json -Depth 15
4241
$AppId = (Invoke-RestMethod 'https://graph.microsoft.com/v1.0/applications' -Headers @{ authorization = "Bearer $($Token.access_token)" } -Method POST -Body $app -ContentType 'application/json')
4342
$attempt = 0
@@ -76,17 +75,17 @@ Function Invoke-ExecCreateSAMApp {
7675
if ($env:AzureWebJobsStorage -eq 'UseDevelopmentStorage=true') {
7776
$DevSecretsTable = Get-CIPPTable -tablename 'DevSecrets'
7877
$Secret = Get-CIPPAzDataTableEntity @DevSecretsTable -Filter "PartitionKey eq 'Secret' and RowKey eq 'Secret'"
79-
$Secret.TenantId = $TenantId
80-
$Secret.ApplicationId = $AppId.appId
81-
$Secret.ApplicationSecret = $AppPassword
78+
$Secret | Add-Member -MemberType NoteProperty -Name 'tenantid' -Value $TenantId -Force
79+
$Secret | Add-Member -MemberType NoteProperty -Name 'applicationid' -Value $AppId.appId -Force
80+
$Secret | Add-Member -MemberType NoteProperty -Name 'applicationsecret' -Value $AppPassword -Force
8281
Add-CIPPAzDataTableEntity @DevSecretsTable -Entity $Secret -Force
8382
Write-Information ($Secret | ConvertTo-Json -Depth 5)
8483
} else {
8584
Set-AzKeyVaultSecret -VaultName $kv -Name 'tenantid' -SecretValue (ConvertTo-SecureString -String $TenantId -AsPlainText -Force)
8685
Set-AzKeyVaultSecret -VaultName $kv -Name 'applicationid' -SecretValue (ConvertTo-SecureString -String $Appid.appId -AsPlainText -Force)
8786
Set-AzKeyVaultSecret -VaultName $kv -Name 'applicationsecret' -SecretValue (ConvertTo-SecureString -String $AppPassword -AsPlainText -Force)
8887
}
89-
$Results = @{'message' = "Succesfully $state the application registration. The application ID is $($AppId.id). You may continue to the next step."; severity = 'success' }
88+
$Results = @{'message' = "Succesfully $state the application registration. The application ID is $($AppId.appid). You may continue to the next step."; severity = 'success' }
9089
}
9190

9291
} catch {
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
using namespace System.Net
2+
3+
Function Invoke-ExecTokenExchange {
4+
<#
5+
.FUNCTIONALITY
6+
Entrypoint,AnyTenant
7+
.ROLE
8+
CIPP.AppSettings.ReadWrite
9+
#>
10+
[CmdletBinding()]
11+
param($Request, $TriggerMetadata)
12+
13+
# Get the key vault name
14+
$KV = $env:WEBSITE_DEPLOYMENT_ID
15+
$APIName = $Request.Params.CIPPEndpoint
16+
17+
try {
18+
if (!$Request.Body) {
19+
Write-LogMessage -API $APIName -message 'Request body is missing' -Sev 'Error'
20+
throw 'Request body is missing'
21+
}
22+
23+
$TokenRequest = $Request.Body.tokenRequest
24+
$TokenUrl = $Request.Body.tokenUrl
25+
$TenantId = $Request.Body.tenantId
26+
27+
if (!$TokenRequest -or !$TokenUrl) {
28+
Write-LogMessage -API $APIName -message 'Missing required parameters: tokenRequest or tokenUrl' -Sev 'Error'
29+
throw 'Missing required parameters: tokenRequest or tokenUrl'
30+
}
31+
32+
Write-LogMessage -API $APIName -message "Making token request to $TokenUrl" -Sev 'Info'
33+
34+
# Make sure we get the latest authentication
35+
$auth = Get-CIPPAuthentication
36+
37+
if ($env:AzureWebJobsStorage -eq 'UseDevelopmentStorage=true') {
38+
$DevSecretsTable = Get-CIPPTable -tablename 'DevSecrets'
39+
$Secret = Get-CIPPAzDataTableEntity @DevSecretsTable -Filter "PartitionKey eq 'Secret' and RowKey eq 'Secret'"
40+
$ClientSecret = $Secret.applicationsecret
41+
Write-LogMessage -API $APIName -message 'Retrieved client secret from development secrets' -Sev 'Info'
42+
} else {
43+
try {
44+
$ClientSecret = (Get-AzKeyVaultSecret -VaultName $kv -Name 'applicationsecret' -AsPlainText).SecretValue
45+
Write-LogMessage -API $APIName -message 'Retrieved client secret from key vault' -Sev 'Info'
46+
} catch {
47+
Write-LogMessage -API $APIName -message "Failed to retrieve client secret: $($_.Exception.Message)" -Sev 'Error'
48+
throw "Failed to retrieve client secret: $($_.Exception.Message)"
49+
}
50+
}
51+
52+
if (!$ClientSecret) {
53+
Write-LogMessage -API $APIName -message 'Client secret is empty or null' -Sev 'Error'
54+
throw 'Client secret is empty or null'
55+
}
56+
57+
# Convert token request to form data and add client secret
58+
$FormData = @{}
59+
foreach ($key in $TokenRequest.PSObject.Properties.Name) {
60+
$FormData[$key] = $TokenRequest.$key
61+
}
62+
63+
# Add client_secret to the form data if not already present
64+
if (!$FormData.ContainsKey('client_secret')) {
65+
$FormData['client_secret'] = $ClientSecret
66+
}
67+
68+
Write-Host "Posting this data: $($FormData | ConvertTo-Json -Depth 15)"
69+
$Results = Invoke-RestMethod -Uri $TokenUrl -Method Post -Body $FormData -ContentType 'application/x-www-form-urlencoded' -ErrorAction Stop -SkipHttpErrorCheck
70+
} catch {
71+
$ErrorMessage = $_.Exception
72+
$Results = @{
73+
error = 'server_error'
74+
error_description = "Token exchange failed: $ErrorMessage"
75+
}
76+
}
77+
if ($Results.error) {
78+
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
79+
StatusCode = [HttpStatusCode]::BadRequest
80+
Body = $Results
81+
Headers = @{'Content-Type' = 'application/json' }
82+
})
83+
} else {
84+
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
85+
StatusCode = [HttpStatusCode]::OK
86+
Body = $Results
87+
Headers = @{'Content-Type' = 'application/json' }
88+
})
89+
}
90+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
using namespace System.Net
2+
3+
Function Invoke-ExecUpdateRefreshToken {
4+
<#
5+
.FUNCTIONALITY
6+
Entrypoint,AnyTenant
7+
.ROLE
8+
CIPP.AppSettings.ReadWrite.
9+
#>
10+
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingConvertToSecureStringWithPlainText', '')]
11+
[CmdletBinding()]
12+
param($Request, $TriggerMetadata)
13+
14+
$KV = $env:WEBSITE_DEPLOYMENT_ID
15+
16+
try {
17+
# Handle refresh token update
18+
#make sure we get the latest authentication:
19+
$auth = Get-CIPPAuthentication
20+
if ($env:AzureWebJobsStorage -eq 'UseDevelopmentStorage=true') {
21+
$DevSecretsTable = Get-CIPPTable -tablename 'DevSecrets'
22+
$Secret = Get-CIPPAzDataTableEntity @DevSecretsTable -Filter "PartitionKey eq 'Secret' and RowKey eq 'Secret'"
23+
if ($env:ApplicationId -eq $Request.body.tenantId) {
24+
$Secret.RefreshToken = $Request.body.RefreshToken
25+
} else {
26+
Write-Host "$($env:Applicationid) does not match $($Request.body.tenantId)"
27+
$secret | Add-Member -MemberType NoteProperty -Name $($Request.body.tenantId) -Value $Request.body.refreshtoken -Force
28+
}
29+
Add-CIPPAzDataTableEntity @DevSecretsTable -Entity $Secret -Force
30+
} else {
31+
if ($env:ApplicationId -eq $Request.body.tenantId) {
32+
Set-AzKeyVaultSecret -VaultName $kv -Name 'RefreshToken' -SecretValue (ConvertTo-SecureString -String $Request.body.refreshtoken -AsPlainText -Force)
33+
} else {
34+
Set-AzKeyVaultSecret -VaultName $kv -Name $Request.body.tenantId -SecretValue (ConvertTo-SecureString -String $Request.body.refreshtoken -AsPlainText -Force)
35+
}
36+
}
37+
$InstanceId = Start-UpdatePermissionsOrchestrator #start the CPV refresh immediately while wizard still runs.
38+
$Results = @{'message' = "Successfully updated your stored authentication for $($request.body.tenantId)."; severity = 'success' }
39+
} catch {
40+
$Results = [pscustomobject]@{'Results' = "Failed. $($_.InvocationInfo.ScriptLineNumber): $($_.Exception.message)"; severity = 'failed' }
41+
}
42+
43+
# Associate values to output bindings by calling 'Push-OutputBinding'.
44+
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
45+
StatusCode = [HttpStatusCode]::OK
46+
Body = $Results
47+
})
48+
49+
}

Modules/CIPPCore/Public/Entrypoints/Invoke-ExecListAppId.ps1

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,16 @@ Function Invoke-ExecListAppId {
1414
$Headers = $Request.Headers
1515
Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug'
1616
$ResponseURL = "$(($Request.headers.'x-ms-original-url').replace('/api/ExecListAppId','/api/ExecSAMSetup'))"
17-
17+
#make sure we get the very latest version of the appid from kv:
18+
if ($env:AzureWebJobsStorage -eq 'UseDevelopmentStorage=true') {
19+
$DevSecretsTable = Get-CIPPTable -tablename 'DevSecrets'
20+
$Secret = Get-CIPPAzDataTableEntity @DevSecretsTable -Filter "PartitionKey eq 'Secret' and RowKey eq 'Secret'"
21+
$env:ApplicationID = $Secret.ApplicationID
22+
$env:TenantID = $Secret.TenantID
23+
} else {
24+
$env:ApplicationID = (Get-AzKeyVaultSecret -AsPlainText -VaultName $env:WEBSITE_DEPLOYMENT_ID -Name 'ApplicationID').SecretValueText
25+
$env:TenantID = (Get-AzKeyVaultSecret -AsPlainText -VaultName $env:WEBSITE_DEPLOYMENT_ID -Name 'TenantID').SecretValueText
26+
}
1827
$Results = @{
1928
applicationId = $env:ApplicationID
2029
tenantId = $env:TenantID

Modules/CIPPCore/Public/Get-CIPPAuthentication.ps1

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ function Get-CIPPAuthentication {
1818
Set-Item -Path env:$Var -Value $Secret.$Var -Force -ErrorAction Stop
1919
}
2020
}
21+
Write-Host "Got secrets from dev storage. ApplicationID: $env:ApplicationID"
2122
} else {
2223
Write-Information 'Connecting to Azure'
2324
Connect-AzAccount -Identity

0 commit comments

Comments
 (0)