You dont have javascript enabled! Please enable it!

Automate Just In Time VM Access Request with PowerShell #AzureSecurityCenter #AzureSecurity #ASC #PowerShell

7 Min. Read

Image Credit: FreeClipart.org

Update! The PowerShell tool is updated to work with the latest Azure RM Security module!!! Please check here.

During Microsoft Ignite in November 2021, Azure Security Center and Azure Defender are now called Microsoft Defender for Cloud. They’ve also renamed Azure Defender plans to Microsoft Defender plans. For example, Azure Defender for Storage is now Microsoft Defender for Storage.

Introduction

The most frequent attack that we see today is an attack on RDP/SSH management port (the brute force attack), and Microsoft provides you with the capability that you don’t need to have these ports open even for legitimate administrative purposes, you don’t need to have these ports open, with Azure Security Center you can only make these ports available for administration purposes for your virtual machines only when they are required.

Just-in-Time VM Access is one of many features that is included in Azure Security Center which is something you should consider for your virtual machines. You can specify rules for how users can connect to virtual machines. When needed, access can be requested from Azure Security Center or via PowerShell. As long as the request complies with the rules, access is automatically granted for the requested time only.

How Just in Time VM Access Works

So what the just-in-time VM access feature actually does, is it really automates the Network Security Group (NSG) exception to let me connect in, by default the VM is locked and it’s blocking any RDP or SSH remote management, and I cannot connect to it, when it’s time for me to do a connection, what actually happens is, I go to Azure Portal, then I go to the Azure Security Center, and I Enable just-in-time VM access for that VM.

Automate Just In Time VM Access Request with PowerShell #AzureSecurityCenter #AzureSecurity #ASC #PowerShell 1

Then I specify for how many hours I want to allow access and click OK.

Automate Just In Time VM Access Request with PowerShell #AzureSecurityCenter #AzureSecurity #ASC #PowerShell 2

When I need to access my Azure virtual machine, I go to Azure Portal again, then I go to the Azure Security Center, and I Request access for that VM. At this point it works out what is my public-facing IP address, and it will go and modify the Network Security Group to allow an exception for whichever protocol I’m selecting be an RDP or SSH or WS management, it will add that exception just for my IP address that I want to access just for that period of time, when I enable it now I can go and RDP in from the Internet, when that time expires, it will close that exception so I cannot access it anymore.

Automate Just In Time VM Access Request with PowerShell #AzureSecurityCenter #AzureSecurity #ASC #PowerShell 3

And Microsoft recently announced a new configuration option for Just-In-Time VM Access from the virtual machine blade directly to make it even easier for you to reduce your exposure to threats.

Automate Just In Time VM Access Request with PowerShell #AzureSecurityCenter #AzureSecurity #ASC #PowerShell 4

So the real benefit of this, if I have to have something public-facing to access, maybe this is a Jump Box machine so I connect to it and navigate to other virtual machines, then with the just-in-time VM access I’m not having just an open connection, I’m not even having it always there for my particular IP, instead of when I need to access it just in time, I go to the portal, and I say hey, I want to turn this on, Azure Security Center behind the scene will add the exceptions to whichever Network Security Groups (NSGs) there are, now I have to add the NSG there already by either on the vNIC or on the subnet, and it will add the exceptions to either or both if I have both it will add the necessary exceptions to both of them, so that’s what it’s doing with just-in-time VM access.

Automate Just In Time VM Access Request

I was working on a PowerShell tool that will help me to automate just-in-time VM access to my Azure Virtual Machines. So instead of going every time to Azure Portal to enable and request access over and over, I developed that tool to automate the entire process. The script will connect to the Azure Security Center endpoint, and then will open the requested port for the time I specified. If Just in Time VM Access is not enabled for that VM, the script will enable it, and then request VM access. Additionally, the script will automatically install Azure Resource Manager and Azure Security Center PowerShell modules if they are not installed on your machine only the first time you run this tool.

You can run the script in multiple scenarios as follows:

EXAMPLE -1-

.\Request-JITVMAccess.ps1 -VMName [VMName] -Credential [AzureUser@domain.com] -Port [PortNumber] -Time [Hours] -Verbose

This example will enable Just in Time VM Access for a particular Azure VM from any source IP. The management port will be set as specified including the number of hours.
If Just in Time VM Access is not enabled, the tool will enable the policy for the VM, you need to provide the maximum requested time in hours.

Automate Just In Time VM Access Request with PowerShell #AzureSecurityCenter #AzureSecurity #ASC #PowerShell 5

EXAMPLE -2-

.\Request-JITVMAccess.ps1 -VMName [VMName] -Credential [AzureUser@domain.com] -Port [PortNumber] -AddressPrefix [AllowedSourceIP] -Time [Hours] -Verbose

This example will enable Just in Time VM Access for a particular Azure VM including the management port, source IP, and a number of hours.
If Just in Time VM Access is not enabled, the tool will enable the policy for the VM, you need to provide the maximum requested time in hours.

Automate Just In Time VM Access Request with PowerShell #AzureSecurityCenter #AzureSecurity #ASC #PowerShell 6

EXAMPLE -3-

.\Request-JITVMAccess.ps1 -VMName [VMName] -Credential [AzureUser@domain.com] -Port [PortNumber] -AddressPrefix [AllowedSourceIP] -Verbose

This example will enable Just in Time VM Access for a particular Azure VM including the management port, and source IP address.
If Just in Time VM Access is not enabled, the tool will enable the policy for the VM, you need to provide the maximum requested time in hours.
If Just in Time VM Access is already enabled, the tool will automatically extract the maximum requested time set by the policy and then request VM access.

Automate Just In Time VM Access Request with PowerShell #AzureSecurityCenter #AzureSecurity #ASC #PowerShell 7

EXAMPLE -4-

.\Request-JITVMAccess.ps1 -VMName [VMName] -Credential [AzureUser@domain.com] -Port [PortNumber] -Verbose

This example will enable Just in Time VM Access for a particular Azure VM from any source IP. The management port will be set as specified.
If Just in Time VM Access is not enabled, the tool will enable the policy for the VM, you need to provide the maximum requested time in hours.
If Just in Time VM Access is already enabled, the tool will automatically extract the maximum requested time set by the policy and then request VM access.

Automate Just In Time VM Access Request with PowerShell #AzureSecurityCenter #AzureSecurity #ASC #PowerShell 8

Where can I download this tool?

This tool is available on my GitHub repository. You can download the documentation and the script from here.

<#
.SYNOPSIS
Enable Just In Time VM access.

.DESCRIPTION
Automate Just in time VM request access with PowerShell.

.NOTES
File Name : Request-JITVMAccess.ps1
Author    : Charbel Nemnom
Version   : 1.0
Date      : 20-August-2018
Update    : 27-August-2018
Requires  : PowerShell Version 5.1 or later
Module    : AzureRM Version 6.7.0
Module    : Azure-Security-Center Version 0.0.22

