14 - Playbook Reproducción en Otro PC (para agente IA)
Propósito: playbook autocontenido que un agente IA (u operador humano) puede seguir para reproducir exactamente el mismo setup de monitorización Splunk en otro PC Windows 11 con Splunk Enterprise ya instalado localmente.
Prerequisites del PC destino:
- Windows 10/11 x64
- Splunk Enterprise ya instalado y corriendo (
Splunkdservice, puerto 8000 web)- PowerShell 5.1+
wingetdisponible- Acceso a administrador local (para UAC)
- Acceso a Internet (para descargar UF, Sysmon config y apps)
- Splunk admin credentials para REST API (verificar antes)
Tiempo estimado: 30-45 minutos (con descargas). Resultado: UF instalado + 14 índices
win_*+ Sysmon con SwiftOnSecurity + TA-Windows + CIM + SSE + hardening logging + artefactos persistidos.
Arquitectura objetivo
+----------------------------+ +-----------------------------------+
| PC destino (Windows) | | Splunk Enterprise (local) |
| | | |
| Sysmon64 + SwiftOnSec | | Indexer + Web UI (8000) |
| WinEventLog (Security, | | Mgmt (8089) |
| PowerShell, Defender, | | Receiving (9997) |
| Sysmon, WMI, RDP, ...) | | |
| Perfmon (CPU/Mem/Net/Dsk) | | Apps: |
| FIM (hosts/lmhosts/GPO) | | - SOC-Windows-Local (índices) |
| | | | - Splunk_TA_windows (parseo CIM)|
| v | TCP | - Splunk_SA_CIM (datamodels) |
| Splunk Universal Forwarder|------->| - Splunk_Security_Essentials |
| (inputs.conf + outputs) | 9997 | |
+----------------------------+ +-----------------------------------+
FASE 0 — Verificación de prerequisitos
0.1 Confirmar Splunk Enterprise corriendo
# (NO admin)
Get-Service Splunkd | Format-Table Name,Status,StartType
foreach ($p in 8000,8089) {
$t = Test-NetConnection -ComputerName 127.0.0.1 -Port $p -WarningAction SilentlyContinue
"Puerto $p : $($t.TcpTestSucceeded)"
}Esperado: Splunkd Running, puertos 8000 y 8089 True.
Si no → abortar: el indexer no está listo.
0.2 Confirmar winget
winget --version
winget search Splunk.UniversalForwarder | Select-Object -First 5Esperado: versión de winget + línea con Splunk.UniversalForwarder 10.x.x.
0.3 Verificar credenciales Splunk admin
Necesitas usuario + password de Splunk Web (http://127.0.0.1:8000). El agente debe pedirlo al usuario.
0.4 Preparar carpeta de trabajo
$base = "$env:TEMP\opencode\SplunkUF_Install"
New-Item -ItemType Directory -Path $base -Force | Out-NullFASE 1 — Generar artefactos de configuración
Crear en $base estos 3 archivos (copiar literal):
1.1 outputs.conf
[tcpout]
defaultGroup = default-autolb-group
useACK = true
heartbeatFrequency = 30
maxQueueSize = 500KB
[tcpout:default-autolb-group]
server = 127.0.0.1:9997⚠ CRÍTICO:
useACKcon K mayúscula.useAckprovocaInvalid keyy aborta el arranque. Ver 08 - Troubleshooting > 4. useACK-case-sensitive.
Si el indexer NO está en localhost, cambiar
127.0.0.1:9997por<ip_indexer>:9997.
1.2 inputs.conf
## ===========================================================
## inputs.conf - Splunk Universal Forwarder (PC local analista SOC)
## Ruta destino: $SPLUNK_HOME\etc\apps\SOC-Windows-Local\local\inputs.conf
## ===========================================================
[default]
host = <HOSTNAME_DEL_PC_DESTINO>
## --- Windows Event Logs criticos para SOC -------------------------------
[WinEventLog://Security]
disabled = 0
index = win_security
renderXml = true
checkpointInterval = 5
start_from = oldest
current_only = 0
evt_resolve_ad_obj = 0
[WinEventLog://System]
disabled = 0
index = win_system
renderXml = true
evt_resolve_ad_obj = 0
[WinEventLog://Application]
disabled = 0
index = win_app
renderXml = true
evt_resolve_ad_obj = 0
[WinEventLog://Setup]
disabled = 0
index = win_setup
renderXml = true
[WinEventLog://Microsoft-Windows-Sysmon/Operational]
disabled = 0
index = win_sysmon
renderXml = true
checkpointInterval = 5
start_from = oldest
current_only = 0
evt_resolve_ad_obj = 0
[WinEventLog://Microsoft-Windows-PowerShell/Operational]
disabled = 0
index = win_powershell
renderXml = true
evt_resolve_ad_obj = 0
[WinEventLog://Microsoft-Windows-Windows Defender/Operational]
disabled = 0
index = win_defender
renderXml = true
[WinEventLog://Microsoft-Windows-WMI-Activity/Operational]
disabled = 0
index = win_wmi
renderXml = true
[WinEventLog://Microsoft-Windows-TerminalServices-LocalSessionManager/Operational]
disabled = 0
index = win_rdp
renderXml = true
[WinEventLog://Microsoft-Windows-TaskScheduler/Operational]
disabled = 0
index = win_tasks
renderXml = true
[WinEventLog://Microsoft-Windows-PrintService/Admin]
disabled = 0
index = win_print
renderXml = true
## --- Perfmon CPU/Memoria/Red (anomalias y baselines) -------------------
[perfmon://CPU]
interval = 60
counters = % Processor Time; % User Time; % Privileged Time; % Interrupt Time
instances = _Total
index = win_perfmon
disabled = 0
[perfmon://Memory]
interval = 60
counters = Available MBytes; Committed Bytes; % Committed Bytes In Use; Pool Paged Bytes; Pool Nonpaged Bytes
index = win_perfmon
disabled = 0
[perfmon://Network]
interval = 60
object = Network Interface
counters = Bytes Total/sec; Packets/sec; Packets Received Errors; Output Queue Length
instances = *
index = win_perfmon
disabled = 0
[perfmon://LogicalDisk]
interval = 60
counters = % Free Space; Avg. Disk sec/Transfer; Disk Read Bytes/sec; Disk Write Bytes/sec
instances = *
index = win_perfmon
disabled = 0
## --- Endpoint script: estado del UF ------------------------------------
[script://$SPLUNK_HOME\bin\scripts\win-listen.bat]
disabled = 1
interval = 300
index = win_status
sourcetype = script:win-listen
## --- File Integrity Monitoring (rutas criticas) -----------------------
[monitor://C:\Windows\System32\drivers\etc\hosts]
disabled = 0
index = win_fim
[monitor://C:\Windows\System32\drivers\etc\lmhosts]
disabled = 0
index = win_fim
[monitor://C:\Windows\System32\GroupPolicy]
disabled = 0
index = win_fim
recursive = trueCambios respecto al original de este PC:
host = <HOSTNAME_DEL_PC_DESTINO>→ sustituir por el hostname real (obtenible conhostnameo$env:COMPUTERNAME)evt_resolve_ad_obj = 0añadido a todas las stanzas WinEventLog → evita erroresEvtDC::bind (1355)en hosts workgroupwin-listen.batscript stanzadisabled = 1(el script no existe por defecto y genera errorExecProcessor)
Ver detalles en 08 - Troubleshooting.
1.3 (Opcional) reusar artefactos del vault
Si tienes acceso al vault de Obsidian, los archivos inputs.conf, outputs.conf están en:
<VAULT>\Destino\SPLUNK\Monitorizacion PC Local\artefactos\
Copia outputs.conf y inputs.conf a $base, y ajusta:
outputs.conf: IP del indexer si no es localhost.inputs.conf: valor dehost =con el hostname del nuevo PC.
FASE 2 — Script de instalación principal (admin)
Crear $base\install_all.ps1 con este contenido. Se ejecuta como administrador (UAC):
## install_all.ps1 - Instalacion completa UF + Indexer config + Hardening + Sysmon + Apps
#Requires -Version 5.1
$ErrorActionPreference = 'Continue'
$base = "$env:TEMP\opencode\SplunkUF_Install"
$log = Join-Path $base 'install_all.log'
Start-Transcript -Path $log -Force | Out-Null
try {
$splunkHome = 'C:\Program Files\Splunk'
$ufHome = 'C:\Program Files\SplunkUniversalForwarder'
$idxBin = Join-Path $splunkHome 'bin\splunk.exe'
$ufBin = Join-Path $ufHome 'bin\splunk.exe'
$hostName = $env:COMPUTERNAME
function W-Step($m){ Write-Host "`n==== $m ====" -ForegroundColor Cyan }
function Copy-Cfg($src,$dst){
$d = Split-Path $dst -Parent
if (!(Test-Path $d)) { New-Item -ItemType Directory -Path $d -Force | Out-Null }
Copy-Item -LiteralPath $src -Destination $dst -Force
}
## 1. Instalar UF via winget --------------------------------
W-Step '1/12 Instalando Splunk Universal Forwarder (winget)'
$prev = winget list --id Splunk.UniversalForwarder 2>$null
if ($LASTEXITCODE -eq 0 -and $prev -match 'Splunk.UniversalForwarder') {
Write-Host 'UF ya instalado; continuando' -ForegroundColor Yellow
} else {
winget install --exact --id Splunk.UniversalForwarder `
--silent --accept-package-agreements --accept-source-agreements `
--disable-interactivity
}
Start-Sleep -Seconds 5
## 2. outputs.conf en UF ------------------------------------
W-Step '2/12 Copiando outputs.conf a UF/etc/system/local'
Copy-Cfg (Join-Path $base 'outputs.conf') (Join-Path $ufHome 'etc\system\local\outputs.conf')
## 3. App SOC-Windows-Local en UF ---------------------------
W-Step '3/12 Creando app SOC-Windows-Local en UF'
$appUf = Join-Path $ufHome 'etc\apps\SOC-Windows-Local'
New-Item -ItemType Directory -Path $appUf -Force | Out-Null
New-Item -ItemType Directory -Path (Join-Path $appUf 'local') -Force | Out-Null
# Sustituir host en inputs.conf
$inputsContent = Get-Content (Join-Path $base 'inputs.conf') -Raw
$inputsContent = $inputsContent -replace 'host = <HOSTNAME_DEL_PC_DESTINO>', "host = $hostName"
Set-Content -Path (Join-Path $appUf 'local\inputs.conf') -Value $inputsContent -Encoding UTF8
@'
[app]
author = SOC Local
description = Inputs Windows para monitorizacion de PC analista ciberseguridad
version = 1.0.0
'@ | Set-Content -Path (Join-Path $appUf 'app.conf') -Encoding UTF8
## 4. App SOC-Windows-Local en INDEXER -----------------------
W-Step '4/12 Creando app SOC-Windows-Local en Indexer con indexes.conf'
$idxApp = Join-Path $splunkHome 'etc\apps\SOC-Windows-Local'
New-Item -ItemType Directory -Path $idxApp -Force | Out-Null
New-Item -ItemType Directory -Path (Join-Path $idxApp 'local') -Force | Out-Null
New-Item -ItemType Directory -Path (Join-Path $idxApp 'metadata') -Force | Out-Null
$indexes = 'win_security','win_system','win_app','win_setup','win_sysmon',
'win_powershell','win_defender','win_wmi','win_rdp','win_tasks',
'win_print','win_perfmon','win_fim','win_status'
$tpl = @'
[{NAME}]
homePath = $SPLUNK_DB/{NAME}/db
coldPath = $SPLUNK_DB/{NAME}/colddb
thawedPath = $SPLUNK_DB/{NAME}/thaweddb
maxTotalDataSizeMB = 5000
'@
$content = ''
foreach ($i in $indexes) { $content += ($tpl -replace '\{NAME\}',$i) }
Set-Content -Path (Join-Path $idxApp 'local\indexes.conf') -Value $content -Encoding UTF8
@'
[app]
author = SOC Local
description = Indices Windows para monitorizacion de PC analista ciberseguridad
version = 1.0.0
'@ | Set-Content -Path (Join-Path $idxApp 'app.conf') -Encoding UTF8
@'
[]
access = read : [ * ], write : [ admin ]
export = system
'@ | Set-Content -Path (Join-Path $idxApp 'metadata\default.meta') -Encoding UTF8
## 5. Habilitar receiving 9997 en Indexer --------------------
W-Step '5/12 Habilitando splunktcp://9997'
$idxInputs = Join-Path $splunkHome 'etc\system\local\inputs.conf'
$needAdd = $true
if (Test-Path $idxInputs) {
$c = Get-Content $idxInputs -Raw
if ($c -match '\[splunktcp://9997\]') { $needAdd = $false }
}
if ($needAdd) {
$newBlock = "`r`n[splunktcp://9997]`r`n`r`n"
if (Test-Path $idxInputs) { Add-Content -Path $idxInputs -Value $newBlock -Encoding UTF8 }
else { Set-Content -Path $idxInputs -Value $newBlock -Encoding UTF8 }
'Anadido [splunktcp://9997]'
} else { '[splunktcp://9997] ya presente' }
## 6. Hardening logging (PS 4104 + Process Command Line) ---
W-Step '6/12 Hardening logging SOC'
$psP = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell'
New-Item -Path "$psP\ScriptBlockLogging" -Force | Out-Null
Set-ItemProperty -Path "$psP\ScriptBlockLogging" -Name 'EnableScriptBlockLogging' -Value 1 -Type DWord
New-Item -Path "$psP\ModuleLogging" -Force | Out-Null
Set-ItemProperty -Path "$psP\ModuleLogging" -Name 'EnableModuleLogging' -Value 1 -Type DWord
Set-ItemProperty -Path "$psP\ModuleLogging" -Name 'ModuleNames' -Value '*' -Type MultiString
$apc = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\AuditProcessCreation'
New-Item -Path $apc -Force | Out-Null
Set-ItemProperty -Path $apc -Name 'IncludeCommandLine' -Value 1 -Type DWord
auditpol /set /subcategory:"Process Creation" /success:enable /failure:enable | Out-Null
auditpol /set /subcategory:"Logon" /success:enable /failure:enable | Out-Null
auditpol /set /subcategory:"Logoff" /success:enable | Out-Null
auditpol /set /subcategory:"Special Logon" /success:enable | Out-Null
'Politicas y auditpol actualizados'
## 7. Sysmon: instalar o actualizar con SwiftOnSecurity -----
W-Step '7/12 Sysmon + SwiftOnSecurity'
$sysmonDir = 'C:\Sysmon'
if (!(Test-Path $sysmonDir)) { New-Item -ItemType Directory -Path $sysmonDir -Force | Out-Null }
$svc = Get-Service Sysmon64 -ErrorAction SilentlyContinue
# Descargar SwiftOnSecurity
$swiftUrl = 'https://raw.githubusercontent.com/SwiftOnSecurity/sysmon-config/master/sysmonconfig-export.xml'
$swiftPath = Join-Path $sysmonDir 'sysmonconfig-swiftonsecurity.xml'
try {
Invoke-WebRequest -Uri $swiftUrl -OutFile $swiftPath -UseBasicParsing -ErrorAction Stop
} catch {
& curl.exe -L -o $swiftPath $swiftUrl 2>&1 | Out-Null
}
"SwiftOnSecurity descargado: $(Test-Path $swiftPath) ($((Get-Item $swiftPath -ErrorAction SilentlyContinue).Length) bytes)"
# Validar XML
try {
[xml]$xml = Get-Content $swiftPath -Raw
"XML valido, RuleGroups: $($xml.SelectNodes('//RuleGroup').Count)"
} catch {
throw "XML invalido: $($_.Exception.Message)"
}
# Descargar Sysmon si no esta instalado
if (-not $svc) {
W-Step '7b/12 Descargando e instalando Sysmon64'
$sysmonUrl = 'https://download.sysinternals.com/files/Sysmon.zip'
$zipPath = Join-Path $sysmonDir 'Sysmon.zip'
Invoke-WebRequest -Uri $sysmonUrl -OutFile $zipPath -UseBasicParsing
Expand-Archive -Path $zipPath -DestinationPath $sysmonDir -Force
$sysmonExe = Join-Path $sysmonDir 'Sysmon64.exe'
& $sysmonExe -accepteula -i $swiftPath 2>&1 | Out-Host
Start-Sleep -Seconds 3
} else {
# Aplicar config al Sysmon existente
& 'C:\Windows\Sysmon64.exe' -accepteula -c $swiftPath 2>&1 | Out-Host
Start-Sleep -Seconds 3
}
"Sysmon64 status: $((Get-Service Sysmon64 -ErrorAction SilentlyContinue).Status)"
## 8. FIX CRÍTICO: SDDL canal Sysmon -----------------------
W-Step '8/12 Modificar SDDL canal Sysmon (grant Everyone read)'
$newSddl = 'O:BAG:SYD:(A;;0xf0007;;;SY)(A;;0x7;;;BA)(A;;0x1;;;BO)(A;;0x1;;;SO)(A;;0x1;;;S-1-5-32-573)(A;;0x1;;;WD)'
wevtutil set-log 'Microsoft-Windows-Sysmon/Operational' /ca:$newSddl 2>&1 | Out-Null
'SDDL actualizado'
## 9. Verificar apps preinstaladas problematicas ------------
W-Step '9/12 Verificar apps con props.conf invalido'
$apps = Get-ChildItem (Join-Path $splunkHome 'etc\apps') -Directory
foreach ($a in $apps) {
$p = Join-Path $a.FullName 'default\props.conf'
if (Test-Path -LiteralPath $p) {
$lines = Get-Content -LiteralPath $p -ErrorAction SilentlyContinue
# Buscar lineas con EXTRACT-<name> sin '=' despues
$bad = $lines | Where-Object { $_ -match '^\s*EXTRACT-[A-Za-z0-9_\-]+\s+[^=\s]' -and $_ -notmatch '=' }
if ($bad) {
$bak = "$p.bak"
if (Test-Path -LiteralPath $bak) { Remove-Item -LiteralPath $bak -Force }
Move-Item -LiteralPath $p -Destination $bak -Force
"Renombrado (props invalido): $($a.Name)\default\props.conf -> .bak"
}
}
}
## 10. Instalar Splunk_TA_windows --------------------------
W-Step '10/12 Instalar Splunk Add-on for Windows'
$taInstalled = Test-Path (Join-Path $splunkHome 'etc\apps\Splunk_TA_windows')
if (-not $taInstalled) {
# Buscar .spl o .tgz en Downloads
$taFile = Get-ChildItem "$env:USERPROFILE\Downloads" -Filter '*add-on-for-microsoft-windows*' -ErrorAction SilentlyContinue | Select-Object -First 1
if (-not $taFile) {
$taFile = Get-ChildItem "$env:USERPROFILE\Downloads" -Filter '*TA_windows*' -ErrorAction SilentlyContinue | Select-Object -First 1
}
if ($taFile) {
& tar -xzf $taFile.FullName -C (Join-Path $splunkHome 'etc\apps') 2>&1 | Out-Null
"TA-Windows instalado desde: $($taFile.FullName)"
} else {
'WARN: No se encontro Splunk_TA_windows en Downloads. Descargar manualmente de https://splunkbase.splunk.com/app/742'
}
} else { 'TA-Windows ya instalado' }
## 11. Instalar CIM + Splunk Security Essentials ------------
W-Step '11/12 Instalar CIM y Splunk Security Essentials'
# CIM
$cimInstalled = Test-Path (Join-Path $splunkHome 'etc\apps\Splunk_SA_CIM')
if (-not $cimInstalled) {
$cimFile = Get-ChildItem "$env:USERPROFILE\Downloads" -Filter '*common-information-model*' -ErrorAction SilentlyContinue | Select-Object -First 1
if ($cimFile) {
& tar -xzf $cimFile.FullName -C (Join-Path $splunkHome 'etc\apps') 2>&1 | Out-Null
"CIM instalado desde: $($cimFile.FullName)"
} else {
'WARN: No se encontro CIM en Downloads. Descargar manualmente de https://splunkbase.splunk.com/app/1621'
}
} else { 'CIM ya instalado' }
# SSE
$sseInstalled = Test-Path (Join-Path $splunkHome 'etc\apps\Splunk_Security_Essentials')
if (-not $sseInstalled) {
$sseFile = Get-ChildItem "$env:USERPROFILE\Downloads" -Filter '*security-essentials*' -ErrorAction SilentlyContinue | Select-Object -First 1
if ($sseFile) {
# Podria ser .tgz o carpeta extraida
if ($sseFile.PSIsContainer) {
$sseApp = Get-ChildItem $sseFile.FullName -Directory -Filter 'Splunk_Security_Essentials' -ErrorAction SilentlyContinue | Select-Object -First 1
if ($sseApp) {
Copy-Item $sseApp.FullName (Join-Path $splunkHome 'etc\apps\Splunk_Security_Essentials') -Recurse -Force
}
} else {
& tar -xzf $sseFile.FullName -C (Join-Path $splunkHome 'etc\apps') 2>&1 | Out-Null
}
"SSE instalado desde: $($sseFile.FullName)"
} else {
'WARN: No se encontro SSE en Downloads. Descargar manualmente de https://splunkbase.splunk.com/app/3522'
}
} else { 'SSE ya instalado' }
## 12. Restart Indexer + UF ----------------------------------
W-Step '12/12 Restart Indexer y UF'
& $idxBin restart 2>&1 | Out-Host
Start-Sleep -Seconds 15
if (Test-Path $ufBin) { & $ufBin restart 2>&1 | Out-Host }
Start-Sleep -Seconds 5
Get-Service Splunkd,SplunkForwarder | Format-Table Name,Status,StartType -AutoSize
W-Step 'INSTALACION COMPLETA'
Write-Host 'Siguiente: ejecutar verify_install.ps1 (NO admin) para verificar llegada de datos'
} catch {
Write-Host "ERROR: $($_.Exception.Message)" -ForegroundColor Red
Write-Host $_.ScriptStackTrace
} finally { Stop-Transcript | Out-Null }FASE 3 — Script de verificación (NO admin)
Crear $base\verify_install.ps1:
## verify_install.ps1 - Verifica llegada de datos via REST API (NO admin)
[Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}
# Pedir credenciales Splunk
$spUser = Read-Host "Usuario Splunk admin (ej: admin)"
$spPass = Read-Host "Password Splunk" -AsSecureString
$spPass = [Runtime.InteropServices.Marshal]::PtrToStringAuto(
[Runtime.InteropServices.Marshal]::SecureStringToBSTR($spPass))
$auth = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes("${spUser}:${spPass}"))
$h = @{Authorization = ("Basic " + $auth)}
function Invoke-SplunkSearch($spl, $earliest = '-24h') {
$body = "search=" + [Uri]::EscapeDataString("search $spl") +
"&earliest_time=$earliest&latest_time=now&output_mode=json"
Invoke-RestMethod -Uri 'https://127.0.0.1:8089/services/search/jobs/export' `
-Method Post -Headers $h -ContentType 'application/x-www-form-urlencoded' `
-Body $body -TimeoutSec 120
}
# 1. Servicios
Write-Host "`n==== 1. Servicios ====" -ForegroundColor Cyan
Get-Service Splunkd,SplunkForwarder | Format-Table Name,Status -AutoSize
# 2. Puertos
Write-Host "==== 2. Puertos ====" -ForegroundColor Cyan
foreach ($p in 8000,8089,9997) {
$t = Test-NetConnection 127.0.0.1 -Port $p -WarningAction SilentlyContinue
"Puerto $p : $($t.TcpTestSucceeded)"
}
# 3. Apps instaladas
Write-Host "`n==== 3. Apps instaladas ====" -ForegroundColor Cyan
$wc = New-Object System.Net.WebClient
$wc.Headers.Add('Authorization', "Basic $auth")
$r = $wc.DownloadString('https://127.0.0.1:8089/services/apps/local?count=-1')
($r -split "`n") | Select-String '(?i)<title>' | ForEach-Object {
($_.Line -replace '<[^>]+>','').Trim()
} | Where-Object { $_ -match 'Secur|CIM|TA_W|SOC-Windows|Essentials' }
# 4. Llegada por index
Write-Host "`n==== 4. Eventos por index win_* ====" -ForegroundColor Cyan
$q = '| tstats count where index=win_* by index | sort -count'
$res = Invoke-SplunkSearch $q
$res | Format-Table -AutoSize
# 5. Sysmon EIDs
Write-Host "`n==== 5. Sysmon EIDs recibidos ====" -ForegroundColor Cyan
$q = 'index=win_sysmon | stats count by EventID | sort -count'
$res = Invoke-SplunkSearch $q
$res | Format-Table -AutoSize
# 6. Last events
Write-Host "`n==== 6. Ultimos eventos por index ====" -ForegroundColor Cyan
$q = '| tstats latest(_time) as last where index=win_* by index,sourcetype | convert ctime(last) timeformat="%Y-%m-%d %H:%M:%S" | sort -last'
$res = Invoke-SplunkSearch $q
$res | Format-Table -AutoSize
Write-Host "`n==== VERIFICACION COMPLETA ====" -ForegroundColor GreenFASE 4 — Ejecución paso a paso
4.1 Generar artefactos (FASE 1)
En una sesión NO admin de PowerShell:
$base = "$env:TEMP\opencode\SplunkUF_Install"
New-Item -ItemType Directory -Path $base -Force | Out-Null
# Sustituir <HOSTNAME_DEL_PC_DESTINO> en inputs.conf placeholder
# Crear outputs.conf, inputs.conf y install_all.ps1 con el contenido de FASE 1 y 24.2 Descargar apps manualmente (si no están en Downloads)
El agente NO puede descargar de splunkbase (requiere login). El usuario debe descargar:
| App | URL | Guardar como |
|---|---|---|
| Splunk Add-on for Windows | https://splunkbase.splunk.com/app/742 | Downloads\splunk-add-on-for-microsoft-windows_*.spl |
| Splunk CIM | https://splunkbase.splunk.com/app/1621 | Downloads\splunk-common-information-model-*.tgz |
| Splunk Security Essentials | https://splunkbase.splunk.com/app/3522 | Downloads\splunk-security-essentials-*.tgz |
⚠ El script
install_all.ps1busca estos archivos automáticamente enDownloadscon patrones wildcard. Si no los encuentra, continua con WARN.
4.3 Ejecutar instalación (admin)
# (NO admin) Lanzar UAC
Start-Process -FilePath 'powershell.exe' `
-ArgumentList @('-NoProfile','-ExecutionPolicy','Bypass','-File',"$base\install_all.ps1") `
-Verb RunAs -WaitAprobar UAC cuando aparezca.
4.4 Verificar (NO admin)
powershell -NoProfile -ExecutionPolicy Bypass -File "$base\verify_install.ps1"Introducir credenciales Splunk cuando pida. Esperado:
- Servicios
Splunkd+SplunkForwarderRunning - Puertos 8000/8089/9997 True
- Apps:
Splunk_TA_windows,Splunk_SA_CIM,Splunk_Security_Essentials,SOC-Windows-Local win_security,win_sysmon,win_powershellcon count > 0- Sysmon EIDs: 1, 3, 22, 11, 13, 5
- Ultimos timestamps recientes (minutos)
4.5 Activar CIM datamodel acceleration (manual, Splunk Web)
- http://127.0.0.1:8000 → Settings → Data Models
- Activar acceleration en:
AuthenticationEndpoint.ProcessesEndpoint.NetworkSessionsEndpoint.ServicesPerformance
- Summary range: 1 year (o 30 days si disco limitado)
4.6 Persistir artefactos (opcional)
Si el PC destino tiene carpeta de Obsidian:
$vaultArte = '<RUTA_VAULT_OBSIDIAN>\Destino\SPLUNK\Monitorizacion PC Local\artefactos'
if (!(Test-Path $vaultArte)) { New-Item -ItemType Directory -Path $vaultArte -Force | Out-Null }
Get-ChildItem $base -File | Copy-Item -Destination $vaultArte -ForceFASE 5 — Troubleshooting conocido
Si algo falla, consultar 08 - Troubleshooting (aplica los mismos errores). Resumen:
| Error | Causa | Fix |
|---|---|---|
Problem parsing indexes.conf: homePath must be absolute | $SPLUNK_DB expandido por PowerShell | Usar here-string single-quoted: ver FASE 2 sección 4 |
Invalid key ... useAck (value: true) | Case-sensitive, debe ser useACK | outputs.conf: useACK = true (K mayúscula) |
Cannot parse into key-value pair: EXTRACT-src | App preinstalada con props.conf roto (botsv3) | Renombrar default\props.conf a .bak en app culpable |
Could not subscribe to Windows Event Log channel 'Microsoft-Windows-Sysmon/Operational': errorCode=5 | UF no tiene acceso al canal Sysmon (no es SYSTEM) | Modificar SDDL con wevtutil set-log (FASE 2 sección 8) |
EvtDC::bind: Failed to get domain controller name (1355) | Host workgroup, sin AD | Añadir evt_resolve_ad_obj = 0 en stanzas WinEventLog |
win_perfmon = 0 eventos | Error PDH counter en algunos Windows | No crítico, revisar contadores disponibles |
FASE 6 — Post-instalación
6.1 Activar detecciones en SSE
- Abrir Splunk Security Essentials app.
- Showcased Content → MITRE ATT&CK → explorar detecciones.
- “Open in Search” en cada detection para adaptar a
win_*indexes.
6.2 Crear dashboards SOC
Usar queries de 11 - Busquedas SOC y Casos de Uso como base. Save As → Dashboard Panel.
6.3 Configurar alertas
Usar queries de la sección 15 de Busquedas SOC. Save As → Alert con cron y action (email/webhook).
6.4 Documentación
Este playbook + los 13 documentos del vault son toda la base de conocimiento necesaria. El nuevo PC puede copiar la carpeta Destino\SPLUNK\Monitorización PC Local\ completa al suya.
Checklist final
- Splunk Enterprise corriendo (indexer)
- UF instalado y Running
- Puerto 9997 escuchando en indexer
- App
SOC-Windows-Localen UF e indexer - 14 índices
win_*creados - Sysmon con SwiftOnSecurity
- SDDL canal Sysmon modificado (Everyone read)
-
Splunk_TA_windowsinstalado -
Splunk_SA_CIMinstalado -
Splunk_Security_Essentialsinstalado - PowerShell ScriptBlock Logging (4104) activado
- Process Creation audit + CommandLine activado
- Eventos llegando (
verify_install.ps1todos los counts > 0 salvo perfmon/FIM) - CIM datamodels acceleration activada
- Artefactos copiados a carpeta persistente
Notas para el agente IA que reproduzca este playbook
- Leer antes todo el documento y los documentos referenciados del vault (08 - Troubleshooting, Anexo A - inputs.conf, Anexo B - outputs.conf, Anexo C - indexes.conf).
- No asumir credenciales Splunk por defecto — pedirlas al usuario.
- No omitir el paso SDDL (FASE 2 sección 8) — sin él,
win_sysmonqueda en 0 eventos silenciosamente. - No omitir
evt_resolve_ad_obj = 0en hosts workgroup — causa errores 1355 en logs. - Renombrar
props.confinválidos en apps preinstaladas antes de restart Splunkd — si no, Splunkd no arranca. - Validar
useACKcasing antes de copiar outputs.conf —useAckaborta el UF. - Verificar llegada de datos con
verify_install.ps1al final — no asumir que funciona sin confirmar. - Documentar cada paso en log/transcript como se hace en este playbook.
Volver a: 00 - MOC Monitorización PC Local | Ver también: 08 - Troubleshooting | 10 - Artefactos y Scripts | 12 - Apps Complementarias y Post-Instalación