Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Included the change to auto remediate the Redis Cache BRS #255

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
223 changes: 179 additions & 44 deletions Scripts/RemediationScripts/Remediate-DisableNonSSLPortOnRedisCache.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -89,15 +89,18 @@ function Setup-Prerequisites
# List of required modules
$requiredModules = @("Az.Accounts", "Az.Resources")

Write-Host "Required modules: $($requiredModules -join ', ')" -ForegroundColor $([Constants]::MessageType.Info)
Write-Host "Checking if the required modules are present..."
Write-Host "Required modules: $($requiredModules -join ', ')"
Write-Host $([Constants]::SingleDashLine)
Write-Host "Checking if the required modules are present..." -ForegroundColor $([Constants]::MessageType.Info)
Write-Host $([Constants]::SingleDashLine)

$availableModules = $(Get-Module -ListAvailable $requiredModules -ErrorAction Stop)

# Check if the required modules are installed.
$requiredModules | ForEach-Object {
if ($availableModules.Name -notcontains $_)
{
Write-Host "$($_) module is not present." -ForegroundColor $([Constants]::MessageType.Warning)
Write-Host "Installing [$($_)] module..." -ForegroundColor $([Constants]::MessageType.Info)
Install-Module -Name $_ -Scope CurrentUser -Repository 'PSGallery' -ErrorAction Stop
Write-Host "[$($_)] module is installed." -ForegroundColor $([Constants]::MessageType.Update)
Expand All @@ -107,6 +110,7 @@ function Setup-Prerequisites
Write-Host "[$($_)] module is present." -ForegroundColor $([Constants]::MessageType.Update)
}
}
Write-Host $([Constants]::SingleDashLine)
}


Expand Down Expand Up @@ -175,62 +179,128 @@ function Disable-NonSSLPortOnRedisCache

[String]
[Parameter(ParameterSetName = "WetRun", HelpMessage="Specifies the path to the file to be used as input for the remediation")]
$FilePath
$FilePath,

[String]
[Parameter(ParameterSetName = "WetRun", HelpMessage="Specifies the path to the file to be used as input for the remediation when AutoRemediation switch is used")]
$Path,

[Switch]
[Parameter(ParameterSetName = "WetRun", HelpMessage="Specifies script is run as a subroutine of AutoRemediation Script")]
$AutoRemediation,

[String]
[Parameter(ParameterSetName = "WetRun", HelpMessage="Specifies the time of creation of file to be used for logging remediation details when AutoRemediation switch is used")]
$TimeStamp
)

Write-Host $([Constants]::DoubleDashLine)
Write-Host $([Constants]::DoubleDashLine)
Write-Host "[Step 1 of 4] Prepare to disable NON SSL port for Redis Cache in Subscription: [$($SubscriptionId)]"
Write-Host $([Constants]::SingleDashLine)

if ($PerformPreReqCheck)
{
try
{
Write-Host "[Step 1 of 4] Validating and installing the modules required to run the script and validating the user..."
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't this was better way for describing this step?

Write-Host $([Constants]::SingleDashLine)
Write-Host "Setting up prerequisites..."
Write-Host "Setting up prerequisites..." -ForegroundColor $([Constants]::MessageType.Info)
Write-Host $([Constants]::SingleDashLine)
Setup-Prerequisites
Write-Host "Completed setting up prerequisites." -ForegroundColor $([Constants]::MessageType.Update)
Write-Host $([Constants]::SingleDashLine)
}
catch
{
Write-Host "Error occurred while setting up prerequisites. Error: $($_)" -ForegroundColor $([Constants]::MessageType.Error)
break
return
}
}
else
{
Write-Host "[Step 1 of 4] Validating the user... "
}

# Connect to Azure account
$context = Get-AzContext

if ([String]::IsNullOrWhiteSpace($context))
{
Write-Host $([Constants]::SingleDashLine)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why removed these lines?

Write-Host "Connecting to Azure account..."
Connect-AzAccount -Subscription $SubscriptionId -ErrorAction Stop | Out-Null
Write-Host "Connected to Azure account." -ForegroundColor $([Constants]::MessageType.Update)
Write-Host "No active Azure login session found. Exiting..." -ForegroundColor $([Constants]::MessageType.Error)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we also tell the user what action to perform in this case?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey Vamsee, tried to add msg as ' please try to reconnect your azure account as 'connect-az account' with subs id.
pls help to have a look

return
}

# Setting up context for the current Subscription.
$context = Set-AzContext -SubscriptionId $SubscriptionId -ErrorAction Stop

