# curadise-agent

Async monitoring agent for Curadise - collects system metrics, sends heartbeats, and executes remote commands with security-first design.

## Features

- **Async-first architecture** - Built on `anyio` for high-performance concurrent operations
- **System metrics collection** - CPU, memory, disk, network via `psutil`
- **HTTP health checks** - Monitor endpoints with customizable checks
- **Buffered transport** - In-memory buffer with optional persistence for reliability
- **Heartbeat service** - Regular health reporting with automatic reconnection
- **Remote command execution** - Secure sandboxed execution with allowlist/denylist
- **mTLS support** - Mutual TLS authentication for secure communication
- **JWT authentication** - Token-based auth with automatic refresh
- **Hot-reload configuration** - Watch config files for changes without restart
- **Structured logging** - JSON logging via `structlog` for easy parsing
- **Auto-remediation** - Server-driven playbooks with detection rules
- **Detection checks** - Command, HTTP, process, and log pattern monitoring
- **Signed playbooks** - ECDSA-SHA256 signature verification
- **Rate limiting** - Configurable cooldowns and max remediations per hour
- **Dry-run mode** - Test remediation without executing

## Requirements

- Python 3.12+
- Linux or macOS

## Installation

```bash
# Using pip
pip install curadise-agent

# Using uv (recommended)
uv pip install curadise-agent

# From source
git clone https://github.com/pysingh09/curadise-agent.git
cd curadise-agent
uv pip install -e .
```

## Quick Start

1. Create a configuration file:

```bash
cp examples/agent.yaml /etc/curadise/agent.yaml
```

2. Set your enrollment token:

```bash
export CURADISE_ENROLLMENT_TOKEN="your-token-here"
```

3. Run the agent:

```bash
curadise-agent run --config /etc/curadise/agent.yaml
```

## CLI Commands

```bash
# Run the agent
curadise-agent run --config agent.yaml

# Check agent version
curadise-agent version

# Validate configuration
curadise-agent config validate --config agent.yaml

# Show effective configuration
curadise-agent config show --config agent.yaml

# Register agent with server
curadise-agent register --token <enrollment-token>

# Check agent status
curadise-agent status

# Unregister agent
curadise-agent unregister
```

## Configuration

The agent is configured via YAML files with Jinja2 templating support for environment variables.

### Minimal Configuration

```yaml
server:
  url: "https://curadise.example.com"

auth:
  enrollment_token: "{{ env('CURADISE_ENROLLMENT_TOKEN') }}"
```

### Key Configuration Sections

| Section | Description |
|---------|-------------|
| `server` | Server URL, timeout, SSL settings |
| `auth` | Enrollment token, mTLS certificates |
| `buffer` | Memory buffer size, persistence, batching |
| `retry` | Retry attempts, backoff, circuit breaker |
| `heartbeat` | Heartbeat interval and health metrics |
| `collectors` | System metrics and HTTP check configuration |
| `executor` | Command execution settings and allowlist |
| `remediation` | Auto-remediation settings and playbook controls |
| `logging` | Log level, format, and file rotation |
| `state` | Persistent state directory |
| `tags` | Custom tags for metrics and heartbeats |

See `examples/agent.yaml` for a complete configuration reference.

### Remediation Configuration

```yaml
remediation:
  enabled: false
  sync_interval: 300.0
  check_interval: 60.0
  max_concurrent: 1
  max_remediations_per_hour: 20
  require_signature: true
  dry_run: false
```

| Option | Default | Description |
|--------|---------|-------------|
| `enabled` | `false` | Enable auto-remediation service |
| `sync_interval` | `300.0` | Seconds between playbook sync from server |
| `check_interval` | `60.0` | Seconds between detection rule checks |
| `max_concurrent` | `1` | Max concurrent remediation executions |
| `max_remediations_per_hour` | `20` | Rate limit for remediation actions |
| `require_signature` | `true` | Require ECDSA-SHA256 signatures on playbooks |
| `dry_run` | `false` | Log actions without executing |

### Environment Variables

Configuration values can reference environment variables:

```yaml
auth:
  enrollment_token: "{{ env('CURADISE_ENROLLMENT_TOKEN') }}"

http_checks:
  - url: "https://api.example.com/health"
    headers:
      Authorization: "Bearer {{ env('API_TOKEN') }}"
```

## Architecture

```
curadise-agent/
├── src/curadise_agent/
│   ├── auth/          # JWT tokens, mTLS, registration
│   ├── collectors/    # Metrics collectors (system, HTTP)
│   ├── config/        # Configuration loading, schema, watcher
│   ├── executor/      # Command execution with sandbox
│   ├── heartbeat/     # Heartbeat service and health checks
│   ├── models/        # Pydantic models (domain, API)
│   ├── remediation/   # Auto-remediation with playbooks
│   ├── state/         # Persistent state management
│   ├── transport/     # HTTP client, buffering, batching
│   └── utils/         # Logging, retry, shutdown handling
└── tests/
    ├── unit/          # Unit tests
    └── integration/   # Integration tests
```

## Development

### Setup

```bash
# Clone the repository
git clone https://github.com/pysingh09/curadise-agent.git
cd curadise-agent

# Create virtual environment
uv venv
source .venv/bin/activate

# Install with dev dependencies
uv pip install -e ".[dev]"

# Install pre-commit hooks
pre-commit install
```

### Running Tests

```bash
# Run all tests
pytest

# Run with coverage
pytest --cov=curadise_agent --cov-report=html

# Run only unit tests
pytest tests/unit/

# Run integration tests
pytest tests/integration/ -m integration
```

### Code Quality

```bash
# Linting
ruff check src/ tests/

# Type checking
mypy src/

# Format code
ruff format src/ tests/
```

## Security

The agent implements defense-in-depth security:

### Command Execution
- **No shell injection** - Uses `subprocess_exec`, not `subprocess_shell`
- **Character blocklist** - Rejects dangerous shell metacharacters
- **Executable allowlist** - Only approved binaries can run

### Network Security
- **SSRF prevention** - Blocks internal IPs (10.x, 172.16.x, 192.168.x, 127.x, 169.254.x)
- **DNS rebinding protection** - Validates resolved IPs before requests
- **Scheme validation** - Only HTTP/HTTPS allowed

### File System Security
- **Path traversal prevention** - Uses `realpath()` with symlink resolution
- **Allowed path prefixes** - Files must be under configured directories

### Cryptographic Security
- **Playbook signatures** - ECDSA-SHA256 verification required
- **Nonce replay prevention** - 24-hour expiration window
- **JWT with refresh** - Short-lived tokens with automatic refresh

### General
- **mTLS support** - Mutual TLS for server authentication
- **No secrets in config** - Use environment variables for sensitive data

## License

MIT License - see LICENSE file for details.