.LINK
To provide feedback or for further assistance please visit:
Cover Page
.EXAMPLE .\Request-JITVMAccess.ps1 -VMName [VMName] -Credential [AzureUser@domain.com] -Port [PortNumber] -Time [Hours] -Verbose This example will enable Just in Time VM Access for a particular Azure VM from any source IP. The management port will be set as specified including the number of hours. If Just in Time VM Access is not enabled, the tool will enable the policy for the VM, you need to provide the maximum requested time in hours. .EXAMPLE .\Request-JITVMAccess.ps1 -VMName [VMName] -Credential [AzureUser@domain.com] -Port [PortNumber] -AddressPrefix [AllowedSourceIP] -Time [Hours] -Verbose This example will enable Just in Time VM Access for a particular Azure VM including the management port, source IP, and number of hours. If Just in Time VM Access is not enabled, the tool will enable the policy for the VM, you need to provide the maximum requested time in hours. .EXAMPLE .\Request-JITVMAccess.ps1 -VMName [VMName] -Credential [AzureUser@domain.com] -Port [PortNumber] -AddressPrefix [AllowedSourceIP] -Verbose This example will enable Just in Time VM Access for a particular Azure VM including the management port, and source IP address. If Just in Time VM Access is not enabled, the tool will enable the policy for the VM, you need to provide the maximum requested time in hours. If Just in Time VM Access is already enabled, the tool will automatically extract the maximum requested time set by the policy, and then request VM access. .EXAMPLE .\Request-JITVMAccess.ps1 -VMName [VMName] -Credential [AzureUser@domain.com] -Port [PortNumber] -Verbose This example will enable Just in Time VM Access for a particular Azure VM from any source IP. The management port will be set as specified. If Just in Time VM Access is not enabled, the tool will enable the policy for the VM, you need to provide the maximum requested time in hours. If Just in Time VM Access is already enabled, the tool will automatically extract the maximum requested time set by the policy, and then request VM access. #> [CmdletBinding()] Param( [Parameter(Position=0, Mandatory=$True, HelpMessage='Specify the VM Name')] [Alias('VM')] [String]$VMName, [Parameter(Position=1, Mandatory=$True, HelpMessage='Specify Azure Credentials')] [Alias('AzureCred')] [PSCredential]$Credential, [Parameter(Position=2, Mandatory=$True, HelpMessage='Specify remote access port, must be a number between 1 and 65535.')] [Alias('AccessPort')] [ValidateRange(1,65535)] [Int]$Port, [Parameter(Position=3, HelpMessage='Source IP Address Prefix. (IP Address, CIDR block, or *) Default = * (Any)')] [Alias('SourceIP')] [String]$AddressPrefix = '*', [Parameter(Position=4, HelpMessage='Specify time range in hours, valid range: 1-24 hours')] [Alias('Hours')] [ValidateRange(1,24)] [Int]$Time ) Function Install-AzureRM { Set-PSRepository -Name PSGallery -Installation Trusted -Verbose:$false Install-Module -Name AzureRM -AllowClobber -Confirm:$false -Verbose:$false } Function Install-ASC { Set-PSRepository -Name PSGallery -Installation Trusted -Verbose:$false Install-Module -Name Azure-Security-Center -AllowClobber -Confirm:$false -Verbose:$false } Function ExtractMaxDuration ([string]$InStr){ $Out = $InStr -replace("[^\d]") try{return [int]$Out} catch{} try{return [uint64]$Out} catch{return 0}} #! Check AzureRM PowerShell Module Try { Import-Module -Name AzureRM -ErrorAction Stop -Verbose:$false | Out-Null Write-Verbose "Importing Azure RM PowerShell Module..." } Catch { Write-Warning "Azure Resource Manager PowerShell Module not found..." Write-Verbose "Installing Azure Resource Manager PowerShell Module..." Install-AzureRM } #! Check Azure Security Center PowerShell Module Try { Import-Module -Name Azure-Security-Center -WarningAction SilentlyContinue -Verbose:$false | Out-Null Write-Verbose "Importing Azure Security Center PowerShell Module..." } Catch { Write-Warning "Azure Security Center PowerShell Module not found..." Write-Verbose "Installing Azure Security Center PowerShell Module..." Install-ASC } #! Check Azure Cloud Connection Try { Write-Verbose "Connecting to Azure Cloud..." Login-AzureRmAccount -Environment AzureCloud -Credential $Credential -ErrorAction Stop | Out-Null } Catch { Write-Warning "Cannot connect to Azure environment. Please check your credentials. Exiting!" Break } #! Get Azure Virtual Machine Info $VMInfo = Get-AzureRMVM | ?{$_.Name -eq "$VMName"} If (!$VMInfo) { Write-Warning "Azure virtual machine ($VMName) cannot be found. Please check your virtual machine name. Exiting!" Break } $VMAccessPolicy = Get-ASCJITAccessPolicy | Select -ExpandProperty Properties | Select -ExpandProperty VirtualMachines | Where-Object {$_.id -like "*$VMName*"} | Select -Property Ports If (!$VMAccessPolicy) { Write-Warning "Just in Time VM Access is not enabled for Azure VM ($VMName)" if (-Not $time) { Try { $time = Read-Host "`nEnter Max Requested Time in Hours, valid range: 1-24 hours" } Catch { Write-Warning "The maximum requested time entered is not in the valid range: 1-24 hours" Break } } #! Enable Access to the VM including management Port, and Time Range in Hours Write-Verbose "Enabling Just in Time VM Access Policy for ($VMName)" Set-ASCJITAccessPolicy -VM $VMInfo.Name -ResourceGroupName $VMInfo.ResourceGroupName -Port $Port -Protocol * -AllowedSourceAddressPrefix $AddressPrefix -MaxRequestHour $time } #! Request Access to the VM including management Port, Source IP and Time Range in Hours if (-Not $time) { $VMAccessPolicy.PSObject.Properties | foreach-object { $value = $_.Value } $MaxRequest = $value | where-object {$_.Number -eq "$Port"} $Time = ExtractMaxDuration $MaxRequest.maxRequestAccessDuration Invoke-ASCJITAccess -VM $VMInfo.Name -ResourceGroupName $VMInfo.ResourceGroupName -Port $Port -AddressPrefix $AddressPrefix -Hours $Time } Else { Invoke-ASCJITAccess -VM $VMInfo.Name -ResourceGroupName $VMInfo.ResourceGroupName -Port $Port -AddressPrefix $AddressPrefix -Hours $Time }