Write-Host $([Constants]::SingleDashLine)
Write-Host "Subscription Name: [$($context.Subscription.Name)]"
Write-Host "Subscription ID: [$($context.Subscription.SubscriptionId)]"
Write-Host "Account Name: [$($context.Account.Id)]"
Write-Host "Account Type: [$($context.Account.Type)]"
Write-Host $([Constants]::SingleDashLine)
if(-not($AutoRemediation))
{
Write-Host $([Constants]::SingleDashLine)
Write-Host "Subscription Name: [$($context.Subscription.Name)]"
Write-Host "Subscription ID: [$($context.Subscription.SubscriptionId)]"
Write-Host "Account Name: [$($context.Account.Id)]"
Write-Host "Account Type: [$($context.Account.Type)]"
Write-Host $([Constants]::SingleDashLine)
}


Write-Host "*** To Disable Non-SSL port on Redis Cache in a Subscription, Contributor or higher privileges on the Redis Cache are required.***" -ForegroundColor $([Constants]::MessageType.Info)

Write-Host $([Constants]::DoubleDashLine)
Write-Host "[Step 2 of 4] Preparing to fetch all Redis Cache(s)..."
Write-Host "To Disable Non-SSL port on Redis Cache in a Subscription, Contributor or higher privileges on the Redis Cache are required." -ForegroundColor $([Constants]::MessageType.Warning)
Write-Host $([Constants]::SingleDashLine)
Write-Host "[Step 2 of 4] Fetch all Redis Cache(s)"
Write-Host $([Constants]::SingleDashLine)

# list to store Container details.
$RedisCacheDetails = @()

# No file path provided as input to the script. Fetch all Redis Cache(s) in the Subscription.
# To keep track of remediated and skipped resources
$logRemediatedResources = @()
$logSkippedResources=@()

# Control Id
$controlIds = "Azure_RedisCache_DP_Use_SSL_Port"

if($AutoRemediation)
{
if (-not (Test-Path -Path $Path))
{
Write-Host "File containing failing controls details [$($Path)] not found. Skipping remediation..." -ForegroundColor $([Constants]::MessageType.Error)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What action user has to take in this case? Can we guide the user better?

Especially in auto remediation, last option which user should have is to reach out to us.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added the msg to verify if path is correct and failed control are placed on the same path

Write-Host $([Constants]::SingleDashLine)
return
}

Write-Host "Fetching all Redis Cache for the [$($controlIds)] control from [$($Path)]..." -ForegroundColor $([Constants]::MessageType.Info)
Write-Host $([Constants]::SingleDashLine)
$controlForRemediation = Get-content -path $Path | ConvertFrom-Json
$controls = $controlForRemediation.ControlRemediationList
$resourceDetails = $controls | Where-Object { $controlIds -eq $_.ControlId };
$validResources = $resourceDetails.FailedResourceList | Where-Object {![String]::IsNullOrWhiteSpace($_.ResourceId)}
if(($resourceDetails | Measure-Object).Count -eq 0 -or ($validResources | Measure-Object).Count -eq 0)
{
Write-Host "No Redis Cache(s) found in input json file for remediation." -ForegroundColor $([Constants]::MessageType.Error)
Write-Host $([Constants]::SingleDashLine)
return
}
$validResources | ForEach-Object {
$resourceId = $_.ResourceId
try
{
$RedisCacheResource = Get-AzRedisCache -ResourceGroupName $_.ResourceGroupName -Name $_.ResourceName -ErrorAction SilentlyContinue
$RedisCacheDetails += $RedisCacheResource | Select-Object @{N='ResourceId';E={$_.Id}},
@{N='ResourceGroupName';E={$_.ResourceGroupName}},
@{N='ResourceName';E={$_.Name}},
@{N='Enable_Non_SSLPort';E={$_.EnableNonSslPort}}
}
catch
{
Write-Host "Valid resource id(s) not found in input json file. Error: [$($_)]" -ForegroundColor $([Constants]::MessageType.Error)
Write-Host "Skipping the Resource: [$($_.ResourceName)]..."
$logResource = @{}
$logResource.Add("ResourceGroupName",($_.ResourceGroupName))
$logResource.Add("ResourceName",($_.ResourceName))
$logResource.Add("Reason","Valid resource id(s) not found in input json file.")
$logSkippedResources += $logResource
Write-Host $([Constants]::SingleDashLine)
}
}
}

