Skip to main content

Observer Scripts

A quick reference to write your own observer scripts

Script Template

Observer 'ArbitraryObserverName' {

Init {
# Init is called before any action. Use it to initialize your observer script.

# TODO: implement observer setup

# import modules

# fetch observer environment
$tenantId = $env:GOV_TENANT_ID
$clientId = $env:GOV_CLIENT_ID
$CertificateFile = $env:GOV_CERTIFICATE_FILE
$CertificatePassword = Get-Content $env:GOV_CERTIFICATE_SECRET -Raw | ConvertTo-SecureString -AsPlainText -Force
$Certificate = [System.Security.Cryptography.X509Certificates.X509Certificate2]::new($CertificateFile, $CertificatePassword)
#$organizationname = $env:GOV_ORGANIZATION_NAME

# get access token with client certificate
$Token = Get-MsalToken -ClientId $clientId -TenantId $tenantId -ClientCertificate $Certificate -Verbose
}

Shutdown {
# Shutdown is called after any successful or non-successful action. Use it to release resources.

# TODO: implement observer shutdown
Disconnect-MgGraph
}

Action 'List' {
# Perform list observation (delta + non-delta)
param($Order)

# TODO: implement list observation
return New-ObservationResult `
-Table "TABLE_NAME" `
-PartitionKey "PARTITION_KEY" `
-ItemId "INVENTORY_ITEM_ID" `
-ObjectId "OPTIONAL_GOVERNED_OBJECT_ID" `
-Observation @{ OPTIONAL_KEY_VALUE_PAIRS = "..." } `
-ParentRefs @( "OPTIONAL_PARENT_OBJECT_ALIASES" ) `
-ChildRefs @( "OPTIONAL_CHILD_OBJECT_ALIASES" ) `
-Message "OPTIONAL_MESSAGE" `
-Reason "OPTIONAL_REASON"

return New-ObservationError `
-ObservationType "OBSERVATION_TYPE" `
-ItemId "OPTIONAL_INVENTORY_ITEM_ID" `
-ObjectId "OPTIONAL_GOVERNED_OBJECT_ID" `
-Message "OPTIONAL_MESSAGE" `
-Reason "OPTIONAL_REASON" `
-Repeat -Cooldown COOLDOWN_SECS
}

Action 'Object' {
# Perform single object observation
param($Order)

# TODO: implement single object observation
return New-ObservationResult `
-Table "TABLE_NAME" `
-PartitionKey "PARTITION_KEY" `
-ItemId "INVENTORY_ITEM_ID" `
-ObjectId "OPTIONAL_GOVERNED_OBJECT_ID" `
-Observation @{ OPTIONAL_KEY_VALUE_PAIRS = "..." } `
-ParentRefs @( "OPTIONAL_PARENT_OBJECT_ALIASES" ) `
-ChildRefs @( "OPTIONAL_CHILD_OBJECT_ALIASES" ) `
-Message "OPTIONAL_MESSAGE" `
-Reason "OPTIONAL_REASON"

return New-ObservationError `
-ObservationType "OBSERVATION_TYPE" `
-ItemId "OPTIONAL_INVENTORY_ITEM_ID" `
-ObjectId "OPTIONAL_GOVERNED_OBJECT_ID" `
-Message "OPTIONAL_MESSAGE" `
-Reason "OPTIONAL_REASON" `
-Repeat -Cooldown COOLDOWN_SECS
}

Action 'ArbitraryActionName' {
param($Order)
}
}

Observation Orders

Full List Observation

Sample

{
"OrderId": "dc720478-d3ad-4003-9d45-35434e9ff4bc",
"ObservationType": "M365UserLicense/List",
"Payload": {
"delta": false
}
}

Delta List Observation

{
"OrderId": "dc720478-d3ad-4003-9d45-35434e9ff4bc",
"ObservationType": "M365UserLicense/List",
"Payload": {
"delta": true
}
}

Single Object Observation

Sample

{
"OrderId": "dc720478-d3ad-4003-9d45-35434e9ff4bc",
"ObservationType": "M365UserLicense/Object",
"Payload": {
"__NativeId": [
"f30db892-07e9-47e9-837c-80727f46fd3d",
"3218bdff-cfd8-4d36-bce9-492f2cd21b92"
],
"__ObjectId": "6ee2b7ef-d64e-4e15-9bf8-6fcb2be61d08",
"__MasterItemKey": "[\"Group\",\"License_FlowFree\",\"FLOW_FREE\"]",
"__InventoryItemId": "f30db892-07e9-47e9-837c-80727f46fd3d:3218bdff-cfd8-4d36-bce9-492f2cd21b92",
// all "IsSpec" fields from the target object
"id": "f30db892-07e9-47e9-837c-80727f46fd3d:3218bdff-cfd8-4d36-bce9-492f2cd21b92",
"license": "FLOW_FREE",
"user": "",
"group": "License_FlowFree",
"LicenseAssigned": true,
"licenseType": "Group",
"licenseActive": true
}
}

Minimal Example

Observer Script

# ./Scripts/Observers/xMinimal.Observer.ps1
Observer 'Minimal' {
Init {}

Shutdown {}

Action "Hello" {
param($Order)
$name = $Order.Payload["name"]

return New-ObservationResult -Table 'HelloWorld' -PartitionKey 'Greetings' -ItemId $name `
-Observation @{ message = "Hello ${name}!" } -Reason "Observed"
}
}

Script Binding

// appsettings.json
{
"ScriptBindings": {
"Observations": {
"Minimal/Hello": {
"Observer": "./Scripts/Observers/xMinimal.Observer.ps1",
"Action": "Hello"
}
}
}
// ...
}

Order Payload

Property Payload is mandatory and cannot be changed. Add your values within Payload

// Scripts/mocks/minimal-hello-order.json
{
"Payload": {
"name": "World"
}
}

Debugger Parameters

# Scripts/DebugObserverScript.ps1
param(
# Select your action
[string] $Action = 'Minimal/Hello',

# You can export a governed object via RestAPI and provide it as JSON file.
[string] $MockFile = './mocks/minimal-hello-order.json',

# Must provide the appsettings.json to have the same settings for script invocation.
[string] $AppConfig = '../appsettings.json'
)