Showing posts with label Powershell. Show all posts
Showing posts with label Powershell. Show all posts

Thursday, 27 March 2025

Azure MFA NPS Extension Configuration Failure Due to Microsoft Graph PowerShell Module Conflicts

Introduction

When configuring the Azure MFA NPS Extension using the official script (AzureMfaNpsExtnConfigSetup.ps1), administrators may encounter a failure during the update of the Azure Active Directory service principal. The script attempts to push certificate data using the Microsoft Graph PowerShell SDK, and the process fails with the following error:

Update-MgServicePrincipal : Cannot convert the literal '<cert_blob>' to the expected type 'Edm.Binary'.
Status: 400 (BadRequest)

This issue typically occurs due to multiple versions or conflicting installations of the Microsoft Graph PowerShell modules, which can lead to serialization or data formatting errors during API operations.

This KB provides a tested remediation process by removing all existing Graph modules and reinstalling the required components cleanly.

Instructions

✅ Step 1 – Manually Uninstall All Microsoft.Graph Modules

Open PowerShell as Administrator and run the following script to uninstall all installed versions of any Microsoft.Graph modules:

$Modules = Get-Module Microsoft.Graph* -ListAvailable | Where {$_.Name -ne "Microsoft.Graph.Authentication"} | Select-Object Name -Unique
Foreach ($Module in $Modules)
{
    $ModuleName = $Module.Name
    $Versions = Get-Module $ModuleName -ListAvailable
    Foreach ($Version in $Versions)
    {
        $ModuleVersion = $Version.Version
        Write-Host "Uninstall-Module $ModuleName $ModuleVersion"
        Uninstall-Module $ModuleName -RequiredVersion $ModuleVersion
    }
}

# Uninstall Microsoft.Graph.Authentication
$ModuleName = "Microsoft.Graph.Authentication"
$Versions = Get-Module $ModuleName -ListAvailable
Foreach ($Version in $Versions)
{
    $ModuleVersion = $Version.Version
    Write-Host "Uninstall-Module $ModuleName $ModuleVersion"
    Uninstall-Module $ModuleName -RequiredVersion $ModuleVersion
}

After the script completes, manually rerun it until this command returns no results:

Get-InstalledModule | Where-Object { $_.Name -like "Microsoft.Graph*" }

📝 Note: Some modules may be reloaded or may not uninstall cleanly on the first attempt, especially if there are versioning or dependency overlaps. Repeating the uninstall step ensures a clean removal.

✅ Step 2 – Install Required Microsoft Graph Modules

Once all previous versions are removed, install only the latest required modules:

Install-Module Microsoft.Graph

✅ Step 3 – Rerun the Configuration Script

With a clean module set installed, rerun the configuration script:

C:\Program Files\Microsoft\AzureMfa\Config\AzureMfaNpsExtnConfigSetup.ps1

The script should now complete successfully, allowing Azure MFA to integrate with the NPS service and Remote Desktop Gateway.

Additional Notes

This issue has been independently reported in the sysadmin community and is reproducible in environments where Microsoft Graph modules are upgraded over time without cleanup.

No interference was found from Microsoft Defender in typical environments, though exclusions may still be useful in some configurations.

Friday, 20 December 2024

Search for an IP Address in the Last 7 Days of Windows Security Event Logs

This PowerShell script allows you to filter Windows Security event logs for a specific IP address, focusing on events from the past 7 days. The results are saved to a CSV file for further analysis.







The Script

# Define the IP address and output CSV file path $ipaddress = "10.1.1.1" $outputFile = "C:\SecurityEvents_Last7Days.csv" # Define the start date (7 days ago) $startDate = (Get-Date).AddDays(-7) # Extract the events from the last 7 days and export to CSV Get-WinEvent -LogName Security -FilterXPath "*[EventData[Data[@Name='IpAddress']='$ipaddress']]" | Where-Object { $_.TimeCreated -ge $startDate } | Select-Object TimeCreated, Id, Message | Export-Csv -Path $outputFile -NoTypeInformation -Encoding UTF8 # Notify user of completion Write-Output "Events from the last 7 days successfully exported to $outputFile"

Key Features

  1. Filters by IP Address: Searches for events where the IP address matches the specified value.
  2. Time Range: Limits results to events that occurred in the last 7 days using the TimeCreated property.
  3. CSV Output: Saves event details (timestamp, ID, and message) to a specified CSV file.

