From 04492a9b763990bc1e62dff41adc90b6c81b60f2 Mon Sep 17 00:00:00 2001 From: Oscar Pocock Date: Thu, 26 Jan 2023 16:57:15 +0000 Subject: [PATCH] Added GenerateConformanceSpreadsheet.ps1 to generate spreadsheet of non-compliant resources --- GenerateConformanceSpreadsheet.ps1 | 157 +++++++++++++++++++++++++++++ 1 file changed, 157 insertions(+) create mode 100644 GenerateConformanceSpreadsheet.ps1 diff --git a/GenerateConformanceSpreadsheet.ps1 b/GenerateConformanceSpreadsheet.ps1 new file mode 100644 index 0000000..43d6f16 --- /dev/null +++ b/GenerateConformanceSpreadsheet.ps1 @@ -0,0 +1,157 @@ +# Used for generating a spreadsheet of non-compliant resources for a given conformance pack +# +# Use: +# Returns a CSV for all the non-compliant resources for the given comformance pack in the context of the logged in user +# .\GenerateConformanceSpreadsheet.ps1 -conformancePack OrgConformsPack-uk-gov-xxxxxxxx + +Param ( +[string]$conformancePack +) + + +$currentAccountId = (Invoke-Expression "aws sts get-caller-identity" | ConvertFrom-Json).Account +$accountName = (Invoke-Expression "aws organizations describe-account --account-id $currentAccountId" | ConvertFrom-Json).Account.Name + +$UniqueIdTypes = @("AGPA", "AIDA", "AKIA", "ANPA", "AROA", "ASCA") +$arn = $true + +function GetInfoFromUniqueId($target) { + $uniqueIdType = "$($target.Substring(0,4))" + + switch($uniqueIdType){ + # "ABIA" { $command="" } + # "ACCA" { $command="" } + "AGPA" { $command="list-groups" + $types="Groups" + $type="Group" } + "AIDA" { $command="list-users" + $types="Users" + $type="User" } + # "AIPA" { $command="" } + # "AKIA" { $command="" } + "ANPA" { $command="list-policies" + $types="Policies" + $type="Policy" } + # "ANVA" { $command="" } + # "APKA" { $command="" } + "AROA" { $command="list-roles" + $types="Roles" + $type="Role" } + # "ASCA" { $command="list-server-certificates" + # $types="ServerCertificateMetadataList" } + # "ASIA" { $command="" } + default { Write-Output "Invalid 'target' value."; return} + } + + $env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + $awsCommand = "aws iam $command" + Invoke-Expression $awsCommand -OutVariable succOut -ErrorVariable errOut 2>&1 >$null + + if ($errOut -ne $null) { + Write-Output "$($errOut[1].ToString())" + return + } + else { + $returnedObjects = ($succOut | ConvertFrom-Json).$types + } + + $selectedObject = $returnedObjects | Where-Object {$_."$($type)Id" -eq $target} + + if ($selectedObject -eq $null) { + Write-Output "Unique ID '$target' not found" + return + } + + if ($json) { + return $selectedObject | ConvertTo-Json + } + if ($name) { + return $selectedObject."$($type)Name" + } + if ($arn) { + return $selectedObject.Arn + } + if ($id) { + return $selectedObject."$($type)Id" + } +} + +function GenerateCSV($conformancePack) { + $awsCommand = "aws configservice get-conformance-pack-compliance-details --conformance-pack-name $conformancePack --filters ComplianceType=NON_COMPLIANT" + $returnedObjects = Invoke-Expression $awsCommand | ConvertFrom-Json + + $collection = $returnedObjects + + while ($returnedObjects.NextToken -ne $null) { + $nextTokenCommand = $awsCommand + " --next-token " + $returnedObjects.NextToken + $returnedObjects = Invoke-Expression $nextTokenCommand | ConvertFrom-Json + $collection.ConformancePackRuleEvaluationResults += $returnedObjects.ConformancePackRuleEvaluationResults + } + + $NewObject = @() + + $discoveredConfigRules = @() + + foreach($object in $collection.ConformancePackRuleEvaluationResults) { + if ($discoveredConfigRules.Contains($object.EvaluationResultIdentifier.EvaluationResultQualifier.ConfigRuleName)) { + ($NewObject | Where-Object {$_.ConfigRuleName -eq $object.EvaluationResultIdentifier.EvaluationResultQualifier.ConfigRuleName}).ResourceDetails += [PSCustomObject]@{ + ResourceNo = ($NewObject | Where-Object {$_.ConfigRuleName -eq $object.EvaluationResultIdentifier.EvaluationResultQualifier.ConfigRuleName}).ResourceDetails.Count + 1 + ResourceId = $object.EvaluationResultIdentifier.EvaluationResultQualifier.ResourceId + Annotation = $object.Annotation + ResourceType =$object.EvaluationResultIdentifier.EvaluationResultQualifier.ResourceType + } + } + else { + $discoveredConfigRules += $object.EvaluationResultIdentifier.EvaluationResultQualifier.ConfigRuleName + $ResourceDetails = [PSCustomObject]@{ + ResourceNo = 1 + ResourceId = $object.EvaluationResultIdentifier.EvaluationResultQualifier.ResourceId + Annotation = $object.Annotation + ResourceType = $object.EvaluationResultIdentifier.EvaluationResultQualifier.ResourceType + } + $NewObject += [PSCustomObject]@{ + RuleNo = $discoveredConfigRules.Count + ConfigRuleName = $object.EvaluationResultIdentifier.EvaluationResultQualifier.ConfigRuleName + ResourceDetails = @($ResourceDetails) + Resolution = "" + } + } + } + + $csvExportObject = @() + + foreach($rule in $NewObject) { + $csvExportObject += [PSCustomObject]@{ + RuleNo = $rule.RuleNo + ConfigRuleName = $rule.ConfigRuleName + ResourceNo = "" + ResourceId = "" + ResourceType = "" + Annotation = "" + Resolution = "" + } + foreach ($resource in $rule.ResourceDetails) { + if ($UniqueIdTypes.Contains($resource.ResourceId.Substring(0,4))) { + $TrueResourceId = "$($resource.ResourceId)" + " " + "($(GetInfoFromUniqueId($resource.ResourceId)))" + } + else { + $TrueResourceId = $resource.ResourceId + } + $csvExportObject += [PSCustomObject]@{ + RuleNo = "" + ConfigRuleName = "" + ResourceNo = $resource.ResourceNo + ResourceId = $TrueResourceId + Annotation = $Resource.Annotation + ResourceType = $Resource.ResourceType + Resolution = "" + } + } + } + + return $csvExportObject +} + +$date = Get-Date -Format "yyyy-MM-dd_HH-mm-ss" +$csvString = $conformancePack + "_" + $accountName + "-" + $date + ".csv" +GenerateCSV($conformancePack) | Export-Csv -NoTypeInformation $csvString \ No newline at end of file