refactor: reorganize project into src layout and update API documentation

Update project structure to use a src/ directory layout and
improve documentation across multiple files.

- Update README.md build command to use ./src
- Add directory structure documentation
- Update status endpoint to include DB health status
- Add pagination support (limit/offset) to whitelist list endpoints
- Document new query parameters with examples
- Update deployment guide to mark API token as required
- Add testing instructions
- Clarify audit log rotation in design documentation
This commit is contained in:
db123-test
2026-05-05 11:51:45 +03:30
parent 33b0e4e30e
commit 8d25bda386
6 changed files with 143 additions and 14 deletions

View File

@@ -18,7 +18,7 @@ On 401/403 NGINX returns the response to the client. Whitelisted IPs never see a
## Build
```bash
go build -o auth-proxy .
go build -o auth-proxy ./src
```
## Docker
@@ -42,6 +42,27 @@ vim .env
./auth-proxy
```
## Directory structure
```
├── src/
│ ├── main.go — entry point
│ ├── auth.go — HTTP handlers
│ ├── db.go — database operations
│ ├── config.go — configuration
│ ├── cleanup.go — cleanup goroutine
│ └── auth_test.go — unit tests
├── docs/
│ ├── api.md
│ ├── deploy.md
│ ├── design.md
│ └── security.md
├── Dockerfile
├── docker-compose.yml
├── go.mod
└── openapi.yaml
```
## API
The API requires a bearer token set via `AUTH_PROXY_API_TOKEN`. All endpoints return `401 Unauthorized` if the token is missing or invalid.
@@ -55,7 +76,7 @@ The API requires a bearer token set via `AUTH_PROXY_API_TOKEN`. All endpoints re
| GET | `/api/whitelist/perm/list` | List active permanent entries |
| DELETE | `/api/whitelist/perm/{entry}` | Remove a permanent entry |
| GET | `/api/logs` | Retrieve audit log entries |
| GET | `/status` | Health check |
| GET | `/status` | Health check with DB status |
See `docs/api.md` for full API reference.

View File

@@ -35,6 +35,13 @@ List all currently active temporary whitelisted IPs.
**Authorization:** Bearer `{API_TOKEN}`
**Query parameters:**
| Parameter | Type | Required | Default | Description |
|-----------|--------|----------|---------|---------------------------------------------------------------------|
| `limit` | int | No | 200 | Number of entries to return (max 1000) |
| `offset` | int | No | 0 | Number of entries to skip |
**Response body:**
```json
@@ -47,6 +54,13 @@ List all currently active temporary whitelisted IPs.
]
```
**Example:**
```bash
curl -X GET "http://127.0.0.1:8080/api/whitelist/temp/list?limit=50&offset=0" \
-H "Authorization: Bearer CHANGE_ME"
```
### DELETE /api/whitelist/temp/{ip}
Remove a temporary whitelisted IP.
@@ -86,6 +100,13 @@ List all currently active permanent whitelisted IPs.
**Authorization:** Bearer `{API_TOKEN}`
**Query parameters:**
| Parameter | Type | Required | Default | Description |
|-----------|--------|----------|---------|---------------------------------------------------------------------|
| `limit` | int | No | 200 | Number of entries to return (max 1000) |
| `offset` | int | No | 0 | Number of entries to skip |
**Response body:**
```json
@@ -96,6 +117,13 @@ List all currently active permanent whitelisted IPs.
]
```
**Example:**
```bash
curl -X GET "http://127.0.0.1:8080/api/whitelist/perm/list?limit=50&offset=0" \
-H "Authorization: Bearer CHANGE_ME"
```
### DELETE /api/whitelist/perm/{entry}
Remove a permanent whitelisted IP or CIDR range.
@@ -149,9 +177,19 @@ The NGINX auth_request endpoint. Do NOT call this directly.
### GET /status
Health check.
Health check with DB status.
**Response:** 200 `ok`
**Response:** 200 `application/json`
```json
{
"status": "ok",
"uptime": "1h30m0s",
"perm_whitelist_count": 15,
"temp_whitelist_count": 3,
"db_ok": true
}
```
## Security notes

View File

@@ -83,11 +83,17 @@ nginx -s reload
| Variable | Description | Default |
|----------|-------------|---------|
| AUTH_PROXY_PORT | HTTP listen port | 8080 |
| AUTH_PROXY_API_TOKEN | API bearer token | (none) |
| AUTH_PROXY_API_TOKEN | API bearer token | (required) |
| AUTH_PROXY_DB_PATH | SQLite database path | /data/auth-proxy.db |
| DATA_DIR | Data directory | /data |
| CLEANUP_INTERVAL | Cleanup interval | 60s |
## Testing
```bash
go test ./src/...
```
## Graceful shutdown
```bash

