# 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: # 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:: accountid::" } } # 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 }