-
Notifications
You must be signed in to change notification settings - Fork 174
ROX-30135: Send baselines to sensor when deployment leaves observation #16077
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
d77b428
1173c6c
fe779a1
5267950
f9abaa8
89af50f
7eae4ae
986e97b
c264034
ade5925
e4d93de
d9e9ce5
cd11907
b583e14
d71f71c
0d0f8fc
618ff7c
343cea3
95f5c2e
4387c22
f8761ba
829b7d2
5351e5d
0d46ce6
53d88a2
7703df6
fd17e0c
3fdc16d
379d14f
6c97e89
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -20,9 +20,12 @@ import ( | |
| baselineDataStore "github.com/stackrox/rox/central/processbaseline/datastore" | ||
| processIndicatorDatastore "github.com/stackrox/rox/central/processindicator/datastore" | ||
| "github.com/stackrox/rox/central/reprocessor" | ||
| "github.com/stackrox/rox/central/sensor/service/connection" | ||
| "github.com/stackrox/rox/generated/internalapi/central" | ||
| "github.com/stackrox/rox/generated/storage" | ||
| "github.com/stackrox/rox/pkg/concurrency" | ||
| "github.com/stackrox/rox/pkg/env" | ||
| "github.com/stackrox/rox/pkg/features" | ||
| "github.com/stackrox/rox/pkg/policies" | ||
| "github.com/stackrox/rox/pkg/postgres/pgutils" | ||
| "github.com/stackrox/rox/pkg/process/filter" | ||
|
|
@@ -81,6 +84,8 @@ type managerImpl struct { | |
| removedOrDisabledPolicies set.StringSet | ||
|
|
||
| processAggregator aggregator.ProcessAggregator | ||
|
|
||
| connectionManager connection.Manager | ||
| } | ||
|
|
||
| func (m *managerImpl) copyAndResetIndicatorQueue() map[string]*storage.ProcessIndicator { | ||
|
|
@@ -248,6 +253,27 @@ func (m *managerImpl) buildMapAndCheckBaseline(indicatorSlice []*storage.Process | |
| } | ||
| } | ||
|
|
||
| func (m *managerImpl) SendBaselineToSensor(baseline *storage.ProcessBaseline) error { | ||
| clusterId := baseline.GetKey().GetClusterId() | ||
| err := m.connectionManager.SendMessage(clusterId, ¢ral.MsgToSensor{ | ||
| Msg: ¢ral.MsgToSensor_BaselineSync{ | ||
| BaselineSync: ¢ral.BaselineSync{ | ||
| Baselines: []*storage.ProcessBaseline{baseline}, | ||
| }}, | ||
| }) | ||
| if err != nil { | ||
| log.Errorf("Error sending process baseline to cluster %q: %v", clusterId, err) | ||
| return err | ||
| } | ||
| log.Infof("Successfully sent process baseline to cluster %q: %s", clusterId, baseline.GetId()) | ||
|
|
||
| return nil | ||
| } | ||
|
|
||
| func checkIfBaselineCanBeSkipped(elements []*storage.BaselineItem, inObservation bool, baseline *storage.ProcessBaseline) bool { | ||
| return len(elements) == 0 && (inObservation || !features.AutoLockProcessBaselines.Enabled() || processbaseline.IsUserLocked(baseline)) | ||
| } | ||
|
|
||
| func (m *managerImpl) checkAndUpdateBaseline(baselineKey processBaselineKey, indicators []*storage.ProcessIndicator) (bool, error) { | ||
| key := &storage.ProcessBaselineKey{ | ||
| DeploymentId: baselineKey.deploymentID, | ||
|
|
@@ -256,15 +282,19 @@ func (m *managerImpl) checkAndUpdateBaseline(baselineKey processBaselineKey, ind | |
| Namespace: baselineKey.namespace, | ||
| } | ||
|
|
||
| autolockEnabled := features.AutoLockProcessBaselines.Enabled() | ||
|
|
||
| // TODO joseph what to do if exclusions ("baseline" in the old non-inclusive language) doesn't exist? Always create for now? | ||
| baseline, exists, err := m.baselines.GetProcessBaseline(lifecycleMgrCtx, key) | ||
| if err != nil { | ||
| return false, err | ||
| } | ||
|
|
||
| inObservation := m.deploymentObservationQueue.InObservation(key.GetDeploymentId()) | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There are now more checks for the deployment being in observation, so this is saved to a new variable. |
||
|
|
||
| // If the baseline does not exist AND this deployment is in the observation period, we | ||
| // need not process further at this time. | ||
| if !exists && m.deploymentObservationQueue.InObservation(key.GetDeploymentId()) { | ||
| if !exists && inObservation { | ||
| return false, nil | ||
| } | ||
|
|
||
|
|
@@ -286,22 +316,63 @@ func (m *managerImpl) checkAndUpdateBaseline(baselineKey processBaselineKey, ind | |
| insertableElement := &storage.BaselineItem{Item: &storage.BaselineItem_ProcessName{ProcessName: baselineItem}} | ||
| elements = append(elements, insertableElement) | ||
| } | ||
| if len(elements) == 0 { | ||
|
|
||
| if checkIfBaselineCanBeSkipped(elements, inObservation, baseline) { | ||
| return false, nil | ||
| } | ||
|
|
||
| if !exists { | ||
| _, err = m.baselines.UpsertProcessBaseline(lifecycleMgrCtx, key, elements, true, true) | ||
| userLock := autolockEnabled && !inObservation | ||
| upsertedBaseline, err := m.baselines.UpsertProcessBaseline(lifecycleMgrCtx, key, elements, true, true, userLock) | ||
| if err != nil { | ||
| return false, err | ||
| } | ||
| if userLock { | ||
| err = m.SendBaselineToSensor(upsertedBaseline) | ||
| } | ||
| return false, err | ||
| } | ||
|
|
||
| userBaseline := processbaseline.IsUserLocked(baseline) | ||
| roxBaseline := processbaseline.IsRoxLocked(baseline) && hasNonStartupProcess | ||
| if userBaseline || roxBaseline { | ||
| reprocessRisk := userBaseline || roxBaseline | ||
|
|
||
| if reprocessRisk { | ||
| // We already checked if it's in the baseline and it is not, so reprocess risk to mark the results are suspicious if necessary | ||
| m.reprocessor.ReprocessRiskForDeployments(baselineKey.deploymentID) | ||
| } else { | ||
| // So we have a baseline, but not locked. Now we need to add these elements to the unlocked baseline | ||
| _, err = m.baselines.UpdateProcessBaselineElements(lifecycleMgrCtx, key, elements, nil, true) | ||
| } | ||
|
|
||
| if !autolockEnabled { | ||
| if !reprocessRisk { | ||
| _, err := m.baselines.UpdateProcessBaselineElements(lifecycleMgrCtx, key, elements, nil, true, false) | ||
| if err != nil { | ||
| return false, err | ||
| } | ||
| } | ||
| return userBaseline, nil | ||
| } | ||
|
|
||
| // If this point is reached AutoLockProcessBaselines is enabled. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Doesn't this section violate our discussion of allowing the user to unlock an auto locked baseline? If I'm following this code correctly, if a baseline exists as unlocked but autolock is on, this will lock it. I don't think that is what we want. As we stated in the meeting on August 26 we only want to lock baselines from point forward.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think what you are saying is that if a user locks a process baseline and then unlocks before the deployment leaves the observation period, it will be auto-locked, which is probably not what the user intended when they unlocked it. There is currently no mechanism to tell if a process baseline is unlocked, because it has always been unlocked, or if it was locked and then unlocked. I don't know how we could distinguish between those two cases. I think distinguishing between those two cases requires much more work and is probably outside of the scope of this PR.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There might be other cases where this causes the process baseline to be locked, then the corner case I mentioned above. One difficulty is that there are two paths that can lead to I might need to take some time, to make sure everything works as it should.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. actually I was talking about the case where user unlocked after the observation period was over and then the indicators were flushed. |
||
| // When AutoLockProcessBaselines we don't need to do anything if the baseline is user or stackrox locked. | ||
| // However, if the feature is enabled we need to user lock it if it is not user locked. It also needs to be | ||
| // stackrox locked if it is neither user locked or stackrox locked. | ||
| if !userBaseline { | ||
| // If the baseline is out of observation it needs to be user locked. | ||
| // Since we are here the baseline is not user locked and if it isn't stackrox locked either, | ||
| // it needs to be updated. | ||
| userLock := !inObservation | ||
| if userLock || !roxBaseline { | ||
| upsertedBaseline, err := m.baselines.UpdateProcessBaselineElements(lifecycleMgrCtx, key, elements, nil, true, userLock) | ||
| if err != nil { | ||
| return false, err | ||
| } | ||
| if userLock { | ||
| err := m.SendBaselineToSensor(upsertedBaseline) | ||
| if err != nil { | ||
| return false, err | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| return userBaseline, err | ||
|
|
||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Uh oh!
There was an error while loading. Please reload this page.