Skip to content

Commit

Permalink
[Optimization engine] Improve Storage Account access and interactive …
Browse files Browse the repository at this point in the history
…scripts security (microsoft#991)

Co-authored-by: Helder Pinto <helder.pinto@microsoft.com>
Co-authored-by: Michael Flanakin <flanakin@users.noreply.github.com>
  • Loading branch information
3 people authored Sep 26, 2024
1 parent 776cb9c commit 5274e9a
Show file tree
Hide file tree
Showing 51 changed files with 349 additions and 339 deletions.
2 changes: 1 addition & 1 deletion docs/_optimize/optimization-engine/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ Once deployed and after all the initial ingestion and recommendations generation
## 📋 Requirements

* A supported Azure subscription (see the [FAQ](./faq.md))
* A user account with Owner permissions over the chosen subscription, so that the Automation Managed Identity is granted the required privileges over the subscription (Reader) and deployment resource group (Contributor)
* A user account with Owner permissions over the chosen subscription, so that the Automation Managed Identity is granted the required privileges over the subscription (Reader) and deployment resource group (Storage Blob Data Contributor)
* Azure Powershell 9.0.0+
* (Optional, for Identity and RBAC governance) Microsoft.Graph.Authentication and Microsoft.Graph.Identity.DirectoryManagement PowerShell modules (version 2.4.0+)
* (Optional, for Identity and RBAC governance) A user account with at least Privileged Role Administrator permissions over the Microsoft Entra tenant, so that the Managed Identity is granted the required privileges over Microsoft Entra ID (Global Reader)
Expand Down
8 changes: 8 additions & 0 deletions docs/_resources/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,14 @@ Legend:
> 1. Added Azure Advisor cost recommendations.
> 2. Added Unattached disks.
🔍 Optimization engine
{: .fs-5 .fw-500 .mt-4 mb-0 }

> ✏️ Changed:
>
> 1. Replaced storage account key-based authentication with Entra ID authentication for improved security.
>
🖥️ PowerShell
{: .fs-5 .fw-500 .mt-4 mb-0 }

Expand Down
32 changes: 22 additions & 10 deletions src/optimization-engine/Deploy-AzureOptimizationEngine.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -1113,6 +1113,18 @@ if ("Y", "y" -contains $continueInput) {
Write-Host "Enabling Entra ID-only authentication in SQL Database..." -ForegroundColor Green
Enable-AzSqlServerActiveDirectoryOnlyAuthentication -ServerName $sqlServerName -ResourceGroupName $resourceGroupName | Out-Null
}

# Ensuring the Automation Account identity has the necessary permissions to access the Storage Account (needed for partial upgrades)
$sa = Get-AzStorageAccount -ResourceGroupName $resourceGroupName -Name $storageAccountName
$auto = Get-AzAutomationAccount -Name $automationAccountName -ResourceGroupName $resourceGroupName
$spnId = $auto.Identity.PrincipalId
$storageBlobContributorRoleId = "ba92f5b4-2d11-453d-a403-e96b0029c9fe" # Storage Blob Data Contributor role
$roleAssignment = Get-AzRoleAssignment -ObjectId $spnId -Scope $sa.Id -ErrorAction SilentlyContinue
if (-not($roleAssignment) -or -not($roleAssignment.RoleDefinitionId -contains $storageBlobContributorRoleId))
{
Write-Host "Granting Storage Blob Data Contributor role to the Automation Account identity..." -ForegroundColor Green
New-AzRoleAssignment -ObjectId $spnId -RoleDefinitionId $storageBlobContributorRoleId -Scope $sa.Id | Out-Null
}

#region Open SQL Server firewall rule
if (-not($sqlServerName -like "*.database.*"))
Expand Down Expand Up @@ -1153,10 +1165,10 @@ if ("Y", "y" -contains $continueInput) {
try {

$azureSqlDomain = $cloudDetails.SqlDatabaseDnsSuffix.Substring(1)
$dbToken = Get-AzAccessToken -ResourceUrl "https://$azureSqlDomain/"
$dbToken = (Get-AzAccessToken -ResourceUrl "https://$azureSqlDomain/" -AsSecureString).Token | ConvertFrom-SecureString -AsPlainText

$Conn = New-Object System.Data.SqlClient.SqlConnection("Server=tcp:$sqlServerEndpoint,1433;Database=$databaseName;Encrypt=True;Connection Timeout=$SqlTimeout;")
$Conn.AccessToken = $dbToken.Token
$Conn.AccessToken = $dbToken
$Conn.Open()

$createTableQuery = Get-Content -Path "./model/loganalyticsingestcontrol-table.sql"
Expand All @@ -1168,7 +1180,7 @@ if ("Y", "y" -contains $continueInput) {
$Conn.Close()

$Conn = New-Object System.Data.SqlClient.SqlConnection("Server=tcp:$sqlServerEndpoint,1433;Database=$databaseName;Encrypt=True;Connection Timeout=$SqlTimeout;")
$Conn.AccessToken = $dbToken.Token
$Conn.AccessToken = $dbToken
$Conn.Open()

$initTableQuery = Get-Content -Path "./model/loganalyticsingestcontrol-initialize.sql"
Expand All @@ -1180,7 +1192,7 @@ if ("Y", "y" -contains $continueInput) {
$Conn.Close()

$Conn = New-Object System.Data.SqlClient.SqlConnection("Server=tcp:$sqlServerEndpoint,1433;Database=$databaseName;Encrypt=True;Connection Timeout=$SqlTimeout;")
$Conn.AccessToken = $dbToken.Token
$Conn.AccessToken = $dbToken
$Conn.Open()

$upgradeTableQuery = Get-Content -Path "./model/loganalyticsingestcontrol-upgrade.sql"
Expand All @@ -1192,7 +1204,7 @@ if ("Y", "y" -contains $continueInput) {
$Conn.Close()

$Conn = New-Object System.Data.SqlClient.SqlConnection("Server=tcp:$sqlServerEndpoint,1433;Database=$databaseName;Encrypt=True;Connection Timeout=$SqlTimeout;")
$Conn.AccessToken = $dbToken.Token
$Conn.AccessToken = $dbToken
$Conn.Open()

$createTableQuery = Get-Content -Path "./model/sqlserveringestcontrol-table.sql"
Expand All @@ -1204,7 +1216,7 @@ if ("Y", "y" -contains $continueInput) {
$Conn.Close()

$Conn = New-Object System.Data.SqlClient.SqlConnection("Server=tcp:$sqlServerEndpoint,1433;Database=$databaseName;Encrypt=True;Connection Timeout=$SqlTimeout;")
$Conn.AccessToken = $dbToken.Token
$Conn.AccessToken = $dbToken
$Conn.Open()

$initTableQuery = Get-Content -Path "./model/sqlserveringestcontrol-initialize.sql"
Expand All @@ -1216,7 +1228,7 @@ if ("Y", "y" -contains $continueInput) {
$Conn.Close()

$Conn = New-Object System.Data.SqlClient.SqlConnection("Server=tcp:$sqlServerEndpoint,1433;Database=$databaseName;Encrypt=True;Connection Timeout=$SqlTimeout;")
$Conn.AccessToken = $dbToken.Token
$Conn.AccessToken = $dbToken
$Conn.Open()

$createTableQuery = Get-Content -Path "./model/recommendations-table.sql"
Expand All @@ -1228,7 +1240,7 @@ if ("Y", "y" -contains $continueInput) {
$Conn.Close()

$Conn = New-Object System.Data.SqlClient.SqlConnection("Server=tcp:$sqlServerEndpoint,1433;Database=$databaseName;Encrypt=True;Connection Timeout=$SqlTimeout;")
$Conn.AccessToken = $dbToken.Token
$Conn.AccessToken = $dbToken
$Conn.Open()

$createTableQuery = Get-Content -Path "./model/recommendations-sp.sql"
Expand All @@ -1240,7 +1252,7 @@ if ("Y", "y" -contains $continueInput) {
$Conn.Close()

$Conn = New-Object System.Data.SqlClient.SqlConnection("Server=tcp:$sqlServerEndpoint,1433;Database=$databaseName;Encrypt=True;Connection Timeout=$SqlTimeout;")
$Conn.AccessToken = $dbToken.Token
$Conn.AccessToken = $dbToken
$Conn.Open()

$createTableQuery = Get-Content -Path "./model/filters-table.sql"
Expand All @@ -1252,7 +1264,7 @@ if ("Y", "y" -contains $continueInput) {
$Conn.Close()

$Conn = New-Object System.Data.SqlClient.SqlConnection("Server=tcp:$sqlServerEndpoint,1433;Database=$databaseName;Encrypt=True;Connection Timeout=$SqlTimeout;")
$Conn.AccessToken = $dbToken.Token
$Conn.AccessToken = $dbToken
$Conn.Open()

$createUserQuery = (Get-Content -Path "./model/automation-user.sql").Replace("<automation-account-name>", $automationAccountName)
Expand Down
8 changes: 4 additions & 4 deletions src/optimization-engine/Suppress-Recommendation.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -114,9 +114,9 @@ $connectionSuccess = $false
do {
$tries++
try {
$dbToken = Get-AzAccessToken -ResourceUrl "https://$azureSqlDomain/"
$dbToken = Get-AzAccessToken -ResourceUrl "https://$azureSqlDomain/" -AsSecureString
$Conn = New-Object System.Data.SqlClient.SqlConnection("Server=tcp:$databaseServer,1433;Database=$databaseName;Encrypt=True;Connection Timeout=$SqlTimeout;")
$Conn.AccessToken = $dbToken.Token
$Conn.AccessToken = $dbToken.Token | ConvertFrom-SecureString -AsPlainText
$Conn.Open()
$Cmd=new-object system.Data.SqlClient.SqlCommand
$Cmd.Connection = $Conn
Expand Down Expand Up @@ -261,9 +261,9 @@ if ("Y", "y" -contains $continueInput)

$sqlStatement = "INSERT INTO [$suppressionsTable] VALUES (NEWID(), '$($controlRows.RecommendationSubTypeId)', '$suppressionType', $scope, GETDATE(), $endDate, '$author', '$notes', 1)"

$dbToken = Get-AzAccessToken -ResourceUrl "https://$azureSqlDomain/"
$dbToken = Get-AzAccessToken -ResourceUrl "https://$azureSqlDomain/" -AsSecureString
$Conn2 = New-Object System.Data.SqlClient.SqlConnection("Server=tcp:$databaseServer,1433;Database=$databaseName;Encrypt=True;Connection Timeout=$SqlTimeout;")
$Conn2.AccessToken = $dbToken.Token
$Conn2.AccessToken = $dbToken.Token | ConvertFrom-SecureString -AsPlainText
$Conn2.Open()

$Cmd=new-object system.Data.SqlClient.SqlCommand
Expand Down
Loading

0 comments on commit 5274e9a

Please sign in to comment.