else
{
# No file path provided as input to the script. Fetch all Redis Cache(s) in the Subscription.
if ([String]::IsNullOrWhiteSpace($FilePath))
{
Write-Host "Fetching all Redis Cache(s) in Subscription: $($context.Subscription.SubscriptionId)" -ForegroundColor $([Constants]::MessageType.Info)
Expand Down Expand Up @@ -276,16 +346,18 @@ function Disable-NonSSLPortOnRedisCache
}
}

}


$totalRedisCache = ($RedisCacheDetails| Measure-Object).Count

if ($totalRedisCache -eq 0)
{
Write-Host "No Redis Cache(s) found. Exiting..." -ForegroundColor $([Constants]::MessageType.Warning)
break
Write-Host "No Redis Cache(s) found. Exiting..." -ForegroundColor $([Constants]::MessageType.Update)
return
}

Write-Host "Found [$($totalRedisCache)] Redis Cache(s)." -ForegroundColor $([Constants]::MessageType.Update)

Write-Host "Found [$($totalRedisCache)] Redis Cache(s)." -ForegroundColor $([Constants]::MessageType.Update)
Write-Host $([Constants]::SingleDashLine)

# list for storing Redis Cache(s) for which Non-SSL port is enabled.
Expand All @@ -306,10 +378,13 @@ function Disable-NonSSLPortOnRedisCache
if ($totalRedisCacheWithNonSSLPortEnabled -eq 0)
{
Write-Host "No Redis Cache(s) found with Non-SSL port enabled.. Exiting..." -ForegroundColor $([Constants]::MessageType.Warning)
break
return
}

Write-Host "Found [$($totalRedisCacheWithNonSSLPortEnabled)] Redis Cache(s) for which Non-SSL port is enabled." -ForegroundColor $([Constants]::MessageType.Update)
Write-Host $([Constants]::SingleDashLine)



$colsProperty = @{Expression={$_.ResourceName};Label="ResourceName";Width=30;Alignment="left"},
@{Expression={$_.ResourceGroupName};Label="ResourceGroupName";Width=30;Alignment="left"},
Expand Down Expand Up @@ -388,46 +463,106 @@ function Disable-NonSSLPortOnRedisCache
if($RedisCacheResource.EnableNonSslPort -eq $false)
{
$RedisCacheRemediated += $RedisCache
$logResource = @{}
$logResource.Add("ResourceGroupName",($_.ResourceGroupName))
$logResource.Add("ResourceName",($_.ResourceName))
$logRemediatedResources += $logResource
}
else
{
$RedisCacheSkipped += $RedisCache
$logResource = @{}
$logResource.Add("ResourceGroupName",($_.ResourceGroupName))
$logResource.Add("ResourceName",($_.ResourceName))
$logResource.Add("Reason", "Error disabling Non-SSL port on Redis Cache(s): [$($RedisCache)]")
$logSkippedResources += $logResource
}
}
catch
{
$RedisCacheSkipped += $RedisCache
$logResource = @{}
$logResource.Add("ResourceGroupName",($_.ResourceGroupName))
$logResource.Add("ResourceName",($_.ResourceName))
$logResource.Add("Reason","Encountered error while disabling Non-SSL port on Redis Cache(s) configuration")
$logSkippedResources += $logResource
Write-Host "Skipping this resource..." -ForegroundColor $([Constants]::MessageType.Warning)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the user action needed in this case?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this will require some research as this is on the control level and how it failed.

}
}

Write-Host $([Constants]::DoubleDashLine)
Write-Host "Remediation Summary:`n" -ForegroundColor $([Constants]::MessageType.Info)


