Initial commit

This commit is contained in:
Nathan Windisch 2024-07-25 02:31:34 +01:00
commit d8f1ac024e
13 changed files with 766 additions and 0 deletions

View File

@ -0,0 +1,66 @@
function Connect-GraylogService {
<#
.SYNOPSIS
Connects to the Graylog server.
.DESCRIPTION
Connects to the Graylog server using the provided credentials.
.PARAMETER Credential
The credentials to use to connect to the Graylog server.
.OUTPUTS
None, the session is stored in the global variable $GraylogSession.
.EXAMPLE
Connect-GraylogService
Connects to the Graylog server using the stored credentials.
.EXAMPLE
Connect-GraylogService -Credential (Get-Credential)
Connects to the Graylog server using the provided credentials prompting for both the username and password.
.EXAMPLE
Connect-GraylogService -Credential (Get-Credential -UserName "ab123456")
Connects to the Graylog server using the provided credentials, prompting for just a password.
.EXAMPLE
$Credential = [PSCredential]::new("ab123456", (ConvertTo-SecureString "Password123" -AsPlainText -Force))
Connect-GraylogService -Credential $Credential
Connects to the Graylog server using the provided credentials without prompting for any input. (Other methods of creating a PSCredential object can be used)
.NOTES
The session is stored in the global variable $GraylogSession and is used for subsequent requests to the Graylog server.
#>
[Alias("Connect-Graylog")]
param (
[Parameter()]
[PSCredential]
$Credential
)
if ((Test-Session)) { return } # If the session is still valid, don't create a new one
if (-NOT $Credential) {
try {
$Credential = Get-Secret Graylog_Credential -ErrorAction Stop
} catch {
try {
Write-Host "The Graylog Credential secret is missing, prompting for input..."
$Credential = Get-Credential -Message "Enter your Graylog credentials (the same way as you would via the web service)"
$Credential | Set-Secret Graylog_Credential -ErrorAction Stop
} catch {
throw "Failed to set the Graylog Credential secret: $_"
}
}
}
$Request = @{
Method = "POST"
URI = "$(Get-Secret Graylog_BaseURI -AsPlainText)/api/system/sessions"
Body = ConvertTo-Json @{
host = $BaseURI.Authority
username = $Credential.Username.Split("@")[0]
password = $Credential.GetNetworkCredential().Password
}
ContentType = "application/json"
UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML; like Gecko) Chrome/125.0.0.0 Safari/537.36 Edg/125.0.0.0"
Headers = @{ "X-Requested-By" = "XMLHttpRequest" }
SessionVariable = "GraylogSession"
}
# Use a regular Invoke-RestMethod for the initial sign-in request to avoid any issues with the WebSession
try { $null = Invoke-RestMethod @Request }
catch { throw $_ }
$GraylogSession | ConvertFrom-GraylogSession | Set-Secret Graylog_Session
}
# Export-ModuleMember -Function Connect-Graylog

View File

@ -0,0 +1,56 @@
function ConvertFrom-GraylogSession {
<#
.SYNOPSIS
Converts a WebRequestSession object to a JSON string.
.DESCRIPTION
Converts a WebRequestSession object to a JSON string.
.PARAMETER InputObject
The WebRequestSession object to convert to a JSON string.
.OUTPUTS
A JSON string containing the properties of the WebRequestSession object.
.EXAMPLE
ConvertFrom-Session -WebSession $global:GraylogSession
Converts the WebRequestSession object to a JSON string.
.EXAMPLE
$global:GraylogSession | ConvertFrom-Session
Converts the WebRequestSession object to a JSON string.
#>
param (
[Parameter(Mandatory, ValueFromPipeline)]
[Microsoft.PowerShell.Commands.WebRequestSession]
$InputObject
)
try { $local:Graylog_BaseURI = Get-Secret Graylog_BaseURI -AsPlainText }
catch { Initialize-ServiceVault }
# $Output = @{
# Headers = $InputObject.Headers
# Cookies = [Collections.Generic.List[PSCustomObject]]::new()
# UseDefaultCredentials = $InputObject.UseDefaultCredentials
# Credentials = $InputObject.Credentials
# Certificates = $InputObject.Certificates
# UserAgent = $InputObject.UserAgent
# Proxy = $InputObject.Proxy
# MaximumRedirection = $InputObject.MaximumRedirection
# MaximumRetryCount = $InputObject.MaximumRetryCount
# RetryIntervalInSeconds = $InputObject.RetryIntervalInSeconds
# }
$Output = $InputObject
if ($InputObject.Cookies.Count) {
# GetAllCookies is only available in PowerShell Core :c
$InputObject.Cookies.GetCookies($local:Graylog_BaseURI) | ForEach-Object {
$Output.Cookies.Add(
[PSCustomObject]@{
Name = $_.Name
Value = $_.Value
Domain = $_.Domain
Path = $_.Path
Expires = $_.Expires
Secure = $_.Secure
HttpOnly = $_.HttpOnly
})
}
}
return ConvertTo-Json $Output
}

View File

@ -0,0 +1,52 @@
function ConvertTo-GraylogSession {
<#
.SYNOPSIS
Converts a JSON string to a WebRequestSession object.
.DESCRIPTION
Converts a JSON string to a WebRequestSession object.
.PARAMETER InputObject
The JSON string to convert to a WebRequestSession object.
.OUTPUTS
A WebRequestSession object containing the properties from the JSON string.
.EXAMPLE
ConvertTo-Session -InputObject $Json
Converts the JSON string to a WebRequestSession object.
.EXAMPLE
$Json | ConvertTo-Session
Converts the JSON string to a WebRequestSession object.
.NOTES
This function is used to convert a JSON string to a WebRequestSession object.
#>
param (
[Parameter(Mandatory, ValueFromPipeline)]
[string]
$InputObject
)
$Object = ConvertFrom-Json $InputObject
$Session = [Microsoft.PowerShell.Commands.WebRequestSession]::new()
$Object.Headers.PSObject.Properties | ForEach-Object { $Session.Headers.Add($_.Name, $_.Value) }
$Session.UseDefaultCredentials = $Object.UseDefaultCredentials
$Session.Credentials = $Object.Credentials
$Session.Certificates = $Object.Certificates
$Session.UserAgent = $Object.UserAgent
$Session.Proxy = $Object.Proxy
$Session.MaximumRedirection = $Object.MaximumRedirection
try { $Session.MaximumRetryCount = $Object.MaximumRetryCount } catch {} # MaximumRetryCount is only available in PowerShell Core
try { $Session.RetryIntervalInSeconds = $Object.RetryIntervalInSeconds } catch {} # RetryIntervalInSeconds is only available in PowerShell Core
if ($Object.Cookies) {
$Object.Cookies | ForEach-Object {
$Cookie = [Net.Cookie]::new()
$Cookie.Name = $_.Name
$Cookie.Value = $_.Value
$Cookie.Domain = $_.Domain
$Cookie.Path = $_.Path
$Cookie.Expires = $_.Expires
$Cookie.Secure = $_.Secure
$Cookie.HttpOnly = $_.HttpOnly
$Session.Cookies.Add($Cookie)
}
}
return $Session
}

View File

@ -0,0 +1,26 @@
function Disconnect-GraylogService {
<#
.SYNOPSIS
Disconnects from the Graylog server.
.DESCRIPTION
Disconnects from the Graylog server by deleting the session using the current WebSession data. By default, the stored credentials are not removed.
.PARAMETER Force
An optional switch to force the removal of the stored credentials as well as the session.
.OUTPUTS
None
.EXAMPLE
Disconnect-GraylogService
Disconnects from the Graylog server.
.NOTES
Garbage collection is called after the session is deleted to ensure that the session is removed from memory.
#>
[Alias("Disconnect-Graylog")]
param (
[Parameter()]
[Switch]
$Force
)
Invoke-GraylogRequest DELETE "/api/system/sessions"
Remove-Secret Graylog_Session
if ($Force) { Remove-Secret Graylog_Credential }
}

View File

@ -0,0 +1,31 @@
function Get-GraylogStreamId {
<#
.SYNOPSIS
Gets the ID of a log stream in Graylog.
.DESCRIPTION
Gets the ID of a log stream in Graylog using the provided log name.
.PARAMETER LogName
The name of the log stream to get the ID for, the log name has to be an exact match for a known log stream.
.OUTPUTS
The ID of the log stream if it exists, otherwise null.
.EXAMPLE
Get-GraylogStreamId -LogName "Windows Security"
Gets the ID of the log stream with the name "Windows Security" (645b6fdd9d3689589cdce1bc).
#>
param (
[Parameter(Mandatory)]
[ValidateSet("Infoblox", "Infoblox DNS", "Windows Application", "Windows Security", "Windows System")]
[string]
$LogName
)
# TODO: Use Secret Management module to get the Graylog API URI
if ($null -eq $global:GraylogStreams) {
$Response = Invoke-GraylogRequest GET "/streams"
$global:GraylogStreams = $Response.Streams
}
$Stream = $global:GraylogStreams.Where{$_.Title -eq $LogName}
if ($null -eq $Stream) { return $null }
return $Stream.Id
}

View File

@ -0,0 +1,41 @@
function Initialize-GraylogServiceVault {
try {
$null = Get-SecretVault "Graylog" -ErrorAction Stop
} catch {
try {
$null = Register-SecretVault "Graylog" -ModuleName "Microsoft.PowerShell.SecretStore" -ErrorAction Stop
} catch {
throw "Failed to create the Graylog secret vault: $_"
}
}
try {
$null = Get-Secret Graylog_BaseURI -ErrorAction Stop
} catch {
try {
do {
Write-Host "The Graylog Base URI secret is missing, prompting for input..."
$local:Graylog_Host = [string](Read-Host -Prompt "Enter Graylog Host (e.g. graylog.example.com)")
$local:Graylog_Port = [int](Read-Host -Prompt "Enter Graylog Port (e.g. 80, 443, 9000, etc)")
$local:Graylog_IsHTTPS = [bool]$Host.UI.PromptForChoice("Graylog Base URI - Is the application served over HTTPS?", "(Is there a lock symbol when you visit the app?)", @("&No", "&Yes"), 0)
$local:Graylog_Protocol = if ($local:Graylog_IsHTTPS) { "https" } else { "http" }
$local:Graylog_BaseURI = "${local:Graylog_Protocol}://${local:Graylog_Host}:${local:Graylog_Port}"
$local:Graylog_IsBaseURICorrect = [bool]$Host.UI.PromptForChoice("Graylog Base URI - Is the following URI correct?", $local:Graylog_BaseURI, @("&No", "&Yes"), 0)
} while (-NOT $local:Graylog_IsBaseURICorrect)
$null = $local:Graylog_BaseURI | Set-Secret Graylog_BaseURI -ErrorAction Stop
} catch {
throw "Failed to set the Graylog Base URI secret: $_"
}
}
try {
$null = Get-Secret Graylog_Credential -ErrorAction Stop
} catch {
try {
Write-Host "The Graylog Credential secret is missing, prompting for input..."
Get-Credential -Message "Enter your Graylog credentials (the same way as you would via the web service)" | Set-Secret Graylog_Credential -ErrorAction Stop
} catch {
throw "Failed to set the Graylog Credential secret: $_"
}
}
}

View File

