Table of Contents
WPSecure Beacon gathers login time, boot time, location, and other properties that describe the Who, Where, and When information of Windows 10 and 11 devices. It is certificate-authenticated and operates in the background.
This tool uses Azure Function Apps. The management of the Azure Function Apps, as well as their security and setup, are outside the scope of WPSecure package support and licensing. This integration is provided for convenience and interoperability with other cloud infrastructures. If you have any issues with Azure Function Apps, please get in touch with Microsoft Support.
This article will guide you through setting up an Azure Function with a PowerShell Core runtime stack to collect the below information at preset intervals and publish it to a SharePoint Online list. Although this article focuses on using SharePoint Online, you can modify the PowerShell function to direct the data to your chosen datastore, such as MSSQL, MySQL, Dataverse, etc.
Details | Variable Name |
---|---|
User Principal Name | upn |
Device Hostname | hostname |
Operating System and Version | operatingsystem |
Device Location Latitude | latitude |
Device Location Longitude | longitude |
Beacon Launch Time | beaconlaunchtime |
Device Last Used By User | lastusetime |
System Boot Time | systemboottime |
User Last Logon Time | lastlogontime |
WPSecure Desktop Wallpaper Package Version | bgversion |
WPSecure Lock Screen Package Version | lsversion |
WPSecure Signature For New Messages Package Version | signewversion |
WPSecure Signature For Reply Messages Package Version | sigreplyversion |
WPSecure Signature For Web Messages Package Version | sigwebversion |
WPSecure Screensaver Package Version | scrnsaveversion |
Is Device Pending Reboot? | pendingreboot |
Is Device Compliant? | compliant |
Ways to secure the Azure Function
The Azure function you create must be secure but UI-free. Therefore, we will have to authenticate using a Certificate. The calls to the Function App cannot trigger any authentication windows or request user interaction.
Function Key | Function keys help ensure that only authorized users or systems can execute your functions, adding an extra layer of security. Using a Function Key alone does not secure your Function App. |
Certificate based authentication | Using certificate-based authentication helps protect your Azure Functions from unauthorized access and ensures secure communication between WPSecure clients and the function. |
VNI and NSGs | Deploy your function app within a virtual network to manage inbound and outbound traffic. Use Network Security Groups (NSGs) to restrict traffic based on port, protocol, source IP address, or destination IP address. Note that this topic is beyond the scope of this article. |
What administrative permissions are required?
To successfully execute the procedures in this document, you will need Azure Global Admin permissions to set up the Function App. Additionally, SharePoint Online Administrative permissions are required to create a SharePoint List and grant the Azure Functions Managed Identity access to the SharePoint List.
Create a Function App in Azure Portal
Having discussed the fundamentals, it is now time to create the Azure Function and make the necessary configuration changes.
Create a resource in Azure and select ‘Function App‘ as the service type.

Select either Consumption or Function Premium with the Windows OS option. However, select Function Premium to prevent cold starts.

In the next step, choose a name. We suggest using the format “wpsecure-no-ui-32456,” where 32456 is a random number.
Note: We can utilize the same Azure Function App to automatically set the WPSecure Web mail signature.

Select a storage account. If you already have a storage account, you can choose to use it.

Public access should be based on your organizational needs and security governance requirements. We recommend setting it to ‘Public‘ during the initial setup. After you have successfully completed the setup, you can implement additional network restrictions.

Azure Monitor application insights is an Application Performance Management (APM) service for developers and DevOps professionals. Enable it below to monitor your application automatically. It will detect performance anomalies and include powerful analytics tools to help you diagnose issues and understand what users do with your app.

Continuous deployment settings and the tags should be based on your organization’s needs. Finally, review and Create.
When the deployment is complete, go to the resource.

Copy the Function App default domain
On the overview page of the Function App, the first parameter that needs to be copied and saved for future reference is the “Default Domain.” Please copy and paste the default domain into a Notepad file.

Copy Function App Managed Identity ID
Enable “System Assigned Managed Identity” and save and copy the PrincipalID of the managed identity to Notepad.

