<!-- Copyright (c) 2026 defconxt. All rights reserved. -->
<!-- Licensed under AGPL-3.0 — see LICENSE file for details. -->
---
name: building-detection-as-code
description: >-
  Implement detection-as-code practices for SOC operations including version-
  controlled detection rules, CI/CD pipelines for Sigma/YARA/Splunk detections,
  automated testing, peer review workflows, and deployment to SIEM platforms
  using Git-based workflows.
domain: cybersecurity
subdomain: soc-operations
tags:
  - detection-as-code
  - sigma
  - yara
  - splunk
  - elastic
  - ci-cd
  - git
  - detection-engineering
  - testing
version: "1.0"
author: defconxt
license: AGPL-3.0
metadata:
  mitre-attack: []
---

# Building Detection as Code

## Overview

Detection-as-code applies software engineering practices to security detection
rules. Rules are version-controlled in Git, validated through CI/CD pipelines,
tested against known-good and known-bad data, peer-reviewed, and automatically
deployed to SIEM platforms. This eliminates ad-hoc rule management and ensures
detection quality.

## Prerequisites

| Requirement | Purpose |
|---|---|
| Git repository | Version control for rules |
| CI/CD platform (GitHub Actions/GitLab CI) | Automated validation |
| Sigma CLI (`sigma-cli`) | Rule validation and conversion |
| SIEM API access | Automated deployment |

## Key Concepts

### Repository Structure

```
detection-rules/
├── sigma/
│   ├── windows/
│   │   ├── process_creation/
│   │   │   ├── proc_creation_win_mimikatz.yml
│   │   │   └── proc_creation_win_lolbin_certutil.yml
│   │   ├── registry/
│   │   └── network/
│   ├── linux/
│   └── cloud/
├── yara/
│   ├── malware/
│   └── webshells/
├── splunk/
│   ├── correlation_searches/
│   └── macros/
├── tests/
│   ├── test_data/
│   │   ├── true_positive/
│   │   └── false_positive/
│   └── test_sigma_rules.py
├── .github/
│   └── workflows/
│       ├── validate.yml
│       └── deploy.yml
└── README.md
```

### Sigma Rule with Metadata

```yaml
title: Mimikatz Credential Dumping via CommandLine
id: f018b7a2-3b14-4c5a-9e2d-7f8a6b3c1d4e
status: test
description: |
  Detects Mimikatz execution via command line arguments commonly
  used for credential dumping operations.
references:
  - https://attack.mitre.org/techniques/T1003/001/
author: SOC Team
date: 2026/03/15
modified: 2026/03/15
logsource:
  category: process_creation
  product: windows
detection:
  selection_binary:
    Image|endswith: '\mimikatz.exe'
  selection_args:
    CommandLine|contains:
      - 'sekurlsa::logonpasswords'
      - 'lsadump::sam'
      - 'lsadump::dcsync'
      - 'sekurlsa::pth'
      - 'kerberos::golden'
  condition: selection_binary or selection_args
falsepositives:
  - Legitimate penetration testing with documented authorization
level: critical
tags:
  - attack.credential_access
  - attack.t1003.001
  - attack.t1003.002
```

### CI/CD Pipeline (GitHub Actions)

```yaml
name: Detection Rule Validation
on:
  pull_request:
    paths: ['sigma/**', 'yara/**', 'splunk/**']

jobs:
  validate-sigma:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Install sigma-cli
        run: pip install sigma-cli pySigma-backend-splunk pySigma-backend-elasticsearch
      - name: Validate Sigma rules
        run: |
          sigma check sigma/ --fail-on-error
      - name: Convert to Splunk SPL
        run: |
          sigma convert -t splunk -p splunk_cim sigma/ -o output/splunk/
      - name: Convert to Elastic EQL
        run: |
          sigma convert -t elasticsearch -p ecs_windows sigma/ -o output/elastic/

  validate-yara:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Install YARA
        run: sudo apt-get install -y yara
      - name: Validate YARA rules
        run: |
          find yara/ -name "*.yar" -exec yara -w {} /dev/null \;

  test-detections:
    runs-on: ubuntu-latest
    needs: [validate-sigma]
    steps:
      - uses: actions/checkout@v4
      - name: Run detection tests
        run: python -m pytest tests/ -v

  deploy:
    runs-on: ubuntu-latest
    needs: [validate-sigma, validate-yara, test-detections]
    if: github.ref == 'refs/heads/main'
    steps:
      - name: Deploy to Splunk
        run: |
          python scripts/deploy_splunk.py --rules output/splunk/
        env:
          SPLUNK_URL: ${{ secrets.SPLUNK_URL }}
          SPLUNK_TOKEN: ${{ secrets.SPLUNK_TOKEN }}
```

### Detection Testing Framework

```python
# tests/test_sigma_rules.py
import yaml
import glob
import pytest

REQUIRED_FIELDS = [
    "title", "id", "status", "description",
    "logsource", "detection", "level", "tags",
]


@pytest.fixture(params=glob.glob("sigma/**/*.yml", recursive=True))
def sigma_rule(request):
    with open(request.param) as f:
        return yaml.safe_load(f), request.param


def test_required_fields(sigma_rule):
    rule, path = sigma_rule
    for field in REQUIRED_FIELDS:
        assert field in rule, f"{path}: missing required field '{field}'"


def test_has_attack_tags(sigma_rule):
    rule, path = sigma_rule
    tags = rule.get("tags", [])
    attack_tags = [t for t in tags if t.startswith("attack.")]
    assert len(attack_tags) > 0, f"{path}: missing ATT&CK tags"


def test_false_positives_documented(sigma_rule):
    rule, path = sigma_rule
    fps = rule.get("falsepositives", [])
    assert len(fps) > 0, f"{path}: no false positives documented"
    for fp in fps:
        assert fp != "Unknown", f"{path}: FP entry should be specific"
```

### SIEM Deployment Script

```python
#!/usr/bin/env python3
"""Deploy converted rules to Splunk via REST API."""
import requests
import glob
import os

SPLUNK_URL = os.environ["SPLUNK_URL"]
SPLUNK_TOKEN = os.environ["SPLUNK_TOKEN"]

for rule_file in glob.glob("output/splunk/*.spl"):
    with open(rule_file) as f:
        spl_query = f.read()
    rule_name = os.path.basename(rule_file).replace(".spl", "")
    response = requests.post(
        f"{SPLUNK_URL}/servicesNS/admin/SplunkEnterpriseSecuritySuite"
        f"/saved/searches",
        headers={"Authorization": f"Bearer {SPLUNK_TOKEN}"},
        data={"name": rule_name, "search": spl_query,
              "is_scheduled": "1", "cron_schedule": "*/5 * * * *"},
        verify=False,
    )
    print(f"{rule_name}: {response.status_code}")
```

## Workflow

1. **Write** — Author detection rule in Sigma/YARA format
2. **Test** — Validate against test data (TP and FP samples)
3. **Review** — Submit PR for peer review by detection engineer
4. **Pipeline** — CI validates syntax, converts, runs tests
5. **Merge** — Approved rule merged to main branch
6. **Deploy** — CD pipeline pushes to SIEM platform
7. **Monitor** — Track rule performance (FP rate, fire rate)
8. **Iterate** — Tune based on SOC feedback, commit changes

## Verification

| Check | Method |
|---|---|
| All rules pass CI validation | Pipeline green status |
| ATT&CK tags present | Automated test check |
| FP scenarios documented | pytest rule field validation |
| Converted rules deploy successfully | Deployment log review |
| Peer review before merge | Branch protection enforced |
