Skip to content

devhhu/chronicle-detection-as-code-lab

Repository files navigation

Detection-as-Code Lab (Google SecOps-Inspired)

Experimental project simulating the Detection-as-Code (DaC) lifecycle as it would operate in a Google Chronicle SecOps environment, this is more focused on a bare-bones build as getting access to a Chronicle license, is not an option.

Instead, I’ve decided to build this from a bottom up approach of the expected detection flow, and later dive into how the Chronicle API will fit into this picture

Note: What's not included, as this is experimental
- A full Detection-as-Code CI/CD pipeline which would contain (testing, validating content and use cases, linting and formatting) --> Will be something to  explore later.

Project Structure

.
├── `docker-log-generator/`      # Synthetic mock UDM logs to Fluentd
├── `fluentd/`                   # Collects and buffers logs locally
├── `processed-logs/udm_log/`    # Logging sink (simulates Chronicle UDM ingestion)
├── `scripts/`                   # Custom Python logic to match logs with rules
├── `rules/`                     # YARA-L and YAML rule definitions
├── `reference_lists/`           # Chronicle-style reference lists (IP ranges, etc.)
├── `terraform/`                 # Example rule and datasource definitions (Chronicle-like)
├── `secops_rules.yaml`          # DaC-friendly YAML defining rules to deploy (How it would be operationalised)
├── `secops_reference_lists.yaml`
├── `alerts/`                    # Simulated alerts generated from matching rules
├── `docs/`                      # Extra documentation
├── `Makefile`                   # Easy CLI for bringing the system up/down
└── `tests/`                     # Rule test cases (to be continued)

Project Goal

Engineering Parts:

  • Docker container running fluentd
  • UDM-compatible synthetic logs
  • Custom Python detection engine and alert creation
  • Another script to generate logs for fluentd

Detection Life Cycle Management:

  • Detection logic in YAML/ YARA-L format for handling
  • Looking into Terraform IaC to manage rules and data sources
  • Simulated GitOps model for lifecycle management

High-Level Architecture

image

Step 1: Log Generation

Logs are emitted by docker-log-generator/log_emitter.py, simulating user activity like logins, admin changes, geolocation anomalies, etc. The logs are already UDM-shaped (based on Chronicle’s Unified Data Model) and pushed to Fluentd:

{
  "metadata": {
    "event_timestamp": "2025-08-06T12:34:56Z",
    ...
  },
  "principal": {
    "ip": "8.8.8.8",
    "location": {
      "country_or_region": "RU"
    },
    ...
  },
  "security_result": {
    "action": "LOGIN_SUCCESS",
    ...
  }
}

Step 2: Log Parsing + Matching

Logs are consumed by a custom Python engine in scripts/match_logs_from_fluentd.py, which performs:

  • UDM field normalization
{"metadata":{"event_timestamp":"2025-08-06T13:07:12.122409+00:00","ingested_timestamp":"2025-08-06T13:07:12.122409+00:00"},"product":"gcp","event_type":"LOGIN","vendor_name":"Google","principal":{"email_addresses":["[email protected]"],"ip":"103.27.4.178","hostname":"host-103-27-4-178.reliancejio.com"},"geo":{"country":"IN","is_admin":true},"network":{"asn":"AS55410","asn_name":"Reliance Jio","ip":"103.27.4.178","reverse_dns":"host-103-27-4-178.reliancejio.com"},"security_result":{"severity":"HIGH","rule_name":"None"}}
  • Matching UDM fields against rule conditions
  • Cross-referencing with reference lists (e.g., internal IP ranges)
  • Emitting alerts to the alerts/ folder

This simulates what Chronicle’s Detection Engine would do using the YARA-L rule format.

Step 3: Rules & Reference Lists

YAML/YARA-L Rules define detection logic:

rule: impossible_travel
condition: |
  principal.ip NOT IN private_ip_ranges.txt AND
  principal.location.country_or_region CHANGED_WITHIN 1 HOUR
severity: HIGH
type: anomaly

Reference list example (reference_lists/private_ip_ranges.txt):

10.0.0.0/8
192.168.0.0/16

Step 4: Alerts & Tests

If a match is found, alerts are generated to the alerts/ folder in JSON format. You can also run test cases in tests/ against your rules.

New Detection: impossible_travel_alerts

{
  "metadata": {
    "event_timestamp": "2025-08-06T13:07:14.148646+00:00",
    "ingested_timestamp": "2025-08-06T13:07:14.148646+00:00"
  },
  "locations": [
    {
      "ip": "3.32.132.92",
      "hostname": "host-3-32-132-92.googlellc.com",
      "geo": {
        "country": "US",
        "is_admin": true
      }
    },
    {
      "ip": "142.112.180.19",
      "hostname": "host-142-112-180-19.teluscommunicationsinc.com",
      "geo": {
        "country": "CA",
        "is_admin": true
      }
    }
  ],
  "note": "Two admin logins from different locations within the same second"
}

New Detection: high_volume_login_alerts

