Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added Resource imports for Terraform #118

Merged
merged 11 commits into from
Jul 15, 2024
2 changes: 1 addition & 1 deletion docs/resources/integration_aws.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ variable "aws_access_key" {
}

variable "aws_secret_key" {
description = "AWS access key"
description = "AWS secret key"
type = string
}

Expand Down
3 changes: 1 addition & 2 deletions examples/resources/mondoo_integration_aws/resource.tf
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ variable "aws_access_key" {
}

variable "aws_secret_key" {
description = "AWS access key"
description = "AWS secret key"
type = string
}

Expand All @@ -33,4 +33,3 @@ resource "mondoo_integration_aws" "name" {
}
}
}

7 changes: 2 additions & 5 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -123,7 +121,6 @@ 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
gopkg.in/yaml.v2 v2.4.0 // indirect
google.golang.org/protobuf v1.34.2 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -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=
Expand Down
23 changes: 21 additions & 2 deletions internal/provider/custom_compliance_framework_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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)
}
37 changes: 37 additions & 0 deletions internal/provider/custom_policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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)
}
37 changes: 37 additions & 0 deletions internal/provider/custom_querypack.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"context"
"fmt"
"os"
"strings"

"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
"github.com/hashicorp/terraform-plugin-framework/path"
Expand Down Expand Up @@ -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)
}
124 changes: 124 additions & 0 deletions internal/provider/gql.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ type Policy struct {
IsPublic mondoov1.Boolean
CreatedAt mondoov1.String
UpdatedAt mondoov1.String
Docs mondoov1.String
}

type PolicyNode struct {
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -448,6 +493,85 @@ func (c *ExtendedGqlClient) DeleteIntegration(ctx context.Context, mrn string) (
return &deleteMutation.DeleteClientIntegration, nil
}

type AzureConfigurationOptions struct {
TenantId string
ClientId string
SubscriptionsWhitelist []string
SubscriptionsBlacklist []string
ScanVms bool
}

type HostConfigurationOptions struct {
Host string `graphql:"host"`
HTTPS bool `graphql:"https"`
HTTP bool `graphql:"http"`
}

type SlackConfigurationOptions struct {
Placeholder string
}

type GithubConfigurationOptions struct {
Owner string
Repository string
Organization string
Type string
ReposAllowList []string
ReposDenyList []string
}

type Ms365ConfigurationOptions struct {
TenantId string
ClientId string
}

type HostedAwsConfigurationOptions struct {
AccessKeyId string
Role string
}

type GcpConfigurationOptions struct {
ProjectId string
DiscoverAll bool
}

type ClientIntegrationConfigurationOptions struct {
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
}

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
}
Expand Down
26 changes: 25 additions & 1 deletion internal/provider/integration_aws_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"context"
"fmt"
"regexp"
"strings"

"github.com/hashicorp/terraform-plugin-framework-validators/objectvalidator"
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
Expand Down Expand Up @@ -279,5 +280,28 @@ 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(integration.Mrn),
Name: types.StringValue(integration.Name),
Credential: integrationAwsCredentialModel{
Role: &roleCredentialModel{
RoleArn: types.StringValue(integration.ConfigurationOptions.HostedAwsConfigurationOptions.Role),
ExternalId: types.StringPointerValue(nil), // cannot be imported
},
Key: &accessKeyCredentialModel{
AccessKey: types.StringValue(integration.ConfigurationOptions.HostedAwsConfigurationOptions.AccessKeyId),
SecretKey: types.StringPointerValue(nil), // cannot be imported
},
},
}

resp.State.Set(ctx, &model)
}
Loading
Loading