Skip to content
Merged
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
1 change: 1 addition & 0 deletions BUILD_WEEK.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ Work started during the submission period includes:
|---|---|---|
| Phase 1 | Reproducible randomized incident generation and repository stabilization | Issue #90 / PR #91 |
| Phase 2 | Argus findings and entity posture synchronization with the Sentinel World Model | Issue #92 |
| Phase 3 | Cluster-free setup, launch, simulation, and troubleshooting path | Issue #94 |

### Phase 2 — World Model integration

Expand Down
28 changes: 27 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
.PHONY: help cluster-up cluster-down cluster-status deploy-cilium deploy-falco \
deploy-kyverno deploy-observability deploy-agent deploy-ui \
hubble-ui grafana-ui k9s test test-agent test-ui simulate-threats clean
setup-local dev-agent dev-ui demo-local hubble-ui grafana-ui k9s \
test test-agent test-ui simulate-threats clean

THREAT_COUNT ?= 10
THREAT_SCENARIO ?= mixed
Expand All @@ -24,6 +25,10 @@ help:
@echo " make deploy-observability Install Prometheus + Grafana + Loki"
@echo ""
@echo " Application"
@echo " make setup-local Install local backend and UI dependencies"
@echo " make demo-local Start a populated cluster-free demo"
@echo " make dev-agent Start only the backend on localhost:8000"
@echo " make dev-ui Start only the console on localhost:5173"
@echo " make deploy-agent Build and deploy AI agent"
@echo " make deploy-ui Build and deploy React UI"
@echo ""
Expand Down Expand Up @@ -88,6 +93,22 @@ deploy-agent:
deploy-ui:
@echo "TODO: implement in Module 5"

setup-local:
python3 -m venv .venv
.venv/bin/pip install -r agent/requirements.txt
npm --prefix ui ci

dev-agent:
@test -x .venv/bin/python || (echo "Missing local environment. Run: make setup-local" && exit 1)
@cd agent/src && ../../.venv/bin/python -m uvicorn main:app --reload --host 127.0.0.1 --port 8000

dev-ui:
@test -d ui/node_modules || (echo "Missing UI dependencies. Run: make setup-local" && exit 1)
@npm --prefix ui run dev -- --host 127.0.0.1

demo-local:
@bash scripts/demo-local.sh "$(THREAT_COUNT)" "$(THREAT_SCENARIO)" "$(THREAT_SEED)"

test: test-agent test-ui

test-agent:
Expand All @@ -97,6 +118,11 @@ test-ui:
@npm --prefix ui run build

simulate-threats:
@curl --fail --silent http://localhost:8000/health >/dev/null || \
(echo "Argus backend is not running on localhost:8000."; \
echo "Start it with: make dev-agent"; \
echo "Or launch the complete cluster-free demo with: make demo-local"; \
exit 1)
@curl --fail --silent --show-error \
-X POST http://localhost:8000/simulate-threats \
-H "Content-Type: application/json" \
Expand Down
53 changes: 38 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,31 @@ Commit history: https://github.com/CodeBuildder/argus-k8s/commits/main
</a>
</p>

## Quickstart — no cluster required

The fastest path to a populated Argus console requires only Python, Node.js, npm, and
curl. It does **not** require OrbStack, Kubernetes, Falco, Cilium, an API key, or cloud
infrastructure.

```bash
make setup-local
make demo-local
```

Then open **http://127.0.0.1:5173**.

`make demo-local` starts the backend and UI, waits for the backend health check, and
generates ten randomized incidents. Press `Ctrl-C` to stop both services. For every
command, expected result, testing mode, and troubleshooting path, follow the
**[Getting Started guide](docs/GETTING_STARTED.md)**.

### Two testing modes

| Mode | Command | Cluster required? | Evidence |
|---|---|---:|---|
| Local synthetic | `make demo-local` | No | Generated incidents for console and workflow testing |
| Full Kubernetes | `bash cluster/test-diverse-threats.sh` | Yes | Real Falco, Cilium, and Kyverno signals |

## Part of the Sentinel multi-agent platform

Argus is the security domain agent in a larger autonomous-infrastructure system. It
Expand Down Expand Up @@ -249,7 +274,10 @@ Kyverno catches a separate category of threat — workloads that violate securit
| 4 — Detection Agent | Falco webhook, context enrichment, reasoning layer, action router | Complete |
| 5 — Command & Control UI | React console, threat feed, approval queue, cluster map | In Progress |

## Local setup
## Full Kubernetes setup

Start with the cluster-free [Quickstart](#quickstart--no-cluster-required) unless you
specifically need real kernel, network, and admission-control evidence.

### Prerequisites
- macOS (Apple Silicon M-series)
Expand All @@ -269,39 +297,34 @@ make cluster-status
cilium hubble ui
```

### Run locally (development)
### Run services separately

**Backend agent:**
```bash
cd agent/src
source ../.env
uvicorn main:app --reload --port 8000
make dev-agent
```

**Console UI:**
```bash
cd ui
npm install
npm run dev
make dev-ui
```

The UI runs at `http://localhost:5173` and proxies `/api/*` to the agent at port 8000.

To populate the console with sample incidents:
The backend must be running before generating incidents. To populate the console:
```bash
curl -X POST http://localhost:8000/simulate-threats \
-H "Content-Type: application/json" \
-d '{"count": 10, "scenario": "mixed"}'
make simulate-threats THREAT_COUNT=10 THREAT_SCENARIO=mixed
```

The generator randomizes threat type, workload, blast radius, enrichment evidence, and
recommended response. Use a seed to replay the exact same selection during tests or a
recorded demo:

```bash
curl -X POST http://localhost:8000/simulate-threats \
-H "Content-Type: application/json" \
-d '{"count": 10, "scenario": "mixed", "seed": 20260717}'
make simulate-threats \
THREAT_COUNT=10 \
THREAT_SCENARIO=mixed \
THREAT_SEED=20260717
```

Supported scenarios are `mixed`, `human_approval`, and `attack_chain`. The response
Expand Down
140 changes: 140 additions & 0 deletions docs/GETTING_STARTED.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
# Getting Started

This guide provides one path from a fresh checkout to a populated Argus console. Start
with local synthetic mode. Use full-cluster mode only when you specifically need real
Falco, Cilium, or Kyverno evidence.

## Choose a mode

| Mode | What it proves | Requires Kubernetes? |
|---|---|---:|
| Local synthetic | API, console, approvals, attack chains, and incident workflows | No |
| Full cluster | Real syscall, network, and admission-control detections | Yes |

## Local synthetic mode

### Prerequisites

- Python 3.11 or newer
- Node.js 18 or newer
- npm
- curl

No API key, OrbStack VM, Kubernetes cluster, Falco, Cilium, or Kyverno installation is
required.

### 1. Install dependencies

From the repository root:

```bash
make setup-local
```

This creates `.venv`, installs the agent requirements, and installs the locked UI
dependencies with `npm ci`.

### 2. Launch the populated demo

```bash
make demo-local
```

The command performs the complete startup sequence:

1. Verify local dependencies.
2. Confirm ports 8000 and 5173 are available.
3. Start the FastAPI agent.
4. Start the Vite console.
5. Wait for `/health` to succeed.
6. Generate ten mixed incidents.
7. Print the console and API URLs.

Open [http://127.0.0.1:5173](http://127.0.0.1:5173). Press `Ctrl-C` in the terminal to
stop both services.

### 3. Generate another batch

While `make demo-local` is running, use a second terminal:

```bash
make simulate-threats THREAT_COUNT=10 THREAT_SCENARIO=mixed
```

Supported scenarios:

| Scenario | Result |
|---|---|
| `mixed` | Random Falco, Kyverno, Cilium, and kernel-style incidents |
| `human_approval` | Incidents routed into the approval queue |
| `attack_chain` | Ordered incidents designed to form a correlated chain |

Replay a known incident selection:

```bash
make simulate-threats \
THREAT_COUNT=10 \
THREAT_SCENARIO=attack_chain \
THREAT_SEED=20260717
```

The API returns the effective seed for every unseeded run. Preserve it when you need an
identical selection later.

### Run services separately

Use this only when developing one service:

```bash
make dev-agent
```

In another terminal:

```bash
make dev-ui
```

The UI proxies `/api/*` to the agent at `http://127.0.0.1:8000`.

### Local-mode limitations

- Incidents are stored in memory and disappear when the backend stops.
- Kubernetes telemetry is unavailable, so cluster-derived panels may be empty or degraded.
- Generated incidents exercise application workflows; they are not real Falco detections.
- Automated Kubernetes remediation is not executed without a cluster.

## Full-cluster mode

Full-cluster mode provisions three k3s nodes on OrbStack and deploys Cilium, Falco,
Kyverno, Prometheus, Grafana, Loki, and Argus. Follow [setup.md](../setup.md) for the
complete prerequisites and deployment sequence.

After the stack is healthy, create real policy-compliant workloads that trigger runtime
rules:

```bash
bash cluster/test-diverse-threats.sh
```

This script requires a working `kubectl` context. It creates real pods and runs continuously
until those pods are deleted.

## Troubleshooting

| Symptom | Cause | Fix |
|---|---|---|
| `curl: (7) Failed to connect to localhost port 8000` | Agent is not running | Run `make dev-agent` or `make demo-local` |
| `Missing local environment` | Python dependencies are not installed | Run `make setup-local` |
| Port 8000 or 5173 is already in use | Another local service is running | Stop it, then rerun `make demo-local` |
| Console opens but has no incidents | The backend was restarted or never seeded | Run `make simulate-threats` |
| Cluster panels show no live data | Local synthetic mode has no Kubernetes telemetry | Use full-cluster mode for real telemetry |
| `kubectl` connection failure | Full-cluster mode is not configured | Complete [setup.md](../setup.md) |

## Verify the repository

```bash
make test
```

This runs the complete backend test suite and a production UI build.
102 changes: 102 additions & 0 deletions scripts/demo-local.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
#!/usr/bin/env bash
set -Eeuo pipefail

repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
threat_count="${1:-10}"
threat_scenario="${2:-mixed}"
threat_seed="${3:-}"
agent_pid=""
ui_pid=""

cleanup() {
trap - INT TERM EXIT
if [[ -n "${agent_pid}" ]]; then
kill "${agent_pid}" 2>/dev/null || true
wait "${agent_pid}" 2>/dev/null || true
fi
if [[ -n "${ui_pid}" ]]; then
kill "${ui_pid}" 2>/dev/null || true
wait "${ui_pid}" 2>/dev/null || true
fi
echo "Argus local demo stopped."
}

stop_cleanly() {
cleanup
exit 0
}

trap stop_cleanly INT TERM
trap cleanup EXIT

if [[ ! -x "${repo_root}/.venv/bin/python" || ! -d "${repo_root}/ui/node_modules" ]]; then
echo "Local dependencies are not installed."
echo "Run: make setup-local"
exit 1
fi

if curl --fail --silent http://127.0.0.1:8000/health >/dev/null 2>&1; then
echo "Port 8000 already has an Argus backend running. Stop it before using make demo-local."
exit 1
fi

if curl --fail --silent http://127.0.0.1:5173 >/dev/null 2>&1; then
echo "Port 5173 is already in use. Stop that service before using make demo-local."
exit 1
fi

echo "Starting Argus backend at http://127.0.0.1:8000 ..."
(
cd "${repo_root}/agent/src"
exec ../../.venv/bin/python -m uvicorn main:app --host 127.0.0.1 --port 8000
) &
agent_pid=$!

echo "Starting Argus console at http://127.0.0.1:5173 ..."
npm --prefix "${repo_root}/ui" run dev -- --host 127.0.0.1 &
ui_pid=$!

backend_ready=false
for _attempt in $(seq 1 30); do
if curl --fail --silent http://127.0.0.1:8000/health >/dev/null 2>&1; then
backend_ready=true
break
fi
if ! kill -0 "${agent_pid}" 2>/dev/null; then
echo "Argus backend exited before becoming ready."
exit 1
fi
if ! kill -0 "${ui_pid}" 2>/dev/null; then
echo "Argus console exited before the backend became ready."
exit 1
fi
sleep 1
done

if [[ "${backend_ready}" != "true" ]]; then
echo "Argus backend did not become ready within 30 seconds."
exit 1
fi

seed_field=""
if [[ -n "${threat_seed}" ]]; then
seed_field=", \"seed\": ${threat_seed}"
fi

echo "Generating ${threat_count} '${threat_scenario}' incidents ..."
simulation_response="$(curl --fail --silent --show-error \
-X POST http://127.0.0.1:8000/simulate-threats \
-H "Content-Type: application/json" \
-d "{\"count\": ${threat_count}, \"scenario\": \"${threat_scenario}\"${seed_field}}")"

echo "${simulation_response}"
echo ""
echo "Argus is ready:"
echo " Console: http://127.0.0.1:5173"
echo " API docs: http://127.0.0.1:8000/docs"
echo " Health: http://127.0.0.1:8000/health"
echo ""
echo "No Kubernetes cluster is being used. Incidents are stored in memory."
echo "Press Ctrl-C to stop the backend and console."

wait "${agent_pid}"
Loading