Copy the Azure AD Tenant ID
Open the EntraID portal in a new window or tab and copy the Tenant ID from the ‘basic information‘ section.

Copy the Application ID and Name
Copy the “Object (Principal) ID,” which is the ID of the System Assigned Managed Identity, and keep it in memory. In the Entra ID portal (Open in a new tab or window), open the Enterprise Applications panel. Paste the “Object (Principal) ID” into the search field.
The search will yield one result that matches the name of the Azure Function app that you are creating. In this case, the name of the Azure Function is “wpsecure-no-ui-32456.”

Create SharePoint List and Copy ID's
You need PowerShell 7.4.4 or later to use PnP PowerShell. Read more.
Install-Module PnP.PowerShell -Scope CurrentUser
Run the below PowerShell script to create a SharePoint List. Copy and paste your SiteURL into the below script.
$spSiteURL = "https://Your-SharePoint-Organization.onmicrosoft.com/sites/Your-Site-Name"
$spListName = "WPSecure Beacon Information"
$spListDesc = "Gather infomation about System boot time, User logon time, WPSecure package versions etc."
Connect-PnPOnline -UseWebLogin -Url $spSiteURL
New-PnPList -Title $spListName -Template GenericList
Set-PnPList -Identity $spListName -Description $spListDesc
Add-PnPField -List $spListName -DisplayName "upn" -InternalName "int_upn" -Type Text -AddToDefaultView
Add-PnPField -List $spListName -DisplayName "hostname" -InternalName "int_hostname" -Type Text -AddToDefaultView
Add-PnPField -List $spListName -DisplayName "operatingsystem" -InternalName "int_operatingsystem" -Type Text -AddToDefaultView
Add-PnPField -List $spListName -DisplayName "beaconlaunchtime" -InternalName "int_beaconlaunchtime" -Type DateTime
Add-PnPField -List $spListName -DisplayName "lastusetime" -InternalName "int_lastusetime" -Type DateTime -AddToDefaultView
Add-PnPField -List $spListName -DisplayName "systemboottime" -InternalName "int_systemboottime" -Type DateTime -AddToDefaultView
Add-PnPField -List $spListName -DisplayName "lastlogontime" -InternalName "int_lastlogontime" -Type DateTime -AddToDefaultView
Add-PnPField -List $spListName -DisplayName "pendingreboot" -InternalName "int_pendingreboot" -Type Boolean -AddToDefaultView
Add-PnPField -List $spListName -DisplayName "location" -InternalName "int_location" -Type Geolocation -AddToDefaultView
Add-PnPField -List $spListName -DisplayName "bgversion" -InternalName "int_bgversion" -Type Text
Add-PnPField -List $spListName -DisplayName "lsversion" -InternalName "int_lsversion" -Type Text
Add-PnPField -List $spListName -DisplayName "signewversion" -InternalName "int_signewversion" -Type Text
Add-PnPField -List $spListName -DisplayName "sigreplyversion" -InternalName "int_sigreplyversion" -Type Text
Add-PnPField -List $spListName -DisplayName "sigwebversion" -InternalName "int_sigwebversion" -Type Text
Add-PnPField -List $spListName -DisplayName "scrnsaveversion" -InternalName "int_scrnsaveversion" -Type Text
Write-Host "SharePoint SiteID is ==> $($(Get-PnPSite -Includes Id).Url)"
Write-Host "SharePoint ListID is ==> $spListName"
Copy and paste the SharePoint Site URL and the List name from the script output to Notepad.


Grant the required permissions to the Managed Identity.
To grant the Function App’s managed identity permissions for SharePoint Online, you can use the scripts provided below. The Permission process has two parts
- Register a PNP application in Entra ID that will allow you set PnP AzureAD Service Principal App Role.
- Using the PNP App registration ApplicationID (ClientID) you can set the permissions for the Managed Identity.
!! Note: The below commands will only work under PowerShell V7 or greater.
The below command will register a PNP application in Entra ID that will allow you set PnP AzureAD Service Principal App Role.
Register-PnPEntraIDAppForInteractiveLogin -ApplicationName "PnP Permission Setting App" -Tenant "Your-SharePoint-Organization.onmicrosoft.com" -Interactive

Provide necessary consents during the process (Organization wide consent not required). Copy the “AzureAppId/ClientId” from the PowerShell script output. The value for “AzureAppId/ClientId” can also be fetched directly from the new App Registration.
$principalId = "Copy-From-Notepad" # This is the System Assigned Managed Indetity ID of the Azure Function.
$clientID = "From-Previous-Step" # This is the AzureAppId/ClientId from previous step.
$spSiteURL = "https://Your-SharePoint-Organization.sharepoint.com/sites/Central" # URL for your SharePoint site.
# Connect to SharePoint Online
Connect-PnPOnline -Interactive -Url $spSiteURL -ClientId $clientID
Add-PnPAzureADServicePrincipalAppRole -Principal $principalId -AppRole "Directory.ReadWrite.All" -BuiltInType MicrosoftGraph
Add-PnPAzureADServicePrincipalAppRole -Principal $principalId -AppRole "Sites.FullControl.All" -BuiltInType SharePointOnline
Create a function within the Azure Function App
Open the ‘Overview’ node of the Function App. Click on the ‘Create Function‘ button.

Choose ‘HTTP Trigger‘ and click next.

On the next window, type ‘beacon‘ as the function name and choose ‘Function‘ as the Authorization level. Click Create.

When you click ‘Create,’ you will be presented with a ‘run.ps1‘ PowerShell file in edit mode. Review the file content and understand the layout. Replace the file content with the following code. Please do not forget to ‘Save.‘
using namespace System.Net
using namespace System.Web
# Input bindings are passed in via param block.
param($Request, $TriggerMetadata)
# Write to the Azure Functions log stream.
Write-Host "A new beacon receive process has started."
#Variable definition
try {
$upn = [System.Web.HttpUtility]::HtmlDecode($Request.Body.upn)
$hostname = [System.Web.HttpUtility]::HtmlDecode($Request.Body.hostname)
$operatingsystem = [System.Web.HttpUtility]::HtmlDecode($Request.Body.operatingsystem)
$latitude = [System.Web.HttpUtility]::HtmlDecode($Request.Body.latitude)
$longitude = [System.Web.HttpUtility]::HtmlDecode($Request.Body.longitude)
$beaconlaunchtime = [System.Web.HttpUtility]::HtmlDecode($Request.Body.beaconlaunchtime)
$lastusetime = [System.Web.HttpUtility]::HtmlDecode($Request.Body.lastusetime)
$systemboottime = [System.Web.HttpUtility]::HtmlDecode($Request.Body.systemboottime)
$lastlogontime = [System.Web.HttpUtility]::HtmlDecode($Request.Body.lastlogontime)
$bgversion = [System.Web.HttpUtility]::HtmlDecode($Request.Body.bgversion)
$lsversion = [System.Web.HttpUtility]::HtmlDecode($Request.Body.lsversion)
$signewversion = [System.Web.HttpUtility]::HtmlDecode($Request.Body.signewversion)
$sigreplyversion = [System.Web.HttpUtility]::HtmlDecode($Request.Body.sigreplyversion)
$sigwebversion = [System.Web.HttpUtility]::HtmlDecode($Request.Body.sigwebversion)
$scrnsaveversion = [System.Web.HttpUtility]::HtmlDecode($Request.Body.scrnsaveversion)
$pendingreboot = [System.Web.HttpUtility]::HtmlDecode($Request.Body.pendingreboot)
$compliant = [System.Web.HttpUtility]::HtmlDecode($Request.Body.compliant)
Write-Host "######################################################################"
Write-Host "A beacon with the following information was received."
Write-Host "User Principal Name:$upn"
Write-Host "Device Hostname:$hostname"
Write-Host "Operating System and Version:$operatingsystem"
Write-Host "Device Location Latitude:$latitude"
Write-Host "Device Location Longitude:$longitude"
Write-Host "Beacon Launch Time:$beaconlaunchtime"
Write-Host "Device Last Used By User:$lastusetime"
Write-Host "System Boot Time:$systemboottime"
Write-Host "User Last Logon Time:$lastlogontime"
Write-Host "WPSecure Desktop Wallpaper Package Version:$bgversion"
Write-Host "WPSecure Lock Screen Package Version:$lsversion"
Write-Host "WPSecure Signature For New Messages Package Version:$signewversion"
Write-Host "WPSecure Signature For Reply Messages Package Version:$sigreplyversion"
Write-Host "WPSecure Signature For Web Messages Package Version:$sigwebversion"
Write-Host "WPSecure Screensaver Package Version:$scrnsaveversion"
Write-Host "Is Device Pending Reboot?:$pendingreboot"
Write-Host "Is Device Compliant?:$compliant"
Write-Host "######################################################################"
#SharePoint ID's stored in Environmental Variables
$SHAREPOINT_SITE_URL = $env:SHAREPOINT_SITE_URL
$SHAREPOINT_LIST_NAME = $env:SHAREPOINT_LIST_NAME
if ((-not [string]::IsNullOrWhiteSpace($SHAREPOINT_SITE_URL)) -and (-not [string]::IsNullOrWhiteSpace($SHAREPOINT_LIST_NAME))) {
$internalbeaconlaunchtime = try { [datetime]::ParseExact($beaconlaunchtime, "dddd, d MMMM yyyy h:mm tt", $null) } catch { [datetime]"1900-01-01T00:00:00" }
$internallastusetime = try { [datetime]::ParseExact($lastusetime, "dddd, d MMMM yyyy h:mm tt", $null) } catch { [datetime]"1900-01-01T00:00:00" }
$internalsystemboottime = try { [datetime]::ParseExact($systemboottime, "dddd, d MMMM yyyy h:mm tt", $null) } catch { [datetime]"1900-01-01T00:00:00" }
$internallastlogontime = try { [datetime]::ParseExact($lastlogontime, "dddd, d MMMM yyyy h:mm tt", $null) } catch { [datetime]"1900-01-01T00:00:00" }
$internallatitude = try { [double]::Parse($latitude) } catch { 0.0 }
$internallongitude = try { [double]::Parse($longitude) } catch { 0.0 }
$internalupn = $upn
$internalhostname = $hostname
$internalTitle = "$internalupn ON $hostname AT $internallastusetime"
$internaloperatingsystem = $operatingsystem
$internalbgversion = $bgversion
$internallsversion = $lsversion
$internalsignewversion = $signewversion
$internalsigreplyversion = $sigreplyversion
$internalsigwebversion = $sigwebversion
$internalscrnsaveversion = $scrnsaveversion
$internalpendingreboot = try { [bool]::Parse($pendingreboot) } catch { $false }
$internalcompliant = try { [bool]::Parse($compliant) } catch { $false }
$fieldValues = @{
"Title" = "$internalTitle"
"int_upn" = "$internalupn"
"int_hostname" = "$internalhostname"
"int_operatingsystem" = "$internaloperatingsystem"
"int_beaconlaunchtime" = "$internalbeaconlaunchtime"
"int_lastusetime" = "$internallastusetime"
"int_systemboottime" = "$internalsystemboottime"
"int_lastlogontime" = "$internallastlogontime"
"int_bgversion" = "$internalbgversion"
"int_lsversion" = "$internallsversion"
"int_signewversion" = "$internalsignewversion"
"int_sigreplyversion" = "$internalsigreplyversion"
"int_sigwebversion" = "$internalsigwebversion"
"int_scrnsaveversion" = "$internalscrnsaveversion"
"int_pendingreboot" = "$internalpendingreboot"
"int_compliant" = "$internalcompliant"
"int_location" = "POINT($internallongitude $internallatitude)"
}
Connect-PnPOnline -ManagedIdentity -Url $SHAREPOINT_SITE_URL -Debug
Write-Host "Checking if a record exist for the UPN and HOSTNAME combination."
$existingItemSearchQuery = "$internalhostname $internalupn "
$existingItem = Get-PnPListItem -List $SHAREPOINT_LIST_NAME -Query $existingItemSearchQuery -Debug
if ($existingItem) {
Write-Host "Record exist for the UPN and HOSTNAME combination. Existing record will be updated."
Set-PnPListItem -List $SHAREPOINT_LIST_NAME -Identity $existingItem.Id -Values $fieldValues -Debug
}
else {
Write-Host "Record does not exist for the UPN and HOSTNAME combination. New record will be created."
Add-PnPListItem -List $SHAREPOINT_LIST_NAME -Values $fieldValues -Debug
}
}
}
catch {
$ex = $_.Exception
Write-Error "Exception: The process failed. $($ex.Message)"
# Write-Error "Stack Trace: $($ex.StackTrace)" # Uncomment for detailed troubleshooting.
# Write-Error "Inner Exception: $($ex.InnerException)" # Uncomment for detailed troubleshooting.
}
finally {
Get-PSSession | Remove-PSSession
}

