Framework/Listeners/UserReports/WriteSummaryFile.ps1

Set-StrictMode -Version Latest 
class WriteSummaryFile: FileOutputBase
{   
    hidden static [WriteSummaryFile] $Instance = $null;

    static [WriteSummaryFile] GetInstance()
    {
        if ( $null -eq  [WriteSummaryFile]::Instance)
        {
            [WriteSummaryFile]::Instance = [WriteSummaryFile]::new();
        }
    
        return [WriteSummaryFile]::Instance
    }

    [void] RegisterEvents()
    {
        $this.UnregisterEvents();       

        $this.RegisterEvent([AzSdkRootEvent]::GenerateRunIdentifier, {
            $currentInstance = [WriteSummaryFile]::GetInstance();
            try 
            {
                $currentInstance.SetRunIdentifier([AzSdkRootEventArgument] ($Event.SourceArgs | Select-Object -First 1));            
            }
            catch 
            {
                $currentInstance.PublishException($_);
            }
        });

        $this.RegisterEvent([SVTEvent]::CommandStarted, {
            $currentInstance = [WriteSummaryFile]::GetInstance();
            try 
            {
                $currentInstance.SetFilePath($Event.SourceArgs.ResourceContext, ("SecurityReport-" + $currentInstance.RunIdentifier + ".csv"));
            }
            catch 
            {
                $currentInstance.PublishException($_);
            }
        });
        
        $this.RegisterEvent([SVTEvent]::CommandCompleted, {
            $currentInstance = [WriteSummaryFile]::GetInstance();
            try 
            {
                $currentInstance.WriteToCSV($Event.SourceArgs);
                $currentInstance.FilePath = "";
            }
            catch 
            {
                $currentInstance.PublishException($_);
            }
        });

        $this.RegisterEvent([AzSdkRootEvent]::UnsupportedResources, {
            $currentInstance = [WriteSummaryFile]::GetInstance();
            try 
            {
                $message = $Event.SourceArgs.Messages | Select-Object -First 1
                if($message -and $message.DataObject)
                {
                    $filePath = $currentInstance.CalculateFilePath($Event.SourceArgs.Context, [FileOutputBase]::ETCFolderPath, ("UnsupportedResources-" + $currentInstance.RunIdentifier + ".csv.log"));
                    $message.DataObject | Export-Csv $filePath -NoTypeInformation
                }
            }
            catch 
            {
                $currentInstance.PublishException($_);
            }
        });
    }

    [void] WriteToCSV([SVTEventContext[]] $arguments)
    {
        if ([string]::IsNullOrEmpty($this.FilePath)) {
            return;
        }

        [CsvOutputItem[]] $csvItems = @();
        $arguments | ForEach-Object {
            $item = $_
            if ($item -and $item.ControlResults) {
                $item.ControlResults | ForEach-Object{
                    $csvItem = [CsvOutputItem]@{
                        ControlID = $item.ControlItem.ControlID;
                        ControlSeverity = $item.ControlItem.ControlSeverity;
                        Description = $item.ControlItem.Description;
                        Automated = $item.ControlItem.Automated;

                        FeatureName = $item.ResourceContext.FeatureName;
                        Reference = $item.ResourceContext.Reference;
                        ResourceName = $item.ResourceContext.ResourceName;
                        ResourceGroupName = $item.ResourceContext.ResourceGroupName;

                        ChildResourceName = $_.ChildResourceName;
                        Status = $_.VerificationResult.ToString();
                        Recommendation = $item.ControlItem.Recommendation;
                    };
                    $csvItems += $csvItem;
                }                                
            }
        } 

        if ($csvItems.Count -gt 0) {
            $csvItems | Export-Csv $this.FilePath -NoTypeInformation
        }
    }
}

class CsvOutputItem
{
    #Fields from JSON
    [string] $ControlID = ""
    [string] $Status = ""
    [string] $FeatureName = ""
    [string] $ResourceName = ""
    [string] $ChildResourceName = ""
    [string] $ResourceGroupName = ""
    [string] $ControlSeverity = ""    
    [string] $Automated = ""
    [string] $Description = ""
    [string] $Reference = ""
    [string] $Recommendation = ""
       
}