mirror of
https://github.com/Buriburizaem0n/nezha_domains.git
synced 2026-09-19 09:40:12 +00:00
fix(security): restrict service monitors to probe tasks
This commit is contained in:
@@ -16,6 +16,10 @@
|
||||
repository: "https://github.com/karllao/nezha-pixel"
|
||||
author: "karllao"
|
||||
version: "v1.6.0"
|
||||
# Third-party user themes consume the opaque Server.PublicNote field. Theme
|
||||
# maintainers must validate URL schemes (including after decoding) before using
|
||||
# values such as customData.orderLink in href or window.open; the Dashboard
|
||||
# backend and admin frontend do not execute those fields.
|
||||
- path: "nazhua-dist"
|
||||
name: "Nazhua"
|
||||
repository: "https://github.com/hi2shark/nazhua"
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
package singleton
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/nezhahq/nezha/model"
|
||||
)
|
||||
|
||||
func TestServiceSentinelUpdateRejectsNonProbeTaskTypes(t *testing.T) {
|
||||
ss := &ServiceSentinel{}
|
||||
require.Error(t, ss.Update(nil))
|
||||
for _, taskType := range []uint8{0, model.TaskTypeCommand, model.TaskTypeApplyConfig, model.TaskTypeExec, 255} {
|
||||
require.Error(t, ss.Update(&model.Service{Type: taskType}), "type %d must not be scheduled", taskType)
|
||||
}
|
||||
}
|
||||
|
||||
func TestServiceSentinelQuarantinesInvalidPersistedTypes(t *testing.T) {
|
||||
ss := newServiceMonitorSecurityHarness(t)
|
||||
|
||||
insert := `INSERT INTO services
|
||||
(id, user_id, name, type, target, duration, cover, skip_servers_raw, fail_trigger_tasks_raw, recover_trigger_tasks_raw)
|
||||
VALUES (?, 100, ?, ?, 'example.invalid:443', 3600, ?, '{}', '[]', '[]')`
|
||||
require.NoError(t, DB.Exec(insert, 91, "legacy-command", model.TaskTypeCommand, model.ServiceCoverIgnoreAll).Error)
|
||||
require.NoError(t, DB.Exec(insert, 92, "legacy-apply-config", model.TaskTypeApplyConfig, model.ServiceCoverIgnoreAll).Error)
|
||||
require.NoError(t, DB.Exec(insert, 93, "valid-probe", model.TaskTypeTCPPing, model.ServiceCoverIgnoreAll).Error)
|
||||
|
||||
require.NoError(t, ss.loadServiceHistory())
|
||||
_, commandLoaded := ss.Get(91)
|
||||
_, applyConfigLoaded := ss.Get(92)
|
||||
valid, validLoaded := ss.Get(93)
|
||||
require.False(t, commandLoaded)
|
||||
require.False(t, applyConfigLoaded)
|
||||
require.True(t, validLoaded)
|
||||
require.Equal(t, uint8(model.TaskTypeTCPPing), valid.Type)
|
||||
}
|
||||
@@ -209,7 +209,15 @@ func (ss *ServiceSentinel) loadServiceHistory() error {
|
||||
return err
|
||||
}
|
||||
|
||||
validServices := services[:0]
|
||||
for _, service := range services {
|
||||
if err := model.ValidateServiceMonitorType(uint64(service.Type)); err != nil {
|
||||
// Existing databases may contain values written before Service.Type was
|
||||
// constrained. Quarantine them in the database for operator review, but
|
||||
// never register a cron job that could dispatch a privileged Agent task.
|
||||
log.Printf("NEZHA>> quarantining service %d: %v", service.ID, err)
|
||||
continue
|
||||
}
|
||||
task := service
|
||||
// 通过cron定时将服务监控任务传递给任务调度管道
|
||||
service.CronJobID, err = CronShared.AddFunc(task.CronSpec(), func() {
|
||||
@@ -222,7 +230,9 @@ func (ss *ServiceSentinel) loadServiceHistory() error {
|
||||
ss.serviceCurrentStatusData[service.ID] = new(serviceTaskStatus)
|
||||
ss.serviceCurrentStatusData[service.ID].result = make([]*pb.TaskResult, 0, _CurrentStatusSize)
|
||||
ss.serviceStatusToday[service.ID] = &_TodayStatsOfService{}
|
||||
validServices = append(validServices, service)
|
||||
}
|
||||
services = validServices
|
||||
ss.serviceList = services
|
||||
sortServices(ss.serviceList)
|
||||
|
||||
@@ -339,6 +349,13 @@ func (ss *ServiceSentinel) loadTodayStats(today time.Time) {
|
||||
}
|
||||
|
||||
func (ss *ServiceSentinel) Update(m *model.Service) error {
|
||||
if m == nil {
|
||||
return fmt.Errorf("service is nil")
|
||||
}
|
||||
if err := model.ValidateServiceMonitorType(uint64(m.Type)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ss.serviceResponseDataStoreLock.Lock()
|
||||
defer ss.serviceResponseDataStoreLock.Unlock()
|
||||
ss.monthlyStatusLock.Lock()
|
||||
|
||||
@@ -23,7 +23,10 @@ func initUser() {
|
||||
var users []model.User
|
||||
DB.Find(&users)
|
||||
|
||||
// for backward compatibility
|
||||
// Backward compatibility for pre-user-scoped Agents. AgentSecretKey is a
|
||||
// deployment-wide migration/master credential, so user 0 is intentionally
|
||||
// not tenant-scoped. Do not remove this mapping until every legacy Agent has
|
||||
// rotated to a per-user/per-Agent credential; doing so would disconnect them.
|
||||
UserInfoMap[0] = model.UserInfo{
|
||||
Role: model.RoleAdmin,
|
||||
AgentSecret: Conf.AgentSecretKey,
|
||||
|
||||
Reference in New Issue
Block a user