Learn Splunk in 10 DaysDay 10: Final Project
books.chapter 10Learn Splunk in 10 Days

Day 10: Final Project

Today's Goal

Put everything you have learned over the past nine days into practice by building a Security Operations Center (SOC) dashboard.


Project Overview

Item Details
Dashboard name Security Operations Center (SOC)
Features Threat detection, incident response, compliance reporting
Technologies used SPL, dashboards, alerts, lookups, macros
flowchart TB
    subgraph SOC["SOC Dashboard"]
        KPI["KPI Panels<br>Total events & alert count"]
        Timeline["Timeline<br>Event trends"]
        Threat["Threat Detection<br>Anomalous patterns"]
        Detail["Detailed Analysis<br>Drilldown"]
    end
    style KPI fill:#3b82f6,color:#fff
    style Timeline fill:#22c55e,color:#fff
    style Threat fill:#ef4444,color:#fff
    style Detail fill:#f59e0b,color:#fff

Step 1: Prepare Sample Data

Security Log Samples

Set up the following log sources for your SOC dashboard.

firewall.log

2026-01-30 10:00:01 action=allowed src_ip=192.168.1.10 dst_ip=10.0.0.1 dst_port=443 proto=TCP bytes=2048
2026-01-30 10:00:02 action=blocked src_ip=10.10.10.5 dst_ip=192.168.1.100 dst_port=22 proto=TCP bytes=0
2026-01-30 10:00:03 action=allowed src_ip=192.168.1.20 dst_ip=172.16.0.5 dst_port=80 proto=TCP bytes=4096
2026-01-30 10:00:05 action=blocked src_ip=203.0.113.50 dst_ip=192.168.1.100 dst_port=3389 proto=TCP bytes=0
2026-01-30 10:00:10 action=allowed src_ip=192.168.1.30 dst_ip=10.0.0.2 dst_port=53 proto=UDP bytes=128

auth.log

2026-01-30 10:00:01 action=login_success user=alice src_ip=192.168.1.10 method=password
2026-01-30 10:00:05 action=login_failed user=admin src_ip=203.0.113.50 method=password
2026-01-30 10:00:06 action=login_failed user=admin src_ip=203.0.113.50 method=password
2026-01-30 10:00:07 action=login_failed user=admin src_ip=203.0.113.50 method=password
2026-01-30 10:00:10 action=login_success user=bob src_ip=192.168.1.20 method=ssh_key
2026-01-30 10:00:15 action=login_failed user=root src_ip=198.51.100.10 method=password
2026-01-30 10:00:20 action=privilege_escalation user=alice src_ip=192.168.1.10 target=root

web_access.log

192.168.1.10 - alice [30/Jan/2026:10:00:01 +0900] "GET /admin HTTP/1.1" 200 2048
203.0.113.50 - - [30/Jan/2026:10:00:05 +0900] "GET /../../../../etc/passwd HTTP/1.1" 403 128
192.168.1.20 - bob [30/Jan/2026:10:00:10 +0900] "GET /api/users HTTP/1.1" 200 4096
198.51.100.10 - - [30/Jan/2026:10:00:15 +0900] "POST /api/login HTTP/1.1" 401 64
10.10.10.5 - - [30/Jan/2026:10:00:20 +0900] "GET /wp-admin HTTP/1.1" 404 128

Step 2: Lookup Tables

threat_intel.csv (Threat Intelligence)

ip_address,threat_type,severity,description
203.0.113.50,brute_force,high,Known brute force attacker
198.51.100.10,scanner,medium,Network scanner
10.10.10.5,botnet,critical,Botnet C2 server

asset_inventory.csv (Asset Inventory)

ip_address,hostname,department,criticality
192.168.1.10,ws-alice,Engineering,medium
192.168.1.20,ws-bob,Marketing,low
192.168.1.30,ws-charlie,Finance,high
192.168.1.100,srv-web01,IT,critical
10.0.0.1,srv-db01,IT,critical

Step 3: Search Macros

# macros.conf

# Detect threat IPs
[threat_detected]
definition = lookup threat_intel ip_address AS src_ip OUTPUT threat_type, severity, description AS threat_description | where isnotnull(threat_type)

# Classify event severity
[severity_classification]
definition = eval alert_severity=case(severity="critical", 4, severity="high", 3, severity="medium", 2, severity="low", 1, 1=1, 0)

# Detect authentication failures above a threshold
[auth_failures(1)]
args = threshold
definition = index=security sourcetype=auth_log action=login_failed | stats count by src_ip, user | where count >= $threshold$

