From cb575023d6e036f0f3a8d4b5bb5d821bf5a05a1d Mon Sep 17 00:00:00 2001 From: "Omkar Mohite (TATA CONSULTANCY SERVICES LTD)" Date: Mon, 21 Apr 2025 16:47:30 +0530 Subject: [PATCH 01/11] Code changes to enable encryption at host for virtual machine scale set and virtual machine. --- ...Remediate-EnableEncrytionAtHostForVMSS.ps1 | 415 ++++++++++++++++++ 1 file changed, 415 insertions(+) create mode 100644 Scripts/RemediationScripts/Remediate-EnableEncrytionAtHostForVMSS.ps1 diff --git a/Scripts/RemediationScripts/Remediate-EnableEncrytionAtHostForVMSS.ps1 b/Scripts/RemediationScripts/Remediate-EnableEncrytionAtHostForVMSS.ps1 new file mode 100644 index 00000000..39ac6a23 --- /dev/null +++ b/Scripts/RemediationScripts/Remediate-EnableEncrytionAtHostForVMSS.ps1 @@ -0,0 +1,415 @@ +<########################################## + +# Overview: + This script is used to Enable Encryption at Host for Virtual machine scale sets and Virtual machines. + +# ControlId: + Azure_VirtualMachineScaleSet_DP_Enable_Encryption_At_Host + +# Pre-requisites: + You will need Owner or Contributor role on subscription. + +# Steps performed by the script: + 1. Install and validate pre-requisites to run the script for subscription. + + 2. Get the list of resource groups and check for Virtual machine scale sets and Virtual machines, from subscription. + + 3. Take a backup of these non-compliant resource types. + + 4. Register 'Microsoft.Security' provider and enable Azure Defender plan for all non-compliant resource types for subscription. + +# Step to execute script: + Download and load remediation script in PowerShell session and execute below command. + To know how to load script in PowerShell session refer link: https://aka.ms/AzTS-docs/RemediationscriptExcSteps. + +# Command to execute: + Examples: + 1. Run below command to configure Azure Defender for subscription + + Enable-EncrytionAtHost -SubscriptionId '' -PerformPreReqCheck: $true + + Note: + To rollback changes made by remediation script, execute below command + Disable-EncrytionAtHost -SubscriptionId '' -Path '' -PerformPreReqCheck: $true + +To know more about parameter execute: + a. Get-Help Enable-EncrytionAtHost -Detailed + b. Get-Help Disable-EncrytionAtHost -Detailed + +######################################## +#> +function Pre_requisites { + <# + .SYNOPSIS + This command would check pre requisites modules. + .DESCRIPTION + This command would check pre requisites modules to perform remediation. + #> + + Write-Host "Required modules are: Az.Resources, Az.Security, Az.Accounts" -ForegroundColor Cyan + Write-Host "Checking for required modules..." + $availableModules = $(Get-Module -ListAvailable Az.Resources, Az.Security, Az.Accounts) + + # Checking if 'Az.Accounts' module is available or not. + if ($availableModules.Name -notcontains 'Az.Accounts') { + Write-Host "Installing module Az.Accounts..." -ForegroundColor Yellow + Install-Module -Name Az.Accounts -Scope CurrentUser -Repository 'PSGallery' + } + else { + Write-Host "Az.Accounts module is available." -ForegroundColor Green + } + + # Checking if 'Az.Resources' module is available or not. + if ($availableModules.Name -notcontains 'Az.Resources') { + Write-Host "Installing module Az.Resources..." -ForegroundColor Yellow + Install-Module -Name Az.Resources -Scope CurrentUser -Repository 'PSGallery' + } + else { + Write-Host "Az.Resources module is available." -ForegroundColor Green + } + + # Checking if 'Az.Security' module is available or not. + if ($availableModules.Name -notcontains 'Az.Security') { + Write-Host "Installing module Az.Security..." -ForegroundColor Yellow + Install-Module -Name Az.Security -Scope CurrentUser -Repository 'PSGallery' + } + else { + Write-Host "Az.Security module is available." -ForegroundColor Green + } +} +function Enable-EncrytionAtHost { + <# + .SYNOPSIS + This command would help in remediating 'Azure_VirtualMachineScaleSet_DP_Enable_Encryption_At_Host' control. + .DESCRIPTION + This command would help in remediating 'Azure_VirtualMachineScaleSet_DP_Enable_Encryption_At_Host' control. + .PARAMETER SubscriptionId + Enter subscription id on which remediation needs to be performed. + .PARAMETER PerformPreReqCheck + Perform pre requisites check to ensure all required modules to perform remediation operation are available. + #> + param( + [string] + [Parameter(Mandatory = $true, HelpMessage = "Enter subscription id for remediation")] + $SubscriptionId, + + [switch] + $PerformPreReqCheck + ) + Write-Host $([Constants]::DoubleDashLine) + Write-Host "Starting operation for subscription [$($SubscriptionId)]...`n" + if ($PerformPreReqCheck) { + try { + Write-Host "Checking for pre-requisites..." + Pre_requisites + Write-Host $([Constants]::SingleDashLine) + } + catch { + Write-Host "Error occurred while checking pre-requisites. ErrorMessage [$($_)]" -ForegroundColor Red + break + } + } + # Connect to AzAccount + $isContextSet = Get-AzContext + if ([string]::IsNullOrEmpty($isContextSet)) { + Write-Host "Connecting to AzAccount..." + Connect-AzAccount -ErrorAction Stop + Write-Host "Connected to AzAccount" -ForegroundColor Green + } + # Setting context for current subscription. + $currentSub = Set-AzContext -SubscriptionId $SubscriptionId -ErrorAction Stop -Force + + Write-Host "Metadata Details: `n SubscriptionId: $($SubscriptionId) `n AccountName: $($currentSub.Account.Id) `n AccountType: $($currentSub.Account.Type)" + Write-Host $([Constants]::SingleDashLine) + Write-Host "Starting with Subscription [$($SubscriptionId)]..." + + Write-Host "Step 1 of 3: Validating whether the current user [$($currentSub.Account.Id)] has the required permissions to run the script for subscription [$($SubscriptionId)]..." + + # Safe Check: Checking whether the current account is of type User + if ($currentSub.Account.Type -ne "User") { + Write-Host "Warning: This script can only be run by user account type." -ForegroundColor Yellow + return; + } + + # Safe Check: Current user needs to be either Contributor or Owner for the subscription + $currentLoginRoleAssignments = Get-AzRoleAssignment -SignInName $currentSub.Account.Id -Scope "/subscriptions/$($SubscriptionId)"; + + if (($currentLoginRoleAssignments | Where { $_.RoleDefinitionName -eq "Owner" -or $_.RoleDefinitionName -eq 'Contributor' -or $_.RoleDefinitionName -eq "Security Admin" } | Measure-Object).Count -le 0) { + Write-Host "Warning: This script can only be run by an Owner or Contributor of subscription [$($SubscriptionId)] " -ForegroundColor Yellow + return; + } + + # Get All Resource Groups + $resourceGroups = Get-AzResourceGroup | Select ResourceGroupName + Write-Host $resourceGroups.Count + Get-AzProviderFeature -FeatureName "EncryptionAtHost" -ProviderNamespace "Microsoft.Compute" + $vmScaleSetBackup = @() + $vmBackup = @() + + Write-Host "Authentication successfull!!`n" -ForegroundColor Cyan + Write-Host $([Constants]::SingleDashLine) + Write-Host "Step 2 of 3: Started operation on Virtual machine scale set..." + foreach ($rg in $resourceGroups) { + $ResourceGroupName = $rg.ResourceGroupName + if ($ResourceGroupName -ne "OmkarTestRG") { + continue + } + $virtualMachineScaleSets = Get-AzVmss -ResourceGroupName $ResourceGroupName + Write-Host "Found [$($virtualMachineScaleSets.Count)] Virtual Machine Scale Sets" + + $colsProperty = @{Expression = { $_.Name }; Label = "Virtual Machine Scale Set Name"; Width = 60; Alignment = "left" }, + @{Expression = { $_.Location }; Label = "Location"; Width = 40; Alignment = "left" }, + @{Expression = { $_.ProvisioningState }; Label = "Provisioning State"; Width = 80; Alignment = "left" } + $virtualMachineScaleSets | Format-Table -Property $colsProperty -Wrap + + if (($virtualMachineScaleSets | Measure-Object).Count -gt 0) { + foreach ($ele in $virtualMachineScaleSets) { + $VMScaleSetName = $ele.Name + $VMSS = Get-AzVmss -ResourceGroupName $ResourceGroupName -Name $VMScaleSetName + $isEncrytionSet = $VMSS.VirtualMachineProfile.SecurityProfile.EncryptionAtHost + if ($isEncrytionSet) { + Write-Host "Encryption at Host already enabled for [$($VMScaleSetName)] VM Scale Set.`n" -ForegroundColor Cyan + } + else { + try { + Write-Host "Enabling Encrytion at Host for [$($VMScaleSetName)] VM Scale Set..." + $VMSS = Get-AzVmss -ResourceGroupName $ResourceGroupName -Name $VMScaleSetName + Update-AzVmss -VirtualMachineScaleSet $VMSS -Name $VMScaleSetName -ResourceGroupName $ResourceGroupName -EncryptionAtHost $true + $vmScaleSetBackup += [PSCustomObject]@{ + ResourceGroupName = $ResourceGroupName + VMSSName = $VMScaleSetName + } + } + catch { + Write-Host "Operation Failed : Enable Encryption at Host for [$($VMScaleSetName)].`n" + } + Write-Host "Successfully enabled Encrytion at Host property for [$($VMScaleSetName)] VM Scale Set!!!`n" + + } + } + } + + Write-Host $([Constants]::SingleDashLine) + $VirtualMachines = Get-AzVM -ResourceGroupName $ResourceGroupName + Write-Host "Found [$($VirtualMachines.Count)] Virtual Machines." + $colsProperty = @{Expression = { $_.Name }; Label = "Virtual Machine Name"; Width = 60; Alignment = "left" }, + @{Expression = { $_.Location }; Label = "Location"; Width = 40; Alignment = "left" }, + @{Expression = { $_.OsType }; Label = "OS Type"; Width = 20; Alignment = "left" }, + @{Expression = { $_.VmSize }; Label = "Vm Size"; Width = 20; Alignment = "left" } + $VirtualMachines | Format-Table -Property $colsProperty -Wrap + + foreach ($VirtualMachine in $VirtualMachines) { + $VMName = $VirtualMachine.Name + $VM = Get-AzVM -ResourceGroupName $ResourceGroupName -Name $VMName + if ($VM.SecurityProfile.EncryptionAtHost -ne $true) { + try { + Write-Host "This step will stop and restart [$($VMName)] Virtual Machine." -ForegroundColor Yellow + Write-Host "It may take few minutes..." -ForegroundColor Yellow + Write-Host "Do you want to continue? " -ForegroundColor Yellow + + $userInput = Read-Host -Prompt "(Y|N)" + + if($userInput -eq "Y" -or $userInput -eq "y") { + Write-Host "Enabling Encryption at Host for [$($VMName)] Virtual Machine..." + Stop-AzVM -ResourceGroupName $ResourceGroupName -Name $VMName -Force + Update-AzVM -VM $VM -ResourceGroupName $ResourceGroupName -EncryptionAtHost $true + $vmBackup += [PSCustomObject]@{ + ResourceGroupName = $ResourceGroupName + VMName = $VMName + } + Write-Host "Successfully set Encrytion at Host for [$($VMName)] Virtual machine.`n" -ForegroundColor Cyan + Write-Host "Restarting [$($VMName)] Virtual machine...." + Start-AzVM -ResourceGroupName $ResourceGroupName -Name $VMName + Write-Host "Successfully re-started [$($VMName)] Virtual machine.`n" -ForegroundColor Cyan + } + } + catch { + Write-Host "Operation Failed" -ForegroundColor Red + } + } + else { + Write-Host "Encrytion at Host already enabled for [$($VMName)] virtual machine.`n" -ForegroundColor Cyan + } + + } + Write-Host $([Constants]::SingleDashLine) + } + # Creating the log file + $folderPath = [Environment]::GetFolderPath("MyDocuments") + if (Test-Path -Path $folderPath) { + $folderPath += "\AzTS\Remediation\Subscriptions\$($SubscriptionId.replace("-","_"))\$((Get-Date).ToString('yyyyMMdd_hhmm'))\VirtualMachine" + New-Item -ItemType Directory -Path $folderPath | Out-Null + } + + $backup = New-Object psobject -Property @{ + SubscriptionId = $SubscriptionId + } + $backup | Add-Member -Name 'VMSS' -Type NoteProperty -Value $vmScaleSetBackup + $backup | Add-Member -Name 'VM' -Type NoteProperty -Value $vmBackup + + Write-Host "Step 3 of 3: Taking backup of resource types provider registration status. Please do not delete this file. Without this file you won't be able to rollback any changes done through Remediation script." -ForegroundColor Cyan + $backup | ConvertTo-json | out-file "$($folderpath)\Vmss.json" + Write-Host "Path: $($folderpath)\Vmss.json" + Write-Host "`n" + Write-Host $([Constants]::DoubleDashLine) + Write-Host "Successfully completed remediation of Virtual machine scale set and Virtual machines on subscription [$($SubscriptionId)]" -ForegroundColor Green + Write-Host $([Constants]::DoubleDashLine) +} + + + +function Disable-EncrytionAtHost { + <# + .SYNOPSIS + This command would help in remediating 'Azure_VirtualMachineScaleSet_DP_Enable_Encryption_At_Host' control. + .DESCRIPTION + This command would help in remediating 'Azure_VirtualMachineScaleSet_DP_Enable_Encryption_At_Host' control. + .PARAMETER SubscriptionId + Enter subscription id on which remediation needs to be performed. + .PARAMETER PerformPreReqCheck + Perform pre requisites check to ensure all required modules to perform rollback operation are available. + #> + + param ( + [string] + [Parameter(Mandatory = $true, HelpMessage = "Enter subscription id to perform rollback operation")] + $SubscriptionId, + + [string] + [Parameter(Mandatory = $true, HelpMessage = "Json file path which contain logs generated by remediation script to rollback remediation changes")] + $Path, + + [switch] + $PerformPreReqCheck + ) + + Write-Host $([Constants]::DoubleDashLine) + Write-Host "Started rollback operation on subscription [$($SubscriptionId)]..." + Write-Host $([Constants]::SingleDashLine) + + if ($PerformPreReqCheck) { + try { + Write-Host "Checking for pre-requisites..." + Pre_requisites + Write-Host $([Constants]::SingleDashLine) + } + catch { + Write-Host "Error occurred while checking pre-requisites. ErrorMessage [$($_)]" -ForegroundColor Red + break + } + } + + # Connect to AzAccount + $isContextSet = Get-AzContext + if ([string]::IsNullOrEmpty($isContextSet)) { + Write-Host "Connecting to AzAccount..." + Connect-AzAccount -ErrorAction Stop + Write-Host "Connected to AzAccount" -ForegroundColor Green + } + # Setting context for current subscription. + $currentSub = Set-AzContext -SubscriptionId $SubscriptionId -ErrorAction Stop -Force + + Write-Host "Metadata Details: `n SubscriptionId: $($SubscriptionId) `n AccountName: $($currentSub.Account.Id) `n AccountType: $($currentSub.Account.Type)" + Write-Host $([Constants]::SingleDashLine) + Write-Host "Starting with Subscription [$($SubscriptionId)]..." + + Write-Host "Validating whether the current user [$($currentSub.Account.Id)] has the required permissions to run the script for subscription [$($SubscriptionId)]..." + + # Safe Check: Checking whether the current account is of type User + if ($currentSub.Account.Type -ne "User") { + Write-Host "Warning: This script can only be run by user account type." -ForegroundColor Yellow + return; + } + + # Safe Check: Current user needs to be either Contributor or Owner for the subscription + $currentLoginRoleAssignments = Get-AzRoleAssignment -SignInName $currentSub.Account.Id -Scope "/subscriptions/$($SubscriptionId)"; + + if (($currentLoginRoleAssignments | Where { $_.RoleDefinitionName -eq "Owner" -or $_.RoleDefinitionName -eq 'Contributor' -or $_.RoleDefinitionName -eq "Security Admin" } | Measure-Object).Count -le 0) { + Write-Host "Warning: This script can only be run by an Owner or Contributor of subscription [$($SubscriptionId)] " -ForegroundColor Yellow + return; + } + + # Array to store resource context + if (-not (Test-Path -Path $Path)) { + Write-Host "Warning: Rollback file is not found. Please check if the initial Remediation script has been run from the same machine. Exiting the process" -ForegroundColor Yellow + break; + } + + $remediatedLog = Get-Content -Raw -Path $Path | ConvertFrom-Json + + Write-Host "`nPerforming rollback operation to disable encryption at host for subscription [$($SubscriptionId)]...`n" + + # Rollback Virtual Machine Scale Set + if ($null -ne $remediatedLog.VMSS -and ($remediatedLog.VMSS | Measure-Object).Count -gt 0) { + foreach ($ele in $remediatedLog.VMSS) { + $VMScaleSetName = $ele.VMSSName + $ResourceGroupName = $ele.ResourceGroupName + $VMSS = Get-AzVmss -ResourceGroupName $ResourceGroupName -Name $VMScaleSetName + try { + Write-Host "Disabling Encrytion at Host property for [$($VMScaleSetName)] VM Scale Set..." + $VMSS = Get-AzVmss -ResourceGroupName $ResourceGroupName -Name $VMScaleSetName + Update-AzVmss -VirtualMachineScaleSet $VMSS -Name $VMScaleSetName -ResourceGroupName $ResourceGroupName -EncryptionAtHost $false + + } + catch { + Write-Host "Operation Failed : Disable Encryption at Host for [$($VMScaleSetName)]." + } + Write-Host "Successfully disabled Encrytion at Host property for [$($VMScaleSetName)] VM Scale Set!!!`n" + + + } + + + } + else { + Write-Host "No virtual machine scale sets found to perform rollback operation." -ForegroundColor Green + } + + # Rollback Virtual machines + if ($null -ne $remediatedLog.VM -and ($remediatedLog.VM | Measure-Object).Count -gt 0) { + + foreach ($remediatedVm in $remediatedLog.VM) { + try { + $VMName = $remediatedVm.VMName + + Write-Host "This step will stop and restart [$($VMName)] Virtual Machine." -ForegroundColor Yellow + Write-Host "It may take few minutes..." -ForegroundColor Yellow + Write-Host "Do you want to continue? " -ForegroundColor Yellow + + $userInput = Read-Host -Prompt "(Y|N)" + + if($userInput -eq "Y" -or $userInput -eq "y") { + Write-Host "Disabling Encryption at Host for [$($VMName)] Virtual Machine." + $VM = Get-AzVM -ResourceGroupName $remediatedVm.ResourceGroupName -Name $VMName + + Stop-AzVM -ResourceGroupName $remediatedVm.ResourceGroupName -Name $VMName -Force + + Update-AzVM -VM $VM -ResourceGroupName $remediatedVm.ResourceGroupName -EncryptionAtHost $false + + Write-Host "Successfully disabled Encrytion at Host for [$($VMName)] Virtual machine." + Write-Host "Restarting [$($VMName)] Virtual machine..." + + Start-AzVM -ResourceGroupName $remediatedVm.ResourceGroupName -Name $VMName + Write-Host "Successfully re-started [$($VMName)] Virtual machine.`n" + Write-Host $([Constants]::SingleDashLine) + } + } + catch { + Write-Host "Error occurred while performing rollback operation to disable Encrytion at Host. ErrorMessage [$($_)]" -ForegroundColor Red + } + } + + } + else { + Write-Host "No Virtual Machine records found to perform rollback operation." -ForegroundColor Green + } + + Write-Host $([Constants]::DoubleDashLine) + Write-Host "`nRollback operation completed......." -ForegroundColor Green +} + + +class Constants { + static [String] $DoubleDashLine = "========================================================================================================================" + static [String] $SingleDashLine = "------------------------------------------------------------------------------------------------------------------------" +} \ No newline at end of file From 0898bb6707c46d8e883b044e6a3d9cc8f224ac43 Mon Sep 17 00:00:00 2001 From: Omkar Mohite Date: Wed, 23 Apr 2025 14:59:10 +0530 Subject: [PATCH 02/11] Updated minor changes --- .../Remediate-EnableEncrytionAtHostForVMSS.ps1 | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Scripts/RemediationScripts/Remediate-EnableEncrytionAtHostForVMSS.ps1 b/Scripts/RemediationScripts/Remediate-EnableEncrytionAtHostForVMSS.ps1 index 39ac6a23..df1a7106 100644 --- a/Scripts/RemediationScripts/Remediate-EnableEncrytionAtHostForVMSS.ps1 +++ b/Scripts/RemediationScripts/Remediate-EnableEncrytionAtHostForVMSS.ps1 @@ -141,7 +141,6 @@ function Enable-EncrytionAtHost { # Get All Resource Groups $resourceGroups = Get-AzResourceGroup | Select ResourceGroupName - Write-Host $resourceGroups.Count Get-AzProviderFeature -FeatureName "EncryptionAtHost" -ProviderNamespace "Microsoft.Compute" $vmScaleSetBackup = @() $vmBackup = @() @@ -151,9 +150,6 @@ function Enable-EncrytionAtHost { Write-Host "Step 2 of 3: Started operation on Virtual machine scale set..." foreach ($rg in $resourceGroups) { $ResourceGroupName = $rg.ResourceGroupName - if ($ResourceGroupName -ne "OmkarTestRG") { - continue - } $virtualMachineScaleSets = Get-AzVmss -ResourceGroupName $ResourceGroupName Write-Host "Found [$($virtualMachineScaleSets.Count)] Virtual Machine Scale Sets" @@ -412,4 +408,4 @@ function Disable-EncrytionAtHost { class Constants { static [String] $DoubleDashLine = "========================================================================================================================" static [String] $SingleDashLine = "------------------------------------------------------------------------------------------------------------------------" -} \ No newline at end of file +} From 0315dd44aaa03ed66b2640b77f71ff52554e23bc Mon Sep 17 00:00:00 2001 From: "Omkar Mohite (TATA CONSULTANCY SERVICES LTD)" Date: Fri, 25 Apr 2025 15:56:31 +0530 Subject: [PATCH 03/11] code changes for vmss --- ...Remediate-EnableEncrytionAtHostForVMSS.ps1 | 176 +++++++++++------- 1 file changed, 107 insertions(+), 69 deletions(-) diff --git a/Scripts/RemediationScripts/Remediate-EnableEncrytionAtHostForVMSS.ps1 b/Scripts/RemediationScripts/Remediate-EnableEncrytionAtHostForVMSS.ps1 index df1a7106..ab13da3c 100644 --- a/Scripts/RemediationScripts/Remediate-EnableEncrytionAtHostForVMSS.ps1 +++ b/Scripts/RemediationScripts/Remediate-EnableEncrytionAtHostForVMSS.ps1 @@ -16,7 +16,6 @@ 3. Take a backup of these non-compliant resource types. - 4. Register 'Microsoft.Security' provider and enable Azure Defender plan for all non-compliant resource types for subscription. # Step to execute script: Download and load remediation script in PowerShell session and execute below command. @@ -24,7 +23,7 @@ # Command to execute: Examples: - 1. Run below command to configure Azure Defender for subscription + 1. Run below command to Enable Encrytion at Host for vmss Enable-EncrytionAtHost -SubscriptionId '' -PerformPreReqCheck: $true @@ -38,6 +37,7 @@ To know more about parameter execute: ######################################## #> + function Pre_requisites { <# .SYNOPSIS @@ -77,6 +77,49 @@ function Pre_requisites { Write-Host "Az.Security module is available." -ForegroundColor Green } } + +function Fetch-API { + param ( + [Parameter(Mandatory = $true)] + [string]$Method, + + [Parameter(Mandatory = $true)] + [string]$Uri, + + [Parameter(Mandatory = $false)] + [hashtable]$Body = @{}, + + [Parameter(Mandatory = $false)] + [hashtable]$Headers = @{} + ) + + $cloudEnvironmentResourceManagerUrl = (Get-AzContext).Environment.ResourceManagerUrl + $accessToken = Get-AzAccessToken -ResourceUrl $cloudEnvironmentResourceManagerUrl + $authHeader = "Bearer " + $accessToken.Token + $Headers["Authorization"] = $authHeader + $Headers["Content-Type"] = "application/json" + + try { + switch ($Method.ToUpper()) { + "GET" { + $response = Invoke-WebRequest -Uri $Uri -Method Get -Headers $Headers -UseBasicParsing -ErrorAction Stop + } + default { + throw "Unsupported HTTP method: $Method" + } + } + + if ($response.StatusCode -eq 200 -or $response.StatusCode -eq 201) { + return $response.Content | ConvertFrom-Json + } + else { + throw "API call failed with status code $($response.StatusCode)" + } + } + catch { + Write-Error "Error occurred: $_" + } +} function Enable-EncrytionAtHost { <# .SYNOPSIS @@ -148,86 +191,81 @@ function Enable-EncrytionAtHost { Write-Host "Authentication successfull!!`n" -ForegroundColor Cyan Write-Host $([Constants]::SingleDashLine) Write-Host "Step 2 of 3: Started operation on Virtual machine scale set..." + $reqOrchestrationMode = "Flexible" foreach ($rg in $resourceGroups) { $ResourceGroupName = $rg.ResourceGroupName - $virtualMachineScaleSets = Get-AzVmss -ResourceGroupName $ResourceGroupName + $virtualMachineScaleSets = Get-AzVmss -ResourceGroupName $ResourceGroupName | Select-Object Name, Type, OrchestrationMode Write-Host "Found [$($virtualMachineScaleSets.Count)] Virtual Machine Scale Sets" - $colsProperty = @{Expression = { $_.Name }; Label = "Virtual Machine Scale Set Name"; Width = 60; Alignment = "left" }, - @{Expression = { $_.Location }; Label = "Location"; Width = 40; Alignment = "left" }, - @{Expression = { $_.ProvisioningState }; Label = "Provisioning State"; Width = 80; Alignment = "left" } + $colsProperty = @{Expression = { $_.Name }; Label = "Virtual Machine Scale Set Name"; Width = 60; Alignment = "left" }, + @{Expression = { $_.Location }; Label = "Location"; Width = 40; Alignment = "left" }, + @{Expression = { $_.ProvisioningState }; Label = "Provisioning State"; Width = 80; Alignment = "left" } $virtualMachineScaleSets | Format-Table -Property $colsProperty -Wrap if (($virtualMachineScaleSets | Measure-Object).Count -gt 0) { foreach ($ele in $virtualMachineScaleSets) { - $VMScaleSetName = $ele.Name - $VMSS = Get-AzVmss -ResourceGroupName $ResourceGroupName -Name $VMScaleSetName - $isEncrytionSet = $VMSS.VirtualMachineProfile.SecurityProfile.EncryptionAtHost - if ($isEncrytionSet) { - Write-Host "Encryption at Host already enabled for [$($VMScaleSetName)] VM Scale Set.`n" -ForegroundColor Cyan - } - else { - try { - Write-Host "Enabling Encrytion at Host for [$($VMScaleSetName)] VM Scale Set..." - $VMSS = Get-AzVmss -ResourceGroupName $ResourceGroupName -Name $VMScaleSetName - Update-AzVmss -VirtualMachineScaleSet $VMSS -Name $VMScaleSetName -ResourceGroupName $ResourceGroupName -EncryptionAtHost $true - $vmScaleSetBackup += [PSCustomObject]@{ - ResourceGroupName = $ResourceGroupName - VMSSName = $VMScaleSetName - } + if ($ele.OrchestrationMode -eq $reqOrchestrationMode) { + $VMScaleSetName = $ele.Name + $VMSS = Get-AzVmss -ResourceGroupName $ResourceGroupName -Name $VMScaleSetName + $isEncrytionSet = $VMSS.VirtualMachineProfile.SecurityProfile.EncryptionAtHost + if ($isEncrytionSet) { + Write-Host "Encryption at Host already enabled for [$($VMScaleSetName)] VM Scale Set.`n" -ForegroundColor Cyan } - catch { - Write-Host "Operation Failed : Enable Encryption at Host for [$($VMScaleSetName)].`n" - } - Write-Host "Successfully enabled Encrytion at Host property for [$($VMScaleSetName)] VM Scale Set!!!`n" - - } - } - } - - Write-Host $([Constants]::SingleDashLine) - $VirtualMachines = Get-AzVM -ResourceGroupName $ResourceGroupName - Write-Host "Found [$($VirtualMachines.Count)] Virtual Machines." - $colsProperty = @{Expression = { $_.Name }; Label = "Virtual Machine Name"; Width = 60; Alignment = "left" }, - @{Expression = { $_.Location }; Label = "Location"; Width = 40; Alignment = "left" }, - @{Expression = { $_.OsType }; Label = "OS Type"; Width = 20; Alignment = "left" }, - @{Expression = { $_.VmSize }; Label = "Vm Size"; Width = 20; Alignment = "left" } - $VirtualMachines | Format-Table -Property $colsProperty -Wrap - - foreach ($VirtualMachine in $VirtualMachines) { - $VMName = $VirtualMachine.Name - $VM = Get-AzVM -ResourceGroupName $ResourceGroupName -Name $VMName - if ($VM.SecurityProfile.EncryptionAtHost -ne $true) { - try { - Write-Host "This step will stop and restart [$($VMName)] Virtual Machine." -ForegroundColor Yellow - Write-Host "It may take few minutes..." -ForegroundColor Yellow - Write-Host "Do you want to continue? " -ForegroundColor Yellow - - $userInput = Read-Host -Prompt "(Y|N)" - - if($userInput -eq "Y" -or $userInput -eq "y") { - Write-Host "Enabling Encryption at Host for [$($VMName)] Virtual Machine..." - Stop-AzVM -ResourceGroupName $ResourceGroupName -Name $VMName -Force - Update-AzVM -VM $VM -ResourceGroupName $ResourceGroupName -EncryptionAtHost $true - $vmBackup += [PSCustomObject]@{ + else { + try { + Write-Host "Enabling Encrytion at Host for [$($VMScaleSetName)] VM Scale Set..." + $VMSS = Get-AzVmss -ResourceGroupName $ResourceGroupName -Name $VMScaleSetName + Update-AzVmss -VirtualMachineScaleSet $VMSS -Name $VMScaleSetName -ResourceGroupName $ResourceGroupName -EncryptionAtHost $true + $vmScaleSetBackup += [PSCustomObject]@{ ResourceGroupName = $ResourceGroupName - VMName = $VMName + VMSSName = $VMScaleSetName } - Write-Host "Successfully set Encrytion at Host for [$($VMName)] Virtual machine.`n" -ForegroundColor Cyan - Write-Host "Restarting [$($VMName)] Virtual machine...." - Start-AzVM -ResourceGroupName $ResourceGroupName -Name $VMName - Write-Host "Successfully re-started [$($VMName)] Virtual machine.`n" -ForegroundColor Cyan } + catch { + Write-Host "Operation Failed : Enable Encryption at Host for [$($VMScaleSetName)].`n" + } + Write-Host "Successfully enabled Encrytion at Host property for [$($VMScaleSetName)] VM Scale Set!!!`n" + + } + $Uri = "https://management.azure.com/subscriptions/$SubscriptionId/resourceGroups/$ResourceGroupName/providers/Microsoft.Compute/virtualMachineScaleSets/$VMScaleSetName/virtualMachines?api-version=2024-11-01" + $virtualMachines = Fetch-API -Method "GET" -Uri $Uri + foreach ($virtualMachine in $virtualMachines.Value) { + $VMName = $virtualMachine.Name + $VM = Get-AzVM -ResourceGroupName $ResourceGroupName -Name $VMName + if ($VM.SecurityProfile.EncryptionAtHost -ne $true) { + try { + Write-Host "This step will stop and restart [$($VMName)] Virtual Machine." -ForegroundColor Yellow + Write-Host "It may take few minutes..." -ForegroundColor Yellow + Write-Host "Do you want to continue? " -ForegroundColor Yellow + + $userInput = Read-Host -Prompt "(Y|N)" + + if ($userInput -eq "Y" -or $userInput -eq "y") { + Write-Host "Enabling Encryption at Host for [$($VMName)] Virtual Machine..." + Stop-AzVM -ResourceGroupName $ResourceGroupName -Name $VMName -Force + Update-AzVM -VM $VM -ResourceGroupName $ResourceGroupName -EncryptionAtHost $true + $vmBackup += [PSCustomObject]@{ + ResourceGroupName = $ResourceGroupName + VMName = $VMName + } + Write-Host "Successfully set Encrytion at Host for [$($VMName)] Virtual machine.`n" -ForegroundColor Cyan + Write-Host "Restarting [$($VMName)] Virtual machine...." + Start-AzVM -ResourceGroupName $ResourceGroupName -Name $VMName + Write-Host "Successfully re-started [$($VMName)] Virtual machine.`n" -ForegroundColor Cyan + } + } + catch { + Write-Host "Operation Failed" -ForegroundColor Red + } + } + else { + Write-Host "Encrytion at Host already enabled for [$($VMName)] virtual machine.`n" -ForegroundColor Cyan + } + } } - catch { - Write-Host "Operation Failed" -ForegroundColor Red - } - } - else { - Write-Host "Encrytion at Host already enabled for [$($VMName)] virtual machine.`n" -ForegroundColor Cyan + } - - } + } Write-Host $([Constants]::SingleDashLine) } # Creating the log file @@ -374,7 +412,7 @@ function Disable-EncrytionAtHost { $userInput = Read-Host -Prompt "(Y|N)" - if($userInput -eq "Y" -or $userInput -eq "y") { + if ($userInput -eq "Y" -or $userInput -eq "y") { Write-Host "Disabling Encryption at Host for [$($VMName)] Virtual Machine." $VM = Get-AzVM -ResourceGroupName $remediatedVm.ResourceGroupName -Name $VMName From 1ab7aa0fa1cfc1169c073e987cf850fc5417a0fe Mon Sep 17 00:00:00 2001 From: "Omkar Mohite (TATA CONSULTANCY SERVICES LTD)" Date: Wed, 30 Apr 2025 16:33:48 +0530 Subject: [PATCH 04/11] code changes for extra checks --- ...Remediate-EnableEncrytionAtHostForVMSS.ps1 | 37 +++++++++++++------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/Scripts/RemediationScripts/Remediate-EnableEncrytionAtHostForVMSS.ps1 b/Scripts/RemediationScripts/Remediate-EnableEncrytionAtHostForVMSS.ps1 index ab13da3c..e30920aa 100644 --- a/Scripts/RemediationScripts/Remediate-EnableEncrytionAtHostForVMSS.ps1 +++ b/Scripts/RemediationScripts/Remediate-EnableEncrytionAtHostForVMSS.ps1 @@ -1,7 +1,7 @@ <########################################## # Overview: - This script is used to Enable Encryption at Host for Virtual machine scale sets and Virtual machines. + This script is used to Enable Encryption at Host for Virtual machine scale sets and underlying Virtual machines in flexible orchestration mode. # ControlId: Azure_VirtualMachineScaleSet_DP_Enable_Encryption_At_Host @@ -94,8 +94,11 @@ function Fetch-API { ) $cloudEnvironmentResourceManagerUrl = (Get-AzContext).Environment.ResourceManagerUrl - $accessToken = Get-AzAccessToken -ResourceUrl $cloudEnvironmentResourceManagerUrl - $authHeader = "Bearer " + $accessToken.Token + $accessToken = Get-AzAccessToken -ResourceUrl $cloudEnvironmentResourceManagerUrl -AsSecureString + $credential = New-Object System.Net.NetworkCredential("", $accessToken.Token) + $token = $credential.Password + + $authHeader = "Bearer " + $token $Headers["Authorization"] = $authHeader $Headers["Content-Type"] = "application/json" @@ -190,12 +193,13 @@ function Enable-EncrytionAtHost { Write-Host "Authentication successfull!!`n" -ForegroundColor Cyan Write-Host $([Constants]::SingleDashLine) - Write-Host "Step 2 of 3: Started operation on Virtual machine scale set..." + Write-Host "Step 2 of 3: Started operation on Virtual machine scale set and underlying Virtual machines..." $reqOrchestrationMode = "Flexible" + + Write-Host "Checking Virtual Machine Scale Sets and underlying virtual machines in each Resource Groups..." foreach ($rg in $resourceGroups) { $ResourceGroupName = $rg.ResourceGroupName $virtualMachineScaleSets = Get-AzVmss -ResourceGroupName $ResourceGroupName | Select-Object Name, Type, OrchestrationMode - Write-Host "Found [$($virtualMachineScaleSets.Count)] Virtual Machine Scale Sets" $colsProperty = @{Expression = { $_.Name }; Label = "Virtual Machine Scale Set Name"; Width = 60; Alignment = "left" }, @{Expression = { $_.Location }; Label = "Location"; Width = 40; Alignment = "left" }, @@ -203,6 +207,7 @@ function Enable-EncrytionAtHost { $virtualMachineScaleSets | Format-Table -Property $colsProperty -Wrap if (($virtualMachineScaleSets | Measure-Object).Count -gt 0) { + Write-Host "Found [$($virtualMachineScaleSets.Count)] Virtual Machine Scale Sets" foreach ($ele in $virtualMachineScaleSets) { if ($ele.OrchestrationMode -eq $reqOrchestrationMode) { $VMScaleSetName = $ele.Name @@ -253,9 +258,12 @@ function Enable-EncrytionAtHost { Start-AzVM -ResourceGroupName $ResourceGroupName -Name $VMName Write-Host "Successfully re-started [$($VMName)] Virtual machine.`n" -ForegroundColor Cyan } + else { + Write-Host "User cancelled the operation for [$($VMName)] Virtual machine." -ForegroundColor Yellow + } } catch { - Write-Host "Operation Failed" -ForegroundColor Red + Write-Host "Enabling Encryption at Host for [$($VMName)] Virtual machine operation failed" -ForegroundColor Red } } else { @@ -265,9 +273,10 @@ function Enable-EncrytionAtHost { } } - } - Write-Host $([Constants]::SingleDashLine) + Write-Host $([Constants]::SingleDashLine) + } } + # Creating the log file $folderPath = [Environment]::GetFolderPath("MyDocuments") if (Test-Path -Path $folderPath) { @@ -286,18 +295,19 @@ function Enable-EncrytionAtHost { Write-Host "Path: $($folderpath)\Vmss.json" Write-Host "`n" Write-Host $([Constants]::DoubleDashLine) - Write-Host "Successfully completed remediation of Virtual machine scale set and Virtual machines on subscription [$($SubscriptionId)]" -ForegroundColor Green + Write-Host "Successfully completed remediation of Virtual machine scale set and underlying Virtual machines on subscription [$($SubscriptionId)]" -ForegroundColor Green Write-Host $([Constants]::DoubleDashLine) -} + +} function Disable-EncrytionAtHost { <# .SYNOPSIS - This command would help in remediating 'Azure_VirtualMachineScaleSet_DP_Enable_Encryption_At_Host' control. + This command would help in rollback the changes made by 'Azure_VirtualMachineScaleSet_DP_Enable_Encryption_At_Host' control script. .DESCRIPTION - This command would help in remediating 'Azure_VirtualMachineScaleSet_DP_Enable_Encryption_At_Host' control. + This command would help in rollback the changes made by 'Azure_VirtualMachineScaleSet_DP_Enable_Encryption_At_Host' control script. .PARAMETER SubscriptionId Enter subscription id on which remediation needs to be performed. .PARAMETER PerformPreReqCheck @@ -427,6 +437,9 @@ function Disable-EncrytionAtHost { Write-Host "Successfully re-started [$($VMName)] Virtual machine.`n" Write-Host $([Constants]::SingleDashLine) } + else { + Write-Host "User cancelled the operation for [$($VMName)] Virtual machine." -ForegroundColor Yellow + } } catch { Write-Host "Error occurred while performing rollback operation to disable Encrytion at Host. ErrorMessage [$($_)]" -ForegroundColor Red From 94be9b3bc80b537ce8f4b869b01a480543fd78f1 Mon Sep 17 00:00:00 2001 From: Omkar Mohite Date: Wed, 30 Apr 2025 17:04:56 +0530 Subject: [PATCH 05/11] Update Remediate-EnableEncrytionAtHostForVMSS.ps1 --- .../Remediate-EnableEncrytionAtHostForVMSS.ps1 | 1 - 1 file changed, 1 deletion(-) diff --git a/Scripts/RemediationScripts/Remediate-EnableEncrytionAtHostForVMSS.ps1 b/Scripts/RemediationScripts/Remediate-EnableEncrytionAtHostForVMSS.ps1 index e30920aa..52b82fd1 100644 --- a/Scripts/RemediationScripts/Remediate-EnableEncrytionAtHostForVMSS.ps1 +++ b/Scripts/RemediationScripts/Remediate-EnableEncrytionAtHostForVMSS.ps1 @@ -219,7 +219,6 @@ function Enable-EncrytionAtHost { else { try { Write-Host "Enabling Encrytion at Host for [$($VMScaleSetName)] VM Scale Set..." - $VMSS = Get-AzVmss -ResourceGroupName $ResourceGroupName -Name $VMScaleSetName Update-AzVmss -VirtualMachineScaleSet $VMSS -Name $VMScaleSetName -ResourceGroupName $ResourceGroupName -EncryptionAtHost $true $vmScaleSetBackup += [PSCustomObject]@{ ResourceGroupName = $ResourceGroupName From e86d43772d8c48ea1fda7ca9f7cd0026d369ae37 Mon Sep 17 00:00:00 2001 From: "Omkar Mohite (TATA CONSULTANCY SERVICES LTD)" Date: Tue, 13 May 2025 18:30:01 +0530 Subject: [PATCH 06/11] readme file updated --- .../ControlRemediationSpecification.json | 11 +++++++++++ Scripts/RemediationScripts/Readme.md | 18 ++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/Scripts/RemediationScripts/ControlRemediationSpecification.json b/Scripts/RemediationScripts/ControlRemediationSpecification.json index 17cc0b13..b18cd9c3 100644 --- a/Scripts/RemediationScripts/ControlRemediationSpecification.json +++ b/Scripts/RemediationScripts/ControlRemediationSpecification.json @@ -555,6 +555,17 @@ "RollbackCommand": "Disable-MultiUserAuthorizationOnBackupVaults", "Arguments": ["SubscriptionId"] } + }, + { + "ControlId": "Azure_VirtualMachineScaleSet_DP_Enable_Encryption_At_Host", + "EnableRemediation": "true", + "RemediationScriptUrl": "https://raw.githubusercontent.com/azsk/AzTS-docs/main/Scripts/RemediationScripts/Remediate-EnableEncrytionAtHostForVMSS.ps1", + "LoadCommand": "Remediate-EnableEncrytionAtHostForVMSS.ps1", + "InitCommand": "Enable-EncrytionAtHost", + "RollbackMetadata": { + "RollbackCommand": "Disable-EncrytionAtHost", + "Arguments": ["SubscriptionId", "Path"] + } } ] } \ No newline at end of file diff --git a/Scripts/RemediationScripts/Readme.md b/Scripts/RemediationScripts/Readme.md index ac40040c..0551ebf8 100644 --- a/Scripts/RemediationScripts/Readme.md +++ b/Scripts/RemediationScripts/Readme.md @@ -1517,6 +1517,24 @@ Yes Yes ___ +## 74. Azure_VirtualMachineScaleSet_DP_Enable_Encryption_At_Host + +### Display Name +This script is used to Enable Encryption at Host for Virtual machine scale sets and underlying Virtual machines in flexible orchestration mode. + +### Link to Bulk Remediation Script (BRS) +[Enable-EncrytionAtHost](Remediate-EnableEncrytionAtHostForVMSS.ps1) + +### Minimum permissions required to run the script +Contributor or higher privileged role on Subscription. + +### [Supports managed identity](Readme.md#supports-managed-identity-based-remediations) based remediation +Yes + +### Supports rollback? +Yes +___ + ## Supports managed identity based remediations Both System assigned and User assigned managed identities are supported. From 4932acfaae12480be2e5ddb7cc1a35a4624c590e Mon Sep 17 00:00:00 2001 From: "Omkar Mohite (TATA CONSULTANCY SERVICES LTD)" Date: Mon, 19 May 2025 15:33:15 +0530 Subject: [PATCH 07/11] zip file changed for new scripts --- TemplateFiles/RemediationScripts.zip | Bin 779131 -> 784170 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/TemplateFiles/RemediationScripts.zip b/TemplateFiles/RemediationScripts.zip index f3be60da58e25a038fcfed9b07ae7bcd6f90f5c5..2dd27d9929f85321d2cbd40d2075c784705aa928 100644 GIT binary patch delta 29296 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 delta 24124 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
Fp6B#VoQxE5e@5n1Y_RP_ZLQZfPT$2?o_KeySJ# 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 XKARcQL3iM74}Mb#1K?7Qz~BA@pAQF< From a7c7723ebcb69f6499491e3021f97f07e3798b14 Mon Sep 17 00:00:00 2001 From: "Omkar Mohite (TATA CONSULTANCY SERVICES LTD)" Date: Tue, 20 May 2025 10:26:22 +0530 Subject: [PATCH 08/11] readme file updated --- .../ControlsEligibleForRemediationThroughUI.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Scripts/RemediationScripts/ControlsEligibleForRemediationThroughUI.md b/Scripts/RemediationScripts/ControlsEligibleForRemediationThroughUI.md index e2b4a431..de5547e7 100644 --- a/Scripts/RemediationScripts/ControlsEligibleForRemediationThroughUI.md +++ b/Scripts/RemediationScripts/ControlsEligibleForRemediationThroughUI.md @@ -630,6 +630,18 @@ Multi User Authorization must be enabled on backup vault ### Link to Bulk Remediation Script (BRS) [Enable-MultiUserAuthorizationOnBackupVaults.ps1](Enable-MultiUserAuthorizationOnBackupVaults.ps1) +### Minimum permissions required to run the script +Contributor or higher privileged role on Subscription. +___ + +## 43. Azure_VirtualMachineScaleSet_DP_Enable_Encryption_At_Host + +### Display Name +Encryption at Host must be enabled for Virtual machine scale sets and underlying Virtual machines in flexible orchestration mode. + +### Link to Bulk Remediation Script (BRS) +[Remediate-EnableEncrytionAtHostForVMSS.ps1](Remediate-EnableEncrytionAtHostForVMSS.ps1) + ### Minimum permissions required to run the script Contributor or higher privileged role on Subscription. ___ \ No newline at end of file From aed96ffa33406a88580b1a5009e12c0d53abee42 Mon Sep 17 00:00:00 2001 From: "Omkar Mohite (TATA CONSULTANCY SERVICES LTD)" Date: Thu, 22 May 2025 16:38:31 +0530 Subject: [PATCH 09/11] filter condition changed --- ...Remediate-EnableEncrytionAtHostForVMSS.ps1 | 104 +++++++++--------- 1 file changed, 51 insertions(+), 53 deletions(-) diff --git a/Scripts/RemediationScripts/Remediate-EnableEncrytionAtHostForVMSS.ps1 b/Scripts/RemediationScripts/Remediate-EnableEncrytionAtHostForVMSS.ps1 index 52b82fd1..05f161c4 100644 --- a/Scripts/RemediationScripts/Remediate-EnableEncrytionAtHostForVMSS.ps1 +++ b/Scripts/RemediationScripts/Remediate-EnableEncrytionAtHostForVMSS.ps1 @@ -199,7 +199,7 @@ function Enable-EncrytionAtHost { Write-Host "Checking Virtual Machine Scale Sets and underlying virtual machines in each Resource Groups..." foreach ($rg in $resourceGroups) { $ResourceGroupName = $rg.ResourceGroupName - $virtualMachineScaleSets = Get-AzVmss -ResourceGroupName $ResourceGroupName | Select-Object Name, Type, OrchestrationMode + $virtualMachineScaleSets = Get-AzVmss -ResourceGroupName $ResourceGroupName | where OrchestrationMode -eq $reqOrchestrationMode | Select-Object Name, Type, OrchestrationMode $colsProperty = @{Expression = { $_.Name }; Label = "Virtual Machine Scale Set Name"; Width = 60; Alignment = "left" }, @{Expression = { $_.Location }; Label = "Location"; Width = 40; Alignment = "left" }, @@ -209,66 +209,64 @@ function Enable-EncrytionAtHost { if (($virtualMachineScaleSets | Measure-Object).Count -gt 0) { Write-Host "Found [$($virtualMachineScaleSets.Count)] Virtual Machine Scale Sets" foreach ($ele in $virtualMachineScaleSets) { - if ($ele.OrchestrationMode -eq $reqOrchestrationMode) { - $VMScaleSetName = $ele.Name - $VMSS = Get-AzVmss -ResourceGroupName $ResourceGroupName -Name $VMScaleSetName - $isEncrytionSet = $VMSS.VirtualMachineProfile.SecurityProfile.EncryptionAtHost - if ($isEncrytionSet) { - Write-Host "Encryption at Host already enabled for [$($VMScaleSetName)] VM Scale Set.`n" -ForegroundColor Cyan - } - else { - try { - Write-Host "Enabling Encrytion at Host for [$($VMScaleSetName)] VM Scale Set..." - Update-AzVmss -VirtualMachineScaleSet $VMSS -Name $VMScaleSetName -ResourceGroupName $ResourceGroupName -EncryptionAtHost $true - $vmScaleSetBackup += [PSCustomObject]@{ - ResourceGroupName = $ResourceGroupName - VMSSName = $VMScaleSetName - } - } - catch { - Write-Host "Operation Failed : Enable Encryption at Host for [$($VMScaleSetName)].`n" + $VMScaleSetName = $ele.Name + $VMSS = Get-AzVmss -ResourceGroupName $ResourceGroupName -Name $VMScaleSetName + $isEncrytionSet = $VMSS.VirtualMachineProfile.SecurityProfile.EncryptionAtHost + if ($isEncrytionSet) { + Write-Host "Encryption at Host already enabled for [$($VMScaleSetName)] VM Scale Set.`n" -ForegroundColor Cyan + } + else { + try { + Write-Host "Enabling Encrytion at Host for [$($VMScaleSetName)] VM Scale Set..." + Update-AzVmss -VirtualMachineScaleSet $VMSS -Name $VMScaleSetName -ResourceGroupName $ResourceGroupName -EncryptionAtHost $true + $vmScaleSetBackup += [PSCustomObject]@{ + ResourceGroupName = $ResourceGroupName + VMSSName = $VMScaleSetName } - Write-Host "Successfully enabled Encrytion at Host property for [$($VMScaleSetName)] VM Scale Set!!!`n" - } - $Uri = "https://management.azure.com/subscriptions/$SubscriptionId/resourceGroups/$ResourceGroupName/providers/Microsoft.Compute/virtualMachineScaleSets/$VMScaleSetName/virtualMachines?api-version=2024-11-01" - $virtualMachines = Fetch-API -Method "GET" -Uri $Uri - foreach ($virtualMachine in $virtualMachines.Value) { - $VMName = $virtualMachine.Name - $VM = Get-AzVM -ResourceGroupName $ResourceGroupName -Name $VMName - if ($VM.SecurityProfile.EncryptionAtHost -ne $true) { - try { - Write-Host "This step will stop and restart [$($VMName)] Virtual Machine." -ForegroundColor Yellow - Write-Host "It may take few minutes..." -ForegroundColor Yellow - Write-Host "Do you want to continue? " -ForegroundColor Yellow - - $userInput = Read-Host -Prompt "(Y|N)" - - if ($userInput -eq "Y" -or $userInput -eq "y") { - Write-Host "Enabling Encryption at Host for [$($VMName)] Virtual Machine..." - Stop-AzVM -ResourceGroupName $ResourceGroupName -Name $VMName -Force - Update-AzVM -VM $VM -ResourceGroupName $ResourceGroupName -EncryptionAtHost $true - $vmBackup += [PSCustomObject]@{ - ResourceGroupName = $ResourceGroupName - VMName = $VMName - } - Write-Host "Successfully set Encrytion at Host for [$($VMName)] Virtual machine.`n" -ForegroundColor Cyan - Write-Host "Restarting [$($VMName)] Virtual machine...." - Start-AzVM -ResourceGroupName $ResourceGroupName -Name $VMName - Write-Host "Successfully re-started [$($VMName)] Virtual machine.`n" -ForegroundColor Cyan - } - else { - Write-Host "User cancelled the operation for [$($VMName)] Virtual machine." -ForegroundColor Yellow + catch { + Write-Host "Operation Failed : Enable Encryption at Host for [$($VMScaleSetName)].`n" + } + Write-Host "Successfully enabled Encrytion at Host property for [$($VMScaleSetName)] VM Scale Set!!!`n" + + } + $Uri = "https://management.azure.com/subscriptions/$SubscriptionId/resourceGroups/$ResourceGroupName/providers/Microsoft.Compute/virtualMachineScaleSets/$VMScaleSetName/virtualMachines?api-version=2024-11-01" + $virtualMachines = Fetch-API -Method "GET" -Uri $Uri + foreach ($virtualMachine in $virtualMachines.Value) { + $VMName = $virtualMachine.Name + $VM = Get-AzVM -ResourceGroupName $ResourceGroupName -Name $VMName + if ($VM.SecurityProfile.EncryptionAtHost -ne $true) { + try { + Write-Host "This step will stop and restart [$($VMName)] Virtual Machine." -ForegroundColor Yellow + Write-Host "It may take few minutes..." -ForegroundColor Yellow + Write-Host "Do you want to continue? " -ForegroundColor Yellow + + $userInput = Read-Host -Prompt "(Y|N)" + + if ($userInput -eq "Y" -or $userInput -eq "y") { + Write-Host "Enabling Encryption at Host for [$($VMName)] Virtual Machine..." + Stop-AzVM -ResourceGroupName $ResourceGroupName -Name $VMName -Force + Update-AzVM -VM $VM -ResourceGroupName $ResourceGroupName -EncryptionAtHost $true + $vmBackup += [PSCustomObject]@{ + ResourceGroupName = $ResourceGroupName + VMName = $VMName } + Write-Host "Successfully set Encrytion at Host for [$($VMName)] Virtual machine.`n" -ForegroundColor Cyan + Write-Host "Restarting [$($VMName)] Virtual machine...." + Start-AzVM -ResourceGroupName $ResourceGroupName -Name $VMName + Write-Host "Successfully re-started [$($VMName)] Virtual machine.`n" -ForegroundColor Cyan } - catch { - Write-Host "Enabling Encryption at Host for [$($VMName)] Virtual machine operation failed" -ForegroundColor Red + else { + Write-Host "User cancelled the operation for [$($VMName)] Virtual machine." -ForegroundColor Yellow } } - else { - Write-Host "Encrytion at Host already enabled for [$($VMName)] virtual machine.`n" -ForegroundColor Cyan + catch { + Write-Host "Enabling Encryption at Host for [$($VMName)] Virtual machine operation failed" -ForegroundColor Red } } + else { + Write-Host "Encrytion at Host already enabled for [$($VMName)] virtual machine.`n" -ForegroundColor Cyan + } } } From 053a6d1eaa15336fba4957fcc8e8db9668ebbfc3 Mon Sep 17 00:00:00 2001 From: "Omkar Mohite (TATA CONSULTANCY SERVICES LTD)" Date: Fri, 23 May 2025 10:45:20 +0530 Subject: [PATCH 10/11] readme file changes --- ...ControlsEligibleForRemediationThroughUI.md | 2 ++ Scripts/RemediationScripts/Readme.md | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/Scripts/RemediationScripts/ControlsEligibleForRemediationThroughUI.md b/Scripts/RemediationScripts/ControlsEligibleForRemediationThroughUI.md index d5efee5a..90ec0c80 100644 --- a/Scripts/RemediationScripts/ControlsEligibleForRemediationThroughUI.md +++ b/Scripts/RemediationScripts/ControlsEligibleForRemediationThroughUI.md @@ -87,6 +87,8 @@ 43. [Azure_AISearch_AuthN_Use_Managed_Service_Identity](ControlsEligibleForRemediationThroughUI.md#43-Azure_AISearch_AuthN_Use_Managed_Service_Identity) +43. [Azure_AISearch_AuthN_Use_Managed_Service_Identity](ControlsEligibleForRemediationThroughUI.md#43-Azure_VirtualMachineScaleSet_DP_Enable_Encryption_At_Host) +
___ diff --git a/Scripts/RemediationScripts/Readme.md b/Scripts/RemediationScripts/Readme.md index a8f3c94e..28ac5276 100644 --- a/Scripts/RemediationScripts/Readme.md +++ b/Scripts/RemediationScripts/Readme.md @@ -1555,6 +1555,25 @@ Yes ### Supports rollback? Yes +___ + +## 76. Azure_VirtualMachineScaleSet_DP_Enable_Encryption_At_Host + +### Display Name +This script is used to Enable Encryption at Host for Virtual machine scale sets and underlying Virtual machines in flexible orchestration mode. + +### Link to Bulk Remediation Script (BRS) +[Enable-EncrytionAtHost](Remediate-EnableEncrytionAtHostForVMSS.ps1) + +### Minimum permissions required to run the script +Contributor or higher privileged role on Subscription. + +### [Supports managed identity](Readme.md#supports-managed-identity-based-remediations) based remediation +Yes + +### Supports rollback? +Yes + --- ## Supports managed identity based remediations Both System assigned and User assigned managed identities are supported. From 08e7160c5b3ce73be4fe6214c70ba2bcc3b425af Mon Sep 17 00:00:00 2001 From: Omkar Mohite Date: Thu, 5 Jun 2025 20:30:22 +0530 Subject: [PATCH 11/11] code changes --- .../Remediate-EnableEncrytionAtHostForVMSS.ps1 | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Scripts/RemediationScripts/Remediate-EnableEncrytionAtHostForVMSS.ps1 b/Scripts/RemediationScripts/Remediate-EnableEncrytionAtHostForVMSS.ps1 index 05f161c4..430d1abf 100644 --- a/Scripts/RemediationScripts/Remediate-EnableEncrytionAtHostForVMSS.ps1 +++ b/Scripts/RemediationScripts/Remediate-EnableEncrytionAtHostForVMSS.ps1 @@ -76,6 +76,15 @@ function Pre_requisites { else { Write-Host "Az.Security module is available." -ForegroundColor Green } + + # Checking if 'Az.Compute' module is available or not. + if ($availableModules.Name -notcontains 'Az.Compute') { + Write-Host "Installing module Az.Compute..." -ForegroundColor Yellow + Install-Module -Name Az.Compute -Scope CurrentUser -Repository 'PSGallery' + } + else { + Write-Host "Az.Compute module is available." -ForegroundColor Green + } } function Fetch-API {