Copy the function key
Click on the “Function Keys” tab. Copy the function key of the new function and paste it into Notepad.

Set Azure Function App Environment variables
Move to the main page of the Function App. Go to ‘Settings/Environmental variables‘
We will have to input 2 environmental variables into the Azure Function App.
SHAREPOINT_SITE_URL | Copy and paste from Notepad |
SHAREPOINT_LIST_NAME | Copy and paste from Notepad |


Add an authentication identity provider
Go to ‘Settings/Authentication‘ and add ‘Microsoft‘ as the identity provider.

Accept the default settings for most values. Choose a ‘Secret‘ expiration duration and set a reminder for renewing the secret.

In ‘Permissions‘, accept default values and click ‘Add‘. The process will take you to a screen that resembles the image below. Click to open the newly created Identity Provider, which is a standard Entra ID App Registration object.

Click to open the newly created Identity Provider, a standard Entra ID App Registration object.
Copy the “Application (Client) ID” and the “Directory (tenant) ID” to Notepad. You would have already copied the Tenant ID in the previous steps.

Authentication Provider Platform configuration
The authentication provider ‘Microsoft‘ is just an ‘app registration‘ object in Entra ID. The automatic ‘app registration‘ defaults are mostly correct but require a few modifications. Let’s remove the ‘Web‘ platform because the authentication happens using a Certificate and is non-interactive.

