Framework/Configurations/ContinuousAssurance/RunbookScanAgent.ps1

#telemetry functions

function CreateHelperSchedule($frequencyInMinutes)
{
    #create next run schedule
    Get-AzureRmAutomationSchedule -AutomationAccountName $AutomationAccountName `
    -ResourceGroupName $AutomationAccountRG -Name $CAHelperScheduleName -ErrorAction SilentlyContinue | Remove-AzureRmAutomationSchedule -Force

    New-AzureRmAutomationSchedule -AutomationAccountName $AutomationAccountName -Name $CAHelperScheduleName `
                    -ResourceGroupName $AutomationAccountRG -StartTime $(get-date).AddMinutes($frequencyInMinutes) `
                    -OneTime -ErrorAction Stop | Out-Null
                
    Register-AzureRmAutomationScheduledRunbook -RunbookName $RunbookName -ScheduleName $CAHelperScheduleName `
                    -ResourceGroupName $AutomationAccountRG `
                    -AutomationAccountName $AutomationAccountName -ErrorAction Stop | Out-Null
}

function ConvertStringToBoolean($strToConvert)
{
    switch($strToConvert)
    {
        "true" {return $true}
        "false" {return $false}
    }
    return $false #adding this to prevent error all path doesn't return value"
}

function GetCAStatus()
{
    Set-AzSDKOMSSettings -OMSWorkspaceID $OMSWorkspaceId -OMSSharedKey $OMSWorkspaceSharedKey -Source "CC"
    
    #set values in azsdksettings.json
    $EnableAADAuthForOnlinePolicyStore = ConvertStringToBoolean($EnableAADAuthForOnlinePolicyStore)
    if($EnableAADAuthForOnlinePolicyStore)
    {
        Set-AzSDKPolicySettings -OnlinePolicyStoreUrl $OnlinePolicyStoreUrl -EnableAADAuthForOnlinePolicyStore
    }
    else
    {
        Set-AzSDKPolicySettings -OnlinePolicyStoreUrl $OnlinePolicyStoreUrl 
    }

    $svtResultPath = [string]::Empty
    $subscriptionResultPath = [string]::Empty
    $parentFolderPath = [string]::Empty

    PublishEvent -EventName "Job Scan Started" `
    -Properties @{"ResourceGroupNames"=$ResourceGroupNames;"OnlinePolicyStoreUrl"=$OnlinePolicyStoreUrl;"OMSWorkspaceId"=$OMSWorkspaceId;`
    "AzureADAppId"=$RunAsConnection.ApplicationId}
    
    "Running command 'Get-AzSDKSubscriptionSecurityStatus'"
    $subscriptionResultPath = Get-AzSDKSubscriptionSecurityStatus -SubscriptionId $SubscriptionID -ExcludeTags "OwnerAccess"

    "Running command 'Get-AzSDKAzureServicesSecurityStatus'"
    if($ResourceGroupNames.Trim() -eq "*")
    {
        #run command on all resources
        $svtResultPath = Get-AzSDKAzureServicesSecurityStatus -SubscriptionId $SubscriptionID -ExcludeTags "OwnerAccess"
    }
    else
    {
        $svtResultPath = Get-AzSDKAzureServicesSecurityStatus -SubscriptionId $SubscriptionID -ResourceGroupNames $ResourceGroupNames -ExcludeTags "OwnerAccess"        
    }
     if([string]::IsNullOrWhiteSpace($subscriptionResultPath))
        {
            "Subscription scan failed."
            PublishEvent -EventName "Scan Error" -Properties @{"ScanEntity"="Subscription"} `
            -Metrics @{"SuccessCount"=0}
        }
        else
        {
            "Subscription scan succeeded."
            $parentFolderPath = (Get-Item $subscriptionResultPath).parent.FullName
            PublishEvent -EventName "Scan Completed" -Properties @{"ScanEntity"="Subscription"} `
            -Metrics @{"SuccessCount"=1}
        }
        if([string]::IsNullOrWhiteSpace($svtResultPath))
        {
            "Azure resources scan failed."
            PublishEvent -EventName "Scan Error" -Properties @{"ScanEntity"="Resources";"ResourceGroupNames"=$ResourceGroupNames} `
            -Metrics @{"SuccessCount"=0}
        }
        else
        {
            "Azure resources scan succeeded."
            $parentFolderPath = (Get-Item $svtResultPath).parent.FullName
            PublishEvent -EventName "Scan Completed" -Properties @{"ScanEntity"="Resources";"ResourceGroupNames"=$ResourceGroupNames} `
            -Metrics @{"SuccessCount"=1}
        }   
    if(![string]::IsNullOrWhiteSpace($subscriptionResultPath) -or ![string]::IsNullOrWhiteSpace($svtResultPath))
    {
        #Check if storage account exists
        try
        {
           Get-AzureRmStorageAccount -ResourceGroupName $StorageAccountRG -Name $StorageAccountName -ErrorAction stop | Out-Null
        }
        catch
        {
            Write-Error -Message $_.Exception
            throw $_.Exception
        }
        
        #Create output files in storage
        $containerName = "azsdkexecutionlogs"
        $archiveFilePath = "$parentFolderPath\AutomationLogs_" + $(Get-Date -format "yyyyMMdd_HHmmss") + ".zip"
        $keys = Get-AzureRmStorageAccountKey -ResourceGroupName $StorageAccountRG -Name $StorageAccountName 
        $currentContext = New-AzureStorageContext -StorageAccountName $StorageAccountName -StorageAccountKey $keys[0].Value -Protocol Https
        try
        {
            Get-AzureStorageContainer -Name $containerName -Context $currentContext -ErrorAction Stop | Out-Null
        }
        catch
        {
            New-AzureStorageContainer -Name $containerName -Context $currentContext | Out-Null
        }
        try
        {
            if(![string]::IsNullOrWhiteSpace($svtResultPath)) 
            { 
                Compress-Archive -Path $svtResultPath -CompressionLevel Optimal -DestinationPath $archiveFilePath -Update
            }
            if(![string]::IsNullOrWhiteSpace($subscriptionResultPath)) 
            { 
                Compress-Archive -Path $subscriptionResultPath -CompressionLevel Optimal -DestinationPath $archiveFilePath -Update
            }
            Set-AzureStorageBlobContent -File $archiveFilePath -Container $containerName -Context $currentContext -ErrorAction Stop | Out-Null
            "Exported reports to storage $StorageAccountName"
            PublishEvent -EventName "Reports Persisted" -Properties @{"SuccessCount"=1}
        }
        catch
        {
            "Could not export reports to storage $StorageAccountName"
            PublishEvent -EventName "Reports Persist Error" -Properties @{"SuccessCount"=0}            
            throw $_.Exception
        }

        #clean-up of logs in automation sandbox
        if(![string]::IsNullOrWhiteSpace($svtResultPath)) 
        {
            Remove-Item -Path $svtResultPath -Recurse -ErrorAction Ignore
        }
        if(![string]::IsNullOrWhiteSpace($subscriptionResultPath)) 
        {
            Remove-Item -Path $subscriptionResultPath -Recurse -ErrorAction Ignore
        }
        if(![string]::IsNullOrWhiteSpace($archiveFilePath)) 
        {
            Remove-Item -Path $archiveFilePath -Recurse -ErrorAction Ignore
        }
    }
}
try
{
#config start
$ResourceGroupNames = Get-AutomationVariable -Name "AppResourceGroupNames" 
$OMSWorkspaceId = Get-AutomationVariable -Name "OMSWorkspaceId" 
$OMSWorkspaceSharedKey = Get-AutomationVariable -Name "OMSSharedKey" 
$StorageAccountName =  Get-AutomationVariable -Name "ReportsStorageAccountName"
$AzSDKModuleName = "AzSDKStaging"
$StorageAccountRG = "AzSDKRG"
$RunbookName = "Continuous_Assurance_Runbook"
$CAHelperScheduleName = "CA_Helper_Schedule"
#config end

#Set subscription id
$SubscriptionID = $RunAsConnection.SubscriptionID

$isAzSDKAvailable = (Get-AzureRmAutomationModule -ResourceGroupName $AutomationAccountRG `
-AutomationAccountName $AutomationAccountName `
-Name $AzSDKModuleName -ErrorAction SilentlyContinue | `
Where-Object {$_.ProvisioningState -eq "Succeeded" -or $_.ProvisioningState -eq "Created"} | `
Measure-Object).Count -gt 0

if($isAzSDKAvailable)
{
    Import-Module $AzSDKModuleName
}

#check if AzureRM is available (for scenario where AzSDK is available but AzureRM extraction might have failed)
$isAzureRMAvailable = (Get-AzureRmAutomationModule -ResourceGroupName $AutomationAccountRG `
-AutomationAccountName $AutomationAccountName `
-Name AzureRM -ErrorAction SilentlyContinue | `
Where-Object {$_.ProvisioningState -eq "Succeeded" -or $_.ProvisioningState -eq "Created"} | `
Measure-Object).Count -gt 0

#return if modules are not ready
if((Get-Command -Name "Get-AzSDKAzureServicesSecurityStatus" -ErrorAction SilentlyContinue|Measure-Object).Count -eq 0 -or !$isAzureRMAvailable)
{
    return;
}

#scan and save results to storage
GetCAStatus

#helper schedule not needed anymore
Remove-AzureRmAutomationSchedule -Name $CAHelperScheduleName -ResourceGroupName $AutomationAccountRG -AutomationAccountName $AutomationAccountName -Force
PublishEvent -EventName "Job Completed" -Properties @{"SubscriptionId"=$RunAsConnection.SubscriptionID} -Metrics @{"TimeTakenInMs" = $timer.ElapsedMilliseconds;"SuccessCount" = 1}
}
catch
{
PublishEvent -EventName "Job Error" -Properties @{"ErrorRecord"= $_.Exception.InnerException.ErrorRecord} -Metrics @{"TimeTakenInMs" = $timer.ElapsedMilliseconds;"SuccessCount" = 0}
}