Skip to content
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

Adds: in-file instrumentation for resource prioritizing #802

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 31 additions & 2 deletions pkg/iac-providers/kubernetes/v1/normalize.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,19 @@ import (
)

const (
terrascanSkip = "terrascanSkip"
terrascanSkip = "runterrascan.io/skip"
terrascanSkipRule = "rule"
terrascanSkipComment = "comment"
terrascanMaxSeverity = "runterrascan.io/maxseverity"
terrascanMinSeverity = "runterrascan.io/minseverity"
)

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")

infileInstructionNotPresentLog = "%s not present for resource: %s"
)

// k8sMetadata is used to pull the name, namespace types and annotations for a given resource
Expand Down Expand Up @@ -139,6 +143,11 @@ func (k *K8sV1) Normalize(doc *utils.IacDocument) (*output.ResourceConfig, error
resourceConfig.SkipRules = append(resourceConfig.SkipRules, skipRules...)
}

maxSeverity, minSeverity := readMinMaxSeverityFromAnnotations(resource.Metadata.Annotations, resourceConfig.ID)

resourceConfig.MaxSeverity = maxSeverity
resourceConfig.MinSeverity = minSeverity

configData := make(map[string]interface{})
if err = json.Unmarshal(*jsonData, &configData); err != nil {
return nil, err
Expand All @@ -155,7 +164,7 @@ func readSkipRulesFromAnnotations(annotations map[string]interface{}, resourceID
var skipRulesFromAnnotations interface{}
var ok bool
if skipRulesFromAnnotations, ok = annotations[terrascanSkip]; !ok {
zap.S().Debugf("%s not present for resource: %s", terrascanSkip, resourceID)
zap.S().Debugf(infileInstructionNotPresentLog, terrascanSkip, resourceID)
return nil
}

Expand All @@ -172,3 +181,23 @@ func readSkipRulesFromAnnotations(annotations map[string]interface{}, resourceID
zap.S().Debugf("%s must be a string containing an json array like [{rule: ruleID, comment: reason for skipping}]", terrascanSkip)
return nil
}

// readMinMaxSeverityFromAnnotations finds the min max severity values set in annotations for the resource
func readMinMaxSeverityFromAnnotations(annotations map[string]interface{}, resourceID string) (maxSeverity, minSeverity string) {
var (
minSeverityAnnotation interface{}
maxSeverityAnnotation interface{}
ok bool
)
if minSeverityAnnotation, ok = annotations[terrascanMinSeverity]; !ok {
zap.S().Debugf(infileInstructionNotPresentLog, terrascanMinSeverity, resourceID)
} else if minSeverity, ok = minSeverityAnnotation.(string); !ok {
zap.S().Debugf("%s must be a string cantaining value as (High | Low| Medium)", terrascanMinSeverity)
}
if maxSeverityAnnotation, ok = annotations[terrascanMaxSeverity]; !ok {
zap.S().Debugf(infileInstructionNotPresentLog, terrascanMaxSeverity, resourceID)
} else if maxSeverity, ok = maxSeverityAnnotation.(string); !ok {
zap.S().Debugf("%s must be a string cantaining value as (High | Low| Medium)", terrascanMaxSeverity)
}
return
}
80 changes: 78 additions & 2 deletions pkg/iac-providers/kubernetes/v1/normalize_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ kind: Pod
metadata:
name: myapp-pod
annotations:
terrascanSkip: |
runterrascan.io/skip: |
[{"rule": "accurics.kubernetes.IAM.109", "comment": "reason to skip the rule"}]
spec:
containers:
Expand All @@ -68,7 +68,7 @@ kind: CRD
metadata:
generateName: myapp-pod-prefix-
annotations:
terrascanSkip: |
runterrascan.io/skip: |
[{"rule": "accurics.kubernetes.IAM.109", "comment": "reason to skip the rule"}]
spec:
containers:
Expand Down Expand Up @@ -413,3 +413,79 @@ func TestReadSkipRulesFromAnnotations(t *testing.T) {
})
}
}

func TestReadMinMaxSeverityFromAnnotations(t *testing.T) {
type args struct {
annotations map[string]interface{}
resourceID string
}
tests := []struct {
name string
args args
wantMaxSeverity string
wantMinSeverity string
}{
{
name: "no severity",
args: args{
annotations: map[string]interface{}{
"test": "test",
},
},
wantMinSeverity: "",
wantMaxSeverity: "",
},
{
name: "min severity set to high",
args: args{annotations: map[string]interface{}{
terrascanMinSeverity: "High",
}},
wantMinSeverity: "High",
wantMaxSeverity: "",
},
{
name: "max severity set to low",
args: args{annotations: map[string]interface{}{
terrascanMaxSeverity: "Low",
}},
wantMinSeverity: "",
wantMaxSeverity: "Low",
},
{
name: "max severity set to None",
args: args{annotations: map[string]interface{}{
terrascanMaxSeverity: "None"}},
wantMinSeverity: "",
wantMaxSeverity: "None",
},
{
name: "max severity set to low and Min severity set to high",
args: args{annotations: map[string]interface{}{
terrascanMaxSeverity: "LOw",
terrascanMinSeverity: "hiGh",
}},
wantMinSeverity: "hiGh",
wantMaxSeverity: "LOw",
},
{
name: "invalid min and max value",
args: args{annotations: map[string]interface{}{
terrascanMaxSeverity: 2,
terrascanMinSeverity: false,
}},
wantMinSeverity: "",
wantMaxSeverity: "",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
gotMaxSeverity, gotMinSeverity := readMinMaxSeverityFromAnnotations(tt.args.annotations, tt.args.resourceID)
if gotMaxSeverity != tt.wantMaxSeverity {
t.Errorf("readMinMaxSeverityFromAnnotations() gotMaxSeverity = %v, want %v", gotMaxSeverity, tt.wantMaxSeverity)
}
if gotMinSeverity != tt.wantMinSeverity {
t.Errorf("readMinMaxSeverityFromAnnotations() gotMinSeverity = %v, want %v", gotMinSeverity, tt.wantMinSeverity)
}
})
}
}
4 changes: 3 additions & 1 deletion pkg/iac-providers/output/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ type ResourceConfig struct {
// SkipRules will hold the rules to be skipped for the resource.
// Each iac provider should append the rules to be skipped for a resource,
// while extracting resource from the iac files
SkipRules []SkipRule `json:"skip_rules" yaml:"skip_rules"`
SkipRules []SkipRule `json:"skip_rules" yaml:"skip_rules"`
MaxSeverity string `json:"max_severity"`
MinSeverity string `json:"min_severity"`
}

