Skip to content

Commit

Permalink
Merge pull request #40 from KelvinTegelaar/master
Browse files Browse the repository at this point in the history
[pull] master from KelvinTegelaar:master
  • Loading branch information
pull[bot] authored Jul 12, 2024
2 parents 3d142dd + af19f65 commit 717f460
Show file tree
Hide file tree
Showing 112 changed files with 2,352 additions and 2,841 deletions.
8 changes: 4 additions & 4 deletions Modules/CIPPCore/Public/Add-CIPPScheduledTask.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,19 @@ function Add-CIPPScheduledTask {
$propertiesToCheck = @('Webhook', 'Email', 'PSA')
$PostExecution = ($propertiesToCheck | Where-Object { $task.PostExecution.$_ -eq $true }) -join ','
$Parameters = [System.Collections.Hashtable]@{}
foreach ($Key in $task.Parameters.Keys) {
foreach ($Key in $task.Parameters.PSObject.Properties.Name) {
$Param = $task.Parameters.$Key
if ($Param.Key) {
if ($Param -is [System.Collections.IDictionary]) {
$ht = @{}
foreach ($p in $Param) {
Write-Host $p.Key
foreach ($p in $Param.GetEnumerator()) {
$ht[$p.Key] = $p.Value
}
$Parameters[$Key] = [PSCustomObject]$ht
} else {
$Parameters[$Key] = $Param
}
}

$Parameters = ($Parameters | ConvertTo-Json -Depth 10 -Compress)
$AdditionalProperties = [System.Collections.Hashtable]@{}
foreach ($Prop in $task.AdditionalProperties) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ function Push-GetTenantDomains {
Param($Item)
$DomainTable = Get-CippTable -tablename 'Domains'
$Filter = "PartitionKey eq 'TenantDomains' and TenantGUID eq '{0}'" -f $Item.TenantGUID
$Domains = Get-CIPPAzDataTableEntity @DomainTable -Filter $Filter -Property RowKey | Select-Object RowKey, @{n = 'FunctionName'; exp = { 'DomainAnalyserDomain' } }
$Domains = Get-CIPPAzDataTableEntity @DomainTable -Filter $Filter -Property PartitionKey, RowKey | Select-Object RowKey, @{n = 'FunctionName'; exp = { 'DomainAnalyserDomain' } }
return @($Domains)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ function Push-GetPendingWebhooks {
#>
Param($Item)
$Table = Get-CIPPTable -TableName WebhookIncoming
$Webhooks = Get-CIPPAzDataTableEntity @Table -Property RowKey, FunctionName -First 10000
$Webhooks = Get-CIPPAzDataTableEntity @Table -Property PartitionKey, RowKey, FunctionName -First 10000
$WebhookCount = ($Webhooks | Measure-Object).Count
$Message = 'Processing {0} webhooks' -f $WebhookCount
Write-LogMessage -API 'Webhooks' -message $Message -sev Info
return $Webhooks
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ function Invoke-ExecDurableFunctions {
if ($Request.Query.PartitionKey) {
$HistoryTable = Get-CippTable -TableName ('{0}History' -f $FunctionName)
$Filter = "PartitionKey eq '{0}'" -f $Request.Query.PartitionKey
$History = Get-CippAzDataTableEntity @HistoryTable -Filter $Filter -Property RowKey, Timestamp, EventType, Name, IsPlayed, OrchestrationStatus | Select-Object * -ExcludeProperty ETag
$History = Get-CippAzDataTableEntity @HistoryTable -Filter $Filter -Property PartitionKey, RowKey, Timestamp, EventType, Name, IsPlayed, OrchestrationStatus | Select-Object * -ExcludeProperty ETag

$Body = [PSCustomObject]@{
Results = @($History)
Expand Down Expand Up @@ -173,4 +173,4 @@ function Invoke-ExecDurableFunctions {
StatusCode = [HttpStatusCode]::OK
Body = $Body
})
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ Function Invoke-ExecExtensionsConfig {
}
}
if ($Request.Body.$APIKey.PSObject.Properties -notcontains 'APIKey') {
$Request.Body.$APIKey | Add-Member -MemberType NoteProperty -Name APIKey -Value 'SentToKeyVault' -PassThru
$Request.Body.$APIKey | Add-Member -MemberType NoteProperty -Name APIKey -Value 'SentToKeyVault'
} else {
$Request.Body.$APIKey.APIKey = 'SentToKeyVault'
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ Function Invoke-AddGroupTemplate {
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)

$APIName = $TriggerMetadata.FunctionName
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'

Expand All @@ -36,8 +35,7 @@ Function Invoke-AddGroupTemplate {
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Created Group template named $($Request.body.displayname) with GUID $GUID" -Sev 'Debug'

$body = [pscustomobject]@{'Results' = 'Successfully added template' }
}
catch {
} catch {
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Group Template Creation failed: $($_.Exception.Message)" -Sev 'Error'
$body = [pscustomobject]@{'Results' = "Group Template Creation failed: $($_.Exception.Message)" }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@ Function Invoke-ExecClrImmId {
Try {
$TenantFilter = $Request.Query.TenantFilter
$UserID = $Request.Query.ID
$Body = [pscustomobject] @{
onPremisesImmutableId = $null
} | ConvertTo-Json
$GraphRequest = New-GraphPostRequest -uri "https://graph.microsoft.com/beta/users/$UserID" -tenantid $TenantFilter -type PATCH -body $Body
$Body = [pscustomobject]@{ onPremisesImmutableId = $null }
$Body = ConvertTo-Json -InputObject $Body -Depth 5 -Compress
$null = New-GraphPostRequest -uri "https://graph.microsoft.com/beta/users/$UserID" -tenantid $TenantFilter -type PATCH -body $Body
$Results = [pscustomobject]@{'Results' = 'Successfully Cleared ImmutableId' }
} catch {
$Results = [pscustomobject]@{'Results' = "Failed. $_.Exception.Message"; colour = 'danger' }
$ErrorMessage = Get-NormalizedError -Message $_.Exception
$Results = [pscustomobject]@{'Results' = "Failed. $ErrorMessage"; colour = 'danger' }
$_.Exception
}

Expand All @@ -35,5 +35,4 @@ Function Invoke-ExecClrImmId {
StatusCode = [HttpStatusCode]::OK
Body = $Results
})

}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ Function Invoke-ExecJITAdmin {
param($Request, $TriggerMetadata)

$APIName = 'ExecJITAdmin'
Write-LogMessage -user $Request.Headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'
$User = $Request.Headers.'x-ms-client-principal'

Write-LogMessage -user $User -API $APINAME -message 'Accessed this API' -Sev 'Debug'

if ($Request.Query.Action -eq 'List') {
$Schema = Get-CIPPSchemaExtensions | Where-Object { $_.id -match '_cippUser' }
Expand Down Expand Up @@ -61,14 +63,14 @@ Function Invoke-ExecJITAdmin {
if ($Request.Body.UserId -match '^[a-f0-9]{8}-([a-f0-9]{4}-){3}[a-f0-9]{12}$') {
$Username = (New-GraphGetRequest -uri "https://graph.microsoft.com/v1.0/users/$($Request.Body.UserId)" -tenantid $Request.Body.TenantFilter).userPrincipalName
}
Write-LogMessage -user $Request.Headers.'x-ms-client-principal' -API $APINAME -message "Executing JIT Admin for $Username" -Sev 'Info'
Write-LogMessage -user $User -API $APINAME -message "Executing JIT Admin for $Username" -Sev 'Info'

$Start = ([System.DateTimeOffset]::FromUnixTimeSeconds($Request.Body.StartDate)).DateTime.ToLocalTime()
$Expiration = ([System.DateTimeOffset]::FromUnixTimeSeconds($Request.Body.EndDate)).DateTime.ToLocalTime()
$Results = [System.Collections.Generic.List[string]]::new()

if ($Request.Body.useraction -eq 'create') {
Write-LogMessage -user $Request.Headers.'x-ms-client-principal' -API $APINAME -message "Creating JIT Admin user $($Request.Body.UserPrincipalName)" -Sev 'Info'
if ($Request.Body.useraction -eq 'Create') {
Write-LogMessage -user $User -API $APINAME -message "Creating JIT Admin user $($Request.Body.UserPrincipalName)" -Sev 'Info'
Write-Information "Creating JIT Admin user $($Request.Body.UserPrincipalName)"
$JITAdmin = @{
User = @{
Expand All @@ -86,7 +88,7 @@ Function Invoke-ExecJITAdmin {
if (!$Request.Body.UseTAP) {
$Results.Add("Password: $($CreateResult.password)")
}
$Results.Add("JIT Expires: $($Expiration)")
$Results.Add("JIT Admin Expires: $($Expiration)")
Start-Sleep -Seconds 1
}

Expand All @@ -101,14 +103,27 @@ Function Invoke-ExecJITAdmin {
$TapBody = '{}'
}
Write-Information "https://graph.microsoft.com/beta/users/$Username/authentication/temporaryAccessPassMethods"
$TapRequest = New-GraphPostRequest -uri "https://graph.microsoft.com/beta/users/$($Username)/authentication/temporaryAccessPassMethods" -tenantid $Request.Body.TenantFilter -type POST -body $TapBody
# Retry creating the TAP up to 5 times, since it can fail due to the user not being fully created yet
$Retries = 0
do {
try {
$TapRequest = New-GraphPostRequest -uri "https://graph.microsoft.com/beta/users/$($Username)/authentication/temporaryAccessPassMethods" -tenantid $Request.Body.TenantFilter -type POST -body $TapBody
} catch {
Start-Sleep -Seconds 2
Write-Information 'ERROR: Failed to create TAP, retrying'
Write-Information ( ConvertTo-Json -Depth 5 -InputObject (Get-CippException -Exception $_))
}
$Retries++
} while ( $null -eq $TapRequest.temporaryAccessPass -and $Retries -le 5 )

$TempPass = $TapRequest.temporaryAccessPass
$PasswordExpiration = $TapRequest.LifetimeInMinutes

$PasswordLink = New-PwPushLink -Payload $TempPass
if ($PasswordLink) {
$Password = $PasswordLink
} else {
$Password = $TempPass
}
$Results.Add("Temporary Access Pass: $Password")
$Results.Add("This TAP is usable starting at $($TapRequest.startDateTime) UTC for the next $PasswordExpiration minutes")
Expand Down Expand Up @@ -147,7 +162,9 @@ Function Invoke-ExecJITAdmin {
}
}
Add-CIPPScheduledTask -Task $TaskBody -hidden $false
Set-CIPPUserJITAdminProperties -TenantFilter $Request.Body.TenantFilter -UserId $Request.Body.UserId -Expiration $Expiration
if ($Request.Body.useraction -ne 'Create') {
Set-CIPPUserJITAdminProperties -TenantFilter $Request.Body.TenantFilter -UserId $Request.Body.UserId -Expiration $Expiration
}
$Results.Add("Scheduling JIT Admin enable task for $Username")
} else {
$Results.Add("Executing JIT Admin enable task for $Username")
Expand Down Expand Up @@ -176,7 +193,7 @@ Function Invoke-ExecJITAdmin {
}
ScheduledTime = $Request.Body.EndDate
}
Add-CIPPScheduledTask -Task $DisableTaskBody -hidden $false
$null = Add-CIPPScheduledTask -Task $DisableTaskBody -hidden $false
$Results.Add("Scheduling JIT Admin $($Request.Body.ExpireAction) task for $Username")
$Body = @{
Results = @($Results)
Expand Down
2 changes: 1 addition & 1 deletion Modules/CIPPCore/Public/Entrypoints/Invoke-ListDomains.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ Function Invoke-ListDomains {
$TenantFilter = $Request.Query.TenantFilter

try {
$GraphRequest = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/domains' -tenantid $TenantFilter | Select-Object id, isdefault, isinitial | Sort-Object isdefault
$GraphRequest = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/domains' -tenantid $TenantFilter | Select-Object id, isdefault, isinitial | Sort-Object isdefault -Descending
$StatusCode = [HttpStatusCode]::OK
} catch {
$ErrorMessage = Get-NormalizedError -Message $_.Exception.Message
Expand Down
54 changes: 31 additions & 23 deletions Modules/CIPPCore/Public/Get-CIPPAzDatatableEntity.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -17,47 +17,55 @@ function Get-CIPPAzDataTableEntity {
foreach ($entity in $Results) {
if ($entity.OriginalEntityId) {
$entityId = $entity.OriginalEntityId
if (-not $mergedResults.ContainsKey($entityId)) {
$mergedResults[$entityId] = @{
$partitionKey = $entity.PartitionKey
if (-not $mergedResults.ContainsKey($partitionKey)) {
$mergedResults[$partitionKey] = @{}
}
if (-not $mergedResults[$partitionKey].ContainsKey($entityId)) {
$mergedResults[$partitionKey][$entityId] = @{
Parts = New-Object 'System.Collections.ArrayList'
}
}
$mergedResults[$entityId]['Parts'].Add($entity) > $null
$mergedResults[$partitionKey][$entityId]['Parts'].Add($entity) > $null
} else {
$mergedResults[$entity.RowKey] = @{
$partitionKey = $entity.PartitionKey
if (-not $mergedResults.ContainsKey($partitionKey)) {
$mergedResults[$partitionKey] = @{}
}
$mergedResults[$partitionKey][$entity.RowKey] = @{
Entity = $entity
Parts = New-Object 'System.Collections.ArrayList'
}
}
}

# Second pass: Reassemble entities from parts
$finalResults = @()
foreach ($entityId in $mergedResults.Keys) {
$entityData = $mergedResults[$entityId]
if ($entityData.Parts.Count -gt 0) {
$fullEntity = [PSCustomObject]@{}
$parts = $entityData.Parts | Sort-Object PartIndex
foreach ($part in $parts) {
foreach ($key in $part.PSObject.Properties.Name) {
if ($key -notin @('OriginalEntityId', 'PartIndex', 'PartitionKey', 'RowKey', 'Timestamp')) {
if ($fullEntity.PSObject.Properties[$key]) {
$fullEntity | Add-Member -MemberType NoteProperty -Name $key -Value ($fullEntity.$key + $part.$key) -Force
} else {
$fullEntity | Add-Member -MemberType NoteProperty -Name $key -Value $part.$key
foreach ($partitionKey in $mergedResults.Keys) {
foreach ($entityId in $mergedResults[$partitionKey].Keys) {
$entityData = $mergedResults[$partitionKey][$entityId]
if ($entityData.Parts.Count -gt 0) {
$fullEntity = [PSCustomObject]@{}
$parts = $entityData.Parts | Sort-Object PartIndex
foreach ($part in $parts) {
foreach ($key in $part.PSObject.Properties.Name) {
if ($key -notin @('OriginalEntityId', 'PartIndex', 'PartitionKey', 'RowKey', 'Timestamp')) {
if ($fullEntity.PSObject.Properties[$key]) {
$fullEntity | Add-Member -MemberType NoteProperty -Name $key -Value ($fullEntity.$key + $part.$key) -Force
} else {
$fullEntity | Add-Member -MemberType NoteProperty -Name $key -Value $part.$key
}
}
}
}
$fullEntity | Add-Member -MemberType NoteProperty -Name 'PartitionKey' -Value $parts[0].PartitionKey -Force
$fullEntity | Add-Member -MemberType NoteProperty -Name 'RowKey' -Value $entityId -Force
$finalResults = $finalResults + @($fullEntity)
} else {
$finalResults = $finalResults + @($entityData.Entity)
}
$fullEntity | Add-Member -MemberType NoteProperty -Name 'PartitionKey' -Value $parts[0].PartitionKey -Force
$fullEntity | Add-Member -MemberType NoteProperty -Name 'RowKey' -Value $entityId -Force
$finalResults = $finalResults + @($fullEntity)
} else {
$finalResults = $finalResults + @($entityData.Entity)
}
}

# Third pass: Process split properties and remerge them
foreach ($entity in $finalResults) {
if ($entity.SplitOverProps) {
$splitInfoList = $entity.SplitOverProps | ConvertFrom-Json
Expand Down
3 changes: 2 additions & 1 deletion Modules/CIPPCore/Public/GraphHelper/New-ExoRequest.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,15 @@ function New-ExoRequest ($tenantid, $cmdlet, $cmdParams, $useSystemMailbox, $Anc
if ($cmdparams.anr) { $Anchor = $cmdparams.anr }
if ($cmdparams.User) { $Anchor = $cmdparams.User }
if ($cmdparams.mailbox) { $Anchor = $cmdparams.mailbox }
if ($cmdlet -in 'Set-AdminAuditLogConfig', 'Get-AdminAuditLogConfig', 'Enable-OrganizationCustomization', 'Get-OrganizationConfig') { $anchor = "UPN:SystemMailbox{8cc370d3-822a-4ab8-a926-bb94bd0641a9}@$($OnMicrosoft)" }
if (!$Anchor -or $useSystemMailbox) {
if (!$Tenant.initialDomainName -or $Tenant.initialDomainName -notlike '*onmicrosoft.com*') {
$OnMicrosoft = (New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/domains?$top=999' -tenantid $tenantid -NoAuthCheck $NoAuthCheck | Where-Object -Property isInitial -EQ $true).id
} else {
$OnMicrosoft = $Tenant.initialDomainName
}
$anchor = "UPN:SystemMailbox{bb558c35-97f1-4cb9-8ff7-d53741dc928c}@$($OnMicrosoft)"
if ($cmdlet -in 'Set-AdminAuditLogConfig', 'Get-AdminAuditLogConfig', 'Enable-OrganizationCustomization', 'Get-OrganizationConfig') { $anchor = "UPN:SystemMailbox{8cc370d3-822a-4ab8-a926-bb94bd0641a9}@$($OnMicrosoft)" }

}
#if the anchor is a GUID, try looking up the user.
if ($Anchor -match '^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$') {
Expand Down
22 changes: 18 additions & 4 deletions Modules/CIPPCore/Public/GraphHelper/Write-CippFunctionStats.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,23 @@ function Write-CippFunctionStats {
[string]$ErrorMsg = ''
)
try {
$Start = Get-Date $Start
$End = Get-Date $End

$Table = Get-CIPPTable -tablename CippFunctionStats
$RowKey = [string](New-Guid).Guid
$TimeSpan = New-TimeSpan -Start $Start -End $End
$Duration = [int]$TimeSpan.TotalSeconds
$DurationMS = [int]$TimeSpan.TotalMilliseconds

# if datetime is local, convert to UTC
if ($Start.Kind -eq 'Local') {
$Start = $Start.ToUniversalTime()
}
if ($End.Kind -eq 'Local') {
$End = $End.ToUniversalTime()
}

$StatEntity = @{}
# Flatten data to json string
$StatEntity.PartitionKey = $FunctionType
Expand All @@ -28,13 +39,16 @@ function Write-CippFunctionStats {
$StatEntity.ErrorMsg = $ErrorMsg
$Entity = [PSCustomObject]$Entity
foreach ($Property in $Entity.PSObject.Properties.Name) {
if ($Entity.$Property.GetType().Name -in ('Hashtable', 'PSCustomObject', 'OrderedHashtable')) {
$StatEntity.$Property = [string]($Entity.$Property | ConvertTo-Json -Compress)
} elseif ($Property -notin ('ETag', 'RowKey', 'PartitionKey', 'Timestamp', 'LastRefresh')) {
$StatEntity.$Property = $Entity.$Property
if ($Entity.$Property) {
if ($Entity.$Property.GetType().Name -in ('Hashtable', 'PSCustomObject', 'OrderedHashtable')) {
$StatEntity.$Property = [string]($Entity.$Property | ConvertTo-Json -Compress)
} elseif ($Property -notin ('ETag', 'RowKey', 'PartitionKey', 'Timestamp', 'LastRefresh')) {
$StatEntity.$Property = $Entity.$Property
}
}
}
$StatEntity = [PSCustomObject]$StatEntity

Add-CIPPAzDataTableEntity @Table -Entity $StatEntity -Force
} catch {
Write-Host "Exception logging stats $($_.Exception.Message)"
Expand Down
Loading

0 comments on commit 717f460

Please sign in to comment.