You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

324 lines
11 KiB

# currently must be 'runas' administrator for proper install
Param(
[string]$ReceivingIndexer,
[string]$splunk_home,
[string]$dimensions,
[string]$log_sources_param,
[string]$metrics_param,
[string]$per_cpu,
[string]$metrics_index,
[string]$receiver_port
)
# if splunk_home not provided, use default
if([string]::IsNullOrEmpty($splunk_home)) {
$splunk_home = "$env:programfiles\SplunkUniversalForwarder"
}
if([string]::IsNullOrEmpty($metrics_index)) {
$metrics_index = 'itsi_im_metrics'
}
if([string]::IsNullOrEmpty($receiver_port)) {
$receiver_port = '9997'
}
# URI to download the install file
$insturi = 'https://download.splunk.com/products/universalforwarder/releases/9.0.5/windows/splunkforwarder-9.0.5-e9494146ae5c-x64-release.msi'
# directory for file to be downloaded to:
# currently set to download in the path that the script is in: %TEMP%
$path = Convert-Path .
$outputdir = $path + '\splunkuniversalforwarder.msi'
# file name of .msi installation file
$install_file = 'splunkuniversalforwarder.msi'
# Installation Directory for UniversalForwarder
$installdir = $splunk_home
echo "[*] checking for previous installations of splunk>..."
# checks to see if a splunk folder already exists in Program Files
# will skip installation if it finds a splunk folder
if (Test-Path -Path $installdir -PathType Container)
{
echo "[!] install directory already exists. continuing to configure .."
}else{
echo "[*] downloading splunk> universal forwarder..."
# downloads splunk install file
# this method significantly faster than Invoke-WebRequest
(New-Object System.Net.WebClient).DownloadFile($insturi, $outputdir)
# check if download succeeded
if (-not $?)
{
echo "[!] failed to download splunk> universal forwarder..."
exit 1
}
echo "[*] installing splunk> universal forwarder..."
# uses msi to install splunk forwarder, file names need to match and be co-located
# /quiet suppresses gui, otherwise the script will fail
# additional switches would be needed for an enterprise installation
# testing on whether local user can collect log files (i believe no)
# might need to be installed as a domain user or local admin?
# see: <https://docs.splunk.com/Documentation/Forwarder/6.5.1/Forwarder/InstallaWindowsuniversalforwarderfromthecommandline>
# for supported switches and installation instructions
Start-Process -FilePath msiexec.exe -ArgumentList "/i $install_file INSTALLDIR=`"$installdir`" AGREETOLICENSE=Yes /quiet" -Wait
}
# ********** Configure Outputs.conf file in SplunkUniversalForwarder local Directory ************
if(-Not [string]::IsNullOrEmpty($ReceivingIndexer))
{
# hostname or ip : port of indexer
$indexer = $ReceivingIndexer + ':' + $receiver_port
echo "[*] indexer server: $indexer"
# location of outputs.conf file
$outputsconf = $splunk_home + "\etc\apps\SplunkUniversalForwarder\local\outputs.conf"
echo "[tcpout]" > $outputsconf
echo "defaultGroup = default-autolb-group" >> $outputsconf
echo "" >> $outputsconf
echo "[tcpout:default-autolb-group]" >> $outputsconf
echo "server = $indexer" >> $outputsconf
echo "" >> $outputsconf
}
# ********** Configure Inputs.conf file in SplunkUniversalForwarder local Directory ************
# location of inputs.conf file
$inputconf = $splunk_home + "\etc\apps\SplunkUniversalForwarder\local\inputs.conf"
# check if supported environment variables set, use default if not
# If not set, use the default value
if([string]::IsNullOrEmpty($metrics_param)) {
$metrics_param = "logical_disk,physical_disk,cpu,memory,network,system,process"
}
if([string]::IsNullOrEmpty($log_sources_param)) {
$log_sources_param = "application%WinEventLog,system%WinEventLog,security%WinEventLog"
}
if([string]::IsNullOrEmpty($per_cpu)) {
$per_cpu = "false"
}
# check if cpu metrics collected per cpu or total
if ($env:per_cpu -eq "true") {$cpu_instance_type = '*'}
else {$cpu_instance_type = '_Total'}
# Set instance_id and account_id depending on CLOUD env variable.
if ($env:CLOUD -eq "AWS") {
$instance_id = Invoke-RestMethod -Uri http://169.254.169.254/latest/meta-data/instance-id
$account_id = (Invoke-RestMethod -Uri http://169.254.169.254/latest/meta-data/identity-credentials/ec2/info/).accountId
if ([string]::IsNullOrEmpty($instance_id) -or [string]::IsNullOrEmpty($account_id)) {
echo "Please configure Cloud Type, AWS instance ID and AWS Account ID manually in inputs.conf under the respective log sources and metric stanzas as follows: _meta = cloud::AWS instanceid::<instance_id> accountid::<account_id>"
}
}
# Inputs.conf stanza for the supported metrics
$m_cpu =`
"[perfmon://CPU]`r`n" `
+ "counters = % C1 Time;% C2 Time;% Idle Time;% Processor Time;% User Time;% Privileged Time;% Reserved Time;% Interrupt Time`r`n" `
+ "instances = $cpu_instance_type`r`n" `
+ "interval = 60`r`n" `
+ "object = Processor`r`n" `
+ "mode = single`r`n" `
+ "disabled = 0`r`n" `
+ "useEnglishOnly = true`r`n" `
+ "sourcetype = PerfmonMetrics:CPU`r`n" `
+ "index = $metrics_index"
$m_memory =`
"[perfmon://Memory]`r`n" `
+ "counters = Cache Bytes;% Committed Bytes In Use;Page Reads/sec;Pages Input/sec;Pages Output/sec;Committed Bytes;Available Bytes`r`n" `
+ "interval = 60`r`n" `
+ "object = Memory`r`n" `
+ "mode = single`r`n" `
+ "disabled = 0`r`n" `
+ "useEnglishOnly = true`r`n" `
+ "sourcetype = PerfmonMetrics:Memory`r`n" `
+ "index = $metrics_index"
$m_physical_disk =`
"[perfmon://PhysicalDisk]`r`n" `
+ "counters = % Disk Read Time;% Disk Write Time`r`n" `
+ "instances = *`r`n" `
+ "interval = 60`r`n" `
+ "object = PhysicalDisk`r`n" `
+ "mode = single`r`n" `
+ "disabled = 0`r`n" `
+ "useEnglishOnly = true`r`n" `
+ "sourcetype = PerfmonMetrics:PhysicalDisk`r`n" `
+ "index = $metrics_index"
$m_logical_disk =`
"[perfmon://LogicalDisk]`r`n" `
+ "counters = Free Megabytes;% Free Space`r`n" `
+ "instances = *`r`n" `
+ "interval = 60`r`n" `
+ "object = LogicalDisk`r`n" `
+ "mode = single`r`n" `
+ "disabled = 0`r`n" `
+ "useEnglishOnly = true`r`n" `
+ "sourcetype = PerfmonMetrics:LogicalDisk`r`n" `
+ "index = $metrics_index"
$m_network =`
"[perfmon://Network]`r`n" `
+ "counters = Bytes Received/sec;Bytes Sent/sec;Packets Received/sec;Packets Sent/sec;Packets Received Errors;Packets Outbound Errors`r`n" `
+ "instances = *`r`n" `
+ "interval = 60`r`n" `
+ "mode = single`r`n" `
+ "object = Network Interface`r`n" `
+ "disabled = 0`r`n" `
+ "useEnglishOnly = true`r`n" `
+ "sourcetype = PerfmonMetrics:Network`r`n" `
+ "index = $metrics_index"
$m_system =`
"[perfmon://System]`r`n" `
+ "counters = Processor Queue Length;Threads;System Up Time`r`n" `
+ "instances = *`r`n" `
+ "interval = 60`r`n" `
+ "object = System`r`n" `
+ "mode = single`r`n" `
+ "disabled = 0`r`n" `
+ "useEnglishOnly = true`r`n" `
+ "sourcetype = PerfmonMetrics:System`r`n" `
+ "index = $metrics_index"
$m_process =`
"[perfmon://Process]`r`n" `
+ "counters = % Processor Time;% User Time;% Privileged Time; Elapsed Time; ID Process; Virtual Bytes; Working Set; Private Bytes; IO Read Bytes/sec; IO Write Bytes/sec;`r`n" `
+ "instances = *`r`n" `
+ "interval = 60`r`n" `
+ "object = Process`r`n" `
+ "mode = single`r`n" `
+ "disabled = 0`r`n" `
+ "useEnglishOnly = true`r`n" `
+ "sourcetype = PerfmonMetrics:Process`r`n" `
+ "index = $metrics_index"
# Inputs.conf options for the supported Windows EventLogs
if([string]::IsNullOrEmpty($Env:CLOUD) -or [string]::IsNullOrEmpty($instance_id) -or [string]::IsNullOrEmpty($account_id))
{
$eventlog_options =`
"checkpointInterval = 10`r`n" `
+ "current_only = 0`r`n" `
+ "disabled = 0`r`n" `
+ "start_from = oldest"
}
elseif ($env:CLOUD -eq "AWS") {
$eventlog_options =`
"checkpointInterval = 10`r`n" `
+ "current_only = 0`r`n" `
+ "disabled = 0`r`n" `
+ "start_from = oldest`r`n" `
+ "_meta = cloud::$Env:CLOUD instanceid::$instance_id accountid::$account_id"
}
# extract os & ip info
$os_info = Get-CimInstance Win32_OperatingSystem | Select-Object Caption, Version
$ipv6_addr= (Get-NetIPConfiguration).IPv6Address
$ipv4_addr= (Get-NetIPConfiguration).IPv4Address
# Add OS & ip info as dimension
# If these dimensions are to be updated, user has to rerun this script
$dims = $dimensions + " os::" + "`"" + $os_info.Caption + "`""
$dims = $dims + " os_version::" + $os_info.Version
$dims = $dims + ' entity_type::Windows_Host'
if (![string]::IsNullOrEmpty($ipv4_addr)) {
$ip_info = Test-Connection -ComputerName $env:computername -count 1 | Select-Object IPV4Address
$dims = $dims + " ip::" + "`"" + $ip_info.IPV4Address.IPAddressToString + "`""
}
if (![string]::IsNullOrEmpty($ipv6_addr)) {
$ipv6_info = Get-NetIPAddress -AddressFamily IPv6 -SuffixOrigin Manual | Select-Object IPAddress
$dims = $dims + " ipv6::" + "`"" + $ipv6_info.IPAddress + "`""
}
if($env:CLOUD = "AWS" -and ![string]::IsNullOrEmpty($instance_id) -and ![string]::IsNullOrEmpty($account_id) )
{
$dims = $dims + ' instanceid::"' + $instance_id +'"' + ' accountid::' + $account_id + ' cloud::"' + $env:CLOUD + '"'
}
$metrics = $metrics_param -split ','
$log_sources = $log_sources_param -split ','
echo "[*] configuring metrics & log inputs..."
echo "# *** Configure Metrics & Logs collected ***" > $inputconf
# Add all other perfmon metrics
For ($i=0; $i -lt $metrics.Length; $i++) {
$m_name = "m_" + $metrics[$i]
Get-Variable -Name $m_name -ValueOnly -ErrorAction 'Ignore' >> $inputconf
# Add dimensions
echo "_meta = $dims" >> $inputconf
echo "`n" >> $inputconf
}
# Add other log sources stanza
For ($i=0; $i -lt $log_sources.Length; $i++) {
if([string]::IsNullOrEmpty($log_sources[$i])) { continue }
# split log source into source and sourcetype
$logsource = $log_sources[$i] -split '%'
if ($logsource.Length -ne 2) { continue }
$log_source = $($logsource[0])
$log_sourcetype = $($logsource[1])
if ($log_sourcetype -eq 'WinEventLog') {
#Get-Variable -Name $log_source -ValueOnly -ErrorAction 'Ignore' >> $inputconf
echo "[WinEventLog://$log_source]" >> $inputconf
echo "$eventlog_options" >> $inputconf
echo "`r`n" >> $inputconf
}
else {
echo "[monitor://$log_source]" >> $inputconf
echo "sourcetype = $log_sourcetype" >> $inputconf
echo "disabled = false" >> $inputconf
if ($log_sourcetype -eq 'collectd' -Or $log_sourcetype -eq 'uf') {
echo "index = _internal" >> $inputconf
}
echo "`r`n" >> $inputconf
}
}
# ********** Start Splunk and check if process started *****************
# restart splunk universal forwarder
$splunkexe = $splunk_home + "\bin\splunk.exe"
echo "[*] Restarting splunk> universal forwarder"
& "$splunkexe" restart
# checks to see if splunkd is running which indicates good install
# then adds the necessary lines to input.conf to retrieve powershell logs
$splunk = Get-Process -Name "splunkd" -ErrorAction SilentlyContinue
if ($splunk -ne $null) # confirms if it restarted successfully
{
echo "[*] splunk> successfully started."
echo "[*] running clean up."
if (Test-Path -Path $install_file)
{
Remove-Item $install_file
}
echo "[*] clean up complete. Exiting..."
return
}else{
echo '[!] splunk process not running!'
echo '[!] check to make sure installation was successful.'
return
}