Files
Salus/README.md
2026-04-27 14:47:35 +02:00

193 lines
5.8 KiB
Markdown

# Omada AP Manager
A web-based tool for viewing and rebooting TP-Link Omada access points.
Secured via Authentik OIDC, with a full audit log exported as CSV.
---
## Features
- Live AP list fetched from Omada Controller (status, uptime, model, IP, MAC)
- Single and bulk reboot with confirmation modal
- Full audit log (who rebooted which AP, when, and whether it succeeded)
- CSV export of the entire audit log
- Authentik OIDC login (Authorization Code Flow)
- Deployable as a Docker container via Portainer
---
## Prerequisites
| Component | Version |
|-----------|---------|
| Omada Controller | 5.x or later |
| Authentik | Any recent self-hosted version |
| Docker / Portainer | Docker 20+ |
| Nginx Proxy Manager | Any recent version |
---
## 1. Authentik: Create an OAuth2 Provider + Application
### 1.1 Create an OAuth2 Provider
1. In Authentik, go to **Admin → Providers → Create**.
2. Choose **OAuth2/OpenID Provider**.
3. Fill in:
- **Name**: `qwe-salus`
- **Authorization flow**: your default authorization flow
- **Client type**: `Confidential`
- **Client ID**: auto-generated (copy it)
- **Client Secret**: auto-generated (copy it)
- **Redirect URIs**: `https://salus.qwe.stranto.com/auth/callback`
- **Scopes**: `openid`, `profile`, `email`
- **Subject mode**: `Based on the User's username` (or `hashed user ID`)
4. Save.
### 1.2 Create an Application
1. Go to **Admin → Applications → Create**.
2. Fill in:
- **Name**: `Omada AP Manager`
- **Slug**: `qwe-salus`
- **Provider**: select the provider created above
3. Save.
### 1.3 Note the Issuer URL
The issuer URL follows the pattern:
```
https://<your-authentik-domain>/application/o/<application-slug>/
```
Example: `https://auth.stranto.com/application/o/qwe-salus/`
---
## 2. Omada Controller: Create an API User
1. In Omada Controller, go to **Settings → Administrators**.
2. Create a **local admin** account (not linked to OIDC):
- Username: `api-user`
- Password: a strong, unique password
- Role: **Viewer** is enough for listing APs; needs **Administrator** role to send reboot commands.
3. Note the username and password — these go into `OMADA_USERNAME` / `OMADA_PASSWORD`.
**Required permissions for the API user:**
- Read access to site and AP data
- Execute device commands (for reboot)
> If self-signed certs are used, set `OMADA_VERIFY_SSL=false`.
---
## 3. Deploy via Portainer (Stack)
### 3.1 Build the image first (on the Docker host)
```bash
git clone <this-repo> qwe-salus
cd qwe-salus
docker build -t qwe-salus:latest .
```
Or add a `build: .` section in the stack (Portainer will build it if the source is available).
### 3.2 Create a Portainer Stack
1. In Portainer, go to **Stacks → Add stack**.
2. Paste the contents of `docker-compose.yml`.
3. Fill in all environment variable values (see table below).
4. Click **Deploy the stack**.
### Environment Variables
| Variable | Description | Example |
|----------|-------------|---------|
| `OMADA_BASE_URL` | Base URL of the Omada Controller | `https://192.168.1.1:8043` |
| `OMADA_USERNAME` | Local Omada admin username | `api-user` |
| `OMADA_PASSWORD` | Local Omada admin password | `s3cr3t` |
| `OMADA_SITE_NAME` | Site name in Omada | `Default` |
| `OMADA_VERIFY_SSL` | Set to `false` for self-signed certs | `false` |
| `AUTHENTIK_ISSUER` | OIDC issuer URL from Authentik | `https://auth.example.com/application/o/slug/` |
| `AUTHENTIK_CLIENT_ID` | OAuth2 client ID from Authentik | `abc123...` |
| `AUTHENTIK_CLIENT_SECRET` | OAuth2 client secret from Authentik | `xyz789...` |
| `AUTHENTIK_REDIRECT_URI` | Must match what Authentik has configured | `https://salus.example.com/auth/callback` |
| `SESSION_SECRET_KEY` | Random secret for cookie signing — **change this!** | `openssl rand -hex 32` |
| `DB_PATH` | Path to the SQLite database inside the container | `/data/audit.db` |
### Generating a SESSION_SECRET_KEY
```bash
openssl rand -hex 32
```
---
## 4. Nginx Proxy Manager Setup
1. Add a **Proxy Host**:
- **Domain Names**: `salus.qwe.stranto.com`
- **Forward Hostname / IP**: the Docker host IP (or container name if on the same network)
- **Forward Port**: `8098`
- Enable **Websockets Support** (optional but harmless)
2. Under **SSL**, issue/select a Let's Encrypt certificate.
3. **Important**: The app uses `--proxy-headers` in uvicorn so it correctly handles `X-Forwarded-For` and `X-Forwarded-Proto` from NPM.
---
## 5. Accessing the Audit Log CSV Export
Once logged in, navigate to **Audit Log** (top navigation) and click **Export CSV**.
The file is named `audit_log_YYYY-MM-DD.csv` and contains:
| Column | Description |
|--------|-------------|
| Timestamp (UTC) | ISO 8601 timestamp |
| Username | OIDC `preferred_username` |
| Email | OIDC `email` claim |
| AP Name | Name as shown in Omada |
| MAC | AP MAC address |
| IP | AP IP address |
| Result | `success` or `error` |
| Error | Error message if result is `error` |
---
## Local Development
```bash
# Create a .env file
cp .env.example .env # edit with your values
pip install -r requirements.txt
# SQLite DB will be written to /data/audit.db by default
# override for local dev:
export DB_PATH=./audit.db
uvicorn app.main:app --reload --port 8080
```
---
## Project Structure
```
qwe-salus/
├── app/
│ ├── main.py # FastAPI routes
│ ├── auth.py # Authentik OIDC logic
│ ├── omada.py # Omada Controller API client
│ ├── database.py # SQLAlchemy models + DB init
│ ├── templates/
│ │ ├── base.html # Nav, toast system
│ │ ├── login.html # Login landing page
│ │ ├── index.html # AP list + reboot UI
│ │ └── audit.html # Audit log + CSV export
│ └── static/
├── Dockerfile
├── docker-compose.yml
└── requirements.txt
```