- Standalone SQS-service repository - Multi-tenant message queue service, AWS SQS compatible - Based on GoAws, with mutable tenants, auth, WebUI, Redis persistence - Ready for independent development and deployment - See doc/ and README.md for architecture and usage
116 lines
4.1 KiB
Markdown
116 lines
4.1 KiB
Markdown
# BYOC — Bring Your Own Credentials
|
|
|
|
**Дата**: 2026-04-09
|
|
**Статус**: частично реализовано (backend), UI/API — TODO
|
|
|
|
---
|
|
|
|
## Суть
|
|
|
|
Возможность создать тенанта с **произвольными** Access Key и Secret Key вместо авто-генерируемых.
|
|
|
|
Нужно для:
|
|
- демо-стенда с фиксированными credentials (README всегда актуален)
|
|
- интеграционных тестов с предсказуемыми значениями
|
|
- миграции с другого SQS-совместимого сервиса (сохранение существующих ключей)
|
|
|
|
---
|
|
|
|
## Что уже сделано
|
|
|
|
### `app/tenant/tenant_store.go` — `CreateFixed`
|
|
|
|
```go
|
|
func (s *TenantStore) CreateFixed(
|
|
name string,
|
|
maxQueues int,
|
|
tenantID string,
|
|
accessKey string,
|
|
secretKey string,
|
|
) (*Tenant, error)
|
|
```
|
|
|
|
Создаёт тенанта с заранее известными credentials.
|
|
Проверяет уникальность и `tenantID`, и `accessKey` — конфликт возвращает ошибку.
|
|
|
|
### `app/cmd/seed.go` — демо-тенант
|
|
|
|
Использует `CreateFixed` при `SHARED_SQS_SEED_DEMO=true`:
|
|
|
|
```
|
|
tenantID = "t-demo-shared-sqs-ngcloud"
|
|
accessKey = "SSAK-demo-shared-sqs"
|
|
secretKey = "demo-secret-key-shared-sqs-ngcloud-2026"
|
|
```
|
|
|
|
---
|
|
|
|
## Что нужно сделать (TODO)
|
|
|
|
### Admin API — `POST /admin/tenants`
|
|
|
|
Добавить в `createTenantRequest` два опциональных поля:
|
|
|
|
```go
|
|
// app/admin/admin.go
|
|
type createTenantRequest struct {
|
|
Name string `json:"name"`
|
|
MaxQueues int `json:"max_queues"`
|
|
AccessKey string `json:"access_key,omitempty"` // TODO: BYOC
|
|
SecretKey string `json:"secret_key,omitempty"` // TODO: BYOC
|
|
}
|
|
```
|
|
|
|
Логика в `createTenant` handler:
|
|
|
|
```go
|
|
var t *tenant.Tenant
|
|
var err error
|
|
if req.AccessKey != "" || req.SecretKey != "" {
|
|
// BYOC: оба поля обязательны
|
|
if req.AccessKey == "" || req.SecretKey == "" {
|
|
jsonErr(w, http.StatusBadRequest, "both access_key and secret_key required when specifying custom credentials")
|
|
return
|
|
}
|
|
// Минимальная длина — защита от случайно слабых ключей
|
|
if len(req.AccessKey) < 8 || len(req.SecretKey) < 16 {
|
|
jsonErr(w, http.StatusBadRequest, "access_key min 8 chars, secret_key min 16 chars")
|
|
return
|
|
}
|
|
t, err = h.store.CreateFixed(req.Name, req.MaxQueues, generateTenantID(), req.AccessKey, req.SecretKey)
|
|
} else {
|
|
t, err = h.store.Create(req.Name, req.MaxQueues)
|
|
}
|
|
```
|
|
|
|
> `generateTenantID()` — уже есть в tenant_store.go, нужно экспортировать или вынести.
|
|
|
|
### UI — Web форма создания тенанта
|
|
|
|
- Добавить в модальное окно "Создать тенанта" два опциональных поля: Access Key, Secret Key
|
|
- Показывать только если нажата кнопка "задать свои credentials"
|
|
- Валидация на клиенте: оба поля заполнены, мин. длина
|
|
|
|
---
|
|
|
|
## Безопасность
|
|
|
|
- BYOC-credentials **не дают доступа к admin API** — admin защищён отдельным Bearer токеном
|
|
- Тенант видит **только свои очереди** — изоляция по AccessKey в auth middleware
|
|
- Слабые ключи отклоняются на уровне API (минимальная длина)
|
|
- Credentials передаются только по HTTPS
|
|
|
|
---
|
|
|
|
## Демо-credentials (открыты намеренно)
|
|
|
|
| | |
|
|
|---|---|
|
|
| **Access Key** | `SSAK-demo-shared-sqs` |
|
|
| **Secret Key** | `demo-secret-key-shared-sqs-ngcloud-2026` |
|
|
| **Tenant ID** | `t-demo-shared-sqs-ngcloud` |
|
|
| **Лимит очередей** | 10 |
|
|
|
|
Эти credentials жёстко прописаны в `app/cmd/seed.go`.
|
|
Тенант создаётся только если `SHARED_SQS_SEED_DEMO=true` (env var в deployment.yaml).
|