core/modules/monkeyruleset/public/Get-Rule.ps1
# Monkey365 - the PowerShell Cloud Security Tool for Azure and Microsoft 365 (copyright 2022) by Juan Garrido # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. Function Get-Rule{ <# .SYNOPSIS Get rule .DESCRIPTION .INPUTS .OUTPUTS .EXAMPLE .NOTES Author : Juan Garrido Twitter : @tr1ana File Name : Get-Rule Version : 1.0 .LINK https://github.com/silverhack/monkey365 #> [CmdletBinding()] Param ( [parameter(Mandatory= $false, HelpMessage= "json file with all rules")] [ValidateScript({ if( -Not (Test-Path -Path $_) ){ throw ("The ruleset does not exist in {0}" -f (Split-Path -Path $_)) } if(-Not (Test-Path -Path $_ -PathType Leaf) ){ throw "The ruleSet argument must be a json file. Folder paths are not allowed." } if($_ -notmatch "(\.json)"){ throw "The file specified in the ruleset argument must be of type json" } return $true })] [System.IO.FileInfo]$RuleSet, [parameter(Mandatory=$false,HelpMessage="Path to rules")] [ValidateScript({ if( -Not (Test-Path -Path $_) ){ throw ("The directory does not exist in {0}" -f (Split-Path -Path $_)) } if(-Not (Test-Path -Path $_ -PathType Container) ){ throw "The RulesPath argument must be a directory. Files are not allowed." } return $true })] [System.IO.DirectoryInfo]$RulesPath, [Parameter(Mandatory=$false)] [ValidateSet('Azure','Microsoft365')] $Instance, [Parameter(Mandatory=$false, HelpMessage="Include Azure AD")] [Switch] $IncludeEntraID, [parameter(Mandatory=$false,HelpMessage="Full object")] [Switch]$Full, [parameter(Mandatory=$false,HelpMessage="Pretty table")] [Switch]$Pretty ) Begin{ $MyRules = $mrules = $null; $colors = [ordered]@{ info = 36; low = 34; medium = 33; high = 31; critical = 35; good = 32; } $e = [char]27 #Get window size if($null -eq (Get-Variable -Name psISE -ErrorAction Ignore)){ $windowSize = $Host.UI.RawUI.WindowSize.Width } else{ $windowSize = [int32]::MaxValue } $Verbose = $False; $Debug = $False; $InformationAction = 'SilentlyContinue' if($PSBoundParameters.ContainsKey('Verbose') -and $PSBoundParameters.Verbose){ $Verbose = $True } if($PSBoundParameters.ContainsKey('Debug') -and $PSBoundParameters.Debug){ $Debug = $True } if($PSBoundParameters.ContainsKey('InformationAction')){ $InformationAction = $PSBoundParameters['InformationAction'] } #Get Command metadata $MetaData = New-Object -TypeName "System.Management.Automation.CommandMetaData" (Get-Command -Name "Initialize-MonkeyRuleset") $newPsboundParams = [ordered]@{} if($null -ne $MetaData){ $param = $MetaData.Parameters.Keys foreach($p in $param.GetEnumerator()){ if($PSBoundParameters.ContainsKey($p) -and $PSBoundParameters[$p]){ $newPsboundParams.Add($p,$PSBoundParameters[$p]) } } } #Add verbose, debug $newPsboundParams.Add('Verbose',$Verbose) $newPsboundParams.Add('Debug',$Debug) $newPsboundParams.Add('InformationAction',$InformationAction) } Process{ If($newPsboundParams.Count -eq 5){ #Remove vars Remove-InternalVar #Initialize Ruleset [void](Initialize-MonkeyRuleset @newPsboundParams) } try{ If($PSBoundParameters.ContainsKey('RulesPath') -and $PSBoundParameters['RulesPath'] -and !$PSBoundParameters.ContainsKey('RuleSet')){ if($RulesPath.GetDirectories('findings').Count -gt 0){ $findingsPath = $RulesPath.GetDirectories('findings') $all_rules = Get-File -Filter "*json" -Rulepath $findingsPath.FullName.ToString() $all_rules = $all_rules | Select-Object * -Unique #Get rule info $MyRules = $all_rules | Get-RuleFileContent #@($all_rules).ForEach({$r = (Get-Content $_.FullName -Raw) | ConvertFrom-Json; if ($r | Test-isValidRule){$r | Add-Member -Type NoteProperty -name File -value $_ -Force; $r}}) } else{ Write-Warning ("Findings folder was not found on {0}" -f $RulesPath.FullName) } } ElseIf($null -ne (Get-Variable -Name AllRules -ErrorAction Ignore)){ $MyRules = $Script:AllRules } } catch{ Write-Verbose $_.Exception.Message } } End{ try{ if($null -ne $MyRules){ if($PSBoundParameters.ContainsKey('Full') -and $PSBoundParameters['Full'].IsPresent){ $MyRules return } elseif($PSBoundParameters.ContainsKey('RuleSet') -and $PSBoundParameters['RuleSet']){ $mrules = $MyRules | Select-Object displayName,serviceType,level,IdSuffix } else{ $mrules = @() if($PSBoundParameters.ContainsKey('Instance') -and $PSBoundParameters['Instance']){ $mrules += @($MyRules).Where({$_.File.FullName -notlike "*EntraID*" -and $_.File.FullName -like ("*{0}*" -f $PSBoundParameters['Instance'])}) } if($PSBoundParameters.ContainsKey('IncludeEntraID') -and $PSBoundParameters['IncludeEntraID'].IsPresent){ $mrules += @($MyRules).Where({$_.File.FullName -like "*EntraID*"}) } if($mrules.Count -gt 0){ $mrules = $mrules | Select-Object displayName,serviceType,level,IdSuffix } else{ $mrules = $MyRules | Select-Object displayName,serviceType,level,IdSuffix } } #Check if pretty if($PSBoundParameters.ContainsKey('Pretty') -and $PSBoundParameters['Pretty'].IsPresent){ $maxWidthName = $mrules | Select-Object -ExpandProperty displayName | Group-Object {$_.Length} | Select-Object -ExpandProperty Name | Measure-Object -Maximum | Select-Object -ExpandProperty Maximum $maxWidthType = $mrules | Select-Object -ExpandProperty serviceType | Group-Object {$_.Length} | Select-Object -ExpandProperty Name | Measure-Object -Maximum | Select-Object -ExpandProperty Maximum $Name = @{label="Rule Name";expression={$_.displayName};Width = [int]$maxWidthName-50}; $ResourceName = @{label="Service";expression={$_.serviceType};Width = [int]$maxWidthType}; $Level = @{label="Risk";expression={$_.level};Width = 12} $IdSuffix = @{label="Id";expression={$_.idSuffix}} if($null -eq (Get-Variable -Name psISE -ErrorAction Ignore)){ foreach($r in $mrules){ if($null -ne $r.level){ $color = $colors.Item($r.level) if($color){ $r.level = "$e[${color}m$($r.level)${e}[0m" } else{ $color = 48 $r.level = "$e[${color}m$($r.level)${e}[0m" } } $green = 32 $r.serviceType = "$e[${green}m$($r.serviceType)${e}[0m" } } if($windowSize -gt 160){ $mrules | Select-Object * | Sort-Object -Property serviceType | Format-Table $Name,$ResourceName,$Level,$IdSuffix } else{ $mrules | Select-Object * | Sort-Object -Property serviceType | Format-List } if($null -eq (Get-Variable -Name psISE -ErrorAction Ignore)){ $message = ("There are $e[${color}m$(@($mrules).Count)${e}[0m available rules") } else{ $message = ('There are {0} available rules' -f $MyFrameworks.Count) } Write-Output $message } else{ $mrules | Select-Object displayName,serviceType,idSuffix } } } catch{ Write-Verbose $_.Exception.Message } } } |