Back to Analyze the record in SBD-SPLUNK01

COURSE 1.5 · CONFIGURATION CHECKLIST

Analyze the record in SBD-SPLUNK01

Secure By Design · Edition 2.0 · 15 October 2026

This is the last of three logging courses: course 1.3 collects the record on SBD-SYSLOG01, course 1.4 protects it on SBD-AUDIT01, and this course analyzes a working copy in SBD-SPLUNK01, then traces one event through all three. SBD-SPLUNK01 is a single Splunk instance: one server holds every Splunk role this network needs. Analysis is a search someone actually runs and an alert someone owns. Linux commands are for the Red Hat Enterprise Linux–family release course 1.2 chose. Retention periods, alert thresholds and alert expirations depend on your environment and policy: the course says what each one is for, and you record the value you chose.

Download the workbook (Word)

Before you start

1. Plan analysis and build SBD-SPLUNK01

About 40 min · Open this lesson

Commands:

# On SBD-SPLUNK01 (Tier 1 SSH session from SBD-ADMIN-SRV01)
cd /srv/media && sha256sum -c --quiet SHA256SUMS-splunk.txt   # expected: no output
dnf repolist --all              # expected: only the sbd-repo01 repositories enabled
chronyc sources -v; chronyc tracking   # ^* one controller, ^+ or ^- the other
realm list                      # sbd.test, kerberos-member, one permitted group
openssl x509 -inform der -in /tmp/sbd-root.cer -noout -fingerprint -sha256   # matches course 1.1's record
firewall-cmd --get-active-zones
firewall-cmd --list-all       # SSH, 8000, and 9997 from their sources only; no 8089 or 8191
logger -t sbd-splunk-proof 'SBD-SPLUNK01 syslog over TLS test'
# On SBD-SYSLOG01 (Tier 1 session): the test message in SBD-SPLUNK01's daily file
Select-String -Path D:\Logs\Syslog\*\*.log -Pattern 'sbd-splunk-proof' | Select-Object -First 1

Verify: The design names what the single instance holds and the VM's allocation, analysis's job, both indexes with their retention and sizing inside the free-space reserve, the roles and who holds them, and the console paths; the media matches its published and transfer hashes; and SBD-SPLUNK01 resolves to 10.0.50.10, lists SBD-REPO01 as its only package source, has a controller selected with a small, stable offset, is joined with one permitted group, trusts the course 1.1 root whose hash matches that course's record, admits only the registered paths, and its test message arrives on the collector.

Evidence: Keep the analysis design (the single instance and its allocation, job, indexes, the retention period you chose and why, sizing with the reserve, roles, ports and console paths), the media hashes with the transfer record, and SBD-SPLUNK01's build record: package sources, chrony output, realm list, the root certificate's hash compared with course 1.1's record, firewall zones, and its first syslog line on the collector.

Notes / result / date:

2. Prepare the host, install Splunk, and bring in the streams

About 45 min · Open this lesson

Commands:

# On SBD-SPLUNK01 (Tier 1 SSH session): the host prepared for Splunk
sudo grubby --update-kernel=ALL --args="transparent_hugepage=never"   # then reboot
cat /sys/kernel/mm/transparent_hugepage/enabled   # expected: always madvise [never]
getenforce; systemctl is-active fapolicyd         # Enforcing; active where the STIG turned it on
sudo fapolicyd-cli --file add /opt/splunk/ --trust-file splunk && sudo fapolicyd-cli --update
stat -c '%U %a %n' /opt/splunk /srv/splunk         # splunk 700
systemctl show Splunkd -p User -p LimitNOFILE -p LimitNPROC -p TasksMax
sudo ausearch -m AVC,USER_AVC,SELINUX_ERR,USER_SELINUX_ERR -ts recent   # expected: <no matches>
# On SBD-SPLUNK01 (Tier 1 SSH session): the first-start decisions, an index, and the TLS port
grep -E '^SPLUNK_(DB|FIPS)' /opt/splunk/etc/splunk-launch.conf
sudo -u splunk /opt/splunk/bin/splunk btool indexes list sbd_wineventlog | grep -E 'frozenTimePeriodInSecs|maxTotalDataSizeMB|enableDataIntegrityControl'
sudo -u splunk /opt/splunk/bin/splunk btool inputs list splunktcp-ssl:9997 --debug
openssl s_client -connect SBD-SPLUNK01.sbd.test:9997 -CAfile /opt/splunk/etc/auth/sbd/sbd-chain.pem </dev/null 2>/dev/null | grep -E 'Verify return code|Protocol'
# On SBD-SYSLOG01 (Tier 1 session): the forwarder's account and connection, and one closed hour
Get-CimInstance Win32_Service -Filter "Name='SplunkForwarder'" | Select-Object StartName, State
Select-String 'C:\Program Files\SplunkUniversalForwarder\var\log\splunk\splunkd.log' -Pattern 'Connected to idx' | Select-Object -Last 1
$start = (Get-Date).Date.AddHours((Get-Date).Hour - 2); $end = $start.AddHours(1)
(Get-WinEvent -FilterHashtable @{LogName='ForwardedEvents'; StartTime=$start; EndTime=$end}).Count
# In Splunk Web (Search), as admin (lesson 3 connects the domain accounts): the same hour, the forwarder's connection, and the stored size
index=sbd_wineventlog earliest=-2h@h latest=-1h@h | stats count
index=_internal source=*metrics.log group=tcpin_connections | stats latest(connectionType) AS type, latest(version) AS version BY hostname, sourceIp
| dbinspect index=sbd_wineventlog index=sbd_syslog | stats sum(sizeOnDiskMB) AS MB BY index

