Private/Set-AACStorageConfigurationFix.ps1
|
function Set-AACStorageConfigurationFix { <# .SYNOPSIS A copy of a storage account configuration with the automatic PSRule fixes (Get-AACStorageRuleFix, Kind Auto) applied - what -UseSuggestedFix deploys, and the configuration snippet the view suggests. .DESCRIPTION Each fix's Setting is a path in the configuration: allowSharedKeyAccess, networkAcls.defaultAction, blobServices.containers[name=raw].publicAccess. Missing levels are created; a container given only by its name becomes @{ name = ... }. The input configuration is not changed. #> [CmdletBinding()] [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '', Justification = 'Returns a changed copy of a hashtable; nothing outside the process changes.')] [OutputType([System.Collections.Specialized.OrderedDictionary])] param( [Parameter(Mandatory)] [System.Collections.IDictionary] $Configuration, [Parameter(Mandatory)] [AllowEmptyCollection()] [object[]] $Fix ) # A deep copy: hashtables and lists rebuilt, values kept. $copy = { param($Value) if ($Value -is [System.Collections.IDictionary]) { $out = [ordered]@{}; foreach ($key in $Value.Keys) { $out[[string]$key] = & $copy $Value[$key] }; return , $out } if ($Value -is [System.Collections.IList] -and $Value -isnot [string]) { return , @(foreach ($item in $Value) { & $copy $item }) } $Value } $result = & $copy $Configuration foreach ($item in @($Fix | Where-Object { $_.Kind -eq 'Auto' -and $_.Setting })) { $parts = @([regex]::Matches($item.Setting, '[^.\[\]]+(\[name=[^\]]+\])?') | ForEach-Object { $_.Value }) $node = $result for ($i = 0; $i -lt $parts.Count; $i++) { $part = $parts[$i] $last = $i -eq $parts.Count - 1 if ($part -match '^(?<key>[^\[]+)\[name=(?<name>[^\]]+)\]$') { # An item of a list, by its name (a string item becomes a hashtable). $key = $Matches['key']; $name = $Matches['name'] $list = @(if ($node.Contains($key)) { $node[$key] }) $index = -1 for ($j = 0; $j -lt $list.Count; $j++) { $entryName = if ($list[$j] -is [System.Collections.IDictionary]) { [string]$list[$j]['name'] } else { [string]$list[$j] } if ($entryName -eq $name) { $index = $j; break } } if ($index -lt 0) { $list += [ordered]@{ name = $name }; $index = $list.Count - 1 } if ($list[$index] -isnot [System.Collections.IDictionary]) { $list[$index] = [ordered]@{ name = [string]$list[$index] } } $node[$key] = $list $node = $list[$index] continue } if ($last) { $node[$part] = $item.Value; break } if ($node[$part] -isnot [System.Collections.IDictionary]) { # blobServices given replaces AVM's default blob settings whole: # start from them, so one fix doesn't drop the others. $node[$part] = if ($i -eq 0 -and $part -eq 'blobServices') { [ordered]@{ containerDeleteRetentionPolicyEnabled = $true; containerDeleteRetentionPolicyDays = 7; deleteRetentionPolicyEnabled = $true; deleteRetentionPolicyDays = 6 } } else { [ordered]@{} } } $node = $node[$part] } } $result } |