Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FEAT: Testing PR #5

Merged
merged 21 commits into from
Sep 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions coverage.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Code Coverage Report - Scope.psm1
| Metric | Value |
|-----------------|-------------|
| Result | ✅ Passed |
| Passed Count | ✅ 3 |
| Failed Count | ✅ 0 |
| Coverage (%) | ❌ 42.4242424242424 |
| Target Coverage (%) | 75 |
72 changes: 72 additions & 0 deletions coverage.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE report PUBLIC "-//JACOCO//DTD Report 1.1//EN" "report.dtd"[]>
<report name="Pester (09/18/2024 11:02:20)">
<sessioninfo id="this" start="1726657340490" dump="1726657340772" />
<package name="scope">
<class name="scope/scope" sourcefilename="scope.psm1">
<method name="Get-WAFResourceGroupsByList" desc="()" line="90">
<counter type="INSTRUCTION" missed="0" covered="5" />
<counter type="LINE" missed="0" covered="4" />
<counter type="METHOD" missed="0" covered="1" />
</method>
<method name="Get-WAFSubscriptionsByList" desc="()" line="141">
<counter type="INSTRUCTION" missed="0" covered="5" />
<counter type="LINE" missed="0" covered="4" />
<counter type="METHOD" missed="0" covered="1" />
</method>
<method name="Get-WAFResourcesByList" desc="()" line="194">
<counter type="INSTRUCTION" missed="0" covered="4" />
<counter type="LINE" missed="0" covered="4" />
<counter type="METHOD" missed="0" covered="1" />
</method>
<method name="Get-WAFUnfilteredResourceList" desc="()" line="239">
<counter type="INSTRUCTION" missed="11" covered="0" />
<counter type="LINE" missed="3" covered="0" />
<counter type="METHOD" missed="1" covered="0" />
</method>
<method name="Get-WAFFilteredResourceList" desc="()" line="282">
<counter type="INSTRUCTION" missed="8" covered="0" />
<counter type="LINE" missed="5" covered="0" />
<counter type="METHOD" missed="1" covered="0" />
</method>
<counter type="INSTRUCTION" missed="19" covered="14" />
<counter type="LINE" missed="8" covered="12" />
<counter type="METHOD" missed="2" covered="3" />
<counter type="CLASS" missed="0" covered="1" />
</class>
<sourcefile name="scope.psm1">
<line nr="90" mi="0" ci="1" mb="0" cb="0" />
<line nr="91" mi="0" ci="2" mb="0" cb="0" />
<line nr="92" mi="0" ci="1" mb="0" cb="0" />
<line nr="96" mi="0" ci="1" mb="0" cb="0" />
<line nr="141" mi="0" ci="1" mb="0" cb="0" />
<line nr="142" mi="0" ci="2" mb="0" cb="0" />
<line nr="143" mi="0" ci="1" mb="0" cb="0" />
<line nr="147" mi="0" ci="1" mb="0" cb="0" />
<line nr="194" mi="0" ci="1" mb="0" cb="0" />
<line nr="195" mi="0" ci="1" mb="0" cb="0" />
<line nr="196" mi="0" ci="1" mb="0" cb="0" />
<line nr="200" mi="0" ci="1" mb="0" cb="0" />
<line nr="239" mi="7" ci="0" mb="0" cb="0" />
<line nr="240" mi="3" ci="0" mb="0" cb="0" />
<line nr="241" mi="1" ci="0" mb="0" cb="0" />
<line nr="282" mi="2" ci="0" mb="0" cb="0" />
<line nr="284" mi="2" ci="0" mb="0" cb="0" />
<line nr="286" mi="2" ci="0" mb="0" cb="0" />
<line nr="290" mi="1" ci="0" mb="0" cb="0" />
<line nr="292" mi="1" ci="0" mb="0" cb="0" />
<counter type="INSTRUCTION" missed="19" covered="14" />
<counter type="LINE" missed="8" covered="12" />
<counter type="METHOD" missed="2" covered="3" />
<counter type="CLASS" missed="0" covered="1" />
</sourcefile>
<counter type="INSTRUCTION" missed="19" covered="14" />
<counter type="LINE" missed="8" covered="12" />
<counter type="METHOD" missed="2" covered="3" />
<counter type="CLASS" missed="0" covered="1" />
</package>
<counter type="INSTRUCTION" missed="19" covered="14" />
<counter type="LINE" missed="8" covered="12" />
<counter type="METHOD" missed="2" covered="3" />
<counter type="CLASS" missed="0" covered="1" />
</report>
156 changes: 156 additions & 0 deletions src/modules/WARA/collector/collector.psm1
Original file line number Diff line number Diff line change
@@ -1,2 +1,158 @@
Function Get-WAFAllAzGraphResource {
param (
[string[]]$subscriptionIds,
[string]$query = 'Resources | project id, resourceGroup, subscriptionId, name, type, location'
)

if ($Debugging) {
Write-Host
Write-Host "[-Debugging]: Running resource graph query..." -ForegroundColor Magenta
Write-Host
Write-Host "$query" -ForegroundColor Magenta
Write-Host
}

$result = $subscriptionIds ? (Search-AzGraph -Query $query -first 1000 -Subscription $subscriptionIds) : (Search-AzGraph -Query $query -first 1000 -usetenantscope) # -first 1000 returns the first 1000 results and subsequently reduces the amount of queries required to get data.

# Collection to store all resources
$allResources = @($result)

# Loop to paginate through the results using the skip token
$result = while ($result.SkipToken) {
# Retrieve the next set of results using the skip token
$result = $subscriptionId ? (Search-AzGraph -Query $query -SkipToken $result.SkipToken -Subscription $subscriptionIds -First 1000) : (Search-AzGraph -query $query -SkipToken $result.SkipToken -First 1000 -UseTenantScope)
# Add the results to the collection
write-output $result
}

$allResources += $result

# Output all resources
return $allResources
}

