security: fix critical/high auth, idor, races and persistence
This commit is contained in:
+20
-4
@@ -14,6 +14,7 @@ import (
|
||||
|
||||
"shared-sqs/app/auth"
|
||||
"shared-sqs/app/models"
|
||||
"shared-sqs/app/persistence"
|
||||
"shared-sqs/app/tenant"
|
||||
|
||||
"github.com/google/uuid"
|
||||
@@ -36,9 +37,9 @@ func findQueue(tenantAccessKey, queueName string) (string, *models.Queue) {
|
||||
|
||||
// Handler — admin API handler, holds TenantStore и admin token
|
||||
type Handler struct {
|
||||
store *tenant.TenantStore
|
||||
adminToken string
|
||||
nubesEndpoint string // URL nubes API для валидации JWT (напр. https://deck-api-test.ngcloud.ru/api/v1)
|
||||
store *tenant.TenantStore
|
||||
adminToken string
|
||||
nubesEndpoint string // URL nubes API для валидации JWT (напр. https://deck-api-test.ngcloud.ru/api/v1)
|
||||
}
|
||||
|
||||
// NewHandler — создаёт admin handler
|
||||
@@ -188,12 +189,18 @@ func (h *Handler) jwtMiddleware(next http.Handler) http.Handler {
|
||||
}
|
||||
|
||||
// Проверяем что тенант существует (был создан при /ui/api/auth)
|
||||
_, ok := h.store.GetBySub(claims.Sub)
|
||||
jwtTenant, ok := h.store.GetBySub(claims.Sub)
|
||||
if !ok {
|
||||
jsonErr(w, http.StatusForbidden, "tenant not found — authenticate first via POST /ui/api/auth")
|
||||
return
|
||||
}
|
||||
|
||||
// IDOR защита: для /ui/api/tenants/{id}/... разрешаем доступ только к своему tenant ID.
|
||||
if pathTenantID, exists := mux.Vars(r)["id"]; exists && pathTenantID != "" && pathTenantID != jwtTenant.ID {
|
||||
jsonErr(w, http.StatusForbidden, "forbidden tenant access")
|
||||
return
|
||||
}
|
||||
|
||||
next.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
@@ -315,13 +322,18 @@ func (h *Handler) deleteTenant(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
// Удаляем все очереди тенанта из SyncQueues
|
||||
prefix := t.AccessKey + ":"
|
||||
deletedQueueKeys := make([]string, 0)
|
||||
models.SyncQueues.Lock()
|
||||
for key := range models.SyncQueues.Queues {
|
||||
if strings.HasPrefix(key, prefix) {
|
||||
deletedQueueKeys = append(deletedQueueKeys, key)
|
||||
delete(models.SyncQueues.Queues, key)
|
||||
}
|
||||
}
|
||||
models.SyncQueues.Unlock()
|
||||
for _, queueKey := range deletedQueueKeys {
|
||||
persistence.DeleteQueue(queueKey)
|
||||
}
|
||||
|
||||
h.store.Delete(id)
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
@@ -427,6 +439,7 @@ func (h *Handler) createTenantQueue(w http.ResponseWriter, r *http.Request) {
|
||||
Messages: []models.SqsMessage{},
|
||||
Duplicates: make(map[string]time.Time),
|
||||
}
|
||||
persistence.SaveQueue(key, models.SyncQueues.Queues[key])
|
||||
models.SyncQueues.Unlock()
|
||||
log.Infof("admin: created queue %s for tenant %s", req.Name, t.ID)
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
@@ -453,6 +466,7 @@ func (h *Handler) deleteTenantQueue(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
delete(models.SyncQueues.Queues, key)
|
||||
models.SyncQueues.Unlock()
|
||||
persistence.DeleteQueue(key)
|
||||
log.Infof("admin: deleted queue %s for tenant %s", queueName, t.ID)
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
}
|
||||
@@ -552,6 +566,7 @@ func (h *Handler) sendMessageToQueue(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
models.SyncQueues.Lock()
|
||||
models.SyncQueues.Queues[key].Messages = append(models.SyncQueues.Queues[key].Messages, msg)
|
||||
persistence.SaveQueue(key, models.SyncQueues.Queues[key])
|
||||
models.SyncQueues.Unlock()
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
@@ -575,6 +590,7 @@ func (h *Handler) purgeQueue(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
models.SyncQueues.Lock()
|
||||
models.SyncQueues.Queues[key].Messages = models.SyncQueues.Queues[key].Messages[:0]
|
||||
persistence.SaveQueue(key, models.SyncQueues.Queues[key])
|
||||
models.SyncQueues.Unlock()
|
||||
log.Infof("admin: purged queue %s for tenant %s", queueName, t.ID)
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
|
||||
Reference in New Issue
Block a user