Skip to content

Commit c0a2f8e

Browse files
committed
feat(secure): add imageConfigLabelWithValueAndLabelsExist predicate to vulnerability rule bundles
1 parent 56617d8 commit c0a2f8e

4 files changed

Lines changed: 117 additions & 9 deletions

File tree

sysdig/internal/client/v2/vulnerability_rule_bundle_model.go

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,16 @@ type VulnerabilityRulePredicate struct {
2121

2222
type VulnerabilityRulePredicateExtra struct {
2323
// Common fields for different predicate types
24-
Level *Level `json:"level,omitempty"`
25-
Age *int `json:"age,omitempty"`
26-
Days *int `json:"days,omitempty"`
27-
PkgType *string `json:"pkgType,omitempty"`
28-
VulnIDS []string `json:"vulnIds,omitempty"`
29-
Packages []Package `json:"packages,omitempty"`
30-
Key *string `json:"key,omitempty"`
31-
User *string `json:"user,omitempty"`
32-
Value any `json:"value,omitempty"` // For image labels or CVSS score
24+
Level *Level `json:"level,omitempty"`
25+
Age *int `json:"age,omitempty"`
26+
Days *int `json:"days,omitempty"`
27+
PkgType *string `json:"pkgType,omitempty"`
28+
VulnIDS []string `json:"vulnIds,omitempty"`
29+
Packages []Package `json:"packages,omitempty"`
30+
Key *string `json:"key,omitempty"`
31+
User *string `json:"user,omitempty"`
32+
Value any `json:"value,omitempty"` // For image labels or CVSS score
33+
RequiredLabels []string `json:"requiredLabels,omitempty"`
3334

3435
// Disclosure Date Range
3536
StartDate *string `json:"startDate,omitempty"`

sysdig/resource_sysdig_secure_vulnerability_rule_bundle.go

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,32 @@ func vulnerabilityRuleSchemaImageConfigLabel() *schema.Schema {
5656
},
5757
},
5858
},
59+
"label_with_value_and_required_labels": {
60+
Type: schema.TypeList,
61+
Optional: true,
62+
MaxItems: 1,
63+
Description: "A label key-value pair that must exist along with additional required labels.",
64+
Elem: &schema.Resource{
65+
Schema: map[string]*schema.Schema{
66+
"target_label": {
67+
Type: schema.TypeString,
68+
Required: true,
69+
Description: "Label key that must exist with the specified value.",
70+
},
71+
"target_value": {
72+
Type: schema.TypeString,
73+
Required: true,
74+
Description: "Expected value for the target label. Can be empty.",
75+
},
76+
"required_labels": {
77+
Type: schema.TypeList,
78+
Required: true,
79+
Description: "Additional label keys that must also exist.",
80+
Elem: &schema.Schema{Type: schema.TypeString},
81+
},
82+
},
83+
},
84+
},
5985
},
6086
},
6187
}
@@ -574,6 +600,17 @@ func vulnerabilityRuleImageConfigLabelToData(ruleBundle v2.VulnerabilityRule) (m
574600
}},
575601
}},
576602
}, nil
603+
case "imageConfigLabelWithValueAndLabelsExist":
604+
return map[string]any{
605+
"image_label": []map[string]any{{
606+
"id": ruleBundle.ID,
607+
"label_with_value_and_required_labels": []map[string]any{{
608+
"target_label": ruleBundle.Predicates[0].Extra.Key,
609+
"target_value": ruleBundle.Predicates[0].Extra.Value,
610+
"required_labels": ruleBundle.Predicates[0].Extra.RequiredLabels,
611+
}},
612+
}},
613+
}, nil
577614
}
578615

579616
return nil, fmt.Errorf("unsupported image config label rule for predicate: %s", ruleBundle.Predicates[0].Type)
@@ -765,6 +802,23 @@ func vulnerabilityRuleImageConfigLabelFromMap(ruleBody map[string]any) (v2.Vulne
765802
})
766803
}
767804

805+
if label, ok := ruleBody["label_with_value_and_required_labels"]; ok && len(label.([]any)) > 0 {
806+
contents := label.([]any)[0].(map[string]any)
807+
rawLabels := contents["required_labels"].([]any)
808+
requiredLabels := make([]string, len(rawLabels))
809+
for i, v := range rawLabels {
810+
requiredLabels[i] = v.(string)
811+
}
812+
rule.Predicates = append(rule.Predicates, v2.VulnerabilityRulePredicate{
813+
Type: "imageConfigLabelWithValueAndLabelsExist",
814+
Extra: &v2.VulnerabilityRulePredicateExtra{
815+
Key: new(contents["target_label"].(string)),
816+
Value: new(contents["target_value"].(string)),
817+
RequiredLabels: requiredLabels,
818+
},
819+
})
820+
}
821+
768822
if len(rule.Predicates) == 0 {
769823
return v2.VulnerabilityRule{}, errors.New("no predicate has been specified for image label rule")
770824
}