Step 4: Alert Definitions

Brute Force Detection

index=security sourcetype=auth_log action=login_failed
| bin _time span=5m
| stats count by src_ip, _time
| where count >= 5
| `threat_detected`

Configuration:

  • Schedule: */5 * * * *
  • Trigger: Number of Results > 0
  • Suppress: 30 minutes per src_ip
  • Actions: Email, Slack notification

Malicious Access Attempts

index=web sourcetype=access_combined
| rex field=uri "(?P<attack_pattern>(\.\./|etc/passwd|wp-admin|\.env|\.git))"
| where isnotnull(attack_pattern)
| stats count by clientip, attack_pattern

Step 5: SOC Dashboard

<dashboard theme="dark">
  <label>Security Operations Center</label>
  <description>Security monitoring dashboard</description>

  <fieldset submitButton="false">
    <input type="time" token="time">
      <default>
        <earliest>-24h@h</earliest>
        <latest>now</latest>
      </default>
    </input>
    <input type="dropdown" token="severity_filter">
      <label>Severity</label>
      <choice value="*">All</choice>
      <choice value="critical">Critical</choice>
      <choice value="high">High</choice>
      <choice value="medium">Medium</choice>
      <default>*</default>
    </input>
  </fieldset>

  <!-- KPI row -->
  <row>
    <panel><title>Total Security Events</title>
      <single>
        <search>
          <query>index=security OR index=web | stats count</query>
          <earliest>$time.earliest$</earliest>
          <latest>$time.latest$</latest>
        </search>
        <option name="colorMode">block</option>
        <option name="rangeColors">["0x22c55e","0xf59e0b","0xef4444"]</option>
        <option name="rangeValues">[1000,5000]</option>
        <option name="useColors">true</option>
      </single>
    </panel>
    <panel><title>Threat Detections</title>
      <single>
        <search>
          <query>
            index=security OR index=web
            | `threat_detected`
            | stats dc(src_ip) AS threat_count
          </query>
          <earliest>$time.earliest$</earliest>
          <latest>$time.latest$</latest>
        </search>
        <option name="colorMode">block</option>
        <option name="rangeColors">["0x22c55e","0xef4444"]</option>
        <option name="rangeValues">[0]</option>
        <option name="useColors">true</option>
      </single>
    </panel>
    <panel><title>Failed Logins</title>
      <single>
        <search>
          <query>index=security sourcetype=auth_log action=login_failed | stats count</query>
          <earliest>$time.earliest$</earliest>
          <latest>$time.latest$</latest>
        </search>
      </single>
    </panel>
    <panel><title>Blocked Connections</title>
      <single>
        <search>
          <query>index=security sourcetype=firewall action=blocked | stats count</query>
          <earliest>$time.earliest$</earliest>
          <latest>$time.latest$</latest>
        </search>
      </single>
    </panel>
  </row>

  <!-- Timeline -->
  <row>
    <panel><title>Security Events Timeline</title>
      <chart>
        <search>
          <query>
            index=security OR index=web
            | eval event_type=case(
                action="blocked", "Firewall Block",
                action="login_failed", "Auth Failure",
                status>=400, "Web Error",
                1=1, "Other"
            )
            | timechart span=1h count by event_type
          </query>
          <earliest>$time.earliest$</earliest>
          <latest>$time.latest$</latest>
        </search>
        <option name="charting.chart">area</option>
        <option name="charting.chart.stackMode">stacked</option>
        <option name="charting.legend.placement">bottom</option>
      </chart>
    </panel>
  </row>

  <!-- Threat analysis -->
  <row>
    <panel><title>Threat Intelligence Matches</title>
      <table>
        <search>
          <query>
            index=security OR index=web
            | `threat_detected`
            | stats count, values(action) AS actions, latest(_time) AS last_seen by src_ip, threat_type, severity
            | eval last_seen=strftime(last_seen, "%Y-%m-%d %H:%M:%S")
            | sort -count
          </query>
          <earliest>$time.earliest$</earliest>
          <latest>$time.latest$</latest>
        </search>
        <option name="drilldown">row</option>
        <drilldown>
          <link target="_blank">/app/search/search?q=index%3Dsecurity%20src_ip%3D$row.src_ip$</link>
        </drilldown>
      </table>
    </panel>
    <panel><title>Top Blocked IPs</title>
      <chart>
        <search>
          <query>
            index=security sourcetype=firewall action=blocked
            | stats count by src_ip
            | sort -count
            | head 10
          </query>
          <earliest>$time.earliest$</earliest>
          <latest>$time.latest$</latest>
        </search>
        <option name="charting.chart">bar</option>
      </chart>
    </panel>
  </row>

  <!-- Authentication analysis -->
  <row>
    <panel><title>Authentication Failures by User</title>
      <chart>
        <search>
          <query>
            index=security sourcetype=auth_log action=login_failed
            | stats count by user
            | sort -count
          </query>
          <earliest>$time.earliest$</earliest>
          <latest>$time.latest$</latest>
        </search>
        <option name="charting.chart">pie</option>
      </chart>
    </panel>
    <panel><title>Recent Security Events</title>
      <table>
        <search>
          <query>
            index=security
            | eval severity=case(
                action="privilege_escalation", "critical",
                action="login_failed", "warning",
                action="blocked", "info",
                1=1, "low"
            )
            | table _time, sourcetype, action, user, src_ip, severity
            | sort -_time
            | head 20
          </query>
          <earliest>$time.earliest$</earliest>
          <latest>$time.latest$</latest>
        </search>
      </table>
    </panel>
  </row>
</dashboard>

10-Day Recap

flowchart TB
    D1["Day 1<br>Splunk Basics<br>Architecture"]
    D2["Day 2<br>Data Ingestion<br>inputs.conf"]
    D3["Day 3<br>Search Fundamentals<br>SPL Intro"]
    D4["Day 4<br>Fields &<br>Filtering"]
    D5["Day 5<br>Statistics &<br>Aggregation"]
    D6["Day 6<br>Data Visualization<br>Dashboards"]
    D7["Day 7<br>Advanced Search<br>lookup/join"]
    D8["Day 8<br>Alerts &<br>Reports"]
    D9["Day 9<br>Splunk Admin<br>Roles/Apps"]
    D10["Day 10<br>Final Project"]
    D1 --> D2 --> D3 --> D4 --> D5
    D5 --> D6 --> D7 --> D8 --> D9 --> D10
    style D1 fill:#3b82f6,color:#fff
    style D2 fill:#3b82f6,color:#fff
    style D3 fill:#22c55e,color:#fff
    style D4 fill:#22c55e,color:#fff
    style D5 fill:#22c55e,color:#fff
    style D6 fill:#f59e0b,color:#fff
    style D7 fill:#f59e0b,color:#fff
    style D8 fill:#8b5cf6,color:#fff
    style D9 fill:#8b5cf6,color:#fff
    style D10 fill:#ef4444,color:#fff
Day Topic Skills Acquired
1 Welcome to Splunk Architecture, installation, Web UI
2 Data Ingestion monitor, HEC, sourcetype, indexes
3 Search Fundamentals SPL syntax, keyword/field search, pipes
4 Fields and Filtering eval, where, rex
5 Statistics and Aggregation stats, chart, timechart, top, eventstats
6 Data Visualization Dashboards, Simple XML, drilldown
7 Advanced Search Subsearches, lookup, join, transaction
8 Alerts and Reports Scheduled searches, alerts, macros
9 Splunk Administration Roles, index management, knowledge objects
10 Final Project SOC dashboard build

What to Learn Next

Now that you have a solid foundation in Splunk, here are some topics to explore next.

Topic Description
Splunk Enterprise Security (ES) Full SIEM capabilities
Splunk SOAR Security orchestration and automated response
SPL2 The next-generation search language
Data Models and CIM Common Information Model
Splunk Cloud Cloud-hosted Splunk deployment
Splunk Certifications Validate your skills professionally

Splunk Certifications

Certification Level Focus
Splunk Core Certified User Foundation Basic SPL operations
Splunk Core Certified Power User Intermediate Advanced SPL, dashboards
Splunk Core Certified Advanced Power User Advanced Data models, optimization
Splunk Enterprise Certified Admin Administration Infrastructure management, configuration

Exercises

Exercise 1: Feature Addition

Use the iplocation command to add a map panel that shows the geographic origin of attack source IPs.

Exercise 2: Applied

Use eventstats to calculate the normal access frequency for each IP and write a query that detects anomalous activity (three times the average or higher).

Exercise 3: Challenge

Package the entire SOC dashboard as a standalone Splunk app. Include app.conf, navigation, dashboards, lookups, macros, and saved searches (alerts).


References


Congratulations! You have completed the 10-day Splunk fundamentals course. The knowledge you have built here -- from SPL basics to dashboard design, alerting, and administration -- forms a strong foundation for security operations, IT monitoring, data analysis, and any other domain where Splunk is used.