function Get-WAFResourceGroup {
param (
[string[]]$SubscriptionIds
)

# Query to get all resource groups in the tenant
$q = "resourcecontainers
| where type == 'microsoft.resources/subscriptions'
| project subscriptionId, subscriptionName = name
| join (resourcecontainers
| where type == 'microsoft.resources/subscriptions/resourcegroups')
on subscriptionId
| project subscriptionName, subscriptionId, resourceGroup, id=tolower(id)"

$r = $SubscriptionIds ? (Get-WAFAllAzGraphResource -query $q -subscriptionIds $SubscriptionIds -usetenantscope) : (Get-WAFAllAzGraphResource -query $q -usetenantscope)

# Returns the resource groups
return $r
}

#This function grabs all resources inside of resource groups with matching tags.

#This function grabs all resources that have matching tags and returns them.
Function Get-WAFTaggedResources {
param(
[String[]]$tagArray,
[String[]]$SubscriptionIds
)

$queryTemplate = "| where (tags['<name>'] =~ '<value>')"

$queryobj = @()
foreach($tag in $tagArray){
$tagName, $tagValue = $tag.Split('==').Trim()
$queryobj += $queryTemplate -replace "<name>", $tagName -replace "<value>", $tagValue
}

$queryobj = $queryobj -join "`r`n"

$q = "resources
<insert>
| project id, name, type, location, resourceGroup, subscriptionId" -replace "<insert>", $queryobj


Write-host The Query is: `r`n $q

$r = $SubscriptionIds ? (Get-WAFAllAzGraphResource -query $q -subscriptionIds $SubscriptionIds) : (Get-WAFAllAzGraphResource -query $q -usetenantscope)
return $r
}
#This function grabs all resources that have matching tags and returns them.
Function Get-WAFTaggedRGResources {
param(
[String[]]$tagKeys,
[String[]]$tagValues,
[String[]]$SubscriptionIds
)

$tagValuesString = "'" + ($tagValues -join "','").toLower() + "'"
$tagKeysString = "'" + ($tagKeys -join "','").toLower() + "'"

$q = "Resources
| mv-expand bagexpansion=array tags
| where isnotempty(tags)
| where tolower(tags[0]) in ($tagValuesString) // Specify your tag names here
| where tolower(tags[1]) in ($tagKeysString) // Specify your tag values here
| project name,id,type,resourceGroup,location,subscriptionId"

Write-host The Query is $q

$r = $SubscriptionIds ? (Get-WAFAllAzGraphResource -query $q -subscriptionIds $SubscriptionIds) : (Get-WAFAllAzGraphResource -query $q -usetenantscope)
return $r
}

Function Invoke-WAFQueryLoop {
param(
$RecommendationObject,
[string[]]$subscriptionIds
)

$Types = Get-WAFResourceType -SubscriptionIds $subscriptionIds

$QueryObject = Get-WAFQueryByResourceType -ObjectList $RecommendationObject -FilterList $Types.type -KeyColumn "recommendationResourceType"

$return = $QueryObject | Where-Object{$_.automationavailable -eq "arg"} | ForEach-Object {
Write-Progress -Activity "Running Queries" -Status "Running Query for $($_.recommendationResourceType)" -PercentComplete (($QueryObject.IndexOf($_) / $QueryObject.Count) * 100)
Get-WAFAllAzGraphResource -query $_.query -subscriptionIds $subscriptionIds
}

return $return
}

Function Get-WAFResourceType {
param(
[String[]]$SubscriptionIds
)

$q = "Resources
| summarize count() by type
| project type"

$r = $SubscriptionIds ? (Get-WAFAllAzGraphResource -query $q -subscriptionIds $SubscriptionIds) : (Get-WAFAllAzGraphResource -query $q -usetenantscope)

return $r
}

function Get-WAFQueryByResourceType {
param (
[Parameter(Mandatory = $true)]
[array]$ObjectList,

[Parameter(Mandatory = $true)]
[array]$FilterList,

[Parameter(Mandatory = $true)]
[string]$KeyColumn
)

$matchingObjects = foreach ($obj in $ObjectList) {
if ($obj.$KeyColumn -in $FilterList) {
$obj
}
}

return $matchingObjects
}
57 changes: 57 additions & 0 deletions src/modules/WARA/runbook/runbook.psm1
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<#
.SYNOPSIS
WARA Runbook module

.DESCRIPTION
Enables developers to consume WARA runbook files
#>

function Read-Runbook {
param(
[Parameter(Mandatory = $true)]
[string]$RunbookPath
)

# First, check to make sure the runbook actually exists...
if (!(Test-Path $RunbookPath -PathType Leaf)) {

# If not, fail early.
Write-Error "[-RunbookPath]: No runbook found at [$RunbookPath]."
$null

} else {

# If so, let's read this runbook!
$runbook = @{
Parameters = @{}
Selectors = @{}
Checks = @{}
QueryOverrides = @()
}

# Read the runbook JSON
$runbookJson = Get-Content -Raw $RunbookPath | ConvertFrom-Json

# Try to load parameters
$runbookJson.parameters.PSObject.Properties | ForEach-Object {
$runbook.Parameters[$_.Name] = $_.Value
}

# Try to load selectors
$runbookJson.selectors.PSObject.Properties | ForEach-Object {
$runbook.Selectors[$_.Name.ToLower()] = $_.Value
}

# Try to load checks
$runbookJson.checks.PSObject.Properties | ForEach-Object {
$runbook.Checks[$_.Name.ToLower()] = $_.Value
}

# Try to load query overrides
$runbookJson.query_overrides | ForEach-Object {
$runbook.QueryOverrides += [string]$_
}

return [pscustomobject]$runbook
}
}
Loading
Loading