From 9e61f4bd3ab6eac789d7e36053e08b1f68e167d6 Mon Sep 17 00:00:00 2001 From: Paul Date: Thu, 27 Jun 2024 14:54:13 +0200 Subject: [PATCH 01/10] feat: added import feature for some resources Signed-off-by: Paul --- .../mondoo_integration_aws/resource.tf | 3 +- internal/provider/gql.go | 121 ++++++++++++++++++ internal/provider/integration_aws_resource.go | 31 ++++- .../provider/integration_azure_resource.go | 22 ++++ .../provider/integration_domain_resource.go | 22 +++- 5 files changed, 195 insertions(+), 4 deletions(-) diff --git a/examples/resources/mondoo_integration_aws/resource.tf b/examples/resources/mondoo_integration_aws/resource.tf index b0509ba..a901c2c 100644 --- a/examples/resources/mondoo_integration_aws/resource.tf +++ b/examples/resources/mondoo_integration_aws/resource.tf @@ -9,7 +9,7 @@ variable "aws_access_key" { } variable "aws_secret_key" { - description = "AWS access key" + description = "AWS secret key" type = string } @@ -33,4 +33,3 @@ resource "mondoo_integration_aws" "name" { } } } - diff --git a/internal/provider/gql.go b/internal/provider/gql.go index 4e092d0..9f8a723 100644 --- a/internal/provider/gql.go +++ b/internal/provider/gql.go @@ -320,6 +320,127 @@ func (c *ExtendedGqlClient) DeleteIntegration(ctx context.Context, mrn string) ( return &deleteMutation.DeleteClientIntegration, nil } +// type AWSConfigurationOptions struct { +// AccountIds []string +// Region string +// IsOrganization bool +// ScanConfiguration ScanConfiguration +// SnsEndpoint string +// OriginAWSAccountId string `graphql:"originAWSAccountId"` +// CloudFormationTemplateUrl string +// } + +// type ScanConfiguration struct { +// AccountScan bool +// Ec2Scan bool `graphql:"ec2Scan"` +// EcrScan bool `graphql:"ecrScan"` +// EcsScan bool `graphql:"ecsScan"` +// CronScaninHours int +// EventScanTriggers []AWSEventPattern +// Ec2ScanOptions Ec2ScanOptions `graphql:"ec2ScanOptions"` +// } + +// type AWSEventPattern struct { +// ScanType string +// EventSource string +// EventDetailType string +// } + +// type Ec2ScanOptions struct { +// Ssm bool +// AwsSecretsManagerVault bool +// SecretsMetadataQuery string +// InstanceIdsFilter []string +// RegionsFilter []string +// TagsFilter map[string]string +// VaultType string +// EbsVolumeScan bool +// EbsScanOptions EbsScanOptions +// InstanceConnect bool +// } + +// type EbsScanOptions struct { +// TargetInstancesPerScanner int +// MaxAsgInstances int +// } + +type AzureConfigurationOptions struct { + TenantId string + ClientId string + SubscriptionsWhitelist []string + SubscriptionsBlacklist []string + // Certificate string + ScanVms bool + // ClientSecret string +} + +type HostConfigurationOptions struct { + Host string `graphql:"host"` + HTTPS bool `graphql:"https"` + HTTP bool `graphql:"http"` +} + +// type SlackConfigurationOptions struct { +// SlackToken string `graphql:"slackToken"` +// } + +type GithubConfigurationOptions struct { + Owner string + Repository string + Organization string + // Token string + Type string //graphql enum + ReposAllowList []string + ReposDenyList []string +} + +type Ms365ConfigurationOptions struct { + TenantId string + ClientId string +} + +type HostedAwsConfigurationOptions struct { + AccessKeyId string + Role string +} + +type ClientIntegrationConfigurationOptions struct { + // AWSConfigurationOptions AWSConfigurationOptions `graphql:"... on AWSConfigurationOptions"` + AzureConfigurationOptions AzureConfigurationOptions `graphql:"... on AzureConfigurationOptions"` + HostConfigurationOptions HostConfigurationOptions `graphql:"... on HostConfigurationOptions"` + Ms365ConfigurationOptions Ms365ConfigurationOptions `graphql:"... on Ms365ConfigurationOptions"` + // SlackConfigurationOptions SlackConfigurationOptions `graphql:"... on SlackConfigurationOptions"` + GithubConfigurationOptions GithubConfigurationOptions `graphql:"... on GithubConfigurationOptions"` + HostedAwsConfigurationOptions HostedAwsConfigurationOptions `graphql:"... on HostedAwsConfigurationOptions"` + // Add other configuration options here +} + +type Integration struct { + Mrn string + Name string + ConfigurationOptions ClientIntegrationConfigurationOptions `graphql:"configurationOptions"` +} + +type ClientIntegration struct { + Integration Integration +} + +func (c *ExtendedGqlClient) GetClientIntegration(ctx context.Context, mrn string) (Integration, error) { + var q struct { + ClientIntegration ClientIntegration `graphql:"clientIntegration(input: {mrn: $mrn})"` + } + variables := map[string]interface{}{ + "mrn": mondoov1.String(mrn), + } + + err := c.Query(ctx, &q, variables) + if err != nil { + return Integration{}, err + } + + return q.ClientIntegration.Integration, nil +} + type triggerActionPayload struct { Mrn string } diff --git a/internal/provider/integration_aws_resource.go b/internal/provider/integration_aws_resource.go index 2cadd9d..0fec886 100644 --- a/internal/provider/integration_aws_resource.go +++ b/internal/provider/integration_aws_resource.go @@ -6,6 +6,8 @@ package provider import ( "context" "fmt" + "strings" + "github.com/hashicorp/terraform-plugin-framework-validators/objectvalidator" "github.com/hashicorp/terraform-plugin-framework/path" "github.com/hashicorp/terraform-plugin-framework/resource" @@ -14,6 +16,7 @@ import ( "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" "github.com/hashicorp/terraform-plugin-framework/schema/validator" "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-plugin-framework/types/basetypes" mondoov1 "go.mondoo.com/mondoo-go" ) @@ -261,5 +264,31 @@ func (r *integrationAwsResource) Delete(ctx context.Context, req resource.Delete } func (r *integrationAwsResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { - resource.ImportStatePassthroughID(ctx, path.Root("mrn"), req, resp) + mrn := req.ID + integration, err := r.client.GetClientIntegration(ctx, mrn) + if err != nil { + resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to import AWS integration, got error: %s", err)) + return + } + + model := integrationAwsResourceModel{ + SpaceId: types.StringValue(strings.Split(integration.Mrn, "/")[len(strings.Split(integration.Mrn, "/"))-3]), + Mrn: types.StringValue(string(integration.Mrn)), + Name: types.StringValue(string(integration.Name)), + Credential: integrationAwsCredentialModel{ + Role: &roleCredentialModel{ + RoleArn: types.StringValue(string(integration.ConfigurationOptions.HostedAwsConfigurationOptions.Role)), + ExternalId: basetypes.NewStringNull(), // cannot be imported + }, + Key: &accessKeyCredentialModel{ + AccessKey: types.StringValue(string(integration.ConfigurationOptions.HostedAwsConfigurationOptions.AccessKeyId)), + SecretKey: basetypes.NewStringNull(), // cannot be imported + }, + }, + } + + resp.State.SetAttribute(ctx, path.Root("space_id"), model.SpaceId) + resp.State.SetAttribute(ctx, path.Root("mrn"), model.Mrn) + resp.State.SetAttribute(ctx, path.Root("name"), model.Name) + resp.State.SetAttribute(ctx, path.Root("credentials"), model.Credential) } diff --git a/internal/provider/integration_azure_resource.go b/internal/provider/integration_azure_resource.go index 9673149..4d1c431 100644 --- a/internal/provider/integration_azure_resource.go +++ b/internal/provider/integration_azure_resource.go @@ -272,4 +272,26 @@ func (r *integrationAzureResource) Delete(ctx context.Context, req resource.Dele func (r *integrationAzureResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { resource.ImportStatePassthroughID(ctx, path.Root("mrn"), req, resp) + + // mrn := req.ID + // integration, err := r.client.GetClientIntegration(ctx, mrn) + // if err != nil { + // resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to import Azure integration, got error: %s", err)) + // return + // } + + // model := integrationAzureResourceModel{ + // SpaceId: types.StringValue(strings.Split(integration.Mrn, "/")[len(strings.Split(integration.Mrn, "/"))-3]), + // Mrn: types.StringValue(string(integration.Mrn)), + // Name: types.StringValue(string(integration.Name)), + // ClientId: types.StringValue(integration.ConfigurationOptions.AzureConfigurationOptions.ClientId), + // TenantId: types.StringValue(integration.ConfigurationOptions.AzureConfigurationOptions.TenantId), + // SubscriptionAllowList: types.ToListValue(ctx, integration.ConfigurationOptions.AzureConfigurationOptions.SubscriptionsWhitelist), + // } + + // resp.State.SetAttribute(ctx, path.Root("space_id"), model.SpaceId) + // resp.State.SetAttribute(ctx, path.Root("mrn"), model.Mrn) + // resp.State.SetAttribute(ctx, path.Root("name"), model.Name) + // resp.State.SetAttribute(ctx, path.Root("credentials"), model.Credential) + } diff --git a/internal/provider/integration_domain_resource.go b/internal/provider/integration_domain_resource.go index e88e03b..5672d9b 100644 --- a/internal/provider/integration_domain_resource.go +++ b/internal/provider/integration_domain_resource.go @@ -3,6 +3,7 @@ package provider import ( "context" "fmt" + "strings" "github.com/hashicorp/terraform-plugin-framework/path" "github.com/hashicorp/terraform-plugin-framework/resource" @@ -203,5 +204,24 @@ func (r *integrationDomainResource) Delete(ctx context.Context, req resource.Del } func (r *integrationDomainResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { - resource.ImportStatePassthroughID(ctx, path.Root("mrn"), req, resp) + mrn := req.ID + integration, err := r.client.GetClientIntegration(ctx, mrn) + if err != nil { + resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to retrieve integration, got error: %s", err)) + return + } + + model := integrationDomainResourceModel{ + SpaceId: types.StringValue(strings.Split(integration.Mrn, "/")[len(strings.Split(integration.Mrn, "/"))-3]), + Mrn: types.StringValue(integration.Mrn), + Host: types.StringValue(integration.ConfigurationOptions.HostConfigurationOptions.Host), + Https: types.BoolValue(integration.ConfigurationOptions.HostConfigurationOptions.HTTPS), + Http: types.BoolValue(integration.ConfigurationOptions.HostConfigurationOptions.HTTP), + } + + resp.State.SetAttribute(ctx, path.Root("space_id"), model.SpaceId) + resp.State.SetAttribute(ctx, path.Root("mrn"), model.Mrn) + resp.State.SetAttribute(ctx, path.Root("host"), model.Host) + resp.State.SetAttribute(ctx, path.Root("https"), model.Https) + resp.State.SetAttribute(ctx, path.Root("http"), model.Http) } From 002b7d64b19b49aaa3d94647750db5cf16e5b932 Mon Sep 17 00:00:00 2001 From: Paul Date: Wed, 3 Jul 2024 10:58:52 +0200 Subject: [PATCH 02/10] feat: added azure resource terraform import Signed-off-by: Paul --- go.mod | 2 +- go.sum | 4 +- .../provider/integration_azure_resource.go | 66 ++++++++++++------- 3 files changed, 47 insertions(+), 25 deletions(-) diff --git a/go.mod b/go.mod index 7643e31..eedbefc 100644 --- a/go.mod +++ b/go.mod @@ -120,7 +120,7 @@ require ( google.golang.org/appengine v1.6.8 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de // indirect google.golang.org/grpc v1.63.2 // indirect - google.golang.org/protobuf v1.34.0 // indirect + google.golang.org/protobuf v1.34.2 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 2baecb2..1508224 100644 --- a/go.sum +++ b/go.sum @@ -686,8 +686,8 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.34.0 h1:Qo/qEd2RZPCf2nKuorzksSknv0d3ERwp1vFG38gSmH4= -google.golang.org/protobuf v1.34.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/internal/provider/integration_azure_resource.go b/internal/provider/integration_azure_resource.go index 4d1c431..ecf61e7 100644 --- a/internal/provider/integration_azure_resource.go +++ b/internal/provider/integration_azure_resource.go @@ -3,13 +3,16 @@ package provider import ( "context" "fmt" + "strings" + "github.com/hashicorp/terraform-plugin-framework/attr" "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" + "github.com/hashicorp/terraform-plugin-framework/types/basetypes" mondoov1 "go.mondoo.com/mondoo-go" ) @@ -271,27 +274,46 @@ func (r *integrationAzureResource) Delete(ctx context.Context, req resource.Dele } func (r *integrationAzureResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { - resource.ImportStatePassthroughID(ctx, path.Root("mrn"), req, resp) - - // mrn := req.ID - // integration, err := r.client.GetClientIntegration(ctx, mrn) - // if err != nil { - // resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to import Azure integration, got error: %s", err)) - // return - // } - - // model := integrationAzureResourceModel{ - // SpaceId: types.StringValue(strings.Split(integration.Mrn, "/")[len(strings.Split(integration.Mrn, "/"))-3]), - // Mrn: types.StringValue(string(integration.Mrn)), - // Name: types.StringValue(string(integration.Name)), - // ClientId: types.StringValue(integration.ConfigurationOptions.AzureConfigurationOptions.ClientId), - // TenantId: types.StringValue(integration.ConfigurationOptions.AzureConfigurationOptions.TenantId), - // SubscriptionAllowList: types.ToListValue(ctx, integration.ConfigurationOptions.AzureConfigurationOptions.SubscriptionsWhitelist), - // } - - // resp.State.SetAttribute(ctx, path.Root("space_id"), model.SpaceId) - // resp.State.SetAttribute(ctx, path.Root("mrn"), model.Mrn) - // resp.State.SetAttribute(ctx, path.Root("name"), model.Name) - // resp.State.SetAttribute(ctx, path.Root("credentials"), model.Credential) + mrn := req.ID + integration, err := r.client.GetClientIntegration(ctx, mrn) + if err != nil { + resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to import Azure integration, got error: %s", err)) + return + } + allowList := r.ConvertListValue(ctx, integration.ConfigurationOptions.AzureConfigurationOptions.SubscriptionsWhitelist) + denyList := r.ConvertListValue(ctx, integration.ConfigurationOptions.AzureConfigurationOptions.SubscriptionsBlacklist) + + model := integrationAzureResourceModel{ + SpaceId: types.StringValue(strings.Split(integration.Mrn, "/")[len(strings.Split(integration.Mrn, "/"))-3]), + Mrn: types.StringValue(string(integration.Mrn)), + Name: types.StringValue(string(integration.Name)), + ClientId: types.StringValue(integration.ConfigurationOptions.AzureConfigurationOptions.ClientId), + TenantId: types.StringValue(integration.ConfigurationOptions.AzureConfigurationOptions.TenantId), + SubscriptionAllowList: allowList, + SubscriptionDenyList: denyList, + Credential: integrationAzureCredentialModel{ + PEMFile: basetypes.NewStringNull(), + }, + ScanVms: types.BoolValue(integration.ConfigurationOptions.AzureConfigurationOptions.ScanVms), + } + + resp.State.SetAttribute(ctx, path.Root("space_id"), model.SpaceId) + resp.State.SetAttribute(ctx, path.Root("mrn"), model.Mrn) + resp.State.SetAttribute(ctx, path.Root("client_id"), model.ClientId) + resp.State.SetAttribute(ctx, path.Root("tenant_id"), model.TenantId) + resp.State.SetAttribute(ctx, path.Root("name"), model.Name) + resp.State.SetAttribute(ctx, path.Root("credentials"), model.Credential) + resp.State.SetAttribute(ctx, path.Root("scan_vms"), model.ScanVms) + resp.State.SetAttribute(ctx, path.Root("subscription_allow_list"), model.SubscriptionAllowList) + resp.State.SetAttribute(ctx, path.Root("subscription_deny_list"), model.SubscriptionDenyList) +} + +func (r *integrationAzureResource) ConvertListValue(ctx context.Context, list []string) types.List { + var valueList []attr.Value + for _, str := range list { + valueList = append(valueList, types.StringValue(str)) + } + // Ensure the list is of type types.StringType + return types.ListValueMust(types.StringType, valueList) } From 15c840b8f60084f02320598078af8cf3cce5ad5e Mon Sep 17 00:00:00 2001 From: Paul Date: Thu, 4 Jul 2024 09:43:17 +0200 Subject: [PATCH 03/10] feat: added gcp/github/ms365 import Signed-off-by: Paul --- internal/provider/gql.go | 7 +++ internal/provider/integration_gcp_resource.go | 25 +++++++++- .../provider/integration_github_resource.go | 49 ++++++++++++++++++- .../provider/integration_ms365_resource.go | 28 ++++++++++- 4 files changed, 104 insertions(+), 5 deletions(-) diff --git a/internal/provider/gql.go b/internal/provider/gql.go index 9f8a723..a289485 100644 --- a/internal/provider/gql.go +++ b/internal/provider/gql.go @@ -404,11 +404,18 @@ type HostedAwsConfigurationOptions struct { Role string } +type GcpConfigurationOptions struct { + ProjectId string + // OrganizationId string + DiscoverAll bool +} + type ClientIntegrationConfigurationOptions struct { // AWSConfigurationOptions AWSConfigurationOptions `graphql:"... on AWSConfigurationOptions"` AzureConfigurationOptions AzureConfigurationOptions `graphql:"... on AzureConfigurationOptions"` HostConfigurationOptions HostConfigurationOptions `graphql:"... on HostConfigurationOptions"` Ms365ConfigurationOptions Ms365ConfigurationOptions `graphql:"... on Ms365ConfigurationOptions"` + GcpConfigurationOptions GcpConfigurationOptions `graphql:"... on GcpConfigurationOptions"` // SlackConfigurationOptions SlackConfigurationOptions `graphql:"... on SlackConfigurationOptions"` GithubConfigurationOptions GithubConfigurationOptions `graphql:"... on GithubConfigurationOptions"` HostedAwsConfigurationOptions HostedAwsConfigurationOptions `graphql:"... on HostedAwsConfigurationOptions"` diff --git a/internal/provider/integration_gcp_resource.go b/internal/provider/integration_gcp_resource.go index 13c1fe6..9954ea8 100644 --- a/internal/provider/integration_gcp_resource.go +++ b/internal/provider/integration_gcp_resource.go @@ -6,6 +6,7 @@ package provider import ( "context" "fmt" + "strings" "github.com/hashicorp/terraform-plugin-framework/path" "github.com/hashicorp/terraform-plugin-framework/resource" @@ -13,6 +14,7 @@ import ( "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" + "github.com/hashicorp/terraform-plugin-framework/types/basetypes" mondoov1 "go.mondoo.com/mondoo-go" ) @@ -216,5 +218,26 @@ func (r *integrationGcpResource) Delete(ctx context.Context, req resource.Delete } func (r *integrationGcpResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { - resource.ImportStatePassthroughID(ctx, path.Root("mrn"), req, resp) + mrn := req.ID + integration, err := r.client.GetClientIntegration(ctx, mrn) + if err != nil { + resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to get GCP integration, got error: %s", err)) + return + } + + model := integrationGcpResourceModel{ + Mrn: types.StringValue(string(integration.Mrn)), + Name: types.StringValue(string(integration.Name)), + SpaceId: types.StringValue(strings.Split(integration.Mrn, "/")[len(strings.Split(integration.Mrn, "/"))-3]), + ProjectId: types.StringValue(integration.ConfigurationOptions.GcpConfigurationOptions.ProjectId), + Credential: integrationGcpCredentialModel{ + PrivateKey: basetypes.NewStringNull(), + }, + } + + resp.State.SetAttribute(ctx, path.Root("space_id"), model.SpaceId) + resp.State.SetAttribute(ctx, path.Root("mrn"), model.Mrn) + resp.State.SetAttribute(ctx, path.Root("name"), model.Name) + resp.State.SetAttribute(ctx, path.Root("project_id"), model.ProjectId) + resp.State.SetAttribute(ctx, path.Root("credentials"), model.Credential) } diff --git a/internal/provider/integration_github_resource.go b/internal/provider/integration_github_resource.go index 71ed6f0..15c9c74 100644 --- a/internal/provider/integration_github_resource.go +++ b/internal/provider/integration_github_resource.go @@ -3,7 +3,9 @@ package provider import ( "context" "fmt" + "strings" + "github.com/hashicorp/terraform-plugin-framework/attr" "github.com/hashicorp/terraform-plugin-framework/path" "github.com/hashicorp/terraform-plugin-framework/resource" "github.com/hashicorp/terraform-plugin-framework/resource/schema" @@ -38,7 +40,7 @@ type integrationGithubResourceModel struct { RepositoryDenyList types.List `tfsdk:"repository_deny_list"` // credentials - Credential integrationGithubCredentialModel `tfsdk:"credentials"` + Credential *integrationGithubCredentialModel `tfsdk:"credentials"` } type integrationGithubCredentialModel struct { @@ -260,5 +262,48 @@ func (r *integrationGithubResource) Delete(ctx context.Context, req resource.Del } func (r *integrationGithubResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { - resource.ImportStatePassthroughID(ctx, path.Root("mrn"), req, resp) + mrn := req.ID + integration, err := r.client.GetClientIntegration(ctx, mrn) + if err != nil { + resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to get Domain integration, got error: %s", err)) + return + } + + allowList := r.ConvertListValue(ctx, integration.ConfigurationOptions.GithubConfigurationOptions.ReposAllowList) + denyList := r.ConvertListValue(ctx, integration.ConfigurationOptions.GithubConfigurationOptions.ReposDenyList) + + model := integrationGithubResourceModel{ + Mrn: types.StringValue(mrn), + Name: types.StringValue(integration.Name), + SpaceId: types.StringValue(strings.Split(integration.Mrn, "/")[len(strings.Split(integration.Mrn, "/"))-3]), + Owner: types.StringValue(integration.ConfigurationOptions.GithubConfigurationOptions.Owner), + Repository: types.StringValue(integration.ConfigurationOptions.GithubConfigurationOptions.Repository), + RepositoryAllowList: allowList, + RepositoryDenyList: denyList, + Credential: &integrationGithubCredentialModel{ + Token: types.StringPointerValue(nil), + }, + } + + if model.Owner.ValueString() == "" { + model.Owner = types.StringValue(integration.ConfigurationOptions.GithubConfigurationOptions.Organization) + } + + resp.State.SetAttribute(ctx, path.Root("mrn"), model.Mrn) + resp.State.SetAttribute(ctx, path.Root("name"), model.Name) + resp.State.SetAttribute(ctx, path.Root("space_id"), model.SpaceId) + resp.State.SetAttribute(ctx, path.Root("owner"), model.Owner) + resp.State.SetAttribute(ctx, path.Root("repository"), model.Repository) + resp.State.SetAttribute(ctx, path.Root("repository_allow_list"), model.RepositoryAllowList) + resp.State.SetAttribute(ctx, path.Root("repository_deny_list"), model.RepositoryDenyList) + resp.State.SetAttribute(ctx, path.Root("credential"), model.Credential) +} + +func (r *integrationGithubResource) ConvertListValue(ctx context.Context, list []string) types.List { + var valueList []attr.Value + for _, str := range list { + valueList = append(valueList, types.StringValue(str)) + } + // Ensure the list is of type types.StringType + return types.ListValueMust(types.StringType, valueList) } diff --git a/internal/provider/integration_ms365_resource.go b/internal/provider/integration_ms365_resource.go index ace14db..0e20ba0 100644 --- a/internal/provider/integration_ms365_resource.go +++ b/internal/provider/integration_ms365_resource.go @@ -3,6 +3,7 @@ package provider import ( "context" "fmt" + "strings" "github.com/hashicorp/terraform-plugin-framework/path" "github.com/hashicorp/terraform-plugin-framework/resource" @@ -34,7 +35,7 @@ type integrationMs365ResourceModel struct { TenantId types.String `tfsdk:"tenant_id"` // credentials - Credential integrationMs365CredentialModel `tfsdk:"credentials"` + Credential *integrationMs365CredentialModel `tfsdk:"credentials"` } type integrationMs365CredentialModel struct { @@ -219,5 +220,28 @@ func (r *integrationMs365Resource) Delete(ctx context.Context, req resource.Dele } func (r *integrationMs365Resource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { - resource.ImportStatePassthroughID(ctx, path.Root("mrn"), req, resp) + mrn := req.ID + integration, err := r.client.GetClientIntegration(ctx, mrn) + if err != nil { + resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to get Ms365 integration, got error: %s", err)) + return + } + + model := integrationMs365ResourceModel{ + Mrn: types.StringValue(string(integration.Mrn)), + Name: types.StringValue(string(integration.Name)), + SpaceId: types.StringValue(strings.Split(integration.Mrn, "/")[len(strings.Split(integration.Mrn, "/"))-3]), + TenantId: types.StringValue(integration.ConfigurationOptions.Ms365ConfigurationOptions.TenantId), + ClientId: types.StringValue(integration.ConfigurationOptions.Ms365ConfigurationOptions.ClientId), + Credential: &integrationMs365CredentialModel{ + PEMFile: types.StringPointerValue(nil), + }, + } + + resp.State.SetAttribute(ctx, path.Root("space_id"), model.SpaceId) + resp.State.SetAttribute(ctx, path.Root("mrn"), model.Mrn) + resp.State.SetAttribute(ctx, path.Root("name"), model.Name) + resp.State.SetAttribute(ctx, path.Root("tenant_id"), model.TenantId) + resp.State.SetAttribute(ctx, path.Root("client_id"), model.ClientId) + resp.State.SetAttribute(ctx, path.Root("pem_file"), model.Credential.PEMFile) } From 7199fd6a752c4290ea86259b5c732bf276ca67ef Mon Sep 17 00:00:00 2001 From: Matthias Theuermann Date: Thu, 4 Jul 2024 10:58:15 +0200 Subject: [PATCH 04/10] feat: added import for slack and ms365 Signed-off-by: Matthias Theuermann --- internal/provider/gql.go | 16 ++++++++-------- .../provider/integration_github_resource.go | 2 +- .../provider/integration_ms365_resource.go | 6 +++--- .../provider/integration_slack_resource.go | 18 ++++++++++++++++-- 4 files changed, 28 insertions(+), 14 deletions(-) diff --git a/internal/provider/gql.go b/internal/provider/gql.go index a289485..2ab72b2 100644 --- a/internal/provider/gql.go +++ b/internal/provider/gql.go @@ -380,9 +380,9 @@ type HostConfigurationOptions struct { HTTP bool `graphql:"http"` } -// type SlackConfigurationOptions struct { -// SlackToken string `graphql:"slackToken"` -// } +type SlackConfigurationOptions struct { + Placeholder string +} type GithubConfigurationOptions struct { Owner string @@ -412,11 +412,11 @@ type GcpConfigurationOptions struct { type ClientIntegrationConfigurationOptions struct { // AWSConfigurationOptions AWSConfigurationOptions `graphql:"... on AWSConfigurationOptions"` - AzureConfigurationOptions AzureConfigurationOptions `graphql:"... on AzureConfigurationOptions"` - HostConfigurationOptions HostConfigurationOptions `graphql:"... on HostConfigurationOptions"` - Ms365ConfigurationOptions Ms365ConfigurationOptions `graphql:"... on Ms365ConfigurationOptions"` - GcpConfigurationOptions GcpConfigurationOptions `graphql:"... on GcpConfigurationOptions"` - // SlackConfigurationOptions SlackConfigurationOptions `graphql:"... on SlackConfigurationOptions"` + AzureConfigurationOptions AzureConfigurationOptions `graphql:"... on AzureConfigurationOptions"` + HostConfigurationOptions HostConfigurationOptions `graphql:"... on HostConfigurationOptions"` + Ms365ConfigurationOptions Ms365ConfigurationOptions `graphql:"... on Ms365ConfigurationOptions"` + GcpConfigurationOptions GcpConfigurationOptions `graphql:"... on GcpConfigurationOptions"` + SlackConfigurationOptions SlackConfigurationOptions `graphql:"... on SlackConfigurationOptions"` GithubConfigurationOptions GithubConfigurationOptions `graphql:"... on GithubConfigurationOptions"` HostedAwsConfigurationOptions HostedAwsConfigurationOptions `graphql:"... on HostedAwsConfigurationOptions"` // Add other configuration options here diff --git a/internal/provider/integration_github_resource.go b/internal/provider/integration_github_resource.go index 15c9c74..1118c3e 100644 --- a/internal/provider/integration_github_resource.go +++ b/internal/provider/integration_github_resource.go @@ -265,7 +265,7 @@ func (r *integrationGithubResource) ImportState(ctx context.Context, req resourc mrn := req.ID integration, err := r.client.GetClientIntegration(ctx, mrn) if err != nil { - resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to get Domain integration, got error: %s", err)) + resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to get GitHub integration, got error: %s", err)) return } diff --git a/internal/provider/integration_ms365_resource.go b/internal/provider/integration_ms365_resource.go index 0e20ba0..0a6643e 100644 --- a/internal/provider/integration_ms365_resource.go +++ b/internal/provider/integration_ms365_resource.go @@ -35,7 +35,7 @@ type integrationMs365ResourceModel struct { TenantId types.String `tfsdk:"tenant_id"` // credentials - Credential *integrationMs365CredentialModel `tfsdk:"credentials"` + Credential integrationMs365CredentialModel `tfsdk:"credentials"` } type integrationMs365CredentialModel struct { @@ -233,7 +233,7 @@ func (r *integrationMs365Resource) ImportState(ctx context.Context, req resource SpaceId: types.StringValue(strings.Split(integration.Mrn, "/")[len(strings.Split(integration.Mrn, "/"))-3]), TenantId: types.StringValue(integration.ConfigurationOptions.Ms365ConfigurationOptions.TenantId), ClientId: types.StringValue(integration.ConfigurationOptions.Ms365ConfigurationOptions.ClientId), - Credential: &integrationMs365CredentialModel{ + Credential: integrationMs365CredentialModel{ PEMFile: types.StringPointerValue(nil), }, } @@ -243,5 +243,5 @@ func (r *integrationMs365Resource) ImportState(ctx context.Context, req resource resp.State.SetAttribute(ctx, path.Root("name"), model.Name) resp.State.SetAttribute(ctx, path.Root("tenant_id"), model.TenantId) resp.State.SetAttribute(ctx, path.Root("client_id"), model.ClientId) - resp.State.SetAttribute(ctx, path.Root("pem_file"), model.Credential.PEMFile) + resp.State.SetAttribute(ctx, path.Root("credentials"), model.Credential) } diff --git a/internal/provider/integration_slack_resource.go b/internal/provider/integration_slack_resource.go index 889de79..cd637dd 100644 --- a/internal/provider/integration_slack_resource.go +++ b/internal/provider/integration_slack_resource.go @@ -3,8 +3,8 @@ package provider import ( "context" "fmt" + "strings" - "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" @@ -197,5 +197,19 @@ func (r *integrationSlackResource) Delete(ctx context.Context, req resource.Dele } func (r *integrationSlackResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { - resource.ImportStatePassthroughID(ctx, path.Root("mrn"), req, resp) + mrn := req.ID + integration, err := r.client.GetClientIntegration(ctx, mrn) + if err != nil { + resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to get Slack integration, got error: %s", err)) + return + } + + model := integrationSlackResourceModel{ + Mrn: types.StringValue(string(integration.Mrn)), + Name: types.StringValue(string(integration.Name)), + SlackToken: types.StringPointerValue(nil), + SpaceId: types.StringValue(strings.Split(integration.Mrn, "/")[len(strings.Split(integration.Mrn, "/"))-3]), + } + + resp.State.Set(ctx, &model) } From a49ba69009d8a66945d69265fef81b82cd0f34df Mon Sep 17 00:00:00 2001 From: Matthias Theuermann Date: Thu, 4 Jul 2024 11:24:36 +0200 Subject: [PATCH 05/10] fix: import errors and state import method Signed-off-by: Matthias Theuermann --- go.mod | 5 +---- internal/provider/integration_aws_resource.go | 7 ++----- internal/provider/integration_azure_resource.go | 14 +++----------- internal/provider/integration_domain_resource.go | 9 ++------- internal/provider/integration_gcp_resource.go | 7 +------ internal/provider/integration_github_resource.go | 15 ++++----------- internal/provider/integration_ms365_resource.go | 8 +------- internal/provider/integration_slack_resource.go | 3 +-- internal/provider/space_resource.go | 5 +---- 9 files changed, 16 insertions(+), 57 deletions(-) diff --git a/go.mod b/go.mod index 224e154..4cbab7f 100644 --- a/go.mod +++ b/go.mod @@ -10,8 +10,8 @@ require ( github.com/hashicorp/terraform-plugin-go v0.23.0 github.com/hashicorp/terraform-plugin-log v0.9.0 github.com/hashicorp/terraform-plugin-testing v1.8.0 - github.com/stretchr/testify v1.9.0 go.mondoo.com/mondoo-go v0.0.0-20240611114249-2c3b9b20e67a + gopkg.in/yaml.v2 v2.4.0 ) require ( @@ -34,7 +34,6 @@ require ( github.com/cli/safeexec v1.0.1 // indirect github.com/cli/shurcooL-graphql v0.0.4 // indirect github.com/cloudflare/circl v1.3.8 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect github.com/fatih/color v1.16.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/go-jose/go-jose/v3 v3.0.3 // indirect @@ -91,7 +90,6 @@ require ( github.com/muesli/termenv v0.15.2 // indirect github.com/oklog/run v1.0.0 // indirect github.com/oklog/ulid v1.3.1 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect github.com/posener/complete v1.2.3 // indirect github.com/rivo/uniseg v0.4.7 // indirect github.com/samber/lo v1.39.0 // indirect @@ -124,6 +122,5 @@ require ( google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de // indirect google.golang.org/grpc v1.63.2 // indirect google.golang.org/protobuf v1.34.2 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/internal/provider/integration_aws_resource.go b/internal/provider/integration_aws_resource.go index 4334295..a983367 100644 --- a/internal/provider/integration_aws_resource.go +++ b/internal/provider/integration_aws_resource.go @@ -6,8 +6,8 @@ package provider import ( "context" "fmt" - "strings" "regexp" + "strings" "github.com/hashicorp/terraform-plugin-framework-validators/objectvalidator" "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" @@ -304,8 +304,5 @@ func (r *integrationAwsResource) ImportState(ctx context.Context, req resource.I }, } - resp.State.SetAttribute(ctx, path.Root("space_id"), model.SpaceId) - resp.State.SetAttribute(ctx, path.Root("mrn"), model.Mrn) - resp.State.SetAttribute(ctx, path.Root("name"), model.Name) - resp.State.SetAttribute(ctx, path.Root("credentials"), model.Credential) + resp.State.Set(ctx, &model) } diff --git a/internal/provider/integration_azure_resource.go b/internal/provider/integration_azure_resource.go index 16d6234..f5061f2 100644 --- a/internal/provider/integration_azure_resource.go +++ b/internal/provider/integration_azure_resource.go @@ -4,10 +4,10 @@ import ( "context" "fmt" "strings" - - "github.com/hashicorp/terraform-plugin-framework/attr" + "github.com/hashicorp/terraform-plugin-framework-validators/listvalidator" "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" + "github.com/hashicorp/terraform-plugin-framework/attr" "github.com/hashicorp/terraform-plugin-framework/path" "github.com/hashicorp/terraform-plugin-framework/resource" "github.com/hashicorp/terraform-plugin-framework/resource/schema" @@ -316,15 +316,7 @@ func (r *integrationAzureResource) ImportState(ctx context.Context, req resource ScanVms: types.BoolValue(integration.ConfigurationOptions.AzureConfigurationOptions.ScanVms), } - resp.State.SetAttribute(ctx, path.Root("space_id"), model.SpaceId) - resp.State.SetAttribute(ctx, path.Root("mrn"), model.Mrn) - resp.State.SetAttribute(ctx, path.Root("client_id"), model.ClientId) - resp.State.SetAttribute(ctx, path.Root("tenant_id"), model.TenantId) - resp.State.SetAttribute(ctx, path.Root("name"), model.Name) - resp.State.SetAttribute(ctx, path.Root("credentials"), model.Credential) - resp.State.SetAttribute(ctx, path.Root("scan_vms"), model.ScanVms) - resp.State.SetAttribute(ctx, path.Root("subscription_allow_list"), model.SubscriptionAllowList) - resp.State.SetAttribute(ctx, path.Root("subscription_deny_list"), model.SubscriptionDenyList) + resp.State.Set(ctx, &model) } func (r *integrationAzureResource) ConvertListValue(ctx context.Context, list []string) types.List { diff --git a/internal/provider/integration_domain_resource.go b/internal/provider/integration_domain_resource.go index bdffd91..4c173bc 100644 --- a/internal/provider/integration_domain_resource.go +++ b/internal/provider/integration_domain_resource.go @@ -3,11 +3,10 @@ package provider import ( "context" "fmt" - "strings" "regexp" + "strings" "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" - "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" @@ -228,9 +227,5 @@ func (r *integrationDomainResource) ImportState(ctx context.Context, req resourc Http: types.BoolValue(integration.ConfigurationOptions.HostConfigurationOptions.HTTP), } - resp.State.SetAttribute(ctx, path.Root("space_id"), model.SpaceId) - resp.State.SetAttribute(ctx, path.Root("mrn"), model.Mrn) - resp.State.SetAttribute(ctx, path.Root("host"), model.Host) - resp.State.SetAttribute(ctx, path.Root("https"), model.Https) - resp.State.SetAttribute(ctx, path.Root("http"), model.Http) + resp.State.Set(ctx, &model) } diff --git a/internal/provider/integration_gcp_resource.go b/internal/provider/integration_gcp_resource.go index 98b0a15..688e06b 100644 --- a/internal/provider/integration_gcp_resource.go +++ b/internal/provider/integration_gcp_resource.go @@ -9,7 +9,6 @@ import ( "strings" "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" - "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" @@ -240,9 +239,5 @@ func (r *integrationGcpResource) ImportState(ctx context.Context, req resource.I }, } - resp.State.SetAttribute(ctx, path.Root("space_id"), model.SpaceId) - resp.State.SetAttribute(ctx, path.Root("mrn"), model.Mrn) - resp.State.SetAttribute(ctx, path.Root("name"), model.Name) - resp.State.SetAttribute(ctx, path.Root("project_id"), model.ProjectId) - resp.State.SetAttribute(ctx, path.Root("credentials"), model.Credential) + resp.State.Set(ctx, &model) } diff --git a/internal/provider/integration_github_resource.go b/internal/provider/integration_github_resource.go index bc2cf68..c770383 100644 --- a/internal/provider/integration_github_resource.go +++ b/internal/provider/integration_github_resource.go @@ -3,12 +3,12 @@ package provider import ( "context" "fmt" + "regexp" "strings" - "regexp" - - "github.com/hashicorp/terraform-plugin-framework/attr" + "github.com/hashicorp/terraform-plugin-framework-validators/listvalidator" "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" + "github.com/hashicorp/terraform-plugin-framework/attr" "github.com/hashicorp/terraform-plugin-framework/path" "github.com/hashicorp/terraform-plugin-framework/resource" "github.com/hashicorp/terraform-plugin-framework/resource/schema" @@ -314,14 +314,7 @@ func (r *integrationGithubResource) ImportState(ctx context.Context, req resourc model.Owner = types.StringValue(integration.ConfigurationOptions.GithubConfigurationOptions.Organization) } - resp.State.SetAttribute(ctx, path.Root("mrn"), model.Mrn) - resp.State.SetAttribute(ctx, path.Root("name"), model.Name) - resp.State.SetAttribute(ctx, path.Root("space_id"), model.SpaceId) - resp.State.SetAttribute(ctx, path.Root("owner"), model.Owner) - resp.State.SetAttribute(ctx, path.Root("repository"), model.Repository) - resp.State.SetAttribute(ctx, path.Root("repository_allow_list"), model.RepositoryAllowList) - resp.State.SetAttribute(ctx, path.Root("repository_deny_list"), model.RepositoryDenyList) - resp.State.SetAttribute(ctx, path.Root("credential"), model.Credential) + resp.State.Set(ctx, &model) } func (r *integrationGithubResource) ConvertListValue(ctx context.Context, list []string) types.List { diff --git a/internal/provider/integration_ms365_resource.go b/internal/provider/integration_ms365_resource.go index 2a53eae..7ecb9ef 100644 --- a/internal/provider/integration_ms365_resource.go +++ b/internal/provider/integration_ms365_resource.go @@ -6,7 +6,6 @@ import ( "strings" "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" - "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" @@ -243,10 +242,5 @@ func (r *integrationMs365Resource) ImportState(ctx context.Context, req resource }, } - resp.State.SetAttribute(ctx, path.Root("space_id"), model.SpaceId) - resp.State.SetAttribute(ctx, path.Root("mrn"), model.Mrn) - resp.State.SetAttribute(ctx, path.Root("name"), model.Name) - resp.State.SetAttribute(ctx, path.Root("tenant_id"), model.TenantId) - resp.State.SetAttribute(ctx, path.Root("client_id"), model.ClientId) - resp.State.SetAttribute(ctx, path.Root("credentials"), model.Credential) + resp.State.Set(ctx, &model) } diff --git a/internal/provider/integration_slack_resource.go b/internal/provider/integration_slack_resource.go index 5f8d53e..c300c81 100644 --- a/internal/provider/integration_slack_resource.go +++ b/internal/provider/integration_slack_resource.go @@ -3,11 +3,10 @@ package provider import ( "context" "fmt" - "strings" "regexp" + "strings" "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" - "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" diff --git a/internal/provider/space_resource.go b/internal/provider/space_resource.go index c3ee9f9..e78cb4c 100644 --- a/internal/provider/space_resource.go +++ b/internal/provider/space_resource.go @@ -236,8 +236,5 @@ func (r *SpaceResource) ImportState(ctx context.Context, req resource.ImportStat OrgID: types.StringValue(spacePayload.Organization.Id), } - resp.State.SetAttribute(ctx, path.Root("id"), model.SpaceID) - resp.State.SetAttribute(ctx, path.Root("name"), model.Name) - resp.State.SetAttribute(ctx, path.Root("org_id"), model.OrgID) - resp.State.SetAttribute(ctx, path.Root("mrn"), model.SpaceMrn) + resp.State.Set(ctx, &model) } From 8fc7f1932feb973132780c91ef1642f99d4db9f9 Mon Sep 17 00:00:00 2001 From: Matthias Theuermann Date: Thu, 4 Jul 2024 11:27:45 +0200 Subject: [PATCH 06/10] fix: updated docs Signed-off-by: Matthias Theuermann --- docs/resources/integration_aws.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/resources/integration_aws.md b/docs/resources/integration_aws.md index 6ea5661..7822052 100644 --- a/docs/resources/integration_aws.md +++ b/docs/resources/integration_aws.md @@ -24,7 +24,7 @@ variable "aws_access_key" { } variable "aws_secret_key" { - description = "AWS access key" + description = "AWS secret key" type = string } From 02e136cdf2a13b3856f3161da94773962e2036ce Mon Sep 17 00:00:00 2001 From: Matthias Theuermann Date: Thu, 4 Jul 2024 11:34:29 +0200 Subject: [PATCH 07/10] fix: removed unnecessary string conversion Signed-off-by: Matthias Theuermann --- internal/provider/integration_aws_resource.go | 8 ++++---- internal/provider/integration_azure_resource.go | 4 ++-- internal/provider/integration_gcp_resource.go | 4 ++-- internal/provider/integration_ms365_resource.go | 4 ++-- internal/provider/integration_slack_resource.go | 4 ++-- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/internal/provider/integration_aws_resource.go b/internal/provider/integration_aws_resource.go index a983367..2588105 100644 --- a/internal/provider/integration_aws_resource.go +++ b/internal/provider/integration_aws_resource.go @@ -290,15 +290,15 @@ func (r *integrationAwsResource) ImportState(ctx context.Context, req resource.I model := integrationAwsResourceModel{ SpaceId: types.StringValue(strings.Split(integration.Mrn, "/")[len(strings.Split(integration.Mrn, "/"))-3]), - Mrn: types.StringValue(string(integration.Mrn)), - Name: types.StringValue(string(integration.Name)), + Mrn: types.StringValue(integration.Mrn), + Name: types.StringValue(integration.Name), Credential: integrationAwsCredentialModel{ Role: &roleCredentialModel{ - RoleArn: types.StringValue(string(integration.ConfigurationOptions.HostedAwsConfigurationOptions.Role)), + RoleArn: types.StringValue(integration.ConfigurationOptions.HostedAwsConfigurationOptions.Role), ExternalId: basetypes.NewStringNull(), // cannot be imported }, Key: &accessKeyCredentialModel{ - AccessKey: types.StringValue(string(integration.ConfigurationOptions.HostedAwsConfigurationOptions.AccessKeyId)), + AccessKey: types.StringValue(integration.ConfigurationOptions.HostedAwsConfigurationOptions.AccessKeyId), SecretKey: basetypes.NewStringNull(), // cannot be imported }, }, diff --git a/internal/provider/integration_azure_resource.go b/internal/provider/integration_azure_resource.go index f5061f2..4b1d0e6 100644 --- a/internal/provider/integration_azure_resource.go +++ b/internal/provider/integration_azure_resource.go @@ -304,8 +304,8 @@ func (r *integrationAzureResource) ImportState(ctx context.Context, req resource model := integrationAzureResourceModel{ SpaceId: types.StringValue(strings.Split(integration.Mrn, "/")[len(strings.Split(integration.Mrn, "/"))-3]), - Mrn: types.StringValue(string(integration.Mrn)), - Name: types.StringValue(string(integration.Name)), + Mrn: types.StringValue(integration.Mrn), + Name: types.StringValue(integration.Name), ClientId: types.StringValue(integration.ConfigurationOptions.AzureConfigurationOptions.ClientId), TenantId: types.StringValue(integration.ConfigurationOptions.AzureConfigurationOptions.TenantId), SubscriptionAllowList: allowList, diff --git a/internal/provider/integration_gcp_resource.go b/internal/provider/integration_gcp_resource.go index 688e06b..e047b24 100644 --- a/internal/provider/integration_gcp_resource.go +++ b/internal/provider/integration_gcp_resource.go @@ -230,8 +230,8 @@ func (r *integrationGcpResource) ImportState(ctx context.Context, req resource.I } model := integrationGcpResourceModel{ - Mrn: types.StringValue(string(integration.Mrn)), - Name: types.StringValue(string(integration.Name)), + Mrn: types.StringValue(integration.Mrn), + Name: types.StringValue(integration.Name), SpaceId: types.StringValue(strings.Split(integration.Mrn, "/")[len(strings.Split(integration.Mrn, "/"))-3]), ProjectId: types.StringValue(integration.ConfigurationOptions.GcpConfigurationOptions.ProjectId), Credential: integrationGcpCredentialModel{ diff --git a/internal/provider/integration_ms365_resource.go b/internal/provider/integration_ms365_resource.go index 7ecb9ef..cdec3b5 100644 --- a/internal/provider/integration_ms365_resource.go +++ b/internal/provider/integration_ms365_resource.go @@ -232,8 +232,8 @@ func (r *integrationMs365Resource) ImportState(ctx context.Context, req resource } model := integrationMs365ResourceModel{ - Mrn: types.StringValue(string(integration.Mrn)), - Name: types.StringValue(string(integration.Name)), + Mrn: types.StringValue(integration.Mrn), + Name: types.StringValue(integration.Name), SpaceId: types.StringValue(strings.Split(integration.Mrn, "/")[len(strings.Split(integration.Mrn, "/"))-3]), TenantId: types.StringValue(integration.ConfigurationOptions.Ms365ConfigurationOptions.TenantId), ClientId: types.StringValue(integration.ConfigurationOptions.Ms365ConfigurationOptions.ClientId), diff --git a/internal/provider/integration_slack_resource.go b/internal/provider/integration_slack_resource.go index c300c81..59c13bd 100644 --- a/internal/provider/integration_slack_resource.go +++ b/internal/provider/integration_slack_resource.go @@ -217,8 +217,8 @@ func (r *integrationSlackResource) ImportState(ctx context.Context, req resource } model := integrationSlackResourceModel{ - Mrn: types.StringValue(string(integration.Mrn)), - Name: types.StringValue(string(integration.Name)), + Mrn: types.StringValue(integration.Mrn), + Name: types.StringValue(integration.Name), SlackToken: types.StringPointerValue(nil), SpaceId: types.StringValue(strings.Split(integration.Mrn, "/")[len(strings.Split(integration.Mrn, "/"))-3]), } From 3ee5ab5d6aa7ccf74cc0ea4568e0b6be4288d743 Mon Sep 17 00:00:00 2001 From: Matthias Theuermann Date: Thu, 4 Jul 2024 11:36:37 +0200 Subject: [PATCH 08/10] fix: changed from basetype to types.StringPointerValue(nil) in import statement Signed-off-by: Matthias Theuermann --- internal/provider/integration_aws_resource.go | 5 ++--- internal/provider/integration_azure_resource.go | 3 +-- internal/provider/integration_gcp_resource.go | 3 +-- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/internal/provider/integration_aws_resource.go b/internal/provider/integration_aws_resource.go index 2588105..871201b 100644 --- a/internal/provider/integration_aws_resource.go +++ b/internal/provider/integration_aws_resource.go @@ -18,7 +18,6 @@ import ( "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" "github.com/hashicorp/terraform-plugin-framework/schema/validator" "github.com/hashicorp/terraform-plugin-framework/types" - "github.com/hashicorp/terraform-plugin-framework/types/basetypes" mondoov1 "go.mondoo.com/mondoo-go" ) @@ -295,11 +294,11 @@ func (r *integrationAwsResource) ImportState(ctx context.Context, req resource.I Credential: integrationAwsCredentialModel{ Role: &roleCredentialModel{ RoleArn: types.StringValue(integration.ConfigurationOptions.HostedAwsConfigurationOptions.Role), - ExternalId: basetypes.NewStringNull(), // cannot be imported + ExternalId: types.StringPointerValue(nil), // cannot be imported }, Key: &accessKeyCredentialModel{ AccessKey: types.StringValue(integration.ConfigurationOptions.HostedAwsConfigurationOptions.AccessKeyId), - SecretKey: basetypes.NewStringNull(), // cannot be imported + SecretKey: types.StringPointerValue(nil), // cannot be imported }, }, } diff --git a/internal/provider/integration_azure_resource.go b/internal/provider/integration_azure_resource.go index 4b1d0e6..2a77f3e 100644 --- a/internal/provider/integration_azure_resource.go +++ b/internal/provider/integration_azure_resource.go @@ -15,7 +15,6 @@ import ( "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" "github.com/hashicorp/terraform-plugin-framework/schema/validator" "github.com/hashicorp/terraform-plugin-framework/types" - "github.com/hashicorp/terraform-plugin-framework/types/basetypes" mondoov1 "go.mondoo.com/mondoo-go" ) @@ -311,7 +310,7 @@ func (r *integrationAzureResource) ImportState(ctx context.Context, req resource SubscriptionAllowList: allowList, SubscriptionDenyList: denyList, Credential: integrationAzureCredentialModel{ - PEMFile: basetypes.NewStringNull(), + PEMFile: types.StringPointerValue(nil), }, ScanVms: types.BoolValue(integration.ConfigurationOptions.AzureConfigurationOptions.ScanVms), } diff --git a/internal/provider/integration_gcp_resource.go b/internal/provider/integration_gcp_resource.go index e047b24..8325ed8 100644 --- a/internal/provider/integration_gcp_resource.go +++ b/internal/provider/integration_gcp_resource.go @@ -15,7 +15,6 @@ import ( "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" "github.com/hashicorp/terraform-plugin-framework/schema/validator" "github.com/hashicorp/terraform-plugin-framework/types" - "github.com/hashicorp/terraform-plugin-framework/types/basetypes" mondoov1 "go.mondoo.com/mondoo-go" ) @@ -235,7 +234,7 @@ func (r *integrationGcpResource) ImportState(ctx context.Context, req resource.I SpaceId: types.StringValue(strings.Split(integration.Mrn, "/")[len(strings.Split(integration.Mrn, "/"))-3]), ProjectId: types.StringValue(integration.ConfigurationOptions.GcpConfigurationOptions.ProjectId), Credential: integrationGcpCredentialModel{ - PrivateKey: basetypes.NewStringNull(), + PrivateKey: types.StringPointerValue(nil), }, } From 8be09f714a64d4c787313b465fe1a02d50ddcfdf Mon Sep 17 00:00:00 2001 From: Paul Date: Thu, 4 Jul 2024 16:16:36 +0200 Subject: [PATCH 09/10] feat: added custom-resources imports Signed-off-by: Paul --- .../custom_compliance_framework_resource.go | 23 +++++++++- internal/provider/custom_policy.go | 37 +++++++++++++++ internal/provider/custom_querypack.go | 37 +++++++++++++++ internal/provider/gql.go | 45 +++++++++++++++++++ 4 files changed, 140 insertions(+), 2 deletions(-) diff --git a/internal/provider/custom_compliance_framework_resource.go b/internal/provider/custom_compliance_framework_resource.go index c803b4d..aba55ca 100644 --- a/internal/provider/custom_compliance_framework_resource.go +++ b/internal/provider/custom_compliance_framework_resource.go @@ -4,8 +4,8 @@ import ( "context" "fmt" "os" + "strings" - "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" @@ -217,5 +217,24 @@ func (r *customComplianceFrameworkResource) Delete(ctx context.Context, req reso } func (r *customComplianceFrameworkResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { - resource.ImportStatePassthroughID(ctx, path.Root("mrn"), req, resp) + // resource.ImportStatePassthroughID(ctx, path.Root("mrn"), req, resp) + mrn := req.ID + splitMrn := strings.Split(mrn, "/") + spaceMrn := spacePrefix + splitMrn[len(splitMrn)-3] + spaceId := splitMrn[len(splitMrn)-3] + uid := splitMrn[len(splitMrn)-1] + + framework, err := r.client.GetFramework(ctx, spaceMrn, spaceId, uid) + if err != nil { + resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to get Compliance Framework, got error: %s", err)) + return + } + + model := customComplianceFrameworkResourceModel{ + Mrn: types.StringValue(string(framework.Mrn)), + DataUrl: types.StringPointerValue(nil), + SpaceId: types.StringValue(spaceId), + } + + resp.State.Set(ctx, &model) } diff --git a/internal/provider/custom_policy.go b/internal/provider/custom_policy.go index d834236..4ef4382 100644 --- a/internal/provider/custom_policy.go +++ b/internal/provider/custom_policy.go @@ -8,6 +8,7 @@ import ( "fmt" "hash/crc32" "os" + "strings" "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" "github.com/hashicorp/terraform-plugin-framework/path" @@ -296,3 +297,39 @@ func (r *customPolicyResource) Delete(ctx context.Context, req resource.DeleteRe } } } + +func (r *customPolicyResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { + mrn := req.ID + splitMrn := strings.Split(mrn, "/") + spaceMrn := spacePrefix + splitMrn[len(splitMrn)-3] + spaceId := splitMrn[len(splitMrn)-3] + + policy, err := r.client.GetPolicy(ctx, mrn, spaceMrn) + if err != nil { + resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to get policy, got error: %s", err)) + return + } + + content, err := r.client.DownloadBundle(ctx, string(policy.Mrn)) + if err != nil { + resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to download bundle, got error: %s", err)) + return + } + + mrns, _ := types.ListValueFrom(ctx, types.StringType, []string{mrn}) + + model := customPolicyResourceModel{ + SpaceId: types.StringValue(spaceId), + Mrns: mrns, + Overwrite: types.BoolValue(false), + Source: types.StringPointerValue(nil), + Content: types.StringValue(content), + Crc32Checksum: types.StringPointerValue(nil), + } + + checksum := newCrc32Checksum([]byte(content)) + + model.Crc32Checksum = types.StringValue(checksum) + + resp.State.Set(ctx, &model) +} diff --git a/internal/provider/custom_querypack.go b/internal/provider/custom_querypack.go index 3eac849..af70a21 100644 --- a/internal/provider/custom_querypack.go +++ b/internal/provider/custom_querypack.go @@ -7,6 +7,7 @@ import ( "context" "fmt" "os" + "strings" "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" "github.com/hashicorp/terraform-plugin-framework/path" @@ -288,3 +289,39 @@ func (r *customQueryPackResource) Delete(ctx context.Context, req resource.Delet } } } + +func (r *customQueryPackResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { + mrn := req.ID + splitMrn := strings.Split(mrn, "/") + spaceMrn := spacePrefix + splitMrn[len(splitMrn)-3] + spaceId := splitMrn[len(splitMrn)-3] + + queryPack, err := r.client.GetPolicy(ctx, mrn, spaceMrn) + if err != nil { + resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to get policy, got error: %s", err)) + return + } + + content, err := r.client.DownloadBundle(ctx, string(queryPack.Mrn)) + if err != nil { + resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to download bundle, got error: %s", err)) + return + } + + mrns, _ := types.ListValueFrom(ctx, types.StringType, []string{mrn}) + + model := customQueryPackResourceModel{ + SpaceId: types.StringValue(spaceId), + Mrns: mrns, + Overwrite: types.BoolValue(false), + Source: types.StringPointerValue(nil), + Content: types.StringValue(content), + Crc32Checksum: types.StringPointerValue(nil), + } + + checksum := newCrc32Checksum([]byte(content)) + + model.Crc32Checksum = types.StringValue(checksum) + + resp.State.Set(ctx, &model) +} diff --git a/internal/provider/gql.go b/internal/provider/gql.go index d87b621..d8173fa 100644 --- a/internal/provider/gql.go +++ b/internal/provider/gql.go @@ -168,6 +168,7 @@ type Policy struct { IsPublic mondoov1.Boolean CreatedAt mondoov1.String UpdatedAt mondoov1.String + Docs mondoov1.String } type PolicyNode struct { @@ -250,6 +251,28 @@ type ContentPayload struct { Content Content } +func (c *ExtendedGqlClient) DownloadBundle(ctx context.Context, policyMrn string) (string, error) { + var q struct { + DownloadBundle struct { + PolicyBundleYaml struct { + Yaml string `graphql:"yaml"` + } `graphql:"... on PolicyBundleYaml"` + } `graphql:"downloadBundle(input: $input)"` + } + variables := map[string]interface{}{ + "input": mondoov1.DownloadBundleInput{ + Mrn: mondoov1.String(policyMrn), + }, + } + + err := c.Query(ctx, &q, variables) + if err != nil { + return "", err + } + + return q.DownloadBundle.PolicyBundleYaml.Yaml, nil +} + func (c *ExtendedGqlClient) GetPolicies(ctx context.Context, scopeMrn string, catalogType string, assignedOnly bool) (*[]Policy, error) { // Define the query struct according to the provided query var contentQuery struct { @@ -284,6 +307,28 @@ func (c *ExtendedGqlClient) GetPolicies(ctx context.Context, scopeMrn string, ca return &policies, nil } +func (c *ExtendedGqlClient) GetPolicy(ctx context.Context, policyMrn string, spaceMrn string) (*Policy, error) { + var q struct { + Policy Policy `graphql:"policy(input: $input)"` + } + + input := mondoov1.PolicyInput{ + Mrn: mondoov1.NewStringPtr(mondoov1.String(policyMrn)), + SpaceMrn: mondoov1.NewStringPtr(mondoov1.String(spaceMrn)), + } + + variables := map[string]interface{}{ + "input": input, + } + + err := c.Query(ctx, &q, variables) + if err != nil { + return nil, err + } + + return &q.Policy, nil +} + func (c *ExtendedGqlClient) AssignPolicy(ctx context.Context, spaceMrn string, action mondoov1.PolicyAction, policyMrns []string) error { var list *[]mondoov1.String From 340b280aa28b42407dc69c8a8a7ccab91ab9d841 Mon Sep 17 00:00:00 2001 From: Paul Date: Wed, 10 Jul 2024 10:14:31 +0200 Subject: [PATCH 10/10] fix: removed unused comments Signed-off-by: Paul --- internal/provider/gql.go | 61 ++++------------------------------------ 1 file changed, 6 insertions(+), 55 deletions(-) diff --git a/internal/provider/gql.go b/internal/provider/gql.go index d8173fa..487a9f5 100644 --- a/internal/provider/gql.go +++ b/internal/provider/gql.go @@ -493,58 +493,12 @@ func (c *ExtendedGqlClient) DeleteIntegration(ctx context.Context, mrn string) ( return &deleteMutation.DeleteClientIntegration, nil } -// type AWSConfigurationOptions struct { -// AccountIds []string -// Region string -// IsOrganization bool -// ScanConfiguration ScanConfiguration -// SnsEndpoint string -// OriginAWSAccountId string `graphql:"originAWSAccountId"` -// CloudFormationTemplateUrl string -// } - -// type ScanConfiguration struct { -// AccountScan bool -// Ec2Scan bool `graphql:"ec2Scan"` -// EcrScan bool `graphql:"ecrScan"` -// EcsScan bool `graphql:"ecsScan"` -// CronScaninHours int -// EventScanTriggers []AWSEventPattern -// Ec2ScanOptions Ec2ScanOptions `graphql:"ec2ScanOptions"` -// } - -// type AWSEventPattern struct { -// ScanType string -// EventSource string -// EventDetailType string -// } - -// type Ec2ScanOptions struct { -// Ssm bool -// AwsSecretsManagerVault bool -// SecretsMetadataQuery string -// InstanceIdsFilter []string -// RegionsFilter []string -// TagsFilter map[string]string -// VaultType string -// EbsVolumeScan bool -// EbsScanOptions EbsScanOptions -// InstanceConnect bool -// } - -// type EbsScanOptions struct { -// TargetInstancesPerScanner int -// MaxAsgInstances int -// } - type AzureConfigurationOptions struct { TenantId string ClientId string SubscriptionsWhitelist []string SubscriptionsBlacklist []string - // Certificate string - ScanVms bool - // ClientSecret string + ScanVms bool } type HostConfigurationOptions struct { @@ -558,11 +512,10 @@ type SlackConfigurationOptions struct { } type GithubConfigurationOptions struct { - Owner string - Repository string - Organization string - // Token string - Type string //graphql enum + Owner string + Repository string + Organization string + Type string ReposAllowList []string ReposDenyList []string } @@ -578,13 +531,11 @@ type HostedAwsConfigurationOptions struct { } type GcpConfigurationOptions struct { - ProjectId string - // OrganizationId string + ProjectId string DiscoverAll bool } type ClientIntegrationConfigurationOptions struct { - // AWSConfigurationOptions AWSConfigurationOptions `graphql:"... on AWSConfigurationOptions"` AzureConfigurationOptions AzureConfigurationOptions `graphql:"... on AzureConfigurationOptions"` HostConfigurationOptions HostConfigurationOptions `graphql:"... on HostConfigurationOptions"` Ms365ConfigurationOptions Ms365ConfigurationOptions `graphql:"... on Ms365ConfigurationOptions"`