diff --git a/docs/resources/integration_aws_serverless.md b/docs/resources/integration_aws_serverless.md new file mode 100644 index 0000000..05a2ec9 --- /dev/null +++ b/docs/resources/integration_aws_serverless.md @@ -0,0 +1,167 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "mondoo_integration_aws_serverless Resource - terraform-provider-mondoo" +subcategory: "" +description: |- + Continuously scan AWS organization and accounts for misconfigurations and vulnerabilities. +--- + +# mondoo_integration_aws_serverless (Resource) + +Continuously scan AWS organization and accounts for misconfigurations and vulnerabilities. + +## Example Usage + +```terraform +variable "mondoo_org" { + description = "Mondoo Organization" + type = string +} + +variable "origin_aws_account" { + description = "Origin AWS Account" + type = string + default = "764453172858" +} + +variable "aws_region" { + description = "AWS Region" + type = string + default = "us-east-1" +} + +variable "aws_account_id" { + description = "value of the AWS account ID" + type = string +} + +provider "mondoo" { + region = "us" +} + +provider "aws" { + region = var.aws_region +} + +data "aws_region" "current" {} + +# Create a new space +resource "mondoo_space" "my_space" { + name = "AWS Terraform" + org_id = var.mondoo_org +} + +# Setup the AWS integration +resource "mondoo_integration_aws_serverless" "aws_serverless" { + space_id = mondoo_space.my_space.id + name = "AWS Integration" + region = data.aws_region.current.name + is_organization = false + console_sign_in_trigger = true + instance_state_change_trigger = true + account_ids = [var.aws_account_id] + scan_configuration = { + ec2_scan = true + ecr_scan = false + ecs_scan = false + cron_scan_in_hours = 24 + ec2_scan_options = { + ssm = true + ebs_volume_scan = true + ebs_scan_options = { + target_instances_per_scanner = 5 + max_asg_instances = 10 + } + instance_connect = false + } + } +} + +# for single account deploys +resource "aws_cloudformation_stack" "mondoo_stack" { + name = "mondoo-stack" + template_url = "https://s3.amazonaws.com/mondoo.${data.aws_region.current.name}/mondoo-lambda-stackset-cf.json" + capabilities = ["CAPABILITY_NAMED_IAM"] + parameters = { + MondooIntegrationMrn = mondoo_integration_aws_serverless.aws_serverless.mrn + MondooToken = mondoo_integration_aws_serverless.aws_serverless.token + OriginAwsAccount = var.origin_aws_account + } +} + +# for organisation wide deploys use aws_cloudformation_stack_set and aws_cloudformation_stack_set_instance instead of aws_cloudformation_stack +# https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudformation_stack_set +# https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudformation_stack_set_instance +``` + + +## Schema + +### Required + +- `name` (String) Name of the integration. +- `region` (String) AWS region. +- `scan_configuration` (Attributes) (see [below for nested schema](#nestedatt--scan_configuration)) +- `space_id` (String) Mondoo Space Identifier. + +### Optional + +- `account_ids` (List of String) List of AWS account IDs. +- `console_sign_in_trigger` (Boolean) Enable console sign in trigger. +- `instance_state_change_trigger` (Boolean) Enable instance state change trigger. +- `is_organization` (Boolean) Is organization. + +### Read-Only + +- `mrn` (String) Integration identifier +- `token` (String) Integration token + + +### Nested Schema for `scan_configuration` + +Required: + +- `ec2_scan_options` (Attributes) (see [below for nested schema](#nestedatt--scan_configuration--ec2_scan_options)) + +Optional: + +- `cron_scan_in_hours` (Number) Cron scan in hours. +- `ec2_scan` (Boolean) Enable EC2 scan. +- `ecr_scan` (Boolean) Enable ECR scan. +- `ecs_scan` (Boolean) Enable ECS scan. +- `event_scan_triggers` (Attributes) (see [below for nested schema](#nestedatt--scan_configuration--event_scan_triggers)) + + +### Nested Schema for `scan_configuration.ec2_scan_options` + +Required: + +- `ebs_scan_options` (Attributes) (see [below for nested schema](#nestedatt--scan_configuration--ec2_scan_options--ebs_scan_options)) + +Optional: + +- `ebs_volume_scan` (Boolean) Enable EBS volume scan. +- `instance_connect` (Boolean) Enable instance connect. +- `instance_ids_filter` (List of String) List of instance IDs filter. +- `regions_filter` (List of String) List of regions filter. +- `ssm` (Boolean) Enable SSM. +- `tags_filter` (Map of String) Tags filter. + + +### Nested Schema for `scan_configuration.ec2_scan_options.ebs_scan_options` + +Optional: + +- `max_asg_instances` (Number) Max ASG instances. +- `target_instances_per_scanner` (Number) Target instances per scanner. + + + + +### Nested Schema for `scan_configuration.event_scan_triggers` + +Optional: + +- `event_detail_type` (String) Event detail type. +- `event_source` (String) Event source. +- `scan_type` (String) Scan type. diff --git a/examples/resources/mondoo_integration_aws_serverless/main.tf b/examples/resources/mondoo_integration_aws_serverless/main.tf new file mode 100644 index 0000000..dd86232 --- /dev/null +++ b/examples/resources/mondoo_integration_aws_serverless/main.tf @@ -0,0 +1,12 @@ +terraform { + required_providers { + mondoo = { + source = "mondoohq/mondoo" + version = ">= 0.4.0" + } + aws = { + source = "hashicorp/aws" + version = "5.50.0" + } + } +} \ No newline at end of file diff --git a/examples/resources/mondoo_integration_aws_serverless/resource.tf b/examples/resources/mondoo_integration_aws_serverless/resource.tf new file mode 100644 index 0000000..3e475ae --- /dev/null +++ b/examples/resources/mondoo_integration_aws_serverless/resource.tf @@ -0,0 +1,79 @@ +variable "mondoo_org" { + description = "Mondoo Organization" + type = string +} + +variable "origin_aws_account" { + description = "Origin AWS Account" + type = string + default = "764453172858" +} + +variable "aws_region" { + description = "AWS Region" + type = string + default = "us-east-1" +} + +variable "aws_account_id" { + description = "value of the AWS account ID" + type = string +} + +provider "mondoo" { + region = "us" +} + +provider "aws" { + region = var.aws_region +} + +data "aws_region" "current" {} + +# Create a new space +resource "mondoo_space" "my_space" { + name = "AWS Terraform" + org_id = var.mondoo_org +} + +# Setup the AWS integration +resource "mondoo_integration_aws_serverless" "aws_serverless" { + space_id = mondoo_space.my_space.id + name = "AWS Integration" + region = data.aws_region.current.name + is_organization = false + console_sign_in_trigger = true + instance_state_change_trigger = true + account_ids = [var.aws_account_id] + scan_configuration = { + ec2_scan = true + ecr_scan = false + ecs_scan = false + cron_scan_in_hours = 24 + ec2_scan_options = { + ssm = true + ebs_volume_scan = true + ebs_scan_options = { + target_instances_per_scanner = 5 + max_asg_instances = 10 + } + instance_connect = false + } + } +} + +# for single account deploys +resource "aws_cloudformation_stack" "mondoo_stack" { + name = "mondoo-stack" + template_url = "https://s3.amazonaws.com/mondoo.${data.aws_region.current.name}/mondoo-lambda-stackset-cf.json" + capabilities = ["CAPABILITY_NAMED_IAM"] + parameters = { + MondooIntegrationMrn = mondoo_integration_aws_serverless.aws_serverless.mrn + MondooToken = mondoo_integration_aws_serverless.aws_serverless.token + OriginAwsAccount = var.origin_aws_account + } +} + +# for organisation wide deploys use aws_cloudformation_stack_set and aws_cloudformation_stack_set_instance instead of aws_cloudformation_stack +# https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudformation_stack_set +# https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudformation_stack_set_instance diff --git a/internal/provider/gql.go b/internal/provider/gql.go index a189250..14e5a63 100644 --- a/internal/provider/gql.go +++ b/internal/provider/gql.go @@ -418,8 +418,9 @@ func (c *ExtendedGqlClient) DeletePolicy(ctx context.Context, policyMrn string) } type CreateClientIntegrationPayload struct { - Mrn mondoov1.String - Name mondoov1.String + Mrn mondoov1.String + Name mondoov1.String + Token mondoov1.String } func (c *ExtendedGqlClient) CreateIntegration(ctx context.Context, spaceMrn, name string, typ mondoov1.ClientIntegrationType, opts mondoov1.ClientIntegrationConfigurationInput) (*CreateClientIntegrationPayload, error) { @@ -448,6 +449,45 @@ func (c *ExtendedGqlClient) CreateIntegration(ctx context.Context, spaceMrn, nam return &createMutation.CreateClientIntegration.Integration, nil } +type GetClientIntegrationTokenInput struct { + mrn mondoov1.String + longLivedToken mondoov1.Boolean +} + +type ClientIntegrationToken struct { + Token mondoov1.String +} + +func (c *ExtendedGqlClient) GetClientIntegrationToken(ctx context.Context, mrn string, longLivedToken bool) (*ClientIntegrationToken, error) { + // Define the response structure + var query struct { + ClientIntegrationToken ClientIntegrationToken `graphql:"getClientIntegrationToken(input: $input)"` + } + + // Define the input variables + input := GetClientIntegrationTokenInput{ + mrn: mondoov1.String(mrn), + longLivedToken: mondoov1.Boolean(longLivedToken), + } + variables := map[string]interface{}{ + "input": input, + } + + // Trace the input variables for debugging + tflog.Trace(ctx, "GetClientIntegrationTokenInput", map[string]interface{}{ + "input": fmt.Sprintf("%+v", input), + }) + + // Perform the GraphQL query + err := c.Query(ctx, &query, variables) + if err != nil { + return nil, err + } + + // Return the token from the response + return &query.ClientIntegrationToken, nil +} + type UpdateIntegrationPayload struct { Name mondoov1.String } diff --git a/internal/provider/integration_aws_serverless_resource.go b/internal/provider/integration_aws_serverless_resource.go new file mode 100644 index 0000000..8b303e2 --- /dev/null +++ b/internal/provider/integration_aws_serverless_resource.go @@ -0,0 +1,442 @@ +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/resource/schema/planmodifier" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" + "github.com/hashicorp/terraform-plugin-framework/types" + mondoov1 "go.mondoo.com/mondoo-go" +) + +var _ resource.Resource = (*integrationAwsServerlessResource)(nil) + +func NewIntegrationAwsServerlessResource() resource.Resource { + return &integrationAwsServerlessResource{} +} + +type integrationAwsServerlessResource struct { + client *ExtendedGqlClient +} + +type integrationAwsServerlessResourceModel struct { + // scope + SpaceId types.String `tfsdk:"space_id"` + + // integration details + Mrn types.String `tfsdk:"mrn"` + Name types.String `tfsdk:"name"` + Token types.String `tfsdk:"token"` + + Region types.String `tfsdk:"region"` + ScanConfiguration ScanConfigurationInput `tfsdk:"scan_configuration"` + + // (Optional.) + AccountIDs types.List `tfsdk:"account_ids"` + // (Optional.) + IsOrganization types.Bool `tfsdk:"is_organization"` + + // (Optional.) + ConsoleSignInTrigger types.Bool `tfsdk:"console_sign_in_trigger"` + // (Optional.) + InstanceStateChangeTrigger types.Bool `tfsdk:"instance_state_change_trigger"` +} + +type ScanConfigurationInput struct { + // (Optional.) + Ec2Scan types.Bool `tfsdk:"ec2_scan"` + // (Optional.) + EcrScan types.Bool `tfsdk:"ecr_scan"` + // (Optional.) + EcsScan types.Bool `tfsdk:"ecs_scan"` + // (Optional.) + CronScaninHours types.Int64 `tfsdk:"cron_scan_in_hours"` + // (Optional.) + EventScanTriggers *[]*AWSEventPatternInput `tfsdk:"event_scan_triggers"` + // (Optional.) + Ec2ScanOptions *Ec2ScanOptionsInput `tfsdk:"ec2_scan_options"` +} + +type AWSEventPatternInput struct { + // (Required.) + ScanType types.String `tfsdk:"scan_type"` + // (Required.) + EventSource types.String `tfsdk:"event_source"` + // (Required.) + EventDetailType types.String `tfsdk:"event_detail_type"` +} + +type Ec2ScanOptionsInput struct { + // (Optional.) + Ssm types.Bool `tfsdk:"ssm"` + // (Optional.) + InstanceIDsFilter types.List `tfsdk:"instance_ids_filter"` + // (Optional.) + RegionsFilter types.List `tfsdk:"regions_filter"` + // (Optional.) + TagsFilter types.Map `tfsdk:"tags_filter"` + // (Optional.) + EbsVolumeScan types.Bool `tfsdk:"ebs_volume_scan"` + // (Optional.) + EbsScanOptions *EbsScanOptionsInput `tfsdk:"ebs_scan_options"` + // (Optional.) + InstanceConnect types.Bool `tfsdk:"instance_connect"` +} + +type EbsScanOptionsInput struct { + // (Optional.) + TargetInstancesPerScanner types.Int64 `tfsdk:"target_instances_per_scanner"` + // (Optional.) + MaxAsgInstances types.Int64 `tfsdk:"max_asg_instances"` +} + +func (m integrationAwsServerlessResourceModel) GetConfigurationOptions() *mondoov1.AWSConfigurationOptionsInput { + var opts *mondoov1.AWSConfigurationOptionsInput + var eventScanTriggers []*mondoov1.AWSEventPatternInput + + if m.InstanceStateChangeTrigger.ValueBool() && m.ConsoleSignInTrigger.ValueBool() { + eventScanTriggers = append(eventScanTriggers, &mondoov1.AWSEventPatternInput{ + ScanType: mondoov1.String("ALL"), + EventSource: mondoov1.String("aws.signin"), + EventDetailType: mondoov1.String("AWS Console Sign In via CloudTrail"), + }) + eventScanTriggers = append(eventScanTriggers, &mondoov1.AWSEventPatternInput{ + ScanType: mondoov1.String("ALL"), + EventSource: mondoov1.String("aws.ec2"), + EventDetailType: mondoov1.String("EC2 Instance State-change Notification"), + }) + } else if m.ConsoleSignInTrigger.ValueBool() && !m.InstanceStateChangeTrigger.ValueBool() { + eventScanTriggers = append(eventScanTriggers, &mondoov1.AWSEventPatternInput{ + ScanType: mondoov1.String("ALL"), + EventSource: mondoov1.String("aws.signin"), + EventDetailType: mondoov1.String("AWS Console Sign In via CloudTrail"), + }) + } else if m.InstanceStateChangeTrigger.ValueBool() && !m.ConsoleSignInTrigger.ValueBool() { + eventScanTriggers = append(eventScanTriggers, &mondoov1.AWSEventPatternInput{ + ScanType: mondoov1.String("ALL"), + EventSource: mondoov1.String("aws.ec2"), + EventDetailType: mondoov1.String("EC2 Instance State-change Notification"), + }) + } + + var instanceIdsFilter []mondoov1.String + instanceIds, _ := m.ScanConfiguration.Ec2ScanOptions.InstanceIDsFilter.ToListValue(context.Background()) + instanceIds.ElementsAs(context.Background(), &instanceIdsFilter, true) + + var RegionsFilter []mondoov1.String + regions, _ := m.ScanConfiguration.Ec2ScanOptions.RegionsFilter.ToListValue(context.Background()) + regions.ElementsAs(context.Background(), &RegionsFilter, true) + + var tagsFilter mondoov1.Map + tags, _ := m.ScanConfiguration.Ec2ScanOptions.TagsFilter.ToMapValue(context.Background()) + tags.ElementsAs(context.Background(), &tagsFilter, true) + + var accountIDs []mondoov1.String + accountIds, _ := m.AccountIDs.ToListValue(context.Background()) + accountIds.ElementsAs(context.Background(), &accountIDs, true) + + opts = &mondoov1.AWSConfigurationOptionsInput{ + Region: mondoov1.String(m.Region.ValueString()), + IsOrganization: mondoov1.NewBooleanPtr(mondoov1.Boolean(m.IsOrganization.ValueBool())), + AccountIDs: &accountIDs, + ScanConfiguration: mondoov1.ScanConfigurationInput{ + Ec2Scan: mondoov1.NewBooleanPtr(mondoov1.Boolean(m.ScanConfiguration.Ec2Scan.ValueBool())), + EcrScan: mondoov1.NewBooleanPtr(mondoov1.Boolean(m.ScanConfiguration.EcrScan.ValueBool())), + EcsScan: mondoov1.NewBooleanPtr(mondoov1.Boolean(m.ScanConfiguration.EcsScan.ValueBool())), + CronScaninHours: mondoov1.NewIntPtr(mondoov1.Int(m.ScanConfiguration.CronScaninHours.ValueInt64())), + EventScanTriggers: &eventScanTriggers, + Ec2ScanOptions: &mondoov1.Ec2ScanOptionsInput{ + Ssm: mondoov1.NewBooleanPtr(mondoov1.Boolean(m.ScanConfiguration.Ec2ScanOptions.Ssm.ValueBool())), + InstanceIDsFilter: &instanceIdsFilter, + RegionsFilter: &RegionsFilter, + TagsFilter: &tagsFilter, + EbsVolumeScan: mondoov1.NewBooleanPtr(mondoov1.Boolean(m.ScanConfiguration.Ec2ScanOptions.EbsVolumeScan.ValueBool())), + EbsScanOptions: &mondoov1.EbsScanOptionsInput{ + TargetInstancesPerScanner: mondoov1.NewIntPtr(mondoov1.Int(m.ScanConfiguration.Ec2ScanOptions.EbsScanOptions.TargetInstancesPerScanner.ValueInt64())), + MaxAsgInstances: mondoov1.NewIntPtr(mondoov1.Int(m.ScanConfiguration.Ec2ScanOptions.EbsScanOptions.MaxAsgInstances.ValueInt64())), + }, + InstanceConnect: mondoov1.NewBooleanPtr(mondoov1.Boolean(m.ScanConfiguration.Ec2ScanOptions.InstanceConnect.ValueBool())), + }, + }, + } + + return opts +} + +func (r *integrationAwsServerlessResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_integration_aws_serverless" +} + +func (r *integrationAwsServerlessResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { + resp.Schema = schema.Schema{ + MarkdownDescription: `Continuously scan AWS organization and accounts for misconfigurations and vulnerabilities.`, + Attributes: map[string]schema.Attribute{ + "space_id": schema.StringAttribute{ + MarkdownDescription: "Mondoo Space Identifier.", + Required: true, + }, + "mrn": schema.StringAttribute{ + Computed: true, + MarkdownDescription: "Integration identifier", + PlanModifiers: []planmodifier.String{ + stringplanmodifier.UseStateForUnknown(), + }, + }, + "token": schema.StringAttribute{ + Computed: true, + MarkdownDescription: "Integration token", + PlanModifiers: []planmodifier.String{ + stringplanmodifier.UseStateForUnknown(), + }, + }, + "name": schema.StringAttribute{ + MarkdownDescription: "Name of the integration.", + Required: true, + }, + "region": schema.StringAttribute{ + MarkdownDescription: "AWS region.", + Required: true, + }, + "console_sign_in_trigger": schema.BoolAttribute{ + MarkdownDescription: "Enable console sign in trigger.", + Optional: true, + }, + "instance_state_change_trigger": schema.BoolAttribute{ + MarkdownDescription: "Enable instance state change trigger.", + Optional: true, + }, + "scan_configuration": schema.SingleNestedAttribute{ + Required: true, + Attributes: map[string]schema.Attribute{ + "ec2_scan": schema.BoolAttribute{ + MarkdownDescription: "Enable EC2 scan.", + Optional: true, + }, + "ecr_scan": schema.BoolAttribute{ + MarkdownDescription: "Enable ECR scan.", + Optional: true, + }, + "ecs_scan": schema.BoolAttribute{ + MarkdownDescription: "Enable ECS scan.", + Optional: true, + }, + "cron_scan_in_hours": schema.Int64Attribute{ + MarkdownDescription: "Cron scan in hours.", + Optional: true, + }, + "ec2_scan_options": schema.SingleNestedAttribute{ + Required: true, + Attributes: map[string]schema.Attribute{ + "ssm": schema.BoolAttribute{ + MarkdownDescription: "Enable SSM.", + Optional: true, + }, + "instance_ids_filter": schema.ListAttribute{ + MarkdownDescription: "List of instance IDs filter.", + Optional: true, + ElementType: types.StringType, + }, + "regions_filter": schema.ListAttribute{ + MarkdownDescription: "List of regions filter.", + Optional: true, + ElementType: types.StringType, + }, + "tags_filter": schema.MapAttribute{ + MarkdownDescription: "Tags filter.", + Optional: true, + ElementType: types.StringType, + }, + "ebs_volume_scan": schema.BoolAttribute{ + MarkdownDescription: "Enable EBS volume scan.", + Optional: true, + }, + "ebs_scan_options": schema.SingleNestedAttribute{ + Required: true, + Attributes: map[string]schema.Attribute{ + "target_instances_per_scanner": schema.Int64Attribute{ + MarkdownDescription: "Target instances per scanner.", + Optional: true, + }, + "max_asg_instances": schema.Int64Attribute{ + MarkdownDescription: "Max ASG instances.", + Optional: true, + }, + }, + }, + "instance_connect": schema.BoolAttribute{ + MarkdownDescription: "Enable instance connect.", + Optional: true, + }, + }, + }, + "event_scan_triggers": schema.SingleNestedAttribute{ + Optional: true, + Attributes: map[string]schema.Attribute{ + "scan_type": schema.StringAttribute{ + MarkdownDescription: "Scan type.", + Optional: true, + }, + "event_source": schema.StringAttribute{ + MarkdownDescription: "Event source.", + Optional: true, + }, + "event_detail_type": schema.StringAttribute{ + MarkdownDescription: "Event detail type.", + Optional: true, + }, + }, + }, + }, + }, + "account_ids": schema.ListAttribute{ + MarkdownDescription: "List of AWS account IDs.", + Optional: true, + ElementType: types.StringType, + }, + "is_organization": schema.BoolAttribute{ + MarkdownDescription: "Is organization.", + Optional: true, + }, + }, + } +} + +func (r *integrationAwsServerlessResource) 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 *integrationAwsServerlessResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { + var data integrationAwsServerlessResourceModel + + // 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. + spaceMrn := "" + if data.SpaceId.ValueString() != "" { + spaceMrn = spacePrefix + data.SpaceId.ValueString() + } + + var accountIDs []mondoov1.String + accountIds, _ := data.AccountIDs.ToListValue(context.Background()) + accountIds.ElementsAs(context.Background(), &accountIDs, true) + + // Check if both whitelist and blacklist are provided + if len(accountIDs) > 0 && data.IsOrganization.ValueBool() { + resp.Diagnostics.AddError("ConflictingAttributesError", "Cannot install CloudFormation Stack to both AWS organization and accounts.") + return + } + + integration, err := r.client.CreateIntegration(ctx, + spaceMrn, + data.Name.ValueString(), + mondoov1.ClientIntegrationTypeAws, + mondoov1.ClientIntegrationConfigurationInput{ + AwsConfigurationOptions: data.GetConfigurationOptions(), + }) + if err != nil { + resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to create AWS integration, got error: %s", err)) + return + } + + // Save space mrn into the Terraform state. + data.Mrn = types.StringValue(string(integration.Mrn)) + data.Name = types.StringValue(string(integration.Name)) + data.SpaceId = types.StringValue(data.SpaceId.ValueString()) + data.Token = types.StringValue(string(integration.Token)) + + // Save data into Terraform state + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) +} + +func (r *integrationAwsServerlessResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { + var data integrationAwsServerlessResourceModel + + // 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 *integrationAwsServerlessResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { + var data integrationAwsServerlessResourceModel + + // Read Terraform plan data into the model + resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...) + + var accountIDs []mondoov1.String + accountIds, _ := data.AccountIDs.ToListValue(context.Background()) + accountIds.ElementsAs(context.Background(), &accountIDs, true) + + // Check if both whitelist and blacklist are provided + if len(accountIDs) > 0 && data.IsOrganization.ValueBool() { + resp.Diagnostics.AddError("ConflictingAttributesError", "Cannot install CloudFormation Stack to both AWS organization and accounts.") + return + } + + if resp.Diagnostics.HasError() { + return + } + + // Do GraphQL request to API to update the resource. + opts := mondoov1.ClientIntegrationConfigurationInput{ + AwsConfigurationOptions: data.GetConfigurationOptions(), + } + + _, err := r.client.UpdateIntegration(ctx, data.Mrn.ValueString(), data.Name.ValueString(), mondoov1.ClientIntegrationTypeAws, opts) + if err != nil { + resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to update AWS integration, got error: %s", err)) + return + } + + // Save updated data into Terraform state + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) +} + +func (r *integrationAwsServerlessResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { + var data integrationAwsServerlessResourceModel + + // Read Terraform prior state data into the model + resp.Diagnostics.Append(req.State.Get(ctx, &data)...) + + if resp.Diagnostics.HasError() { + return + } + + // Delete API call logic +} + +func (r *integrationAwsServerlessResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { + resource.ImportStatePassthroughID(ctx, path.Root("mrn"), req, resp) +} diff --git a/internal/provider/provider.go b/internal/provider/provider.go index d0e4143..91440f1 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -164,6 +164,7 @@ func (p *MondooProvider) Resources(ctx context.Context) []func() resource.Resour NewScimGroupMappingResource, NewIntegrationAzureResource, NewIntegrationAwsResource, + NewIntegrationAwsServerlessResource, NewIntegrationDomainResource, NewIntegrationGcpResource, NewIntegrationOciTenantResource,