Summary

Just-in-time VM access is a very good feature since Azure network administrators don’t need to go and change the Network Security Group (NSG) settings each and every time and with this tool, it becomes even faster to automate this process. Please note that Just-in-time VM access will incur additional charges to your Azure subscription as it is part of the Azure Security Center Standard Pricing Tier. For more information on the Azure Security Center pricing Tier, please check the following URL.

Roadmap

I am planning to improve this tool in the future. This is still version 1.0. If you have any feedback or changes that everyone should receive, please feel free to update the source code and create a pull request.

Until then… Stay secure with Just in Time VM Access!

__
Thank you for reading my blog.

If you have any questions or feedback, please leave a comment.

-Charbel Nemnom-

Photo of author
About the Author
Charbel Nemnom
Charbel Nemnom is a Senior Cloud Architect, Swiss Certified ICT Security Expert, Certified Cloud Security Professional (CCSP), Certified Information Security Manager (CISM), Microsoft Most Valuable Professional (MVP), and Microsoft Certified Trainer (MCT). He has over 20 years of broad IT experience serving on and guiding technical teams to optimize the performance of mission-critical enterprise systems with extensive practical knowledge of complex systems build, network design, business continuity, and cloud security.
Previous

How To Enable TLS 1.2 Protocol In System Center Data Protection Manager #SCDPM #TLS1.2

Configure Azure Stack Automatic Infrastructure Backup With PowerShell #AzureStack #AzureStackDevKit #ASDK

Next

2 thoughts on “Automate Just In Time VM Access Request with PowerShell #AzureSecurityCenter #AzureSecurity #ASC #PowerShell”

Leave a comment...

  1. Hello Everardo, thanks for the comment!
    Yes, you could add Approval requests at JIT to VM access by leveraging the Workflow Automation in Microsoft Defender for Cloud.
    I already wrote an article on how to enable Just-In-Time VM Access On Virtual Machines with Workflow Automation in Defender for Cloud.
    You can use the same logic and add another step for approval using email with (Office 365 Outlook) for example.
    Check the following document to create approval-based workflows by using Azure Logic Apps.
    Hope it helps!

Let me know what you think, or ask a question...

error: Alert: The content of this website is copyrighted from being plagiarized! You can copy from the 'Code Blocks' in 'Black' by selecting the Code. Thank You!