Jump to content


anyweb

Root Admin
  • Posts

    9,110
  • Joined

  • Last visited

  • Days Won

    363

anyweb last won the day on April 18

anyweb had the most liked content!

About anyweb

  • Birthday 11/24/1966

Contact Methods

  • Website URL
    http://www.niallbrady.com

Profile Information

  • Gender
    Male
  • Location
    Sweden
  • Interests
    Modern management of devices with Microsoft Intune and System Center Configuration Manager

Recent Profile Visitors

4,181,309 profile views

anyweb's Achievements

  1. Introduction In part 1 I showed you how to prepare Azure for the PC Buyback app, in part 2 you added the Win32 app, deployed it and saw how it behaved on a Windows Autopilot registered device. In this part we'll add some additional functionality namely logging to Azure tables so that we have a record of when the PC went through the process of PC Buyback. To set this up we'll add another 2 http triggers, and then configure their integration. Note: If you are new to this it might seem overwhelming, don't panic, take your time and follow my guide, if you do it correctly you'll get a successful result. This mini series is broken down into the following parts: PC Buyback for Windows Autopilot devices - part 1 PC Buyback for Windows Autopilot devices - part 2 PC Buyback for Windows Autopilot devices - part 3 <--- You are here Step 1. Create the AddDataToAzure http trigger In the previously created PCBuyback Function app, create a new http trigger called AddDataToAzure In the newly created Http trigger, click on Code + Test and paste in the following code to overwrite the existing code... ####################################################################################################################################### # use this code in a http trigger as part of a function app # Niall Brady, 2024/05/08 # for more info see https://www.windows-noob.com/forums/topic/23414-pc-buyback-for-windows-autopilot-devices-part-3 # https://docs.microsoft.com/en-us/azure/azure-functions/functions-reference-powershell?tabs=portal ####################################################################################################################################### using namespace System.Net; using namespace System; #using namespace System.DateTime; # Input bindings are passed in via param block. param($Request, $TriggerMetadata, $inputTable) $Tenant = "windowsnoob.com" $triggerName = "ADD data TO Azure Table" # Write to the Azure Functions log stream. Write-Host "PowerShell HTTP trigger function processed a request." # Interact with query parameters or the body of the request. $ComputerName = $Request.Query.ComputerName if (-not $ComputerName) { $ComputerName = $Request.Body.ComputerName } $UserName = $Request.Query.UserName if (-not $UserName) { $UserName = $Request.Body.UserName } $Model = $Request.Query.Model if (-not $Model) { $Model = $Request.Body.Model } $Manufacturer = $Request.Query.Manufacturer if (-not $Manufacturer) { $Manufacturer = $Request.Body.Manufacturer } $Serial = $Request.Query.Serial if (-not $Serial) { $Serial = $Request.Body.Serial } #$DateReset = $Request.Query.DateReset #if (-not $DateReset) { # $DateReset = $Request.Body.DateReset #} $Status = $Request.Query.Status if (-not $Status) { $Status = $Request.Body.Status } $Reason = $Request.Query.Reason if (-not $Reason) { $Reason = $Request.Body.Reason } $ResetType = $Request.Query.ResetType if (-not $ResetType) { $ResetType = $Request.Body.ResetType } $a = Get-Date $body = $body + "$a ------------------------------------`n" $a = Get-Date $body = $body + "$a Starting the following trigger: '$triggerName'.`n" $a = Get-Date $body = $body + "$a Connected to tenant: '$Tenant'.`n" if ($ComputerName) { $a = Get-Date $body = $body + "$a Adding this computer to Azure Tables: '$ComputerName'.`n" #} #fix the date #$NewDate = $(get-date($DateReset) -UFormat '+%Y-%m-%dT%H:%M:%S.000Z') #$DateReset = $NewDate $a = Get-Date $body = $body + "$a Get next row key....`n" #$nextRowKey=$([int]$(($inputTable.RowKey|measure -Maximum).Maximum)+1) $nextRowKey=Get-Random $a = Get-Date $body = $body + "$a nextRowKey = '$nextRowKey'.`n" # this will be the row key that we insert in this operation # Input row into DB #$tableStorageItems = @() Add-Type @" public struct rowitem { public System.String PartitionKey; public System.String RowKey; public System.String ComputerName; public System.String UserName; public System.String Model; public System.String Manufacturer; public System.String Serial; public System.String Status; public System.String Reason; public System.String ResetType; } "@ $PCBuyback = New-Object rowitem $PCBuyback.PartitionKey = 1 $PCBuyback.RowKey = $nextRowKey.ToString() $PCBuyback.ComputerName = $ComputerName $PCBuyback.UserName = $UserName $PCBuyback.Model = $Model $PCBuyback.Manufacturer = $Manufacturer $PCBuyback.Serial = $Serial $PCBuyback.Status = $Status $PCBuyback.Reason = $Reason $PCBuyback.ResetType = $ResetType #$tableStorageItems += $PCBuyback # insert the data $Result = Push-OutputBinding -Name outputTable -Value $PCBuyback $body = $body + " Adding the data returned (usually blank...): $Result `n" } $a = get-date $body = $body + "$a Exiting Azure function.`n" $a = Get-Date $body = $body + "$a ------------------------------------`n" # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ StatusCode = [HttpStatusCode]::OK Body = $body }) Save the changes, like so... Step 2. Modify the http trigger Integration In the new http trigger AddDataToAzure, click on Integration and then click on Add input In the Binding Type drop down menu, select Azure Table Storage, in the Storage account connection click on New and select your pcbuyback storage account (which was created during part 1 in the initial creation of the function app. Change the Table name to PCBuyback. When done, click on Add. Next, do the same thing for Output by clicking on Add output, then configure it as shown in the screenshot below. Finally click Add. After adding both the input and output, the integration should appear like this. Step 3. Create the VerifyDataAdded http trigger In the previously created PCBuyback Function app, create a new http trigger called VerifyDataAdded In the newly created Http trigger, click on Code + Test and paste in the following code to overwrite the existing code... ####################################################################################################################################### # use this code in a http trigger as part of a function app # Niall Brady, 2024/05/08 # for more info see https://www.windows-noob.com/forums/topic/23414-pc-buyback-for-windows-autopilot-devices-part-3 # https://docs.microsoft.com/en-us/azure/azure-functions/functions-reference-powershell?tabs=portal ####################################################################################################################################### using namespace System.Net # Input bindings are passed in via param block. param($Request, $TriggerMetadata, $inputTable) $Tenant = "windowsnoob.com" $triggerName = "VerifyDataAdded" # Write to the Azure Functions log stream. Write-Host "PowerShell HTTP trigger function processed a request." # Interact with query parameters or the body of the request. $nextRowKey = $Request.Query.nextRowKey if (-not $nextRowKey) { $nextRowKey = $Request.Body.nextRowKey } $CheckComputerName = $Request.Query.CheckComputerName if (-not $CheckComputerName) { $CheckComputerName = $Request.Body.CheckComputerName } $a = Get-Date $body = $body + "$a ------------------------------------`n" $a = Get-Date $body = $body + "$a Starting the following trigger: '$triggerName'.`n" $a = Get-Date $body = $body + "$a Connected to tenant: '$Tenant'.`n" if ($nextRowKey -and $CheckComputerName) { $a = Get-Date $body = $body + "$a Checking the following row: '$nextRowKey'.`n" $body = $body + "$a Looking for this computername: '$CheckComputerName'.`n" #} #Put all table rows into $table $table="" foreach($row in $inputTable){ $table+="$($row.PartitionKey) - $($row.RowKey) - $($row.ComputerName) - $($row.UserName) - $($row.Model) - $($row.Manufacturer) - $($row.Serial) - $($row.Status) - $($row.Reason) - $($row.ResetType) " } # print out the results... #write-host ">>>>>$table<<<<<" #validate section #$body = $body + "Validate: $($($inputTable|Where-Object -Property RowKey -EQ 12).ComputerName)" $a = Get-Date $found = $($($inputTable|Where-Object -Property RowKey -EQ $nextRowKey).ComputerName) $body = $body + "$a ComputerName found: $found`n" #write-host "DEBUG: found " $found if ($found -match $CheckComputerName) { $a = Get-Date $body = $body + "$a FOUND a MATCH :-)`n" } else { $a = Get-Date $body = $body + "$a sorry, did not find a match :-(`n" } } $a = get-date $body = $body + "$a Exiting Azure function.`n" $a = Get-Date $body = $body + "$a ------------------------------------`n" # show the output to the browser...Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ StatusCode = [HttpStatusCode]::OK Body = $body }) Click Save after adding the code above to the new trigger. Step 4. Modify the http trigger Integration In the new http trigger VerifyDataAdded, click on Integration and then click on Add input, configure it like so And next, make the following changes to the output. Step 5. Modify PCBuyback Azure table permissions In your PCBuyback storage (contained within the PCBuyback resource group) modify the Access control (IAM) and add the following role assignments to your user that you want to create the Azure Table in the next step. Storage Table Data Contributor Storage Table Data Reader Step 6. Create the PCBuyback Azure table In your PCBuyback storage (contained within the PCBuyback resource group) which may be named differently depending on how you setup the functionapp, using the Storage browser option in the menu, browse to Tables and click on + Add table as shown here. The Table name must be PCBuyback as shown here, click OK when done. The created PCBuyback table is shown. Step 7. Verify the http triggers Now that you've created the triggers and modified the integration, you'll need to verify that they do what they are supposed to do. Let's start with the AddDataToAzure trigger. To test this, paste in the following text and click on Test/Run. { "ComputerName": "AP-XXXXXXXX", "UserName": "NIALL", "Model": "HP EliteBook 830 G7 Notebook PC", "Manufacturer": "HP", "Serial": "XXXXXXXX", "Status": "OK", "Reason": "PC Buyback (Intune)", "ResetType": "WIPE" } as shown here... If you did everything correctly it'll return a 200 HTTP response code along with the HTTP response content, if not, verify the steps above again. Once the above trigger is tested successfully, click on Overview in the http trigger, and copy the function URL somewhere useful. Finally, you can verify that it actually has poked the data into Azure tables, by browsing to the PCBuyback table and reviewing the data added. Now that you have the RowKey and ComputerName, you can use that data to verify the other trigger in this part, namely the VerifyDataAdded trigger. Use the following code in that Test/Run and modify it as appropriate for your environment. Note: The nextRowKey value will be revealed in the previous test and will be random, you need to provide the exact one from the previous test or copy it from the PCBuyback Azure tables. In other words, the nextRowKey value I'm showing below is unique to my environment and will most likely NOT work in your verification test. { "nextRowKey": "1352755005", "CheckComputerName": "AP-XXXXXXXX" } After running that test, Success ! It found a MATCH. Once the above trigger is tested successfully, click on Overview in the http trigger, and copy the function URL somewhere useful. Step 8. Modify the PCBuyback.ps1 script At this point we are done with the Azure changes and now need to modify the PCBuyback.ps1 PowerShell script. In PowerShell ISE (or VSCode) find this line and remove the # infront of StoreDetailsInAzure as shown below, also remove the $DateReset variable as we don't need it. so that the line looks like this. Next, locate the URI section here and add the two function URLS you copied in the steps above. Save the script Step 9. Upload changes to Intune Use the IntuneWinAppUtil.exe to create a new version of the app that we created in Step 6, part 2 here, After uploading the new intunewin version, log onto a test PC targeted with the PC Buyback app and test it. The app launches by the user clicking on it... and after clicking OK and reading the warning, the PC Buyback process begins in earnest. and while the PC is busy resetting itself as described in Part 2, a record was added to our PCBuyback Azure tables, confirming that the user actually did buy back their PC. Success ! that's it for this blog series, see you in the next one, cheers Niall
  2. have you configured features to allow for the viewing of the keys ? and permissions ? which version of Windows Server are you using ? see >https://learn.microsoft.com/en-us/troubleshoot/windows-server/windows-security/bitlocker-recovery-password-viewer-tool see also > https://blog.michaellecomber.info/2019/05/05/ad-delegate-access-to-view-bitlocker-recovery-keys/ Once added you should be able to review the bitlocker recovery info If your user does not have permission to review these keys, (doman admins will already have access to view the recovery keys) but any other user will not have permissions to view the protected recovery keys. This permission has to be delegated down through the ‘Delegate Access’ wizard found in ‘AD User and Computers’. To do this follow the below: Log into AD Users and Computers Make a new Security group called “Bitlocker-Recovery-Admins” Add the relevant users to the group Navigate to the OU where you want to start the delegation. (The computers must sit in a OU below from starting the delegation) Right-click on the OU and select ‘Delegate Control’ In the ‘Users or Groups’ step enter the newly created ‘Bitlocker-Recovery-Admins’ In the ‘Tasks to Delegate’ select ‘Create a custom task to delegate’ In the Active Directory Object Type dialog, select Only the following objects in the folder. In the list select msFVE-RecoveryInformation objects and click Next For permissions set as ‘Full Control’ and select finish Now any user in our security group will be able to view the Bitlocker recovery keys.
  3. renewing certificates isn't so bad, have a read of my guide here > https://www.niallbrady.com/2020/08/16/how-can-i-replace-an-expired-iis-certificate-in-a-pki-enabled-configmgr-environment/
  4. can you please show me a screenshot of where you are seeing this error ?
  5. Introduction In part 1 I showed you how to prepare Azure for the PC Buyback app, in this part we'll add the Win32 app, deploy it and see how it behaves on a Windows Autopilot registered device. This mini series is broken down into the following parts: PC Buyback for Windows Autopilot devices - part 1 PC Buyback for Windows Autopilot devices - part 2 <--- You are here PC Buyback for Windows Autopilot devices - part 3 Step 1. Download the scripts Download this zip and extract to C:\Dev\Intune\Win32 apps Note: you must be a logged on member of windows-noob.com to download the ZIP PC Buyback - Intune.zip Step 2. Get ServiceUI.exe from MDT You'll need the ServiceUI.exe executable file to display user interfaces (UI) to end users when operating in SYSTEM context. To get the file, download and install MDT somewhere and navigate to C:\Program Files\Microsoft Deployment Toolkit\Templates\Distribution\Tools\x64. To download MDT click here. Copy the 64 bit version of ServiceUI.exe file to your extracted win32app_source folder so it looks like this. Step 3. Get 7Zip for compressing files Download 7Zip and install it. Copy 7z.dll and 7z.exe from the default folder C:\Program Files\7-Zip Copy those 2 files to C:\Dev\Intune\Win32 apps\PC Buyback - Intune\encode In PowerShell ISE run the Encode script.. After it is completed encoding the files, you'll have a bunch of additional text files in the encode folder. Open each text file using notepad, press CTRL+A to mark all the text, then copy using CTRL+C and paste the content of each file using CTRL+V into the corresponding section of the PCBuyback.ps1 script as shown below. Note: The QR code used in the PC Buyback app points to part 1 of this blog series, but you can customize it to point to an internal knowledge base article to assist users with the entire process. One thing to keep in mind, I used https://www.qr-code-generator.com to create the QR code, but after creating it, you'll need to resize it to 118x120 pixels (in MS paint or similar). Step 4. Modify variables In the PCBuyback.ps1 script, configure the following email related variables: $ToAddress $FromAddress $APIkey Next, copy the Function URL for each of the http triggers you created in part 1, below shows you how to do that paste those URLs into the corresponding variable in the script Save the changes to the PCBuyback.ps1 script. Step 5. Get the Microsoft Win32 content prep tool Download the Win32 content prep tool from here. Copy the IntuneWinAppUtil.exe file to your Win32 apps root folder, it should look like this. Open a command prompt and browse to the PCBuyback folder structure. Launch the IntuneWinAppUtil.exe file and answer the following. Please specify the source folder: win32app_source Please specify the setup file: PCBuyback.ps1 Please specify the output folder: win32app_target Do you want to specify catalog folder (Y/N)? n as shown here. Step 6. Add the Win32 app in Intune Log into Intune and add a new Win32 App. Below are some screenshots showing how I've configured the app. For Select app type, select Windows app (Win32) from the drop down menu Click on Select app package file and point it to the pcbuyback.intunewin file in the win32app_target folder, fill in some info about the app, for the logo, click on Select image and point it to the encode folder where the icon file can be used fill in the install commands, point it to install_pcbuyback.cmd fill in the requirements, and for detection rules point it to the detection script in the root of the PC Buyback - Intune files finally deploy it to an Entra ID group that contains the computers that are targeted for buyback, and deploy it as Available. Step 7. Test the app on a device On a test device that is already enrolled into Intune and Windows Autopilot registered, add the device to the azure ad group above and launch Company Portal. The PC Buyback app should appear. Click Install and after a few moments the app should appear. Clicking OK shows a warning and clicking OK to the warning starts the process, after a few moments it will remove the device from Intune, then remove the Windows Autopilot registered device and zip up the logs before emailing them After emailing the logs and confirmation that it's done PC Buyback, it will restart after the restart it will start resetting Windows removing all apps and settings that were on the device After the reset, Windows installs itself again... and after the reinstallation, it's back to the first screen of the OOBE, so the user can now setup their device personally When the user runs PC Buyback an email is sent to the email address you configured... and the process will store details in Azure tables (coming in Part 3) Troubleshooting If the app fails for whatever reason, it will log the details in C:\ProgramData\windowsnoob\PCBuyback\win.ap.pcbuyback.log Below is a sample of that log file from a successfully wiped device 04/06/2024 10:00:42 Starting script: 'Win.AP.PCBuyback' version: '0.0.5' ... 04/06/2024 10:00:42 extracting scripts to 'C:\ProgramData\windowsnoob\PCBuyback'... 04/06/2024 10:00:42 decoding BASE64 encoded file...'7z.exe' 04/06/2024 10:00:43 decoding BASE64 encoded file...'7z.dll' 04/06/2024 10:00:45 decoding BASE64 encoded file...'scanforhelp.png' 04/06/2024 10:00:45 decoding BASE64 encoded file...'PCBuybackUI.png' 04/06/2024 10:00:47 Detecting the logged on user... 04/06/2024 10:00:47 localuserfull was identified as: 'AzureAD\NiallBrady' 04/06/2024 10:00:47 Detection method 1: The user was identified as: NiallBrady 04/06/2024 10:00:47 SID: 'S-1-12-1-1583932090-1131944776-3006070936-2698034199' 04/06/2024 10:00:47 found sid 04/06/2024 10:00:48 registrypath is: HKU:\S-1-12-1-1583932090-1131944776-3006070936-2698034199\SOFTWARE\windowsnoob\Autopilot 04/06/2024 10:00:48 Checking if registryvalue: 'PCBuyback' in registrypath: 'HKU:\S-1-12-1-1583932090-1131944776-3006070936-2698034199\SOFTWARE\windowsnoob\Autopilot' exists... 04/06/2024 10:00:49 Reg key exists... 04/06/2024 10:00:49 registrypath is: HKU:\S-1-12-1-1583932090-1131944776-3006070936-2698034199\SOFTWARE\windowsnoob\Autopilot 04/06/2024 10:00:49 Checking if registryvalue: 'PCBuyback' in registrypath: 'HKU:\S-1-12-1-1583932090-1131944776-3006070936-2698034199\SOFTWARE\windowsnoob\Autopilot' exists... 04/06/2024 10:01:09 Reason added: '' 04/06/2024 10:01:11 The user chose OK to the PCBuyback warning, starting the reset process... 04/06/2024 10:01:11 Is this a Windows Autopilot device: 04/06/2024 10:01:11 Checking if the device is registered as a Windows Autopilot device started... 04/06/2024 10:01:11 Device serial number: 3135-5201-3107-6925-8353-2276-24 04/06/2024 10:01:19 DEBUG: The following was returned from the graph call. ' 04/06/2024 17:01:19 Starting Azure function... 04/06/2024 17:01:19 Connected to tenant: windowsnoob.com. 04/06/2024 17:01:19 supplied serial number: '3135-5201-3107-6925-8353-2276-24'. 04/06/2024 17:01:19 Get Device Reference from Intune. DeviceTrue. 04/06/2024 17:01:19 Serial number: 3135-5201-3107-6925-8353-2276-24 is an autopilot machine. Exiting Azure function.' 04/06/2024 10:01:19 the device was detected as a Windows Autopilot device, so let's remove it as a registered AP device 04/06/2024 10:01:19 Remove Windows Autopilot device from Intune started. 04/06/2024 10:01:19 Windows Autopilot device serial number: 3135-5201-3107-6925-8353-2276-24 04/06/2024 10:01:20 DEBUG: The following was returned from the graph call. 'Success' 04/06/2024 10:01:20 Removed Windows Autopilot device '3135-5201-3107-6925-8353-2276-24' from intune. 04/06/2024 10:01:20 Exiting the Intune based PC Buyback script, thanks for watching :-). If all went well and if the recovery partition on this device is healthy, Windows Reset should begin in the next few moments... 04/06/2024 10:01:20 DEBUG: The user chose OK to the PC Buyback Warning message. Starting the Windows reinstallation process now... 04/06/2024 10:01:20 checking for Power... 04/06/2024 10:01:20 virtual machine detected, will not check for power. 04/06/2024 10:01:20 Creating folder to store logs etc... 04/06/2024 10:01:20 Grabbing the reason why the user wanted to reset... 04/06/2024 10:01:20 Grabbing 'C:\ProgramData\windowsnoob\PCBuyback' logs 04/06/2024 10:01:20 Grabbing Windows temp logs 04/06/2024 10:01:20 DEBUG: Folder size (in bytes) = 2.22250366210938 04/06/2024 10:01:20 DEBUG: truncated bytes = 3 04/06/2024 10:01:20 Folder size (in MB) = 3 04/06/2024 10:01:20 Log files size: 3 04/06/2024 10:01:20 Log file size limit = 10 04/06/2024 10:01:20 Log file size (3) is less than 10, will include temp logs in email... 04/06/2024 10:01:20 Creating Autopilot cab file... 04/06/2024 10:01:42 adding C:\ProgramData\windowsnoob\PCBuyback\Win.AP.PCBuyback.log
  6. Introduction Windows Autopilot allows you to quickly enroll devices using policies, apps and settings applicable to your tenant, and that's great for deploying new Windows devices. Those devices can be registered as Windows Autopilot registered devices by the OEM (Original Equipment Manufacturer) or by a third party integrator or by the organization themselves by importing the Windows Autopilot hardware CSV into Intune. After a device has reached end of life however, it needs to be disposed of or sold on. It would be nice to offer end users the ability to buy back their old Company hardware with minimum fuss, but at the same time to remove Intune management and remove the device from Windows Autopilot registration while installing a new copy of Windows 11 professional that the end user could use for their own personal use. I created a Win32 app that does all this called PC Buyback. The app integrates with a back end Azure app using http triggers to do the magic. This post will cover the app features and code needed to implement it in your own tenant. The features of the app are as follows: Easy to use Self-Service app available in Company Portal Removes company data and apps Re-installs Windows Changes Windows edition using OEM license info stored in BIOS Emails results to a company inbox Logging to Azure tables (optional) Note: In this blog, the app uses http triggers that use certificate secrets, this is fine in a lab, but in production you should use Azure Key Vault instead as it's more secure. This mini series is broken down into the following parts: PC Buyback for Windows Autopilot devices - part 1 <--- You are here PC Buyback for Windows Autopilot devices - part 2 PC Buyback for Windows Autopilot devices - part 3 Step 1. Create resource group In Entra, using an account that has permission to create Resource Groups in your subscription, create a resource group called PCBuyback, create it in the region that your tenant is located. Step 2. Create a function app in the resource group In the PCBuyback resource group, create a function app in the same region as the resource group you created above. Step 3. Create a RemoveAutopilotDevice http trigger In the Function app, create a trigger called RemoveAutopilotDevice In the newly created Http trigger, click on Code + Test and paste in the following code to overwrite the existing code... # # Remove Autopilot device by serial number # Verify if the device is autopilot and delete it from intune # version: 0.1 windowsnoob.com 2024/03/31 using namespace System.Net # Input bindings are passed in via param block. param($Request, $TriggerMetadata) # Write to the Azure Functions log stream. Write-Host "PowerShell HTTP trigger function processed a request." # Interact with query parameters or the body of the request. $serialNumber = $Request.Query.serialNumber if (-not $serialNumber) { $serialNumber = $Request.Body.serialNumber } # define the following variables $ApplicationID = "" # create an application with permissions to delete devices in Azure $TenantDomainName = "" # your tenant name $AccessSecret = "" # this is the secret of the app you create in app registrations $GraphBody = @{ Grant_Type = "client_credentials" Scope = "https://graph.microsoft.com/.default" client_Id = $ApplicationID Client_Secret = $AccessSecret } # make initial connection to Graph $ConnectGraph = Invoke-RestMethod -Uri "https://login.microsoftonline.com/$TenantDomainName/oauth2/v2.0/token" -Method POST -Body $GraphBody #get the token $token = $ConnectGraph.access_token # to improve logging... $body = " `n" $response = "" $body = $body + "$(Get-Date)" + " Starting Azure function...`n" $body = $body + "$(Get-Date)" + " Connected to tenant: $TenantDomainName.`n" # now do things... if ($serialNumber) { $body = $body + "$(Get-Date)" + " You supplied serialNumber: '$serialNumber'" + ".`n" Try{ # Get Device Reference from Intune $body = $body + "$(Get-Date)" + " Get Device Reference from Intune" + ".`n" $Device = Invoke-RestMethod -Method Get -uri "https://graph.microsoft.com/v1.0/deviceManagement/managedDevices?`$filter=contains(serialNumber,'$serialNumber')" -Headers @{Authorization = "Bearer $token"} | Select-Object -ExpandProperty Value If($Device){ $body = $body + "$(Get-Date)" + " Found number of devices similar to '$serialNumber': $($Device.count)" + "`n" Foreach($d in $Device){ If($d.serialNumber -eq $serialNumber){ $body = $body + "$(Get-Date)" + " Get deviceID from Intune: $($d.id)" + ".`n" Invoke-RestMethod -Method Delete -uri "https://graph.microsoft.com/v1.0/deviceManagement/managedDevices/$($d.id)" -Headers @{Authorization = "Bearer $token"} $body = $body + "$(Get-Date)" + " Successfully deleted Device $($d.serialNumber) from Intune. May take a few minutes to complete in Intune Portal." + ".`n" Write-Host $body $response = "Success" break } } } Else{ $body = $body + "$(Get-Date)" + " serialNumber: $serialNumber does not exist in Intune" + ".`n" $response += "Failed" Write-Host $body } } Catch{ $body = $body + "$(Get-Date)" + " $($Error)" + ".`n" $body = $body + "$(Get-Date)" + " Failed to get Device Reference from Intune." + ".`n" $response += "Failed" Write-Host $body } Try{ # Get Device Reference from Windows AutoPilot $body = $body + "$(Get-Date)" + " Get Device Reference from Windows AutoPilot" + ".`n" $Device = Invoke-RestMethod -Method Get -uri "https://graph.microsoft.com/v1.0/deviceManagement/windowsAutopilotDeviceIdentities?`$filter=contains(serialNumber,'$serialNumber')" -Headers @{Authorization = "Bearer $token"} | Select-Object -ExpandProperty Value If($Device){ $body = $body + "$(Get-Date)" + " Found number of devices similar to '$serialNumber': $($Device.count)" + "`n" Foreach($d in $Device){ If($($d.serialNumber) -eq $serialNumber){ $body = $body + "$(Get-Date)" + " Get deviceID from Windows Autopilot: $($d.id)" + ".`n" $body = $body + "$(Get-Date)" + " Get ManagedDeviceId from Windows Autopilot: $($d.managedDeviceId)" + ".`n" Invoke-RestMethod -Method Delete -uri "https://graph.microsoft.com/v1.0/deviceManagement/windowsAutopilotDeviceIdentities/$($d.id)" -Headers @{Authorization = "Bearer $token"} $body = $body + "$(Get-Date)" + " Successfully deleted Serial Number $($d.serialNumber) from Windows Autopilot device. May take a few minutes to complete in Intune Portal." + ".`n" $response = "Success" Write-Host $body break } } } Else{ $body = $body + "$(Get-Date)" + " Serial Number: $serialNumber does not exist in Windows Autopilot" + ".`n" $response += "Failed" Write-Host $body } } Catch{ $body = $body + "$(Get-Date)" + " $($Error)" + ".`n" $body = $body + "$(Get-Date)" + " Failed to get Serial Number: $serialNumber from Windows Autopilot." + ".`n" $response += "Failed" Write-Host $body } $body = $body + "$(Get-Date)" + " Exiting Azure function." } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ StatusCode = [HttpStatusCode]::OK Body = $response }) Step 4. Create a GetAPDeviceFromIntune http trigger In the Function app, create a another http trigger called GetAPDeviceFromIntune and paste in the following code for that trigger. # Get Autopilot device from Intune # version: 0.1 windowsnoob.com 2024/03/31 using namespace System.Net param($Request, $TriggerMetadata) # define the following variables $ApplicationID = "" # create an application with permissions to delete devices in Azure $TenantDomainName = "" # your tenant name $AccessSecret = "" # this is the secret of the app you create in app registrations $serialNumber = $Request.Query.serialNumber if (-not $serialNumber) { $serialNumber = $Request.Body.serialNumber } $GraphBody = @{ Grant_Type = "client_credentials" Scope = "https://graph.microsoft.com/.default" client_Id = $ApplicationID Client_Secret = $AccessSecret } # make initial connection to Graph $ConnectGraph = Invoke-RestMethod -Uri "https://login.microsoftonline.com/$TenantDomainName/oauth2/v2.0/token" -Method POST -Body $GraphBody #get the token $token = $ConnectGraph.access_token Write-Host "Get AP Device from Intune" # to improve logging... $body = " `n" $body = $body + "$(Get-Date)" + " Starting Azure function...`n" $body = $body + "$(Get-Date)" + " Connected to tenant: $TenantDomainName.`n" # now do things... if ($serialNumber) { $body = $body + "$(Get-Date)" + " supplied serial number: '$serialNumber'" + ".`n" try { # Get Device Reference from Intune $body = $body + "$(Get-Date)" + " Get Device Reference from Intune" + ".`n" $DeviceReference = Invoke-RestMethod -Method Get -uri "https://graph.microsoft.com/v1.0/deviceManagement/windowsAutopilotDeviceIdentities?`$top=25&`$filter=contains(serialNumber,'$serialNumber')" -Headers @{Authorization = "Bearer $token"} | Select-Object -ExpandProperty Value #Write-Host $body Write-Host "Device Reference count: $($DeviceReference.Count)" if($DeviceReference.Count -gt 0) { $body = $body + "DeviceTrue" + ".`n" $body = $body + "$(Get-Date)" + " Serial number: $serialNumber is an autopilot machine" + ".`n" } Else { $body = $body + "DeviceFalse" + ".`n" $body = $body + "$(Get-Date)" + " Serial number: $serialNumber is not an autopilot machine" + ".`n" #Write-Host "Device doesn't Exists" } } Catch { $body = $body + "$(Get-Date)" + " $($Error)" + ".`n" $body = $body + "$(Get-Date)" + " Failed to get Device Reference from Intune." + ".`n" } } $body = $body + "$a Exiting Azure function." # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ StatusCode = [HttpStatusCode]::OK Body = $body }) Step 5. Create an enterprise app In Microsoft EntraId, create an enterprise app called PCBuyback Step 6. assign permissions to the app Once created, click on API permissions and using the + Add a permission button, add permissions as I've listed below. Note that these are Application permissions (type) for Microsoft Graph, once done, don't forget to grant permission for your tenant. Step 7. Create a secret In production use Azure key vault, for your lab you can quickly create a secret to test this. Copy the value somewhere safe as you'll need it for the next step. Step 8. Edit the variables in the two triggers In the two http triggers you just created, edit the variables and paste in the Enterprise App ID and secret, and your tenant name like so Once done, save the changes Step 9. Verify the http triggers Now that you've created the triggers and assigned permissions, you'll need to verify that they do what they are supposed to do. Let's start with the GetAPDeviceFromIntune. To test this, paste in the serial number of a Windows Autopilot registered device and click on Test/Run. Replace the serial number below with the serial number of the computer you want to test with. { "serialNumber": "5366-8776-5502-4105-6320-3369-17" } After running, we can see it reports that the device is true as it is a Windows Autopilot registered device. Now we know it works, let's test the other trigger. And that too, works great! That's it for part 1, see you in the part 2 where we'll create the Win32 app and test it !
  7. have you reviewed my guides here ? https://www.niallbrady.com/2019/11/13/want-to-learn-about-the-new-bitlocker-management-in-microsoft-endpoint-manager-configuration-manager/
  8. can you share exactly what you have in the step that's failing? i do see the following typo above $TSEnv = New-Objct should be $TSEnv = New-Object
  9. can you show me a snippet of the new errors seen ? looking back at the original error it's complaining about 'invalid date' did you see that ?
  10. you need to trigger a Software Update sync and look at the wsyncmgr.log and WSUSctrl.log to figure out the problem
  11. have you checked and verified that WSUS is syncing correctly and no issues there ?
  12. for context, here's a snapshot of what yours is downloading before it fails versus the same moment from my working lab
  13. from what i can see here it's downloading the wrong type of boot image have you deployed the X64 boot wim from your distribution point and made it PXE bootable ?
×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.