@ -0,0 +1,61 @@
function Invoke-GraylogRequest {
<#
.SYNOPSIS
Invokes a request to the Graylog API.
.DESCRIPTION
Invokes a request to the Graylog API using the provided parameters and HTTP method.
.PARAMETER Method
The HTTP method to use for the request (default: GET, available: DELETE, GET, HEAD, OPTIONS, POST, PUT, PATCH).
.PARAMETER Path
The path to the API endpoint to invoke the request to.
.PARAMETER Body
The (optional) body of the request to send to the API endpoint, which should be provided as a JSON string (or eqivalent object for other formats).
.PARAMETER ContentType
The content type of the request body (default: application/json).
.OUTPUTS
The response from the Graylog API.
.EXAMPLE
Invoke-GraylogRequest GET "/api/system/sessions"
.EXAMPLE
Invoke-GraylogRestRequest -Method GET -Path "/api/system/sessions"
Invokes a GET request to the /api/system/sessions endpoint in the Graylog API using the global WebSession object.
.EXAMPLE
Invoke-GraylogRestRequest -Method POST -Path "/api/system/sessions" -Body @{
host = $BaseURI.Authority
username = $Credential.Username.Split("@")[0]
password = $Credential.GetNetworkCredential().Password
}
Invokes a POST request to the /api/system/sessions endpoint in the Graylog API using the global WebSession object and the provided body.
.NOTES
This function is used to invoke requests to the Graylog API using the provided parameters.
The Method, Path, and WebSession parameters are required, while the Body, ContentType, Headers, and UserAgent parameters are optional.
#>
[Alias("igsr")]
param (
[Parameter(Mandatory)]
[ValidateSet("DELETE", "GET", "HEAD", "OPTIONS", "POST", "PUT", "PATCH")]
[string]
$Method,
[Parameter(Mandatory)]
[string]
$Path,
[Parameter()]
[string]
$Body,
[Parameter()]
[string]
$ContentType = "application/json"
)
$Session = Get-Secret Graylog_Session Graylog -AsPlainText -ErrorAction Stop
$Request = @{
Method = $Method
URI = "$(Get-Secret Graylog_BaseURI -AsPlainText)/api/$($Path.TrimStart('/api'))"
WebSession = (ConvertTo-GraylogSession $Session)
ContentType = $ContentType
}
if ($Body) { $Request.Body = $Body }
Invoke-RestMethod @Request
}

View File

@ -0,0 +1,58 @@
function Receive-GraylogSearchJob {
<#
.SYNOPSIS
Retrieves the results of a search job in Graylog.
.DESCRIPTION
Retrieves the results of a search job in Graylog using the provided SearchId, QueryId, and Filter
Alternatively, a PSCustomObject containing the SearchId, QueryId, and FilterId can be provided to retrieve the results.
.PARAMETER Job
A PSCustomObject containing the SearchId, QueryId, and FilterId of the search job. This parameter cannot be used with the other *Id parameters.
.PARAMETER SearchId
The ID of the search job to retrieve the results for.
.PARAMETER QueryId
The ID of the query to retrieve the results for.
.PARAMETER FilterId
The ID of the filter to retrieve the results for.
.OUTPUTS
The results of the search job.
.EXAMPLE
Receive-GraylogSearchJob -Job $Job
Retrieves the results of the search job using the provided PSCustomObject containing the SearchId, QueryId, and FilterId.
.EXAMPLE
Receive-GraylogSearchJob -SearchId "..." -QueryId "..." -FilterId ".."
Retrieves the results of the search job with the provided SearchId, QueryId, and FilterId.
.NOTES
The SearchId, QueryId, and FilterId are used to retrieve the results of the search job using the Receive-GraylogJob function.
These can either be provided as the Job parameter, or as individual parameters.
#>
param (
[Parameter(Mandatory, ParameterSetName="ByPSCustomObject", ValueFromPipeline, ValueFromRemainingArguments)]
[PSCustomObject]
$Job,
[Parameter(Mandatory={-NOT $Job}, ParameterSetName="ById")]
[string]
$SearchId,
[Parameter(Mandatory={-NOT $Job}, ParameterSetName="ById")]
[string]
$QueryId,
[Parameter(Mandatory={-NOT $Job}, ParameterSetName="ById")]
[string]
$FilterId
)
if ($PSCmdlet.ParameterSetName -eq "ByPSCustomObject") {
$SearchId = $Job.SearchId
$QueryId = $Job.QueryId
$FilterId = $Job.FilterId
}
$Body = ConvertTo-Json @{
global_override = @{ keep_queries = @($QueryId) }
parameter_bindings = @{}
}
$Response = Invoke-GraylogRequest POST "/views/search/$SearchId/execute" $Body
$Data = $Response.results.$QueryId.search_types.$FilterId
if ($Data.total_results -eq 0) { throw "No results found for the search job '$SearchId'." }
return $Data.messages.message
}