sysdig/resource_sysdig_secure_vulnerability_rule_bundle_test.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,16 @@ func TestAccVulnerabilityRuleBundle(t *testing.T) {
9494
resource.TestCheckResourceAttr("sysdig_secure_vulnerability_rule_bundle.sample", "rule.0.image_label.0.label_must_exist_and_contain_value.0.required_value", "required-value"),
9595
),
9696
},
97+
{
98+
Config: singleRuleConfig_label_with_value_and_required_labels(random()),
99+
Check: resource.ComposeTestCheckFunc(
100+
resource.TestCheckResourceAttr("sysdig_secure_vulnerability_rule_bundle.sample", "rule.0.image_label.0.label_with_value_and_required_labels.0.target_label", "Vendor"),
101+
resource.TestCheckResourceAttr("sysdig_secure_vulnerability_rule_bundle.sample", "rule.0.image_label.0.label_with_value_and_required_labels.0.target_value", "BNPP"),
102+
resource.TestCheckResourceAttr("sysdig_secure_vulnerability_rule_bundle.sample", "rule.0.image_label.0.label_with_value_and_required_labels.0.required_labels.#", "2"),
103+
resource.TestCheckResourceAttr("sysdig_secure_vulnerability_rule_bundle.sample", "rule.0.image_label.0.label_with_value_and_required_labels.0.required_labels.0", "Team"),
104+
resource.TestCheckResourceAttr("sysdig_secure_vulnerability_rule_bundle.sample", "rule.0.image_label.0.label_with_value_and_required_labels.0.required_labels.1", "Org"),
105+
),
106+
},
97107
{
98108
Config: fullVulnerabilityRuleBundleConfig_Severities(random()),
99109
Check: resource.ComposeTestCheckFunc(
@@ -259,6 +269,24 @@ resource "sysdig_secure_vulnerability_rule_bundle" "sample" {
259269
`, suffix)
260270
}
261271

272+
func singleRuleConfig_label_with_value_and_required_labels(suffix string) string {
273+
return fmt.Sprintf(`
274+
resource "sysdig_secure_vulnerability_rule_bundle" "sample" {
275+
name = "TERRAFORM TEST %s"
276+
description = "rule with label_with_value_and_required_labels"
277+
rule {
278+
image_label {
279+
label_with_value_and_required_labels {
280+
target_label = "Vendor"
281+
target_value = "BNPP"
282+
required_labels = ["Team", "Org"]
283+
}
284+
}
285+
}
286+
}
287+
`, suffix)
288+
}
289+
262290
func fullVulnerabilityRuleBundleConfig_Severities(suffix string) string {
263291
return fmt.Sprintf(`
264292
resource "sysdig_secure_vulnerability_rule_bundle" "sample" {
@@ -469,6 +497,16 @@ resource "sysdig_secure_vulnerability_rule_bundle" "sample" {
469497
}
470498
}
471499
500+
rule {
501+
image_label {
502+
label_with_value_and_required_labels {
503+
target_label = "Vendor"
504+
target_value = "BNPP"
505+
required_labels = ["Team", "Org"]
506+
}
507+
}
508+
}
509+
472510
rule {
473511
severities_and_threats {
474512
severity_at_least = "high"

website/docs/r/secure_vulnerability_rule_bundle.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,17 @@ resource "sysdig_secure_vulnerability_rule_bundle" "example_image_label" {
4747
}
4848
}
4949
}
50+
51+
# Rule to ensure a label exists with a value AND other labels also exist
52+
rule {
53+
image_label {
54+
label_with_value_and_required_labels {
55+
target_label = "Vendor"
56+
target_value = "BNPP"
57+
required_labels = ["Team", "Org"]
58+
}
59+
}
60+
}
5061
}
5162
```
5263

@@ -114,6 +125,10 @@ Defines rules based on image labels to evaluate image configuration. Only one of
114125
* `label_must_exist_and_contain_value` - (Optional) A block specifying a label key and value that must exist in the image configuration.
115126
* `required_label` - (Required) The label key that must exist.
116127
* `required_value` - (Required) The expected value for the given label key.
128+
* `label_with_value_and_required_labels` - (Optional) A block specifying a label key-value pair that must exist along with additional required labels.
129+
* `target_label` - (Required) The label key that must exist with the specified value.
130+
* `target_value` - (Required) The expected value for the target label. Can be empty.
131+
* `required_labels` - (Required) A list of additional label keys that must also exist.
117132

118133
#### `severities_and_threats`
119134

0 commit comments

Comments
 (0)