diff --git a/policy/resolver.go b/policy/resolver.go index e06abea0..5f2feb77 100644 --- a/policy/resolver.go +++ b/policy/resolver.go @@ -725,13 +725,13 @@ func (s *LocalServices) policyToJobs(ctx context.Context, policyMrn string, owne } for i := range group.Checks { check := group.Checks[i] - if check.Action == explorer.Action_DEACTIVATE || group.Type == GroupType_DISABLE { + if check.Action == explorer.Action_DEACTIVATE || (group.Type == GroupType_DISABLE && group.ReviewStatus != ReviewStatus_REJECTED) { cache.removedQueries[check.Mrn] = struct{}{} } } for i := range group.Queries { query := group.Queries[i] - if query.Action == explorer.Action_DEACTIVATE || group.Type == GroupType_DISABLE { + if query.Action == explorer.Action_DEACTIVATE || (group.Type == GroupType_DISABLE && group.ReviewStatus != ReviewStatus_REJECTED) { cache.removedQueries[query.Mrn] = struct{}{} } } @@ -891,7 +891,9 @@ func (s *LocalServices) policyGroupToJobs(ctx context.Context, group *PolicyGrou continue } - if check.Action == explorer.Action_IGNORE || group.Type == GroupType_IGNORED { + // The type is IGNORED and the review status is not REJECTED + ignoreGroup := group.Type == GroupType_IGNORED && group.ReviewStatus != ReviewStatus_REJECTED + if check.Action == explorer.Action_IGNORE || ignoreGroup { stillValid := CheckValidUntil(group.EndDate, check.Mrn) if !stillValid { // the exception is no longer valid => score the check @@ -904,7 +906,7 @@ func (s *LocalServices) policyGroupToJobs(ctx context.Context, group *PolicyGrou if impact == nil { impact = &explorer.Impact{} } - if check.Action == explorer.Action_IGNORE || group.Type == GroupType_IGNORED { + if check.Action == explorer.Action_IGNORE || ignoreGroup { impact.Scoring = explorer.ScoringSystem_IGNORE_SCORE impact.Action = explorer.Action_IGNORE } @@ -917,7 +919,7 @@ func (s *LocalServices) policyGroupToJobs(ctx context.Context, group *PolicyGrou } // TODO: can we simplify this to simply IGNORE? - if check.Action == explorer.Action_MODIFY || check.Action == explorer.Action_IGNORE || group.Type == GroupType_IGNORED { + if check.Action == explorer.Action_MODIFY || check.Action == explorer.Action_IGNORE || ignoreGroup { cache.modifyCheckJob(check, impact) } } diff --git a/policy/scan/local_scanner_test.go b/policy/scan/local_scanner_test.go index fa9ea7f7..0544cadf 100644 --- a/policy/scan/local_scanner_test.go +++ b/policy/scan/local_scanner_test.go @@ -253,6 +253,71 @@ func (s *LocalScannerSuite) TestRunIncognito_ExceptionGroups() { } } +func (s *LocalScannerSuite) TestRunIncognito_ExceptionGroups_RejectedReview() { + bundle, err := policy.BundleFromPaths("./testdata/exception-groups.mql.yaml") + s.Require().NoError(err) + + bundle.Policies[1].Groups[0].ReviewStatus = policy.ReviewStatus_REJECTED + bundle.Policies[1].Groups[1].ReviewStatus = policy.ReviewStatus_REJECTED + + _, err = bundle.CompileExt(context.Background(), policy.BundleCompileConf{ + Schema: s.schema, + RemoveFailing: true, + }) + s.Require().NoError(err) + + s.job.Bundle = bundle + s.job.PolicyFilters = []string{"asset-policy"} + bundleMap := bundle.ToMap() + + ctx := context.Background() + scanner := NewLocalScanner() + res, err := scanner.RunIncognito(ctx, s.job) + s.Require().NoError(err) + s.Require().NotNil(res) + + full := res.GetFull() + s.Require().NotNil(full) + + s.Equal(1, len(full.Reports)) + + for k, r := range full.Reports { + // Verify the score is 16 + s.Equal(uint32(16), r.GetScore().Value) + + p := full.ResolvedPolicies[k] + + // Get the code id for all the executed queries + executedQueries := []string{} + for qCodeId := range p.ExecutionJob.Queries { + executedQueries = append(executedQueries, qCodeId) + } + + expectedQueries := []string{ + bundleMap.Queries["//local.cnspec.io/run/local-execution/queries/ignored-query"].CodeId, + bundleMap.Queries["//local.cnspec.io/run/local-execution/queries/deactivate-query"].CodeId, + bundleMap.Queries["//local.cnspec.io/run/local-execution/queries/sshd-score-01"].CodeId, + } + s.ElementsMatch(expectedQueries, executedQueries) + + queryIdToReportingJob := map[string]*policy.ReportingJob{} + for _, rj := range p.CollectorJob.ReportingJobs { + _, ok := queryIdToReportingJob[rj.QrId] + s.Require().False(ok) + queryIdToReportingJob[rj.QrId] = rj + } + + // Make sure the ignored query is ignored + queryRj := queryIdToReportingJob[bundleMap.Queries["//local.cnspec.io/run/local-execution/queries/ignored-query"].CodeId] + s.Require().NotNil(queryRj) + + parent := queryRj.Notify[0] + parentJob := p.CollectorJob.ReportingJobs[parent] + s.Require().NotNil(parentJob) + s.Equal(explorer.ScoringSystem_SCORING_UNSPECIFIED, parentJob.ChildJobs[queryRj.Uuid].Scoring) + } +} + func (s *LocalScannerSuite) TestRunIncognito_QueryExceptions() { bundle, err := policy.BundleFromPaths("./testdata/exceptions.mql.yaml") s.Require().NoError(err)