Authentication Provider Certificate based authentication setup
For production environments, deploy a certificate to the ‘CurrentUser‘ ‘Personal‘ certificate store and ensure there is a valid trusted chain in the “Trusted Root Certification Authorities” using Microsoft Intune or Active Directory Group Policy. Identify and copy the certificate thumbprint.

For this article, we will use a self-signed certificate. However, we recommend using a certificate from your internal CA or a reputable certificate authority.
!! Caution
Self-signed certificates are digital certificates that a trusted third-party CA doesn’t sign. They are created, issued, and signed by the company or developer responsible for the website or software being signed. This is why self-signed certificates are considered unsafe for public-facing websites and applications.
Use the following Powershell script to generate a self-signed certificate. The script will create two file.
wpsecure-no-ui-32456.cer | Import into Azure Function authentication provider. |
wpsecure-no-ui-32456.pfx | Secure it and use it in other automations or import certificate into other devices. |
# Define variables
$SubjectName = "wpsecure-no-ui-32456"
$CertificateStore = "CurrentUser"
$ValidityPeriodMonths = 24
$CertificateFolderPath = "C:\temp\certs"
# Create a new self-signed certificate
$NewCertificateParams = @{
Subject = "CN=$($SubjectName)"
CertStoreLocation = "Cert:\$($CertificateStore)\My"
KeyExportPolicy = "Exportable"
KeySpec = "Signature"
NotAfter = (Get-Date).AddMonths($($ValidityPeriodMonths))
}
$Certificate = New-SelfSignedCertificate @NewCertificateParams
# Export the public key only
$ExportPublicKeyParams = @{
Cert = $Certificate
FilePath = "$($CertificateFolderPath)\$($SubjectName).cer"
}
Export-Certificate @ExportPublicKeyParams
# Export the certificate with the private key
$CertificateThumbprint = $Certificate.Thumbprint
$CertificatePassword = Read-Host -Prompt "Enter password for your certificate: " -AsSecureString
$ExportPfxParams = @{
Cert = "Cert:\$($CertificateStore)\My\$($CertificateThumbprint)"
FilePath = "$($CertificateFolderPath)\$($SubjectName).pfx"
ChainOption = "EndEntityCertOnly"
NoProperties= $null
Password = $CertificatePassword
}
Export-PfxCertificate @ExportPfxParams
# *** DELETE THE CERTIFICATE ***
try {
# Get the certificate again, as it might have a different path after export.
$CertificateToDelete = Get-ChildItem "Cert:\$($CertificateStore)\My\$($CertificateThumbprint)"
if ($CertificateToDelete) {
Remove-Item -Path $CertificateToDelete.PSPath -Force -Confirm:$false # -Confirm:$false suppresses confirmation prompts
Write-Host "Certificate '$SubjectName' deleted successfully."
} else {
Write-Warning "Certificate '$SubjectName' not found for deletion."
}
}
catch {
Write-Error "Error deleting certificate: $_"
}
# Best Practice: Clear the secure string password from memory
$CertificatePassword.Dispose()
# Best Practice: Check if the files were created
if (Test-Path "$($CertificateFolderPath)\$($SubjectName).cer") {
Write-Host "Public key certificate exported successfully."
} else {
Write-Warning "Public key certificate export failed."
}
if (Test-Path "$($CertificateFolderPath)\$($SubjectName).pfx") {
Write-Host "PFX certificate exported successfully."
} else {
Write-Warning "PFX certificate export failed."
}
Write-Host "Certificate Thumbprint ==> $CertificateThumbprint"
When you run the PowerShell script, you will get two certificates, and the script’s output will be the certificate thumbprint. Copy the thumbprint to Notepad.


Install (Rightclick Install PFX) the PFX certificate into the Current user’s “Personal” certificate store and make it ‘NonExportable.’ If you use a self-signed certificate, copy the certificate to the “Trusted Root Certification Authorities” as well.

Upload the Certificate (.cer) file to the Azure Functions authentication provider object.
From within the Authentication Provider object (App registration), click on the ‘Manage/Certificate and secrets‘ node and then on the ‘Certificates‘ tab. Click on the ‘Upload certificate‘ button.

Verify if the imported thumbprint matches the thumbprint that you copied to Notepad.

Prepare Powershell modules for upload to Azure Function App
Let’s upload the following PowerShell modules to the Function App from your computer. The reason for doing so is simple: The Function App will time-out if the modules were to be downloaded and installed at Function run time.
Install the following modules on your computer. Aim to download and install the latest but stable version.
Az.Accounts | 4.0.2 |
Az.ManagedServiceIdentity | 1.3.0 |
ExchangeOnlineManagement | 3.7.1 |
PowerShellGet | 2.2.5 |
PackageManagement | 1.4.8.1 |
Microsoft.Graph.Users | 2.19.0 |
Microsoft.Graph.Authentication | 2.24.0 |
Microsoft.Graph.Sites | 2.24.0 |
PnP.PowerShell | 2.12.0 |
Some modules might not be required, but we recommend uploading them. These modules will allow you to expand the Azure Function to accommodate your organization-specific needs.
Install the latest or the most appropriate version of each of the above-listed modules on your computer. The newly installed modules will be found at the following location, Assuming the ‘C:’ drive contains your Program Files folder.
C:\Program Files\WindowsPowerShell\Modules
Let’s copy the required modules from the above location to a temp location of your choice.

Look for the required PowerShell modules and copy the module folder to your temporary location. Each module could have one or more versions within subfolders. For the sake of space management, we recommend deleting unnecessary versions.

Compress all of the above folders into a ZIP file and call the ZIP file “PSModules.zip“.

Add references to Powershell modules in the Azure Function App
Open the Azure Function App in the portal. Go to ‘Function/App files‘.
Paste the following content into the ‘requirements.psd1′ file. Make sure you use the correct version for each of these modules.
'Az.Accounts' = '4.0.2'
'Az.ManagedServiceIdentity' = '1.3.0'
'ExchangeOnlineManagement' = '3.7.1'
'PowerShellGet' = '2.2.5'
'PackageManagement' = '1.4.8.1'
'Microsoft.Graph.Users' = '2.19.0'
'Microsoft.Graph.Authentication' = '2.24.0'
'Microsoft.Graph.Sites' = '2.24.0'
'PnP.PowerShell' = '2.12.0'
Paste the above content under the commented module #’AZ’ = ’13.*’.

Please Save your Function App before you proceed with the setup.
Deploy Powershell modules to the Azure Function App
Upload the ZIP file containing the Powershell modules to the Function App. Open the Function App in the portal and go to ‘Development Tools/Advanced Tools.‘


Clicking ‘Go‘ will open Microsoft KUDU+ Environment. Click on the ‘Debug console‘ menu item and then ‘PowerShell.‘

Click on the directory structure at the top. Change directory to ‘site/wwwroot/‘. Create a directory called “Modules“.


The individual module folders will be placed inside the “Modules” directory. Click to get into the Modules directory.
Drag the ‘PSModules.zip‘ file into the area highlighted in the image below.

After uploading the Powershell modules, the ‘Modules‘ directory will look similar to the image below.

!!! RESTART the Azure Function App from the overview page.
The Azure function is now ready to receive a request from WPSecure. The rest of the article will explain how to set up a WPSecure package to call the Azure function.
Ensure you save the Notepad file with the necessary inputs for future use. The WPSecure Beacon will use the highlighted items to communicate with this Azure Function App.

Enabling or disabling WPSecure Beacon
By default, automatic Beacon is disabled. To enable it, run the following command as an administrator. The executable is in the WPSecure application directory within the ProgramFiles (x86) directory.
"C:\Program Files (x86)\wpsecure\wpsecure-set.exe" -defaultdomain wpsecure-no-ui-32456.azurewebsites.net -frequency 4 -functionkey 8HPIF213fgKl9L-570aQsawkiUO-pzgiXAF4pwnxd45dgjFuwTjnnQ== -tenantid 9f4567d6-7541-490f-a49a-001d5671f -clientid 8d063d4dd-544c-4073-b298-bfcsdf3ad8 -thumbprint 0DE027D62378965905EF1DBC906ACD5SD3AA9 -version 7.3.56
-defaultdomain | Notepad: Default Domain |
-frequency | 2 or 4 or 6 or 8 |
-functionkey | Notepad: Function Key |
-tenantid | Notepad: Tenant ID |
-clientid | Notepad: Identify Provider Application (ClientID) |
-thumbprint | Notepad: ThumbPrint |
-version | Registry detection after deployment (See below) |
The above command can be run either as an Intune/SCCM application or as a baseline in the SYSTEM context.
To detect the setting’s presence, set your detection methods to look for the following registry value and use the operator “greater than or equal to” to compare the value as a TYPE: Version.


To disable, run the following command as an administrator.
"C:\Program Files (x86)\wpsecure\wpsecure-set.exe" -dbeacon
Pending Reboot and Device Compliance attributes
WPSecure does not calculate these attributes; these states are just picked up and uploaded by the Becon. Organizations can run their baselines to populate the Registry DWord values below. The Beacon will send the status to SharePoint via the Azure Function.
‘pendingreboot‘ value of 1 would mean the device is pending a reboot, and a ‘devicenotcompliant‘ value of 1 would mean the device is not compliant.

Troubleshooting
After a successful setup, the process runs on autopilot at the set frequency (2, 4, 6,or 8 hours). But getting there is never a straight line. That is when ‘Log stream‘ plays a vital role.
- Devices have to authenticate to access the function.
- Devices must use the correct “function code” to access the function.
- If no logs appear in the “Log steam,” the device has not correctly authenticated to the Function App.
- From within the function, all the PowerShell modules should have been loaded.
- The System assigned managed identity should have access to Exchange Online.
Client-side logs will be in ‘wpsecure-set.log‘ in the ‘%TEMP%’ directory
