Skip to content

Commit

Permalink
✨ Added custom compliance framework upload and compliance framework (…
Browse files Browse the repository at this point in the history
…de)activation (#108)

* ✨ Added custom compliance framework upload and compliance framework (de)activation

Signed-off-by: Paul <[email protected]>

* fix: linting errors

Signed-off-by: Paul <[email protected]>

* fix: implemented requested feedback

Signed-off-by: Paul <[email protected]>

* fix: made requested changes

Signed-off-by: Paul <[email protected]>

* fix: updated linter

Signed-off-by: Paul <[email protected]>

---------

Signed-off-by: Paul <[email protected]>
  • Loading branch information
Pauti authored Jun 28, 2024
1 parent 5bb5468 commit bb2ab1a
Show file tree
Hide file tree
Showing 12 changed files with 688 additions and 1 deletion.
2 changes: 1 addition & 1 deletion .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,4 @@ linters:
- unconvert
- unparam
- unused
- vet
- govet
54 changes: 54 additions & 0 deletions docs/resources/custom_framework.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_custom_framework Resource - terraform-provider-mondoo"
subcategory: ""
description: |-
Set custom Compliance Frameworks for a Mondoo Space.
---

# mondoo_custom_framework (Resource)

Set custom Compliance Frameworks for a Mondoo Space.

## Example Usage

```terraform
provider "mondoo" {
region = "us"
}
variable "mondoo_org" {
description = "The Mondoo Organization ID"
type = string
default = "my-org-1234567"
}
variable "my_custom_framework" {
description = "Path to the custom policy file. The file must be in MQL format."
type = string
default = "framework.mql.yaml"
}
# Create a new space
resource "mondoo_space" "my_space" {
name = "Custom Framework Space"
org_id = var.mondoo_org
}
resource "mondoo_custom_framework" "compliance_framework_example" {
space_id = mondoo_space.my_space.id
data_url = var.my_custom_framework
}
```

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

### Required

- `data_url` (String) URL to the custom Compliance Framework data.
- `space_id` (String) Mondoo Space Identifier.

### Read-Only

- `mrn` (String) Mondoo Resource Name.
47 changes: 47 additions & 0 deletions docs/resources/framework_assignment.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "mondoo_framework_assignment Resource - terraform-provider-mondoo"
subcategory: ""
description: |-
Set Compliance Frameworks for a Mondoo Space.
---

# mondoo_framework_assignment (Resource)

Set Compliance Frameworks for a Mondoo Space.

## Example Usage

```terraform
provider "mondoo" {
region = "us"
}
variable "mondoo_org" {
description = "The Mondoo Organization ID"
type = string
default = "my-org-1234567"
}
# Create a new space
resource "mondoo_space" "my_space" {
name = "Framework Space"
org_id = var.mondoo_org
}
resource "mondoo_framework_assignment" "compliance_framework_example" {
space_id = mondoo_space.my_space.id
framework_mrn = ["//policy.api.mondoo.app/frameworks/cis-controls-8",
"//policy.api.mondoo.app/frameworks/iso-27001-2022"]
enabled = true
}
```

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

### Required

- `enabled` (Boolean) Enable or disable the Compliance Framework.
- `framework_mrn` (List of String) Compliance Framework MRN.
- `space_id` (String) Mondoo Space Identifier.
44 changes: 44 additions & 0 deletions examples/resources/mondoo_custom_framework/framework.mql.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
frameworks:
- uid: example-framework
name: Example Framework
version: "1.0"
license: open-source
tags:
example.com/icon: example
authors:
- name: Example Author
groups:
- uid: example-group-am
title: Asset Management (AM)
controls:
- uid: example-control-am-01
title: Asset Inventory
docs:
desc: >-
A short description
evidence:
- uid: example-evidence-01
- uid: example-control-am-02
title: Acceptable Use and Safe Handling of Assets Policy
docs:
desc: >-
A short description
evidence:
- uid: example-evidence-02
- uid: example-group-bcm
title: Business Continuity Management (BCM)
controls:
- uid: example-control-bcm-01
title: Top Management Responsibility
docs:
desc: >-
A short description
evidence:
- uid: example-evidence-03
- uid: example-control-bcm-02
title: Business Impact Analysis Policies and Instructions
docs:
desc: >-
A short description
evidence:
- uid: example-evidence-04
8 changes: 8 additions & 0 deletions examples/resources/mondoo_custom_framework/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
terraform {
required_providers {
mondoo = {
source = "mondoohq/mondoo"
version = ">= 0.4.0"
}
}
}
26 changes: 26 additions & 0 deletions examples/resources/mondoo_custom_framework/resource.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
provider "mondoo" {
region = "us"
}

variable "mondoo_org" {
description = "The Mondoo Organization ID"
type = string
default = "my-org-1234567"
}

variable "my_custom_framework" {
description = "Path to the custom policy file. The file must be in MQL format."
type = string
default = "framework.mql.yaml"
}

# Create a new space
resource "mondoo_space" "my_space" {
name = "Custom Framework Space"
org_id = var.mondoo_org
}

resource "mondoo_custom_framework" "compliance_framework_example" {
space_id = mondoo_space.my_space.id
data_url = var.my_custom_framework
}
8 changes: 8 additions & 0 deletions examples/resources/mondoo_framework_assignment/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
terraform {
required_providers {
mondoo = {
source = "mondoohq/mondoo"
version = ">= 0.4.0"
}
}
}
22 changes: 22 additions & 0 deletions examples/resources/mondoo_framework_assignment/resource.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
provider "mondoo" {
region = "us"
}

variable "mondoo_org" {
description = "The Mondoo Organization ID"
type = string
default = "my-org-1234567"
}

# Create a new space
resource "mondoo_space" "my_space" {
name = "Framework Space"
org_id = var.mondoo_org
}

resource "mondoo_framework_assignment" "compliance_framework_example" {
space_id = mondoo_space.my_space.id
framework_mrn = ["//policy.api.mondoo.app/frameworks/cis-controls-8",
"//policy.api.mondoo.app/frameworks/iso-27001-2022"]
enabled = true
}
153 changes: 153 additions & 0 deletions internal/provider/compliance_framework_resource.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
package provider

import (
"context"
"fmt"

"github.com/hashicorp/terraform-plugin-framework/path"
"github.com/hashicorp/terraform-plugin-framework/resource"
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
"github.com/hashicorp/terraform-plugin-framework/types"
mondoov1 "go.mondoo.com/mondoo-go"
)

var _ resource.Resource = (*complianceFrameworkResource)(nil)

func NewComplianceFrameworkResource() resource.Resource {
return &complianceFrameworkResource{}
}

type complianceFrameworkResource struct {
client *ExtendedGqlClient
}

type complianceFrameworkResourceModel struct {
// scope
SpaceId types.String `tfsdk:"space_id"`

// resource details
FrameworkMrn types.List `tfsdk:"framework_mrn"`
Enabled types.Bool `tfsdk:"enabled"`
}

func (r *complianceFrameworkResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
resp.TypeName = req.ProviderTypeName + "_framework_assignment"
}

func (r *complianceFrameworkResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
resp.Schema = schema.Schema{
MarkdownDescription: `Set Compliance Frameworks for a Mondoo Space.`,
Attributes: map[string]schema.Attribute{
"space_id": schema.StringAttribute{
MarkdownDescription: "Mondoo Space Identifier.",
Required: true,
},
"framework_mrn": schema.ListAttribute{
MarkdownDescription: "Compliance Framework MRN.",
Required: true,
ElementType: types.StringType,
},
"enabled": schema.BoolAttribute{
MarkdownDescription: "Enable or disable the Compliance Framework.",
Required: true,
},
},
}
}

func (r *complianceFrameworkResource) Configure(ctx context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) {
// Prevent panic if the provider has not been configured.
if req.ProviderData == nil {
return
}

client, ok := req.ProviderData.(*mondoov1.Client)

if !ok {
resp.Diagnostics.AddError(
"Unexpected Resource Configure Type",
fmt.Sprintf("Expected *http.Client, got: %T. Please report this issue to the provider developers.", req.ProviderData),
)

return
}

r.client = &ExtendedGqlClient{client}
}

func (r *complianceFrameworkResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
var data complianceFrameworkResourceModel

// Read Terraform plan data into the model
resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...)

if resp.Diagnostics.HasError() {
return
}

err := r.client.BulkUpdateFramework(ctx, data.FrameworkMrn, data.SpaceId.ValueString(), data.Enabled.ValueBool())
if err != nil {
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to create Compliance Framework, got error: %s", err))
return
}

// Save data into Terraform state
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
}