View File

@@ -106,8 +106,9 @@ If you need persistence across restarts, add a disk-backed store later.
## Why a background cleanup goroutine?
Checking expiry on every request adds latency (two map lookups per request).
The cleanup goroutine is a one-time cost that keeps the hot path fast.
The cleanup goroutine removes expired temporary entries and rotates the audit log.
It runs every 60 seconds (configurable). The audit log rotation keeps the database
from growing indefinitely — it maintains a maximum of 100,000 entries.
## Why poll instead of inotify?

View File

@@ -30,6 +30,7 @@
The API key is the only secret for the /api/* endpoints. It's sent as a bearer token
in the Authorization header.
- **Required.** The service will not start without it.
- Keep it secret. Don't log it. Don't put it in the URL.
- Use a strong random string.
- Rotate it regularly.
@@ -43,10 +44,20 @@ Each entry records:
- `ip` or `cidr` — the affected IP or CIDR
- `ttl_seconds` — for temp entries
- `reason` — the reason provided
- `api_client_ip` — the IP that made the API call
- `api_client_ip` — the IP that made the API call (from NGINX `X-Real-IP`)
Retrieve logs via the `/api/logs` endpoint.
The audit log is automatically rotated to maintain a maximum of 100,000 entries.
## IP validation
The `/api/whitelist/temp` and `/api/whitelist/perm` endpoints validate inputs:
- `/api/whitelist/temp` requires a valid IP address.
- `/api/whitelist/perm` requires a valid IP address or CIDR range.
- Invalid inputs return `400 Bad Request`.
## Graceful shutdown
The service listens for SIGTERM and SIGINT. On signal:
@@ -68,7 +79,7 @@ This ensures Docker deployments can shut down cleanly.
- We don't support TLS. The auth endpoint should always be served over TLS.
- We don't support logging to a file. Logs go to stdout (Docker).
- We don't support metrics. If you need metrics, add them later.
- We don't support health checks with Prometheus. The /status endpoint is a simple text response.
- We don't support health checks with Prometheus. The /status endpoint returns a JSON response with uptime, DB status, and whitelist counts.
- We don't support configuration via a config file. Use environment variables.
- We don't support multiple domains. The auth-proxy service doesn't care about domains.
- We don't support HTTP/2. The auth-proxy service uses HTTP/1.1 only.

View File

@@ -39,17 +39,32 @@ paths:
/status:
get:
summary: Health check
description: Simple health check endpoint.
description: Returns JSON with uptime, DB status, and whitelist counts.
operationId: healthCheck
security: []
responses:
'200':
description: OK
content:
text/plain:
application/json:
schema:
type: object
properties:
status:
type: string
example: "ok\n"
example: "ok"
uptime:
type: string
example: "1h30m0s"
perm_whitelist_count:
type: integer
example: 15
temp_whitelist_count:
type: integer
example: 3
db_ok:
type: boolean
example: true
/api/whitelist/temp:
post:
@@ -99,6 +114,24 @@ paths:
summary: List temporary whitelisted IPs
description: List all currently active temporary whitelisted IPs.
operationId: listTempWhitelist
parameters:
- name: limit
in: query
required: false
schema:
type: integer
minimum: 1
maximum: 1000
default: 200
description: Number of entries to return (default 200, max 1000)
- name: offset
in: query
required: false
schema:
type: integer
minimum: 0
default: 0
description: Number of entries to skip (default 0)
responses:
'200':
description: List of temporary whitelisted IPs
@@ -168,7 +201,7 @@ paths:
'204':
description: Created
'400':
description: Bad request — entry required
description: Bad request — missing entry or invalid entry (must be valid IP or CIDR range)
'401':
description: Unauthorized — invalid API token
'409':
@@ -186,6 +219,24 @@ paths:
summary: List permanent whitelisted IPs
description: List all currently active permanent whitelisted IPs.
operationId: listPermWhitelist
parameters:
- name: limit
in: query
required: false
schema:
type: integer
minimum: 1
maximum: 1000
default: 200
description: Number of entries to return (default 200, max 1000)
- name: offset
in: query
required: false
schema:
type: integer
minimum: 0
default: 0
description: Number of entries to skip (default 0)
responses:
'200':
description: List of permanent whitelisted IPs
@@ -233,6 +284,7 @@ paths:
Retrieve the last 200 audit log entries (up to 1000 with `limit`).
Each entry records a whitelist operation with its timestamp, action, affected IP,
and the IP of the API client that performed the action.
The audit log is automatically rotated to a maximum of 200,000 entries.
operationId: getLogs
parameters:
- name: action