forked from tenable/terrascan
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adds support to scan config resources with applicable policies & Refa…
…ctors filteration (tenable#803) * implement regometada filters * tests * Policy type filter added (#29) * policy type filter added * variable name issue fixed 1. cloud type --> policytypes * more unit tests * fix validation * adds header to new files * incorporate review comments Co-authored-by: Gaurav Gogia <16029099+gaurav-gogia@users.noreply.github.com>
- Loading branch information
1 parent
9adfe1d
commit 5f4b15a
Showing
13 changed files
with
856 additions
and
701 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
/* | ||
Copyright (C) 2020 Accurics, Inc. | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
package filters | ||
|
||
import ( | ||
"github.com/accurics/terrascan/pkg/policy" | ||
"github.com/accurics/terrascan/pkg/utils" | ||
) | ||
|
||
// PolicyTypesFilterSpecification is policy type based Filter Spec | ||
type PolicyTypesFilterSpecification struct { | ||
policyTypes []string | ||
} | ||
|
||
// IsSatisfied implementation for policy type based Filter spec | ||
func (p PolicyTypesFilterSpecification) IsSatisfied(r *policy.RegoMetadata) bool { | ||
// if policy type is not present for rego metadata, | ||
// or if policy types is not specified, return true | ||
if len(r.PolicyType) < 1 || len(p.policyTypes) < 1 { | ||
return true | ||
} | ||
return utils.CheckPolicyType(r.PolicyType, p.policyTypes) | ||
} | ||
|
||
// ResourceTypeFilterSpecification is resource type based Filter Spec | ||
type ResourceTypeFilterSpecification struct { | ||
resourceType string | ||
} | ||
|
||
// IsSatisfied implementation for resource type based Filter spec | ||
func (rs ResourceTypeFilterSpecification) IsSatisfied(r *policy.RegoMetadata) bool { | ||
// if resource type is not present for rego metadata, return true | ||
if len(r.ResourceType) < 1 { | ||
return true | ||
} | ||
return rs.resourceType == r.ResourceType | ||
} | ||
|
||
// RerefenceIDFilterSpecification is reference ID based Filter Spec | ||
type RerefenceIDFilterSpecification struct { | ||
ReferenceID string | ||
} | ||
|
||
// IsSatisfied implementation for reference ID based Filter spec | ||
func (rs RerefenceIDFilterSpecification) IsSatisfied(r *policy.RegoMetadata) bool { | ||
return rs.ReferenceID == r.ReferenceID | ||
} | ||
|
||
// RerefenceIDsFilterSpecification is reference IDs based Filter Spec | ||
type RerefenceIDsFilterSpecification struct { | ||
ReferenceIDs []string | ||
} | ||
|
||
// IsSatisfied implementation for reference IDs based Filter spec | ||
func (rs RerefenceIDsFilterSpecification) IsSatisfied(r *policy.RegoMetadata) bool { | ||
// when reference ID's are not specified (could be skip or scan rules), | ||
// return true | ||
if len(rs.ReferenceIDs) < 1 { | ||
return true | ||
} | ||
isSatisfied := false | ||
for _, refID := range rs.ReferenceIDs { | ||
rfIDSpec := RerefenceIDFilterSpecification{refID} | ||
if rfIDSpec.IsSatisfied(r) { | ||
isSatisfied = true | ||
break | ||
} | ||
} | ||
return isSatisfied | ||
} | ||
|
||
// CategoryFilterSpecification is categories based Filter Spec | ||
type CategoryFilterSpecification struct { | ||
categories []string | ||
} | ||
|
||
// IsSatisfied implementation for category based Filter spec | ||
func (c CategoryFilterSpecification) IsSatisfied(r *policy.RegoMetadata) bool { | ||
// when categories are not specified, return true | ||
if len(c.categories) < 1 { | ||
return true | ||
} | ||
return utils.CheckCategory(r.Category, c.categories) | ||
} | ||
|
||
// SeverityFilterSpecification is severity based Filter Spec | ||
type SeverityFilterSpecification struct { | ||
severity string | ||
} | ||
|
||
// IsSatisfied implementation for severity based Filter spec | ||
func (s SeverityFilterSpecification) IsSatisfied(r *policy.RegoMetadata) bool { | ||
// when severity is not specified, return true | ||
if len(s.severity) < 1 { | ||
return true | ||
} | ||
return utils.CheckSeverity(r.Severity, s.severity) | ||
} | ||
|
||
// AndFilterSpecification is a logical AND Filter spec which | ||
// determines if a list of filter specs satisfy the condition | ||
type AndFilterSpecification struct { | ||
filterSpecs []policy.FilterSpecification | ||
} | ||
|
||
// IsSatisfied implementation for And Filter spec | ||
func (a AndFilterSpecification) IsSatisfied(r *policy.RegoMetadata) bool { | ||
if len(a.filterSpecs) < 1 { | ||
return false | ||
} | ||
for _, filterSpec := range a.filterSpecs { | ||
if !filterSpec.IsSatisfied(r) { | ||
return false | ||
} | ||
} | ||
return true | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
/* | ||
Copyright (C) 2020 Accurics, Inc. | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
package filters | ||
|
||
import ( | ||
"github.com/accurics/terrascan/pkg/policy" | ||
) | ||
|
||
// RegoMetadataPreLoadFilter is a pre load filter | ||
// this filter would be while the policy files are processed by policy engine | ||
type RegoMetadataPreLoadFilter struct { | ||
scanRules []string | ||
skipRules []string | ||
categories []string | ||
policyTypes []string | ||
severity string | ||
filterSpecs []policy.FilterSpecification | ||
} | ||
|
||
// NewRegoMetadataPreLoadFilter is a constructor func for RegoMetadataPreLoadFilter | ||
func NewRegoMetadataPreLoadFilter(scanRules, skipRules, categories, policyTypes []string, severity string) *RegoMetadataPreLoadFilter { | ||
return &RegoMetadataPreLoadFilter{ | ||
scanRules: scanRules, | ||
skipRules: skipRules, | ||
categories: categories, | ||
policyTypes: policyTypes, | ||
severity: severity, | ||
// add applicable filter specs to the list | ||
filterSpecs: []policy.FilterSpecification{ | ||
RerefenceIDsFilterSpecification{scanRules}, | ||
CategoryFilterSpecification{categories: categories}, | ||
SeverityFilterSpecification{severity: severity}, | ||
PolicyTypesFilterSpecification{policyTypes: policyTypes}, | ||
}, | ||
} | ||
} | ||
|
||
// IsFiltered checks whether a RegoMetada should be filtered or not | ||
func (r *RegoMetadataPreLoadFilter) IsFiltered(regoMetadata *policy.RegoMetadata) bool { | ||
// if skip rules are specified, RegoMetada is not filtered | ||
if len(r.skipRules) < 1 { | ||
return false | ||
} | ||
refIDsSpec := RerefenceIDsFilterSpecification{r.skipRules} | ||
return refIDsSpec.IsSatisfied(regoMetadata) | ||
} | ||
|
||
// IsAllowed checks whether a RegoMetada should be allowed or not | ||
func (r *RegoMetadataPreLoadFilter) IsAllowed(regoMetadata *policy.RegoMetadata) bool { | ||
andSpec := AndFilterSpecification{r.filterSpecs} | ||
return andSpec.IsSatisfied(regoMetadata) | ||
} | ||
|
||
// RegoDataFilter is a pre scan filter, | ||
// it will be used by policy engine before the evaluation of resources start | ||
type RegoDataFilter struct{} | ||
|
||
// Filter func will filter based on resource type | ||
func (r *RegoDataFilter) Filter(rmap map[string]*policy.RegoData, input policy.EngineInput) map[string]*policy.RegoData { | ||
// if resource config is empty, return original map | ||
if len(*input.InputData) < 1 { | ||
return rmap | ||
} | ||
tempMap := make(map[string]*policy.RegoData) | ||
for resType := range *input.InputData { | ||
for k := range rmap { | ||
resFilterSpec := ResourceTypeFilterSpecification{resType} | ||
if resFilterSpec.IsSatisfied(&rmap[k].Metadata) { | ||
tempMap[k] = rmap[k] | ||
} | ||
} | ||
} | ||
return tempMap | ||
} |
Oops, something went wrong.