func (r *complianceFrameworkResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
var data complianceFrameworkResourceModel

// Read Terraform prior state data into the model
resp.Diagnostics.Append(req.State.Get(ctx, &data)...)

if resp.Diagnostics.HasError() {
return
}

// Read API call logic

// Save updated data into Terraform state
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
}

func (r *complianceFrameworkResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
var data complianceFrameworkResourceModel

// Read Terraform plan data into the model
resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...)

if resp.Diagnostics.HasError() {
return
}

err := r.client.BulkUpdateFramework(ctx, data.FrameworkMrn, data.SpaceId.ValueString(), data.Enabled.ValueBool())
if err != nil {
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to create Compliance Framework, got error: %s", err))
return
}

// Save updated data into Terraform state
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
}

func (r *complianceFrameworkResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
var data complianceFrameworkResourceModel

// Read Terraform prior state data into the model
resp.Diagnostics.Append(req.State.Get(ctx, &data)...)

if resp.Diagnostics.HasError() {
return
}

err := r.client.BulkUpdateFramework(ctx, data.FrameworkMrn, data.SpaceId.ValueString(), false)
if err != nil {
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to create Compliance Framework, got error: %s", err))
return
}
}

func (r *complianceFrameworkResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
resource.ImportStatePassthroughID(ctx, path.Root("mrn"), req, resp)
}
Loading

0 comments on commit bb2ab1a

Please sign in to comment.