Upload-AutopilotHash.ps1

<#PSScriptInfo
 
.VERSION 1.0.2
.GUID 9f4f1b7a-3b7a-49b3-bd7d-5a5c86d50aab
.AUTHOR Shishir Kushawaha
.COMPANYNAME Shishir Kushawaha
.COPYRIGHT (c) 2025 Your Company. All rights reserved.
.TAGS Intune Autopilot Webhook DeviceManagement
.LICENSEURI https://opensource.org/licenses/MIT
.PROJECTURI https://github.com/POWERSHELLCAM
.RELEASENOTES
    Initial release of Upload-AutopilotHash script.
#>


<#
.SYNOPSIS
    Uploads Windows Autopilot hardware hash to an Azure Automation Webhook.
 
.DESCRIPTION
    Collects device hardware hash, serial number, and product key, then uploads it
    securely to a webhook with GroupTag and password authentication.
    Includes logging and connectivity checks.
 
.PARAMETER GroupTag
    Autopilot GroupTag value to be assigned to the device.
 
.PARAMETER WebhookPassword
    Password/token used for authentication when calling the webhook.
 
.PARAMETER WebhookUrl
    The target webhook URL.
 
.PARAMETER LogPath
    Path where logs will be written. Default: C:\Temp\Logs
 
.EXAMPLE
    Upload-AutopilotHash.ps1 -GroupTag "HR-Laptops" -WebhookPassword "P@ssw0rd" -WebhookUrl "https://contoso.webhook.azure-automation.net/..."
 
.NOTES
    Author: Shishir Kushawaha
    Email: srktcet@outlook.com
    Version: 1.0.2
#>


[CmdletBinding()]
param(
    [Parameter(Mandatory = $true)]
    [string]$GroupTag,

    [Parameter(Mandatory = $true)]
    [string]$WebhookPassword,

    [Parameter(Mandatory = $true)]
    [string]$WebhookUrl,

    [string]$LogPath = "C:\Temp\Autopilot\Logs"
)

#region Logging
$logfile = Join-Path $LogPath "APEnrollmentProfile.log"
if (!(Test-Path $LogPath)) 
{
    New-Item -Path $LogPath -ItemType Directory -Force | Out-Null
}

function Write-Log 
{
    param(
        [string]$Message,
        [ValidateSet("INFO","SUCCESS","WARN","ERROR")] 
        [string]$LogLevel = 'INFO'
    )

    $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
    $logEntry  = "$timestamp [$LogLevel] - $Message"

    # Write to log file
    Add-Content -Path $logfile -Value $logEntry

    # Color-coded console output
    switch ($LogLevel) 
    {
        "SUCCESS" { Write-Host $logEntry -ForegroundColor Green }
        "ERROR"   { Write-Host $logEntry -ForegroundColor Red }
        "WARN"    { Write-Host $logEntry -ForegroundColor Yellow }
        default   { Write-Host $logEntry -ForegroundColor Cyan }
    }
}

#endregion Logging

function Test-InternetConnection 
{
    try 
    {
        return Test-Connection -ComputerName "8.8.8.8" -Count 2 -Quiet
    } 
    catch 
    {
        return $false
    }
}

function Test-Webhook 
{
    param ([string]$URL)
    try 
    {
        if (Test-InternetConnection) 
        {
            Write-Log "Internet is available." "SUCCESS"
            $conn = Test-NetConnection -ComputerName ([uri]$URL).Host -Port 443
            if ($conn.TcpTestSucceeded) 
            {
                Write-Log "Webhook reachable. Remote IP = $($conn.RemoteAddress.IPAddressToString)" "SUCCESS"
            } 
            else 
            {
                Write-Log "Webhook is NOT reachable." "ERROR"
            }
        } 
        else 
        {
            Write-Log "No internet access." "ERROR"
        }
    } 
    catch 
    {
        Write-Log "Failed to test webhook: $_" "ERROR"
    }
}

# Check if running as Administrator
function Test-Admin 
{
    $currentUser = [Security.Principal.WindowsIdentity]::GetCurrent()
    $principal   = New-Object Security.Principal.WindowsPrincipal($currentUser)
    return $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
}

Write-Output " " | Out-File $logfile -Append
Write-Log "SECTION START : Upload Hardware Hash with Webhook."
# Check at script start
if (-not (Test-Admin)) 
{
    Write-Log "This script requires Administrator privileges. Please run PowerShell as Administrator." "ERROR"
    exit 1
}
else 
{
    Write-Log "✅ Script is running with Administrator privileges." "SUCCESS"
}
Test-Webhook -URL $WebhookUrl

try 
{
    Write-Log "Gathering device details..." "INFO"
    $DeviceHashData = (Get-WmiObject -Namespace "root/cimv2/mdm/dmmap" `
        -Class "MDM_DevDetail_Ext01" `
        -Filter "InstanceID='Ext' AND ParentID='./DevDetail'" -Verbose:$false `
        -ErrorAction Stop).DeviceHardwareData

    $SerialNumber = (Get-WmiObject -Class "Win32_BIOS" -Verbose:$false -ErrorAction Stop).SerialNumber
    $ProductKey   = (Get-WmiObject -Class "SoftwareLicensingService" -Verbose:$false -ErrorAction Stop).OA3xOriginalProductKey

    Write-Log "Serial Number = $SerialNumber" "SUCCESS"
    Write-Log "Product Key = $ProductKey" "SUCCESS"
    Write-Log "Group Tag = $GroupTag" "SUCCESS"
    $body = @{
    ProductKey     = $ProductKey
    SerialNumber   = $SerialNumber
    DeviceHashData = $DeviceHashData
    GroupTag       = $GroupTag
    }

    $params = @{
        ContentType = 'application/json'
        Headers     = @{
            'from'    = 'AutoPilotDeviceInfo'
            'Date'    = (Get-Date)
            'message' = $WebhookPassword
        }
        Body   = ($body | ConvertTo-Json -Depth 5)
        Method = 'Post'
        Uri    = $WebhookUrl
    }
}
catch 
{
    Write-Log "❌ Failed to gather device details. Error: $($_.Exception.Message)" "ERROR"
}
finally 
{
    Write-Log "Device details collection attempt completed." "SUCCESS"
}

try 
{
    Write-Log "Sending hardware hash to Azure Automation via webhook..."
    Invoke-RestMethod @params -Verbose
    write-log "Sending hardware hash to Azure Automation via webhook completed" "SUCCESS"
} 
catch 
{
    Write-Log "Failed to send the hardware hash data to Azure Automation: $_" "ERROR"
}
write-log "Log file located at: $logfile"
Write-Log "SECTION END : Upload Hardware Hash with Webhook."