// SkipRule struct will hold the skipped rule and any comment for the skipped rule
Expand Down
17 changes: 10 additions & 7 deletions pkg/iac-providers/terraform/commons/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,18 @@ func CreateResourceConfig(managedResource *hclConfigs.Resource) (resourceConfig
return resourceConfig, fmt.Errorf("failed to convert hcl.Body to go struct")
}

minSeverity, maxSeverity := utils.GetMinMaxSeverity(c.rangeSource(hclBody.Range()))
// create a resource config
resourceConfig = output.ResourceConfig{
ID: fmt.Sprintf("%s.%s", managedResource.Type, managedResource.Name),
Name: managedResource.Name,
Type: managedResource.Type,
Source: managedResource.DeclRange.Filename,
Line: managedResource.DeclRange.Start.Line,
Config: goOut,
SkipRules: utils.GetSkipRules(c.rangeSource(hclBody.Range())),
ID: fmt.Sprintf("%s.%s", managedResource.Type, managedResource.Name),
Name: managedResource.Name,
Type: managedResource.Type,
Source: managedResource.DeclRange.Filename,
Line: managedResource.DeclRange.Start.Line,
Config: goOut,
SkipRules: utils.GetSkipRules(c.rangeSource(hclBody.Range())),
MaxSeverity: maxSeverity,
MinSeverity: minSeverity,
}

// successful
Expand Down
32 changes: 24 additions & 8 deletions pkg/iac-providers/terraform/v12/testdata/tfjson/config1.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@
"${aws_security_group.sg_playground.id}"
]
},
"skip_rules": null
"skip_rules": null,
"max_severity": "",
"min_severity": ""
}
],
"aws_internet_gateway": [
Expand All @@ -57,7 +59,9 @@
},
"vpc_id": "${aws_vpc.vpc_playground.id}"
},
"skip_rules": null
"skip_rules": null,
"max_severity": "",
"min_severity": ""
}
],
"aws_key_pair": [
Expand All @@ -72,7 +76,9 @@
"key_name": "testKey",
"public_key": "${file(var.public_key_path)}"
},
"skip_rules": null
"skip_rules": null,
"max_severity": "",
"min_severity": ""
}
],
"aws_route_table": [
Expand All @@ -95,7 +101,9 @@
},
"vpc_id": "${aws_vpc.vpc_playground.id}"
},
"skip_rules": null
"skip_rules": null,
"max_severity": "",
"min_severity": ""
}
],
"aws_route_table_association": [
Expand All @@ -110,7 +118,9 @@
"route_table_id": "${aws_route_table.rtb_public_playground.id}",
"subnet_id": "${aws_subnet.subnet_public_playground.id}"
},
"skip_rules": null
"skip_rules": null,
"max_severity": "",
"min_severity": ""
}
],
"aws_security_group": [
Expand Down Expand Up @@ -156,7 +166,9 @@
},
"vpc_id": "${aws_vpc.vpc_playground.id}"
},
"skip_rules": null
"skip_rules": null,
"max_severity": "",
"min_severity": ""
}
],
"aws_subnet": [
Expand All @@ -175,7 +187,9 @@
},
"vpc_id": "${aws_vpc.vpc_playground.id}"
},
"skip_rules": null
"skip_rules": null,
"max_severity": "",
"min_severity": ""
}
],
"aws_vpc": [
Expand All @@ -194,7 +208,9 @@
"Environment": "${var.environment_tag}"
}
},
"skip_rules": null
"skip_rules": null,
"max_severity": "",
"min_severity": ""
}
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@
"region": "${var.region}"
}
},
"skip_rules": null
"skip_rules": null,
"max_severity": "",
"min_severity": ""
}
],
"type1": [
Expand All @@ -43,7 +45,9 @@
"test2": 5,
"test3": "${1 + 2}"
},
"skip_rules": null
"skip_rules": null,
"max_severity": "",
"min_severity": ""
}
],
"type2": [
Expand All @@ -66,7 +70,9 @@
"thing": "${[for x in local.arr: x * 2]}"
}
},
"skip_rules": null
"skip_rules": null,
"max_severity": "",
"min_severity": ""
}
],
"type3": [
Expand All @@ -83,7 +89,9 @@
"heredoc2": "\t\tAnother heredoc, that\n\t\tdoesn't remove indentation\n\t\tlocal.other.3\n\t\t%{if true ? false : true}\"gotcha\"\\n%{else}4%{endif}\n",
"simple": "${4 - 2}"
},
"skip_rules": null
"skip_rules": null,
"max_severity": "",
"min_severity": ""
}
]
}
Loading