rules.ps1
function Import-ICRule { [cmdletbinding(DefaultParameterSetName = 'Rule')] Param( [parameter( Mandatory, ValueFromPipeline, ParameterSetName = 'Rule')] [ValidateNotNullOrEmpty()] [PSCustomObject]$Rule, [parameter( Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName, ParameterSetName = 'Path')] [ValidateNotNullorEmpty()] [String]$Path, [parameter(ParameterSetName = 'Rule')] [parameter(ParameterSetName = 'Path')] [Switch]$Active, [parameter(ParameterSetName = 'Rule')] [parameter(ParameterSetName = 'Path')] [Switch]$Force ) PROCESS { if ($Path) { $Body = Get-Content $Path -Raw #$reader = New-Object -TypeName System.IO.StreamReader -ArgumentList $Path $rules = ConvertFrom-Yaml $Body | convertto-json | convertfrom-json | ForEach-Object { if ($null -eq $_.rule) { Write-Error "Incorrect filetype. Not an Infocyte Rule" continue } $_ } } else { if ($null -eq $rule.rule) { Write-Error "Incorrect filetype. Not an Infocyte Rule" continue } $rules = $rule } $rules | Foreach-Object { $rule = $_ if ($rule.guid) { if ($rule.guid -notmatch $GUID_REGEX) { Write-Error "Incorrect guid format: $($rule.guid). Should be a guid of form: $GUID_REGEX. Use the following command to generate a new one: [guid]::NewGuid().Guid" $guid = [guid]::NewGuid().Guid Write-Warning "Missing guid: Generating a new one prior to import: $guid" $rule.guid = $guid } else { $existingRule = Get-ICRule -where @{ guid = $rule.guid } -NoBody | Select-Object -First 1 if ($existingRule) { if (-NOT $Force) { Write-Warning "There is already an existing rule named $($existingRule.name) [$($existingRule.Id)] with guid $($rule.guid). Try using Update-ICRule or use -Force flag." continue } Write-Warning "There is already an existing rule named $($existingRule.name) [$($existingRule.Id)] with guid $($rule.guid). Forcing update." $id = $existingRule.id Invoke-ICAPI -Endpoint rules -method POST -body @{ id = $id name = $rule.name short = $rule.short description = $rule.description body = $rule.rule } continue } } } else { $rule | Add-Member -TypeName NoteProperty -Name guid -Value ([guid]::NewGuid().Guid) } Write-Verbose "Adding new Rule named: $($rule.name)" Invoke-ICAPI -Endpoint rule -method POST -body @{ name = $rule.name short = $rule.short description = $rule.description body = $rule.rule guid = $rule.guid } } } } function Get-ICRule { [cmdletbinding(DefaultParameterSetName = "List")] Param( [parameter( Mandatory, ValueFromPipeline, ParameterSetName = 'Id')] [ValidateScript( { if ($_ -match $GUID_REGEX) { $true } else { throw "Incorrect input: $_. Should be a guid." } })] [alias('ruleId')] [String]$Id, [parameter( ParameterSetName = 'List', HelpMessage = "This will convert a hashtable into a JSON-encoded Loopback Where-filter: https://loopback.io/doc/en/lb2/Where-filter ")] [HashTable]$where = @{}, [parameter( ParameterSetName = 'List')] [Switch]$NoLimit, [parameter( ParameterSetName = 'List')] [Switch]$CountOnly, [Switch]$IncludeBody, [Switch]$Export ) PROCESS { if ($Id) { Write-Verbose "Looking up rule by Id." $Endpoint = "rules/$Id" $rules = Get-ICAPI -Endpoint $Endpoint -ea 0 if (-NOT $rules) { Write-Warning "Could not find rule with Id: $($Id)" return } } else { Write-Verbose "Getting rules" $Endpoint = "rules" $rules = Get-ICAPI -endpoint $Endpoint -where $where -NoLimit:$NoLimit -CountOnly:$CountOnly if (-NOT $rules) { Write-Verbose "Could not find any rules loaded with filter: $($where|convertto-json -Compress)" return } if ($CountOnly) { return $rules } } $n = 1 if ($null -eq $rules.count) { $c = 1 } else { $c = $rules.count } if ($IncludeBody -or $Export) { $rules | ForEach-Object { $rule = $_ Write-Verbose "Getting Rule $($rule.name) [$($rule.id)]" try { $pc = [math]::Floor(($n / $c) * 100) } catch { $pc = -1 } Write-Progress -Id 1 -Activity "Getting Rule Body from Infocyte API" -Status "Requesting Body from Rule $n of $c" -PercentComplete $pc $ruleBody = Get-ICAPI -endpoint "rules/$($rule.id)/LatestVersion" -fields body, sha256 $rule | Add-Member -MemberType NoteProperty -Name rule -Value $ruleBody.body $rule | Add-Member -MemberType NoteProperty -Name sha256 -Value $ruleBody.sha256 Write-Verbose "Looking up user: $($rule.createdBy) and $($rule.updatedBy)" $rule.createdBy = (Get-ICAPI -endpoint users -where @{ id = $rule.createdBy } -fields email -ea 0).email $rule.updatedBy = (Get-ICAPI -endpoint users -where @{ id = $rule.updatedBy } -fields email -ea 0).email $n += 1 } Write-Progress -Id 1 -Activity "Getting Rules from Infocyte API" -Status "Complete" -Completed } if ($Export) { $rules | ForEach-Object { $FilePath = "$($(Resolve-Path .\).Path)\$($($_.name).ToLower().Replace(' ','_')).yaml" $new_rule = [PSCustomObject][Ordered]@{ name = $_.name guid = if ($_.guid) { $_.guid } else { $null } rule = $_.body author = $_.createdBy description = $_.description short = $_.short severity = if ($_.severity) { $_.severity } else { "Medium" } created = $_.created updated = $_.updated action = @{ alert = $true } } Write-Verbose "Exported Rule [$($_.name)] to $FilePath" $_ | Convertto-YAML -Force -OutFile $FilePath } } $rules } } function New-ICRule { [cmdletbinding()] param( [parameter(mandatory)] [String]$Name, [Parameter(Mandatory)] [String]$Rule, [Parameter()] [String]$Author = $env:Username, [Parameter()] [String]$Short, [Parameter()] [String]$Description, [Parameter()] [ValidateSet( "Critical", "High", "Medium", "Low" )] [String]$Severity = "Medium", [Switch]$Force ) $today = Get-Date -UFormat "%F" $new_rule = [PSCustomObject][Ordered]@{ name = $Name guid = [Guid]::NewGuid().guid rule = $Rule author = $Author description = $Description short = $Short severity = $Severity created = $today updated = $today action = @{ alert = $true } } $SavePath = (Resolve-Path .\).Path + "\new_rule.yaml" Write-Verbose "Created rule from template and saved to $SavePath" $new_rule | ConvertTo-YAML -OutFile $SavePath -Force Write-Output $new_rule } function Update-ICRule { <# Updates an existing rule with a new body from a file or string. #> [cmdletbinding(SupportsShouldProcess = $true)] Param( [parameter()] [ValidateScript( { if ($_ -match $GUID_REGEX) { $true } else { throw "Incorrect input: $_. Should be a guid." } })] [alias('ruleId')] [String]$Id, [parameter(Mandatory)] [ValidateNotNullorEmpty()] [PSCustomObject]$Rule, [parameter(Mandatory)] [Switch]$Active ) PROCESS { $Endpoint = "rules" $rule = ConvertFrom-Yaml $Body | convertto-json | convertfrom-json if ($null -eq $_.rule) { Write-Error "Incorrect filetype. Not an Infocyte Rule" return } $postbody = @{ name = $rule.name short = $rule.short description = $rule.description body = $rule.rule guid = $rule.guid active = $Active } if ($Id) { Write-Verbose "Looking up rule by Id" $existing_rule = Get-ICRule -id $Id -ea 0 if ($existing_rule) { $Endpoint = "rules/$Id" Write-Verbose "Rule found: `n$($existing_rule | ConvertTo-Json)" if (-NOT $postbody['active']) { $postbody['active'] = $existing_rule.active } if (-NOT $postbody['name']) { $postbody['name'] = $existing_rule.name } if (-NOT $postbody['short']) { $postbody['short'] = $existing_rule.short } if (-NOT $postbody['description']) { $postbody['description'] = $existing_rule.description } if (-NOT $postbody['body']) { $postbody['body'] = $existing_rule.body } if (-NOT $postbody['guid']) { $postbody['guid'] = $existing_rule.guid } elseif ($rule.guid -AND $existing_rule.guid -ne $rule.guid) { Write-Warning "Rule guids do not match. Cannot be updated, try importing the new rule!`nCurrent: $($existing_rule.guid)`nNew: $($rule.guid)" return } } else { Write-Warning "Rule with id $id not found!" return } } else { Write-Verbose "Looking up rule by Guid" $existing_rule = Get-ICRule -ea 0 -where @{ guid = $rule.guid } -NoBody if ($existing_rule) { Write-Verbose "Found existing rule with matching guid $($existing_rule.guid). Updating id $($existing_rule.id)" $Endpoint = "rules/$($existing_rule.id)" $existing_rule = Get-ICRule -id $existing_rule.id if (-NOT $postbody['active']) { $postbody['active'] = $existing_rule.active } if (-NOT $postbody['name']) { $postbody['name'] = $existing_rule.name } if (-NOT $postbody['short']) { $postbody['short'] = $existing_rule.short } if (-NOT $postbody['description']) { $postbody['description'] = $existing_rule.description } if (-NOT $postbody['body']) { $postbody['body'] = $existing_rule.body } } else { Write-Warning "Could not find existing rule with Guid: $($existing_rule.guid)" return } } Write-Verbose "Updating Rule: $($rule['name']) [Guid=$($rule.guid)] with `n$($postbody|convertto-json)" if ($PSCmdlet.ShouldProcess($($rule.name), "Will update rule $($postbody['name']) [$postbody['id'])]")) { Invoke-ICAPI -Endpoint $Endpoint -body $postbody -method POST } } } function Remove-ICRule { [cmdletbinding(SupportsShouldProcess = $true)] Param( [parameter( ValueFromPipeline, ValueFromPipelineByPropertyName)] [ValidateScript( { if ($_ -match $GUID_REGEX) { $true } else { throw "Incorrect input: $_. Should be a guid." } })] [alias('ruleId')] [String]$Id ) PROCESS { if ($Id) { $rule = Get-ICRule -id $Id if (-NOT $rule) { Write-Error "Rule with id $id not found!" return } $Endpoint = "rules/$Id" if ($PSCmdlet.ShouldProcess($($rule.Id), "Will remove $($rule.name) with ruleId '$($rule.id)'")) { try { Invoke-ICAPI -Endpoint $Endpoint -Method DELETE Write-Verbose "Removed rule $($rule.name) [$($rule.id)]" } catch { Write-Warning "Rule $($rule.name) [$($rule.id)] could not be removed!" } } } else { $endpoint = "rules" Invoke-ICAPI -Endpoint $Endpoint -Method DELETE Write-Verbose "Removed all rules" } } } # SIG # Begin signature block # MIINFwYJKoZIhvcNAQcCoIINCDCCDQQCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUszwo5d9ETLHkjIAqStKh9N8Q # hsKgggpZMIIFITCCBAmgAwIBAgIQD1SHruUyzkN01AFx5d7oATANBgkqhkiG9w0B # AQsFADByMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYD # VQQLExB3d3cuZGlnaWNlcnQuY29tMTEwLwYDVQQDEyhEaWdpQ2VydCBTSEEyIEFz # c3VyZWQgSUQgQ29kZSBTaWduaW5nIENBMB4XDTIwMTExNzAwMDAwMFoXDTIyMTEy # OTIzNTk1OVowXjELMAkGA1UEBhMCVVMxDjAMBgNVBAgTBVRleGFzMQ8wDQYDVQQH # EwZBdXN0aW4xFjAUBgNVBAoTDUluZm9jeXRlLCBJbmMxFjAUBgNVBAMTDUluZm9j # eXRlLCBJbmMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDNUhaEiZbu # H7Q6oqA0uq0klkstXkdJU3eJukMrrLpxKdtFqtJwFXcSYp5G/WFlwDRJ8v8fisfp # SiPS1WajFUHe3EWLh2oXjf44eQYVWQ8SqAn2J8dDLNJ5bWY0w7MD2GrSiTwN0Vi9 # X9pJKJDdm7mJo7bSlZ9p7XvNoraSAx/hkODalPSMvCIVAEOZutlzeWyJ4p0DbTDA # kjQPF4EZ7JqxYXFeItoi0uYZQNEHbBxr+5SG45ziC8vuwyljIbo+mKD/PwT48OQl # 9cdnI651Hz+r5kL3t48WvxYrAUJ7g8EJyw2uYnVnSroIC3TmUQHeXS6FuqeObuX7 # MqapBKRcTHvxAgMBAAGjggHFMIIBwTAfBgNVHSMEGDAWgBRaxLl7KgqjpepxA8Bg # +S32ZXUOWDAdBgNVHQ4EFgQUxKDwshqav/aGaGVOFv67CuwSjcYwDgYDVR0PAQH/ # BAQDAgeAMBMGA1UdJQQMMAoGCCsGAQUFBwMDMHcGA1UdHwRwMG4wNaAzoDGGL2h0 # dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9zaGEyLWFzc3VyZWQtY3MtZzEuY3JsMDWg # M6Axhi9odHRwOi8vY3JsNC5kaWdpY2VydC5jb20vc2hhMi1hc3N1cmVkLWNzLWcx # LmNybDBMBgNVHSAERTBDMDcGCWCGSAGG/WwDATAqMCgGCCsGAQUFBwIBFhxodHRw # czovL3d3dy5kaWdpY2VydC5jb20vQ1BTMAgGBmeBDAEEATCBhAYIKwYBBQUHAQEE # eDB2MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wTgYIKwYB # BQUHMAKGQmh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFNIQTJB # c3N1cmVkSURDb2RlU2lnbmluZ0NBLmNydDAMBgNVHRMBAf8EAjAAMA0GCSqGSIb3 # DQEBCwUAA4IBAQByJW5tIcmouIY7tdngPLdEOM4FYqLGf9IjKPMS0s+NeTaP/0hp # dmNeGFEvMozfgDA/gPFCUaRVJwy4rKsGnCznCE1YDA6UFDGZq3VLUbzC6GDP4aY8 # EbfDMbF54TVuOKRue9a6KnVE67gOj+g862qAR6fm/GdeO/KrdvCT1A7xbyg02cCq # +QgdkYoxI3bsiUwgZ33I2rn2T2zSp8C+RX2bZ8rgtXHxgYLCJdayqMptRsPbxOlQ # Z7dRhkQXg5D/PyUnpWASF+sLQQ0IMvx8ZKy/P01IhKU0pTJ8OFSYKwPLQnYm1Zp0 # JT/IXZ/tzmtY/StdhaCs3LlOkuHxl2iERxdtMIIFMDCCBBigAwIBAgIQBAkYG1/V # u2Z1U0O1b5VQCDANBgkqhkiG9w0BAQsFADBlMQswCQYDVQQGEwJVUzEVMBMGA1UE # ChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYD # VQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwHhcNMTMxMDIyMTIwMDAw # WhcNMjgxMDIyMTIwMDAwWjByMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNl # cnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMTEwLwYDVQQDEyhEaWdp # Q2VydCBTSEEyIEFzc3VyZWQgSUQgQ29kZSBTaWduaW5nIENBMIIBIjANBgkqhkiG # 9w0BAQEFAAOCAQ8AMIIBCgKCAQEA+NOzHH8OEa9ndwfTCzFJGc/Q+0WZsTrbRPV/ # 5aid2zLXcep2nQUut4/6kkPApfmJ1DcZ17aq8JyGpdglrA55KDp+6dFn08b7KSfH # 03sjlOSRI5aQd4L5oYQjZhJUM1B0sSgmuyRpwsJS8hRniolF1C2ho+mILCCVrhxK # hwjfDPXiTWAYvqrEsq5wMWYzcT6scKKrzn/pfMuSoeU7MRzP6vIK5Fe7SrXpdOYr # /mzLfnQ5Ng2Q7+S1TqSp6moKq4TzrGdOtcT3jNEgJSPrCGQ+UpbB8g8S9MWOD8Gi # 6CxR93O8vYWxYoNzQYIH5DiLanMg0A9kczyen6Yzqf0Z3yWT0QIDAQABo4IBzTCC # AckwEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwEwYDVR0lBAww # CgYIKwYBBQUHAwMweQYIKwYBBQUHAQEEbTBrMCQGCCsGAQUFBzABhhhodHRwOi8v # b2NzcC5kaWdpY2VydC5jb20wQwYIKwYBBQUHMAKGN2h0dHA6Ly9jYWNlcnRzLmRp # Z2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcnQwgYEGA1UdHwR6 # MHgwOqA4oDaGNGh0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3Vy # ZWRJRFJvb3RDQS5jcmwwOqA4oDaGNGh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9E # aWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcmwwTwYDVR0gBEgwRjA4BgpghkgBhv1s # AAIEMCowKAYIKwYBBQUHAgEWHGh0dHBzOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMw # CgYIYIZIAYb9bAMwHQYDVR0OBBYEFFrEuXsqCqOl6nEDwGD5LfZldQ5YMB8GA1Ud # IwQYMBaAFEXroq/0ksuCMS1Ri6enIZ3zbcgPMA0GCSqGSIb3DQEBCwUAA4IBAQA+ # 7A1aJLPzItEVyCx8JSl2qB1dHC06GsTvMGHXfgtg/cM9D8Svi/3vKt8gVTew4fbR # knUPUbRupY5a4l4kgU4QpO4/cY5jDhNLrddfRHnzNhQGivecRk5c/5CxGwcOkRX7 # uq+1UcKNJK4kxscnKqEpKBo6cSgCPC6Ro8AlEeKcFEehemhor5unXCBc2XGxDI+7 # qPjFEmifz0DLQESlE/DmZAwlCEIysjaKJAL+L3J+HNdJRZboWR3p+nRka7LrZkPa # s7CM1ekN3fYBIM6ZMWM9CBoYs4GbT8aTEAb8B4H6i9r5gkn3Ym6hU/oSlBiFLpKR # 6mhsRDKyZqHnGKSaZFHvMYICKDCCAiQCAQEwgYYwcjELMAkGA1UEBhMCVVMxFTAT # BgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTEx # MC8GA1UEAxMoRGlnaUNlcnQgU0hBMiBBc3N1cmVkIElEIENvZGUgU2lnbmluZyBD # QQIQD1SHruUyzkN01AFx5d7oATAJBgUrDgMCGgUAoHgwGAYKKwYBBAGCNwIBDDEK # MAigAoAAoQKAADAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgorBgEEAYI3 # AgELMQ4wDAYKKwYBBAGCNwIBFTAjBgkqhkiG9w0BCQQxFgQUxMPCc/X987+mieLH # yRJtnQaXnUowDQYJKoZIhvcNAQEBBQAEggEACMbEPYi/XHa9+mIYFRQ7IFuvJZ2a # L6INVpuwEwdU5QXEQK18+IEfSIcoNmdR69px7e9zmnhmUMoyokg+HIcgmlELmPKz # 1RTJMRFqzUJJFLSQ/8LrS24NgDx0tPLawG4iV7dHhN4ZWqn9Z4kTdkKav+xlrNVH # HMk8DHu2ur5xMRaln2OAHH2UPm8inC4E+KeofbEpVyuboNGtVZD68pXznyriTdUc # bs5dLRCARMxMCtH3RXEIKIv4+luby0HRgcxWRFz1UwqMKbhrr9KteA0MOEzfoSZI # o72int6MKnCREfx38X3UQ6Afg5JmrYEoMilPJ+ef4w8kkqtPNdnyZuCCnA== # SIG # End signature block |