Skip to content

Commit

Permalink
annotations based skipping
Browse files Browse the repository at this point in the history
  • Loading branch information
patilpankaj212 committed Jan 8, 2021
1 parent 32ff137 commit 919aece
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 3 deletions.
40 changes: 37 additions & 3 deletions pkg/iac-providers/kubernetes/v1/normalize.go
Expand Up @@ -24,19 +24,23 @@ import (
"github.com/accurics/terrascan/pkg/utils"
yamltojson "github.com/ghodss/yaml"
"github.com/iancoleman/strcase"
"go.uber.org/zap"
"gopkg.in/yaml.v3"
)

const terrascanSkipRules = "terrascanSkipRules"

var (
errUnsupportedDoc = fmt.Errorf("unsupported document type")
// ErrNoKind is returned when the "kind" key is not available (not a valid kubernetes resource)
ErrNoKind = fmt.Errorf("kind does not exist")
)

// k8sMetadata is used to pull the name and namespace types for a given resource
// k8sMetadata is used to pull the name, namespace types and annotations for a given resource
type k8sMetadata struct {
Name string `yaml:"name" json:"name"`
Namespace string `yaml:"namespace" json:"namespace"`
Name string `yaml:"name" json:"name"`
Namespace string `yaml:"namespace" json:"namespace"`
Annotations map[string]interface{} `yaml:"annotations" json:"annotations"`
}

// k8sResource is a generic struct to handle all k8s resource types
Expand Down Expand Up @@ -116,6 +120,12 @@ func (k *K8sV1) Normalize(doc *utils.IacDocument) (*output.ResourceConfig, error
resourceConfig.ID = resourceConfig.Type + "." + resource.Metadata.Name + "." + namespace
}

// read and update skip rules, if present
skipRules := readSkipRulesFromAnnotations(resource.Metadata.Annotations, resourceConfig.ID)
if skipRules != nil {
resourceConfig.SkipRules = append(resourceConfig.SkipRules, skipRules...)
}

configData := make(map[string]interface{})
if err = json.Unmarshal(*jsonData, &configData); err != nil {
return nil, err
Expand All @@ -126,3 +136,27 @@ func (k *K8sV1) Normalize(doc *utils.IacDocument) (*output.ResourceConfig, error

return &resourceConfig, nil
}

func readSkipRulesFromAnnotations(annotations map[string]interface{}, resourceID string) []string {

if _, ok := annotations[terrascanSkipRules]; !ok {
zap.S().Debugf("%s not present for resource: %s", terrascanSkipRules, resourceID)
return nil
}

skipRules := make([]string, 0)
skipRulesFromAnnotations := annotations[terrascanSkipRules]
if rules, ok := skipRulesFromAnnotations.([]interface{}); ok {
for _, rule := range rules {
if value, ok := rule.(string); ok {
skipRules = append(skipRules, value)
} else {
zap.S().Debugf("rules in %s must be string", terrascanSkipRules)
}
}
} else {
zap.S().Debugf("%s must be a slice of rules to skip", terrascanSkipRules)
}

return skipRules
}
16 changes: 16 additions & 0 deletions pkg/policy/opa/engine.go
Expand Up @@ -377,6 +377,22 @@ func (e *Engine) Evaluate(engineInput policy.EngineInput) (policy.EngineOutput,
zap.S().Error(err)
continue
}

// do no report violations if rule is skipped for resource
if len(resource.SkipRules) > 0 {
found := false
for _, rule := range resource.SkipRules {
if strings.EqualFold(k, rule) {
found = true
break
}
}
if found {
zap.S().Debugf("rule: %s skipped for resource: %s", k, resource.Name)
continue
}
}

if resource == nil {
zap.S().Warn("resource was not found", zap.String("resource id", resourceID))
continue
Expand Down

0 comments on commit 919aece

Please sign in to comment.