193 lines
5.8 KiB
Markdown
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
|
|
```
|