if($AutoRemediation)
{

if ($($RedisCacheRemediated | Measure-Object).Count -gt 0)
{
Write-Host "Non-SSL port is disabled on the following Redis Cache(s) in the subscription:" -ForegroundColor $([Constants]::MessageType.Update)

$RedisCacheRemediated | Format-Table -Property $colsProperty -Wrap

$RedisCacheRemediated | Format-Table -Property $colsProperty -Wrap
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not needed when autoremediation feature is in use


# Write this to a file.
$RedisCacheRemediatedFile = "$($backupFolderPath)\RemediatedRedisCache.csv"
$RedisCacheRemediated | Export-CSV -Path $RedisCacheRemediatedFile -NoTypeInformation

Write-Host "This information has been saved to" -NoNewline
Write-Host " [$($RedisCacheRemediatedFile)]" -ForegroundColor $([Constants]::MessageType.Update)
Write-Host "Use this file for any roll back that may be required." -ForegroundColor $([Constants]::MessageType.Info)
Write-Host "This information related to Redis Cache where Non SSL port disbaled has been saved to [$($RedisCacheRemediatedFile)]. Use this file for any roll back that may be required." -ForegroundColor $([Constants]::MessageType.Update)
Write-Host $([Constants]::SingleDashLine)
}

if ($($RedisCacheSkipped | Measure-Object).Count -gt 0)
{
Write-Host "`nError disabling Non-SSL port on the following Redis Cache(s)in the subscription:" -ForegroundColor $([Constants]::MessageType.Error)

$RedisCacheSkipped | Format-Table -Property $colsProperty -Wrap
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to display table when autoremediation feature is in use.


# Write this to a file.
$RedisCacheSkippedFile = "$($backupFolderPath)\SkippedRedisCache.csv"
$RedisCacheSkipped | Export-CSV -Path $RedisCacheSkippedFile -NoTypeInformation
Write-Host "This information has been saved to" -NoNewline
Write-Host " [$($RedisCacheSkippedFile)]" -ForegroundColor $([Constants]::MessageType.Update)
Write-Host "This information related to Redis Cache where Non SSL port disbaled has been saved to [$($RedisCacheSkippedFile)]. Use this file for any roll back that may be required." -ForegroundColor $([Constants]::MessageType.Update)
Write-Host $([Constants]::SingleDashLine)
}

}
else
{
Write-Host "Remediation Summary:`n" -ForegroundColor $([Constants]::MessageType.Info)

if ($($RedisCacheRemediated | Measure-Object).Count -gt 0)
{
Write-Host "Non-SSL port is disabled on the following Redis Cache(s) in the subscription:" -ForegroundColor $([Constants]::MessageType.Update)

$RedisCacheRemediated | Format-Table -Property $colsProperty -Wrap

# Write this to a file.
$RedisCacheRemediatedFile = "$($backupFolderPath)\RemediatedRedisCache.csv"
$RedisCacheRemediated | Export-CSV -Path $RedisCacheRemediatedFile -NoTypeInformation

Write-Host "This information has been saved to" -NoNewline
Write-Host " [$($RedisCacheRemediatedFile)]" -ForegroundColor $([Constants]::MessageType.Update)
Write-Host "Use this file for any roll back that may be required." -ForegroundColor $([Constants]::MessageType.Info)
}

if ($($RedisCacheSkipped | Measure-Object).Count -gt 0)
{
jaiswalricha marked this conversation as resolved.
Show resolved Hide resolved
Write-Host "`nError disabling Non-SSL port on the following Redis Cache(s)in the subscription:" -ForegroundColor $([Constants]::MessageType.Error)
$RedisCacheSkipped | Format-Table -Property $colsProperty -Wrap

# Write this to a file.
$RedisCacheSkippedFile = "$($backupFolderPath)\SkippedRedisCache.csv"
$RedisCacheSkipped | Export-CSV -Path $RedisCacheSkippedFile -NoTypeInformation
Write-Host "This information has been saved to" -NoNewline
Write-Host " [$($RedisCacheSkippedFile)]" -ForegroundColor $([Constants]::MessageType.Update)
}
}
if($AutoRemediation){
$logFile = "LogFiles\"+ $($TimeStamp) + "\log_" + $($SubscriptionId) +".json"
$log = Get-content -Raw -path $logFile | ConvertFrom-Json
foreach($logControl in $log.ControlList){
if($logControl.ControlId -eq $controlIds){
$logControl.RemediatedResources=$logRemediatedResources
$logControl.SkippedResources=$logSkippedResources
$logControl.RollbackFile = $appServicesRemediatedFile
}
}
$log | ConvertTo-json -depth 10 | Out-File $logFile
}
}
else
Expand Down Expand Up @@ -537,7 +672,7 @@ function Enable-NonSSLPortOnRedisCache
Write-Host "Account Type: [$($context.Account.Type)]"
Write-Host $([Constants]::SingleDashLine)

Write-Host "*** To Enable Non-SSL port on Redis Cache in a Subscription, Contributor or higher privileges on the Redis Cache are required.***" -ForegroundColor $([Constants]::MessageType.Info)
Write-Host "To Enable Non-SSL port on Redis Cache in a Subscription, Contributor or higher privileges on the Redis Cache are required." -ForegroundColor $([Constants]::MessageType.Info)

Write-Host $([Constants]::DoubleDashLine)
Write-Host "[Step 2 of 3] Preparing to fetch all Redis Cache(s)..."
Expand Down