Skip to content

rilevera/sumo-detection-as-code

Repository files navigation

sumo-detection-as-code

A minimal, opinionated starter repo for managing Sumo Logic Cloud SIEM rules as code in GitHub. Detections live in YAML, get linted and unit-tested in CI, then deployed to Sumo via the official SumoLogic/sumologic Terraform provider.

This is the companion repo to the blog post "Setting up Detection as Code the Hard Way."

First time here?docs/SETUP.md is the full step-by-step environment guide: Sumo access keys, AWS OIDC, GitHub secrets, branch protection, first deploy, troubleshooting. Start there.


What's in here

rules/                          YAML detection definitions
  aws_cloudtrail_disable_logging.yml
  aws_cloudtrail_root_console_login.yml
  okta_brute_force_single_ip.yml
  _example_failing_rule.yml      <-- deliberately broken; demos the linter

validator/
  schema.py                     JSON Schema for the YAML format
  validate.py                   CLI: schema-check + sanity passes
  compile_to_terraform.py       CLI: YAML -> HCL

terraform/
  providers.tf                  sumologic provider + S3 backend
  main.tf                       (compiled resources are written to generated/)

tests/
  test_validator.py             pytest unit tests for the validator

.github/workflows/
  detection-ci.yml              lint -> plan (PR) -> apply (main)

Local setup

python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt

# Lint every rule
python -m validator.validate rules/

# Run the validator's own unit tests
pytest -q

# Compile YAML -> Terraform (writes terraform/generated/*.tf)
python -m validator.compile_to_terraform

You should see the three real rules pass and _example_failing_rule.yml fail with three distinct errors — that file is intentionally broken to prove the linter is doing something.

Wiring up Sumo Logic + AWS credentials

The full walkthrough — Sumo access keys, AWS OIDC role, S3 state backend, GitHub secrets and environments — is in docs/SETUP.md. Summary of what ends up where:

Name Type What it is
SUMO_ACCESS_ID Repo Secret Sumo API auth
SUMO_ACCESS_KEY Repo Secret Sumo API auth
SUMO_DEPLOYMENT Repo Variable us1 / us2 / eu / …
AWS_ROLE_ARN Repo Variable OIDC role for Terraform state
TF_STATE_BUCKET Repo Variable S3 bucket for Terraform state
TF_STATE_REGION Repo Variable AWS region of that bucket
TF_LOCK_TABLE Repo Variable (optional — only if using DynamoDB locking)

Locally, copy .env.example.env, fill it in, and source it. The Sumo Terraform provider reads its own env-var names (SUMOLOGIC_ACCESSID etc.) — .env.example re-exports our SUMO_* values under the names the provider expects, so you only configure them once.

Add a new detection

  1. Drop a YAML file into rules/ (use one of the existing files as a template).
  2. python -m validator.validate rules/ — fix any errors.
  3. pytest -q — make sure nothing else regressed.
  4. Open a PR. CI runs the linter, compiles to HCL, runs terraform plan, and attaches the plan as an artifact for review.
  5. Merge to main. CI applies to the prod tenant (gated by the prod GitHub environment so a human approves the apply).

YAML schema (cheat sheet)

id: kebab-case-stable-id
name: Human-readable name (shows up in Sumo UI)
type: match | threshold | aggregation | chain | first_seen | outlier
enabled: true
severity: 1-10

expression: |
  metadata_vendor = 'AWS' AND ...

entity_selectors:
  - { entity_type: _ip,       expression: srcDevice_ip }
  - { entity_type: _username, expression: user_username }

signal:
  # name_expression: "..."  # match/aggregation/chain only — drop for threshold/first_seen/outlier
  summary_expression:     "..."
  description_expression: "..."

tags:
  - _mitreAttackTactic:TA0005
  - _mitreAttackTechnique:T1562.008

metadata:
  owner: detection-engineering@example.com
  runbook: https://runbooks.example.com/...
  references: [https://attack.mitre.org/techniques/T1562/008/]

is_prototype: false

# Threshold / aggregation-specific:
group_by: [srcDevice_ip]
window: T10M     # T05M | T10M | T30M | T60M | T12H | T24H | T05D | CUSTOM
count: 10

What this repo is not

  • It doesn't run unit tests against synthetic log events. The Sumo rules engine is server-side, so true "fire this fake event and assert a signal" tests need a Sumo dev tenant. The closest you can get locally is the linter + terraform plan.
  • It doesn't (yet) support every rule type. match and threshold are wired up end-to-end. Aggregation / chain / first-seen / outlier follow the same pattern — see validator/compile_to_terraform.py.

References

About

Companion repo to the 'Detection as Code the Hard Way' blog post. Sumo Logic Cloud SIEM rules as YAML, validated and deployed via Terraform.

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors