From 9b85bf90ab9deeeeb025496cca1844e88a1f2a7c Mon Sep 17 00:00:00 2001 From: GlennChia Date: Wed, 5 Jun 2024 00:25:07 +0000 Subject: [PATCH 01/25] td(gd): names csv add sdkv2 --- names/data/names_data.csv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/names/data/names_data.csv b/names/data/names_data.csv index 4944a0efc6d..01172e45d12 100644 --- a/names/data/names_data.csv +++ b/names/data/names_data.csv @@ -175,7 +175,7 @@ globalaccelerator,globalaccelerator,globalaccelerator,globalaccelerator,,globala glue,glue,glue,glue,,glue,,,Glue,Glue,,1,,,aws_glue_,,glue_,Glue,AWS,,,,,,,Glue,ListRegistries,,, databrew,databrew,gluedatabrew,databrew,,databrew,,gluedatabrew,DataBrew,GlueDataBrew,,1,,,aws_databrew_,,databrew_,Glue DataBrew,AWS,,x,,,,,DataBrew,,,, groundstation,groundstation,groundstation,groundstation,,groundstation,,,GroundStation,GroundStation,,,2,,aws_groundstation_,,groundstation_,Ground Station,AWS,,,,,,,GroundStation,ListConfigs,,, -guardduty,guardduty,guardduty,guardduty,,guardduty,,,GuardDuty,GuardDuty,,1,,,aws_guardduty_,,guardduty_,GuardDuty,Amazon,,,,,,,GuardDuty,ListDetectors,,, +guardduty,guardduty,guardduty,guardduty,,guardduty,,,GuardDuty,GuardDuty,,1,2,,aws_guardduty_,,guardduty_,GuardDuty,Amazon,,,,,,,GuardDuty,ListDetectors,,, health,health,health,health,,health,,,Health,Health,,1,,,aws_health_,,health_,Health,AWS,,x,,,,,Health,,,, healthlake,healthlake,healthlake,healthlake,,healthlake,,,HealthLake,HealthLake,,,2,,aws_healthlake_,,healthlake_,HealthLake,Amazon,,,,,,,HealthLake,ListFHIRDatastores,,, honeycode,honeycode,honeycode,honeycode,,honeycode,,,Honeycode,Honeycode,,1,,,aws_honeycode_,,honeycode_,Honeycode,Amazon,,x,,,,,Honeycode,,,, From b3015d9cbb1066e03d9dca6c2dd1ab0d5ab7a80f Mon Sep 17 00:00:00 2001 From: GlennChia Date: Wed, 5 Jun 2024 00:27:13 +0000 Subject: [PATCH 02/25] td(gd): awsclient_gen add guardduty sdkv2 go generate ./internal/conns/... --- internal/conns/awsclient_gen.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/internal/conns/awsclient_gen.go b/internal/conns/awsclient_gen.go index 64e3e5b05cc..dc90b8767e4 100644 --- a/internal/conns/awsclient_gen.go +++ b/internal/conns/awsclient_gen.go @@ -92,6 +92,7 @@ import ( glacier_sdkv2 "github.com/aws/aws-sdk-go-v2/service/glacier" globalaccelerator_sdkv2 "github.com/aws/aws-sdk-go-v2/service/globalaccelerator" groundstation_sdkv2 "github.com/aws/aws-sdk-go-v2/service/groundstation" + guardduty_sdkv2 "github.com/aws/aws-sdk-go-v2/service/guardduty" healthlake_sdkv2 "github.com/aws/aws-sdk-go-v2/service/healthlake" iam_sdkv2 "github.com/aws/aws-sdk-go-v2/service/iam" identitystore_sdkv2 "github.com/aws/aws-sdk-go-v2/service/identitystore" @@ -722,6 +723,10 @@ func (c *AWSClient) GuardDutyConn(ctx context.Context) *guardduty_sdkv1.GuardDut return errs.Must(conn[*guardduty_sdkv1.GuardDuty](ctx, c, names.GuardDuty, make(map[string]any))) } +func (c *AWSClient) GuardDutyClient(ctx context.Context) *guardduty_sdkv2.Client { + return errs.Must(client[*guardduty_sdkv2.Client](ctx, c, names.GuardDuty, make(map[string]any))) +} + func (c *AWSClient) HealthLakeClient(ctx context.Context) *healthlake_sdkv2.Client { return errs.Must(client[*healthlake_sdkv2.Client](ctx, c, names.HealthLake, make(map[string]any))) } From 08573517ac3b49906c412b9d518af6cef92b1fc6 Mon Sep 17 00:00:00 2001 From: GlennChia Date: Wed, 5 Jun 2024 00:31:55 +0000 Subject: [PATCH 03/25] td(gd): go get sdkv2 packages go get github.com/hashicorp/terraform-provider-aws/internal/conns --- go.mod | 1 + go.sum | 2 ++ 2 files changed, 3 insertions(+) diff --git a/go.mod b/go.mod index 27f03426f1d..01f904126c6 100644 --- a/go.mod +++ b/go.mod @@ -100,6 +100,7 @@ require ( github.com/aws/aws-sdk-go-v2/service/glacier v1.22.10 github.com/aws/aws-sdk-go-v2/service/globalaccelerator v1.24.1 github.com/aws/aws-sdk-go-v2/service/groundstation v1.27.6 + github.com/aws/aws-sdk-go-v2/service/guardduty v1.42.6 github.com/aws/aws-sdk-go-v2/service/healthlake v1.24.6 github.com/aws/aws-sdk-go-v2/service/iam v1.32.6 github.com/aws/aws-sdk-go-v2/service/identitystore v1.23.12 diff --git a/go.sum b/go.sum index 6c9c3bba57e..595c084ad75 100644 --- a/go.sum +++ b/go.sum @@ -220,6 +220,8 @@ github.com/aws/aws-sdk-go-v2/service/globalaccelerator v1.24.1 h1:bDVYY5tSzBnLAc github.com/aws/aws-sdk-go-v2/service/globalaccelerator v1.24.1/go.mod h1:ct31bulbJED7Z4Vdtr+Jtvt6bPRB5PdeH96NNm4wkOc= github.com/aws/aws-sdk-go-v2/service/groundstation v1.27.6 h1:2GSPMCtOlEVwltVhqUT1x6CFKpFi/5D2yFhd/PqaSic= github.com/aws/aws-sdk-go-v2/service/groundstation v1.27.6/go.mod h1:gFFqhE7646BA034Im+oTpkfnefC1AR/E4ZUTs/sV7lc= +github.com/aws/aws-sdk-go-v2/service/guardduty v1.42.6 h1:pb3MeWCl9X97FMxorU4nftL1uiBo+cq5GNDTBMeZ+o4= +github.com/aws/aws-sdk-go-v2/service/guardduty v1.42.6/go.mod h1:tNfynl7aA5gEHA7yJZiEICHYMkITKSc0Z+vic+YpW0M= github.com/aws/aws-sdk-go-v2/service/healthlake v1.24.6 h1:AlmacWcocqb7vowwTlYtVR9AbYWW4vFExIoD7+kFR4g= github.com/aws/aws-sdk-go-v2/service/healthlake v1.24.6/go.mod h1:jp0Co1hHoXMEQTzyRICGBHvN8owh1QISx56d79dulFU= github.com/aws/aws-sdk-go-v2/service/iam v1.32.6 h1:NRlKKQ/BPHPqsuN2Hy6v4WA8/bsRTP0j8/BFPBC5+SU= From 487c1da8ab8680ee2919b45717d30277624410e4 Mon Sep 17 00:00:00 2001 From: GlennChia Date: Wed, 5 Jun 2024 01:33:03 +0000 Subject: [PATCH 04/25] td(gd): generate sdkv2 with v1 make gen --- internal/service/guardduty/generate.go | 1 + .../guardduty/service_endpoints_gen_test.go | 170 +++++++++++++++--- .../service/guardduty/service_package_gen.go | 21 +++ internal/service/guardduty/tagsv2_gen.go | 40 +++++ 4 files changed, 209 insertions(+), 23 deletions(-) create mode 100644 internal/service/guardduty/tagsv2_gen.go diff --git a/internal/service/guardduty/generate.go b/internal/service/guardduty/generate.go index 9ca05391d7b..1da552f2cf6 100644 --- a/internal/service/guardduty/generate.go +++ b/internal/service/guardduty/generate.go @@ -2,6 +2,7 @@ // SPDX-License-Identifier: MPL-2.0 //go:generate go run ../../generate/tags/main.go -ListTags -ServiceTagsMap -UpdateTags +//go:generate go run ../../generate/tags/main.go -AWSSDKVersion=2 -TagsFunc=TagsV2 -KeyValueTagsFunc=keyValueTagsV2 -GetTagsInFunc=getTagsInV2 -SetTagsOutFunc=setTagsOutV2 -ServiceTagsMap -KVTValues -SkipTypesImp -SkipAWSServiceImp -SkipAWSImp -- tagsv2_gen.go //go:generate go run ../../generate/servicepackage/main.go // ONLY generate directives and package declaration! Do not add anything else to this file. diff --git a/internal/service/guardduty/service_endpoints_gen_test.go b/internal/service/guardduty/service_endpoints_gen_test.go index 8dfd48daf27..7c50f087414 100644 --- a/internal/service/guardduty/service_endpoints_gen_test.go +++ b/internal/service/guardduty/service_endpoints_gen_test.go @@ -4,17 +4,22 @@ package guardduty_test import ( "context" + "errors" "fmt" "maps" - "net/url" "os" "path/filepath" + "reflect" "strings" "testing" + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware" + guardduty_sdkv2 "github.com/aws/aws-sdk-go-v2/service/guardduty" aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/endpoints" guardduty_sdkv1 "github.com/aws/aws-sdk-go/service/guardduty" + "github.com/aws/smithy-go/middleware" + smithyhttp "github.com/aws/smithy-go/transport/http" "github.com/google/go-cmp/cmp" "github.com/hashicorp/aws-sdk-go-base/v2/servicemocks" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" @@ -229,52 +234,88 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S }, } - for name, testcase := range testcases { //nolint:paralleltest // uses t.Setenv - testcase := testcase + t.Run("v1", func(t *testing.T) { + for name, testcase := range testcases { //nolint:paralleltest // uses t.Setenv + testcase := testcase - t.Run(name, func(t *testing.T) { - testEndpointCase(t, providerRegion, testcase, callService) - }) - } + t.Run(name, func(t *testing.T) { + testEndpointCase(t, providerRegion, testcase, callServiceV1) + }) + } + }) + + t.Run("v2", func(t *testing.T) { + for name, testcase := range testcases { //nolint:paralleltest // uses t.Setenv + testcase := testcase + + t.Run(name, func(t *testing.T) { + testEndpointCase(t, providerRegion, testcase, callServiceV2) + }) + } + }) } func defaultEndpoint(region string) string { - r := endpoints.DefaultResolver() + r := guardduty_sdkv2.NewDefaultEndpointResolverV2() - ep, err := r.EndpointFor(guardduty_sdkv1.EndpointsID, region) + ep, err := r.ResolveEndpoint(context.Background(), guardduty_sdkv2.EndpointParameters{ + Region: aws_sdkv2.String(region), + }) if err != nil { return err.Error() } - url, _ := url.Parse(ep.URL) - - if url.Path == "" { - url.Path = "/" + if ep.URI.Path == "" { + ep.URI.Path = "/" } - return url.String() + return ep.URI.String() } func defaultFIPSEndpoint(region string) string { - r := endpoints.DefaultResolver() + r := guardduty_sdkv2.NewDefaultEndpointResolverV2() - ep, err := r.EndpointFor(guardduty_sdkv1.EndpointsID, region, func(opt *endpoints.Options) { - opt.UseFIPSEndpoint = endpoints.FIPSEndpointStateEnabled + ep, err := r.ResolveEndpoint(context.Background(), guardduty_sdkv2.EndpointParameters{ + Region: aws_sdkv2.String(region), + UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { return err.Error() } - url, _ := url.Parse(ep.URL) + if ep.URI.Path == "" { + ep.URI.Path = "/" + } + + return ep.URI.String() +} - if url.Path == "" { - url.Path = "/" +func callServiceV2(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { + t.Helper() + + client := meta.GuardDutyClient(ctx) + + var result apiCallParams + + _, err := client.ListDetectors(ctx, &guardduty_sdkv2.ListDetectorsInput{}, + func(opts *guardduty_sdkv2.Options) { + opts.APIOptions = append(opts.APIOptions, + addRetrieveEndpointURLMiddleware(t, &result.endpoint), + addRetrieveRegionMiddleware(&result.region), + addCancelRequestMiddleware(), + ) + }, + ) + if err == nil { + t.Fatal("Expected an error, got none") + } else if !errors.Is(err, errCancelOperation) { + t.Fatalf("Unexpected error: %s", err) } - return url.String() + return result } -func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { +func callServiceV1(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { t.Helper() client := meta.GuardDutyConn(ctx) @@ -443,6 +484,89 @@ func testEndpointCase(t *testing.T, region string, testcase endpointTestCase, ca } } +func addRetrieveEndpointURLMiddleware(t *testing.T, endpoint *string) func(*middleware.Stack) error { + return func(stack *middleware.Stack) error { + return stack.Finalize.Add( + retrieveEndpointURLMiddleware(t, endpoint), + middleware.After, + ) + } +} + +func retrieveEndpointURLMiddleware(t *testing.T, endpoint *string) middleware.FinalizeMiddleware { + return middleware.FinalizeMiddlewareFunc( + "Test: Retrieve Endpoint", + func(ctx context.Context, in middleware.FinalizeInput, next middleware.FinalizeHandler) (middleware.FinalizeOutput, middleware.Metadata, error) { + t.Helper() + + request, ok := in.Request.(*smithyhttp.Request) + if !ok { + t.Fatalf("Expected *github.com/aws/smithy-go/transport/http.Request, got %s", fullTypeName(in.Request)) + } + + url := request.URL + url.RawQuery = "" + url.Path = "/" + + *endpoint = url.String() + + return next.HandleFinalize(ctx, in) + }) +} + +func addRetrieveRegionMiddleware(region *string) func(*middleware.Stack) error { + return func(stack *middleware.Stack) error { + return stack.Serialize.Add( + retrieveRegionMiddleware(region), + middleware.After, + ) + } +} + +func retrieveRegionMiddleware(region *string) middleware.SerializeMiddleware { + return middleware.SerializeMiddlewareFunc( + "Test: Retrieve Region", + func(ctx context.Context, in middleware.SerializeInput, next middleware.SerializeHandler) (middleware.SerializeOutput, middleware.Metadata, error) { + *region = awsmiddleware.GetRegion(ctx) + + return next.HandleSerialize(ctx, in) + }, + ) +} + +var errCancelOperation = fmt.Errorf("Test: Canceling request") + +func addCancelRequestMiddleware() func(*middleware.Stack) error { + return func(stack *middleware.Stack) error { + return stack.Finalize.Add( + cancelRequestMiddleware(), + middleware.After, + ) + } +} + +// cancelRequestMiddleware creates a Smithy middleware that intercepts the request before sending and cancels it +func cancelRequestMiddleware() middleware.FinalizeMiddleware { + return middleware.FinalizeMiddlewareFunc( + "Test: Cancel Requests", + func(_ context.Context, in middleware.FinalizeInput, next middleware.FinalizeHandler) (middleware.FinalizeOutput, middleware.Metadata, error) { + return middleware.FinalizeOutput{}, middleware.Metadata{}, errCancelOperation + }) +} + +func fullTypeName(i interface{}) string { + return fullValueTypeName(reflect.ValueOf(i)) +} + +func fullValueTypeName(v reflect.Value) string { + if v.Kind() == reflect.Ptr { + return "*" + fullValueTypeName(reflect.Indirect(v)) + } + + requestType := v.Type() + return fmt.Sprintf("%s.%s", requestType.PkgPath(), requestType.Name()) +} + func generateSharedConfigFile(config configFile) string { var buf strings.Builder diff --git a/internal/service/guardduty/service_package_gen.go b/internal/service/guardduty/service_package_gen.go index d30127908b8..47d7826d9a2 100644 --- a/internal/service/guardduty/service_package_gen.go +++ b/internal/service/guardduty/service_package_gen.go @@ -5,6 +5,8 @@ package guardduty import ( "context" + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + guardduty_sdkv2 "github.com/aws/aws-sdk-go-v2/service/guardduty" aws_sdkv1 "github.com/aws/aws-sdk-go/aws" endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" @@ -132,6 +134,25 @@ func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*g return guardduty_sdkv1.New(sess.Copy(&cfg)), nil } +// NewClient returns a new AWS SDK for Go v2 client for this service package's AWS API. +func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*guardduty_sdkv2.Client, error) { + cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) + + return guardduty_sdkv2.NewFromConfig(cfg, func(o *guardduty_sdkv2.Options) { + if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + o.BaseEndpoint = aws_sdkv2.String(endpoint) + + if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled + } + } + }), nil +} + func ServicePackage(ctx context.Context) conns.ServicePackage { return &servicePackage{} } diff --git a/internal/service/guardduty/tagsv2_gen.go b/internal/service/guardduty/tagsv2_gen.go new file mode 100644 index 00000000000..b44768da286 --- /dev/null +++ b/internal/service/guardduty/tagsv2_gen.go @@ -0,0 +1,40 @@ +// Code generated by internal/generate/tags/main.go; DO NOT EDIT. +package guardduty + +import ( + "context" + + tftags "github.com/hashicorp/terraform-provider-aws/internal/tags" + "github.com/hashicorp/terraform-provider-aws/internal/types/option" +) + +// map[string]string handling + +// TagsV2 returns guardduty service tags. +func TagsV2(tags tftags.KeyValueTags) map[string]string { + return tags.Map() +} + +// keyValueTagsV2 creates tftags.KeyValueTags from guardduty service tags. +func keyValueTagsV2(ctx context.Context, tags map[string]string) tftags.KeyValueTags { + return tftags.New(ctx, tags) +} + +// getTagsInV2 returns guardduty service tags from Context. +// nil is returned if there are no input tags. +func getTagsInV2(ctx context.Context) map[string]string { + if inContext, ok := tftags.FromContext(ctx); ok { + if tags := TagsV2(inContext.TagsIn.UnwrapOrDefault()); len(tags) > 0 { + return tags + } + } + + return nil +} + +// setTagsOutV2 sets guardduty service tags in Context. +func setTagsOutV2(ctx context.Context, tags map[string]string) { + if inContext, ok := tftags.FromContext(ctx); ok { + inContext.TagsOut = option.Some(keyValueTagsV2(ctx, tags)) + } +} From a9aa38e1ef95764c7bd5d4c24a8070b7c18368d9 Mon Sep 17 00:00:00 2001 From: GlennChia Date: Tue, 11 Jun 2024 08:21:39 +0000 Subject: [PATCH 05/25] feat(gd): malware protection plan schema --- .../guardduty/malware_protection_plan.go | 145 ++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 internal/service/guardduty/malware_protection_plan.go diff --git a/internal/service/guardduty/malware_protection_plan.go b/internal/service/guardduty/malware_protection_plan.go new file mode 100644 index 00000000000..cb86396550f --- /dev/null +++ b/internal/service/guardduty/malware_protection_plan.go @@ -0,0 +1,145 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package guardduty + +import ( + "context" + + awstypes "github.com/aws/aws-sdk-go-v2/service/guardduty/types" + "github.com/hashicorp/terraform-plugin-framework-timetypes/timetypes" + "github.com/hashicorp/terraform-plugin-framework-validators/listvalidator" + "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/listplanmodifier" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/setplanmodifier" + "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-provider-aws/internal/framework" + fwtypes "github.com/hashicorp/terraform-provider-aws/internal/framework/types" + tftags "github.com/hashicorp/terraform-provider-aws/internal/tags" + "github.com/hashicorp/terraform-provider-aws/names" +) + +const ( + ResNameMalwareProtectionPlan = "Malware Protection Plan" +) + +type resourceMalwareProtectionPlan struct { + framework.ResourceWithConfigure +} + +func (r *resourceMalwareProtectionPlan) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { + resp.TypeName = "aws_guardduty_malware_protection_plan" +} + +func (r *resourceMalwareProtectionPlan) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { + resp.Schema = schema.Schema{ + Attributes: map[string]schema.Attribute{ + "actions": schema.ListAttribute{ // proto5 Optional+Computed nested block. + CustomType: fwtypes.NewListNestedObjectTypeOf[actionsModel](ctx), + Optional: true, + Computed: true, + PlanModifiers: []planmodifier.List{ + listplanmodifier.UseStateForUnknown(), + }, + Validators: []validator.List{ + listvalidator.SizeAtMost(1), + }, + ElementType: types.ObjectType{ + AttrTypes: fwtypes.AttributeTypesMust[actionsModel](ctx), + }, + }, + names.AttrARN: framework.ARNAttributeComputedOnly(), + names.AttrCreatedAt: schema.StringAttribute{ + CustomType: timetypes.RFC3339Type{}, + Computed: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.UseStateForUnknown(), + }, + }, + names.AttrID: framework.IDAttribute(), + "role": schema.StringAttribute{ + CustomType: fwtypes.ARNType, + Required: true, + }, + names.AttrStatus: schema.StringAttribute{ + Computed: true, + }, + names.AttrTags: tftags.TagsAttribute(), + names.AttrTagsAll: tftags.TagsAttributeComputedOnly(), + }, + Blocks: map[string]schema.Block{ + "protected_resource": schema.ListNestedBlock{ + CustomType: fwtypes.NewListNestedObjectTypeOf[protectedResourceModel](ctx), + Validators: []validator.List{ + listvalidator.IsRequired(), + listvalidator.SizeAtLeast(1), + listvalidator.SizeAtMost(1), + }, + NestedObject: schema.NestedBlockObject{ + Blocks: map[string]schema.Block{ + "s3_bucket": schema.ListNestedBlock{ + CustomType: fwtypes.NewListNestedObjectTypeOf[s3BucketModel](ctx), + Validators: []validator.List{ + listvalidator.IsRequired(), + listvalidator.SizeAtLeast(1), + listvalidator.SizeAtMost(1), + }, + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "bucket_name": schema.StringAttribute{ + Required: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.RequiresReplace(), + }, + }, + "object_prefixes": schema.SetAttribute{ + CustomType: fwtypes.SetOfStringType, + ElementType: types.StringType, + Optional: true, + Computed: true, + PlanModifiers: []planmodifier.Set{ + setplanmodifier.UseStateForUnknown(), + }, + }, + }, + }, + }, + }, + }, + }, + }, + } +} + +type malwareProtectionPlanResourceModel struct { + Actions fwtypes.ListNestedObjectValueOf[actionsModel] `tfsdk:"actions"` + Arn types.String `tfsdk:"arn"` + CreatedAt timetypes.RFC3339 `tfsdk:"created_at"` + ID types.String `tfsdk:"id"` + ProtectedResource fwtypes.ListNestedObjectValueOf[protectedResourceModel] `tfsdk:"protected_resource"` + Role fwtypes.ARN `tfsdk:"role"` + Status types.String `tfsdk:"status"` + Tags types.Map `tfsdk:"tags"` + TagsAll types.Map `tfsdk:"tags_all"` +} + +type actionsModel struct { + Tagging fwtypes.ListNestedObjectValueOf[taggingModel] `tfsdk:"tagging"` +} + +type taggingModel struct { + Status fwtypes.StringEnum[awstypes.MalwareProtectionPlanTaggingActionStatus] `tfsdk:"status"` +} + +type protectedResourceModel struct { + S3Bucket fwtypes.ListNestedObjectValueOf[s3BucketModel] `tfsdk:"s3_bucket"` +} + +type s3BucketModel struct { + BucketName types.String `tfsdk:"bucket_name"` + ObjectPrefixes fwtypes.SetValueOf[types.String] `tfsdk:"object_prefixes"` +} From 08ce74696185949799ab970e17b1ac9790451a0b Mon Sep 17 00:00:00 2001 From: GlennChia Date: Tue, 11 Jun 2024 08:22:42 +0000 Subject: [PATCH 06/25] feat(gd): malware protection plan read --- internal/service/guardduty/find.go | 45 +++++++++++++++++++ .../guardduty/malware_protection_plan.go | 37 +++++++++++++++ 2 files changed, 82 insertions(+) create mode 100644 internal/service/guardduty/find.go diff --git a/internal/service/guardduty/find.go b/internal/service/guardduty/find.go new file mode 100644 index 00000000000..1d5457ab47e --- /dev/null +++ b/internal/service/guardduty/find.go @@ -0,0 +1,45 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package guardduty + +import ( + "context" + "errors" + + guardduty_v2 "github.com/aws/aws-sdk-go-v2/service/guardduty" + "github.com/aws/aws-sdk-go-v2/service/guardduty/types" + "github.com/aws/aws-sdk-go/aws" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" +) + +func FindMalwareProtectionPlanByID(ctx context.Context, conn *guardduty_v2.Client, id string) (*guardduty_v2.GetMalwareProtectionPlanOutput, error) { + input := &guardduty_v2.GetMalwareProtectionPlanInput{ + MalwareProtectionPlanId: aws.String(id), + } + + return FindMalwareProtectionPlan(ctx, conn, input) +} + +func FindMalwareProtectionPlan(ctx context.Context, conn *guardduty_v2.Client, input *guardduty_v2.GetMalwareProtectionPlanInput) (*guardduty_v2.GetMalwareProtectionPlanOutput, error) { + result, err := conn.GetMalwareProtectionPlan(ctx, input) + + if err != nil { + var nfe *types.ResourceNotFoundException + if errors.As(err, &nfe) { + return nil, &retry.NotFoundError{ + LastError: err, + LastRequest: input, + } + } + + return nil, err + } + + if result == nil { + return nil, tfresource.NewEmptyResultError(input) + } + + return result, nil +} diff --git a/internal/service/guardduty/malware_protection_plan.go b/internal/service/guardduty/malware_protection_plan.go index cb86396550f..a32c0b55d50 100644 --- a/internal/service/guardduty/malware_protection_plan.go +++ b/internal/service/guardduty/malware_protection_plan.go @@ -17,9 +17,12 @@ 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-provider-aws/internal/create" "github.com/hashicorp/terraform-provider-aws/internal/framework" + "github.com/hashicorp/terraform-provider-aws/internal/framework/flex" fwtypes "github.com/hashicorp/terraform-provider-aws/internal/framework/types" tftags "github.com/hashicorp/terraform-provider-aws/internal/tags" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" "github.com/hashicorp/terraform-provider-aws/names" ) @@ -115,6 +118,40 @@ func (r *resourceMalwareProtectionPlan) Schema(ctx context.Context, req resource } } +func (r *resourceMalwareProtectionPlan) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { + conn := r.Meta().GuardDutyClient(ctx) + var state malwareProtectionPlanResourceModel + + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + + if resp.Diagnostics.HasError() { + return + } + + out, err := FindMalwareProtectionPlanByID(ctx, conn, state.ID.ValueString()) + + if tfresource.NotFound(err) { + resp.State.RemoveResource(ctx) + return + } + + if err != nil { + resp.Diagnostics.AddError( + create.ProblemStandardMessage(names.GuardDuty, create.ErrActionSetting, ResNameMalwareProtectionPlan, state.ID.ValueString(), err), + err.Error(), + ) + return + } + + resp.Diagnostics.Append(flex.Flatten(ctx, out, &state)...) + + if resp.Diagnostics.HasError() { + return + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &state)...) +} + type malwareProtectionPlanResourceModel struct { Actions fwtypes.ListNestedObjectValueOf[actionsModel] `tfsdk:"actions"` Arn types.String `tfsdk:"arn"` From 93e411e8847f6ff1f809c4f709b9261fea3f8b83 Mon Sep 17 00:00:00 2001 From: GlennChia Date: Tue, 11 Jun 2024 08:23:55 +0000 Subject: [PATCH 07/25] feat(gd): malware protection plan create --- .../guardduty/malware_protection_plan.go | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/internal/service/guardduty/malware_protection_plan.go b/internal/service/guardduty/malware_protection_plan.go index a32c0b55d50..36d5c1e893a 100644 --- a/internal/service/guardduty/malware_protection_plan.go +++ b/internal/service/guardduty/malware_protection_plan.go @@ -5,7 +5,10 @@ package guardduty import ( "context" + "errors" + "time" + "github.com/aws/aws-sdk-go-v2/service/guardduty" awstypes "github.com/aws/aws-sdk-go-v2/service/guardduty/types" "github.com/hashicorp/terraform-plugin-framework-timetypes/timetypes" "github.com/hashicorp/terraform-plugin-framework-validators/listvalidator" @@ -17,6 +20,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-sdk/v2/helper/retry" "github.com/hashicorp/terraform-provider-aws/internal/create" "github.com/hashicorp/terraform-provider-aws/internal/framework" "github.com/hashicorp/terraform-provider-aws/internal/framework/flex" @@ -26,6 +30,8 @@ import ( "github.com/hashicorp/terraform-provider-aws/names" ) +const iamPropagationTimeout = 2 * time.Minute + const ( ResNameMalwareProtectionPlan = "Malware Protection Plan" ) @@ -118,6 +124,69 @@ func (r *resourceMalwareProtectionPlan) Schema(ctx context.Context, req resource } } +func (r *resourceMalwareProtectionPlan) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { + conn := r.Meta().GuardDutyClient(ctx) + var plan malwareProtectionPlanResourceModel + + resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) + + input := &guardduty.CreateMalwareProtectionPlanInput{} + resp.Diagnostics.Append(flex.Expand(ctx, plan, input)...) + + if resp.Diagnostics.HasError() { + return + } + + input.Tags = getTagsInV2(ctx) + + var out *guardduty.CreateMalwareProtectionPlanOutput + + err := tfresource.Retry(ctx, iamPropagationTimeout, func() *retry.RetryError { + var err error + out, err = conn.CreateMalwareProtectionPlan(ctx, input) + if err != nil { + var nfe *awstypes.ResourceNotFoundException + var bre *awstypes.BadRequestException // Error returned due to IAM eventual consistency + if errors.As(err, &nfe) { + return retry.RetryableError(err) + } else if errors.As(err, &bre) { + return retry.RetryableError(err) + } + return retry.NonRetryableError(err) + } + + return nil + }) + + if err != nil { + resp.Diagnostics.AddError( + create.ProblemStandardMessage(names.GuardDuty, create.ErrActionCreating, ResNameMalwareProtectionPlan, "malware protection", nil), + err.Error(), + ) + return + } + + state := plan + state.ID = flex.StringToFramework(ctx, out.MalwareProtectionPlanId) + + // Read after create to get computed attributes omitted from the create response + readOut, err := FindMalwareProtectionPlanByID(ctx, conn, state.ID.ValueString()) + if err != nil { + resp.Diagnostics.AddError( + create.ProblemStandardMessage(names.SSOAdmin, create.ErrActionCreating, ResNameMalwareProtectionPlan, plan.ID.String(), err), + err.Error(), + ) + return + } + resp.Diagnostics.Append(flex.Flatten(ctx, readOut, &state)...) + + if resp.Diagnostics.HasError() { + return + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &state)...) +} + func (r *resourceMalwareProtectionPlan) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { conn := r.Meta().GuardDutyClient(ctx) var state malwareProtectionPlanResourceModel From dc63939c078a0eb0ed8c7e08501b5ede1eeb19b9 Mon Sep 17 00:00:00 2001 From: GlennChia Date: Tue, 11 Jun 2024 08:24:38 +0000 Subject: [PATCH 08/25] feat(gd): malware protection plan update --- .../guardduty/malware_protection_plan.go | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/internal/service/guardduty/malware_protection_plan.go b/internal/service/guardduty/malware_protection_plan.go index 36d5c1e893a..625835020d1 100644 --- a/internal/service/guardduty/malware_protection_plan.go +++ b/internal/service/guardduty/malware_protection_plan.go @@ -221,6 +221,63 @@ func (r *resourceMalwareProtectionPlan) Read(ctx context.Context, req resource.R resp.Diagnostics.Append(resp.State.Set(ctx, &state)...) } +func (r *resourceMalwareProtectionPlan) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { + conn := r.Meta().GuardDutyClient(ctx) + var state, plan malwareProtectionPlanResourceModel + + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + + if resp.Diagnostics.HasError() { + return + } + + resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) + + if resp.Diagnostics.HasError() { + return + } + + if malwareProtectionPlanHasChanges(ctx, plan, state) { + input := &guardduty.UpdateMalwareProtectionPlanInput{} + + resp.Diagnostics.Append(flex.Expand(ctx, plan, input)...) + + if resp.Diagnostics.HasError() { + return + } + + input.MalwareProtectionPlanId = flex.StringFromFramework(ctx, state.ID) + + _, err := conn.UpdateMalwareProtectionPlan(ctx, input) + + if err != nil { + resp.Diagnostics.AddError( + create.ProblemStandardMessage(names.GuardDuty, create.ErrActionUpdating, ResNameMalwareProtectionPlan, state.ID.ValueString(), err), + err.Error(), + ) + return + } + } + + out, err := FindMalwareProtectionPlanByID(ctx, conn, state.ID.ValueString()) + + if err != nil { + resp.Diagnostics.AddError( + create.ProblemStandardMessage(names.GuardDuty, create.ErrActionUpdating, ResNameMalwareProtectionPlan, state.ID.ValueString(), err), + err.Error(), + ) + return + } + + resp.Diagnostics.Append(flex.Flatten(ctx, out, &plan)...) + + if resp.Diagnostics.HasError() { + return + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...) +} + type malwareProtectionPlanResourceModel struct { Actions fwtypes.ListNestedObjectValueOf[actionsModel] `tfsdk:"actions"` Arn types.String `tfsdk:"arn"` @@ -249,3 +306,9 @@ type s3BucketModel struct { BucketName types.String `tfsdk:"bucket_name"` ObjectPrefixes fwtypes.SetValueOf[types.String] `tfsdk:"object_prefixes"` } + +func malwareProtectionPlanHasChanges(_ context.Context, plan, state malwareProtectionPlanResourceModel) bool { + return !plan.Actions.Equal(state.Actions) || + !plan.ProtectedResource.Equal(state.ProtectedResource) || + !plan.Role.Equal(state.Role) +} From 83ee651f965195e485c863216ab82619e9e03d9e Mon Sep 17 00:00:00 2001 From: GlennChia Date: Tue, 11 Jun 2024 08:25:40 +0000 Subject: [PATCH 09/25] feat(gd): malware protection plan delete --- .../guardduty/malware_protection_plan.go | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/internal/service/guardduty/malware_protection_plan.go b/internal/service/guardduty/malware_protection_plan.go index 625835020d1..c7e78d27ab0 100644 --- a/internal/service/guardduty/malware_protection_plan.go +++ b/internal/service/guardduty/malware_protection_plan.go @@ -10,6 +10,7 @@ import ( "github.com/aws/aws-sdk-go-v2/service/guardduty" awstypes "github.com/aws/aws-sdk-go-v2/service/guardduty/types" + "github.com/aws/aws-sdk-go/aws" "github.com/hashicorp/terraform-plugin-framework-timetypes/timetypes" "github.com/hashicorp/terraform-plugin-framework-validators/listvalidator" "github.com/hashicorp/terraform-plugin-framework/resource" @@ -32,6 +33,14 @@ import ( const iamPropagationTimeout = 2 * time.Minute +// @FrameworkResource(name="Malware Protection Plan") +// @Tags(identifierAttribute="arn") +func newResourceMalwareProtectionPlan(_ context.Context) (resource.ResourceWithConfigure, error) { + r := &resourceMalwareProtectionPlan{} + + return r, nil +} + const ( ResNameMalwareProtectionPlan = "Malware Protection Plan" ) @@ -278,6 +287,30 @@ func (r *resourceMalwareProtectionPlan) Update(ctx context.Context, req resource resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...) } +func (r *resourceMalwareProtectionPlan) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { + conn := r.Meta().GuardDutyClient(ctx) + + var state malwareProtectionPlanResourceModel + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + + _, err := conn.DeleteMalwareProtectionPlan(ctx, &guardduty.DeleteMalwareProtectionPlanInput{ + MalwareProtectionPlanId: aws.String(state.ID.ValueString()), + }) + if err != nil { + var nfe *awstypes.ResourceNotFoundException + if errors.As(err, &nfe) { + return + } + resp.Diagnostics.AddError( + create.ProblemStandardMessage(names.GuardDuty, create.ErrActionDeleting, ResNameMalwareProtectionPlan, state.ID.String(), nil), + err.Error(), + ) + } +} + type malwareProtectionPlanResourceModel struct { Actions fwtypes.ListNestedObjectValueOf[actionsModel] `tfsdk:"actions"` Arn types.String `tfsdk:"arn"` From 39d2bb0f52ad1be14c8a79810874be067d7a3ff6 Mon Sep 17 00:00:00 2001 From: GlennChia Date: Tue, 11 Jun 2024 08:26:34 +0000 Subject: [PATCH 10/25] feat(gd): malware protection plan modify plan tags --- internal/service/guardduty/malware_protection_plan.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/internal/service/guardduty/malware_protection_plan.go b/internal/service/guardduty/malware_protection_plan.go index c7e78d27ab0..70211ad9b0a 100644 --- a/internal/service/guardduty/malware_protection_plan.go +++ b/internal/service/guardduty/malware_protection_plan.go @@ -311,6 +311,10 @@ func (r *resourceMalwareProtectionPlan) Delete(ctx context.Context, req resource } } +func (r *resourceMalwareProtectionPlan) ModifyPlan(ctx context.Context, req resource.ModifyPlanRequest, resp *resource.ModifyPlanResponse) { + r.SetTagsAll(ctx, req, resp) +} + type malwareProtectionPlanResourceModel struct { Actions fwtypes.ListNestedObjectValueOf[actionsModel] `tfsdk:"actions"` Arn types.String `tfsdk:"arn"` From 9593377ed6727041e683ab7d4348ee6aa77a257c Mon Sep 17 00:00:00 2001 From: GlennChia Date: Tue, 11 Jun 2024 08:28:04 +0000 Subject: [PATCH 11/25] feat(gd): malware protection plan import state --- internal/service/guardduty/malware_protection_plan.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/internal/service/guardduty/malware_protection_plan.go b/internal/service/guardduty/malware_protection_plan.go index 70211ad9b0a..deebb148fe1 100644 --- a/internal/service/guardduty/malware_protection_plan.go +++ b/internal/service/guardduty/malware_protection_plan.go @@ -13,6 +13,7 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/hashicorp/terraform-plugin-framework-timetypes/timetypes" "github.com/hashicorp/terraform-plugin-framework-validators/listvalidator" + "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/listplanmodifier" @@ -311,6 +312,10 @@ func (r *resourceMalwareProtectionPlan) Delete(ctx context.Context, req resource } } +func (r *resourceMalwareProtectionPlan) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { + resource.ImportStatePassthroughID(ctx, path.Root(names.AttrID), req, resp) +} + func (r *resourceMalwareProtectionPlan) ModifyPlan(ctx context.Context, req resource.ModifyPlanRequest, resp *resource.ModifyPlanResponse) { r.SetTagsAll(ctx, req, resp) } From 031b61f59ac8b27e19700ce84c4ace19b1462d5f Mon Sep 17 00:00:00 2001 From: GlennChia Date: Tue, 11 Jun 2024 08:28:39 +0000 Subject: [PATCH 12/25] build(gd): malware protection plan make gen --- internal/service/guardduty/service_package_gen.go | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/internal/service/guardduty/service_package_gen.go b/internal/service/guardduty/service_package_gen.go index 47d7826d9a2..c8f12f08eb1 100644 --- a/internal/service/guardduty/service_package_gen.go +++ b/internal/service/guardduty/service_package_gen.go @@ -29,7 +29,15 @@ func (p *servicePackage) FrameworkDataSources(ctx context.Context) []*types.Serv } func (p *servicePackage) FrameworkResources(ctx context.Context) []*types.ServicePackageFrameworkResource { - return []*types.ServicePackageFrameworkResource{} + return []*types.ServicePackageFrameworkResource{ + { + Factory: newResourceMalwareProtectionPlan, + Name: "Malware Protection Plan", + Tags: &types.ServicePackageResourceTags{ + IdentifierAttribute: names.AttrARN, + }, + }, + } } func (p *servicePackage) SDKDataSources(ctx context.Context) []*types.ServicePackageSDKDataSource { From a200ca6338e9c03ff1c8d48f0ead3d07c80bcf9e Mon Sep 17 00:00:00 2001 From: GlennChia Date: Tue, 11 Jun 2024 08:29:12 +0000 Subject: [PATCH 13/25] test(gd): malware protection plan exports test --- internal/service/guardduty/exports_test.go | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 internal/service/guardduty/exports_test.go diff --git a/internal/service/guardduty/exports_test.go b/internal/service/guardduty/exports_test.go new file mode 100644 index 00000000000..9364e8e88db --- /dev/null +++ b/internal/service/guardduty/exports_test.go @@ -0,0 +1,9 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package guardduty + +// Exports for use in tests only. +var ( + ResourceMalwareProtectionPlan = newResourceMalwareProtectionPlan +) From 474480ceb76b5861fe1ee62975d2401b4b8e0231 Mon Sep 17 00:00:00 2001 From: GlennChia Date: Tue, 11 Jun 2024 08:31:30 +0000 Subject: [PATCH 14/25] test(gd): malware protection plan basic --- .../guardduty/malware_protection_plan_test.go | 284 ++++++++++++++++++ 1 file changed, 284 insertions(+) create mode 100644 internal/service/guardduty/malware_protection_plan_test.go diff --git a/internal/service/guardduty/malware_protection_plan_test.go b/internal/service/guardduty/malware_protection_plan_test.go new file mode 100644 index 00000000000..bffb34baf11 --- /dev/null +++ b/internal/service/guardduty/malware_protection_plan_test.go @@ -0,0 +1,284 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package guardduty_test + +import ( + "context" + "errors" + "fmt" + "testing" + + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/guardduty" + awstypes "github.com/aws/aws-sdk-go-v2/service/guardduty/types" + sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/terraform" + "github.com/hashicorp/terraform-provider-aws/internal/acctest" + "github.com/hashicorp/terraform-provider-aws/internal/conns" + "github.com/hashicorp/terraform-provider-aws/internal/create" + tfguardduty "github.com/hashicorp/terraform-provider-aws/internal/service/guardduty" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" + "github.com/hashicorp/terraform-provider-aws/names" +) + +func TestAccGuardDutyMalwareProtectionPlan_basic(t *testing.T) { + ctx := acctest.Context(t) + + var malwareProtectionPlan guardduty.GetMalwareProtectionPlanOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_guardduty_malware_protection_plan.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + testAccPreCheck(ctx, t) + }, + ErrorCheck: acctest.ErrorCheck(t, names.GuardDutyServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckMalwareProtectionPlanDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccMalwareProtectionPlanConfig_basic(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckMalwareProtectionPlanExists(ctx, resourceName, &malwareProtectionPlan), + resource.TestCheckResourceAttrSet(resourceName, names.AttrARN), + resource.TestCheckResourceAttrSet(resourceName, names.AttrCreatedAt), + resource.TestCheckResourceAttrSet(resourceName, names.AttrID), + resource.TestCheckResourceAttrPair(resourceName, "role", "aws_iam_role.test", names.AttrARN), + resource.TestCheckResourceAttr(resourceName, "status", string(awstypes.MalwareProtectionPlanStatusActive)), + resource.TestCheckResourceAttr(resourceName, "actions.#", acctest.Ct1), + resource.TestCheckResourceAttr(resourceName, "actions.0.tagging.#", acctest.Ct1), + resource.TestCheckResourceAttr(resourceName, "actions.0.tagging.0.status", string(awstypes.MalwareProtectionPlanTaggingActionStatusDisabled)), + resource.TestCheckResourceAttr(resourceName, "protected_resource.#", acctest.Ct1), + resource.TestCheckResourceAttr(resourceName, "protected_resource.0.s3_bucket.#", acctest.Ct1), + resource.TestCheckResourceAttrPair(resourceName, "protected_resource.0.s3_bucket.0.bucket_name", "aws_s3_bucket.test", names.AttrID), + resource.TestCheckResourceAttr(resourceName, "protected_resource.0.s3_bucket.0.object_prefixes.#", acctest.Ct0), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{}, + }, + }, + }) +} + +func testAccCheckMalwareProtectionPlanDestroy(ctx context.Context) resource.TestCheckFunc { + return func(s *terraform.State) error { + conn := acctest.Provider.Meta().(*conns.AWSClient).GuardDutyClient(ctx) + + for _, rs := range s.RootModule().Resources { + if rs.Type != "aws_guardduty_malware_protection_plan" { + continue + } + + _, err := tfguardduty.FindMalwareProtectionPlanByID(ctx, conn, rs.Primary.ID) + + if tfresource.NotFound(err) { + continue + } + + if err != nil { + return create.Error(names.GuardDuty, create.ErrActionCheckingDestroyed, tfguardduty.ResNameMalwareProtectionPlan, rs.Primary.ID, err) + } + } + + return nil + } +} + +func testAccCheckMalwareProtectionPlanExists(ctx context.Context, name string, malwareProtectionPlan *guardduty.GetMalwareProtectionPlanOutput) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[name] + if !ok { + return create.Error(names.GuardDuty, create.ErrActionCheckingExistence, tfguardduty.ResNameMalwareProtectionPlan, name, errors.New("not found")) + } + + if rs.Primary.ID == "" { + return create.Error(names.GuardDuty, create.ErrActionCheckingExistence, tfguardduty.ResNameMalwareProtectionPlan, name, errors.New("not set")) + } + + conn := acctest.Provider.Meta().(*conns.AWSClient).GuardDutyClient(ctx) + resp, err := conn.GetMalwareProtectionPlan(ctx, &guardduty.GetMalwareProtectionPlanInput{ + MalwareProtectionPlanId: aws.String(rs.Primary.ID), + }) + + if err != nil { + return create.Error(names.GuardDuty, create.ErrActionCheckingExistence, tfguardduty.ResNameMalwareProtectionPlan, rs.Primary.ID, err) + } + + *malwareProtectionPlan = *resp + + return nil + } +} + +func testAccPreCheck(ctx context.Context, t *testing.T) { + conn := acctest.Provider.Meta().(*conns.AWSClient).GuardDutyClient(ctx) + + input := &guardduty.ListMalwareProtectionPlansInput{} + _, err := conn.ListMalwareProtectionPlans(ctx, input) + + if acctest.PreCheckSkipError(err) { + t.Skipf("skipping acceptance testing: %s", err) + } + if err != nil { + t.Fatalf("unexpected PreCheck error: %s", err) + } +} + +func testAccMalwareProtectionPlanConfigBase(rName string) string { + return fmt.Sprintf(` +data "aws_region" "current" {} +data "aws_caller_identity" "current" {} +data "aws_partition" "current" {} + +data "aws_iam_policy_document" "assume_role" { + statement { + actions = ["sts:AssumeRole"] + effect = "Allow" + + principals { + type = "Service" + identifiers = ["malware-protection-plan.guardduty.amazonaws.com"] + } + } +} + +data "aws_iam_policy_document" "test" { + statement { + sid = "AllowManagedRuleToSendS3EventsToGuardDuty" + actions = [ + "events:PutRule", + "events:DeleteRule", + "events:PutTargets", + "events:RemoveTargets" + ] + effect = "Allow" + resources = [ + "arn:${data.aws_partition.current.partition}:events:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:rule/DO-NOT-DELETE-AmazonGuardDutyMalwareProtectionS3*" + ] + + condition { + test = "StringLike" + variable = "events:ManagedBy" + + values = [ + "malware-protection-plan.guardduty.amazonaws.com" + ] + } + } + + statement { + sid = "AllowGuardDutyToMonitorEventBridgeManagedRule" + actions = [ + "events:DescribeRule", + "events:ListTargetsByRule" + ] + effect = "Allow" + resources = [ + "arn:${data.aws_partition.current.partition}:events:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:rule/DO-NOT-DELETE-AmazonGuardDutyMalwareProtectionS3*" + ] + } + + statement { + sid = "AllowPostScanTag" + actions = [ + // Customer bucket is versioned + "s3:PutObjectTagging", + "s3:GetObjectTagging", + // Customer bucket is not versioned + "s3:PutObjectVersionTagging", + "s3:GetObjectVersionTagging" + ] + effect = "Allow" + resources = [ + "${aws_s3_bucket.test.arn}/*" + ] + } + + statement { + sid = "AllowEnableS3EventBridgeEvents" + actions = [ + "s3:PutBucketNotification", + "s3:GetBucketNotification" + ] + effect = "Allow" + resources = [ + aws_s3_bucket.test.arn + ] + } + + statement { + sid = "AllowPutValidationObject" + actions = [ + "s3:PutObject" + ] + effect = "Allow" + resources = [ + "${aws_s3_bucket.test.arn}/malware-protection-resource-validation-object" + ] + } + + statement { + sid = "AllowCheckBucketOwnership" + actions = [ + "s3:ListBucket" + ] + effect = "Allow" + resources = [ + aws_s3_bucket.test.arn + ] + } + + statement { + sid = "AllowMalwareScan" + actions = [ + // Customer bucket is versioned + "s3:GetObject", + // Customer bucket is not versioned + "s3:GetObjectVersion" + ] + effect = "Allow" + resources = [ + "${aws_s3_bucket.test.arn}/*" + ] + } +} + +resource "aws_s3_bucket" "test" { + bucket = %[1]q + force_destroy = true +} + +resource "aws_iam_role" "test" { + name = %[1]q + assume_role_policy = data.aws_iam_policy_document.assume_role.json + + inline_policy { + name = %[1]q + policy = data.aws_iam_policy_document.test.json + } +} +`, rName) +} + +func testAccMalwareProtectionPlanConfig_basic(rName string) string { + return acctest.ConfigCompose( + testAccMalwareProtectionPlanConfigBase(rName), ` +resource "aws_guardduty_malware_protection_plan" "test" { + role = aws_iam_role.test.arn + + protected_resource { + s3_bucket { + bucket_name = aws_s3_bucket.test.id + } + } +} +`, + ) +} From 780c96caaa03be79126b42526a4cbc7ffdc4ee36 Mon Sep 17 00:00:00 2001 From: GlennChia Date: Tue, 11 Jun 2024 08:32:22 +0000 Subject: [PATCH 15/25] test(gd): malware protection plan role --- .../guardduty/malware_protection_plan_test.go | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/internal/service/guardduty/malware_protection_plan_test.go b/internal/service/guardduty/malware_protection_plan_test.go index bffb34baf11..40fdd21821a 100644 --- a/internal/service/guardduty/malware_protection_plan_test.go +++ b/internal/service/guardduty/malware_protection_plan_test.go @@ -67,6 +67,47 @@ func TestAccGuardDutyMalwareProtectionPlan_basic(t *testing.T) { }) } +func TestAccGuardDutyMalwareProtectionPlan_role(t *testing.T) { + ctx := acctest.Context(t) + + var malwareProtectionPlan guardduty.GetMalwareProtectionPlanOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + rName2 := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_guardduty_malware_protection_plan.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + testAccPreCheck(ctx, t) + }, + ErrorCheck: acctest.ErrorCheck(t, names.GuardDutyServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckMalwareProtectionPlanDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccMalwareProtectionPlanConfig_role(rName, rName2, "first"), + Check: resource.ComposeTestCheckFunc( + testAccCheckMalwareProtectionPlanExists(ctx, resourceName, &malwareProtectionPlan), + resource.TestCheckResourceAttrPair(resourceName, "role", "aws_iam_role.test", names.AttrARN), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{}, + }, + { + Config: testAccMalwareProtectionPlanConfig_role(rName, rName2, "second"), + Check: resource.ComposeTestCheckFunc( + testAccCheckMalwareProtectionPlanExists(ctx, resourceName, &malwareProtectionPlan), + resource.TestCheckResourceAttrPair(resourceName, "role", "aws_iam_role.test2", names.AttrARN), + ), + }, + }, + }) +} + func testAccCheckMalwareProtectionPlanDestroy(ctx context.Context) resource.TestCheckFunc { return func(s *terraform.State) error { conn := acctest.Provider.Meta().(*conns.AWSClient).GuardDutyClient(ctx) @@ -282,3 +323,34 @@ resource "aws_guardduty_malware_protection_plan" "test" { `, ) } + +func testAccMalwareProtectionPlanConfig_role(rName, rName2, selectRole string) string { + return acctest.ConfigCompose( + testAccMalwareProtectionPlanConfigBase(rName), + fmt.Sprintf(` +locals { + select_role = %[2]q +} + +resource "aws_iam_role" "test2" { + name = %[1]q + assume_role_policy = data.aws_iam_policy_document.assume_role.json + + inline_policy { + name = %[1]q + policy = data.aws_iam_policy_document.test.json + } +} + +resource "aws_guardduty_malware_protection_plan" "test" { + role = local.select_role == "first" ? aws_iam_role.test.arn : aws_iam_role.test2.arn + + protected_resource { + s3_bucket { + bucket_name = aws_s3_bucket.test.id + } + } +} +`, rName2, selectRole), + ) +} From 07e171d1dbc3e66e3c6027047c42402d7d684cb9 Mon Sep 17 00:00:00 2001 From: GlennChia Date: Tue, 11 Jun 2024 08:34:24 +0000 Subject: [PATCH 16/25] test(gd): malware protection plan tagging status --- .../guardduty/malware_protection_plan_test.go | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/internal/service/guardduty/malware_protection_plan_test.go b/internal/service/guardduty/malware_protection_plan_test.go index 40fdd21821a..863360f0882 100644 --- a/internal/service/guardduty/malware_protection_plan_test.go +++ b/internal/service/guardduty/malware_protection_plan_test.go @@ -108,6 +108,53 @@ func TestAccGuardDutyMalwareProtectionPlan_role(t *testing.T) { }) } +func TestAccGuardDutyMalwareProtectionPlan_actionsTaggingStatus(t *testing.T) { + ctx := acctest.Context(t) + + var malwareProtectionPlan guardduty.GetMalwareProtectionPlanOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_guardduty_malware_protection_plan.test" + + originalStatus := string(awstypes.MalwareProtectionPlanTaggingActionStatusDisabled) + updatedStatus := string(awstypes.MalwareProtectionPlanTaggingActionStatusEnabled) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + testAccPreCheck(ctx, t) + }, + ErrorCheck: acctest.ErrorCheck(t, names.GuardDutyServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckMalwareProtectionPlanDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccMalwareProtectionPlanConfig_actionsTaggingStatus(rName, originalStatus), + Check: resource.ComposeTestCheckFunc( + testAccCheckMalwareProtectionPlanExists(ctx, resourceName, &malwareProtectionPlan), + resource.TestCheckResourceAttr(resourceName, "actions.#", acctest.Ct1), + resource.TestCheckResourceAttr(resourceName, "actions.0.tagging.#", acctest.Ct1), + resource.TestCheckResourceAttr(resourceName, "actions.0.tagging.0.status", originalStatus), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{}, + }, + { + Config: testAccMalwareProtectionPlanConfig_actionsTaggingStatus(rName, updatedStatus), + Check: resource.ComposeTestCheckFunc( + testAccCheckMalwareProtectionPlanExists(ctx, resourceName, &malwareProtectionPlan), + resource.TestCheckResourceAttr(resourceName, "actions.#", acctest.Ct1), + resource.TestCheckResourceAttr(resourceName, "actions.0.tagging.#", acctest.Ct1), + resource.TestCheckResourceAttr(resourceName, "actions.0.tagging.0.status", updatedStatus), + ), + }, + }, + }) +} + func testAccCheckMalwareProtectionPlanDestroy(ctx context.Context) resource.TestCheckFunc { return func(s *terraform.State) error { conn := acctest.Provider.Meta().(*conns.AWSClient).GuardDutyClient(ctx) @@ -354,3 +401,26 @@ resource "aws_guardduty_malware_protection_plan" "test" { `, rName2, selectRole), ) } + +func testAccMalwareProtectionPlanConfig_actionsTaggingStatus(rName, status string) string { + return acctest.ConfigCompose( + testAccMalwareProtectionPlanConfigBase(rName), + fmt.Sprintf(` +resource "aws_guardduty_malware_protection_plan" "test" { + role = aws_iam_role.test.arn + + protected_resource { + s3_bucket { + bucket_name = aws_s3_bucket.test.id + } + } + + actions { + tagging { + status = %[1]q + } + } +} +`, status), + ) +} From ef16d4926e397610d31ea8b47c56b3c94333be32 Mon Sep 17 00:00:00 2001 From: GlennChia Date: Tue, 11 Jun 2024 08:35:32 +0000 Subject: [PATCH 17/25] test(gd): malware protection plan prot bucket name --- .../guardduty/malware_protection_plan_test.go | 198 ++++++++++++++++++ 1 file changed, 198 insertions(+) diff --git a/internal/service/guardduty/malware_protection_plan_test.go b/internal/service/guardduty/malware_protection_plan_test.go index 863360f0882..e5323cc20cb 100644 --- a/internal/service/guardduty/malware_protection_plan_test.go +++ b/internal/service/guardduty/malware_protection_plan_test.go @@ -155,6 +155,57 @@ func TestAccGuardDutyMalwareProtectionPlan_actionsTaggingStatus(t *testing.T) { }) } +func TestAccGuardDutyMalwareProtectionPlan_protectedResourceS3BucketName(t *testing.T) { + ctx := acctest.Context(t) + + var malwareProtectionPlanV1, malwareProtectionPlanV2 guardduty.GetMalwareProtectionPlanOutput + + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + rName2 := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_guardduty_malware_protection_plan.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + testAccPreCheck(ctx, t) + }, + ErrorCheck: acctest.ErrorCheck(t, names.GuardDutyServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckMalwareProtectionPlanDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccMalwareProtectionPlanConfig_protectedResourceS3BucketName(rName, rName2, "first"), + Check: resource.ComposeTestCheckFunc( + testAccCheckMalwareProtectionPlanExists(ctx, resourceName, &malwareProtectionPlanV1), + resource.TestCheckResourceAttrPair(resourceName, "role", "aws_iam_role.test", names.AttrARN), + resource.TestCheckResourceAttr(resourceName, "protected_resource.#", acctest.Ct1), + resource.TestCheckResourceAttr(resourceName, "protected_resource.0.s3_bucket.#", acctest.Ct1), + resource.TestCheckResourceAttrPair(resourceName, "protected_resource.0.s3_bucket.0.bucket_name", "aws_s3_bucket.test", names.AttrID), + resource.TestCheckResourceAttr(resourceName, "protected_resource.0.s3_bucket.0.object_prefixes.#", acctest.Ct0), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{}, + }, + { + Config: testAccMalwareProtectionPlanConfig_protectedResourceS3BucketName(rName, rName2, "second"), + Check: resource.ComposeTestCheckFunc( + testAccCheckMalwareProtectionPlanExists(ctx, resourceName, &malwareProtectionPlanV2), + testAccCheckMalwareProtectionPlanRecreated(&malwareProtectionPlanV1, &malwareProtectionPlanV2), + resource.TestCheckResourceAttrPair(resourceName, "role", "aws_iam_role.test2", names.AttrARN), + resource.TestCheckResourceAttr(resourceName, "protected_resource.#", acctest.Ct1), + resource.TestCheckResourceAttr(resourceName, "protected_resource.0.s3_bucket.#", acctest.Ct1), + resource.TestCheckResourceAttrPair(resourceName, "protected_resource.0.s3_bucket.0.bucket_name", "aws_s3_bucket.test2", names.AttrID), + resource.TestCheckResourceAttr(resourceName, "protected_resource.0.s3_bucket.0.object_prefixes.#", acctest.Ct0), + ), + }, + }, + }) +} + func testAccCheckMalwareProtectionPlanDestroy(ctx context.Context) resource.TestCheckFunc { return func(s *terraform.State) error { conn := acctest.Provider.Meta().(*conns.AWSClient).GuardDutyClient(ctx) @@ -205,6 +256,16 @@ func testAccCheckMalwareProtectionPlanExists(ctx context.Context, name string, m } } +func testAccCheckMalwareProtectionPlanRecreated(before, after *guardduty.GetMalwareProtectionPlanOutput) resource.TestCheckFunc { + return func(s *terraform.State) error { + if before, after := aws.ToString(before.Arn), aws.ToString(after.Arn); before == after { + return fmt.Errorf("Malware Protection Plan (%s) not recreated", before) + } + + return nil + } +} + func testAccPreCheck(ctx context.Context, t *testing.T) { conn := acctest.Provider.Meta().(*conns.AWSClient).GuardDutyClient(ctx) @@ -424,3 +485,140 @@ resource "aws_guardduty_malware_protection_plan" "test" { `, status), ) } + +func testAccMalwareProtectionPlanConfig_protectedResourceS3BucketName(rName, rName2, selectBucket string) string { + return acctest.ConfigCompose( + testAccMalwareProtectionPlanConfigBase(rName), + fmt.Sprintf(` +locals { + select_bucket = %[2]q +} + +data "aws_iam_policy_document" "test2" { + statement { + sid = "AllowManagedRuleToSendS3EventsToGuardDuty" + actions = [ + "events:PutRule", + "events:DeleteRule", + "events:PutTargets", + "events:RemoveTargets" + ] + effect = "Allow" + resources = [ + "arn:${data.aws_partition.current.partition}:events:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:rule/DO-NOT-DELETE-AmazonGuardDutyMalwareProtectionS3*" + ] + + condition { + test = "StringLike" + variable = "events:ManagedBy" + + values = [ + "malware-protection-plan.guardduty.amazonaws.com" + ] + } + } + + statement { + sid = "AllowGuardDutyToMonitorEventBridgeManagedRule" + actions = [ + "events:DescribeRule", + "events:ListTargetsByRule" + ] + effect = "Allow" + resources = [ + "arn:${data.aws_partition.current.partition}:events:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:rule/DO-NOT-DELETE-AmazonGuardDutyMalwareProtectionS3*" + ] + } + + statement { + sid = "AllowPostScanTag" + actions = [ + // Customer bucket is versioned + "s3:PutObjectTagging", + "s3:GetObjectTagging", + // Customer bucket is not versioned + "s3:PutObjectVersionTagging", + "s3:GetObjectVersionTagging" + ] + effect = "Allow" + resources = [ + "${aws_s3_bucket.test2.arn}/*" + ] + } + + statement { + sid = "AllowEnableS3EventBridgeEvents" + actions = [ + "s3:PutBucketNotification", + "s3:GetBucketNotification" + ] + effect = "Allow" + resources = [ + aws_s3_bucket.test2.arn + ] + } + + statement { + sid = "AllowPutValidationObject" + actions = [ + "s3:PutObject" + ] + effect = "Allow" + resources = [ + "${aws_s3_bucket.test2.arn}/malware-protection-resource-validation-object" + ] + } + + statement { + sid = "AllowCheckBucketOwnership" + actions = [ + "s3:ListBucket" + ] + effect = "Allow" + resources = [ + aws_s3_bucket.test2.arn + ] + } + + statement { + sid = "AllowMalwareScan" + actions = [ + // Customer bucket is versioned + "s3:GetObject", + // Customer bucket is not versioned + "s3:GetObjectVersion" + ] + effect = "Allow" + resources = [ + "${aws_s3_bucket.test2.arn}/*" + ] + } +} + +resource "aws_s3_bucket" "test2" { + bucket = %[1]q + force_destroy = true +} + +resource "aws_iam_role" "test2" { + name = %[1]q + assume_role_policy = data.aws_iam_policy_document.assume_role.json + + inline_policy { + name = %[1]q + policy = data.aws_iam_policy_document.test2.json + } +} + +resource "aws_guardduty_malware_protection_plan" "test" { + role = local.select_bucket == "first" ? aws_iam_role.test.arn : aws_iam_role.test2.arn + + protected_resource { + s3_bucket { + bucket_name = local.select_bucket == "first" ? aws_s3_bucket.test.id : aws_s3_bucket.test2.id + } + } +} +`, rName2, selectBucket), + ) +} From c328a45fc3c10a11b5c560970d11ef0476fd3177 Mon Sep 17 00:00:00 2001 From: GlennChia Date: Tue, 11 Jun 2024 08:36:32 +0000 Subject: [PATCH 18/25] test(gd): malware protection plan prot obj prefix --- .../guardduty/malware_protection_plan_test.go | 119 ++++++++++++++++++ 1 file changed, 119 insertions(+) diff --git a/internal/service/guardduty/malware_protection_plan_test.go b/internal/service/guardduty/malware_protection_plan_test.go index e5323cc20cb..f9fc3a048a6 100644 --- a/internal/service/guardduty/malware_protection_plan_test.go +++ b/internal/service/guardduty/malware_protection_plan_test.go @@ -206,6 +206,72 @@ func TestAccGuardDutyMalwareProtectionPlan_protectedResourceS3BucketName(t *test }) } +func TestAccGuardDutyMalwareProtectionPlan_protectedResourceS3BucketObjectPrefix(t *testing.T) { + ctx := acctest.Context(t) + + var malwareProtectionPlan guardduty.GetMalwareProtectionPlanOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_guardduty_malware_protection_plan.test" + + firstObjectPrefixOriginal := "first-original" + firstObjectPrefixUpdated := "first-updated" + secondObjectPrefixOriginal := "second-original" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + testAccPreCheck(ctx, t) + }, + ErrorCheck: acctest.ErrorCheck(t, names.GuardDutyServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckMalwareProtectionPlanDestroy(ctx), + Steps: []resource.TestStep{ + { + // Test create with single object prefix + Config: testAccMalwareProtectionPlanConfig_protectedResourceS3BucketObjectPrefixesOne(rName, firstObjectPrefixOriginal), + Check: resource.ComposeTestCheckFunc( + testAccCheckMalwareProtectionPlanExists(ctx, resourceName, &malwareProtectionPlan), + resource.TestCheckResourceAttr(resourceName, "protected_resource.#", acctest.Ct1), + resource.TestCheckResourceAttr(resourceName, "protected_resource.0.s3_bucket.#", acctest.Ct1), + resource.TestCheckResourceAttrPair(resourceName, "protected_resource.0.s3_bucket.0.bucket_name", "aws_s3_bucket.test", names.AttrID), + resource.TestCheckResourceAttr(resourceName, "protected_resource.0.s3_bucket.0.object_prefixes.#", acctest.Ct1), + resource.TestCheckTypeSetElemAttr(resourceName, "protected_resource.0.s3_bucket.0.object_prefixes.*", firstObjectPrefixOriginal), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{}, + }, + { + // Test updating the first original value and introducing a new value + Config: testAccMalwareProtectionPlanConfig_protectedResourceS3BucketObjectPrefixesTwo(rName, firstObjectPrefixUpdated, secondObjectPrefixOriginal), + Check: resource.ComposeTestCheckFunc( + testAccCheckMalwareProtectionPlanExists(ctx, resourceName, &malwareProtectionPlan), + resource.TestCheckResourceAttr(resourceName, "protected_resource.#", acctest.Ct1), + resource.TestCheckResourceAttr(resourceName, "protected_resource.0.s3_bucket.#", acctest.Ct1), + resource.TestCheckResourceAttrPair(resourceName, "protected_resource.0.s3_bucket.0.bucket_name", "aws_s3_bucket.test", names.AttrID), + resource.TestCheckResourceAttr(resourceName, "protected_resource.0.s3_bucket.0.object_prefixes.#", acctest.Ct2), + resource.TestCheckTypeSetElemAttr(resourceName, "protected_resource.0.s3_bucket.0.object_prefixes.*", firstObjectPrefixUpdated), + resource.TestCheckTypeSetElemAttr(resourceName, "protected_resource.0.s3_bucket.0.object_prefixes.*", secondObjectPrefixOriginal), + ), + }, + { + // Test removal of all object prefixes + Config: testAccMalwareProtectionPlanConfig_protectedResourceS3BucketObjectPrefixesZero(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckMalwareProtectionPlanExists(ctx, resourceName, &malwareProtectionPlan), + resource.TestCheckResourceAttr(resourceName, "protected_resource.#", acctest.Ct1), + resource.TestCheckResourceAttr(resourceName, "protected_resource.0.s3_bucket.#", acctest.Ct1), + resource.TestCheckResourceAttrPair(resourceName, "protected_resource.0.s3_bucket.0.bucket_name", "aws_s3_bucket.test", names.AttrID), + resource.TestCheckResourceAttr(resourceName, "protected_resource.0.s3_bucket.0.object_prefixes.#", acctest.Ct0), + ), + }, + }, + }) +} + func testAccCheckMalwareProtectionPlanDestroy(ctx context.Context) resource.TestCheckFunc { return func(s *terraform.State) error { conn := acctest.Provider.Meta().(*conns.AWSClient).GuardDutyClient(ctx) @@ -622,3 +688,56 @@ resource "aws_guardduty_malware_protection_plan" "test" { `, rName2, selectBucket), ) } + +func testAccMalwareProtectionPlanConfig_protectedResourceS3BucketObjectPrefixesOne(rName, objectPrefixValue string) string { + return acctest.ConfigCompose( + testAccMalwareProtectionPlanConfigBase(rName), + fmt.Sprintf(` +resource "aws_guardduty_malware_protection_plan" "test" { + role = aws_iam_role.test.arn + + protected_resource { + s3_bucket { + bucket_name = aws_s3_bucket.test.id + object_prefixes = [%[1]q] + } + } +} +`, objectPrefixValue), + ) +} + +func testAccMalwareProtectionPlanConfig_protectedResourceS3BucketObjectPrefixesTwo(rName, objectPrefixValue1, objectPrefixValue2 string) string { + return acctest.ConfigCompose( + testAccMalwareProtectionPlanConfigBase(rName), + fmt.Sprintf(` +resource "aws_guardduty_malware_protection_plan" "test" { + role = aws_iam_role.test.arn + + protected_resource { + s3_bucket { + bucket_name = aws_s3_bucket.test.id + object_prefixes = [%[1]q, %[2]q] + } + } +} +`, objectPrefixValue1, objectPrefixValue2), + ) +} + +func testAccMalwareProtectionPlanConfig_protectedResourceS3BucketObjectPrefixesZero(rName string) string { + return acctest.ConfigCompose( + testAccMalwareProtectionPlanConfigBase(rName), ` +resource "aws_guardduty_malware_protection_plan" "test" { + role = aws_iam_role.test.arn + + protected_resource { + s3_bucket { + bucket_name = aws_s3_bucket.test.id + object_prefixes = [] + } + } +} +`, + ) +} From 348fa951f682b1020ec7d7b2dc1e43e64a8d6dad Mon Sep 17 00:00:00 2001 From: GlennChia Date: Tue, 11 Jun 2024 08:37:00 +0000 Subject: [PATCH 19/25] test(gd): malware protection plan prot disappears --- .../guardduty/malware_protection_plan_test.go | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/internal/service/guardduty/malware_protection_plan_test.go b/internal/service/guardduty/malware_protection_plan_test.go index f9fc3a048a6..1cc219b308b 100644 --- a/internal/service/guardduty/malware_protection_plan_test.go +++ b/internal/service/guardduty/malware_protection_plan_test.go @@ -272,6 +272,34 @@ func TestAccGuardDutyMalwareProtectionPlan_protectedResourceS3BucketObjectPrefix }) } +func TestAccGuardDutyMalwareProtectionPlan_disappears(t *testing.T) { + ctx := acctest.Context(t) + + var malwareProtectionPlan guardduty.GetMalwareProtectionPlanOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_guardduty_malware_protection_plan.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + testAccPreCheck(ctx, t) + }, + ErrorCheck: acctest.ErrorCheck(t, names.GuardDutyServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckMalwareProtectionPlanDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccMalwareProtectionPlanConfig_basic(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckMalwareProtectionPlanExists(ctx, resourceName, &malwareProtectionPlan), + acctest.CheckFrameworkResourceDisappears(ctx, acctest.Provider, tfguardduty.ResourceMalwareProtectionPlan, resourceName), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + func testAccCheckMalwareProtectionPlanDestroy(ctx context.Context) resource.TestCheckFunc { return func(s *terraform.State) error { conn := acctest.Provider.Meta().(*conns.AWSClient).GuardDutyClient(ctx) From eb0cc5e31488878dce4c0120970a49c72ead7062 Mon Sep 17 00:00:00 2001 From: GlennChia Date: Tue, 11 Jun 2024 08:37:19 +0000 Subject: [PATCH 20/25] test(gd): malware protection plan prot tags --- .../guardduty/malware_protection_plan_test.go | 93 +++++++++++++++++++ 1 file changed, 93 insertions(+) diff --git a/internal/service/guardduty/malware_protection_plan_test.go b/internal/service/guardduty/malware_protection_plan_test.go index 1cc219b308b..cbf095214fe 100644 --- a/internal/service/guardduty/malware_protection_plan_test.go +++ b/internal/service/guardduty/malware_protection_plan_test.go @@ -300,6 +300,56 @@ func TestAccGuardDutyMalwareProtectionPlan_disappears(t *testing.T) { }) } +func TestAccGuardDutyMalwareProtectionPlan_tags(t *testing.T) { + ctx := acctest.Context(t) + + var malwareProtectionPlan guardduty.GetMalwareProtectionPlanOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_guardduty_malware_protection_plan.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + testAccPreCheck(ctx, t) + }, + ErrorCheck: acctest.ErrorCheck(t, names.GuardDutyServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckMalwareProtectionPlanDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccMalwareProtectionPlanConfig_tags(rName, acctest.CtKey1, acctest.CtValue1), + Check: resource.ComposeTestCheckFunc( + testAccCheckMalwareProtectionPlanExists(ctx, resourceName, &malwareProtectionPlan), + resource.TestCheckResourceAttr(resourceName, acctest.CtTagsPercent, acctest.Ct1), + resource.TestCheckResourceAttr(resourceName, acctest.CtTagsKey1, acctest.CtValue1), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccMalwareProtectionPlanConfig_tags2(rName, acctest.CtKey1, acctest.CtValue1Updated, acctest.CtKey2, acctest.CtValue2), + Check: resource.ComposeTestCheckFunc( + testAccCheckMalwareProtectionPlanExists(ctx, resourceName, &malwareProtectionPlan), + resource.TestCheckResourceAttr(resourceName, acctest.CtTagsPercent, acctest.Ct2), + resource.TestCheckResourceAttr(resourceName, acctest.CtTagsKey1, acctest.CtValue1Updated), + resource.TestCheckResourceAttr(resourceName, acctest.CtTagsKey2, acctest.CtValue2), + ), + }, + { + Config: testAccMalwareProtectionPlanConfig_tags(rName, acctest.CtKey2, acctest.CtValue2), + Check: resource.ComposeTestCheckFunc( + testAccCheckMalwareProtectionPlanExists(ctx, resourceName, &malwareProtectionPlan), + resource.TestCheckResourceAttr(resourceName, acctest.CtTagsPercent, acctest.Ct1), + resource.TestCheckResourceAttr(resourceName, acctest.CtTagsKey2, acctest.CtValue2), + ), + }, + }, + }) +} + func testAccCheckMalwareProtectionPlanDestroy(ctx context.Context) resource.TestCheckFunc { return func(s *terraform.State) error { conn := acctest.Provider.Meta().(*conns.AWSClient).GuardDutyClient(ctx) @@ -769,3 +819,46 @@ resource "aws_guardduty_malware_protection_plan" "test" { `, ) } + +func testAccMalwareProtectionPlanConfig_tags(rName, tagKey, tagValue string) string { + return acctest.ConfigCompose( + testAccMalwareProtectionPlanConfigBase(rName), + fmt.Sprintf(` +resource "aws_guardduty_malware_protection_plan" "test" { + role = aws_iam_role.test.arn + + protected_resource { + s3_bucket { + bucket_name = aws_s3_bucket.test.id + } + } + + tags = { + %[2]q = %[3]q + } +} +`, rName, tagKey, tagValue), + ) +} + +func testAccMalwareProtectionPlanConfig_tags2(rName, tagKey, tagValue, tagKey2, tagValue2 string) string { + return acctest.ConfigCompose( + testAccMalwareProtectionPlanConfigBase(rName), + fmt.Sprintf(` +resource "aws_guardduty_malware_protection_plan" "test" { + role = aws_iam_role.test.arn + + protected_resource { + s3_bucket { + bucket_name = aws_s3_bucket.test.id + } + } + + tags = { + %[2]q = %[3]q + %[4]q = %[5]q + } +} +`, rName, tagKey, tagValue, tagKey2, tagValue2), + ) +} From 4e045beca7f538f0b6796ffc58a22b5146d09e0b Mon Sep 17 00:00:00 2001 From: GlennChia Date: Tue, 11 Jun 2024 13:56:21 +0000 Subject: [PATCH 21/25] docs(gd): malware protection plan --- ...duty_malware_protection_plan.html.markdown | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 website/docs/r/guardduty_malware_protection_plan.html.markdown diff --git a/website/docs/r/guardduty_malware_protection_plan.html.markdown b/website/docs/r/guardduty_malware_protection_plan.html.markdown new file mode 100644 index 00000000000..55e153c5f54 --- /dev/null +++ b/website/docs/r/guardduty_malware_protection_plan.html.markdown @@ -0,0 +1,88 @@ +--- +subcategory: "GuardDuty" +layout: "aws" +page_title: "AWS: aws_guardduty_malware_protection_plan" +description: |- + Provides a resource to manage a GuardDuty Malware Protection Plan +--- + +# Resource: aws_guardduty_malware_protection_plan + +Provides a resource to manage a GuardDuty malware protection plan. + +## Example Usage + +```terraform +resource "aws_guardduty_malware_protection_plan" "example" { + role = aws_iam_role.example.arn + + protected_resource { + s3_bucket { + bucket_name = aws_s3_bucket.example.id + object_prefixes = ["example1", "example2"] + } + } + + actions { + tagging { + status = "ENABLED" + } + } + + tags = { + "Name" = "example" + } +} +``` + +## Argument Reference + +This resource supports the following arguments: + +* `actions` - (Optional) Information about whether the tags will be added to the S3 object after scanning. See [`actions`](#actions-argument-reference) below. +* `protected_resource` - (Required) Information about the protected resource that is associated with the created Malware Protection plan. Presently, S3Bucket is the only supported protected resource. See [`protected_resource`](#protected_resource-argument-reference) below. +* `role` - (Required) The IAM role that includes the permissions required to scan and add tags to the associated protected resource. +* `tags` - (Optional) Key-value mapping of resource tags. If configured with a provider [`default_tags` configuration block](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#default_tags-configuration-block) present, tags with matching keys will overwrite those defined at the provider-level. + +### `actions` argument reference + +* `tagging` - (Required) Indicates whether the scanned S3 object will have tags about the scan result. See [`tagging`](#tagging-argument-reference) below. + +#### `tagging` argument reference + +* `status` - (Required) Indicates whether or not the tags will added. Valid values are `DISABLED` and `ENABLED`. Defaults to `DISABLED` + +### `protected_resource` argument reference + +* `s3_bucket` - (Required) Information about the protected S3 bucket resource. See [`s3_bucket`](#s3_bucket-argument-reference) below. + +#### `s3_bucket` argument reference + +* `bucket_name` - (Required, Forces new resource) Name of the S3 bucket. +* `object_prefixes` - (Optional) The list of object prefixes that specify the S3 objects that will be scanned. + +## Attribute Reference + +This resource exports the following attributes in addition to the arguments above: + +* `arn` - The ARN of the GuardDuty malware protection plan +* `created_at` - The timestamp when the Malware Protection plan resource was created. +* `id` - The ID of the GuardDuty malware protection plan +* `status` - The GuardDuty malware protection plan status. Valid values are `ACTIVE`, `WARNING`, and `ERROR`. + +## Import + +In Terraform v1.5.0 and later, use an [`import` block](https://developer.hashicorp.com/terraform/language/import) to import GuardDuty malware protection plans using their IDs. For example: + +```terraform +import { + to = aws_guardduty_malware_protection_plan.example + id = "1234567890abcdef0123" +} +``` + +Using `terraform import`, import GuardDuty malware protection plans using their IDs. For example: + +```console +% terraform import aws_guardduty_malware_protection_plan.example 1234567890abcdef0123 +``` From 2e9f0a200abe84d14e5938e256a91f06b6af0f45 Mon Sep 17 00:00:00 2001 From: GlennChia Date: Tue, 11 Jun 2024 14:16:43 +0000 Subject: [PATCH 22/25] ci(gd): malware protection plan --- .changelog/37919.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/37919.txt diff --git a/.changelog/37919.txt b/.changelog/37919.txt new file mode 100644 index 00000000000..39fe7d8b3df --- /dev/null +++ b/.changelog/37919.txt @@ -0,0 +1,3 @@ +```release-note:new-resource +aws_guardduty_malware_protection_plan +``` \ No newline at end of file From e262fe23198b501b28c4a53e7dff438434fc7791 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Tue, 11 Jun 2024 14:39:01 -0700 Subject: [PATCH 23/25] go get github.com/aws/aws-sdk-go-v2/service/guardduty. --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 9ac49077d95..523184c08e1 100644 --- a/go.mod +++ b/go.mod @@ -100,7 +100,7 @@ require ( github.com/aws/aws-sdk-go-v2/service/glacier v1.22.10 github.com/aws/aws-sdk-go-v2/service/globalaccelerator v1.24.1 github.com/aws/aws-sdk-go-v2/service/groundstation v1.27.6 - github.com/aws/aws-sdk-go-v2/service/guardduty v1.42.6 + github.com/aws/aws-sdk-go-v2/service/guardduty v1.43.0 github.com/aws/aws-sdk-go-v2/service/healthlake v1.24.6 github.com/aws/aws-sdk-go-v2/service/iam v1.32.6 github.com/aws/aws-sdk-go-v2/service/identitystore v1.23.12 diff --git a/go.sum b/go.sum index f533a7f2fdc..22709fee68d 100644 --- a/go.sum +++ b/go.sum @@ -220,8 +220,8 @@ github.com/aws/aws-sdk-go-v2/service/globalaccelerator v1.24.1 h1:bDVYY5tSzBnLAc github.com/aws/aws-sdk-go-v2/service/globalaccelerator v1.24.1/go.mod h1:ct31bulbJED7Z4Vdtr+Jtvt6bPRB5PdeH96NNm4wkOc= github.com/aws/aws-sdk-go-v2/service/groundstation v1.27.6 h1:2GSPMCtOlEVwltVhqUT1x6CFKpFi/5D2yFhd/PqaSic= github.com/aws/aws-sdk-go-v2/service/groundstation v1.27.6/go.mod h1:gFFqhE7646BA034Im+oTpkfnefC1AR/E4ZUTs/sV7lc= -github.com/aws/aws-sdk-go-v2/service/guardduty v1.42.6 h1:pb3MeWCl9X97FMxorU4nftL1uiBo+cq5GNDTBMeZ+o4= -github.com/aws/aws-sdk-go-v2/service/guardduty v1.42.6/go.mod h1:tNfynl7aA5gEHA7yJZiEICHYMkITKSc0Z+vic+YpW0M= +github.com/aws/aws-sdk-go-v2/service/guardduty v1.43.0 h1:Jz/FJc/n27a9j1du1JxtBaMb/Wg/dSkWPbrfn2Y7CT4= +github.com/aws/aws-sdk-go-v2/service/guardduty v1.43.0/go.mod h1:tNfynl7aA5gEHA7yJZiEICHYMkITKSc0Z+vic+YpW0M= github.com/aws/aws-sdk-go-v2/service/healthlake v1.24.6 h1:AlmacWcocqb7vowwTlYtVR9AbYWW4vFExIoD7+kFR4g= github.com/aws/aws-sdk-go-v2/service/healthlake v1.24.6/go.mod h1:jp0Co1hHoXMEQTzyRICGBHvN8owh1QISx56d79dulFU= github.com/aws/aws-sdk-go-v2/service/iam v1.32.6 h1:NRlKKQ/BPHPqsuN2Hy6v4WA8/bsRTP0j8/BFPBC5+SU= From 211ca8aaca6edeeba07c20b73d5e88160c6341ad Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Tue, 11 Jun 2024 14:41:12 -0700 Subject: [PATCH 24/25] Run 'make clean-tidy'. --- tools/tfsdk2fw/go.mod | 1 + tools/tfsdk2fw/go.sum | 2 ++ 2 files changed, 3 insertions(+) diff --git a/tools/tfsdk2fw/go.mod b/tools/tfsdk2fw/go.mod index c492321e8bd..ae027f216de 100644 --- a/tools/tfsdk2fw/go.mod +++ b/tools/tfsdk2fw/go.mod @@ -117,6 +117,7 @@ require ( github.com/aws/aws-sdk-go-v2/service/glacier v1.22.10 // indirect github.com/aws/aws-sdk-go-v2/service/globalaccelerator v1.24.1 // indirect github.com/aws/aws-sdk-go-v2/service/groundstation v1.27.6 // indirect + github.com/aws/aws-sdk-go-v2/service/guardduty v1.43.0 // indirect github.com/aws/aws-sdk-go-v2/service/healthlake v1.24.6 // indirect github.com/aws/aws-sdk-go-v2/service/iam v1.32.6 // indirect github.com/aws/aws-sdk-go-v2/service/identitystore v1.23.12 // indirect diff --git a/tools/tfsdk2fw/go.sum b/tools/tfsdk2fw/go.sum index d004a336b98..686f367327f 100644 --- a/tools/tfsdk2fw/go.sum +++ b/tools/tfsdk2fw/go.sum @@ -220,6 +220,8 @@ github.com/aws/aws-sdk-go-v2/service/globalaccelerator v1.24.1 h1:bDVYY5tSzBnLAc github.com/aws/aws-sdk-go-v2/service/globalaccelerator v1.24.1/go.mod h1:ct31bulbJED7Z4Vdtr+Jtvt6bPRB5PdeH96NNm4wkOc= github.com/aws/aws-sdk-go-v2/service/groundstation v1.27.6 h1:2GSPMCtOlEVwltVhqUT1x6CFKpFi/5D2yFhd/PqaSic= github.com/aws/aws-sdk-go-v2/service/groundstation v1.27.6/go.mod h1:gFFqhE7646BA034Im+oTpkfnefC1AR/E4ZUTs/sV7lc= +github.com/aws/aws-sdk-go-v2/service/guardduty v1.43.0 h1:Jz/FJc/n27a9j1du1JxtBaMb/Wg/dSkWPbrfn2Y7CT4= +github.com/aws/aws-sdk-go-v2/service/guardduty v1.43.0/go.mod h1:tNfynl7aA5gEHA7yJZiEICHYMkITKSc0Z+vic+YpW0M= github.com/aws/aws-sdk-go-v2/service/healthlake v1.24.6 h1:AlmacWcocqb7vowwTlYtVR9AbYWW4vFExIoD7+kFR4g= github.com/aws/aws-sdk-go-v2/service/healthlake v1.24.6/go.mod h1:jp0Co1hHoXMEQTzyRICGBHvN8owh1QISx56d79dulFU= github.com/aws/aws-sdk-go-v2/service/iam v1.32.6 h1:NRlKKQ/BPHPqsuN2Hy6v4WA8/bsRTP0j8/BFPBC5+SU= From 3aa743e517d44853bcb40ba0bb0f55439e1022c9 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Tue, 11 Jun 2024 15:17:28 -0700 Subject: [PATCH 25/25] Run 'make fix-constants PKG=guardduty'. --- .../service/guardduty/malware_protection_plan.go | 8 ++++---- .../guardduty/malware_protection_plan_test.go | 12 ++++++------ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/internal/service/guardduty/malware_protection_plan.go b/internal/service/guardduty/malware_protection_plan.go index deebb148fe1..efe2773748f 100644 --- a/internal/service/guardduty/malware_protection_plan.go +++ b/internal/service/guardduty/malware_protection_plan.go @@ -57,7 +57,7 @@ func (r *resourceMalwareProtectionPlan) Metadata(_ context.Context, req resource func (r *resourceMalwareProtectionPlan) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { resp.Schema = schema.Schema{ Attributes: map[string]schema.Attribute{ - "actions": schema.ListAttribute{ // proto5 Optional+Computed nested block. + names.AttrActions: schema.ListAttribute{ // proto5 Optional+Computed nested block. CustomType: fwtypes.NewListNestedObjectTypeOf[actionsModel](ctx), Optional: true, Computed: true, @@ -80,7 +80,7 @@ func (r *resourceMalwareProtectionPlan) Schema(ctx context.Context, req resource }, }, names.AttrID: framework.IDAttribute(), - "role": schema.StringAttribute{ + names.AttrRole: schema.StringAttribute{ CustomType: fwtypes.ARNType, Required: true, }, @@ -100,7 +100,7 @@ func (r *resourceMalwareProtectionPlan) Schema(ctx context.Context, req resource }, NestedObject: schema.NestedBlockObject{ Blocks: map[string]schema.Block{ - "s3_bucket": schema.ListNestedBlock{ + names.AttrS3Bucket: schema.ListNestedBlock{ CustomType: fwtypes.NewListNestedObjectTypeOf[s3BucketModel](ctx), Validators: []validator.List{ listvalidator.IsRequired(), @@ -109,7 +109,7 @@ func (r *resourceMalwareProtectionPlan) Schema(ctx context.Context, req resource }, NestedObject: schema.NestedBlockObject{ Attributes: map[string]schema.Attribute{ - "bucket_name": schema.StringAttribute{ + names.AttrBucketName: schema.StringAttribute{ Required: true, PlanModifiers: []planmodifier.String{ stringplanmodifier.RequiresReplace(), diff --git a/internal/service/guardduty/malware_protection_plan_test.go b/internal/service/guardduty/malware_protection_plan_test.go index cbf095214fe..e1119109ffb 100644 --- a/internal/service/guardduty/malware_protection_plan_test.go +++ b/internal/service/guardduty/malware_protection_plan_test.go @@ -46,8 +46,8 @@ func TestAccGuardDutyMalwareProtectionPlan_basic(t *testing.T) { resource.TestCheckResourceAttrSet(resourceName, names.AttrARN), resource.TestCheckResourceAttrSet(resourceName, names.AttrCreatedAt), resource.TestCheckResourceAttrSet(resourceName, names.AttrID), - resource.TestCheckResourceAttrPair(resourceName, "role", "aws_iam_role.test", names.AttrARN), - resource.TestCheckResourceAttr(resourceName, "status", string(awstypes.MalwareProtectionPlanStatusActive)), + resource.TestCheckResourceAttrPair(resourceName, names.AttrRole, "aws_iam_role.test", names.AttrARN), + resource.TestCheckResourceAttr(resourceName, names.AttrStatus, string(awstypes.MalwareProtectionPlanStatusActive)), resource.TestCheckResourceAttr(resourceName, "actions.#", acctest.Ct1), resource.TestCheckResourceAttr(resourceName, "actions.0.tagging.#", acctest.Ct1), resource.TestCheckResourceAttr(resourceName, "actions.0.tagging.0.status", string(awstypes.MalwareProtectionPlanTaggingActionStatusDisabled)), @@ -88,7 +88,7 @@ func TestAccGuardDutyMalwareProtectionPlan_role(t *testing.T) { Config: testAccMalwareProtectionPlanConfig_role(rName, rName2, "first"), Check: resource.ComposeTestCheckFunc( testAccCheckMalwareProtectionPlanExists(ctx, resourceName, &malwareProtectionPlan), - resource.TestCheckResourceAttrPair(resourceName, "role", "aws_iam_role.test", names.AttrARN), + resource.TestCheckResourceAttrPair(resourceName, names.AttrRole, "aws_iam_role.test", names.AttrARN), ), }, { @@ -101,7 +101,7 @@ func TestAccGuardDutyMalwareProtectionPlan_role(t *testing.T) { Config: testAccMalwareProtectionPlanConfig_role(rName, rName2, "second"), Check: resource.ComposeTestCheckFunc( testAccCheckMalwareProtectionPlanExists(ctx, resourceName, &malwareProtectionPlan), - resource.TestCheckResourceAttrPair(resourceName, "role", "aws_iam_role.test2", names.AttrARN), + resource.TestCheckResourceAttrPair(resourceName, names.AttrRole, "aws_iam_role.test2", names.AttrARN), ), }, }, @@ -177,7 +177,7 @@ func TestAccGuardDutyMalwareProtectionPlan_protectedResourceS3BucketName(t *test Config: testAccMalwareProtectionPlanConfig_protectedResourceS3BucketName(rName, rName2, "first"), Check: resource.ComposeTestCheckFunc( testAccCheckMalwareProtectionPlanExists(ctx, resourceName, &malwareProtectionPlanV1), - resource.TestCheckResourceAttrPair(resourceName, "role", "aws_iam_role.test", names.AttrARN), + resource.TestCheckResourceAttrPair(resourceName, names.AttrRole, "aws_iam_role.test", names.AttrARN), resource.TestCheckResourceAttr(resourceName, "protected_resource.#", acctest.Ct1), resource.TestCheckResourceAttr(resourceName, "protected_resource.0.s3_bucket.#", acctest.Ct1), resource.TestCheckResourceAttrPair(resourceName, "protected_resource.0.s3_bucket.0.bucket_name", "aws_s3_bucket.test", names.AttrID), @@ -195,7 +195,7 @@ func TestAccGuardDutyMalwareProtectionPlan_protectedResourceS3BucketName(t *test Check: resource.ComposeTestCheckFunc( testAccCheckMalwareProtectionPlanExists(ctx, resourceName, &malwareProtectionPlanV2), testAccCheckMalwareProtectionPlanRecreated(&malwareProtectionPlanV1, &malwareProtectionPlanV2), - resource.TestCheckResourceAttrPair(resourceName, "role", "aws_iam_role.test2", names.AttrARN), + resource.TestCheckResourceAttrPair(resourceName, names.AttrRole, "aws_iam_role.test2", names.AttrARN), resource.TestCheckResourceAttr(resourceName, "protected_resource.#", acctest.Ct1), resource.TestCheckResourceAttr(resourceName, "protected_resource.0.s3_bucket.#", acctest.Ct1), resource.TestCheckResourceAttrPair(resourceName, "protected_resource.0.s3_bucket.0.bucket_name", "aws_s3_bucket.test2", names.AttrID),