View File

@ -0,0 +1,151 @@
function Search-Graylog {
<#
.SYNOPSIS
Queries Graylog for log data using the provided query and log stream name.
.DESCRIPTION
Query Graylog for log data using the provided query and log stream name. The query should contain the key:value pairs to search for, and the key should be the CASE-SENSITIVE field name to search within.
.PARAMETER Query
The search query to execute, should contain the key:value pairs to search for.
Example: "EventID:4740 && TargetUserName:ab123456" will search for all account lockouts for the user ab123456.
(Note that the LogId would need to be changed to the unique identifier for the Active Directory log stream in the above example)
.PARAMETER TimeSpan
The time span to search within, defaults to 7 days.
.PARAMETER LogName
The name of the log stream to search within, defaults to "Windows Security".
.PARAMETER Limit
The maximum number of results to return, defaults to 150.
.PARAMETER SortField
The field to sort the results by, defaults to "timestamp".
.PARAMETER SortOrder
The order to sort the results by, defaults to "desc".
.PARAMETER AsJob
An optional switch to run the search job as a background job.
.PARAMETER Detailed
An optional switch to return the search job details instead of the results (only does anything when -AsJob is not used).
.OUTPUTS
A PSCustomObject containing the SearchId, QueryId, and FilterId of the search job.
.EXAMPLE
Start-GraylogJob -Query "EventID:4740 && TargetUserName:ab123456"
Starts a search job for all account lockouts for the user ab123456.
.NOTES
A identifier for various parts of the search job (SearchId, QueryId, FilterId) are generated and returned in a PSCustomObject, which can be used to retrieve the results of the search job.
The SearchId, QueryId, and FilterId are used to retrieve the results of the search job using the Receive-GraylogJob function.
#>
[Alias("Search-Graylog")]
param (
[Parameter(Mandatory)]
[ValidateNotNullOrEmpty()]
[string]
$Query,
[Parameter()]
[TimeSpan]
$TimeSpan = [TimeSpan]::FromDays(7),
[Parameter()]
[ValidateSet("Infoblox", "Infoblox DNS", "Windows Application", "Windows Security", "Windows System")]
[string]
$LogName = "Windows Security",
[Parameter()]
[int]
$Limit = 150,
[Parameter()]
[string]
$SortField = "timestamp",
[Parameter()]
[ValidateSet("desc", "asc")]
[string]
$SortOrder = "desc",
[Parameter()]
[switch]
$AsJob,
[Parameter()]
[switch]
$Detailed
)
$LogId = Get-GraylogLogStreamId -LogName $LogName
if ($null -eq $LogId) { throw "The log stream '$LogName' does not exist." }
$SearchId = [String]::Join('', [GUID]::NewGUID().GUID.Replace("-", "")[0..23]) # Generate a unique identifier for the search
$QueryId = [GUID]::NewGUID().GUID.ToString() # Generate a unique identifier for the query
$FilterId = [GUID]::NewGUID().GUID.ToString() # Generate a unique identifier for the filter
$Request = @{
Method = "POST"
Path = "/views/search"
Body = ConvertTo-JSON -Depth 7 @{
id = $SearchId
queries = @(
@{
id = $QueryId
query = @{
type = "elasticsearch"
query_string = $Query
}
timerange = @{
type = "relative"
from = $TimeSpan.TotalSeconds
}
filter = @{
type = "or"
filters = @(@{
type = "stream"
id = $LogId
})
}
filters = @()
search_types = @(@{
id = $FilterId
query = $null
timerange = $null
offset = 0
streams = @()
decorators = @()
type = "messages"
limit = $Limit
filters = @()
sort = @(@{
field = $SortField.ToLower()
order = $SortOrder.ToUpper()
})
})
}
)
parameters = @()
}
}
$QuerySuccess = $true
try { $null = Invoke-GraylogRequest @Request }
catch { $QuerySuccess = $false }
if ($AsJob) {
return [PSCustomObject]@{
Success = $QuerySuccess
SearchId = $SearchId
QueryId = $QueryId
FilterId = $FilterId
Request = $Request
}
} else {
$RetrievalSuccess = $true
try { $Data = Receive-GraylogSearchJob -SearchId $SearchId -QueryId $QueryId -FilterId $FilterId }
catch { $RetrievalSuccess = $false }
if (-NOT $Detailed) { return $Data }
else {
return [PSCustomObject]@{
QuerySuccess = $QuerySuccess
RetrievalSuccess = $RetrievalSuccess
Data = $Data
SearchId = $SearchId
QueryId = $QueryId
FilterId = $FilterId
Request = $Request
}
}
}
}

