Framework/Managers/ControlBaselineManager.ps1
Set-StrictMode -Version Latest class ControlBaselineManager { hidden [PSObject] $AzSDKResourceGroup = $null; hidden [PSObject] $AzSDKStorageAccount = $null; hidden [PSObject] $AzSDKStorageResourceBaselineContainer = $null; hidden [int] $HasWritePermissions = -1; hidden [string] $BaselineResourceBlobName = "BaselineResourceBlob.json" hidden [string] $BaselineContainerName = [Constants]::BaselineContainerName hidden [BaselineResourceMap] $BaselineControlObj = $null [PSObject] $ControlSettings; hidden [ActiveStatus] $ActiveStatus = [ActiveStatus]::NotStarted; hidden static [ControlBaselineManager] $Instance = $null; static [ControlBaselineManager] GetInstance() { if ( $null -eq [ControlBaselineManager]::Instance) { [ControlBaselineManager]::Instance = [ControlBaselineManager]::new(); } return [ControlBaselineManager]::Instance } ControlBaselineManager() { $this.ControlSettings = [ConfigurationManager]::LoadServerConfigFile("ControlSettings.json"); #$this.GetAzSDKControlBaselineContainer() } hidden [bool] HasControlBaselineStatusWritePermissions() { $hasPermissions = $false; return $hasPermissions; } hidden [void] GetAzSDKControlBaselineContainer() { if($null -eq $this.AzSDKStorageAccount) { $this.GetAzSDKStorageAccount() } if($null -eq $this.AzSDKStorageAccount) { return; } try { #Able to read the container then read permissions are good $containerObject = Get-AzureStorageContainer -Context $this.AzSDKStorageAccount.Context -Name $this.BaselineContainerName -ErrorAction Stop $this.AzSDKStorageResourceBaselineContainer = $containerObject; } catch { try { New-AzureStorageContainer -Context $this.AzSDKStorageAccount.Context -Name $this.BaselineContainerName -ErrorAction SilentlyContinue $containerObject = Get-AzureStorageContainer -Context $this.AzSDKStorageAccount.Context -Name $this.BaselineContainerName -ErrorAction SilentlyContinue $this.AzSDKStorageResourceBaselineContainer = $containerObject; } catch { #Do nothing } } } hidden [void] GetAzSDKStorageAccount() { if($null -eq $this.AzSDKResourceGroup) { $this.GetAzSDKRG(); } if($null -ne $this.AzSDKResourceGroup) { $StorageAccount = Get-AzureRmStorageAccount -ResourceGroupName $this.AzSDKResourceGroup.ResourceGroupName | Where-Object {$_.StorageAccountName -like 'azsdk*'} -ErrorAction SilentlyContinue #if no storage account found then it assumes that there is no control state feature is not used and if there are more than one storage account found it assumes the same $this.AzSDKStorageAccount = $StorageAccount; } } hidden [PSObject] GetAzSDKRG() { $azSDKConfigData = [ConfigurationManager]::GetAzSdkConfigData() $resourceGroup = Get-AzureRmResourceGroup -Name $azSDKConfigData.AzSDKRGName -ErrorAction SilentlyContinue $this.AzSDKResourceGroup = $resourceGroup return $resourceGroup; } [void] UpdateResourceStatus([string] $resourceId, [ScanState] $state) { $resourceValues = @(); $this.GetBaselineControlObject(); if($this.IsListAvailableAndActive()) { #$idHash = [Helpers]::ComputeHash($resourceId) $resourceValue = $this.BaselineControlObj.ResourceMapTable | Where-Object { $_.Id -eq $resourceId}; if($null -ne $resourceValue) { $resourceValue.ModifiedDate = [DateTime]::UtcNow; $resourceValue.State = $state; #$this.BaselineControlObj.ResourceMapTable[$idHash] = $resourceValue; } else { $resourceValue = [BaselineResource]@{ Id = $resourceId; State = $state; CreatedDate = [DateTime]::UtcNow; ModifiedDate = [DateTime]::UtcNow; } $this.BaselineControlObj.ResourceMapTable +=$resourceValue; } $this.PersistStorageBlob(); } } [void] RemoveControlBaseline() { if($null -ne $this.BaselineControlObj) { $AzSDKTemp = [Constants]::AzSdkAppFolderPath + "\TempState"; if(-not (Test-Path "$AzSDKTemp\ControlsBaseline")) { mkdir -Path "$AzSDKTemp\ControlsBaseline" -ErrorAction Stop | Out-Null } $masterFilePath = "$AzSDKTemp\ControlsBaseline\$($this.BaselineResourceBlobName)" $controlStateBlob = Get-AzureStorageBlob -Container $this.BaselineContainerName -Context $this.AzSDKStorageAccount.Context -Blob "$($this.BaselineResourceBlobName)" -ErrorAction SilentlyContinue if($null -ne $controlStateBlob) { Get-AzureStorageBlobContent -CloudBlob $controlStateBlob.ICloudBlob -Context $this.AzSDKStorageAccount.Context -Destination $masterFilePath -Force $baselineResources = Get-ChildItem -Path $masterFilePath -Force | Get-Content | ConvertFrom-Json if($baselineResources -ne $null -and ($baselineResources.ResourceMapTable | Measure-Object).Count -gt 0 -and ($baselineResources.ResourceMapTable | Where-Object { $_.State -ne "COMP" } | Measure-Object).Count -eq 0) { $this.ArchiveBlob("_End_"); Remove-AzureStorageBlob -CloudBlob $controlStateBlob.ICloudBlob -Force -Context $this.AzSDKStorageAccount.Context } } $this.BaselineControlObj = $null } } [void] CreateResourceMasterList([PSObject] $resourceIds) { if(($resourceIds | Measure-Object).Count -gt 0) { $resourceIdMap = @(); $resourceIds | ForEach-Object { $resourceId = $_; #$hashId = [Helpers]::ComputeHash($resourceId); $resourceValue = [BaselineResource]@{ Id = $resourceId; State = [ScanState]::INIT CreatedDate = [DateTime]::UtcNow; ModifiedDate = [DateTime]::UtcNow; } #$resourceIdMap.Add($hashId,$resourceValue); $resourceIdMap +=$resourceValue } $masterControlBlob = [BaselineResourceMap]@{ Id = [DateTime]::UtcNow.ToString("yyyyMMdd_HHmmss"); CreatedDate = [DateTime]::UtcNow; ResourceMapTable = $resourceIdMap; } $this.BaselineControlObj = $masterControlBlob; $this.PersistStorageBlob(); $this.ActiveStatus = [ActiveStatus]::Yes; } } [void] PersistStorageBlob() { $this.GetBaselineControlObject(); if($null -ne $this.BaselineControlObj) { $AzSDKTemp = [Constants]::AzSdkAppFolderPath + "\TempState"; if(-not (Test-Path "$AzSDKTemp\ControlsBaseline")) { mkdir -Path "$AzSDKTemp\ControlsBaseline" -ErrorAction Stop | Out-Null } $masterFilePath = "$AzSDKTemp\ControlsBaseline\$($this.BaselineResourceBlobName)" [Helpers]::ConvertToJsonCustom($this.BaselineControlObj) | Out-File $masterFilePath -Force Set-AzureStorageBlobContent -File $masterFilePath -Container $this.BaselineContainerName -BlobType Block -Context $this.AzSDKStorageAccount.Context -Force } } hidden [void] ArchiveBlob() { $this.ArchiveBlob("_"); } hidden [void] ArchiveBlob([string] $token) { try { $AzSDKTemp = [Constants]::AzSdkAppFolderPath + "\TempState"; if(-not (Test-Path "$AzSDKTemp\ControlsBaseline")) { mkdir -Path "$AzSDKTemp\ControlsBaseline" -ErrorAction Stop | Out-Null } $archiveName = $this.BaselineContainerName + $token + (Get-Date).ToUniversalTime().ToString("yyyyMMddHHmmss") + ".json"; $masterFilePath = "$AzSDKTemp\ControlsBaseline\$archiveName" $controlStateBlob = Get-AzureStorageBlob -Container $this.BaselineContainerName -Context $this.AzSDKStorageAccount.Context -Blob "$($this.BaselineResourceBlobName)" -ErrorAction SilentlyContinue if($null -ne $controlStateBlob) { Get-AzureStorageBlobContent -CloudBlob $controlStateBlob.ICloudBlob -Context $this.AzSDKStorageAccount.Context -Destination $masterFilePath -Force Set-AzureStorageBlobContent -File $masterFilePath -Container $this.BaselineContainerName -Blob "Archive/$archiveName" -BlobType Block -Context $this.AzSDKStorageAccount.Context -Force } } catch { #eat exception as archive should not impact actual flow } } hidden [void] GetBaselineControlObject() { if($null -eq $this.BaselineControlObj) { $AzSDKTemp = [Constants]::AzSdkAppFolderPath + "\TempState"; if(-not (Test-Path "$AzSDKTemp\ControlsBaseline")) { mkdir -Path "$AzSDKTemp\ControlsBaseline" -ErrorAction Stop | Out-Null } $masterFilePath = "$AzSDKTemp\ControlsBaseline\$($this.BaselineResourceBlobName)" $controlStateBlob = Get-AzureStorageBlob -Container $this.BaselineContainerName -Context $this.AzSDKStorageAccount.Context -Blob "$($this.BaselineResourceBlobName)" -ErrorAction SilentlyContinue if($null -ne $controlStateBlob) { Get-AzureStorageBlobContent -CloudBlob $controlStateBlob.ICloudBlob -Context $this.AzSDKStorageAccount.Context -Destination $masterFilePath -Force $this.BaselineControlObj = Get-ChildItem -Path $masterFilePath -Force | Get-Content | ConvertFrom-Json } } } [ActiveStatus] IsMasterListActive() { if($null -eq $this.AzSDKStorageAccount -or $null -eq $this.AzSDKStorageResourceBaselineContainer ) { $this.GetAzSDKControlBaselineContainer(); } if($null -ne $this.ControlSettings.BaselineControls) { $this.GetBaselineControlObject(); $expiryInDays = [Int32]::Parse($this.ControlSettings.BaselineControls.ExpiryInDays); if($null -eq $this.BaselineControlObj) { return $this.ActiveStatus = [ActiveStatus]::No; } if($this.BaselineControlObj.CreatedDate.AddDays($expiryInDays) -lt [DateTime]::UtcNow) { $this.RemoveControlBaseline(); return $this.ActiveStatus = [ActiveStatus]::No; } return $this.ActiveStatus = [ActiveStatus]::Yes } else { return $this.ActiveStatus = [ActiveStatus]::No; } } [PSObject] GetResourceStatus([string] $resourceId) { $resourceValues = @(); $this.GetBaselineControlObject(); if($this.IsListAvailableAndActive()) { $idHash = [Helpers]::ComputeHash($resourceId) $resourceValue = $this.BaselineControlObj.ResourceMapTable[$idHash]; $resourceValues += $resourceValue; return $resourceValues; } return $null; } [PSObject] GetNonScannedResources() { $nonScannedResources = @(); $this.GetBaselineControlObject(); if($this.IsListAvailableAndActive()) { $nonScannedResources +=[BaselineResource[]] $this.BaselineControlObj.ResourceMapTable | Where-Object {$_.State -eq [ScanState]::INIT} return $nonScannedResources; } return $null; } [PSObject] GetAllListedResources() { $nonScannedResources = @(); $this.ArchiveBlob() $this.GetBaselineControlObject(); if($this.IsListAvailableAndActive()) { $nonScannedResources += $this.BaselineControlObj.ResourceMapTable return $nonScannedResources; } return $null; } [Bool] IsListAvailableAndActive() { if($null -ne $this.BaselineControlObj -and $this.ActiveStatus -eq [ActiveStatus]::Yes -and $null -ne $this.BaselineControlObj.ResourceMapTable) { return $true } else { return $false } } [PSObject] GetBaselineControlDetails() { return $this.ControlSettings.BaselineControls } } |