Runbook 02 — Security Data Ingestion and Normalization
Runbook Information
Section titled “Runbook Information”Runbook Type: Security Data Engineering / Security Automation Operations
Difficulty: Intermediate → Advanced
Primary Audience: SOC Analysts / Security Engineers / Detection Engineers / Cloud Security Engineers / Security Automation Engineers
Security Domains: SOC / SIEM / SOAR / Cloud Security / Threat Intelligence / Vulnerability Management
Execution Model: Repeatable ingestion and normalization workflow
Primary Goal: Turn inconsistent raw security data into trustworthy, structured, traceable security records
Purpose
Section titled “Purpose”Security automation depends on data.
But security data arrives from many different systems:
SIEM
EDR
FIREWALLS
IDENTITY PLATFORMS
CLOUD PROVIDERS
VULNERABILITY SCANNERS
THREAT INTELLIGENCE
EMAIL SECURITY
APPLICATION LOGS
LINUX SYSTEMS
WINDOWS SYSTEMSEach system may represent similar information differently.
For example:
HOSTNAMEmay appear as:
WEB01
web01
web01.example.local
Web01Severity may appear as:
Critical
CRITICAL
critical
5
P1Authentication outcomes may appear as:
Success
SUCCESS
allowed
accepted
0Before security data can be:
CORRELATED
SCORED
SEARCHED
AUTOMATED
REPORTEDit needs to be:
VALIDATED
NORMALIZED
DEDUPLICATED
ENRICHED
TRACEABLECore Principle
Section titled “Core Principle”The central principle of this runbook is:
BAD SECURITY DATAIN=BAD SECURITY DECISIONSOUTSecurity Data Pipeline
Section titled “Security Data Pipeline”SOURCE ↓COLLECT ↓PRESERVE RAW ↓VALIDATE ↓PARSE ↓NORMALIZE ↓DEDUPLICATE ↓ENRICH ↓QUALITY CHECK ↓STORE ↓CORRELATE ↓SECURITY DECISION01 — Identify the Security Use Case
Section titled “01 — Identify the Security Use Case”Do not start by collecting everything.
Start with:
WHAT SECURITY QUESTIONARE WE TRYING TO ANSWER?Examples:
WHICH USERS ARE EXPERIENCINGREPEATED LOGIN FAILURES?
WHICH INTERNET-FACING ASSETSHAVE CRITICAL VULNERABILITIES?
WHICH CLOUD RESOURCESARE PUBLIC?
WHICH ALERTS INVOLVEPRIVILEGED USERS?
WHICH IOCS APPEARIN SECURITY EVENTS?02 — Define Required Data
Section titled “02 — Define Required Data”For each security question, determine:
WHICH DATAIS ACTUALLY REQUIRED?Example:
Question:Which privileged accounts have suspicious authentication activity?Required data:
AUTHENTICATION EVENTS
IDENTITY INVENTORY
PRIVILEGE STATUS
TIMESTAMPS
SOURCE IP
TARGET SYSTEM03 — Avoid Collecting Everything
Section titled “03 — Avoid Collecting Everything”More data does not automatically mean better security.
Excessive collection increases:
COST
STORAGE
PRIVACY RISK
PROCESSING TIME
NOISE
ATTACK SURFACEUse:
DATA MINIMIZATION04 — Inventory Data Sources
Section titled “04 — Inventory Data Sources”Create a source inventory.
Example:
| Source | Data | Method | Owner |
|---|---|---|---|
| SIEM | Alerts | API | SOC |
| Entra ID | Identity | API | IAM |
| CMDB | Assets | API | IT |
| Vulnerability tool | Findings | API | VM Team |
| Linux hosts | Auth logs | File/Agent | Platform |
| Cloud platform | Config | API | Cloud Team |
05 — Record Source Ownership
Section titled “05 — Record Source Ownership”Every data source should have an owner.
Document:
SOURCE NAME
TECHNICAL OWNER
BUSINESS OWNER
CONTACT
SUPPORT PROCESS06 — Understand Source Authority
Section titled “06 — Understand Source Authority”Not every system is authoritative for every field.
Example:
SIEMmay know:
OBSERVED USERNAMEbut:
IDENTITY DIRECTORYmay be authoritative for:
ACCOUNT STATUS
DEPARTMENT
PRIVILEGE07 — Define Authoritative Sources
Section titled “07 — Define Authoritative Sources”Example:
IDENTITY→ DIRECTORY
ASSET OWNER→ CMDB
VULNERABILITY STATUS→ VULNERABILITY PLATFORM
CLOUD RESOURCE STATE→ CLOUD API08 — Document Source Trust
Section titled “08 — Document Source Trust”For each source, record:
RELIABILITY
FRESHNESS
KNOWN LIMITATIONS
COLLECTION METHOD
FAILURE MODES09 — Choose Collection Method
Section titled “09 — Choose Collection Method”Common collection methods include:
API
LOG FORWARDER
AGENT
FILE EXPORT
DATABASE QUERY
MESSAGE QUEUE
WEBHOOK
CLOUD EVENT STREAM10 — Prefer Structured Data
Section titled “10 — Prefer Structured Data”Where possible prefer:
JSON
CSV
DATABASE RECORDS
STRUCTURED API RESPONSESover unstructured:
FREE-FORM TEXTStructured data is usually easier to:
VALIDATE
PARSE
NORMALIZE
TEST11 — Raw Logs Still Matter
Section titled “11 — Raw Logs Still Matter”Many useful security sources are log-based.
Examples:
LINUX AUTH LOG
WINDOWS EVENT LOG
WEB SERVER LOG
FIREWALL LOG
APPLICATION LOGThese may require:
REGEX
PARSER
FIELD EXTRACTIONbefore normalization.
12 — Define Ingestion Frequency
Section titled “12 — Define Ingestion Frequency”Decide whether data arrives:
REAL-TIME
NEAR REAL-TIME
HOURLY
DAILY
WEEKLY
ON DEMAND13 — Match Frequency to Security Need
Section titled “13 — Match Frequency to Security Need”Example:
SOC ALERTS→ NEAR REAL-TIME
ASSET INVENTORY→ DAILY MAY BE ACCEPTABLE
QUARTERLY COMPLIANCE EVIDENCE→ PERIODIC14 — Define Collection Time
Section titled “14 — Define Collection Time”Every collection should record:
WHEN WAS THIS DATA COLLECTED?Use:
UTCwhere possible.
Example:
2026-08-29T06:30:00Z15 — Event Time vs Collection Time
Section titled “15 — Event Time vs Collection Time”Do not confuse:
EVENT TIMEwith:
COLLECTION TIMEExample:
EVENT OCCURRED:10:00
COLLECTOR RECEIVED:10:02
PIPELINE PROCESSED:10:05These are different.
16 — Preserve Original Timestamp
Section titled “16 — Preserve Original Timestamp”Never discard the original timestamp if it is useful for investigation.
Store:
original_timestampand normalized:
event_time_utc17 — Preserve Raw Data
Section titled “17 — Preserve Raw Data”Before transforming important security data:
PRESERVETHE ORIGINALArchitecture:
SOURCE ↓RAW COPY ↓NORMALIZED COPY18 — Why Preserve Raw Data?
Section titled “18 — Why Preserve Raw Data?”If normalization produces the wrong result, you need:
ORIGINAL EVIDENCEto determine:
WAS THE SOURCE WRONG?
WAS THE PARSER WRONG?
WAS THE NORMALIZER WRONG?19 — Raw Data Storage
Section titled “19 — Raw Data Storage”Possible structure:
data/|+-- raw/| +-- siem/| +-- identity/| +-- cloud/| +-- vulnerability/|+-- normalized/20 — Do Not Modify Raw Evidence
Section titled “20 — Do Not Modify Raw Evidence”Treat raw data as:
IMMUTABLEwhere practical.
Do transformations on:
COPIES21 — Hash Important Raw Files
Section titled “21 — Hash Important Raw Files”Use:
SHA-256to support integrity checking.
Mental model:
RAW FILE ↓SHA-256 ↓INTEGRITY REFERENCE22 — Record Provenance
Section titled “22 — Record Provenance”Every normalized record should ideally answer:
WHERE DID THIS COME FROM?Add fields such as:
source_system
source_record_id
collection_time
collector_version23 — Example Provenance
Section titled “23 — Example Provenance”{ "source_system": "identity-monitor", "source_record_id": "ALT-1002", "collection_time": "2026-08-29T06:20:00Z", "collector_version": "1.3.0"}24 — Validate File Presence
Section titled “24 — Validate File Presence”Before processing files:
DOES FILE EXIST?If not:
LOG FAILURE
MARK SOURCE UNAVAILABLE
DO NOT PRETEND DATA IS EMPTY25 — Missing File vs Empty File
Section titled “25 — Missing File vs Empty File”These are different:
FILE MISSINGmay mean:
COLLECTION FAILUREwhereas:
EMPTY VALID FILEmay mean:
NO EVENTS26 — Validate File Type
Section titled “26 — Validate File Type”Confirm expected formats such as:
JSON
CSV
LOG
NDJSONDo not assume extensions guarantee content validity.
27 — Validate JSON
Section titled “27 — Validate JSON”A JSON source can fail because of:
MALFORMED JSON
TRUNCATED FILE
ENCODING ISSUE
UNEXPECTED STRUCTURE28 — Validate CSV Headers
Section titled “28 — Validate CSV Headers”Before parsing CSV:
EXPECTED:alert_idtimestampseverityassetIf the source provides:
idtimeriskhostnamedo not silently assume mappings.
29 — Define Required Fields
Section titled “29 — Define Required Fields”Example alert schema:
alert_id
timestamp
source
alert_type
severityOptional:
user
asset
source_ip
description30 — Reject or Quarantine Invalid Records
Section titled “30 — Reject or Quarantine Invalid Records”Invalid records should be:
QUARANTINEDrather than silently discarded.
Example:
invalid-records.json31 — Record Rejection Reason
Section titled “31 — Record Rejection Reason”Example:
{ "record_id": "ALT-20", "reason": "Invalid timestamp"}32 — Do Not Crash on One Bad Record
Section titled “32 — Do Not Crash on One Bad Record”Preferred behavior:
1000 RECORDS ↓999 VALID1 INVALID ↓PROCESS 999QUARANTINE 1rather than:
1 BAD RECORD ↓ENTIRE PIPELINE FAILSunless integrity requirements demand the entire batch be rejected.
33 — Schema Versioning
Section titled “33 — Schema Versioning”Data sources change.
Add:
schema_versionwhere practical.
Example:
1.034 — Why Schema Versions Matter
Section titled “34 — Why Schema Versions Matter”Version 1 may use:
hostnameVersion 2 may use:
device_nameYour parser needs to know which schema it received.
35 — Normalize Field Names
Section titled “35 — Normalize Field Names”Create consistent internal names.
Example:
host
hostname
device
computer
machinebecomes:
asset36 — Common Security Schema
Section titled “36 — Common Security Schema”Example normalized alert:
{ "event_id": "ALT-1001", "event_time": "2026-08-29T08:15:00Z", "event_type": "authentication_failure", "severity": "medium", "user": "admin01", "asset": "JUMP01", "source_ip": "203.0.113.25"}37 — Normalize Severity
Section titled “37 — Normalize Severity”Choose one internal severity model.
For example:
critical
high
medium
low
informational
unknown38 — Map Vendor Severity
Section titled “38 — Map Vendor Severity”Example:
Vendor:5
Internal:criticalor:
Vendor:P2
Internal:highDocument mappings explicitly.
39 — Never Guess Ambiguous Mapping
Section titled “39 — Never Guess Ambiguous Mapping”If a vendor field says:
risk = 7you need documentation before deciding whether:
7=high40 — Preserve Original Severity
Section titled “40 — Preserve Original Severity”Store:
source_severityand:
normalized_severitywhen useful.
41 — Normalize Status
Section titled “41 — Normalize Status”Different systems may use:
Open
OPEN
active
new
in_progressDefine a common model.
Example:
open
in_progress
closed
unknown42 — Preserve Source Status
Section titled “42 — Preserve Source Status”Do not lose vendor-specific meaning.
Store:
source_statuswhere necessary.
43 — Normalize Boolean Fields
Section titled “43 — Normalize Boolean Fields”Source values may include:
True
TRUE
yes
1
enabledNormalize to:
true / false / unknown44 — Avoid False Defaults
Section titled “44 — Avoid False Defaults”Do not convert:
MISSINGto:
falseautomatically.
Use:
unknownwhere appropriate.
45 — Normalize Hostnames
Section titled “45 — Normalize Hostnames”Example:
web01
WEB01
Web01to:
WEB0146 — FQDN vs Hostname
Section titled “46 — FQDN vs Hostname”Example:
WEB01.EXAMPLE.LOCALmay need:
asset_fqdnand:
asset_short_nameDo not blindly remove domains if they matter.
47 — Asset Identity Is Hard
Section titled “47 — Asset Identity Is Hard”An asset may be identified by:
HOSTNAME
IP
CLOUD RESOURCE ID
AGENT ID
SERIAL NUMBER
INSTANCE ID48 — Prefer Stable Asset IDs
Section titled “48 — Prefer Stable Asset IDs”Where possible correlate on:
ASSET IDrather than only:
HOSTNAMEbecause hostnames can change.
49 — Normalize Usernames
Section titled “49 — Normalize Usernames”Examples:
ADMIN01
admin01
DOMAIN\admin01
admin01@example.commay refer to:
SAME OR DIFFERENT IDENTITIESDo not normalize blindly.
50 — Preserve Identity Namespace
Section titled “50 — Preserve Identity Namespace”Store fields such as:
username
domain
upn
identity_id51 — Stable Identity IDs
Section titled “51 — Stable Identity IDs”Prefer:
DIRECTORY OBJECT ID
EMPLOYEE ID
ACCOUNT IDfor correlation where available.
52 — Normalize IP Addresses
Section titled “52 — Normalize IP Addresses”Use standard representations.
For IPv4:
010.001.001.001should be handled carefully.
For IPv6:
multiple textual formsmay represent the same address.
Use proper IP parsing libraries.
53 — Validate IP Addresses
Section titled “53 — Validate IP Addresses”Do not accept:
999.999.999.999as a valid IP.
54 — Classify IP Context
Section titled “54 — Classify IP Context”Potential categories:
PRIVATE
PUBLIC
LOOPBACK
LINK-LOCAL
DOCUMENTATION
UNKNOWN55 — Normalize Domains
Section titled “55 — Normalize Domains”Convert:
Example.COMto:
example.comwhen appropriate.
56 — Handle Trailing Dot
Section titled “56 — Handle Trailing Dot”DNS names may appear as:
example.com.Document your normalization approach.
57 — Normalize URLs
Section titled “57 — Normalize URLs”Avoid over-normalizing URLs.
These may differ:
https://example.com/login
https://example.com/Logindepending on application behavior.
58 — Normalize Hashes
Section titled “58 — Normalize Hashes”File hashes should be:
LOWERCASE HEXfor consistent comparison.
Common lengths:
MD532 hex
SHA-140 hex
SHA-25664 hex59 — Validate Hash Format
Section titled “59 — Validate Hash Format”Do not classify:
randomtextas:
SHA-25660 — Normalize CVE IDs
Section titled “60 — Normalize CVE IDs”Example:
cve-2026-1234to:
CVE-2026-1234where valid.
61 — Validate CVSS Scores
Section titled “61 — Validate CVSS Scores”Expected:
0.0–10.0Reject or mark unknown values such as:
15
high
N/A62 — Normalize Dates
Section titled “62 — Normalize Dates”Convert:
08/29/2026
2026-08-29
29-08-2026into a consistent internal representation.
Preferred:
ISO 860163 — Timezone Normalization
Section titled “63 — Timezone Normalization”Convert event timestamps to:
UTCwhile preserving original time if useful.
64 — Do Not Assume Local Time
Section titled “64 — Do Not Assume Local Time”A log without timezone is dangerous.
Example:
2026-08-29 10:00:00Ask:
WHICH TIMEZONE?65 — Daylight Saving Considerations
Section titled “65 — Daylight Saving Considerations”Timezones can change because of:
DSTPrefer timezone-aware timestamps.
66 — Timestamp Parsing Failure
Section titled “66 — Timestamp Parsing Failure”If a timestamp cannot be parsed:
DO NOTMAKE ONE UPMark:
timestamp_status = invalid67 — Normalize Event Types
Section titled “67 — Normalize Event Types”Sources may report:
4625
login_failed
failed_authentication
authentication_failureMap them to a common type such as:
authentication_failure68 — Preserve Source Event Code
Section titled “68 — Preserve Source Event Code”Keep:
source_event_id = 4625because source-specific context still matters.
69 — Normalize Protocols
Section titled “69 — Normalize Protocols”Example:
TCP
tcp
6could normalize to:
tcpwhen mapping is clear.
70 — Normalize Ports
Section titled “70 — Normalize Ports”Convert:
"443"to integer:
443after validation.
71 — Validate Port Range
Section titled “71 — Validate Port Range”Expected:
0–65535depending on your model.
72 — Normalize Cloud Providers
Section titled “72 — Normalize Cloud Providers”Use:
aws
azure
gcpinstead of:
Amazon Web Services
Microsoft Azure
Google Cloud Platforminternally.
73 — Normalize Cloud Scope
Section titled “73 — Normalize Cloud Scope”Create standard fields:
cloud_provider
cloud_scope_id
cloud_scope_name
resource_id
resource_type74 — Preserve Native Resource ID
Section titled “74 — Preserve Native Resource ID”Cloud resource names can be duplicated.
Prefer:
FULL RESOURCE IDENTIFIERwhere possible.
75 — Normalize Environment
Section titled “75 — Normalize Environment”Possible model:
production
staging
development
test
sandbox
unknown76 — Normalize Criticality
Section titled “76 — Normalize Criticality”Example internal model:
critical
high
medium
low
unknown77 — Do Not Guess Criticality
Section titled “77 — Do Not Guess Criticality”If asset inventory has no criticality:
unknownis safer than:
low78 — Normalize Owner
Section titled “78 — Normalize Owner”Owner may represent:
TEAM
APPLICATION OWNER
BUSINESS OWNER
TECHNICAL OWNERSeparate these when required.
79 — Validate Owner Against Directory
Section titled “79 — Validate Owner Against Directory”Avoid free-text owner fields when possible.
Use stable identifiers such as:
TEAM ID
GROUP ID80 — Deduplication
Section titled “80 — Deduplication”Security systems often generate duplicate records.
Causes:
RETRIES
MULTIPLE COLLECTORS
MULTIPLE SCANNERS
MESSAGE REDELIVERY
REIMPORT81 — Define Deduplication Key
Section titled “81 — Define Deduplication Key”Examples:
ALERT IDor:
ASSET+CVE+PORT+SCANNERor:
USER+SOURCE IP+TIMESTAMP BUCKET+EVENT TYPE82 — Avoid Weak Deduplication
Section titled “82 — Avoid Weak Deduplication”This:
same hostnameis not enough to declare:
duplicate vulnerability83 — Preserve Duplicate Evidence
Section titled “83 — Preserve Duplicate Evidence”Do not necessarily delete duplicates permanently.
Store:
DUPLICATE COUNT
SOURCE IDS
FIRST SEEN
LAST SEEN84 — Deduplication vs Correlation
Section titled “84 — Deduplication vs Correlation”These are different.
DEDUPLICATIONasks:
IS THIS THE SAME RECORD?CORRELATIONasks:
ARE THESE DIFFERENT RECORDSRELATED?85 — Example
Section titled “85 — Example”5 identical alertsmay be:
DUPLICATESbut:
FAILED LOGIN+SUCCESSFUL LOGINare:
RELATEDnot duplicates.
86 — Handle Late-Arriving Data
Section titled “86 — Handle Late-Arriving Data”Events may arrive after newer events.
Do not assume ingestion order equals:
EVENT ORDERUse:
EVENT TIMESTAMPfor timelines.
87 — Handle Out-of-Order Data
Section titled “87 — Handle Out-of-Order Data”Example:
EVENT A10:02
EVENT B10:01may be collected:
B AFTER Abecause of pipeline delay.
88 — Event ID Design
Section titled “88 — Event ID Design”Normalized records should have a stable identifier.
Options:
SOURCE ID
UUID
HASH-BASED FINGERPRINT89 — Build Record Fingerprints
Section titled “89 — Build Record Fingerprints”Possible fingerprint:
source+event_type+asset+user+timestampHash the combination for tracking.
90 — Fingerprint Limitations
Section titled “90 — Fingerprint Limitations”Do not use fingerprinting blindly where timestamps or fields change slightly between copies.
91 — Data Enrichment
Section titled “91 — Data Enrichment”After normalization, add context.
Examples:
ASSET OWNER
ASSET CRITICALITY
IDENTITY PRIVILEGE
DEPARTMENT
CLOUD PROVIDER
IOC CONTEXT
VULNERABILITY CONTEXT92 — Enrichment Order
Section titled “92 — Enrichment Order”Recommended:
NORMALIZE FIRST
ENRICH SECONDbecause matching normalized values is more reliable.
93 — Identity Enrichment
Section titled “93 — Identity Enrichment”Example:
user = admin01becomes:
user = admin01
department = Cloud Operations
privileged = true
account_status = enabled94 — Asset Enrichment
Section titled “94 — Asset Enrichment”Example:
asset = WEB01becomes:
criticality = high
environment = production
internet_facing = true
owner = Application Team95 — IOC Enrichment
Section titled “95 — IOC Enrichment”Example:
203.0.113.25may gain:
source
classification
confidence
last_seen96 — Vulnerability Enrichment
Section titled “96 — Vulnerability Enrichment”An alert on:
WEB01may gain:
critical_open_vulnerabilities = 197 — Enrichment Failure
Section titled “97 — Enrichment Failure”If an enrichment source is unavailable:
KEEP THE RECORDMark:
enrichment_status = partial98 — Graceful Degradation
Section titled “98 — Graceful Degradation”Example:
IDENTITY✓
ASSET✓
IOC✗
VULNERABILITY✓Result:
PARTIAL CONTEXTnot:
DROP ALERT99 — Data Quality Dimensions
Section titled “99 — Data Quality Dimensions”Measure:
COMPLETENESS
VALIDITY
CONSISTENCY
UNIQUENESS
FRESHNESS
ACCURACY100 — Completeness
Section titled “100 — Completeness”Question:
ARE REQUIRED FIELDS PRESENT?Example:
98% OF ALERTSHAVE ASSET ID101 — Validity
Section titled “101 — Validity”Question:
DO VALUES MATCH EXPECTED FORMAT?Example:
99.9% OF IP ADDRESSESARE VALID102 — Consistency
Section titled “102 — Consistency”Question:
IS THE SAME CONCEPTREPRESENTED THE SAME WAY?Example:
criticalinstead of:
critical / CRIT / 5 / urgent103 — Uniqueness
Section titled “103 — Uniqueness”Question:
HOW MANY RECORDSARE DUPLICATES?104 — Freshness
Section titled “104 — Freshness”Question:
HOW OLD IS THE DATA?105 — Accuracy
Section titled “105 — Accuracy”Harder question:
DOES THE DATAREFLECT REALITY?This often requires comparison with authoritative systems.
106 — Data Quality Score
Section titled “106 — Data Quality Score”A future model might track:
completeness
validity
freshness
enrichment coverageDo not compress everything into one opaque score without explanation.
107 — Context Completeness
Section titled “107 — Context Completeness”Example:
IDENTITY FOUND
ASSET FOUND
IOC CHECK COMPLETE
VULNERABILITY CONTEXT AVAILABLE108 — Unknown Context Should Be Visible
Section titled “108 — Unknown Context Should Be Visible”Analysts should see:
ASSET CONTEXT:UNKNOWNrather than the field silently disappearing.
109 — Build a Data Quality Report
Section titled “109 — Build a Data Quality Report”Example:
TOTAL RECORDS
VALID RECORDS
INVALID RECORDS
DUPLICATES
UNKNOWN ASSETS
UNKNOWN USERS
INVALID IPS
INVALID TIMESTAMPS110 — Example Data Quality JSON
Section titled “110 — Example Data Quality JSON”{ "total_records": 1000, "valid_records": 960, "invalid_records": 20, "duplicates": 20, "unknown_assets": 15, "unknown_users": 8}111 — Set Quality Thresholds
Section titled “111 — Set Quality Thresholds”Example:
INVALID RATE > 5%→ INVESTIGATE PIPELINEThresholds should reflect your environment.
112 — Detect Sudden Data Changes
Section titled “112 — Detect Sudden Data Changes”Example:
NORMAL:10,000 EVENTS/HOUR
CURRENT:50 EVENTS/HOURPossible causes:
COLLECTOR FAILURE
SOURCE FAILURE
NETWORK ISSUE113 — Detect Volume Spikes
Section titled “113 — Detect Volume Spikes”Example:
NORMAL:10,000
CURRENT:2,000,000Possible:
EVENT STORM
LOOP
ATTACK
PARSER ERROR114 — Source Health
Section titled “114 — Source Health”Track each data source:
HEALTHY
DEGRADED
FAILED
UNKNOWN115 — Collection Health Example
Section titled “115 — Collection Health Example”{ "siem": "healthy", "identity": "healthy", "cmdb": "degraded", "threat_intel": "failed"}116 — Do Not Hide Collection Gaps
Section titled “116 — Do Not Hide Collection Gaps”A report should state:
THREAT INTELLIGENCE SOURCEUNAVAILABLErather than pretending:
NO IOC MATCHES FOUND117 — Storage Model
Section titled “117 — Storage Model”Normalized security data may be stored in:
FILES
SQLITE
POSTGRESQL
DATA LAKE
SIEM INDEX
SEARCH PLATFORM118 — Choose Storage Based on Need
Section titled “118 — Choose Storage Based on Need”For labs:
JSON
CSV
SQLITEare often enough.
For enterprise scale:
CENTRAL DATABASE
SEARCH PLATFORM
DATA LAKEmay be more appropriate.
119 — Separate Raw and Normalized Storage
Section titled “119 — Separate Raw and Normalized Storage”Example:
RAW→ immutable source copy
NORMALIZED→ query-ready data120 — Store Schema Version
Section titled “120 — Store Schema Version”Each normalized dataset should record:
schema_version121 — Store Pipeline Version
Section titled “121 — Store Pipeline Version”Record:
pipeline_versionso you know which code produced the output.
122 — Store Normalization Version
Section titled “122 — Store Normalization Version”A change such as:
P2 → highcan alter analytics.
Track:
normalization_version123 — Store Collection ID
Section titled “123 — Store Collection ID”Generate one:
collection_idper pipeline run.
124 — Why Collection IDs Matter
Section titled “124 — Why Collection IDs Matter”They allow:
TRACEABILITY
ROLLBACK
REPROCESSING
AUDIT125 — Reprocessing
Section titled “125 — Reprocessing”If normalization logic changes, you may need to:
REPROCESS RAW DATAusing the new pipeline.
126 — Never Require Source Recollection if Avoidable
Section titled “126 — Never Require Source Recollection if Avoidable”Preserving raw data allows:
REPROCESSINGwithout requesting the source system again.
127 — Database Constraints
Section titled “127 — Database Constraints”Use:
PRIMARY KEYS
UNIQUE KEYS
NOT NULL
CHECK CONSTRAINTSwhere appropriate.
128 — Example Constraints
Section titled “128 — Example Constraints”risk_score0–100
cvss0–10
port0–65535129 — Index Frequently Queried Fields
Section titled “129 — Index Frequently Queried Fields”Examples:
event_time
asset
user
source_ip
severity130 — Do Not Over-Index
Section titled “130 — Do Not Over-Index”Indexes:
IMPROVE READ PERFORMANCEbut increase:
STORAGE
WRITE COST
MAINTENANCE131 — Normalize Before Correlation
Section titled “131 — Normalize Before Correlation”Do not correlate:
WEB01with:
web01before normalization if they should represent the same asset.
132 — Correlation Keys
Section titled “132 — Correlation Keys”Common:
ASSET ID
USER ID
SOURCE IP
SESSION ID
ALERT ID
CLOUD RESOURCE ID133 — Prefer Stable Keys
Section titled “133 — Prefer Stable Keys”Avoid relying only on:
DISPLAY NAMEif a stable identifier exists.
134 — Correlation Time Windows
Section titled “134 — Correlation Time Windows”Correlation should usually consider:
TIMEExample:
FAILED LOGIN08:15
SUCCESS08:18is more meaningful than:
FAILED LOGINJANUARY
SUCCESSAUGUST135 — Build Normalized Security Event Schema
Section titled “135 — Build Normalized Security Event Schema”Recommended core fields:
event_id
event_time
collection_time
source_system
event_type
severity
user_id
username
asset_id
asset_name
source_ip
destination_ip
status
raw_reference
schema_version136 — Optional Security Context Fields
Section titled “136 — Optional Security Context Fields”privileged_user
asset_criticality
environment
internet_facing
ioc_confidence
open_vulnerability_count
cloud_provider137 — Keep Context Separate Where Needed
Section titled “137 — Keep Context Separate Where Needed”Do not duplicate massive enrichment objects into every record if a relational model is more efficient.
Use:
EVENT TABLE
ASSET TABLE
IDENTITY TABLEwith joins.
138 — Security Data Model Example
Section titled “138 — Security Data Model Example”EVENTS ↓asset_id ↓ASSETS
EVENTS ↓user_id ↓IDENTITIES
EVENTS ↓indicator ↓IOC_CONTEXT139 — Data Lineage
Section titled “139 — Data Lineage”For important records, maintain:
RAW SOURCE ↓PARSER ↓NORMALIZER ↓ENRICHMENT ↓FINAL RECORD140 — Why Lineage Matters
Section titled “140 — Why Lineage Matters”If an analyst challenges a value:
WHY DOES THIS SAYUSER IS PRIVILEGED?you should be able to answer:
SOURCE:Identity Directory
COLLECTED:06:00 UTC141 — Protect Sensitive Data
Section titled “141 — Protect Sensitive Data”Security datasets may contain:
USERNAMES
INTERNAL IPS
HOSTNAMES
VULNERABILITIES
EMAIL ADDRESSES
INCIDENT INFORMATIONTreat them as sensitive.
142 — Apply Access Control
Section titled “142 — Apply Access Control”Not every user needs access to:
RAW SECURITY TELEMETRYDefine:
VIEWER
ANALYST
ENGINEER
ADMINwhere appropriate.
143 — Encryption
Section titled “143 — Encryption”Protect sensitive security data:
IN TRANSIT
AT RESTaccording to organizational requirements.
144 — Logging the Pipeline
Section titled “144 — Logging the Pipeline”Pipeline logs should include:
RUN ID
SOURCE
START TIME
RECORD COUNT
VALID COUNT
INVALID COUNT
DUPLICATE COUNT
FAILURE COUNT
END TIME145 — Avoid Logging Raw Sensitive Payloads
Section titled “145 — Avoid Logging Raw Sensitive Payloads”Do not log entire:
AUTHENTICATION TOKEN
EMAIL BODY
API RESPONSEunless necessary and approved.
146 — Operational Metrics
Section titled “146 — Operational Metrics”Track:
INGESTION RATE
VALIDATION FAILURE RATE
NORMALIZATION FAILURE RATE
DUPLICATE RATE
ENRICHMENT SUCCESS RATE
PROCESSING LATENCY147 — Processing Latency
Section titled “147 — Processing Latency”Calculate:
PROCESSING TIME-EVENT TIMEwhere appropriate.
148 — Detect Pipeline Delay
Section titled “148 — Detect Pipeline Delay”If normal delay is:
1 MINUTEand current delay is:
45 MINUTESinvestigate.
149 — Queue Backlog
Section titled “149 — Queue Backlog”If using message queues, track:
QUEUE DEPTH
OLDEST MESSAGE AGE150 — Dead-Letter Queue
Section titled “150 — Dead-Letter Queue”Invalid or repeatedly failing records can move to:
DEAD-LETTER QUEUEfor review.
151 — Do Not Lose Failed Records
Section titled “151 — Do Not Lose Failed Records”Preferred:
FAILED RECORD ↓QUARANTINE ↓REVIEWnot:
FAILED RECORD ↓DELETE152 — Retry Strategy
Section titled “152 — Retry Strategy”Retries may help for:
TEMPORARY NETWORK ERROR
429
5XX153 — No Infinite Retries
Section titled “153 — No Infinite Retries”Use:
MAX RETRIES
BACKOFF
DEAD-LETTER154 — Idempotent Ingestion
Section titled “154 — Idempotent Ingestion”Running ingestion twice should not unintentionally create:
DOUBLE RECORDS155 — Idempotency Keys
Section titled “155 — Idempotency Keys”Use:
source_record_id
event_id
fingerprint156 — Partial Batch Failure
Section titled “156 — Partial Batch Failure”Example:
10,000 RECORDS
9,950 SUCCESS
50 FAILEDReport:
PARTIAL SUCCESS157 — Do Not Hide Partial Success
Section titled “157 — Do Not Hide Partial Success”Avoid:
STATUS = SUCCESSwithout:
FAILED RECORD COUNT158 — Data Retention
Section titled “158 — Data Retention”Define retention separately for:
RAW DATA
NORMALIZED DATA
QUARANTINED DATA
PIPELINE LOGS159 — Retention Should Have Purpose
Section titled “159 — Retention Should Have Purpose”Do not keep data:
FOREVERwithout a documented need.
160 — Privacy and Regulatory Requirements
Section titled “160 — Privacy and Regulatory Requirements”Security telemetry can overlap with:
EMPLOYEE DATA
CUSTOMER DATA
PERSONAL DATAConsult applicable organizational requirements.
161 — Normalize Without Destroying Evidence
Section titled “161 — Normalize Without Destroying Evidence”The rule is:
NORMALIZE FOR ANALYSIS
PRESERVE FOR INVESTIGATION162 — Example
Section titled “162 — Example”Source:
DOMAIN\Admin01Normalized:
username = admin01domain = DOMAINDo not simply discard:
DOMAINif it is meaningful.
163 — Parser Testing
Section titled “163 — Parser Testing”Every parser should be tested against:
VALID SAMPLE
MISSING FIELD
EXTRA FIELD
INVALID VALUE
EMPTY RECORD
UNEXPECTED TYPE164 — Regression Testing
Section titled “164 — Regression Testing”When source formats change, ensure:
OLD VALID DATAstill processes as expected.
165 — Test Dataset
Section titled “165 — Test Dataset”Maintain synthetic samples:
tests/data/|+-- valid/|+-- invalid/|+-- edge-cases/166 — Source Format Change
Section titled “166 — Source Format Change”If a vendor changes:
host_nameto:
device_namethe pipeline should:
DETECT SCHEMA CHANGErather than silently producing:
EMPTY ASSET VALUES167 — Detect Unexpected Null Increase
Section titled “167 — Detect Unexpected Null Increase”Example:
ASSET NULL RATE
Yesterday:1%
Today:80%This likely indicates a parser or source problem.
168 — Schema Drift Monitoring
Section titled “168 — Schema Drift Monitoring”Track:
NEW FIELD
REMOVED FIELD
TYPE CHANGE
ENUM CHANGE169 — Type Validation
Section titled “169 — Type Validation”Example:
cvssshould be:
NUMBERnot:
OBJECT170 — Enumeration Validation
Section titled “170 — Enumeration Validation”Example severity should belong to:
critical
high
medium
low
informationalAnything else:
UNKNOWNor quarantined according to policy.
171 — Baseline Data Volumes
Section titled “171 — Baseline Data Volumes”Document expected:
EVENTS / HOUR
ALERTS / DAY
VULNERABILITIES / SCAN
ASSETS / INVENTORY172 — Data Volume Anomaly
Section titled “172 — Data Volume Anomaly”A sudden change may indicate:
ATTACK ACTIVITY
COLLECTION FAILURE
DUPLICATION LOOP
CONFIGURATION CHANGE173 — Multi-Source Normalization
Section titled “173 — Multi-Source Normalization”Example:
AWS CloudTrail
Azure Activity Log
Google Cloud Audit Logsall normalize into:
CLOUD ACTIVITY EVENT174 — Preserve Cloud-Native Fields
Section titled “174 — Preserve Cloud-Native Fields”Common model does not mean:
DELETE PROVIDER-SPECIFIC DATAKeep useful native fields in:
source_detailsor related storage.
175 — Normalization Layer
Section titled “175 — Normalization Layer”Architecture:
AWS ↓AWS ADAPTER ↓COMMON MODEL
AZURE ↓AZURE ADAPTER ↓COMMON MODEL
GCP ↓GCP ADAPTER ↓COMMON MODEL176 — Adapter Principle
Section titled “176 — Adapter Principle”Provider-specific parsing belongs in:
ADAPTERCommon analytics should consume:
NORMALIZED RECORD177 — SIEM Normalization
Section titled “177 — SIEM Normalization”For SIEM data, normalize concepts such as:
ALERT ID
RULE ID
EVENT TIME
USER
ASSET
SOURCE IP
SEVERITY178 — EDR Normalization
Section titled “178 — EDR Normalization”Common fields:
DEVICE ID
HOSTNAME
USER
PROCESS
PARENT PROCESS
HASH
ALERT SEVERITY179 — Vulnerability Normalization
Section titled “179 — Vulnerability Normalization”Common fields:
FINDING ID
ASSET ID
CVE
SEVERITY
CVSS
STATUS
FIRST SEEN
LAST SEEN
DUE DATE180 — Threat Intelligence Normalization
Section titled “180 — Threat Intelligence Normalization”Common:
INDICATOR
TYPE
SOURCE
CONFIDENCE
FIRST SEEN
LAST SEEN
EXPIRATION181 — Identity Normalization
Section titled “181 — Identity Normalization”Common:
IDENTITY ID
USERNAME
ACCOUNT TYPE
ENABLED
PRIVILEGED
DEPARTMENT182 — Asset Normalization
Section titled “182 — Asset Normalization”Common:
ASSET ID
HOSTNAME
IP
ENVIRONMENT
CRITICALITY
OWNER
INTERNET FACING183 — Detection Normalization
Section titled “183 — Detection Normalization”Common:
RULE ID
RULE NAME
VERSION
SEVERITY
DATA SOURCE184 — Data Quality Runbook Trigger
Section titled “184 — Data Quality Runbook Trigger”Use this runbook when:
NEW DATA SOURCE ADDED
SCHEMA CHANGED
ALERT FIELDS MISSING
CORRELATION FAILS
DUPLICATE RATE SPIKES
EVENT COUNTS DROP
UNKNOWN ASSETS INCREASE
UNKNOWN USERS INCREASE185 — Initial Triage of Data Pipeline Issue
Section titled “185 — Initial Triage of Data Pipeline Issue”Check:
SOURCE AVAILABLE?
COLLECTOR RUNNING?
AUTHENTICATION WORKING?
EXPECTED FILE/API DATA PRESENT?
SCHEMA CHANGED?
PARSER ERRORS?
DATABASE WRITES WORKING?186 — Troubleshooting Flow
Section titled “186 — Troubleshooting Flow”NO DATA ↓SOURCE? ↓COLLECTOR? ↓NETWORK? ↓AUTH? ↓PARSER? ↓NORMALIZER? ↓STORAGE?187 — If Source Is Down
Section titled “187 — If Source Is Down”Action:
MARK SOURCE FAILED
PRESERVE OTHER PIPELINE OUTPUT
NOTIFY OWNER
DO NOT REPORT FULL COVERAGE188 — If Authentication Fails
Section titled “188 — If Authentication Fails”For:
401review:
TOKEN
EXPIRATION
CLIENT CONFIGURATION189 — If Authorization Fails
Section titled “189 — If Authorization Fails”For:
403review:
REQUIRED PERMISSION
ROLE ASSIGNMENT
SCOPEDo not immediately grant broad admin access.
190 — If Rate Limited
Section titled “190 — If Rate Limited”For:
429use:
BACKOFF
RETRY-AFTER
LOWER REQUEST RATE
CACHING191 — If Schema Changed
Section titled “191 — If Schema Changed”Stop and review:
WHAT CHANGED?
WHICH FIELDS?
WHICH TYPE?
WHICH VERSION?192 — Do Not Patch Schema Blindly
Section titled “192 — Do Not Patch Schema Blindly”Understand vendor/source changes before changing mappings.
193 — If Duplicate Rate Spikes
Section titled “193 — If Duplicate Rate Spikes”Investigate:
RETRY LOOP
FORWARDER DUPLICATION
MULTIPLE COLLECTORS
PAGINATION BUG194 — If Unknown Assets Increase
Section titled “194 — If Unknown Assets Increase”Investigate:
CMDB FRESHNESS
HOSTNAME FORMAT
NEW CLOUD ASSETS
ASSET INVENTORY GAP195 — If Unknown Users Increase
Section titled “195 — If Unknown Users Increase”Investigate:
IDENTITY SYNC
DOMAIN FORMAT
SERVICE ACCOUNTS
DELETED ACCOUNTS
NORMALIZATION BUG196 — Data Quality Escalation
Section titled “196 — Data Quality Escalation”Escalate when:
CRITICAL DATA SOURCE UNAVAILABLE
SCHEMA CHANGE BREAKS INGESTION
LARGE PORTION OF DATA INVALID
NORMALIZATION PRODUCES WRONG IDENTITIES
CORRELATION RESULTS ARE UNTRUSTWORTHY197 — Stop Downstream Automation if Necessary
Section titled “197 — Stop Downstream Automation if Necessary”If data integrity is questionable:
PAUSEHIGH-IMPACT AUTOMATIONuntil data quality is restored.
198 — Why This Matters
Section titled “198 — Why This Matters”A response system acting on:
WRONG USER
WRONG ASSET
WRONG SEVERITYcan create serious business impact.
199 — Build Ingestion Health Dashboard
Section titled “199 — Build Ingestion Health Dashboard”Useful metrics:
SOURCE HEALTH
LAST SUCCESSFUL COLLECTION
RECORD COUNT
INVALID RATE
DUPLICATE RATE
PROCESSING LATENCY
UNKNOWN ASSET RATE
UNKNOWN USER RATE200 — Example Dashboard
Section titled “200 — Example Dashboard”SIEMHealthyLast Collection: 06:30 UTC
IdentityHealthy
CMDBDegradedUnknown Assets: 18%
IOCFailed201 — Alert on Stale Sources
Section titled “201 — Alert on Stale Sources”Example:
NO SUCCESSFULCMDB COLLECTIONFOR 24 HOURSshould trigger operational review.
202 — Prevent Silent Failure
Section titled “202 — Prevent Silent Failure”The worst pipeline state is:
BROKENBUT APPEARS HEALTHYUse:
HEARTBEATS
EXPECTED RECORD COUNTS
LAST-SUCCESS TIMESTAMP203 — Pipeline Heartbeat
Section titled “203 — Pipeline Heartbeat”Record:
run_id
start_time
end_time
status
records_processed204 — Pipeline Run Status
Section titled “204 — Pipeline Run Status”Use:
success
partial_success
failednot only:
success / failure205 — Operational Run Record
Section titled “205 — Operational Run Record”Example:
{ "run_id": "RUN-20260829-001", "status": "partial_success", "sources_expected": 6, "sources_successful": 5, "invalid_records": 7}206 — Runbook Execution Checklist
Section titled “206 — Runbook Execution Checklist”Before ingestion:
- Security use case defined
- Required data identified
- Data sources documented
- Source owners identified
- Authoritative fields understood
- Collection method documented
- Frequency defined
- Access permissions validated
- Secrets protected
- Raw storage prepared
- Expected schema documented
During ingestion:
- Source availability checked
- Collection time recorded
- Raw data preserved
- Source provenance recorded
- File/API response validated
- Required fields validated
- Invalid records quarantined
- Timestamps parsed
- Timezones normalized
- Field names normalized
- Severity normalized
- Status normalized
- Booleans normalized
- Hostnames normalized
- Identities normalized
- IPs validated
- Indicators normalized
- Cloud identifiers preserved
- Duplicates identified
- Duplicates handled
- Enrichment attempted
- Failed enrichment recorded
- Unknown values preserved as unknown
After ingestion:
- Data quality calculated
- Record counts validated
- Duplicate rate reviewed
- Invalid rate reviewed
- Unknown assets reviewed
- Unknown users reviewed
- Source health documented
- Normalized data stored
- Schema version recorded
- Pipeline version recorded
- Collection ID recorded
- Pipeline status recorded
- Downstream automation safe to continue
207 — Data Source Onboarding Template
Section titled “207 — Data Source Onboarding Template”For every new source document:
SOURCE NAME:
OWNER:
PURPOSE:
COLLECTION METHOD:
AUTHENTICATION:
REQUIRED PERMISSIONS:
FORMAT:
SCHEMA VERSION:
COLLECTION FREQUENCY:
EXPECTED RECORD VOLUME:
AUTHORITATIVE FIELDS:
NORMALIZATION RULES:
DEDUPLICATION KEY:
RETENTION:
FAILURE BEHAVIOR:208 — Field Mapping Template
Section titled “208 — Field Mapping Template”Example:
| Source Field | Normalized Field | Rule |
|---|---|---|
| host_name | asset_name | Uppercase |
| userPrincipalName | username | Lowercase |
| risk | severity | Mapping table |
| eventTime | event_time | Convert to UTC |
| srcIp | source_ip | IP validation |
209 — Normalization Mapping Governance
Section titled “209 — Normalization Mapping Governance”Mapping changes should be:
DOCUMENTED
VERSIONED
TESTED
REVIEWED210 — Example Severity Mapping
Section titled “210 — Example Severity Mapping”SOURCE VALUE INTERNAL
5 critical
4 high
3 medium
2 low
1 informationalOnly use if supported by the source’s official definition.
211 — Example Status Mapping
Section titled “211 — Example Status Mapping”SOURCE:
ACTIVENEW
→
openSOURCE:
RESOLVEDCLOSED
→
closed212 — Mapping Change Risk
Section titled “212 — Mapping Change Risk”Changing:
P2FROM MEDIUMTO HIGHcan alter:
DASHBOARDS
SCORES
ALERT QUEUES
AUTOMATIONTreat mapping changes as security engineering changes.
213 — Build Data Quality Investigation Template
Section titled “213 — Build Data Quality Investigation Template”ISSUE:
SOURCE:
FIRST OBSERVED:
EXPECTED:
ACTUAL:
INVALID RATE:
DUPLICATE RATE:
AFFECTED FIELDS:
DOWNSTREAM IMPACT:
ROOT CAUSE:
REMEDIATION:
VALIDATION:214 — Example Issue
Section titled “214 — Example Issue”Issue:Asset enrichment failure
Expected:<5% unknown assets
Actual:68% unknown assets
Cause:EDR started reporting FQDN instead of short hostname215 — Example Resolution
Section titled “215 — Example Resolution”PRESERVE FQDN
EXTRACT SHORT NAME
USE ASSET ID WHERE AVAILABLE
UPDATE NORMALIZATION TESTS
REPROCESS AFFECTED DATA216 — Data Pipeline Mental Model
Section titled “216 — Data Pipeline Mental Model”When data arrives, ask:
WHERE DID IT COME FROM? ↓CAN I TRUST THE SOURCE? ↓IS THE RECORD COMPLETE? ↓IS THE FORMAT VALID? ↓WHAT DOES EACH FIELD MEAN? ↓HOW SHOULD IT BE NORMALIZED? ↓IS IT A DUPLICATE? ↓WHAT CONTEXT CAN BE ADDED? ↓HOW FRESH IS THE CONTEXT? ↓WHAT IS UNKNOWN? ↓CAN DOWNSTREAM AUTOMATIONSAFELY USE THIS DATA?217 — Key Security Lesson
Section titled “217 — Key Security Lesson”The most important lesson is:
NORMALIZATIONIS NOT JUSTFORMATTINGIt is the process of ensuring that:
SECURITY DATAHAS CONSISTENTMEANING218 — Final Security Equation
Section titled “218 — Final Security Equation”RAW DATA +VALIDATION +NORMALIZATION +PROVENANCE +DATA QUALITY +CONTEXT =TRUSTWORTHY SECURITY DATARunbook Outcome
Section titled “Runbook Outcome”After completing this runbook you should have:
DOCUMENTED DATA SOURCES
RAW DATA PRESERVATION
SCHEMA VALIDATION
NORMALIZED SECURITY RECORDS
DEDUPLICATION CONTROLS
DATA QUALITY METRICS
SOURCE HEALTH VISIBILITY
TRACEABLE PROVENANCEYour security data is now ready for:
CORRELATION
ANALYTICS
RISK SCORING
REPORTING
SECURITY AUTOMATIONWhat’s Next?
Section titled “What’s Next?”➡️ Runbook 03 — Security API Integration and Failure Handling
The next runbook focuses on safely operating security API integrations.
You will build a repeatable operational procedure covering:
API DISCOVERY ↓AUTHENTICATION ↓LEAST PRIVILEGE ↓REQUEST VALIDATION ↓TIMEOUTS ↓HTTP STATUS HANDLING ↓RATE LIMITS ↓PAGINATION ↓RETRIES ↓BACKOFF ↓PARTIAL FAILURE ↓API HEALTH ↓RECOVERYThe goal will be to ensure that security automation remains reliable when external APIs are slow, unavailable, rate-limited, malformed, or partially failing.