mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-04-30 20:40:09 +00:00
Require proxy admin for token regeneration
This commit is contained in:
parent
0867490ae0
commit
a2f01f14af
2 changed files with 68 additions and 0 deletions
|
|
@ -2053,6 +2053,8 @@ func TestProxyAuthNonAdminDeniedAdminEndpoints(t *testing.T) {
|
|||
{method: http.MethodPost, path: "/api/system/settings/update", body: `{}`},
|
||||
{method: http.MethodPost, path: "/api/security/reset-lockout", body: `{}`},
|
||||
{method: http.MethodPost, path: "/api/security/apply-restart", body: `{}`},
|
||||
{method: http.MethodPost, path: "/api/security/regenerate-token", body: `{}`},
|
||||
{method: http.MethodPost, path: "/api/security/validate-token", body: `{"token":"abc"}`},
|
||||
{method: http.MethodPost, path: "/api/security/oidc", body: `{}`},
|
||||
{method: http.MethodPost, path: "/api/system/verify-temperature-ssh", body: `{}`},
|
||||
{method: http.MethodPost, path: "/api/system/ssh-config", body: `{}`},
|
||||
|
|
@ -2907,6 +2909,27 @@ func TestRegenerateTokenRequiresSettingsWriteScope(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestRegenerateTokenRejectsProxyNonAdmin(t *testing.T) {
|
||||
cfg := newTestConfigWithTokens(t)
|
||||
cfg.ProxyAuthSecret = "proxy-secret"
|
||||
cfg.ProxyAuthUserHeader = "X-Remote-User"
|
||||
cfg.ProxyAuthRoleHeader = "X-Remote-Roles"
|
||||
cfg.ProxyAuthAdminRole = "admin"
|
||||
router := NewRouter(cfg, nil, nil, nil, nil, "1.0.0")
|
||||
|
||||
ResetRateLimitForIP("203.0.113.25")
|
||||
req := httptest.NewRequest(http.MethodPost, "/api/security/regenerate-token", nil)
|
||||
req.RemoteAddr = "203.0.113.25:1234"
|
||||
req.Header.Set("X-Proxy-Secret", cfg.ProxyAuthSecret)
|
||||
req.Header.Set("X-Remote-User", "viewer-user")
|
||||
req.Header.Set("X-Remote-Roles", "viewer")
|
||||
rec := httptest.NewRecorder()
|
||||
router.Handler().ServeHTTP(rec, req)
|
||||
if rec.Code != http.StatusForbidden {
|
||||
t.Fatalf("expected 403 for non-admin proxy regenerate-token, got %d", rec.Code)
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateTokenRequiresAuthInAPIMode(t *testing.T) {
|
||||
record := newTokenRecord(t, "validate-token-123.12345678", []string{config.ScopeSettingsWrite}, nil)
|
||||
cfg := newTestConfigWithTokens(t, record)
|
||||
|
|
@ -2942,6 +2965,27 @@ func TestValidateTokenRequiresSettingsWriteScope(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestValidateTokenRejectsProxyNonAdmin(t *testing.T) {
|
||||
cfg := newTestConfigWithTokens(t)
|
||||
cfg.ProxyAuthSecret = "proxy-secret"
|
||||
cfg.ProxyAuthUserHeader = "X-Remote-User"
|
||||
cfg.ProxyAuthRoleHeader = "X-Remote-Roles"
|
||||
cfg.ProxyAuthAdminRole = "admin"
|
||||
router := NewRouter(cfg, nil, nil, nil, nil, "1.0.0")
|
||||
|
||||
ResetRateLimitForIP("203.0.113.26")
|
||||
req := httptest.NewRequest(http.MethodPost, "/api/security/validate-token", strings.NewReader(`{"token":"abc"}`))
|
||||
req.RemoteAddr = "203.0.113.26:1234"
|
||||
req.Header.Set("X-Proxy-Secret", cfg.ProxyAuthSecret)
|
||||
req.Header.Set("X-Remote-User", "viewer-user")
|
||||
req.Header.Set("X-Remote-Roles", "viewer")
|
||||
rec := httptest.NewRecorder()
|
||||
router.Handler().ServeHTTP(rec, req)
|
||||
if rec.Code != http.StatusForbidden {
|
||||
t.Fatalf("expected 403 for non-admin proxy validate-token, got %d", rec.Code)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRecoveryEndpointRejectsRemoteWithoutToken(t *testing.T) {
|
||||
cfg := newTestConfigWithTokens(t)
|
||||
router := NewRouter(cfg, nil, nil, nil, nil, "1.0.0")
|
||||
|
|
|
|||
|
|
@ -525,6 +525,18 @@ func (r *Router) HandleRegenerateAPIToken(w http.ResponseWriter, rq *http.Reques
|
|||
return
|
||||
}
|
||||
|
||||
// Check proxy auth for admin status
|
||||
if r.config.ProxyAuthSecret != "" {
|
||||
if valid, username, isAdmin := CheckProxyAuth(r.config, rq); valid && !isAdmin {
|
||||
log.Warn().
|
||||
Str("ip", GetClientIP(rq)).
|
||||
Str("username", username).
|
||||
Msg("Non-admin user attempted API token regeneration")
|
||||
http.Error(w, "Admin privileges required", http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if !ensureSettingsWriteScope(w, rq) {
|
||||
return
|
||||
}
|
||||
|
|
@ -643,6 +655,18 @@ func (r *Router) HandleValidateAPIToken(w http.ResponseWriter, rq *http.Request)
|
|||
return
|
||||
}
|
||||
|
||||
// Check proxy auth for admin status
|
||||
if r.config.ProxyAuthSecret != "" {
|
||||
if valid, username, isAdmin := CheckProxyAuth(r.config, rq); valid && !isAdmin {
|
||||
log.Warn().
|
||||
Str("ip", GetClientIP(rq)).
|
||||
Str("username", username).
|
||||
Msg("Non-admin user attempted API token validation")
|
||||
http.Error(w, "Admin privileges required", http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if !ensureSettingsWriteScope(w, rq) {
|
||||
return
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue