Skip to content

Commit

Permalink
fix: updating exceptions
Browse files Browse the repository at this point in the history
Signed-off-by: Matthias Theuermann <[email protected]>
  • Loading branch information
mati007thm committed Dec 6, 2024
1 parent 8379f89 commit d8698b5
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 169 deletions.
54 changes: 54 additions & 0 deletions docs/resources/exception.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "mondoo_exception Resource - terraform-provider-mondoo"
subcategory: ""
description: |-
Set custom exceptions fot a Scope.
---

# mondoo_exception (Resource)

Set custom exceptions fot a Scope.

## Example Usage

```terraform
variable "spaceId" {
type = string
}
provider "mondoo" {
region = "eu"
space = var.spaceId
}
data "mondoo_assets" "assets_data" {
space_id = var.spaceId
}
locals {
ssl_asset = [for asset in data.mondoo_assets.assets_data.assets : asset if startswith(asset.name, "https")]
assetId = one(local.ssl_asset).id
}
resource "mondoo_exception" "exception" {
scope_mrn = "//assets.api.mondoo.app/spaces/${var.spaceId}/assets/${local.assetId}"
valid_until = "2024-12-11"
justification = "testing"
action = "SNOOZE"
check_mrns = ["//policy.api.mondoo.app/queries/mondoo-tls-security-mitigate-beast"]
}
```

<!-- schema generated by tfplugindocs -->
## Schema

### Optional

- `action` (String) The action to perform. Default is `SNOOZE`. Other options are `ENABLE`, `DISABLE`, `OUT_OF_SCOPE`.
- `check_mrns` (List of String) List of check MRNs to set exceptions for.
- `justification` (String) Description why the exception is required.
- `scope_mrn` (String) The MRN of the scope (either asset mrn or space mrn).
- `valid_until` (String) The timestamp until the exception is valid.
- `vulnerability_mrns` (List of String) List of vulnerability MRNs to set exceptions for.
17 changes: 8 additions & 9 deletions examples/resources/mondoo_exception/resource.tf
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,23 @@ variable "spaceId" {

provider "mondoo" {
region = "eu"
space = var.spaceId
space = var.spaceId
}

data "mondoo_assets" "assets_data" {
space_id = var.spaceId
}

locals {
ssl_asset = [ for asset in data.mondoo_assets.assets_data.assets: asset if startswith(asset.name, "https") ]
assetId = one(local.ssl_asset).id
locals {
ssl_asset = [for asset in data.mondoo_assets.assets_data.assets : asset if startswith(asset.name, "https")]
assetId = one(local.ssl_asset).id
}


resource "mondoo_exception" "exception" {
scope_mrn = "//assets.api.mondoo.app/spaces/${var.spaceId}/assets/${local.assetId}"
valid_until = "2024-12-11" # will be formatted to 2024-12-12T09:33:46.206Z
scope_mrn = "//assets.api.mondoo.app/spaces/${var.spaceId}/assets/${local.assetId}"
valid_until = "2024-12-11"
justification = "testing"
action ="SNOOZE"
// check_mrns = ["//policy.api.mondoo.app/queries/mondoo-tls-security-no-weak-block-cipher-modes"]
check_mrns = [ "//policy.api.mondoo.app/queries/mondoo-tls-security-mitigate-beast" ]
action = "SNOOZE"
check_mrns = ["//policy.api.mondoo.app/queries/mondoo-tls-security-mitigate-beast"]
}
61 changes: 14 additions & 47 deletions internal/provider/exception_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,53 +159,23 @@ func (r *exceptionResource) Create(ctx context.Context, req resource.CreateReque
).Format(time.RFC3339Nano) // Use RFC3339Nano to include nanoseconds
}

// Disable existing exceptions
checksToDisable := []string{}
for _, mrn := range checks {
exceptionGroups, err := r.client.ListExceptionGroups(ctx, scopeMrn, mrn, []string{}, []mondoov1.ExceptionMutationAction{})
if err != nil {
resp.Diagnostics.AddError("Failed to list existing exceptions", err.Error())
return
}
if len(exceptionGroups) > 0 {
for _, group := range exceptionGroups {
checksToDisable = append(checksToDisable, group.Exceptions[0].AssetCheckException.Mrn)
}
}
}
vulnerabilitiesToDisable := []string{}
for _, mrn := range vulnerabilities {
exceptionGroups, err := r.client.ListExceptionGroups(ctx, scopeMrn, mrn, []string{}, []mondoov1.ExceptionMutationAction{})
if err != nil {
resp.Diagnostics.AddError("Failed to list existing exceptions", err.Error())
return
}
if len(exceptionGroups) > 0 {
for _, group := range exceptionGroups {
vulnerabilitiesToDisable = append(vulnerabilitiesToDisable, group.Exceptions[0].AssetAdvisoryException.Mrn)
}
}
}
if len(checksToDisable) > 0 || len(vulnerabilitiesToDisable) > 0 {

tflog.Debug((ctx), fmt.Sprintf("Disabling existing exceptions for scope %s", data.ScopeMrn.ValueString()))
err := r.client.ApplyException(ctx, scopeMrn, mondoov1.ExceptionMutationAction("ENABLE"), checksToDisable, []string{}, []string{}, vulnerabilitiesToDisable, (*string)(mondoov1.NewStringPtr("")), (*string)(mondoov1.NewStringPtr("")), (*bool)(mondoov1.NewBooleanPtr(false)))
if err != nil {
resp.Diagnostics.AddError("Failed to disable existing exceptions", err.Error())
return
}
// disable existing exceptions
tflog.Debug(ctx, fmt.Sprintf("Creating exception for scope %s", data.ScopeMrn.ValueString()))
err := r.client.ApplyException(ctx, scopeMrn, mondoov1.ExceptionMutationActionEnable, checks, []string{}, []string{}, vulnerabilities, (*string)(mondoov1.NewStringPtr("")), (*string)(mondoov1.NewStringPtr("")), (*bool)(mondoov1.NewBooleanPtr(false)))
if err != nil {
resp.Diagnostics.AddError("Failed to disable existing exception", err.Error())
return
}

// Create API call logic
tflog.Debug(ctx, fmt.Sprintf("Creating exception for scope %s", data.ScopeMrn.ValueString()))
err := r.client.ApplyException(ctx, scopeMrn, mondoov1.ExceptionMutationAction(data.Action.ValueString()), checks, []string{}, []string{}, vulnerabilities, data.Justification.ValueStringPointer(), &validUntilStr, (*bool)(mondoov1.NewBooleanPtr(false)))
err = r.client.ApplyException(ctx, scopeMrn, mondoov1.ExceptionMutationAction(data.Action.ValueString()), checks, []string{}, []string{}, vulnerabilities, data.Justification.ValueStringPointer(), &validUntilStr, (*bool)(mondoov1.NewBooleanPtr(false)))
if err != nil {
resp.Diagnostics.AddError("Failed to create exception", err.Error())
return
}

data.ScopeMrn = types.StringValue(scopeMrn)
data.ValidUntil = types.StringValue(validUntilStr)

// Save data into Terraform state
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
Expand Down Expand Up @@ -265,24 +235,21 @@ func (r *exceptionResource) Update(ctx context.Context, req resource.UpdateReque
).Format(time.RFC3339Nano) // Use RFC3339Nano to include nanoseconds
}

tflog.Debug((ctx), fmt.Sprintf("Disabling existing exceptions for scope %s", data.ScopeMrn.ValueString()))
err := r.client.ApplyException(ctx, data.ScopeMrn.ValueString(), mondoov1.ExceptionMutationAction("ENABLE"), checks, []string{}, []string{}, vulnerabilities, (*string)(mondoov1.NewStringPtr("")), (*string)(mondoov1.NewStringPtr("")), (*bool)(mondoov1.NewBooleanPtr(false)))
tflog.Debug(ctx, fmt.Sprintf("Deleting exception for scope %s", data.ScopeMrn.ValueString()))
err := r.client.ApplyException(ctx, data.ScopeMrn.ValueString(), mondoov1.ExceptionMutationActionEnable, checks, []string{}, []string{}, vulnerabilities, (*string)(mondoov1.NewStringPtr("")), (*string)(mondoov1.NewStringPtr("")), (*bool)(mondoov1.NewBooleanPtr(false)))
if err != nil {
resp.Diagnostics.AddError("Failed to disable existing exceptions", err.Error())
resp.Diagnostics.AddError("Failed to disable existing exception", err.Error())
return
}

// Create API call logic
// Update API call logic
tflog.Debug(ctx, fmt.Sprintf("Creating exception for scope %s", data.ScopeMrn.ValueString()))
err = r.client.ApplyException(ctx, data.ScopeMrn.String(), mondoov1.ExceptionMutationAction(data.Action.ValueString()), checks, []string{}, []string{}, vulnerabilities, data.Justification.ValueStringPointer(), &validUntilStr, (*bool)(mondoov1.NewBooleanPtr(false)))
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)))
if err != nil {
resp.Diagnostics.AddError("Failed to create exception", err.Error())
resp.Diagnostics.AddError("Failed to update exception", err.Error())
return
}

data.ScopeMrn = types.StringValue(data.ScopeMrn.ValueString())
data.ValidUntil = types.StringValue(validUntilStr)

// Save updated data into Terraform state
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
}
Expand All @@ -305,7 +272,7 @@ func (r *exceptionResource) Delete(ctx context.Context, req resource.DeleteReque

// Delete API call logic
tflog.Debug(ctx, fmt.Sprintf("Deleting exception for scope %s", data.ScopeMrn.ValueString()))
err := r.client.ApplyException(ctx, data.ScopeMrn.ValueString(), mondoov1.ExceptionMutationAction("ENABLE"), checks, []string{}, []string{}, vulnerabilities, (*string)(mondoov1.NewStringPtr("")), (*string)(mondoov1.NewStringPtr("")), (*bool)(mondoov1.NewBooleanPtr(false)))
err := r.client.ApplyException(ctx, data.ScopeMrn.ValueString(), mondoov1.ExceptionMutationActionEnable, checks, []string{}, []string{}, vulnerabilities, (*string)(mondoov1.NewStringPtr("")), (*string)(mondoov1.NewStringPtr("")), (*bool)(mondoov1.NewBooleanPtr(false)))
if err != nil {
resp.Diagnostics.AddError("Failed to delete exception", err.Error())
return
Expand Down
113 changes: 0 additions & 113 deletions internal/provider/gql.go
Original file line number Diff line number Diff line change
Expand Up @@ -973,118 +973,5 @@ func (c *ExtendedGqlClient) ApplyException(
ApplyToCves: mondoov1.NewBooleanPtr(mondoov1.Boolean(*applyToCves)),
}

fmt.Println("====================================")
fmt.Println("Scope:", input.ScopeMrn)
fmt.Println("Action:", input.Action)
fmt.Println("CheckMrns:", *input.QueryMrns)
// fmt.Println("ControlMrns:", *input.ControlMrns)
// fmt.Println("CveMrns:", *input.CveMrns)
// fmt.Println("VulnerabilityMrns:", *input.AdvisoryMrns)
fmt.Println("Justification:", *input.Justification)
fmt.Println("ValidUntil:", *input.ValidUntil)
fmt.Println("ApplyToCves:", *input.ApplyToCves)
fmt.Println("====================================")

return c.Mutate(ctx, &applyException, input, nil)
}

// Reviewer represents the reviewer of the exception group
type Reviewer struct {
Email string `json:"email"`
Name string `json:"name"`
}

// AssetAdvisoryException represents exceptions related to asset advisories
type AssetAdvisoryException struct {
Mrn string `graphql:"mrn"`
}

// AssetCheckException represents exceptions related to asset checks
type AssetCheckException struct {
Mrn string `graphql:"mrn"`
}

// AssetCveException represents exceptions related to CVEs
type AssetCveException struct {
Mrn string `graphql:"mrn"`
}

// SpaceCheckException represents exceptions related to space checks
type SpaceCheckException struct {
Mrn string `graphql:"mrn"`
}

// Exception is a union of all exception types
type Exception struct {
AssetAdvisoryException *AssetAdvisoryException `graphql:"... on AssetAdvisoryException"`
AssetCheckException *AssetCheckException `graphql:"... on AssetCheckException"`
AssetCveException *AssetCveException `graphql:"... on AssetCveException"`
SpaceCheckException *SpaceCheckException `graphql:"... on SpaceCheckException"`
}

// ExceptionGroup represents a group of exceptions
type ExceptionGroup struct {
ID string `graphql:"id"`
ScopeMrn string `graphql:"scopeMrn"`
Title string `graphql:"title"`
Justification string `graphql:"justification"`
ReviewStatus string `graphql:"reviewStatus"`
Action string `graphql:"action"`
CreatedAt string `graphql:"createdAt"`
ModifiedAt string `graphql:"modifiedAt"`
Author Author `graphql:"author"`
Reviewer Reviewer `graphql:"reviewer"`
Exceptions []Exception `graphql:"exceptions"`
}

// ListExceptionGroups retrieves a list of exception groups
func (c *ExtendedGqlClient) ListExceptionGroups(
ctx context.Context,
scopeMrn string,
mrn string,
types []string,
actions []mondoov1.ExceptionMutationAction,
) ([]ExceptionGroup, error) {
// Struct to hold the query response
var listExceptionGroups struct {
ExceptionGroups []ExceptionGroup `graphql:"exceptionGroups(input: $input)"`
}

// Helper function to convert string slices to *[]mondoov1.ExceptionType
convertToGraphQLList := func(values []string) *[]mondoov1.ExceptionType {
if len(values) == 0 {
return nil
}
entries := []mondoov1.ExceptionType{}
for _, value := range values {
entries = append(entries, mondoov1.ExceptionType(value))
}
return &entries
}

// Safely construct input
var mrnValue *mondoov1.String
if mrn != "" {
mrnValue = mondoov1.NewStringPtr(mondoov1.String(mrn))
}

fmt.Println("mrnValue", mrn)

// Prepare input for the query
input := mondoov1.ExceptionGroupsInput{
ScopeMrn: mondoov1.String(scopeMrn),
Mrn: mrnValue,
Types: convertToGraphQLList(types),
Actions: &actions,
}
variables := map[string]interface{}{
"input": input,
}

// Execute the query
if err := c.Query(ctx, &listExceptionGroups, variables); err != nil {
return nil, fmt.Errorf("failed to list exception groups: %w", err)
}

return listExceptionGroups.ExceptionGroups, nil
}

0 comments on commit d8698b5

Please sign in to comment.