Skip to content

Commit 0725e76

Browse files
authored
✨ add new exception types (#251)
1 parent 404fd51 commit 0725e76

5 files changed

Lines changed: 79 additions & 24 deletions

File tree

docs/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ resource "mondoo_policy_assignment" "cis_policy_assignment_enabled" {
7676
resource "mondoo_exception" "windows_defender_exception" {
7777
scope_mrn = mondoo_space.my_space.mrn
7878
justification = "Windows Defender is disabled. Other EDR is used/configured instead."
79-
action = "SNOOZE"
79+
action = "RISK_ACCEPTED"
8080
check_mrns = [
8181
"//policy.api.mondoo.app/queries/cis-microsoft-windows-10--18.10.42.5.1",
8282
"//policy.api.mondoo.app/queries/cis-microsoft-windows-11--18.10.42.5.1",

docs/resources/exception.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,9 @@ locals {
3535
3636
resource "mondoo_exception" "exception" {
3737
scope_mrn = "//assets.api.mondoo.app/spaces/${var.space_id}/assets/${local.asset_id}"
38-
valid_until = "2024-12-11"
38+
valid_until = "2025-12-11"
3939
justification = "testing"
40-
action = "SNOOZE"
40+
action = "RISK_ACCEPTED"
4141
check_mrns = ["//policy.api.mondoo.app/queries/mondoo-tls-security-mitigate-beast"]
4242
}
4343
```
@@ -47,7 +47,7 @@ resource "mondoo_exception" "exception" {
4747

4848
### Optional
4949

50-
- `action` (String) The action to perform. Default is `SNOOZE`. Other options are `ENABLE`, `DISABLE`, and `OUT_OF_SCOPE`.
50+
- `action` (String) The action to perform. Default is `RISK_ACCEPTED`. Other valid values are `WORKAROUND`, `FALSE_POSITIVE`, `ENABLE`, `DISABLE`, `OUT_OF_SCOPE` and `SNOOZE`.
5151
- `check_mrns` (List of String) List of check MRNs to set exceptions for. If set, `vulnerability_mrns` must not be set.
5252
- `justification` (String) Description why the exception is required.
5353
- `scope_mrn` (String) The MRN of the scope (either asset mrn or space mrn).

examples/provider/provider.tf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ resource "mondoo_policy_assignment" "cis_policy_assignment_enabled" {
5353
resource "mondoo_exception" "windows_defender_exception" {
5454
scope_mrn = mondoo_space.my_space.mrn
5555
justification = "Windows Defender is disabled. Other EDR is used/configured instead."
56-
action = "SNOOZE"
56+
action = "RISK_ACCEPTED"
5757
check_mrns = [
5858
"//policy.api.mondoo.app/queries/cis-microsoft-windows-10--18.10.42.5.1",
5959
"//policy.api.mondoo.app/queries/cis-microsoft-windows-11--18.10.42.5.1",

examples/resources/mondoo_exception/resource.tf

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ locals {
2020

2121
resource "mondoo_exception" "exception" {
2222
scope_mrn = "//assets.api.mondoo.app/spaces/${var.space_id}/assets/${local.asset_id}"
23-
valid_until = "2024-12-11"
23+
valid_until = "2025-12-11"
2424
justification = "testing"
25-
action = "SNOOZE"
25+
action = "RISK_ACCEPTED"
2626
check_mrns = ["//policy.api.mondoo.app/queries/mondoo-tls-security-mitigate-beast"]
2727
}

internal/provider/exception_resource.go

Lines changed: 72 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"fmt"
66
"regexp"
7+
"slices"
78
"time"
89

910
"github.com/hashicorp/terraform-plugin-framework-validators/listvalidator"
@@ -89,40 +90,79 @@ func (r *exceptionResource) GetConfigurationOptions(ctx context.Context, data *e
8990
return scopeMrn, checks, vulnerabilities, validUntilStr, nil
9091
}
9192

92-
// ValidUntilValidator ensures the "valid_until" attribute is only set when "action" is "SNOOZE".
93-
type ValidUntilValidator struct{}
93+
// ValidUntilActionValidator ensures the "valid_until" attribute is only set when "action" is "SNOOZE", "RISK_ACCEPTED", "WORKAROUND" or "FALSE_POSITIVE".
94+
type ValidUntilActionValidator struct{}
95+
96+
// NewValidUntilActionValidator is a convenience function for creating an instance of the validator.
97+
func NewValidUntilActionValidator() validator.String {
98+
return &ValidUntilActionValidator{}
99+
}
94100

95101
// ValidateString performs the validation for the "valid_until" attribute.
96-
func (v ValidUntilValidator) ValidateString(ctx context.Context, req validator.StringRequest, resp *validator.StringResponse) {
102+
func (v ValidUntilActionValidator) ValidateString(ctx context.Context, req validator.StringRequest, resp *validator.StringResponse) {
97103
// Retrieve the "action" attribute value from the attribute path
98104
var actionAttr types.String
99105
err := req.Config.GetAttribute(ctx, path.Root("action"), &actionAttr)
100106
if err != nil || actionAttr.IsNull() {
101107
return // If "action" is not set or there's an error, nothing to validate
102108
}
103109

104-
if actionAttr.ValueString() != "SNOOZE" && !req.ConfigValue.IsNull() {
110+
validUntilActions := []string{"RISK_ACCEPTED", "WORKAROUND", "FALSE_POSITIVE", "SNOOZE"}
111+
if !slices.Contains(validUntilActions, actionAttr.ValueString()) && !req.ConfigValue.IsNull() {
105112
resp.Diagnostics.AddAttributeError(
106113
req.Path,
107-
"'valid_until' Can Only Be Set with 'action' as 'SNOOZE'",
108-
"To use 'valid_until', the 'action' attribute must be set to 'SNOOZE'. Either remove 'valid_until' or change 'action' to 'SNOOZE'.",
114+
"'valid_until' Can Only Be Set with 'action' as `SNOOZE`, 'RISK_ACCEPTED', 'WORKAROUND' or 'FALSE_POSITIVE'",
115+
"To use 'valid_until', the 'action' attribute must be set to one of the above. Either remove 'valid_until' or change 'action'.",
109116
)
110117
}
111118
}
112119

113120
// Description returns a plain-text description of the validator's purpose.
114-
func (v ValidUntilValidator) Description(ctx context.Context) string {
115-
return "'valid_until' can only be set if 'action' is set to 'SNOOZE'."
121+
func (v ValidUntilActionValidator) Description(ctx context.Context) string {
122+
return "'valid_until' can only be set if 'action' is set to 'SNOOZE', 'RISK_ACCEPTED', 'WORKAROUND' or 'FALSE_POSITIVE'."
116123
}
117124

118125
// MarkdownDescription returns a markdown-formatted description of the validator's purpose.
119-
func (v ValidUntilValidator) MarkdownDescription(ctx context.Context) string {
120-
return "'valid_until' can only be set if 'action' is set to `SNOOZE`."
126+
func (v ValidUntilActionValidator) MarkdownDescription(ctx context.Context) string {
127+
return "'valid_until' can only be set if 'action' is set to 'SNOOZE', 'RISK_ACCEPTED', 'WORKAROUND' or 'FALSE_POSITIVE'."
128+
}
129+
130+
// ValidUntilPresentValidator ensures the "valid_until" attribute is only set when "action" is "SNOOZE", "RISK_ACCEPTED", "WORKAROUND" or "FALSE_POSITIVE".
131+
type ValidUntilPresentValidator struct{}
132+
133+
// NewValidUntilPresentValidator is a convenience function for creating an instance of the validator.
134+
func NewValidUntilPresentValidator() validator.String {
135+
return &ValidUntilPresentValidator{}
136+
}
137+
138+
// ValidateString performs the validation for the "valid_until" attribute.
139+
func (v ValidUntilPresentValidator) ValidateString(ctx context.Context, req validator.StringRequest, resp *validator.StringResponse) {
140+
// Retrieve the "action" attribute value from the attribute path
141+
var actionAttr types.String
142+
err := req.Config.GetAttribute(ctx, path.Root("action"), &actionAttr)
143+
if err != nil || actionAttr.IsNull() {
144+
return // If "action" is not set or there's an error, nothing to validate
145+
}
146+
147+
validUntilActions := []string{"RISK_ACCEPTED", "WORKAROUND", "FALSE_POSITIVE", "SNOOZE"}
148+
149+
if slices.Contains(validUntilActions, actionAttr.ValueString()) && req.ConfigValue.IsNull() {
150+
resp.Diagnostics.AddAttributeError(
151+
req.Path,
152+
"'valid_until' Must be supplied when 'actions' is 'SNOOZE', 'RISK_ACCEPTED', 'WORKAROUND' or 'FALSE_POSITIVE'",
153+
fmt.Sprintf("'valid_until' Must be supplied when 'actions' is %s", actionAttr.ValueString()),
154+
)
155+
}
121156
}
122157

123-
// NewValidUntilValidator is a convenience function for creating an instance of the validator.
124-
func NewValidUntilValidator() validator.String {
125-
return &ValidUntilValidator{}
158+
// Description returns a plain-text description of the validator's purpose.
159+
func (v ValidUntilPresentValidator) Description(ctx context.Context) string {
160+
return "'valid_until' must be supplied when 'actions' is 'SNOOZE', 'RISK_ACCEPTED', 'WORKAROUND' or 'FALSE_POSITIVE'"
161+
}
162+
163+
// MarkdownDescription returns a markdown-formatted description of the validator's purpose.
164+
func (v ValidUntilPresentValidator) MarkdownDescription(ctx context.Context) string {
165+
return "'valid_until' must be supplied when 'actions' is 'SNOOZE', 'RISK_ACCEPTED', 'WORKAROUND' or 'FALSE_POSITIVE'"
126166
}
127167

128168
func (r *exceptionResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
@@ -142,20 +182,21 @@ func (r *exceptionResource) Schema(ctx context.Context, req resource.SchemaReque
142182
Optional: true,
143183
Validators: []validator.String{
144184
stringvalidator.RegexMatches(regexp.MustCompile(`[1-9][0-9][0-9]{2}-([0][1-9]|[1][0-2])-([1-2][0-9]|[0][1-9]|[3][0-1])`), "Date must be in the format 'YYYY-MM-DD'"),
145-
NewValidUntilValidator(),
185+
NewValidUntilActionValidator(),
186+
NewValidUntilPresentValidator(),
146187
},
147188
},
148189
"justification": schema.StringAttribute{
149190
MarkdownDescription: "Description why the exception is required.",
150191
Optional: true,
151192
},
152193
"action": schema.StringAttribute{
153-
MarkdownDescription: "The action to perform. Default is `SNOOZE`. Other options are `ENABLE`, `DISABLE`, and `OUT_OF_SCOPE`.",
194+
MarkdownDescription: "The action to perform. Default is `RISK_ACCEPTED`. Other valid values are `WORKAROUND`, `FALSE_POSITIVE`, `ENABLE`, `DISABLE`, `OUT_OF_SCOPE` and `SNOOZE`.",
154195
Optional: true,
155196
Computed: true,
156-
Default: stringdefault.StaticString("SNOOZE"),
197+
Default: stringdefault.StaticString("RISK_ACCEPTED"),
157198
Validators: []validator.String{
158-
stringvalidator.OneOf("SNOOZE", "ENABLE", "DISABLE", "OUT_OF_SCOPE"),
199+
stringvalidator.OneOf("SNOOZE", "RISK_ACCEPTED", "FALSE_POSITIVE", "WORKAROUND", "ENABLE", "DISABLE", "OUT_OF_SCOPE"),
159200
},
160201
},
161202
"check_mrns": schema.ListAttribute{
@@ -210,6 +251,13 @@ func (r *exceptionResource) Create(ctx context.Context, req resource.CreateReque
210251
// Read Terraform plan data into the model
211252
resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...)
212253

254+
if data.Action.ValueString() == "SNOOZE" {
255+
resp.Diagnostics.AddWarning(
256+
"use of deprecated exception action",
257+
`exception action 'SNOOZE' is deprecated, please use 'RISK_ACCEPTED', 'WORKAROUND' OR 'FALSE_POSITIVE'`,
258+
)
259+
}
260+
213261
if resp.Diagnostics.HasError() {
214262
return
215263
}
@@ -281,6 +329,13 @@ func (r *exceptionResource) Update(ctx context.Context, req resource.UpdateReque
281329
return
282330
}
283331

332+
if data.Action.ValueString() == "SNOOZE" {
333+
resp.Diagnostics.AddWarning(
334+
"use of deprecated exception action",
335+
`exception action 'SNOOZE' is deprecated, please use 'RISK_ACCEPTED', 'WORKAROUND' OR 'FALSE_POSITIVE'`,
336+
)
337+
}
338+
284339
// Update API call logic
285340
tflog.Debug(ctx, fmt.Sprintf("Creating exception for scope %s", data.ScopeMrn.ValueString()))
286341
err = r.client.ApplyException(ctx, data.ScopeMrn.ValueString(), mondoov1.ExceptionMutationAction(data.Action.ValueString()), checks, []string{}, []string{}, vulnerabilities, data.Justification.ValueStringPointer(), &validUntilStr, (*bool)(mondoov1.NewBooleanPtr(false)))

0 commit comments

Comments
 (0)