Verify: THP shows [never], SELinux is enforcing with no denials from Splunk, and fapolicyd, where it runs, trusts /opt/splunk; Splunk runs as splunk under systemd with its directories at mode 700 and the recommended process limits; the indexes carry integrity control and the designed retention; Splunk Web answers over HTTPS, TCP 9997 presents the SBD-SPLUNK01 certificate over TLS 1.2, the forwarder runs as NT SERVICE\SplunkForwarder with a TLS connection to the indexer, and a closed hour's count and one event's time match the collector for both streams.

Evidence: Keep the THP, SELinux, and fapolicyd state, the unit's account and limits, the first-start settings and the FIPS decision, the btool listings for the indexes and the receiving port, the TLS handshake result, the forwarder's inputs and outputs files and its service account, the measured daily size, and the count-and-time comparison for both streams.

Notes / result / date:

3. Harden Splunk to the STIG

About 35 min · Open this lesson

Commands:

# On SBD-SPLUNK01 (Tier 1 SSH session): each value, and the file it comes from
sudo -u splunk /opt/splunk/bin/splunk btool web list settings --debug | grep -E 'login_content|sessions.timeout|ui_inactivity_timeout|sslVersions|enableSplunkWebSSL'
sudo -u splunk /opt/splunk/bin/splunk btool server list --debug | grep -E 'sessionTimeout|sslVersions|minFreeSpace'
sudo -u splunk /opt/splunk/bin/splunk btool authentication list --debug | grep -E 'authType|authSettings|host|port|SSLEnabled|bindDN |roleMap|sbd_|minPassword|lockout'
grep -E '^TLS_' /opt/splunk/etc/openldap/ldap.conf
openssl s_client -connect sbd.test:636 -CAfile /opt/splunk/etc/auth/sbd/sbd-chain.pem </dev/null 2>/dev/null | grep -E 'Verify return code|Protocol'
sudo -u splunk /opt/splunk/bin/splunk btool global-banner list --debug
df -m /srv/splunk                                   # minFreeSpace = a quarter of this volume's size
sudo -u splunk /opt/splunk/bin/splunk btool indexes list sbd_syslog | grep enableDataIntegrityControl
sudo -u splunk /opt/splunk/bin/splunk check-integrity -index sbd_wineventlog
stat -c '%U %a %n' /opt/splunk /srv/splunk          # splunk 700
# In Splunk Web (Search), signed in with your sbd_admin account
| rest /services/authentication/users splunk_server=local | table title type roles
index=_audit action="login attempt" earliest=-24h | stats count BY user, info
index=_audit sourcetype=audittrail earliest=-24h | stats count BY action, info

Verify: The login page shows the notice, an idle session ends within 15 minutes, Splunk Web and splunkd accept TLS 1.2 only, and the banner names the system; Splunk reaches the domain controllers over LDAPS with a verified certificate, a domain account from each group signs in with the mapped role, and no Tier 0 account is in either group; [splunk_auth] carries the STIG's password and lockout values and the install-time admin is the one sealed local account; minFreeSpace is a quarter of the index volume, Disk Space is in the health report, and the Monitoring Console is in standalone mode; both indexes have integrity control and pass check-integrity; /opt/splunk and /srv/splunk are splunk's with mode 700; _audit shows the domain sign-ins, the failed sign-in, and the changes; and every STIG item met another way has its reason recorded.

Evidence: Keep the btool listings with the file each value comes from, the LDAPS handshake result, the two groups' membership and the bind account's group list, the account list with types and roles, the sealed-admin record, the minFreeSpace calculation, the health report and Monitoring Console mode, the check-integrity results, the permissions, the _audit results, and the record of STIG items met another way.

Notes / result / date:

4. Build the working searches

About 30 min · Open this lesson

Commands:

# In Splunk Web (Search), signed in as an analyst from SBD-ADMIN-SRV01
| rest /services/authentication/current-context splunk_server=local | table username roles capabilities
| tstats count where index=sbd_* by index, host, sourcetype
index=sbd_wineventlog EventCode=4625 [| inputlookup sbd_tier_admins.csv | fields TargetUserName] | stats count, values(IpAddress) AS sources, latest(_time) AS last BY host, TargetUserName | convert ctime(last)
index=sbd_syslog host=<core> src_ip=* | eval src_vlan="VLAN ".mvindex(split(src_ip, "."), 2) | stats count BY src_vlan, dest_port
(index=sbd_wineventlog "Microsoft-Windows-Time-Service") OR (index=sbd_syslog chronyd) | fillnull value="-" EventCode | stats count, latest(_time) AS last BY host, EventCode | convert ctime(last)
# On SBD-SYSLOG01 (Tier 1 session): course 1.3's subscription carries the Time-Service query
wecutil gs SBD-ForwardedSecurity /f:xml | Select-String 'Time-Service'

