Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .github/workflows/ci-cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,14 @@ jobs:
- name: Check formatting
run: cargo fmt --all -- --check

demo-validate:
name: Demo script validation
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Validate local demo helpers
run: ./examples/demo/validate.sh

# ── Clippy ──────────────────────────────────────────────────────────────────
# Run on all platforms so Linux-specific code (aya, libc), Windows-specific
# code (ferrisetw, windows-rs), and macOS-specific code are each linted
Expand Down
18 changes: 18 additions & 0 deletions docs/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,18 +71,36 @@ Confirm that an alert was written:
Get-Content .\logs\alerts.json.*
```

Or use the end-to-end demo helper:

```powershell
.\examples\demo\run-local-demo.ps1
```

=== "Linux"

```bash
cat logs/alerts.json.*
```

Or use the end-to-end demo helper:

```bash
./examples/demo/run-local-demo.sh
```

=== "macOS"

```bash
cat logs/alerts.json.*
```

Or use the end-to-end demo helper:

```bash
./examples/demo/run-local-demo.sh
```

Bundled demo rules:

| Platform | Rule |
Expand Down
89 changes: 89 additions & 0 deletions examples/demo/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# Local Demo Script

End-to-end helper for the bundled `whoami` Sigma demo: verify prerequisites,
fire the trigger, wait for an alert, and print the latest ECS NDJSON line from
today's alert file.

The scripts read `alerts.directory` and `alerts.filename` from `config.toml`
(defaults: `logs` and `alerts.json`), then watch
`{directory}/{filename}.{YYYY-MM-DD}`.

Rustinel must already be running in another terminal:

```bash
sudo ./rustinel run
```

## Linux & macOS

From the Rustinel install directory (where `config.toml` and `rules/` live):

```bash
./examples/demo/run-local-demo.sh
```

Options:

```text
--root PATH Rustinel install directory (default: auto-detect)
--trigger-only Skip agent and prerequisite checks
--timeout SECS Seconds to wait for a new alert (default: 15)
--siem NAME Print next-step commands for elastic or splunk
-h, --help Show this help
```

## Windows

From an elevated PowerShell in the install directory:

```powershell
.\examples\demo\run-local-demo.ps1
```

Options:

```text
-Root PATH Rustinel install directory (default: auto-detect)
-TriggerOnly Skip agent and prerequisite checks
-TimeoutSeconds Seconds to wait for a new alert (default: 15)
-Siem elastic|splunk Print next-step commands for a SIEM demo
-Help Show this help
```

## Expected success

On success the script exits `0` and prints the latest alert, for example:

```json
{
"@timestamp": "...",
"event": { "kind": "alert", ... },
"rule": { "name": "Example - Whoami Execution (Linux)", ... }
}
```

## Validation

Run the lightweight checks for config parsing and argument handling:

```bash
./examples/demo/validate.sh
```

## SIEM next steps

After a local alert is confirmed:

```bash
./examples/demo/run-local-demo.sh --siem elastic
./examples/demo/run-local-demo.sh --siem splunk
```

See [SIEM Demos](../../docs/siem-demos.md) for full Elastic and Splunk lab setup.

## Troubleshooting

- **Agent not running** — start Rustinel first (`sudo ./rustinel run` on Linux/macOS).
- **Timeout** — confirm bundled rules are present under `rules/sigma/` and Sigma is enabled in `config.toml`.
- **Custom alert paths** — set `[alerts].directory` and `[alerts].filename` in `config.toml`; the demo scripts follow those values.
- **macOS** — support is experimental; see [Getting Started](../../docs/getting-started.md).
105 changes: 105 additions & 0 deletions examples/demo/lib.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
#!/usr/bin/env bash
# Shared helpers for examples/demo scripts.

read_toml_value() {
local section="$1"
local key="$2"
local file="$3"

awk -v section="[$section]" -v key="$key" '
BEGIN { in_section = 0 }
$0 == section { in_section = 1; next }
/^\[/ { in_section = 0 }
in_section && $1 == key {
line = $0
sub(/^[^=]*=[ \t]*/, "", line)
sub(/[ \t]*#.*$/, "", line)
gsub(/^[ \t]+|[ \t]+$/, "", line)
gsub(/^"/, "", line)
gsub(/"$/, "", line)
gsub(/^'\''/, "", line)
gsub(/'\''$/, "", line)
print line
exit
}
' "$file"
}

read_alerts_config() {
local root="$1"
local config_file="$root/config.toml"
local alerts_dir alerts_filename

if [[ ! -f "$config_file" ]]; then
return 1
fi

alerts_dir="$(read_toml_value alerts directory "$config_file")"
alerts_filename="$(read_toml_value alerts filename "$config_file")"

[[ -z "$alerts_dir" ]] && alerts_dir="logs"
[[ -z "$alerts_filename" ]] && alerts_filename="alerts.json"

if [[ "$alerts_dir" != /* ]]; then
alerts_dir="$root/$alerts_dir"
fi

printf '%s\n%s\n' "$alerts_dir" "$alerts_filename"
}

today_date() {
date +%Y-%m-%d
}

today_alert_file() {
local alerts_dir="$1"
local alerts_filename="$2"

printf '%s/%s.%s' "$alerts_dir" "$alerts_filename" "$(today_date)"
}

now_ms() {
if command -v python3 >/dev/null 2>&1; then
python3 -c 'import time; print(int(time.time() * 1000))'
else
echo $(( $(date +%s) * 1000 ))
fi
}

alert_file_line_count() {
local file="$1"

if [[ ! -f "$file" ]]; then
echo 0
return
fi

wc -l <"$file" | tr -d ' '
}

latest_alert_line() {
local alerts_dir="$1"
local alerts_filename="$2"
local today_file latest_file="" file

today_file="$(today_alert_file "$alerts_dir" "$alerts_filename")"
if [[ -f "$today_file" ]]; then
tail -n 1 "$today_file"
return 0
fi

shopt -s nullglob
local files=("$alerts_dir/$alerts_filename".*)
for file in "${files[@]}"; do
if [[ -z "$latest_file" || "$file" -nt "$latest_file" ]]; then
latest_file="$file"
fi
done
shopt -u nullglob

if [[ -z "$latest_file" ]]; then
return 1
fi

tail -n 1 "$latest_file"
}
Loading
Loading