Get-UAJob / Invoke-UAScript

Hi there, just having trouble trying to create a proof of concept site that has a simple button that invokes a script in UA; following the “Active Directory Help Desk” blog examples I’m trying…

New-UDButton -Text 'Run UA script' -Id 'btnRunScript' -OnClick {
    		Show-UDToast -Message "starting run UA script" -Duration 5000
    		
    		#Invoke-UAScript -Id 2 -AppToken $apptoken | Tee-Object -Variable Job | Wait-UAJob
    		#Invoke-UAScript -Name 'Get-Subscribers.ps1' -AppToken $apptoken | Tee-Object -Variable Job | Wait-UAJob
                    Invoke-UAScript -Name 'Get-Subscribers.ps1' | Tee-Object -Variable Job | Wait-UAJob

    		$getJob = Get-UAJob -Id $Job.Id
    		Show-UDToast -Message "job id is: $($getJob.Id)"
    		If ($getJob.Status -eq 'Completed') {
    			Show-UDToast -Message "job completed ok" -Duration 5000
    		} else {
    			$Output = Get-UAJobOutput -JobId $Job.Id | Select-Object -Expand Message
    			Show-UDToast -Message "job failed $($Output -join "`n")" -Duration 5000 -BackgroundColor Red -MessageColor white
    		}
    	}	

It just doesn’t seem to work, I’ve tried with apptokens too, I get no valid response/data in the toasts.

If I run Get-UAJob or Invoke-UAScript from a PowerShell prompt, I get…

PS > Get-UAJob -Id 2
Get-UAJob : Call failed with status code 401 (Unauthorized): GET https://servername/api/v1/Job/2
At line:1 char:1
+ Get-UAJob -Id 2
**+ ~~~~~~~~~~~~~~~**
** + CategoryInfo : NotSpecified: (:slight_smile: [Get-UAJob], FlurlHttpException**
** + FullyQualifiedErrorId : Flurl.Http.FlurlHttpException,UniversalAutomation.GetJobCommand**

or…

PS > Invoke-UAScript -Name 'Get-Subscribers.ps1’
Invoke-UAScript : Cannot retrieve the dynamic parameters for the cmdlet. Call failed with status code 401
(Unauthorized): GET https://servername/api/v1/Script/Get-Subscribers.ps1

But when I throw this into a browser: https://servername/api/v1/Job/2 I get a response, like…

{“id”:2,“createdTime”:“2020-08-07T09:29:43.91+12:00”,“startTime”:“2020-08-07T09:29:43.988+12:00”,“endTime”:“2020-08-07T09:29:46.13+12:00”,“status”:2,“output”:null,“script”:{“id”:2,“name”:null,“description”:null,“createdTime”:“0001-01-01T00:00:00”,“manualTime”:0.0,“commitId”:null,“content”:null,“scriptParameters”:null,“identity”:null,“tags”:null,“schedules”:null,“status”:0,“folder”:null,“fullPath”:null,“requiredPowerShellVersion”:null,“errorAction”:0,“informationAction”:0,“verbose”:false,“debug”:false,“commitNotes”:null,“disableManualInvocation”:false,“maxHistory”:100},“scriptCommitId”:null,“appToken”:{“id”:2,“token”:null,“identity”:null,“revoked”:false,“role”:null,“created”:“0001-01-01T00:00:00”,“expiration”:“0001-01-01T00:00:00”,“revokedDate”:“0001-01-01T00:00:00”},“identity”:{“id”:1,“name”:“Admin”,“source”:0,“role”:null},“parentJob”:null,“parentLineNumber”:0,“debug”:false,“computerName”:“localhost”,“port”:56976,“processId”:12900,“runspaceId”:2,“activity”:“Preparing modules for first use.”,“currentOperation”:null,“percentComplete”:-1,“secondsRemaining”:-1,“statusDescription”:null,“powerShellVersion”:" 5.1.14393.3471",“agent”:null,“computer”:{“id”:1,“name”:null},“errorAction”:0,“children”:null,“jobOutput”:null,“parameters”:null,“notes”:null,“credential”:null}

or likewise with this https://servername/api/v1/Script/Get-Subscribers.ps1

{“id”:2,“name”:“Get-Subscribers.ps1”,“description”:null,“createdTime”:“2020-08-07T09:20:22.241+12:00”,“manualTime”:0.0,“commitId”:null,“content”:"# Get-Subscribers\r\nGet-Process | Where-Object {$_.Name -like “m*”}",“scriptParameters”:null,“identity”:{“id”:1,“name”:null,“source”:0,“role”:null},“tags”:[],“schedules”:null,“status”:0,“folder”:null,“fullPath”:“Get-Subscribers.ps1”,“requiredPowerShellVersion”:null,“errorAction”:0,“informationAction”:2,“verbose”:false,“debug”:false,“commitNotes”:null,“disableManualInvocation”:false,“maxHistory”:100}

Update:
If I connect with the -AppTOken first, then Get-UAJob and Invoke-UAScript work

PS > Connect-UAServer -ComputerName https://servername -AppToken 'JhbGciOi…1SFADhUuyTq4_G’
PS > Get-UAJob -Id 2

Id : 2
CreatedTime : 7/08/2020 9:29:43 AM
StartTime : 7/08/2020 9:29:43 AM
EndTime : 7/08/2020 9:29:46 AM
Status : Completed
Output :
Script :

(With a new job added to the list of jobs in UA after Invoke-UAScript -Id 2)

I feel like it’s so close, just something silly I’m missing. Maybe somehow setting an AppToken for the dashboard when it is started?

Would really appreciate the help! (note: I’m running from IIS, and have tried with Windows auth off and on, which is working when on, I can show $user and $roles in the dashboard)

Cheers,
Steve.

ok, sussed it out (if this is the correct way?)…

I needed to add the “Connect-UAServer” to the top of the dashboard script…

New-UDDashboard -Title "Hello, World!" -Content {
	$server = 'domain.com'
	$credential = Get-Secret -Name 'credForDomain'
	$apptoken = "bGciOiJIUzI1NiIsIn...0CYZWEivQnScuR-cjj2Y"
Connect-UAServer -ComputerName https://servername -AppToken $apptoken
Invoke-UAScript -Name 'Get-Subscribers.ps1' | Tee-Object -Variable Job | Wait-UAJob
		$Job = Get-UAJob -Id $Job.Id
		Show-UDToast -Message "job is: $($Job.Id)"

My quick tests seem to be working ok now :slight_smile: I’m getting the most recent job id returned in the toast message, woohoo.

I’ll leave this all here, it might help someone else out who misses the the Connect-UAServer piece.

2 Likes

Also worth mentioning you need more than read permissions on the app token to invoke the job :wink:

How do you grant a read only app token?

Hmm, does look like that option is not available anymore, it was under “settings” and “Security” where you would have an app token with read only permissions.

Ahh I see. Will keep an eye out for that anyway, might be a feature that returns.

As a sidenote to this task, I have a similar job going, but it seems like it “times out” the connection with the server, so when presenting the result of the job, the task is disconnected from the UA server.

How long can a running task be here? Are there any timeout limits ? If I run the same task after knowing the task is completed, it shows as expected. My task takes somewhere in between 1 minute to gather all information. (Collecting live user data from O365 through Graph) Maybe @adam have more information :wink:

You can use Grant-PSUAppToken to grant app tokens manually using the Universal PS module. We need to add some UI to allow specifying permissions while creating app tokens in the web.

As for your side note, can you let me know where you are seeing this time out? The job times out or waiting for the job times out?

Maybe I am misunderstanding how this works.
From my button here:


I invoke a script, this works as expected, it takes about a minute to perform all steps.
While waiting for the job to complete something stops working, and the end result of the job is not presented.

UserState = New-UDButton -Text ‘Get UserState’ -OnClick {

                        # New-UdProgress -Circular -Color Blue

                        $CustomerDomain = $_.UserPrincipalName -split "@" | Select-Object -Last 1

                        Show-UDToast -Message "Collecting information on user: $($_.UserDisplayName) - TenantId: $($_.TenantId) - CustomerDomain: $CustomerDomain" -Duration 3000

                        Invoke-UAScript -Id 21 -UserPrincipalName $currentUserPrincipalName -CustomerDomain $CustomerDomain -CustomerTenantId $_.TenantId -AppToken $fullAppToken |  Tee-Object -Variable Job | Wait-UAJob -AppToken $fullAppToken

                        # https://github.com/ironmansoftware/universal-templates/blob/master/active-directory/Help%20Desk.ps1#L53   

                                        

                        ### Add a Do While until the job is completed here, to show result on modal instead of tee-object?                   

                        $JobResult = get-uajob -Id $job.id | Get-UAJobPipelineOutput

                

                        if ($jobresult.status -eq "Completed") { 

                            Show-UDToast -Message "Job completed Ok" -duration 4000

                            

                            show-udModal -Content {

                                New-UDTable -Title "MailboxStatus" -Headers @("UserPrincipalName", "ForwardingSmtpAddress", "ForwardingAddress", "DeliverToMailboxAndForward") -Content {

                                    if ($JobResult.Mailbox.DeliverToMailboxAndForward -like "False") {

                                        $ForwardStatus = "False"

                                    }

                                    else {

                                        $ForwardStatus = "True"

                                    }

                                    $JobResult.Mailbox | 

                                        Select-Object UserPrincipalName, ForwardingSmtpAddress, ForwardingAddress, @{Label = "DeliverToMailboxAndForward"; Expression = { $forwardStatus } } | 

                                            Out-UDTableData -Property @("UserPrincipalName", "ForwardingSmtpAddress", "ForwardingAddress", "DeliverToMailboxAndForward")

                                }

                                if (!$JobResult.MailboxRule) {

                                    New-UdRow -Endpoint {

                                        New-UDCard -Title "MailboxRule" -Content {

                                            "No mailboxrules found"

                                        }

                                    }

                                }

                                else {

                                    New-UDRow -Endpoint {

                                        New-udGrid -Title "Mailboxrules" -Endpoint {

                                            $JobResult.MailboxRule | Select-Object Enabled, Name, Description | Out-UDGridData

                                        }

                                    }

                                }

                                if (!$JobResult.UserRiskDetection) {

                                    New-UdRow -Endpoint {

                                        New-UDCard -Title "UserRiskDetectionCard" -Content {

                                            "No user risk detected"

                                        }

                                    }

                                }

                                else {

                                    New-UDRow -Endpoint {

                                        New-udGrid -Title "UserRiskDetection" -Endpoint {

                                            $JobResult.UserRiskDetection | Out-UDGridData

                                        }

                                    }

                                }

                            

                                New-UdRow -Endpoint {

                                    New-UDGrid -Title "UserSignin" -Endpoint {

                                        $JobResult.UserSignin | Out-UDGridData 

                                    }

                                }        

            

                            } -fullScreen -Footer {

                                New-UDButton -Text "Close" -OnClick { Hide-UDModal } 

                            }

                        } # End If job is completed

                        else {

                            $Output = Get-UAJobOutput -JobId $job.id 

                            Show-UdToast -Message "Job failed: $Output" -duration 4000

                        }

                    }

image

Job completes with no issues:

Ah, interesting. That should work. It seems like something is timing out on the Dashboard end. On the dashboard page in the Admin console, are there any errors in the log?

There are some errors, a long one:

[08-09-20 08:29:13 PM] PS: One or more errors occurred.
[08-09-20 08:29:13 PM] PS: One or more errors occurred.
[08-09-20 08:32:38 PM] PS: Cannot convert argument “icon”, with value: “”, for “GetIconName” to type “UniversalDashboard.Models.FontAwesomeIcons”: "Cannot convert null to type “UniversalDashboard.Models.FontAwesomeIcons” due to enumeration values that are not valid. Specify one of the following enumeration values and try again. The possible enumeration values are "None,ad,address_book,address_card,adjust,air_freshener,align_center,align_justify,align_left,align_right,allergies,ambulance,american_sign_language_interpreting,anchor,angle_double_down,angle_double_left,angle_double_right,angle_double_up,angle_down,angle_left,angle_right,angle_up,angry,ankh,apple_alt,archive,archway,arrow_alt_circle_down,arrow_alt_circle_left,arrow_alt_circle_right,arrow_alt_circle_up,arrow_circle_down,arrow_circle_left,arrow_circle_right,arrow_circle_up,arrow_down,arrow_left,arrow_right,arrows_alt,arrows_alt_h,arrows_alt_v,arrow_up,assistive_listening_systems,asterisk,at,atlas,atom,audio_description,award,baby,baby_carriage,backspace,backward,balance_scale,ban,band_aid,barcode,bars,baseball_ball,basketball_ball,bath,battery_empty,battery_full,battery_half,battery_quarter,battery_three_quarters,bed,beer,bell,bell_slash,bezier_curve,bible, … This one goes on with a lot of text with similar items.

Cannot see anything specified what is wrong.