Public/Get-IntuneLapsCredential.ps1
|
function Get-IntuneLapsCredential { <# .SYNOPSIS Retrieves LAPS local admin credentials for an Intune-managed device. .DESCRIPTION Calls the Microsoft Graph API endpoint: GET /directory/deviceLocalCredentials/{deviceId} Without -IncludePassword: returns account name and metadata only. With -IncludePassword: returns the decoded plain-text password as well. Password access requires the Cloud Device Administrator or Intune Administrator Entra role plus DeviceLocalCredential.Read.All scope. Metadata-only access requires Helpdesk Administrator (or higher) plus DeviceLocalCredential.ReadBasic.All scope. .PARAMETER DeviceId The Intune/Entra device object ID (GUID). Accepts pipeline from Find-IntuneLapsDevice. .PARAMETER IncludePassword When specified, requests the password from Graph ($select=credentials). Will fail with a clear error if the signed-in user lacks sufficient permissions. .EXAMPLE Get-IntuneLapsCredential -DeviceId 'b465e4e8-e4e8-b465-e8e4-65b4e8e465b4' .EXAMPLE Get-IntuneLapsCredential -DeviceId 'b465e4e8-e4e8-b465-e8e4-65b4e8e465b4' -IncludePassword .EXAMPLE Find-IntuneLapsDevice -DeviceName 'WS001' | Get-IntuneLapsCredential -IncludePassword #> [CmdletBinding()] [OutputType([PSCustomObject])] param( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [ValidateNotNullOrEmpty()] [string]$DeviceId, [Parameter(Mandatory = $false)] [switch]$IncludePassword ) begin { $ErrorActionPreference = 'Stop' try { $null = Get-MgContext -ErrorAction Stop } catch { throw 'Not connected. Run Connect-IntuneLaps before retrieving credentials.' } } process { try { # --- Step 1: Always fetch metadata first (no password) --- [string]$MetadataUri = "https://graph.microsoft.com/v1.0/directory/deviceLocalCredentials/$DeviceId" Write-Verbose "Fetching LAPS metadata for device: $DeviceId" $MetadataResponse = Invoke-MgGraphRequestWithRetry -Parameters @{ Method = 'GET'; Uri = $MetadataUri } [string]$DeviceName = $MetadataResponse.deviceName [string]$LastBackup = $MetadataResponse.lastBackupDateTime [string]$RefreshDateTime = $MetadataResponse.refreshDateTime # --- Step 2: Fetch credentials only if -IncludePassword is requested --- [string]$AccountName = $null [string]$Password = $null [bool]$PasswordRetrieved = $false if ($IncludePassword) { Write-Verbose 'Requesting LAPS password (requires elevated permissions)...' [string]$PasswordUri = "https://graph.microsoft.com/v1.0/directory/deviceLocalCredentials/$DeviceId" + '?%24select=id,credentials' try { $CredResponse = Invoke-MgGraphRequestWithRetry -Parameters @{ Method = 'GET'; Uri = $PasswordUri } if ($CredResponse.credentials -and $CredResponse.credentials.Count -gt 0) { # Return the most recent credential (first entry = latest backup) $LatestCred = $CredResponse.credentials | Sort-Object backupDateTime -Descending | Select-Object -First 1 $AccountName = $LatestCred.accountName $Password = ConvertFrom-LapsPassword -PasswordBase64 $LatestCred.passwordBase64 $PasswordRetrieved = $true } } catch { # HTTP 403 = insufficient permissions — surface a clean message, don't crash if ("$_" -match '\b403\b') { Write-Warning "Insufficient permissions to retrieve the LAPS password for device '$DeviceName'. Your account requires the 'Cloud Device Administrator' or 'Intune Administrator' Entra role." } else { Write-Error "Failed to retrieve LAPS password for device '$DeviceName': $_" } } } else { # Metadata-only: accountName is not returned without $select=credentials $AccountName = '(Requires elevated permission to view)' } [PSCustomObject]@{ DeviceId = $DeviceId DeviceName = $DeviceName AccountName = $AccountName Password = $Password PasswordRetrieved = $PasswordRetrieved LastBackupDateTime = $LastBackup RefreshDateTime = $RefreshDateTime } } catch { # 404 or 400 "could not be found" = device has no LAPS record in this tenant if ("$_" -match '\b404\b' -or ("$_" -match '\b400\b' -and "$_" -match 'could not be found')) { Write-Warning "No LAPS credential record found for device '$DeviceId'. Ensure LAPS is configured and the device has checked in recently." } else { Write-Error "Failed to retrieve LAPS credential for device '$DeviceId': $_" } } } } |