diff --git a/docs/resources/querypack_assignment.md b/docs/resources/querypack_assignment.md new file mode 100644 index 0000000..396d7e5 --- /dev/null +++ b/docs/resources/querypack_assignment.md @@ -0,0 +1,58 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "mondoo_querypack_assignment Resource - terraform-provider-mondoo" +subcategory: "" +description: |- + +--- + +# mondoo_querypack_assignment (Resource) + + + +## Example Usage + +```terraform +terraform { + required_providers { + mondoo = { + source = "mondoohq/mondoo" + } + } +} + +provider "mondoo" { + region = "us" +} + +resource "mondoo_space" "my_space" { + name = "My Space Name" + org_id = "your-org-1234567" +} + +resource "mondoo_querypack_assignment" "space" { + space_id = mondoo_space.my_space.id + + querypacks = [ + "//policy.api.mondoo.app/policies/mondoo-incident-response-aws", + ] + + state = "enabled" # default is enabled, we also support preview and disabled + + depends_on = [ + mondoo_space.my_space + ] +} +``` + + +## Schema + +### Required + +- `space_id` (String) Mondoo Space Identifier. + +### Optional + +- `querypacks` (List of String) QueryPacks to assign to the space. +- `state` (String) QueryPack Assignment State (enabled, disabled). diff --git a/docs/resources/scim_group_mapping.md b/docs/resources/scim_group_mapping.md new file mode 100644 index 0000000..71a61fb --- /dev/null +++ b/docs/resources/scim_group_mapping.md @@ -0,0 +1,73 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "mondoo_scim_group_mapping Resource - terraform-provider-mondoo" +subcategory: "" +description: |- + This resource provides SCIM 2.0 Group Mapping. It allows the mapping of SCIM 2.0 groups to Mondoo organization or spaces and IAM roles. +--- + +# mondoo_scim_group_mapping (Resource) + +This resource provides SCIM 2.0 Group Mapping. It allows the mapping of SCIM 2.0 groups to Mondoo organization or spaces and IAM roles. + +## Example Usage + +```terraform +terraform { + required_providers { + mondoo = { + source = "mondoohq/mondoo" + } + } +} + +provider "mondoo" { +} + +resource "mondoo_space" "my_space_1" { + name = "My Space 1" + org_id = "your-org-1234567" +} + +resource "mondoo_scim_group_mapping" "MondooAdmin" { + org_id = "your-org-1234567" + group = "MondooAdmin" + mappings = [ + # Give admin group access to the organization + { + org_mrn : "//captain.api.mondoo.app/organizations/your-org-1234567", + iam_role : "//iam.api.mondoo.app/roles/editor" + }, + # Give admin group access to the space + { + space_mrn : mondoo_space.my_space_1.mrn, + iam_role : "//iam.api.mondoo.app/roles/viewer" + } + ] + + depends_on = [ + mondoo_space.my_space_1 + ] +} +``` + + +## Schema + +### Required + +- `group` (String) SCIM 2.0 Group Display Name. +- `mappings` (Attributes List) (see [below for nested schema](#nestedatt--mappings)) +- `org_id` (String) Mondoo Organization Identifier. + + +### Nested Schema for `mappings` + +Required: + +- `iam_role` (String) + +Optional: + +- `org_mrn` (String) +- `space_mrn` (String) diff --git a/examples/resources/mondoo_querypack_assignment/resource.tf b/examples/resources/mondoo_querypack_assignment/resource.tf new file mode 100644 index 0000000..388aff3 --- /dev/null +++ b/examples/resources/mondoo_querypack_assignment/resource.tf @@ -0,0 +1,30 @@ +terraform { + required_providers { + mondoo = { + source = "mondoohq/mondoo" + } + } +} + +provider "mondoo" { + region = "us" +} + +resource "mondoo_space" "my_space" { + name = "My Space Name" + org_id = "your-org-1234567" +} + +resource "mondoo_querypack_assignment" "space" { + space_id = mondoo_space.my_space.id + + querypacks = [ + "//policy.api.mondoo.app/policies/mondoo-incident-response-aws", + ] + + state = "enabled" # default is enabled, we also support preview and disabled + + depends_on = [ + mondoo_space.my_space + ] +} diff --git a/examples/resources/mondoo_scim_group_mapping/resource.tf b/examples/resources/mondoo_scim_group_mapping/resource.tf new file mode 100644 index 0000000..0a2116a --- /dev/null +++ b/examples/resources/mondoo_scim_group_mapping/resource.tf @@ -0,0 +1,36 @@ +terraform { + required_providers { + mondoo = { + source = "mondoohq/mondoo" + } + } +} + +provider "mondoo" { +} + +resource "mondoo_space" "my_space_1" { + name = "My Space 1" + org_id = "your-org-1234567" +} + +resource "mondoo_scim_group_mapping" "MondooAdmin" { + org_id = "your-org-1234567" + group = "MondooAdmin" + mappings = [ + # Give admin group access to the organization + { + org_mrn : "//captain.api.mondoo.app/organizations/your-org-1234567", + iam_role : "//iam.api.mondoo.app/roles/editor" + }, + # Give admin group access to the space + { + space_mrn : mondoo_space.my_space_1.mrn, + iam_role : "//iam.api.mondoo.app/roles/viewer" + } + ] + + depends_on = [ + mondoo_space.my_space_1 + ] +} diff --git a/go.mod b/go.mod index bdb8155..2b6e640 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/hashicorp/terraform-plugin-log v0.9.0 github.com/hashicorp/terraform-plugin-testing v1.6.0 github.com/stretchr/testify v1.9.0 - go.mondoo.com/mondoo-go v0.0.0-20240302214252-fc86ebca9dba + go.mondoo.com/mondoo-go v0.0.0-20240303102235-bc102d6ef0cb ) require ( diff --git a/go.sum b/go.sum index c371ceb..0db6cc8 100644 --- a/go.sum +++ b/go.sum @@ -510,8 +510,8 @@ github.com/zclconf/go-cty v1.14.1/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgr go.etcd.io/etcd/api/v3 v3.5.4/go.mod h1:5GB2vv4A4AOn3yk7MftYGHkUfGtDHnEraIjym4dYz5A= go.etcd.io/etcd/client/pkg/v3 v3.5.4/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= go.etcd.io/etcd/client/v3 v3.5.4/go.mod h1:ZaRkVgBZC+L+dLCjTcF1hRXpgZXQPOvnA/Ak/gq3kiY= -go.mondoo.com/mondoo-go v0.0.0-20240302214252-fc86ebca9dba h1:V3K0LlllLhWDd7nrB9N04MeaBR908XkkiNl7g2pfNgA= -go.mondoo.com/mondoo-go v0.0.0-20240302214252-fc86ebca9dba/go.mod h1:JDTzAPQ3y9bVoDOBrkhcd1zFKHKjmeuJ0jZRTeQ46QA= +go.mondoo.com/mondoo-go v0.0.0-20240303102235-bc102d6ef0cb h1:37qJkE0oehPTtpnRJ4PKzXpBh4v3KVCHyRiWAY3RRF4= +go.mondoo.com/mondoo-go v0.0.0-20240303102235-bc102d6ef0cb/go.mod h1:JDTzAPQ3y9bVoDOBrkhcd1zFKHKjmeuJ0jZRTeQ46QA= go.mongodb.org/mongo-driver v1.10.0 h1:UtV6N5k14upNp4LTduX0QCufG124fSu25Wz9tu94GLg= go.mongodb.org/mongo-driver v1.10.0/go.mod h1:wsihk0Kdgv8Kqu1Anit4sfK+22vSFbUrAVEYRhCXrA8= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= diff --git a/internal/provider/gql.go b/internal/provider/gql.go index b387524..ad38303 100644 --- a/internal/provider/gql.go +++ b/internal/provider/gql.go @@ -7,6 +7,7 @@ import ( "context" "encoding/base64" "fmt" + "github.com/hashicorp/terraform-plugin-log/tflog" mondoov1 "go.mondoo.com/mondoo-go" ) @@ -293,3 +294,19 @@ func (c *ExtendedGqlClient) DeleteIntegration(ctx context.Context, mrn string) ( } return &deleteMutation.DeleteClientIntegration, nil } + +func (c *ExtendedGqlClient) SetScimGroupMapping(ctx context.Context, orgMrn string, group string, mappings []mondoov1.ScimGroupMapping) error { + var setScimGroupMappingMutation struct { + SetScimGroupMapping struct { + Group mondoov1.String + } `graphql:"setScimGroupMapping(input: $input)"` + } + + setScimGroupMappingInput := mondoov1.SetScimGroupMappingInput{ + OrgMrn: mondoov1.String(orgMrn), + Group: mondoov1.String(group), + Mappings: mappings, + } + + return c.Mutate(ctx, &setScimGroupMappingMutation, setScimGroupMappingInput, nil) +} diff --git a/internal/provider/provider.go b/internal/provider/provider.go index d2c9489..658bec9 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -163,6 +163,7 @@ func (p *MondooProvider) Resources(ctx context.Context) []func() resource.Resour NewQueryPackAssigmentResource, NewIntegrationGcpResource, NewIntegrationOciTenantResource, + NewScimGroupMappingResource, } } diff --git a/internal/provider/scim_group_mapping.go b/internal/provider/scim_group_mapping.go new file mode 100644 index 0000000..1503ef0 --- /dev/null +++ b/internal/provider/scim_group_mapping.go @@ -0,0 +1,225 @@ +// Copyright (c) Mondoo, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package provider + +import ( + "context" + "fmt" + + "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 = (*policyAssignmentResource)(nil) + +func NewScimGroupMappingResource() resource.Resource { + return &scimGroupMappingResource{} +} + +type scimGroupMappingResource struct { + client *ExtendedGqlClient +} + +type scimGroupMappingResourceModel struct { + // scope + OrgID types.String `tfsdk:"org_id"` + Group types.String `tfsdk:"group"` + + // mapped org and spaces + Mappings []scimGroupMappingResourceMappingModel `tfsdk:"mappings"` +} + +type scimGroupMappingResourceMappingModel struct { + IamRole types.String `tfsdk:"iam_role"` + SpaceMrn types.String `tfsdk:"space_mrn"` + OrgMrn types.String `tfsdk:"org_mrn"` +} + +func (r *scimGroupMappingResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_scim_group_mapping" +} + +func (r *scimGroupMappingResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { + resp.Schema = schema.Schema{ + MarkdownDescription: ` + This resource provides SCIM 2.0 Group Mapping. It allows the mapping of SCIM 2.0 groups to Mondoo organization or spaces and IAM roles. + `, + Attributes: map[string]schema.Attribute{ + "org_id": schema.StringAttribute{ + MarkdownDescription: "Mondoo Organization Identifier.", + Required: true, + }, + "group": schema.StringAttribute{ + MarkdownDescription: "SCIM 2.0 Group Display Name.", + Required: true, + }, + // https://developer.hashicorp.com/terraform/plugin/framework/handling-data/attributes/list-nested + "mappings": schema.ListNestedAttribute{ + NestedObject: schema.NestedAttributeObject{ + Attributes: map[string]schema.Attribute{ + "iam_role": schema.StringAttribute{ + Required: true, + }, + "space_mrn": schema.StringAttribute{ + Optional: true, + }, + "org_mrn": schema.StringAttribute{ + Optional: true, + }, + }, + }, + Required: true, + }, + }, + } +} + +func (r *scimGroupMappingResource) 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 *scimGroupMappingResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { + var data scimGroupMappingResourceModel + + // Read Terraform plan data into the model + resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...) + + if resp.Diagnostics.HasError() { + return + } + + // Do GraphQL request to API to create the resource + mappings := []mondoov1.ScimGroupMapping{} + + for i := range data.Mappings { + m := data.Mappings[i] + mapping := mondoov1.ScimGroupMapping{ + IamRole: mondoov1.String(m.IamRole.ValueString()), + } + + if !m.SpaceMrn.IsNull() { + mapping.SpaceMrn = mondoov1.NewStringPtr(mondoov1.String(m.SpaceMrn.ValueString())) + } + + if !m.OrgMrn.IsNull() { + mapping.OrgMrn = mondoov1.NewStringPtr(mondoov1.String(m.OrgMrn.ValueString())) + } + + mappings = append(mappings, mapping) + } + + err := r.client.SetScimGroupMapping(ctx, orgPrefix+data.OrgID.ValueString(), data.Group.ValueString(), mappings) + if err != nil { + resp.Diagnostics.AddError( + "Error creating SCIM group mapping", + fmt.Sprintf("Error creating SCIM group mapping: %s", err), + ) + return + } + + // Save data into Terraform state + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) +} + +func (r *scimGroupMappingResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { + var data scimGroupMappingResourceModel + + // 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 *scimGroupMappingResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { + var data scimGroupMappingResourceModel + + // Read Terraform plan data into the model + resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...) + + if resp.Diagnostics.HasError() { + return + } + + // Do GraphQL request to API to create the resource + mappings := []mondoov1.ScimGroupMapping{} + + for i := range data.Mappings { + m := data.Mappings[i] + mapping := mondoov1.ScimGroupMapping{ + IamRole: mondoov1.String(m.IamRole.ValueString()), + } + + if !m.SpaceMrn.IsNull() { + mapping.SpaceMrn = mondoov1.NewStringPtr(mondoov1.String(m.SpaceMrn.ValueString())) + } + + if !m.OrgMrn.IsNull() { + mapping.OrgMrn = mondoov1.NewStringPtr(mondoov1.String(m.OrgMrn.ValueString())) + } + + mappings = append(mappings, mapping) + } + + err := r.client.SetScimGroupMapping(ctx, orgPrefix+data.OrgID.ValueString(), data.Group.ValueString(), mappings) + if err != nil { + resp.Diagnostics.AddError( + "Error creating SCIM group mapping", + fmt.Sprintf("Error creating SCIM group mapping: %s", err), + ) + return + } + + // Save updated data into Terraform state + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) +} + +func (r *scimGroupMappingResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { + var data scimGroupMappingResourceModel + + // Read Terraform prior state data into the model + resp.Diagnostics.Append(req.State.Get(ctx, &data)...) + + if resp.Diagnostics.HasError() { + return + } + + // Do GraphQL request to API to create the resource + + // we intentionally set an empty mapping to remove the mapping + mappings := []mondoov1.ScimGroupMapping{} + err := r.client.SetScimGroupMapping(ctx, orgPrefix+data.OrgID.ValueString(), data.Group.ValueString(), mappings) + if err != nil { + resp.Diagnostics.AddError( + "Error creating SCIM group mapping", + fmt.Sprintf("Error creating SCIM group mapping: %s", err), + ) + return + } + +}