Call API endpoint that then uses invoke-psuscript

Product: PowerShell Universal
Version: 5.4

The idea is to have an API Endpoint that creates some groups in AD. These groups need to get assigned to a *group on an Entra application using `New-AzureADGroupAppRoleAssignment` *

I have an API Endpoint setup that first creates the groups, then it should invoke the child script.
This script should have a 30 min sleep to wait for the sync (hybrid environment), then assign the groups the role.

param(
  [Parameter(Mandatory)][string]$Account,
  [parameter(Mandatory)][string]$Environment,
  [Parameter(Mandatory)][string]$AWSAccount
)

function New-AWSAccountGroups
{
  Param (
    [Parameter(Mandatory)][string]$Account,
    [parameter(Mandatory)][string]$Environment,
    [Parameter(Mandatory)][string]$AWSAccount
  )
  $Roles = 'Admin', 'Ops', 'R', 'Billing'

  $GroupNames = foreach ($Role in $Roles)
  {
    if ($Environment)
    {
      $grpName = "RCWR_AWS_$($Account)_$($Environment)_$($Role)"
    }
    else
    {
      $grpName = "RCWR_AWS_$($Account)_$($Role)"
    }

    New-ADGroup -Name $grpName -SamAccountName $grpName  `
      -Path 'OU=Admins_Hybrid,DC=domain,DC=com' `
      -GroupScope DomainLocal -GroupCategory Security `
      -Description "AWS - $AWSAccount $Role" -whatif

    $grpName
  }
  Write-output $GroupNames
} #end function

try
{
  $outputdata = $null
  $outputdata = New-AWSAccountGroups -AWSAccount $AWSAccount -Account $Account -Environment $Environment
  $jsonResponse = $outputdata | ConvertTo-Json
  $jsonResponse
  #New-PSUApiResponse -StatusCode 200 -body $jsonResponse
}
catch
{
  $errorResponse = @{
    error      = $_.Exception.Message
    identity   = $Identity
    stackTrace = $_.ScriptStackTrace
  }
  New-PSUApiResponse -StatusCode 500 -body ($errorResponse | ConvertTo-Json -Depth 5)
}

# Trigger second script to do sync with roles after 30 minutes
try
{
  # Ensure we have data to pass
  if ($null -eq $outputdata)
  {
    $outputdata = @{
      group = 'this is test to see if it works.'
    }
  }
  $childScriptParams = @{
    InputData = $outputdata
  }

  Invoke-PSUScript -Name 'scripts/APIChild.ps1' -Parameters $childScriptParams
  Write-Host "Child script invoked successfully."
  Write-Host "Child script result: $($result | ConvertTo-Json -Depth 2)"
}
catch
{
  Write-Host "Child script invocation failed:"
  Write-Host "Message: $($_.Exception.Message)"
    
  # Get detailed error information
  if ($_.ErrorDetails.Message)
  {
    Write-Host "Error details: $($_.ErrorDetails.Message)"
  }

}

The child script, has just a simple in this test case.

# Script contents
param(
    [object]$InputData
)
#start-sleep -seconds 10
write-host $InputData
remove-item c:\temp\me.txt -force
$inputdata | out-file c:\temp\me.txt -force

This however, never gets executed, nor do i get a error message. Anyone an idea? is this even possible?

For those reading in the future.

Yes it is possible. But in order to invoke a script via the API, you first need to connect to the PSU server using an apptoken, which you an create in the UI.

Definitely possible and I do it when creating an on-premises user account and adding to mail enabled secrity groups on Exchange Online.

I think it’s more efficient to check that the account is replicated in Entra (or in my case, has an Exchange Online mailbox) and catch any issues.

I check for sync completion every 60 seconds with a 1 hour timeout and graceful fail.

# Set start time to prevent infinit loop while waiting for 365 to update
$StartTime = Get-Date

# Wait for 365 sync or abort after 1 hour
Do {
    Start-Sleep -s 60
    Connect-ExchangeOnline -CertificateThumbPrint $Secret:CertThumbprint -AppID "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" -Organization "xxxxxxxxxxxx.onmicrosoft.com" -ShowBanner:$False

    $Sync = Get-EXOMailbox $Params.UPN -ErrorAction SilentlyContinue

    if (-not $Sync) {
        Disconnect-ExchangeOnline | Out-Null
    }

} Until ($Sync -or $StartTime.AddHours(1) -le (Get-Date) )


# If 365 doesn't sync for over an hour
if (-not $Sync) {
    Write-Host "365 failed to sync for $($Params.UserID)"
    # Abort actions here
    Exit
}


# Successfully synced actions here
.
.
.