View File

@ -0,0 +1,45 @@
function Test-GraylogSession {
<#
.SYNOPSIS
Tests the current session to the Graylog server.
.DESCRIPTION
Tests the current session to the Graylog server to ensure that it is still valid.
.PARAMETER SkipSecretCheck
An optional switch to skip the check for the required secrets.
.PARAMETER SkipSessionCheck
An optional switch to skip the check for the session secret.
.OUTPUTS
True if the session is valid, otherwise false.
.EXAMPLE
Test-GraylogSession
Tests the current session to the Graylog server.
.NOTES
This function is used to test the current session to the Graylog server to ensure that it is still valid.
#>
param (
[Parameter()]
[Switch]
$SkipSecretCheck,
[Parameter()]
[Switch]
$SkipSessionCheck
)
if (-NOT $SkipSecretCheck) {
try { $null = Get-Secret Graylog_BaseURI -ErrorAction Stop }
catch { Write-Error "The Graylog BaseURI secret is missing, try running Initialize-GraylogServiceVault?"; return $false }
try { $null = Get-Secret Graylog_Credential -ErrorAction Stop }
catch { Write-Error "The Graylog Credential secret is missing, try running Initialize-GraylogServiceVault?"; return $false }
try { $null = Get-Secret Graylog_Session -ErrorAction Stop }
catch { Write-Error "The Graylog Session secret is missing, try running Connect-GraylogService?"; return $false }
if ($SkipSessionCheck) { return $true }
}
if (-NOT $SkipSessionCheck) {
try { return (Invoke-GraylogRequest GET "/system/sessions").is_valid }
catch { return $false }
}
throw "-SkipSecretCheck and -SkipSessionCheck are mutually exclusive."
}

149
PSGraylog.psd1 Normal file
View File

