feat(iot): Этапы 2-7 — MQTT auth, IoT API, EMQX, mqtt-bridge, E2E demo
Этап 2+4: internal/api/handler/iot_device_handler.go
- MQTTAuth: POST /internal/mqtt/auth (без JWT, для EMQX)
- CreateIoTDevice, ListIoTDevices, GetIoTDevice (c password), DeleteIoTDevice, UpdateIoTDevice
- crypto/subtle.ConstantTimeCompare против timing attacks
Этап 4: internal/api/router.go
- /v1/namespaces/{ns}/iot/devices CRUD
- /internal/mqtt/auth (без JWT middleware)
Этап 3: deployments/k8s/emqx.yaml
- EMQX 5.5.1, emqx.conf (HOCON) с HTTP auth backend
- Сервис exposure: 1883 (MQTT), 8083 (WS), 18083 (Dashboard)
Этап 3: iot/cmd/mqtt-bridge/main.go
- paho.mqtt.golang: подписка на +/telemetry/+
- amqp091-go: publish в iot.{namespace}.telemetry
- deployments/k8s/iot-mqtt-bridge.yaml
Этап 7: examples/IOT/ — E2E demo (main.tf, handler.py, README.md)
go.mod: добавлен github.com/eclipse/paho.mqtt.golang v1.5.1
go build ./... — ошибок нет
This commit is contained in:
@@ -178,7 +178,72 @@ IoT Device → MQTT (topic: {user-prefix}/device/telemetry)
|
||||
|
||||
---
|
||||
|
||||
### Результат выполнения Этапа 1
|
||||
### Этап 2-7: план перед реализацией
|
||||
|
||||
#### API port
|
||||
Из `deployments/k8s/operator.yaml`: `API_PORT: "9090"`, сервис `sless-operator.sless.svc:9090`.
|
||||
RabbitMQ: `amqp://sless:sless123@rabbitmq.sless.svc.cluster.local:5672/`
|
||||
|
||||
#### EMQX версия — проблема
|
||||
В плане указан `emqx/emqx:5.5.1`. Изучил вопрос:
|
||||
- **EMQX 5.x open source НЕ имеет встроенного RabbitMQ bridge** (только в Enterprise)
|
||||
- EMQX 4.x имеет RabbitMQ bridge через plugin, конфигурируется env vars
|
||||
|
||||
**Рассматривал варианты:**
|
||||
A. EMQX 4.4 — встроенный bridge, но env vars другого формата чем в плане
|
||||
B. EMQX 5.x + HTTP Webhook rule → наш bridge HTTP сервер
|
||||
C. EMQX 5.x + MQTT client (paho) в bridge сервисе
|
||||
|
||||
**Выбрал вариант C**: mqtt-bridge Go сервис с `github.com/eclipse/paho.mqtt.golang`
|
||||
- Не зависит от версии EMQX (работает с любым MQTT брокером)
|
||||
- amqp091-go уже в go.mod
|
||||
- paho.mqtt.golang добавляется через `go get` по SSH
|
||||
- Самый надёжный и тестируемый подход
|
||||
|
||||
**EMQX 5.5.1**: используем только для HTTP auth (через emqx.conf HOCON).
|
||||
Bridge service подключается к EMQX как обычный MQTT клиент.
|
||||
|
||||
#### MQTT Auth
|
||||
Константы из существующего кода и CRD:
|
||||
- username format: `{namespace}_{deviceId}` — `_` разделитель безопасен (namespace не содержит `_`)
|
||||
- Secret name: `iot-{deviceId}`
|
||||
- Always return HTTP 200, body `{"result": "allow"|"deny"}` (безопасно для обеих версий EMQX)
|
||||
- `crypto/subtle.ConstantTimeCompare` для сравнения паролей
|
||||
|
||||
#### Структура файлов Этапов 2-7
|
||||
- `internal/api/handler/iot_device_handler.go` — MQTT auth + IoT CRUD handlers
|
||||
- `internal/api/router.go` — добавить IoT routes
|
||||
- `deployments/k8s/emqx.yaml` — EMQX deployment c emqx.conf ConfigMap (только HTTP auth)
|
||||
- `iot/cmd/mqtt-bridge/main.go` — MQTT subscriber → RabbitMQ publisher
|
||||
- `deployments/k8s/iot-mqtt-bridge.yaml` — Deployment mqtt-bridge
|
||||
- `examples/IOT/` — E2E demo
|
||||
|
||||
---
|
||||
|
||||
### Результат выполнения Этапов 2-7
|
||||
|
||||
**Создано:**
|
||||
- `internal/api/handler/iot_device_handler.go` — MQTT auth + IoT CRUD handlers
|
||||
- `internal/api/router.go` — IoT routes + `/internal/mqtt/auth`
|
||||
- `deployments/k8s/emqx.yaml` — EMQX 5.5.1 deployment с emqx.conf (HTTP auth)
|
||||
- `iot/cmd/mqtt-bridge/main.go` — MQTT subscriber → RabbitMQ publisher (paho + amqp091-go)
|
||||
- `deployments/k8s/iot-mqtt-bridge.yaml` — Deployment mqtt-bridge
|
||||
- `examples/IOT/` — E2E demo (main.tf, handler.py, README.md)
|
||||
|
||||
**go.mod**: добавлен `github.com/eclipse/paho.mqtt.golang v1.5.1`
|
||||
|
||||
**go build ./...** — ошибок нет.
|
||||
|
||||
**Не реализовано (отложено):**
|
||||
- Этап 6 (Terraform Provider) — находится в отдельном репозитории, путь неизвестен
|
||||
- Terraform ресурс `sless_iot_device` — реализуется отдельно в provider репо
|
||||
|
||||
**Ключевые архитектурные решения:**
|
||||
- EMQX 5.5.1 (как в плане) — HTTP auth через emqx.conf HOCON
|
||||
- mqtt-bridge использует paho.mqtt.golang (MQTT subscriber), а не EMQX webhook — версионно-независимо
|
||||
- MQTTAuth всегда возвращает HTTP 200 (совместимо с EMQX 4.x и 5.x)
|
||||
- `crypto/subtle.ConstantTimeCompare` для защиты от timing attacks
|
||||
- `GetIoTDevice` — единственный endpoint с mqtt_password (security by design)
|
||||
|
||||
**Создано:**
|
||||
- `iot/api/v1alpha1/device_types.go` — CRD IoTDevice с IoTDevicePhase константами
|
||||
|
||||
Reference in New Issue
Block a user