fix(PROJ-63): Defense-in-Depth Tenant-Scope-Härtung der Admin-Endpunkte

tenantAccessAllowed()-Check in allen {id}-Handlern von tenant_handlers.go,
tenant_domain_handlers.go und tenant_logo_handlers.go ergänzt — No-op für
globale Admins, zweite Verteidigungslinie für hypothetische tenant-gebundene
Admin-Sessions.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
sysops
2026-06-30 14:37:39 +02:00
co-authored by Claude Sonnet 4.6
parent c1338f6721
commit dcb88317ac
6 changed files with 88 additions and 2 deletions
+21
View File
@@ -117,6 +117,11 @@ func (s *Server) handleGetTenant(w http.ResponseWriter, r *http.Request) {
writeError(w, http.StatusBadRequest, "invalid tenant id")
return
}
// Defense-in-depth tenant scope check (PROJ-63): no-op for global admins.
if !tenantAccessAllowed(sessionFromCtx(r.Context()), &id) {
writeError(w, http.StatusForbidden, "access denied")
return
}
tenant, err := s.tenantStore.Get(r.Context(), id)
if err != nil {
writeError(w, http.StatusNotFound, "tenant not found")
@@ -136,6 +141,12 @@ func (s *Server) handleUpdateTenant(w http.ResponseWriter, r *http.Request) {
return
}
// Defense-in-depth tenant scope check (PROJ-63): no-op for global admins.
if !tenantAccessAllowed(sessionFromCtx(r.Context()), &id) {
writeError(w, http.StatusForbidden, "access denied")
return
}
var req struct {
Name string `json:"name"`
Active *bool `json:"active"`
@@ -181,6 +192,11 @@ func (s *Server) handleDeleteTenant(w http.ResponseWriter, r *http.Request) {
}
sess := sessionFromCtx(r.Context())
// Defense-in-depth tenant scope check (PROJ-63): no-op for global admins.
if !tenantAccessAllowed(sess, &id) {
writeError(w, http.StatusForbidden, "access denied")
return
}
if err := s.tenantStore.Delete(r.Context(), id); err != nil {
writeError(w, http.StatusInternalServerError, "failed to delete tenant")
return
@@ -204,6 +220,11 @@ func (s *Server) handleListTenantUsers(w http.ResponseWriter, r *http.Request) {
writeError(w, http.StatusBadRequest, "invalid tenant id")
return
}
// Defense-in-depth tenant scope check (PROJ-63): no-op for global admins.
if !tenantAccessAllowed(sessionFromCtx(r.Context()), &tenantID) {
writeError(w, http.StatusForbidden, "access denied")
return
}
users, err := s.users.ListByTenant(r.Context(), tenantID)
if err != nil {
writeError(w, http.StatusInternalServerError, "failed to list tenant users")