@ -0,0 +1,149 @@
#
# Module manifest for module 'PSGraylog'
#
# Generated by: Nathan Windisch <n@wnd.sh>
#
# Generated on: 2024-07-24
#
@{
# Script module or binary module file associated with this manifest.
RootModule = 'PSGraylog.psm1'
# Version number of this module.
ModuleVersion = '0.0.1'
# Supported PSEditions
# CompatiblePSEditions = @()
# ID used to uniquely identify this module
GUID = 'a145661b-ef85-4b71-8fa3-cafbb7e210a5'
# Author of this module
Author = 'Nathan Windisch <n@wnd.sh>'
# Company or vendor of this module
CompanyName = 'wnd.sh'
# Copyright statement for this module
Copyright = '(c) Nathan Windisch <n@wnd.sh>. All rights reserved.'
# Description of the functionality provided by this module
Description = 'A PowerShell interface for Graylog'
# Minimum version of the PowerShell engine required by this module
PowerShellVersion = '5.1'
# Name of the PowerShell host required by this module
# PowerShellHostName = ''
# Minimum version of the PowerShell host required by this module
# PowerShellHostVersion = ''
# Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only.
# DotNetFrameworkVersion = ''
# Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only.
# ClrVersion = ''
# Processor architecture (None, X86, Amd64) required by this module
# ProcessorArchitecture = ''
# Modules that must be imported into the global environment prior to importing this module
RequiredModules = @("Microsoft.PowerShell.SecretManagement", "Microsoft.PowerShell.SecretStore")
# Assemblies that must be loaded prior to importing this module
# RequiredAssemblies = @()
# Script files (.ps1) that are run in the caller's environment prior to importing this module.
# ScriptsToProcess = @()
# Type files (.ps1xml) to be loaded when importing this module
# TypesToProcess = @()
# Format files (.ps1xml) to be loaded when importing this module
# FormatsToProcess = @()
# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess
NestedModules = @(
"Functions\Connect-GraylogService.ps1",
"Functions\Disconnect-GraylogService.ps1",
"Functions\Get-GraylogStreamId.ps1",
"Functions\Initialize-GraylogServiceVault.ps1",
"Functions\Invoke-GraylogRequest.ps1",
"Functions\Receive-GraylogSearchJob.ps1",
"Functions\Search-Graylog.ps1",
"Functions\Test-GraylogSession.ps1",
"Functions\ConvertFrom-GraylogSession.ps1",
"Functions\ConvertTo-GraylogSession.ps1"
)
# Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export.
FunctionsToExport = @(
"Connect-GraylogService",
"Disconnect-GraylogService",
"Get-GraylogStreamId",
"Initialize-GraylogServiceVault",
"Invoke-GraylogRequest",
"Receive-GraylogSearchJob",
"Search-Graylog",
"Test-GraylogSession",
"ConvertFrom-GraylogSession",
"ConvertTo-GraylogSession"
)
# Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export.
CmdletsToExport = @()
# Variables to export from this module
VariablesToExport = @()
# Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export.
AliasesToExport = @("igsr", "Connect-Graylog", "Disconnect-Graylog")
# DSC resources to export from this module
# DscResourcesToExport = @()
# List of all modules packaged with this module
# ModuleList = @()
# List of all files packaged with this module
# FileList = @()
# Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell.
PrivateData = @{
PSData = @{
# Tags applied to this module. These help with module discovery in online galleries.
# Tags = @()
# A URL to the license for this module.
# LicenseUri = ''
# A URL to the main website for this project.
# ProjectUri = ''
# A URL to an icon representing this module.
# IconUri = ''
# ReleaseNotes of this module
# ReleaseNotes = ''
# Prerelease string of this module
# Prerelease = ''
# Flag to indicate whether the module requires explicit user acceptance for install/update/save
# RequireLicenseAcceptance = $false
# External dependent modules of this module
# ExternalModuleDependencies = @()
} # End of PSData hashtable
} # End of PrivateData hashtable
# HelpInfo URI of this module
# HelpInfoURI = ''
# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix.
# DefaultCommandPrefix = ""
}

2
PSGraylog.psm1 Normal file
View File

@ -0,0 +1,2 @@
Import-Module "$PSScriptRoot/Functions/Initialize-GraylogServiceVault.ps1"
$null = Initialize-GraylogServiceVault

28
README.md Normal file
View File

@ -0,0 +1,28 @@
# PSGraylog
*A PowerShell interface for Graylog*
# Getting Started
1. First, install and import the module from your local PSGallery repo.
You should be prompted to set up your Graylog host, and your credentials.
(You can always re-run this with `Initialize-GraylogServiceVault`)
```pwsh
TODO: How to install from a repo
Install-Module PSGraylog
Import-Module PSGraylog
```
2. Then, connect to Graylog.
```pwsh
Connect-GraylogService
```
3. Finally, run a query (the default for the -LogName parameter is 'Windows Security', which is (in my environment, anyways) Active Directory logs):
```pwsh
$Query = "EventID:4740 && TargetUsername:ab123456"
Search-Graylog $Query
```
4. If you want to re-use the data, you can use the -AsJob parameter to return a GraylogSearchJob object.
This object contains various identifers used to locate the search query, and is much quicker then
re-running the query.
```pwsh
$Job = Search-Graylog $Query -AsJob
$Job | Receive-GraylogSearchJob
```