Verify: The analyst role searches both indexes and carries no delete capability, every source system appears with the right host and source type, the subscription carries the Time-Service query, and each saved search finds its known test event.

Evidence: Record your role listing, the data-shape table, each saved search with its question, owner, and a result showing its test event, the lookup's source and date, and the subscription's Time-Service query.

Notes / result / date:

5. Own the alerts

About 35 min · Open this lesson

Commands:

# In Splunk Web (Search), as sbd_admin: the alerts as built
| rest /servicesNS/-/-/saved/searches splunk_server=local | search title="SBD - *" is_scheduled=1 | table title cron_schedule dispatch.earliest_time alert.severity alert.suppress.period alert.expires actions
# Each alert's runs and what it triggered, from the scheduler's own log
index=_internal sourcetype=scheduler savedsearch_name="SBD - *" | stats count, sum(result_count) AS results, values(alert_actions) AS actions BY savedsearch_name
# The silent-source alert's search: each expected source's last event against its limit
| inputlookup sbd_expected_sources.csv | join type=left host [| tstats max(_time) AS last where index=sbd_* earliest=-7d by host] | where isnull(last) OR last < relative_time(now(), "-" . max_quiet_minutes . "m")
# The pipeline test, on SBD-SYSLOG01 (Tier 1 session): stop the forwarder past the silence threshold
Stop-Service SplunkForwarder; Start-Sleep -Seconds <silence threshold plus one run interval, in seconds>; Start-Service SplunkForwarder

Verify: Every alert in the register has a recorded threshold, schedule, expiration, severity, responder with deputy, and written first response; each safe condition fired its alert in a test, with the cause and the alert's time recorded; the forwarder stop fired the pipeline alert and its backlog arrived without a gap; and the first daily and weekly reviews are on record.

Evidence: Keep the alert register, the listing of the alerts as built, each test's cause-and-fire record, the seven-day tuning counts with any changes, and the first review records.

Notes / result / date:

6. Prove the chain and hand off

About 35 min · Open this lesson

Commands:

# From AdminJumpBox01 (Tier 0): the test event on its source
Invoke-Command SBD-DC01 { Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4625; StartTime=(Get-Date).AddHours(-1)} | Select-Object TimeCreated, Id, MachineName }
# On SBD-SYSLOG01 (Tier 1 session): the same event on the collector
Get-WinEvent -FilterHashtable @{LogName='ForwardedEvents'; Id=4625; StartTime=(Get-Date).AddHours(-1)} | Select-Object TimeCreated, MachineName
# In Splunk Web (Search), as an analyst: the same event; its alert is in Triggered Alerts
index=sbd_wineventlog host=SBD-DC01* EventCode=4625 earliest=-1h | table _time host TargetUserName
# Next morning, in an auditor's or the custodian's session on SBD-AUDIT01: that UTC day's archive
Get-WinEvent -Path D:\LogArchive\ForwardedEvents\ForwardedEvents-<UTC date>.evtx -FilterXPath '*[System[EventID=4625]]' | Select-Object TimeCreated, MachineName
# On SBD-ADMIN-SRV01: copy course 1.2's Linux assessment set to the host
scp C:\Staging\DISA\linux\<SCC for Linux package> C:\Staging\DISA\linux\<STIG benchmark> <your-account>@SBD-SPLUNK01.sbd.test:/tmp/
# On SBD-SPLUNK01: the same hashes, then SCC's command-line scanner as root (path and options from the SCC readme)
sha256sum /tmp/<SCC for Linux package> /tmp/<STIG benchmark>
sudo <SCC install directory>/cscc
# The version the upgrade procedure starts from
sudo -u splunk /opt/splunk/bin/splunk version
# On SBD-ADMIN-SRV01: collect the session, then hash the course's evidence
New-Item -ItemType Directory -Force C:\Evidence\splunk-analysis\baseline | Out-Null
scp -r <your-account>@SBD-SPLUNK01.sbd.test:<SCC session folder> C:\Evidence\splunk-analysis\baseline\SBD-SPLUNK01
Get-ChildItem C:\Evidence\splunk-analysis -Recurse -File | Get-FileHash -Algorithm SHA256

Verify: The test event appears on SBD-DC01, in ForwardedEvents, in Splunk with its alert fired, and in the next morning's archive with matching catalog hashes, all with the same source time; the probe's deny appears in search two and fired its alert; SBD-SPLUNK01 has its first baseline and a Splunk STIG checklist that answers lesson 3's items and classifies every open one; and the upgrade procedure is written, starting from a version the vendor supports.

Evidence: Keep the four-place trace of the test event with its timestamps and the alert's record, the deny with its alert, SBD-SPLUNK01's scan set and checklist with hashes, the upgrade procedure with the current version, and the handoff note to course 1.6.

Notes / result / date:

Sources