[
  {
    "rule_name": "High Volume Login from CA",
    "severity": "MEDIUM",
    "event_count": 15,
    "events": [
      {
        "metadata": {
          "event_timestamp": "2025-08-06T13:07:29.552018+00:00",
          "ingested_timestamp": "2025-08-06T13:07:29.552018+00:00"
        },
        "product": "gcp",
        "event_type": "LOGIN",
        "vendor_name": "Google",
        "principal": {
          "email_addresses": [
            "[email protected]"
          ],
          "ip": "184.108.217.157",
          "hostname": "host-184-108-217-157.teluscommunicationsinc..com"
        },
        "geo": {
          "country": "CA",
          "is_admin": true
        },
        "network": {
          "asn": "AS852",
          "asn_name": "TELUS Communications Inc.",
          "ip": "184.108.217.157",
          "reverse_dns": "host-184-108-217-157.teluscommunicationsinc..com"
        },
        "security_result": {
          "severity": "HIGH",
          "rule_name": "None"
        }
      },

Step 5: Terraform Emulation

The terraform/ folder simulates how you would actually deploy your resources in a real world environment using the Chronicle API. Each rule can be defined in .tf files and governed via secops_rules.yaml.

You would need to add the UDM fields that are populated for your datasources in here:

File Name: gcp_audit_logsource.tf

In a real Chronicle deployment, these .tf files would use the Chronicle Terraform provider to push rules via API.

Summary

How would leveraging Chronicle API help with Detection-as-Code

This is a more focused table of Chronicle APIs that will be useful for creating, updating, validating and managing detection content like rules, reference lists and data sources.

| Resource Type             | Endpoint                                       | Method   | Description                      | DaC Use Case                                                   |
| ------------------------- | ---------------------------------------------- | -------- | -------------------------------- | -------------------------------------------------------------- |
| **Detection Rules**       | `/v1/detect/rules`                             | `POST`   | Create new YARA-L detection rule | Create rule from GitHub-pushed code                            |
|                           | `/v1/detect/rules/{rule_id}`                   | `PATCH`  | Update an existing rule          | Update rule when a PR is merged                                |
|                           | `/v1/detect/rules/{rule_id}`                   | `DELETE` | Delete a rule                    | Remove deprecated or broken rules                              |
|                           | `/v1/detect/rules`                             | `GET`    | List all existing rules          | Validate drift between Git and Chronicle                       |
|                           | `/v1/detect/rules:validate`                    | `POST`   | Validate rule syntax (dry run)   | Lint rule pre-merge or CI check                                |
| **Rule Alert Counts**     | `/v1/detect/rules/{rule_id}:getAlertStats`     | `GET`    | Get alert stats (volume)         | Prioritize tuning noisy rules                                  |
| **Rule Execution Logs**   | `/v1/detect/rules/{rule_id}:getExecutionStats` | `GET`    | Get match execution stats        | Analyze performance of rules                                   |
| **Reference Lists**       | `/v1/detect/referenceLists`                    | `POST`   | Create new reference list        | Add threat intel or allowlists from Git                        |
|                           | `/v1/detect/referenceLists/{list_id}`          | `PATCH`  | Update reference list            | Update indicators/IPs regularly                                |
|                           | `/v1/detect/referenceLists`                    | `GET`    | List all reference lists         | Audit existing lists vs repo                                   |
|                           | `/v1/detect/referenceLists/{list_id}`          | `DELETE` | Delete reference list            | Remove stale lists                                             |
| **Data Sources**          | `/v2/assets/dataSources`                       | `POST`   | Create new data source           | Register new log sources programmatically                      |
|                           | `/v2/assets/dataSources`                       | `GET`    | List data sources                | Validate ingestion sources match code                          |
| **Parsers (UDM Mapping)** | `/v1/ingestion/parsers` *(limited access)*     | `POST`   | Deploy custom parsers            | Align parser changes with rule logic (requires partner access) |
| **Detection Reports**     | `/v1/detect/reports`                           | `GET`    | Retrieve rule reports            | Track rule health and triage history                           |
| **Auth (OAuth2)**         | `https://oauth2.googleapis.com/token`          | `POST`   | Get access token for API         | Required for all programmatic DaC actions                      |

Template Chronicle Github Repo

.
├── .github/
│   └── workflows/
│       └── detect.yaml         <-- CI/CD pipeline
├── rules/
│   ├── detection_rule_1.yaral
│   ├── detection_rule_2.yaral
│   └── metadata.yaml
├── reference_lists/
│   └── high_risk_ips.yaml
├── tests/
│   └── test_rules.py           <-- (optional) unit tests
├── tools/
│   └── push_to_chronicle.py    <-- Helper script for API calls
├── README.md
└── terraform/                  <-- Optional DaC Terraform setup

Potential CI/CD pipeline flow

flowchart TD
    A[Push to GitHub - main/dev branch] --> B[GitHub Actions Triggered]
    B --> C[Validate Syntax - rules:validate API]
    C --> D{Did Validation Pass?}
    D -- Yes --> E[Deploy to Chronicle API - rules & lists]
    D -- No --> F[Fail CI - Comment on PR]
    E --> G[Check Drift or Sync State]
    G --> H[Post Summary as GitHub PR Comment]

Loading

References

About

Experimenting with Detection-as-Code and how it could be used with Google SecOps:

Topics

Resources

Stars

Watchers

Forks