How to Use It

  1. Replace 10.1.1.1 with the target IP address.
  2. Save the script to a .ps1 file or run it directly in PowerShell with administrator privileges.
  3. Locate the output file (C:\SecurityEvents_Last7Days.csv) for review.

Script Workflow

  1. Input Definition: The $ipaddress variable holds the IP address, and $outputFile specifies the CSV file location.
  2. Time Range Setup: $startDate is calculated as 7 days prior to the current date.
  3. Event Filtering: Get-WinEvent retrieves log entries matching the IP address. Where-Object ensures only events from the past 7 days are included.
  4. Data Export: Selected details are saved to the CSV file for analysis.

Practical Applications

  • Security Monitoring: Quickly identify events tied to suspicious IP activity.
  • Incident Investigation: Focus on recent logs for faster issue resolution.
  • Data Analysis: Exported CSV files can be reviewed in Excel or other tools.

Conclusion

This script is a concise, efficient way to analyze recent security events related to a specific IP address. Adjust the IP and time range as needed for your specific use case, and use the exported data to inform your network security actions.

Wednesday, 3 April 2024

How to Backup BitLocker Key to Azure AD Using PowerShell

BitLocker is a security feature built into Windows that provides encryption for entire volumes. It addresses the threats of data theft or exposure from lost, stolen, or inappropriately decommissioned devices. By encrypting the hard drive where Windows is installed, or the entire computer if it has multiple drives, BitLocker helps protect your data.

BitLocker is particularly useful as it provides protection against unauthorised changes to your system such as firmware-level malware. It also helps mitigate unauthorised data access by enhancing file and system protections. BitLocker is an essential tool for securing your data, especially when data breaches and information theft are common.

The Command

Here is the command that we’ll be using:

BackupToAAD-BitLockerKeyProtector -MountPoint $env:SystemDrive -KeyProtectorId ((Get-BitLockerVolume -MountPoint $env:SystemDrive ).KeyProtector | where {$_.KeyProtectorType -eq "RecoveryPassword" }).KeyProtectorId

This command backs up the BitLocker key protector of type “RecoveryPassword” for the system drive to AAD.

Outputting the Key Protector to the Screen

If you want to output the key protector to the screen, you can use the following command:

(Get-BitLockerVolume -MountPoint C).KeyProtector

This command retrieves the key protector for the C drive and outputs it to the screen.

Wednesday, 27 March 2024

Resolving PowerShell Module Installation Error


When installing a PowerShell module, you may encounter the following error:

WARNING: Unable to resolve package source 'https://www.powershellgallery.com/api/v2'

This error can occur due to various reasons, but one common cause is related to the Transport Layer Security (TLS) version that your PowerShell system is using.

The Role of TLS

The PowerShell Gallery, where PowerShell modules are hosted, only accepts connections using TLS 1.2 or later. If your system is using an older version of TLS, it may fail to establish a connection with the PowerShell Gallery, resulting in the error mentioned above.

The Solution

To resolve this issue, you need to force your PowerShell system to use TLS 1.2. This can be achieved by running the following command in your PowerShell session:

[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

This command sets the security protocol of your PowerShell session to TLS 1.2. After running this command, you should be able to install the PowerShell module without encountering the error.

Please note that this change will only apply to the current PowerShell session. If you start a new session, you will need to run the command again.

Wednesday, 7 June 2023

Hyper-V deleting a checkpoint when the delete option is missing

Hyper-V is a powerful virtualization platform that allows users to create and manage virtual machines efficiently. One of its handy features is the ability to take snapshots, which capture the state of a virtual machine at a specific point in time. These snapshots serve as restore points, allowing you to roll back your VM to a previous state if needed. However, sometimes you may encounter an issue where the delete option for a snapshot is not available in Hyper-V Manager.

Method 1: Using the Keyboard Shortcut in Hyper-V Manager

When the delete option is missing from the Hyper-V Manager interface, you can use a keyboard shortcut to delete the snapshot. Follow these steps:

Step 1: Launch Hyper-V Manager

Open Hyper-V Manager by searching for it in the Start menu

Step 2: Select the Virtual Machine and Snapshot

In the left-hand pane of Hyper-V Manager, locate the virtual machine that contains the snapshot you want to delete. Click on the VM's name to select it. Then, select the specific snapshot you wish to delete from the list of checkpoints displayed in the centre pane.

Step 3: Press the Delete Key

With the VM and the desired snapshot selected, press the "Delete" key on your keyboard. This action will prompt a confirmation dialog.

Step 4: Confirm Snapshot Deletion

In the confirmation dialog, review the details of the snapshot you are about to delete. Ensure that you have selected the correct snapshot, as the deletion process is irreversible. Click "Yes" to proceed.

Method 2: Using PowerShell to Remove the Snapshot

If you prefer using PowerShell, you can employ the following steps to remove the snapshot using command-line tools:

Step 1: Launch PowerShell

Open PowerShell by searching for it in the Start menu or by using the Run dialog (press Win + R and type "powershell" followed by Enter).

Step 2: Remove the Snapshot

In the PowerShell console, run the following command to remove the desired snapshot:
Get-VM <VM-Name> | Remove-VMSnapshot
Replace <VM-Name> with the name of the virtual machine containing the snapshot you wish to delete. This command retrieves the specified virtual machine and pipes it to the Remove-VMSnapshot cmdlet to remove the snapshot.

Friday, 2 June 2023

Failover Cluster VM Load Balancing in Windows Server

Windows Server 2016 introduced the Virtual Machine Load Balancing feature for Failover Clusters. This feature optimizes node utilization by redistributing VMs based on memory pressure and CPU utilization. In this blog post, we will explore the command and usage of this feature.

Heuristics for Balancing:

VM Load Balancing considers two heuristics:

  • Current Memory pressure: Evaluates the memory usage of each node.
  • CPU utilization: Monitors CPU usage averaged over a 5-minute window.

Controlling Aggressiveness of Balancing:

To configure the balancing aggressiveness:

Open PowerShell.
Run (Get-Cluster).AutoBalancerLevel = <value>

AutoBalancerLevel values:

  1. (default): Low aggressiveness, moves VMs when host is >80% loaded.
  2. Medium aggressiveness, moves VMs when host is >70% loaded.
  3. High aggressiveness, averages nodes, and moves VMs when host is >5% above average.

Controlling VM Load Balancing:

To configure when load balancing occurs:
Using Failover Cluster Manager:

  1. Right-click on cluster name, select "Properties."
  2. Go to the "Balancer" pane and configure desired settings.

Using PowerShell:

  1. Open PowerShell.
  2. Run (Get-Cluster).AutoBalancerMode = <value>

AutoBalancerMode values:
  • 0: Disabled.
  • 1: Load balance on node join.
  • 2 (default): Load balance on node join and every 30 minutes.

VM Load Balancing vs. SCVMM Dynamic Optimization:

For deployments without SCVMM, VM Load Balancing provides in-box functionality. However, for SCVMM deployments, SCVMM Dynamic Optimization is recommended for load balancing. SCVMM automatically disables VM Load Balancing when Dynamic Optimization is enabled.

Saturday, 11 March 2023

PowerShell Script: Uninstall Microsoft Teams from a workstation

This script will uninstall Microsoft Teams from a workstation, it will also work while running under a different user, in case you need to role it out via a RMM solution but would work as a Group policy too

# Check if script is running with administrative privileges
if (-not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) {
    Write-Host "This script must be run with administrative privileges."
    Exit 1001
}

# Uninstall Microsoft Teams for all users
$teams_installed = Get-ChildItem -Path "C:\Users\*\AppData\Local\Microsoft\Teams\Update.exe" -ErrorAction SilentlyContinue

if ($teams_installed) {
    # Loop through all instances of Microsoft Teams and uninstall it silently
    foreach ($teams in $teams_installed) {
        Start-Process "$($teams.FullName)" -ArgumentList "-uninstall -s" -Wait
    }
    Write-Host "Microsoft Teams has been uninstalled for all users."
} else {
    Write-Host "Microsoft Teams is not installed on this computer."
}

# Uninstall Teams machine-wide installer
$teamswide_installed = Get-WmiObject -Class Win32_Product | Where-Object {$_.Name -like "*Teams Machine-Wide*"} | Select-Object -ExpandProperty IdentifyingNumber

if ($teamswide_installed) {
    # Uninstall the Teams machine-wide installer silently
    Start-Process "msiexec.exe" -ArgumentList "/x $teamswide_installed /qn" -Wait
    Write-Host "Teams machine-wide installer has been uninstalled."
} else {
    Write-Host "Teams machine-wide installer is not installed on this computer."
}

Wednesday, 22 February 2023

PowerShell Script to ping an host IP address for a set amount of hours

This script will ping a host for the amount of hours you set when you run it,  it will then display any failures and the times it failed, while also output the results at the end of the time or when the user interrupts the script.

$ipAddress = Read-Host "Enter IP address to ping"
$duration = Read-Host "Enter duration of ping test in hours"
$successCount = 0
$failureCount = 0
$startTime = Get-Date
try {
    while ((Get-Date) -lt ($startTime.Addhours($duration))) {
        $pingResult = Test-Connection $ipAddress -Count 1 -ErrorAction SilentlyContinue
        if ($pingResult.StatusCode -eq 0) {
            $successCount++
        } else {
            $failureCount++
            Write-Host "Ping failed at $(Get-Date)" -ForegroundColor Red
        }
    }
}
Finally {
    Write-Host "Ping test complete. Results:" -ForegroundColor Yellow
    Write-Host "  Successful pings: $successCount" -ForegroundColor Green
    Write-Host "  Failed pings: $failureCount" -ForegroundColor Red
}

Thursday, 16 February 2023

PowerShell - See the last reason why a Windows shutdown / rebooted

 Get-EventLog -logname system | Where-Object {$_.EventID -eq 1074 -or $_EventID -eq 6008} | Select -first 1

Wednesday, 8 February 2023

PowerShell to block sign in to shared mailboxes on Microsoft 365

First you will need to connect to the following 365 services and bypass the security in powershell for the process

Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass

Connect-ExchangeOnline
Connect-MsolService

Then run this

Get-EXOMailbox -Filter {recipienttypedetails -eq "SharedMailbox"} | get-MsolUser | Select-Object UserPrincipalName,blockcredential | Where {$_.BlockCredential -eq $False} | ForEach-Object { Set-MsolUser -UserPrincipalName $_.UserPrincipalName -BlockCredential $true}

Thursday, 4 August 2022

PowerShell Quick and dirty add a user to AD

New-ADUser <USERNAME>
Set-ADAccountPassword <USERNAME> -Reset -NewPassword (ConvertTo-SecureString -AsPlainText "<PASSWORD>" -Force -Verbose) -PassThru
Add-ADGroupMember -Identity "<GROUPNAME>" -Members <USERNAME>
enable-adaccount -identity "<USERNAME>"

Wednesday, 3 August 2022

PowerShell Exchange 365 Output Archive sizes and Quota

$table = New-Object System.Data.DataTable
$table.Columns.Add("Name", "System.String")
$table.Columns.add("Archive_Size", "System.String")
$table.Columns.add("Archive_Quoted", "System.String")
$table.Columns.add("AutoExpand", "System.String")

Foreach ($i in (Get-Mailbox -Archive | sort Name)) {
    $archive = $i | Get-MailboxStatistics -Archive
    $row = $table.NewRow()
    $row.Name = $i.Name
    $row.Archive_Quoted = $i.ArchiveQuota
    $row.Archive_Size = $archive.TotalItemSize
    $row.AutoExpand = $i.AutoExpandingArchiveEnabled
    $table.rows.add($row)
}

cls
$table | Format-Table

Monday, 27 June 2022

Powershell check if script is running as administrator

Write-Host "Checking for elevated permissions..."

if (-NOT ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) {

    Write-Warning "Insufficient permissions to run this script."

    Break

}

else {

 <CODE GOES HERE>

}

Friday, 21 May 2021

Powershell Script to reset Windows 2016+ Remote Desktop Host firewall

This a quick script to reset a Windows Servers firewall and insert the fix for cleaning down the rules when user logs off on a Remote Desktop Host.

#Powershell
Remove-Item "HKLM:\SYSTEM\CurrentControlSet\Services\SharedAccess\Parameters\FirewallPolicy\RestrictedServices\Configurable\System"
New-Item "HKLM:\SYSTEM\CurrentControlSet\Services\SharedAccess\Parameters\FirewallPolicy\RestrictedServices\Configurable\System"
Remove-Item "HKLM:\SYSTEM\CurrentControlSet\Services\SharedAccess\Parameters\FirewallPolicy\RestrictedServices\AppIso\FirewallRules"
New-Item "HKLM:\SYSTEM\CurrentControlSet\Services\SharedAccess\Parameters\FirewallPolicy\RestrictedServices\AppIso\FirewallRules"
(New-Object -ComObject HNetCfg.FwPolicy2).RestoreLocalFirewallDefaults()
New-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Services\SharedAccess\Parameters\FirewallPolicy' -Name  'DeleteUserAppContainersOnLogoff' -Value '1' -PropertyType 'DWORD' –Force
#EOF

Tuesday, 23 March 2021

Enable Microsoft 365 Message Encryption

This is a great feature for sending secure emails and is easy to set up.  First the users need to use the feature will need one of the following:

  • Azure Information Protection for Office 365
  • Azure Information Protection Premium P1
  • Azure Information Protection Premium P2
Once you have the right subscription you can enable the option via PowerShell with the following commands.

Import-Module ExchangeOnlineManagement
Import-Module AIPService
Connect-AipService
Connect-ExchangeOnline -UserPrincipalName <Admin Account>
Set-IRMConfiguration -AzureRMSLicensingEnabled $True

#Confirm Not NULL
$RDM = Get-AadrmConfiguration
$Uri = $RDM.LicensingIntranetDistributionPointUrl

Set-IRMConfiguration -LicensingLocation $Uri
Set-IRMConfiguration -InternalLicensingEnabled $true

Once its all set up you can confirm its working with the below Powershell command

Test-IRMConfiguration -Sender <Email address>

Once this is done the option will appear in OWA and Outlook can install the Azure rights management software but this can take a few hours.  you can also make a mail flow in Exchange 365 admin to encrypt on a keyword.  

Pricing – Information Protection | Microsoft Azure

Message Encryption - Microsoft 365 Compliance | Microsoft Docs

Set up new Message Encryption capabilities - Microsoft 365 Compliance | Microsoft Docs

Configure and manage templates for Azure Information Protection - AIP | Microsoft Docs

 

Friday, 12 March 2021

Get Azure AD Users SID's

Powershell

On a computer run the following within PowerShell ISE

Import-Module -Name AzureAD
Connect-AzureAD

function Convert-ObjectIdToSid
{
    param([String] $ObjectId)
     $d=[UInt32[]]::new(4);[Buffer]::BlockCopy([Guid]::Parse($ObjectId).ToByteArray(),0,$d,0,16);"S-1-12-1-$d".Replace(' ','-')
}

Then

Get-AzureADUser | ForEach { [pscustomobject] @{ Name= $_.DisplayName; Sid=Convert-ObjectIdToSid($_.ObjectId)}}

You can do a search within the Get-AzureADUser by using the -SearchString "<USERNAME>"

As the user logged in to a device

Open CMD and type

whoami /user


Friday, 9 October 2020

Control Windows services via PowerShell

List Services
get-service

Stop Service
stop-service <SERVICENAME>

Start Service
start-service <SERVICENAME>

Change start-up type
set-service <SERVICENAME> -StartupType Automatic|Disabled

Stop multiple services at once
get-service | where name -like <SERVICENAME>* | stop-service

https://docs.microsoft.com/en-us/powershell/scripting/samples/managing-services?view=powershell-7 

Monday, 24 August 2020

Setting a PowerShell Scrip to run as a Task

 use:

Powershell.exe  -ExecutionPolicy Bypass -File "<FILE LOCATION>"


for the Task and set it to run with highest privileges and while logged off to without saving the password (Unless it access the network).  

Setting Bandwidth Controls on Windows devices via PowerShell

 You will need to use NetQos in Powershell for this but you can script it to make time profiles too by using Task Scheduler and the set command.

This is just a simple command that does it by destination IP but if you read the documentation you can do more with it.

  1. Run PowerShell as Admin
  2. Type "New-NetQosPolicy -Name "<NAME>" -IPDstPrefixMatchCondition "<IPADDRESS OR NETWORK ADDRESS>" -ThrottleRateActionBitsPerSecond 10MB
To make changes too the new policy use "Set-NetQosPolicy -Name "<NAME>"" with the option you wish to change.