$CustomerId = "" # Log Analytics Workspace ID $SharedKey = '' # Log Analytics Workspace Primary Key $LogType = "DellBIOSUpdate" # Custom log to create in lo Analytics $TimeStampField = "" # let to blank #******************************************************************************* # Log analytics functions # More info there: https://docs.microsoft.com/en-us/azure/azure-monitor/logs/data-collector-api Function Build-Signature ($customerId, $sharedKey, $date, $contentLength, $method, $contentType, $resource) { $xHeaders = "x-ms-date:" + $date $stringToHash = $method + "`n" + $contentLength + "`n" + $contentType + "`n" + $xHeaders + "`n" + $resource $bytesToHash = [Text.Encoding]::UTF8.GetBytes($stringToHash) $keyBytes = [Convert]::FromBase64String($sharedKey) $sha256 = New-Object System.Security.Cryptography.HMACSHA256 $sha256.Key = $keyBytes $calculatedHash = $sha256.ComputeHash($bytesToHash) $encodedHash = [Convert]::ToBase64String($calculatedHash) $authorization = 'SharedKey {0}:{1}' -f $customerId,$encodedHash return $authorization } # Create the function to create and post the request # More info there: https://docs.microsoft.com/en-us/azure/azure-monitor/logs/data-collector-api Function Post-LogAnalyticsData($customerId, $sharedKey, $body, $logType) { $method = "POST" $contentType = "application/json" $resource = "/api/logs" $rfc1123date = [DateTime]::UtcNow.ToString("r") $contentLength = $body.Length $signature = Build-Signature ` -customerId $customerId ` -sharedKey $sharedKey ` -date $rfc1123date ` -contentLength $contentLength ` -method $method ` -contentType $contentType ` -resource $resource $uri = "https://" + $customerId + ".ods.opinsights.azure.com" + $resource + "?api-version=2016-04-01" $headers = @{ "Authorization" = $signature; "Log-Type" = $logType; "x-ms-date" = $rfc1123date; "time-generated-field" = $TimeStampField; } $response = Invoke-WebRequest -Uri $uri -Method $method -ContentType $contentType -Headers $headers -Body $body -UseBasicParsing return $response.StatusCode } $WMI_computersystem = gwmi win32_computersystem $Manufacturer = $WMI_computersystem.manufacturer If($Manufacturer -notlike "*dell*") { write-output "Poste non Dell" EXIT 0 } $ddlCategoryWeb =[xml]@' '@ $Script:dictionaryCategory = @{} $ddlCategoryWeb.select.option | Foreach {$Script:dictionaryCategory[$_.value] = $_.'#text'.Trim()} $Script:ddlCategoryWeb =[xml]@' '@ Class Dell { Static hidden [String]$_vendorName = "Dell" hidden [Object[]] $_deviceCatalog hidden [Object[]] $_deviceImgCatalog # Contructor Dell() { $this._deviceCatalog = [Dell]::GetDevicesCatalog() } ##################################################################### # Get all Data from DELL (Gz format) ##################################################################### # https://www.dell.com/support/components/eula/en-us/eula/api Static hidden [Object[]]GetDevicesCatalog() { $result = Invoke-WebRequest -Uri "https://www.dell.com/support/home/en-us/api/catalog/autosuggest" -UseBasicParsing -Headers @{ "method"="GET" "authority"="www.dell.com" "scheme"="https" "cache-control"="max-age=0" "upgrade-insecure-requests"="1" "accept"="text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9" "sec-fetch-site"="none" "sec-fetch-mode"="navigate" "sec-fetch-user"="?1" "sec-fetch-dest"="document" "accept-encoding"="gzip, deflate, br" "accept-language"="en-US,en;q=0.9" } $jsonObject = $($result.Content | ConvertFrom-Json) | Select-Object -Property "PN","PC" return $jsonObject } ######################################################################### # Find Model Based on User input ######################################################################### [Object[]]FindModel($userInputModel) { $SearchResultFormatted = @() $userSearchResult = $this._deviceCatalog.Where({$_.PN -eq $userInputModel}) foreach($obj in $userSearchResult){ $SearchResultFormatted += [PSCustomObject]@{ Name=$obj.PN; Guid=$obj.PC; Path="/product/$($obj.PC)"; Image= $( $obj = $this._deviceImgCatalog.Where({$_.Id -eq $obj.PC}) if($obj.Image){ "https:$($obj.Image)" }else{ 'https://i.dell.com/is/image/DellContent/content/dam/global-site-design/product_images/esupport/icons/esupport-blank-space-v2.png' } ) } } return $SearchResultFormatted } ######################################################################### # Get Json Data for a Dell Device form its GUID ######################################################################### hidden [Object[]] GetModelWebResponse($modelGUID) { # ==== For Download ======= $modelGzURL = "https://downloads.dell.com/published/data/drivers/$($ModelGUID).gz" $gzContent = Invoke-WebRequest -Uri $modelGzURL -UseBasicParsing -Headers @{ "method"="GET" "authority"="www.dell.com" "scheme"="https" "cache-control"="max-age=0" "upgrade-insecure-requests"="1" "accept"="text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9" "sec-fetch-site"="none" "sec-fetch-mode"="navigate" "sec-fetch-user"="?1" "sec-fetch-dest"="document" "accept-language"="en-US,en;q=0.9" } # === Convert Stream Data to viewable Content ===== $data = $gzContent.Content $memoryStream = [System.IO.MemoryStream]::new() $memoryStream.Write($data, 0, $data.Length) $memoryStream.Seek(0,0) | Out-Null $gZipStream = [System.IO.Compression.GZipStream]::new($memoryStream, [System.IO.Compression.CompressionMode]::Decompress) $streamReader = [System.IO.StreamReader]::new($gZipStream) $xmlModelInputRaw = $streamReader.readtoend() # === Parse content ======================= $xmlModelInput = New-Object -TypeName System.Xml.XmlDocument $xmlModelInput.LoadXml($xmlModelInputRaw) return $xmlModelInput } ######################################################################### # Load All Drivers to exploitable format ######################################################################### hidden [Object[]]LoadDriversFromWebResponse($webresponse) { $DownloadItemsObj = [Collections.ArrayList]@() if($webresponse.Product.Drivers){ $DownloadItemsRaw = $webresponse.Product.Drivers.Driver | Sort-Object -Property Title $DownloadItemsRawGrouped = $DownloadItemsRaw | Group-Object -Property Title ForEach ($Itemgroup in $DownloadItemsRawGrouped){ $item = $Itemgroup.group | Sort-Object -Property LastUpdateDate | Select-Object -Last 1 [Array]$ExeFiles = $item.File $current = [PSCustomObject]@{ Title =$item.Title; Category=$Script:dictionaryCategory[$item.Category]; Class=$item.Type; OperatingSystemKeys=$item.OS.Split(","); Files= [Array]($ExeFiles | ForEach-Object { if($_){ [PSCustomObject]@{ IsSelected=$false; ID=$item.ID; Name=$_.FileName.Split('/')[-1]; Size="$([Math]::Round($_.Size/1MB, 2)) MB"; Type=$item.Type; Version=$item.VendorVersion URL="https://dl.dell.com/$($_.FileName)"; Priority=$item.Importance ; Date=$item.LastUpdateDate } } }) } $DownloadItemsObj.Add($current) | Out-Null } # ForEach ($Itemgroup in $DownloadItemsRawGrouped){ # $item = $null # if($Itemgroup.Group.Count -ge 2){ # $maximum = 0 # foreach($vendorVer in $Itemgroup.Group){ # if($vendorVer.VendorVersion -gt $maximum){ # $maximum = $vendorVer.VendorVersion # $item = $vendorVer # } # } # }else{ # $item = $Itemgroup.Group # } # [Array]$ExeFiles = $item.File # $current = [PSCustomObject]@{ # Title =$item.Title; # Category=$Script:dictionaryCategory[$item.Category]; # Class=$item.Type; # OperatingSystemKeys=$item.OS.Split(","); # Files= [Array]($ExeFiles | ForEach-Object { # if($_){ # [PSCustomObject]@{ # IsSelected=$false; # ID=$item.ID; # Name=$_.FileName.Split('/')[-1]; # Size="$([Math]::Round($_.Size/1MB, 2)) MB"; # Type=$item.Type; # Version=$item.VendorVersion # URL="https://dl.dell.com/$($_.FileName)"; # Priority=$item.Importance ; # Date=$item.LastUpdateDate # } # } # }) # } # $DownloadItemsObj.Add($current) | Out-Null # } } return $DownloadItemsObj } } $SerialNumber = $((Get-WmiObject -Class Win32_BIOS).SerialNumber).Trim() $CurrentOS = (gwmi Win32_OperatingSystem).Version Try { $System_SKU = $((Get-WmiObject -Class Win32_ComputerSystem).SystemSKUNumber).Trim() } catch { Try { $System_SKU = $((Get-ItemProperty -Path HKLM:\HARDWARE\DESCRIPTION\System\BIOS).SystemSKU).Trim() } catch { $System_SKU = "Unknown" } } $Current_User_Profile = Get-ChildItem Registry::\HKEY_USERS -ea silentlycontinue | Where-Object { Test-Path "$($_.pspath)\Volatile Environment" } | ForEach-Object { (Get-ItemProperty "$($_.pspath)\Volatile Environment").USERPROFILE } $Username = $Current_User_Profile.split("\")[2] $Chassis = (Get-CimInstance -ClassName Win32_SystemEnclosure).ChassisTypes $Device_Chassis = [string]$chassis If($Chassis -eq 9 -or $Chassis -eq 10 -or $Chassis -eq 14 -or $Chassis -eq 8 -or $Chassis -eq 11 -or $Chassis -eq 12 -or $Chassis -eq 18 -or $Chassis -eq 21 -or $Chassis -eq 31 -or $Chassis -eq 32) { $Chassis_Type = "Laptop" } else { $Chassis_Type = "Desktop" } $BIOS_Version = Get-ciminstance -class win32_bios $Current_BIOS_Version = $BIOS_Version.SMBIOSBIOSVersion $Current_BIOS_Version_ID = $Current_BIOS_Version.Split("(")[0] $BIOS_release_date = (gwmi win32_bios | select *).ReleaseDate $Format_BIOS_release_date = [DateTime]::new((([wmi]"").ConvertToDateTime($BIOS_release_date)).Ticks, 'Local').ToUniversalTime() $Get_Current_Date = get-date $Diff_CurrentBIOS_and_Today = $Get_Current_Date - $Format_BIOS_release_date $Diff_Today_CurrentBIOS = $Diff_CurrentBIOS_and_Today.Days $BIOS_Maj_Version = $BIOS_Version.SystemBiosMajorVersion $BIOS_Min_Version = $BIOS_Version.SystemBiosMinorVersion $Script:Get_Current_BIOS_Version = "$BIOS_Maj_Version.$BIOS_Min_Version" $Get_Current_BIOS_Version = $Current_BIOS_Version $Get_Current_BIOS_Version_Formated = [System.Version]$Current_BIOS_Version $WMI_computersystem = gwmi win32_computersystem $Get_Current_Model = (($WMI_computersystem).Model) $BIOS_Ver_Model = "$Get_Current_BIOS_Version ($Get_Current_Model)" # $Get_Current_Model = "Latitude E7270" # $Get_Current_Model = "Latitude E5270" # $Get_Current_Model = "XPS 13 9360" # $Get_Current_Model = "Latitude 7390" # $Get_Current_Model = "Latitude 5320" # $Get_Current_Model = "Precision 5530" # $Get_Current_Model = "Precision 5540" $RunspaceScopeVendor = [Dell]::new() $Search_Model = $RunspaceScopeVendor.FindModel("$Get_Current_Model") If($Search_Model -ne $null) { $Get_GUID = $Search_Model.Guid $wbrsp = $RunspaceScopeVendor.GetModelWebResponse("$Get_GUID") $DriversModeldatas = $RunspaceScopeVendor.LoadDriversFromWebResponse($wbrsp) $DriversModelDatasForOsType = [Array]($DriversModeldatas | Where-Object {($_.Title -like "*System BIOS*" )} ) $Get_BIOS_Update = $DriversModelDatasForOsType.files | Where {$_ -like "*EXE*"} $Get_New_BIOS_Version = $Get_BIOS_Update.version $Get_New_BIOS_Version_Formated = [System.Version]$Get_New_BIOS_Version $Get_New_BIOS_Date = $Get_BIOS_Update.Date $Get_New_BIOS_ID = $Get_BIOS_Update.ID [int]$Get_New_BIOS_Date_Month = $Get_New_BIOS_Date.split("/")[0] [int]$Get_New_BIOS_Date_Day = $Get_New_BIOS_Date.split("/")[1] [int]$Get_New_BIOS_Date_Year = $Get_New_BIOS_Date.split("/")[2] If($Get_New_BIOS_Date_month -lt 10) { $Get_Month = "0$Get_New_BIOS_Date_month" } Else { $Get_Month = "$Get_New_BIOS_Date_month" } If($Get_New_BIOS_Date_Day -lt 10) { $Get_Day = "0$Get_New_BIOS_Date_Day" } Else { $Get_Day = "$Get_New_BIOS_Date_Day" } $Get_New_BIOS_Date = "$Get_Month/$Get_Day/$Get_New_BIOS_Date_Year" $Get_Converted_BIOS_Date = [Datetime]::ParseExact($Get_New_BIOS_Date, 'MM/dd/yyyy', $null) # $Is_BIOS_NotUptoDate = ($Get_Current_BIOS_Version -lt $Get_New_BIOS_Version) $Is_BIOS_NotUptoDate = ($Get_Current_BIOS_Version_Formated -lt $Get_New_BIOS_Version_Formated) If($Is_BIOS_NotUptoDate -eq $null) { $Script:Script_Status = "Error" $Script:BIOS_UpToDate = "" $Script:BIOS_New_Version = $Get_New_BIOS_Version $Script:BIOSDaysOld = 0 $Script:Exit_Status = 0 } ElseIf($Is_BIOS_NotUptoDate -eq $True) { $BIOSDaysOld = ($Get_Converted_BIOS_Date - $Format_BIOS_release_date).Days $Script:Script_Status = "Success" $Script:BIOS_UpToDate = "No" $Script:BIOS_New_Version = $Get_New_BIOS_Version $Script:Exit_Status = 1 } Else { $Script:Script_Status = "Success" $Script:BIOS_UpToDate = "Yes" $Script:BIOS_New_Version = $Get_New_BIOS_Version $Script:Exit_Status = 0 } If($BIOSDaysOld -ge 1 -and $BIOSDaysOld -lt 180) { $Diff_Delay = "1_180" } ElseIf($BIOSDaysOld -ge 180 -and $BIOSDaysOld -lt 365) { $Diff_Delay = "180_365" } ElseIf($BIOSDaysOld -ge 365 -and $BIOSDaysOld -lt 730) { $Diff_Delay = "365_730" } ElseIf($BIOSDaysOld -ge 730) { $Diff_Delay = "730_More" } } # Creating the object to send to Log Analytics custom logs $Properties = [Ordered] @{ "ScriptStatus" = $Script_Status "BIOSUpToDate" = $BIOS_UpToDate "ComputerName" = $env:computername "UserName" = $username "SerialNumber" = $SerialNumber "CurrentOS" = $CurrentOS "SystemSKU" = $System_SKU "ModelFamilyName" = $Get_Current_Model "BIOSCurrentVersion" = $Get_Current_BIOS_Version "BIOSCurrentVersionFull" = $Current_BIOS_Version "BIOSVersionModel" = $BIOS_Ver_Model "CurrentBIOSDate" = $Format_BIOS_release_date "BIOSNewVersion" = $BIOS_New_Version "BIOSNewDate" = $Get_Converted_BIOS_Date "GetNewBIOSID" = $Get_New_BIOS_ID "NotUpdatedSince" = $BIOSDaysOld "DateDiffDelay" = $Diff_Delay "BIOSDaysOld" = $BIOSDaysOld "DiffTodayCurrentBIOS" = $Diff_Today_CurrentBIOS "ChassisDevice" = $Device_Chassis "ChassisType" = $Chassis_Type } $BIOSUpdateResult = New-Object -TypeName "PSObject" -Property $Properties # $BIOSUpdateResult $BIOSUpdateResultJson = $BIOSUpdateResult | ConvertTo-Json $params = @{ CustomerId = $customerId SharedKey = $sharedKey Body = ([System.Text.Encoding]::UTF8.GetBytes($BIOSUpdateResultJson)) LogType = $LogType } $LogResponse = Post-LogAnalyticsData @params If($Exit_Status -eq 1) { EXIT 1 } Else { EXIT 0 }