-
Notifications
You must be signed in to change notification settings - Fork 174
Expand file tree
/
Copy pathreprocessor_impl.go
More file actions
197 lines (176 loc) · 5.04 KB
/
reprocessor_impl.go
File metadata and controls
197 lines (176 loc) · 5.04 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
package reprocessor
import (
"context"
"sync/atomic"
"github.com/pkg/errors"
alertDS "github.com/stackrox/rox/central/alert/datastore"
alertutils "github.com/stackrox/rox/central/alert/utils"
configDS "github.com/stackrox/rox/central/config/datastore"
deploymentDS "github.com/stackrox/rox/central/deployment/datastore"
platformmatcher "github.com/stackrox/rox/central/platform/matcher"
v1 "github.com/stackrox/rox/generated/api/v1"
"github.com/stackrox/rox/generated/storage"
"github.com/stackrox/rox/pkg/concurrency"
"github.com/stackrox/rox/pkg/features"
"github.com/stackrox/rox/pkg/logging"
"github.com/stackrox/rox/pkg/sac"
"github.com/stackrox/rox/pkg/search"
"golang.org/x/sync/semaphore"
)
const batchSize = 5000
var (
log = logging.LoggerForModule()
reprocessorCtx = sac.WithAllAccess(context.Background())
unsetPlatformComponentQuery = search.NewQueryBuilder().AddNullField(search.PlatformComponent).ProtoQuery()
)
type platformReprocessorImpl struct {
alertDatastore alertDS.DataStore
configDatastore configDS.DataStore
deploymentDatastore deploymentDS.DataStore
platformMatcher platformmatcher.PlatformMatcher
semaphore *semaphore.Weighted
stopSignal concurrency.Signal
// isStarted will make sure only one reprocessing routine runs for an instance of reprocessor
isStarted atomic.Bool
customized bool
}
func New(alertDatastore alertDS.DataStore,
configDatastore configDS.DataStore,
deploymentDatastore deploymentDS.DataStore,
platformMatcher platformmatcher.PlatformMatcher) PlatformReprocessor {
return &platformReprocessorImpl{
alertDatastore: alertDatastore,
configDatastore: configDatastore,
deploymentDatastore: deploymentDatastore,
platformMatcher: platformMatcher,
semaphore: semaphore.NewWeighted(1),
stopSignal: concurrency.NewSignal(),
customized: features.CustomizablePlatformComponents.Enabled(),
}
}
func (pr *platformReprocessorImpl) Start() {
swapped := pr.isStarted.CompareAndSwap(false, true)
if !swapped {
log.Error("Platform reprocessor was already started")
return
}
go pr.RunReprocessor()
}
func (pr *platformReprocessorImpl) Stop() {
if !pr.isStarted.Load() {
log.Error("Platform reprocessor not started")
}
pr.stopSignal.Signal()
}
func (pr *platformReprocessorImpl) RunReprocessor() {
err := pr.semaphore.Acquire(reprocessorCtx, 1)
if err != nil {
log.Errorf("Failed to acquire platform reprocessor semaphore: %v", err)
return
}
defer pr.semaphore.Release(1)
flag := true
if pr.customized {
config, _, err := pr.configDatastore.GetPlatformComponentConfig(reprocessorCtx)
if err != nil {
log.Errorf("Error getting platform component config: %v", err)
}
flag = config.GetNeedsReevaluation()
}
if flag {
err := pr.reprocessAlerts()
if err != nil {
log.Errorf("Error reprocessing alerts with platform rules: %v", err)
}
err = pr.reprocessDeployments()
if err != nil {
log.Errorf("Error reprocessing deployments with platform rules: %v", err)
}
if pr.customized {
err = pr.configDatastore.MarkPCCReevaluated(reprocessorCtx)
if err != nil {
log.Errorf("Error marking platform component config as reevaluated: %v", err)
}
}
}
}
func (pr *platformReprocessorImpl) reprocessAlerts() error {
var q *v1.Query
if pr.customized {
q = search.EmptyQuery()
} else {
q = unsetPlatformComponentQuery
}
q.Pagination = &v1.QueryPagination{
Limit: batchSize,
}
var alerts []*storage.Alert
for {
if pr.stopSignal.IsDone() {
log.Info("Stop called, stopping platform reprocessor")
break
}
err := pr.alertDatastore.WalkByQuery(reprocessorCtx, q, func(alert *storage.Alert) error {
alert.EntityType = alertutils.GetEntityType(alert)
match, err := pr.platformMatcher.MatchAlert(alert)
if err != nil {
return errors.Wrap(err, "matching alert")
}
alert.PlatformComponent = match
alerts = append(alerts, alert)
return nil
})
if err != nil {
return err
}
if len(alerts) == 0 {
break
}
err = pr.alertDatastore.UpsertAlerts(reprocessorCtx, alerts)
if err != nil {
return err
}
alerts = alerts[:0]
q.Pagination.Offset += batchSize
}
log.Info("Done reprocessing alerts with platform rules")
return nil
}
func (pr *platformReprocessorImpl) reprocessDeployments() error {
var q *v1.Query
if pr.customized {
q = search.EmptyQuery()
} else {
q = unsetPlatformComponentQuery
}
q.Pagination = &v1.QueryPagination{
Limit: batchSize,
}
for {
if pr.stopSignal.IsDone() {
log.Info("Stop called, stopping platform reprocessor")
break
}
deps, err := pr.deploymentDatastore.SearchRawDeployments(reprocessorCtx, q)
if err != nil {
return err
}
if len(deps) == 0 {
break
}
for _, dep := range deps {
match, err := pr.platformMatcher.MatchDeployment(dep)
if err != nil {
return err
}
dep.PlatformComponent = match
err = pr.deploymentDatastore.UpsertDeployment(reprocessorCtx, dep)
if err != nil {
return err
}
}
q.Pagination.Offset += batchSize
}
log.Info("Done reprocessing deployments with platform rules")
return nil
}