From 931f43f6be81bcc65b693f66d2c7d09c3c53a969 Mon Sep 17 00:00:00 2001 From: Max Timchenko Date: Fri, 24 Sep 2021 11:25:31 +0300 Subject: [PATCH 01/31] fix: add validation of GuardDuty filter name This addresses issue #19893. --- aws/resource_aws_guardduty_filter.go | 6 +++++- website/docs/r/guardduty_filter.html.markdown | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/aws/resource_aws_guardduty_filter.go b/aws/resource_aws_guardduty_filter.go index 148b21092fb..b1881dd66dc 100644 --- a/aws/resource_aws_guardduty_filter.go +++ b/aws/resource_aws_guardduty_filter.go @@ -40,7 +40,11 @@ func resourceAwsGuardDutyFilter() *schema.Resource { Type: schema.TypeString, Required: true, ForceNew: true, - ValidateFunc: validation.StringLenBetween(3, 64), + validateFunc: validation.All( + validation.StringLenBetween(3, 64), + validation.StringMatch(regexp.MustCompile(`^[a-zA-Z0-9_.-]+$`), + "only alphanumeric characters, hyphens, underscores, and periods are allowed"), + ) }, "description": { Type: schema.TypeString, diff --git a/website/docs/r/guardduty_filter.html.markdown b/website/docs/r/guardduty_filter.html.markdown index 04d90a44f6a..00da7bd8364 100644 --- a/website/docs/r/guardduty_filter.html.markdown +++ b/website/docs/r/guardduty_filter.html.markdown @@ -49,7 +49,7 @@ resource "aws_guardduty_filter" "MyFilter" { The following arguments are supported: * `detector_id` - (Required) ID of a GuardDuty detector, attached to your account. -* `name` - (Required) The name of your filter. +* `name` - (Required) The name of your filter. Names can be between 3 and 64 characters long and the valid characters are a-z, A-Z, 0-9, '_' (underscore), '-' (hyphen), and '.' (period). * `description` - (Optional) Description of the filter. * `rank` - (Required) Specifies the position of the filter in the list of current filters. Also specifies the order in which this filter is applied to the findings. * `action` - (Required) Specifies the action that is to be applied to the findings that match the filter. Can be one of `ARCHIVE` or `NOOP`. From 399a61242f4171e6405133bdf493cd771501e812 Mon Sep 17 00:00:00 2001 From: Ringo De Smet Date: Thu, 18 May 2023 17:28:39 +0200 Subject: [PATCH 02/31] Support for features in GuardDuty Detector --- internal/service/guardduty/detector.go | 147 ++++++++++++++ internal/service/guardduty/detector_test.go | 194 +++++++++++++++---- internal/service/guardduty/guardduty_test.go | 1 + 3 files changed, 302 insertions(+), 40 deletions(-) diff --git a/internal/service/guardduty/detector.go b/internal/service/guardduty/detector.go index af7ae1899be..3a6b4d6a7f5 100644 --- a/internal/service/guardduty/detector.go +++ b/internal/service/guardduty/detector.go @@ -124,6 +124,40 @@ func ResourceDetector() *schema.Resource { }, }, + "features": { + Type: schema.TypeList, + Optional: true, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + }, + "enable": { + Type: schema.TypeBool, + Required: true, + }, + "additional_configuration": { + Optional: true, + Type: schema.TypeList, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + }, + "enable": { + Type: schema.TypeBool, + Required: true, + }, + }, + }, + }, + }, + }, + }, + "enable": { Type: schema.TypeBool, Optional: true, @@ -163,6 +197,10 @@ func resourceDetectorCreate(ctx context.Context, d *schema.ResourceData, meta in input.DataSources = expandDataSourceConfigurations(v.([]interface{})[0].(map[string]interface{})) } + if v, ok := d.GetOk("features"); ok && len(v.([]interface{})) > 0 { + input.Features = expandFeaturesConfigurations(v.([]interface{})) + } + log.Printf("[DEBUG] Creating GuardDuty Detector: %s", input) output, err := conn.CreateDetectorWithContext(ctx, &input) if err != nil { @@ -211,6 +249,14 @@ func resourceDetectorRead(ctx context.Context, d *schema.ResourceData, meta inte d.Set("datasources", nil) } + if gdo.Features != nil { + if err := d.Set("features", flattenFeaturesConfigurationsResult(gdo.Features)); err != nil { + return sdkdiag.AppendErrorf(diags, "setting features: %s", err) + } + } else { + d.Set("features", nil) + } + d.Set("enable", aws.StringValue(gdo.Status) == guardduty.DetectorStatusEnabled) d.Set("finding_publishing_frequency", gdo.FindingPublishingFrequency) @@ -234,6 +280,10 @@ func resourceDetectorUpdate(ctx context.Context, d *schema.ResourceData, meta in input.DataSources = expandDataSourceConfigurations(d.Get("datasources").([]interface{})[0].(map[string]interface{})) } + if d.HasChange("features") { + input.Features = expandFeaturesConfigurations(d.Get("features").([]interface{})) + } + log.Printf("[DEBUG] Update GuardDuty Detector: %s", input) _, err := conn.UpdateDetectorWithContext(ctx, &input) if err != nil { @@ -399,6 +449,71 @@ func expandMalwareProtectionEBSVolumesConfiguration(tfMap map[string]interface{} return apiObject } +func expandFeaturesConfigurations(items []interface{}) []*guardduty.DetectorFeatureConfiguration { + if items == nil { + return nil + } + + detectorFeatureConfigurations := make([]*guardduty.DetectorFeatureConfiguration, 0, len(items)) + for _, l := range items { + if l == nil { + continue + } + + m := l.(map[string]interface{}) + detectorFeatureConfiguration := &guardduty.DetectorFeatureConfiguration{ + Name: aws.String(m["name"].(string)), + } + if v, ok := m["enable"].(bool); ok { + if v { + enabled := guardduty.FeatureStatusEnabled + detectorFeatureConfiguration.Status = &enabled + } else { + disabled := guardduty.FeatureStatusDisabled + detectorFeatureConfiguration.Status = &disabled + } + } + if a, ok := m["additional_configuration"].([]interface{}); ok { + detectorFeatureConfiguration.AdditionalConfiguration = expandFeaturesAdditionalConfigurations(a) + } + + detectorFeatureConfigurations = append(detectorFeatureConfigurations, detectorFeatureConfiguration) + } + + return detectorFeatureConfigurations +} + +func expandFeaturesAdditionalConfigurations(items []interface{}) []*guardduty.DetectorAdditionalConfiguration { + if items == nil { + return nil + } + + detectorFeatureAdditionalConfigurations := make([]*guardduty.DetectorAdditionalConfiguration, 0, len(items)) + for _, l := range items { + if l == nil { + continue + } + + m := l.(map[string]interface{}) + detectorFeatureAdditionalConfiguration := &guardduty.DetectorAdditionalConfiguration{ + Name: aws.String(m["name"].(string)), + } + if v, ok := m["enable"].(bool); ok { + if v { + enabled := guardduty.FeatureStatusEnabled + detectorFeatureAdditionalConfiguration.Status = &enabled + } else { + disabled := guardduty.FeatureStatusDisabled + detectorFeatureAdditionalConfiguration.Status = &disabled + } + } + + detectorFeatureAdditionalConfigurations = append(detectorFeatureAdditionalConfigurations, detectorFeatureAdditionalConfiguration) + } + + return detectorFeatureAdditionalConfigurations +} + func flattenDataSourceConfigurationsResult(apiObject *guardduty.DataSourceConfigurationsResult) map[string]interface{} { if apiObject == nil { return nil @@ -504,3 +619,35 @@ func flattenMalwareProtectionEBSVolumesConfigurationResult(apiObject *guardduty. return tfMap } +func flattenFeaturesConfigurationsResult(detectorFeatureConfigurations []*guardduty.DetectorFeatureConfigurationResult) []interface{} { + if len(detectorFeatureConfigurations) == 0 { + return []interface{}{} + } + + result := make([]interface{}, len(detectorFeatureConfigurations)) + for i, detectorFeatureConfiguration := range detectorFeatureConfigurations { + result[i] = map[string]interface{}{ + "name": aws.StringValue(detectorFeatureConfiguration.Name), + "enable": aws.StringValue(detectorFeatureConfiguration.Status) == guardduty.FeatureStatusEnabled, + "additional_configuration": flattenFeaturesAdditionalConfigurationsResult(detectorFeatureConfiguration.AdditionalConfiguration), + } + } + + return result +} + +func flattenFeaturesAdditionalConfigurationsResult(detectorAdditionalFeatureConfigurations []*guardduty.DetectorAdditionalConfigurationResult) []interface{} { + if len(detectorAdditionalFeatureConfigurations) == 0 { + return []interface{}{} + } + + result := make([]interface{}, len(detectorAdditionalFeatureConfigurations)) + for i, detectorAdditionalFeatureConfiguration := range detectorAdditionalFeatureConfigurations { + result[i] = map[string]interface{}{ + "name": detectorAdditionalFeatureConfiguration.Name, + "enable": aws.StringValue(detectorAdditionalFeatureConfiguration.Status) == guardduty.FeatureStatusEnabled, + } + } + + return result +} diff --git a/internal/service/guardduty/detector_test.go b/internal/service/guardduty/detector_test.go index ae112613615..ac1ad649466 100644 --- a/internal/service/guardduty/detector_test.go +++ b/internal/service/guardduty/detector_test.go @@ -35,6 +35,28 @@ func testAccDetector_basic(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "datasources.#", "1"), resource.TestCheckResourceAttr(resourceName, "datasources.0.s3_logs.0.enable", "true"), resource.TestCheckResourceAttr(resourceName, "datasources.0.kubernetes.0.audit_logs.0.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.#", "9"), + resource.TestCheckResourceAttr(resourceName, "features.0.name", "CLOUD_TRAIL"), + resource.TestCheckResourceAttr(resourceName, "features.0.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.1.name", "DNS_LOGS"), + resource.TestCheckResourceAttr(resourceName, "features.1.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.2.name", "FLOW_LOGS"), + resource.TestCheckResourceAttr(resourceName, "features.2.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.3.name", "S3_DATA_EVENTS"), + resource.TestCheckResourceAttr(resourceName, "features.3.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.4.name", "EKS_AUDIT_LOGS"), + resource.TestCheckResourceAttr(resourceName, "features.4.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.5.name", "EBS_MALWARE_PROTECTION"), + resource.TestCheckResourceAttr(resourceName, "features.5.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.6.name", "RDS_LOGIN_EVENTS"), + resource.TestCheckResourceAttr(resourceName, "features.6.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.7.name", "EKS_RUNTIME_MONITORING"), + resource.TestCheckResourceAttr(resourceName, "features.7.enable", "false"), + resource.TestCheckResourceAttr(resourceName, "features.7.additional_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "features.7.additional_configuration.0.name", "EKS_ADDON_MANAGEMENT"), + resource.TestCheckResourceAttr(resourceName, "features.7.additional_configuration.0.enable", "false"), + resource.TestCheckResourceAttr(resourceName, "features.8.name", "LAMBDA_NETWORK_LOGS"), + resource.TestCheckResourceAttr(resourceName, "features.8.enable", "true"), resource.TestCheckResourceAttr(resourceName, "finding_publishing_frequency", "SIX_HOURS"), resource.TestCheckResourceAttr(resourceName, "tags.%", "0"), ), @@ -298,6 +320,87 @@ func testAccDetector_datasources_all(t *testing.T) { }) } +func testAccDetector_features_s3_data_events(t *testing.T) { + ctx := acctest.Context(t) + resourceName := "aws_guardduty_detector.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, guardduty.EndpointsID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckDetectorDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccDetectorConfig_features_s3_data_events(true), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckDetectorExists(ctx, resourceName), + resource.TestCheckResourceAttr(resourceName, "datasources.#", "1"), + resource.TestCheckResourceAttr(resourceName, "datasources.0.s3_logs.#", "1"), + resource.TestCheckResourceAttr(resourceName, "datasources.0.s3_logs.0.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.#", "9"), + resource.TestCheckResourceAttr(resourceName, "features.0.name", "CLOUD_TRAIL"), + resource.TestCheckResourceAttr(resourceName, "features.0.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.1.name", "DNS_LOGS"), + resource.TestCheckResourceAttr(resourceName, "features.1.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.2.name", "FLOW_LOGS"), + resource.TestCheckResourceAttr(resourceName, "features.2.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.3.name", "S3_DATA_EVENTS"), + resource.TestCheckResourceAttr(resourceName, "features.3.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.4.name", "EKS_AUDIT_LOGS"), + resource.TestCheckResourceAttr(resourceName, "features.4.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.5.name", "EBS_MALWARE_PROTECTION"), + resource.TestCheckResourceAttr(resourceName, "features.5.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.6.name", "RDS_LOGIN_EVENTS"), + resource.TestCheckResourceAttr(resourceName, "features.6.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.7.name", "EKS_RUNTIME_MONITORING"), + resource.TestCheckResourceAttr(resourceName, "features.7.enable", "false"), + resource.TestCheckResourceAttr(resourceName, "features.7.additional_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "features.7.additional_configuration.0.name", "EKS_ADDON_MANAGEMENT"), + resource.TestCheckResourceAttr(resourceName, "features.7.additional_configuration.0.enable", "false"), + resource.TestCheckResourceAttr(resourceName, "features.8.name", "LAMBDA_NETWORK_LOGS"), + resource.TestCheckResourceAttr(resourceName, "features.8.enable", "true"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccDetectorConfig_features_s3_data_events(false), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckDetectorExists(ctx, resourceName), + resource.TestCheckResourceAttr(resourceName, "datasources.#", "1"), + resource.TestCheckResourceAttr(resourceName, "datasources.0.s3_logs.#", "1"), + resource.TestCheckResourceAttr(resourceName, "datasources.0.s3_logs.0.enable", "false"), + resource.TestCheckResourceAttr(resourceName, "features.#", "9"), + resource.TestCheckResourceAttr(resourceName, "features.0.name", "CLOUD_TRAIL"), + resource.TestCheckResourceAttr(resourceName, "features.0.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.1.name", "DNS_LOGS"), + resource.TestCheckResourceAttr(resourceName, "features.1.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.2.name", "FLOW_LOGS"), + resource.TestCheckResourceAttr(resourceName, "features.2.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.3.name", "S3_DATA_EVENTS"), + resource.TestCheckResourceAttr(resourceName, "features.3.enable", "false"), + resource.TestCheckResourceAttr(resourceName, "features.4.name", "EKS_AUDIT_LOGS"), + resource.TestCheckResourceAttr(resourceName, "features.4.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.5.name", "EBS_MALWARE_PROTECTION"), + resource.TestCheckResourceAttr(resourceName, "features.5.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.6.name", "RDS_LOGIN_EVENTS"), + resource.TestCheckResourceAttr(resourceName, "features.6.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.7.name", "EKS_RUNTIME_MONITORING"), + resource.TestCheckResourceAttr(resourceName, "features.7.enable", "false"), + resource.TestCheckResourceAttr(resourceName, "features.7.additional_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "features.7.additional_configuration.0.name", "EKS_ADDON_MANAGEMENT"), + resource.TestCheckResourceAttr(resourceName, "features.7.additional_configuration.0.enable", "false"), + resource.TestCheckResourceAttr(resourceName, "features.8.name", "LAMBDA_NETWORK_LOGS"), + resource.TestCheckResourceAttr(resourceName, "features.8.enable", "true"), + ), + }, + }, + }) +} + func testAccCheckDetectorDestroy(ctx context.Context) resource.TestCheckFunc { return func(s *terraform.State) error { conn := acctest.Provider.Meta().(*conns.AWSClient).GuardDutyConn() @@ -412,55 +515,66 @@ resource "aws_guardduty_detector" "test" { func testAccDetectorConfig_datasourcesKubernetesAuditLogs(enable bool) string { return fmt.Sprintf(` -resource "aws_guardduty_detector" "test" { - datasources { - kubernetes { - audit_logs { - enable = %[1]t - } - } - } -} -`, enable) + resource "aws_guardduty_detector" "test" { + datasources { + kubernetes { + audit_logs { + enable = %[1]t + } + } + } + } + `, enable) } func testAccDetectorConfig_datasourcesMalwareProtection(enable bool) string { return fmt.Sprintf(` -resource "aws_guardduty_detector" "test" { - datasources { - malware_protection { - scan_ec2_instance_with_findings { - ebs_volumes { - enable = %[1]t - } - } - } - } -} -`, enable) + resource "aws_guardduty_detector" "test" { + datasources { + malware_protection { + scan_ec2_instance_with_findings { + ebs_volumes { + enable = %[1]t + } + } + } + } + } + `, enable) } func testAccDetectorConfig_datasourcesAll(enableK8s, enableS3, enableMalware bool) string { return fmt.Sprintf(` -resource "aws_guardduty_detector" "test" { - datasources { - kubernetes { - audit_logs { - enable = %[1]t - } - } - s3_logs { - enable = %[2]t - } + resource "aws_guardduty_detector" "test" { + datasources { + kubernetes { + audit_logs { + enable = %[1]t + } + } + s3_logs { + enable = %[2]t + } + + malware_protection { + scan_ec2_instance_with_findings { + ebs_volumes { + enable = %[3]t + } + } + } + } + } + `, enableK8s, enableS3, enableMalware) +} - malware_protection { - scan_ec2_instance_with_findings { - ebs_volumes { - enable = %[3]t - } - } - } +func testAccDetectorConfig_features_s3_data_events(enable bool) string { + return fmt.Sprintf(` +resource "aws_guardduty_detector" "test" { + features { + name = "S3_DATA_EVENTS" + enable = %[1]t } } -`, enableK8s, enableS3, enableMalware) +`, enable) } diff --git a/internal/service/guardduty/guardduty_test.go b/internal/service/guardduty/guardduty_test.go index 5a1f8910617..9f8abb406c0 100644 --- a/internal/service/guardduty/guardduty_test.go +++ b/internal/service/guardduty/guardduty_test.go @@ -17,6 +17,7 @@ func TestAccGuardDuty_serial(t *testing.T) { "datasources_kubernetes_audit_logs": testAccDetector_datasources_kubernetes_audit_logs, "datasources_malware_protection": testAccDetector_datasources_malware_protection, "datasources_all": testAccDetector_datasources_all, + "features_s3_data_events": testAccDetector_features_s3_data_events, "tags": testAccDetector_tags, "datasource_basic": testAccDetectorDataSource_basic, "datasource_id": testAccDetectorDataSource_ID, From 835f0685726b6892451b5e370938a153ee819fb1 Mon Sep 17 00:00:00 2001 From: Ringo De Smet Date: Tue, 23 May 2023 14:57:58 +0200 Subject: [PATCH 03/31] Additional test for new detector features --- internal/service/guardduty/detector.go | 1 + internal/service/guardduty/detector_test.go | 376 ++++++++++++++++++- internal/service/guardduty/guardduty_test.go | 4 + 3 files changed, 375 insertions(+), 6 deletions(-) diff --git a/internal/service/guardduty/detector.go b/internal/service/guardduty/detector.go index 3a6b4d6a7f5..c56ee27992a 100644 --- a/internal/service/guardduty/detector.go +++ b/internal/service/guardduty/detector.go @@ -140,6 +140,7 @@ func ResourceDetector() *schema.Resource { }, "additional_configuration": { Optional: true, + Computed: true, Type: schema.TypeList, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ diff --git a/internal/service/guardduty/detector_test.go b/internal/service/guardduty/detector_test.go index ac1ad649466..48894f494d7 100644 --- a/internal/service/guardduty/detector_test.go +++ b/internal/service/guardduty/detector_test.go @@ -361,6 +361,87 @@ func testAccDetector_features_s3_data_events(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "features.8.enable", "true"), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: false, + }, + { + Config: testAccDetectorConfig_features_s3_data_events(false), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckDetectorExists(ctx, resourceName), + resource.TestCheckResourceAttr(resourceName, "datasources.#", "1"), + resource.TestCheckResourceAttr(resourceName, "datasources.0.s3_logs.#", "1"), + resource.TestCheckResourceAttr(resourceName, "datasources.0.s3_logs.0.enable", "false"), + resource.TestCheckResourceAttr(resourceName, "features.#", "9"), + resource.TestCheckResourceAttr(resourceName, "features.0.name", "CLOUD_TRAIL"), + resource.TestCheckResourceAttr(resourceName, "features.0.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.1.name", "DNS_LOGS"), + resource.TestCheckResourceAttr(resourceName, "features.1.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.2.name", "FLOW_LOGS"), + resource.TestCheckResourceAttr(resourceName, "features.2.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.3.name", "S3_DATA_EVENTS"), + resource.TestCheckResourceAttr(resourceName, "features.3.enable", "false"), + resource.TestCheckResourceAttr(resourceName, "features.4.name", "EKS_AUDIT_LOGS"), + resource.TestCheckResourceAttr(resourceName, "features.4.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.5.name", "EBS_MALWARE_PROTECTION"), + resource.TestCheckResourceAttr(resourceName, "features.5.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.6.name", "RDS_LOGIN_EVENTS"), + resource.TestCheckResourceAttr(resourceName, "features.6.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.7.name", "EKS_RUNTIME_MONITORING"), + resource.TestCheckResourceAttr(resourceName, "features.7.enable", "false"), + resource.TestCheckResourceAttr(resourceName, "features.7.additional_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "features.7.additional_configuration.0.name", "EKS_ADDON_MANAGEMENT"), + resource.TestCheckResourceAttr(resourceName, "features.7.additional_configuration.0.enable", "false"), + resource.TestCheckResourceAttr(resourceName, "features.8.name", "LAMBDA_NETWORK_LOGS"), + resource.TestCheckResourceAttr(resourceName, "features.8.enable", "true"), + ), + }, + }, + }) +} + +func testAccDetector_features_eks_audit_logs(t *testing.T) { + ctx := acctest.Context(t) + resourceName := "aws_guardduty_detector.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, guardduty.EndpointsID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckDetectorDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccDetectorConfig_features_eks_audit_logs(true), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckDetectorExists(ctx, resourceName), + resource.TestCheckResourceAttr(resourceName, "datasources.#", "1"), + resource.TestCheckResourceAttr(resourceName, "datasources.0.s3_logs.#", "1"), + resource.TestCheckResourceAttr(resourceName, "datasources.0.s3_logs.0.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.#", "9"), + resource.TestCheckResourceAttr(resourceName, "features.0.name", "CLOUD_TRAIL"), + resource.TestCheckResourceAttr(resourceName, "features.0.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.1.name", "DNS_LOGS"), + resource.TestCheckResourceAttr(resourceName, "features.1.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.2.name", "FLOW_LOGS"), + resource.TestCheckResourceAttr(resourceName, "features.2.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.3.name", "S3_DATA_EVENTS"), + resource.TestCheckResourceAttr(resourceName, "features.3.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.4.name", "EKS_AUDIT_LOGS"), + resource.TestCheckResourceAttr(resourceName, "features.4.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.5.name", "EBS_MALWARE_PROTECTION"), + resource.TestCheckResourceAttr(resourceName, "features.5.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.6.name", "RDS_LOGIN_EVENTS"), + resource.TestCheckResourceAttr(resourceName, "features.6.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.7.name", "EKS_RUNTIME_MONITORING"), + resource.TestCheckResourceAttr(resourceName, "features.7.enable", "false"), + resource.TestCheckResourceAttr(resourceName, "features.7.additional_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "features.7.additional_configuration.0.name", "EKS_ADDON_MANAGEMENT"), + resource.TestCheckResourceAttr(resourceName, "features.7.additional_configuration.0.enable", "false"), + resource.TestCheckResourceAttr(resourceName, "features.8.name", "LAMBDA_NETWORK_LOGS"), + resource.TestCheckResourceAttr(resourceName, "features.8.enable", "true"), + ), + }, { ResourceName: resourceName, ImportState: true, @@ -401,6 +482,241 @@ func testAccDetector_features_s3_data_events(t *testing.T) { }) } +func testAccDetector_features_ebs_malware_protection(t *testing.T) { + ctx := acctest.Context(t) + resourceName := "aws_guardduty_detector.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, guardduty.EndpointsID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckDetectorDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccDetectorConfig_features_ebs_malware_protection(true), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckDetectorExists(ctx, resourceName), + resource.TestCheckResourceAttr(resourceName, "datasources.#", "1"), + resource.TestCheckResourceAttr(resourceName, "datasources.0.s3_logs.#", "1"), + resource.TestCheckResourceAttr(resourceName, "datasources.0.s3_logs.0.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.#", "9"), + resource.TestCheckResourceAttr(resourceName, "features.0.name", "CLOUD_TRAIL"), + resource.TestCheckResourceAttr(resourceName, "features.0.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.1.name", "DNS_LOGS"), + resource.TestCheckResourceAttr(resourceName, "features.1.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.2.name", "FLOW_LOGS"), + resource.TestCheckResourceAttr(resourceName, "features.2.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.3.name", "S3_DATA_EVENTS"), + resource.TestCheckResourceAttr(resourceName, "features.3.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.4.name", "EKS_AUDIT_LOGS"), + resource.TestCheckResourceAttr(resourceName, "features.4.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.5.name", "EBS_MALWARE_PROTECTION"), + resource.TestCheckResourceAttr(resourceName, "features.5.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.6.name", "RDS_LOGIN_EVENTS"), + resource.TestCheckResourceAttr(resourceName, "features.6.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.7.name", "EKS_RUNTIME_MONITORING"), + resource.TestCheckResourceAttr(resourceName, "features.7.enable", "false"), + resource.TestCheckResourceAttr(resourceName, "features.7.additional_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "features.7.additional_configuration.0.name", "EKS_ADDON_MANAGEMENT"), + resource.TestCheckResourceAttr(resourceName, "features.7.additional_configuration.0.enable", "false"), + resource.TestCheckResourceAttr(resourceName, "features.8.name", "LAMBDA_NETWORK_LOGS"), + resource.TestCheckResourceAttr(resourceName, "features.8.enable", "true"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccDetectorConfig_features_ebs_malware_protection(false), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckDetectorExists(ctx, resourceName), + resource.TestCheckResourceAttr(resourceName, "datasources.#", "1"), + resource.TestCheckResourceAttr(resourceName, "datasources.0.s3_logs.#", "1"), + resource.TestCheckResourceAttr(resourceName, "datasources.0.s3_logs.0.enable", "false"), + resource.TestCheckResourceAttr(resourceName, "features.#", "9"), + resource.TestCheckResourceAttr(resourceName, "features.0.name", "CLOUD_TRAIL"), + resource.TestCheckResourceAttr(resourceName, "features.0.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.1.name", "DNS_LOGS"), + resource.TestCheckResourceAttr(resourceName, "features.1.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.2.name", "FLOW_LOGS"), + resource.TestCheckResourceAttr(resourceName, "features.2.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.3.name", "S3_DATA_EVENTS"), + resource.TestCheckResourceAttr(resourceName, "features.3.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.4.name", "EKS_AUDIT_LOGS"), + resource.TestCheckResourceAttr(resourceName, "features.4.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.5.name", "EBS_MALWARE_PROTECTION"), + resource.TestCheckResourceAttr(resourceName, "features.5.enable", "false"), + resource.TestCheckResourceAttr(resourceName, "features.6.name", "RDS_LOGIN_EVENTS"), + resource.TestCheckResourceAttr(resourceName, "features.6.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.7.name", "EKS_RUNTIME_MONITORING"), + resource.TestCheckResourceAttr(resourceName, "features.7.enable", "false"), + resource.TestCheckResourceAttr(resourceName, "features.7.additional_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "features.7.additional_configuration.0.name", "EKS_ADDON_MANAGEMENT"), + resource.TestCheckResourceAttr(resourceName, "features.7.additional_configuration.0.enable", "false"), + resource.TestCheckResourceAttr(resourceName, "features.8.name", "LAMBDA_NETWORK_LOGS"), + resource.TestCheckResourceAttr(resourceName, "features.8.enable", "true"), + ), + }, + }, + }) +} + +func testAccDetector_features_rds_login_events(t *testing.T) { + ctx := acctest.Context(t) + resourceName := "aws_guardduty_detector.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, guardduty.EndpointsID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckDetectorDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccDetectorConfig_features_rds_login_events(true), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckDetectorExists(ctx, resourceName), + resource.TestCheckResourceAttr(resourceName, "datasources.#", "0"), + resource.TestCheckResourceAttr(resourceName, "features.#", "9"), + resource.TestCheckResourceAttr(resourceName, "features.0.name", "CLOUD_TRAIL"), + resource.TestCheckResourceAttr(resourceName, "features.0.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.1.name", "DNS_LOGS"), + resource.TestCheckResourceAttr(resourceName, "features.1.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.2.name", "FLOW_LOGS"), + resource.TestCheckResourceAttr(resourceName, "features.2.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.3.name", "S3_DATA_EVENTS"), + resource.TestCheckResourceAttr(resourceName, "features.3.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.4.name", "EKS_AUDIT_LOGS"), + resource.TestCheckResourceAttr(resourceName, "features.4.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.5.name", "EBS_MALWARE_PROTECTION"), + resource.TestCheckResourceAttr(resourceName, "features.5.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.6.name", "RDS_LOGIN_EVENTS"), + resource.TestCheckResourceAttr(resourceName, "features.6.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.7.name", "EKS_RUNTIME_MONITORING"), + resource.TestCheckResourceAttr(resourceName, "features.7.enable", "false"), + resource.TestCheckResourceAttr(resourceName, "features.7.additional_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "features.7.additional_configuration.0.name", "EKS_ADDON_MANAGEMENT"), + resource.TestCheckResourceAttr(resourceName, "features.7.additional_configuration.0.enable", "false"), + resource.TestCheckResourceAttr(resourceName, "features.8.name", "LAMBDA_NETWORK_LOGS"), + resource.TestCheckResourceAttr(resourceName, "features.8.enable", "true"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccDetectorConfig_features_rds_login_events(false), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckDetectorExists(ctx, resourceName), + resource.TestCheckResourceAttr(resourceName, "datasources.#", "0"), + resource.TestCheckResourceAttr(resourceName, "features.#", "9"), + resource.TestCheckResourceAttr(resourceName, "features.0.name", "CLOUD_TRAIL"), + resource.TestCheckResourceAttr(resourceName, "features.0.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.1.name", "DNS_LOGS"), + resource.TestCheckResourceAttr(resourceName, "features.1.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.2.name", "FLOW_LOGS"), + resource.TestCheckResourceAttr(resourceName, "features.2.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.3.name", "S3_DATA_EVENTS"), + resource.TestCheckResourceAttr(resourceName, "features.3.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.4.name", "EKS_AUDIT_LOGS"), + resource.TestCheckResourceAttr(resourceName, "features.4.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.5.name", "EBS_MALWARE_PROTECTION"), + resource.TestCheckResourceAttr(resourceName, "features.5.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.6.name", "RDS_LOGIN_EVENTS"), + resource.TestCheckResourceAttr(resourceName, "features.6.enable", "false"), + resource.TestCheckResourceAttr(resourceName, "features.7.name", "EKS_RUNTIME_MONITORING"), + resource.TestCheckResourceAttr(resourceName, "features.7.enable", "false"), + resource.TestCheckResourceAttr(resourceName, "features.7.additional_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "features.7.additional_configuration.0.name", "EKS_ADDON_MANAGEMENT"), + resource.TestCheckResourceAttr(resourceName, "features.7.additional_configuration.0.enable", "false"), + resource.TestCheckResourceAttr(resourceName, "features.8.name", "LAMBDA_NETWORK_LOGS"), + resource.TestCheckResourceAttr(resourceName, "features.8.enable", "true"), + ), + }, + }, + }) +} + +func testAccDetector_features_eks_runtime_monitoring(t *testing.T) { + ctx := acctest.Context(t) + resourceName := "aws_guardduty_detector.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, guardduty.EndpointsID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckDetectorDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccDetectorConfig_features_eks_runtime_monitoring(true), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckDetectorExists(ctx, resourceName), + resource.TestCheckResourceAttr(resourceName, "datasources.#", "0"), + resource.TestCheckResourceAttr(resourceName, "features.#", "9"), + resource.TestCheckResourceAttr(resourceName, "features.0.name", "CLOUD_TRAIL"), + resource.TestCheckResourceAttr(resourceName, "features.0.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.1.name", "DNS_LOGS"), + resource.TestCheckResourceAttr(resourceName, "features.1.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.2.name", "FLOW_LOGS"), + resource.TestCheckResourceAttr(resourceName, "features.2.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.3.name", "S3_DATA_EVENTS"), + resource.TestCheckResourceAttr(resourceName, "features.3.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.4.name", "EKS_AUDIT_LOGS"), + resource.TestCheckResourceAttr(resourceName, "features.4.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.5.name", "EBS_MALWARE_PROTECTION"), + resource.TestCheckResourceAttr(resourceName, "features.5.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.6.name", "RDS_LOGIN_EVENTS"), + resource.TestCheckResourceAttr(resourceName, "features.6.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.7.name", "EKS_RUNTIME_MONITORING"), + resource.TestCheckResourceAttr(resourceName, "features.7.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.7.additional_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "features.7.additional_configuration.0.name", "EKS_ADDON_MANAGEMENT"), + resource.TestCheckResourceAttr(resourceName, "features.7.additional_configuration.0.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.8.name", "LAMBDA_NETWORK_LOGS"), + resource.TestCheckResourceAttr(resourceName, "features.8.enable", "true"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccDetectorConfig_features_rds_login_events(false), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckDetectorExists(ctx, resourceName), + resource.TestCheckResourceAttr(resourceName, "datasources.#", "0"), + resource.TestCheckResourceAttr(resourceName, "features.#", "9"), + resource.TestCheckResourceAttr(resourceName, "features.0.name", "CLOUD_TRAIL"), + resource.TestCheckResourceAttr(resourceName, "features.0.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.1.name", "DNS_LOGS"), + resource.TestCheckResourceAttr(resourceName, "features.1.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.2.name", "FLOW_LOGS"), + resource.TestCheckResourceAttr(resourceName, "features.2.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.3.name", "S3_DATA_EVENTS"), + resource.TestCheckResourceAttr(resourceName, "features.3.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.4.name", "EKS_AUDIT_LOGS"), + resource.TestCheckResourceAttr(resourceName, "features.4.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.5.name", "EBS_MALWARE_PROTECTION"), + resource.TestCheckResourceAttr(resourceName, "features.5.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.6.name", "RDS_LOGIN_EVENTS"), + resource.TestCheckResourceAttr(resourceName, "features.6.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "features.7.name", "EKS_RUNTIME_MONITORING"), + resource.TestCheckResourceAttr(resourceName, "features.7.enable", "false"), + resource.TestCheckResourceAttr(resourceName, "features.7.additional_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "features.7.additional_configuration.0.name", "EKS_ADDON_MANAGEMENT"), + resource.TestCheckResourceAttr(resourceName, "features.7.additional_configuration.0.enable", "false"), + resource.TestCheckResourceAttr(resourceName, "features.8.name", "LAMBDA_NETWORK_LOGS"), + resource.TestCheckResourceAttr(resourceName, "features.8.enable", "true"), + ), + }, + }, + }) +} + func testAccCheckDetectorDestroy(ctx context.Context) resource.TestCheckFunc { return func(s *terraform.State) error { conn := acctest.Provider.Meta().(*conns.AWSClient).GuardDutyConn() @@ -570,11 +886,59 @@ func testAccDetectorConfig_datasourcesAll(enableK8s, enableS3, enableMalware boo func testAccDetectorConfig_features_s3_data_events(enable bool) string { return fmt.Sprintf(` -resource "aws_guardduty_detector" "test" { - features { - name = "S3_DATA_EVENTS" - enable = %[1]t - } + resource "aws_guardduty_detector" "test" { + features { + name = "S3_DATA_EVENTS" + enable = %[1]t + } + } + `, enable) } -`, enable) + +func testAccDetectorConfig_features_eks_audit_logs(enable bool) string { + return fmt.Sprintf(` + resource "aws_guardduty_detector" "test" { + features { + name = "EKS_AUDIT_LOGS" + enable = %[1]t + } + } + `, enable) +} + +func testAccDetectorConfig_features_ebs_malware_protection(enable bool) string { + return fmt.Sprintf(` + resource "aws_guardduty_detector" "test" { + features { + name = "EBS_MALWARE_PROTECTION" + enable = %[1]t + } + } + `, enable) +} + +func testAccDetectorConfig_features_rds_login_events(enable bool) string { + return fmt.Sprintf(` + resource "aws_guardduty_detector" "test" { + features { + name = "RDS_LOGIN_EVENTS" + enable = %[1]t + } + } + `, enable) +} + +func testAccDetectorConfig_features_eks_runtime_monitoring(enable bool) string { + return fmt.Sprintf(` + resource "aws_guardduty_detector" "test" { + features { + name = "EKS_RUNTIME_MONITORING" + enable = %[1]t + additional_configuration { + enable = %[1]t + name = "EKS_ADDON_MANAGEMENT" + } + } + } + `, enable) } diff --git a/internal/service/guardduty/guardduty_test.go b/internal/service/guardduty/guardduty_test.go index 9f8abb406c0..b7ed3d6eb4b 100644 --- a/internal/service/guardduty/guardduty_test.go +++ b/internal/service/guardduty/guardduty_test.go @@ -18,6 +18,10 @@ func TestAccGuardDuty_serial(t *testing.T) { "datasources_malware_protection": testAccDetector_datasources_malware_protection, "datasources_all": testAccDetector_datasources_all, "features_s3_data_events": testAccDetector_features_s3_data_events, + "features_eks_audit_logs": testAccDetector_features_eks_audit_logs, + "features_ebs_malware_protection": testAccDetector_features_ebs_malware_protection, + "features_rds_login_events": testAccDetector_features_rds_login_events, + "features_eks_runtime_monitoring": testAccDetector_features_eks_runtime_monitoring, "tags": testAccDetector_tags, "datasource_basic": testAccDetectorDataSource_basic, "datasource_id": testAccDetectorDataSource_ID, From 50676ad9dd90467b4d1dfe8d1daa3c63534d9a09 Mon Sep 17 00:00:00 2001 From: Ringo De Smet Date: Tue, 23 May 2023 15:32:26 +0200 Subject: [PATCH 04/31] Fix test expectations --- internal/service/guardduty/detector_test.go | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/internal/service/guardduty/detector_test.go b/internal/service/guardduty/detector_test.go index 48894f494d7..eaa142b3acd 100644 --- a/internal/service/guardduty/detector_test.go +++ b/internal/service/guardduty/detector_test.go @@ -577,7 +577,9 @@ func testAccDetector_features_rds_login_events(t *testing.T) { Config: testAccDetectorConfig_features_rds_login_events(true), Check: resource.ComposeAggregateTestCheckFunc( testAccCheckDetectorExists(ctx, resourceName), - resource.TestCheckResourceAttr(resourceName, "datasources.#", "0"), + resource.TestCheckResourceAttr(resourceName, "datasources.#", "1"), + resource.TestCheckResourceAttr(resourceName, "datasources.0.s3_logs.#", "1"), + resource.TestCheckResourceAttr(resourceName, "datasources.0.s3_logs.0.enable", "true"), resource.TestCheckResourceAttr(resourceName, "features.#", "9"), resource.TestCheckResourceAttr(resourceName, "features.0.name", "CLOUD_TRAIL"), resource.TestCheckResourceAttr(resourceName, "features.0.enable", "true"), @@ -611,7 +613,9 @@ func testAccDetector_features_rds_login_events(t *testing.T) { Config: testAccDetectorConfig_features_rds_login_events(false), Check: resource.ComposeAggregateTestCheckFunc( testAccCheckDetectorExists(ctx, resourceName), - resource.TestCheckResourceAttr(resourceName, "datasources.#", "0"), + resource.TestCheckResourceAttr(resourceName, "datasources.#", "1"), + resource.TestCheckResourceAttr(resourceName, "datasources.0.s3_logs.#", "1"), + resource.TestCheckResourceAttr(resourceName, "datasources.0.s3_logs.0.enable", "true"), resource.TestCheckResourceAttr(resourceName, "features.#", "9"), resource.TestCheckResourceAttr(resourceName, "features.0.name", "CLOUD_TRAIL"), resource.TestCheckResourceAttr(resourceName, "features.0.enable", "true"), @@ -654,7 +658,9 @@ func testAccDetector_features_eks_runtime_monitoring(t *testing.T) { Config: testAccDetectorConfig_features_eks_runtime_monitoring(true), Check: resource.ComposeAggregateTestCheckFunc( testAccCheckDetectorExists(ctx, resourceName), - resource.TestCheckResourceAttr(resourceName, "datasources.#", "0"), + resource.TestCheckResourceAttr(resourceName, "datasources.#", "1"), + resource.TestCheckResourceAttr(resourceName, "datasources.0.s3_logs.#", "1"), + resource.TestCheckResourceAttr(resourceName, "datasources.0.s3_logs.0.enable", "true"), resource.TestCheckResourceAttr(resourceName, "features.#", "9"), resource.TestCheckResourceAttr(resourceName, "features.0.name", "CLOUD_TRAIL"), resource.TestCheckResourceAttr(resourceName, "features.0.enable", "true"), @@ -688,7 +694,9 @@ func testAccDetector_features_eks_runtime_monitoring(t *testing.T) { Config: testAccDetectorConfig_features_rds_login_events(false), Check: resource.ComposeAggregateTestCheckFunc( testAccCheckDetectorExists(ctx, resourceName), - resource.TestCheckResourceAttr(resourceName, "datasources.#", "0"), + resource.TestCheckResourceAttr(resourceName, "datasources.#", "1"), + resource.TestCheckResourceAttr(resourceName, "datasources.0.s3_logs.#", "1"), + resource.TestCheckResourceAttr(resourceName, "datasources.0.s3_logs.0.enable", "true"), resource.TestCheckResourceAttr(resourceName, "features.#", "9"), resource.TestCheckResourceAttr(resourceName, "features.0.name", "CLOUD_TRAIL"), resource.TestCheckResourceAttr(resourceName, "features.0.enable", "true"), From af620bec956675e49f751a623d86e50e1479e4f0 Mon Sep 17 00:00:00 2001 From: Ringo De Smet Date: Wed, 24 May 2023 11:32:24 +0200 Subject: [PATCH 05/31] Adding the `features` property to the detector datasource --- internal/service/guardduty/detector.go | 1 + .../service/guardduty/detector_data_source.go | 41 ++++++++++++++++ .../guardduty/detector_data_source_test.go | 48 +++++++++++++++++++ 3 files changed, 90 insertions(+) diff --git a/internal/service/guardduty/detector.go b/internal/service/guardduty/detector.go index c56ee27992a..08153454912 100644 --- a/internal/service/guardduty/detector.go +++ b/internal/service/guardduty/detector.go @@ -620,6 +620,7 @@ func flattenMalwareProtectionEBSVolumesConfigurationResult(apiObject *guardduty. return tfMap } + func flattenFeaturesConfigurationsResult(detectorFeatureConfigurations []*guardduty.DetectorFeatureConfigurationResult) []interface{} { if len(detectorFeatureConfigurations) == 0 { return []interface{}{} diff --git a/internal/service/guardduty/detector_data_source.go b/internal/service/guardduty/detector_data_source.go index 7c2cfba8d07..68886954c78 100644 --- a/internal/service/guardduty/detector_data_source.go +++ b/internal/service/guardduty/detector_data_source.go @@ -34,6 +34,40 @@ func DataSourceDetector() *schema.Resource { Type: schema.TypeString, Computed: true, }, + "features": { + Type: schema.TypeList, + Optional: true, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + }, + "enable": { + Type: schema.TypeBool, + Required: true, + }, + "additional_configuration": { + Optional: true, + Computed: true, + Type: schema.TypeList, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + }, + "enable": { + Type: schema.TypeBool, + Required: true, + }, + }, + }, + }, + }, + }, + }, }, } } @@ -79,6 +113,13 @@ func dataSourceDetectorRead(ctx context.Context, d *schema.ResourceData, meta in d.Set("status", getResp.Status) d.Set("service_role_arn", getResp.ServiceRole) d.Set("finding_publishing_frequency", getResp.FindingPublishingFrequency) + if getResp.Features != nil { + if err := d.Set("features", flattenFeaturesConfigurationsResult(getResp.Features)); err != nil { + return sdkdiag.AppendErrorf(diags, "setting features: %s", err) + } + } else { + d.Set("features", nil) + } return diags } diff --git a/internal/service/guardduty/detector_data_source_test.go b/internal/service/guardduty/detector_data_source_test.go index d209515f94e..17f1d0a91c9 100644 --- a/internal/service/guardduty/detector_data_source_test.go +++ b/internal/service/guardduty/detector_data_source_test.go @@ -27,6 +27,30 @@ func testAccDetectorDataSource_basic(t *testing.T) { resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "status", "ENABLED"), acctest.CheckResourceAttrGlobalARN("data.aws_guardduty_detector.test", "service_role_arn", "iam", "role/aws-service-role/guardduty.amazonaws.com/AWSServiceRoleForAmazonGuardDuty"), resource.TestCheckResourceAttrPair("data.aws_guardduty_detector.test", "finding_publishing_frequency", "aws_guardduty_detector.test", "finding_publishing_frequency"), + resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.#", "9"), + resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.0.name", "CLOUD_TRAIL"), + resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.0.enable", "true"), + resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.1.name", "DNS_LOGS"), + resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.1.enable", "true"), + resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.2.name", "FLOW_LOGS"), + resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.2.enable", "true"), + resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.3.name", "S3_DATA_EVENTS"), + resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.3.enable", "true"), + resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.4.name", "EKS_AUDIT_LOGS"), + resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.4.enable", "true"), + resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.5.name", "EBS_MALWARE_PROTECTION"), + resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.5.enable", "true"), + resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.6.name", "RDS_LOGIN_EVENTS"), + resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.6.enable", "true"), + resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.7.name", "EKS_RUNTIME_MONITORING"), + resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.7.enable", "false"), + resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.7.additional_configuration.#", "1"), + resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.7.additional_configuration.0.name", "EKS_ADDON_MANAGEMENT"), + resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.7.additional_configuration.0.enable", "false"), + resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.8.name", "LAMBDA_NETWORK_LOGS"), + resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.8.enable", "true"), + resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "finding_publishing_frequency", "SIX_HOURS"), + resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "tags.%", "0"), ), }, }, @@ -47,6 +71,30 @@ func testAccDetectorDataSource_ID(t *testing.T) { resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "status", "ENABLED"), acctest.CheckResourceAttrGlobalARN("data.aws_guardduty_detector.test", "service_role_arn", "iam", "role/aws-service-role/guardduty.amazonaws.com/AWSServiceRoleForAmazonGuardDuty"), resource.TestCheckResourceAttrPair("data.aws_guardduty_detector.test", "finding_publishing_frequency", "aws_guardduty_detector.test", "finding_publishing_frequency"), + resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.#", "9"), + resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.0.name", "CLOUD_TRAIL"), + resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.0.enable", "true"), + resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.1.name", "DNS_LOGS"), + resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.1.enable", "true"), + resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.2.name", "FLOW_LOGS"), + resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.2.enable", "true"), + resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.3.name", "S3_DATA_EVENTS"), + resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.3.enable", "true"), + resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.4.name", "EKS_AUDIT_LOGS"), + resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.4.enable", "true"), + resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.5.name", "EBS_MALWARE_PROTECTION"), + resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.5.enable", "true"), + resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.6.name", "RDS_LOGIN_EVENTS"), + resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.6.enable", "true"), + resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.7.name", "EKS_RUNTIME_MONITORING"), + resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.7.enable", "false"), + resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.7.additional_configuration.#", "1"), + resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.7.additional_configuration.0.name", "EKS_ADDON_MANAGEMENT"), + resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.7.additional_configuration.0.enable", "false"), + resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.8.name", "LAMBDA_NETWORK_LOGS"), + resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.8.enable", "true"), + resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "finding_publishing_frequency", "SIX_HOURS"), + resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "tags.%", "0"), ), }, }, From 8ae9a49f264076abff018169cb311d94dbb5f98a Mon Sep 17 00:00:00 2001 From: Ringo De Smet Date: Wed, 24 May 2023 13:05:19 +0200 Subject: [PATCH 06/31] Updated the GuardDuty detector resource & datasource --- internal/service/guardduty/detector_test.go | 164 +++++++++--------- .../docs/d/guardduty_detector.html.markdown | 1 + .../docs/r/guardduty_detector.html.markdown | 54 ++++-- 3 files changed, 122 insertions(+), 97 deletions(-) diff --git a/internal/service/guardduty/detector_test.go b/internal/service/guardduty/detector_test.go index eaa142b3acd..1d50a87f061 100644 --- a/internal/service/guardduty/detector_test.go +++ b/internal/service/guardduty/detector_test.go @@ -839,114 +839,114 @@ resource "aws_guardduty_detector" "test" { func testAccDetectorConfig_datasourcesKubernetesAuditLogs(enable bool) string { return fmt.Sprintf(` - resource "aws_guardduty_detector" "test" { - datasources { - kubernetes { - audit_logs { - enable = %[1]t - } - } - } - } - `, enable) +resource "aws_guardduty_detector" "test" { + datasources { + kubernetes { + audit_logs { + enable = %[1]t + } + } + } +} +`, enable) } func testAccDetectorConfig_datasourcesMalwareProtection(enable bool) string { return fmt.Sprintf(` - resource "aws_guardduty_detector" "test" { - datasources { - malware_protection { - scan_ec2_instance_with_findings { - ebs_volumes { - enable = %[1]t - } - } - } - } - } - `, enable) +resource "aws_guardduty_detector" "test" { + datasources { + malware_protection { + scan_ec2_instance_with_findings { + ebs_volumes { + enable = %[1]t + } + } + } + } +} +`, enable) } func testAccDetectorConfig_datasourcesAll(enableK8s, enableS3, enableMalware bool) string { return fmt.Sprintf(` - resource "aws_guardduty_detector" "test" { - datasources { - kubernetes { - audit_logs { - enable = %[1]t - } - } - s3_logs { - enable = %[2]t - } - - malware_protection { - scan_ec2_instance_with_findings { - ebs_volumes { - enable = %[3]t - } - } - } - } - } - `, enableK8s, enableS3, enableMalware) +resource "aws_guardduty_detector" "test" { + datasources { + kubernetes { + audit_logs { + enable = %[1]t + } + } + s3_logs { + enable = %[2]t + } + + malware_protection { + scan_ec2_instance_with_findings { + ebs_volumes { + enable = %[3]t + } + } + } + } +} +`, enableK8s, enableS3, enableMalware) } func testAccDetectorConfig_features_s3_data_events(enable bool) string { return fmt.Sprintf(` - resource "aws_guardduty_detector" "test" { - features { - name = "S3_DATA_EVENTS" - enable = %[1]t - } - } - `, enable) +resource "aws_guardduty_detector" "test" { + features { + name = "S3_DATA_EVENTS" + enable = %[1]t + } +} +`, enable) } func testAccDetectorConfig_features_eks_audit_logs(enable bool) string { return fmt.Sprintf(` - resource "aws_guardduty_detector" "test" { - features { - name = "EKS_AUDIT_LOGS" - enable = %[1]t - } - } - `, enable) +resource "aws_guardduty_detector" "test" { + features { + name = "EKS_AUDIT_LOGS" + enable = %[1]t + } +} +`, enable) } func testAccDetectorConfig_features_ebs_malware_protection(enable bool) string { return fmt.Sprintf(` - resource "aws_guardduty_detector" "test" { - features { - name = "EBS_MALWARE_PROTECTION" - enable = %[1]t - } - } - `, enable) +resource "aws_guardduty_detector" "test" { + features { + name = "EBS_MALWARE_PROTECTION" + enable = %[1]t + } +} +`, enable) } func testAccDetectorConfig_features_rds_login_events(enable bool) string { return fmt.Sprintf(` - resource "aws_guardduty_detector" "test" { - features { - name = "RDS_LOGIN_EVENTS" - enable = %[1]t - } - } - `, enable) +resource "aws_guardduty_detector" "test" { + features { + name = "RDS_LOGIN_EVENTS" + enable = %[1]t + } +} +`, enable) } func testAccDetectorConfig_features_eks_runtime_monitoring(enable bool) string { return fmt.Sprintf(` - resource "aws_guardduty_detector" "test" { - features { - name = "EKS_RUNTIME_MONITORING" - enable = %[1]t - additional_configuration { - enable = %[1]t - name = "EKS_ADDON_MANAGEMENT" - } - } - } - `, enable) +resource "aws_guardduty_detector" "test" { + features { + name = "EKS_RUNTIME_MONITORING" + enable = %[1]t + additional_configuration { + name = "EKS_ADDON_MANAGEMENT" + enable = %[1]t + } + } +} +`, enable) } diff --git a/website/docs/d/guardduty_detector.html.markdown b/website/docs/d/guardduty_detector.html.markdown index 94888fa40f0..3f49f732d35 100644 --- a/website/docs/d/guardduty_detector.html.markdown +++ b/website/docs/d/guardduty_detector.html.markdown @@ -27,3 +27,4 @@ In addition to all arguments above, the following attributes are exported: * `finding_publishing_frequency` - The frequency of notifications sent about subsequent finding occurrences. * `service_role_arn` - Service-linked role that grants GuardDuty access to the resources in the AWS account. * `status` - Current status of the detector. +* `features` - Current configuration of the detector features. diff --git a/website/docs/r/guardduty_detector.html.markdown b/website/docs/r/guardduty_detector.html.markdown index 3998ec02b72..24d508b6b90 100644 --- a/website/docs/r/guardduty_detector.html.markdown +++ b/website/docs/r/guardduty_detector.html.markdown @@ -18,22 +18,28 @@ Provides a resource to manage a GuardDuty detector. resource "aws_guardduty_detector" "MyDetector" { enable = true - datasources { - s3_logs { + features { + name = "S3_DATA_EVENTS" + enable = true + } + + features { + name = "EKS_AUDIT_LOGS" + enable = false + } + + features { + name = "EBS_MALWARE_PROTECTION" + enable = true + } + + features { + name = "EKS_RUNTIME_MONITORING" + enable = true + aditional_configuration { + name = "EKS_ADDON_MANAGEMENT" enable = true } - kubernetes { - audit_logs { - enable = false - } - } - malware_protection { - scan_ec2_instance_with_findings { - ebs_volumes { - enable = true - } - } - } } } ``` @@ -44,7 +50,8 @@ The following arguments are supported: * `enable` - (Optional) Enable monitoring and feedback reporting. Setting to `false` is equivalent to "suspending" GuardDuty. Defaults to `true`. * `finding_publishing_frequency` - (Optional) Specifies the frequency of notifications sent for subsequent finding occurrences. If the detector is a GuardDuty member account, the value is determined by the GuardDuty primary account and cannot be modified, otherwise defaults to `SIX_HOURS`. For standalone and GuardDuty primary accounts, it must be configured in Terraform to enable drift detection. Valid values for standalone and primary accounts: `FIFTEEN_MINUTES`, `ONE_HOUR`, `SIX_HOURS`. See [AWS Documentation](https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_findings_cloudwatch.html#guardduty_findings_cloudwatch_notification_frequency) for more information. -* `datasources` - (Optional) Describes which data sources will be enabled for the detector. See [Data Sources](#data-sources) below for more details. +* `datasources` - (Optional) Describes which data sources will be enabled for the detector. See [Data Sources](#data-sources) below for more details. [Deprecated](https://docs.aws.amazon.com/guardduty/latest/ug/guardduty-feature-object-api-changes-march2023.html) in favor of `features`. +* `features` - (Optional) Describes which features will be enabled for the detector. See [Features](#features) below for more details. * `tags` - (Optional) Key-value map 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. ### Data Sources @@ -58,6 +65,8 @@ The `datasources` block supports the following: * `malware_protection` - (Optional) Configures [Malware Protection](https://docs.aws.amazon.com/guardduty/latest/ug/malware-protection.html). See [Malware Protection](#malware-protection), [Scan EC2 instance with findings](#scan-ec2-instance-with-findings) and [EBS volumes](#ebs-volumes) below for more details. +The `datasources` block is deprecated since March 2023. Use the `features` block instead and [map each `datasources` block to the corresponding `features` block](https://docs.aws.amazon.com/guardduty/latest/ug/guardduty-feature-object-api-changes-march2023.html#guardduty-feature-enablement-datasource-relation). + ### S3 Logs The `s3_logs` block supports the following: @@ -100,6 +109,21 @@ The `ebs_volumes` block supports the following: * `enable` - (Required) If true, enables [Malware Protection](https://docs.aws.amazon.com/guardduty/latest/ug/malware-protection.html) as data source for the detector. Defaults to `true`. +### Features + +The `features` block supports the following: + +* `name` - (Required) Name of the feature to configure. See the [AWS GuardDuty documentation](https://docs.aws.amazon.com/guardduty/latest/ug/guardduty-feature-object-api-changes-march2023.html#guardduty-feature-enablement-datasource-relation) for the allowed feature names. +* `enable` - (Required) If true, enables the feature, false to disable the feature. +* `additional_configuration` - (Optional) Additional feature configuration block See [below](#additional-configuration). + +### Additional Configuration + +The `additional_configuration` block supports the following: + +* `name` - (Required) Name of the additional feature configuration. +* `enable` - (Required) If true, enables the additional feature configuration, false to disable the feature. + ## Attributes Reference In addition to all arguments above, the following attributes are exported: From 4d0b83f964a4edea485b2a2f11aa871a345c8c59 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Tue, 26 Sep 2023 12:01:59 -0400 Subject: [PATCH 07/31] Revert "fix: add validation of GuardDuty filter name" This reverts commit 931f43f6be81bcc65b693f66d2c7d09c3c53a969. --- aws/resource_aws_guardduty_filter.go | 6 +----- website/docs/r/guardduty_filter.html.markdown | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/aws/resource_aws_guardduty_filter.go b/aws/resource_aws_guardduty_filter.go index b1881dd66dc..148b21092fb 100644 --- a/aws/resource_aws_guardduty_filter.go +++ b/aws/resource_aws_guardduty_filter.go @@ -40,11 +40,7 @@ func resourceAwsGuardDutyFilter() *schema.Resource { Type: schema.TypeString, Required: true, ForceNew: true, - validateFunc: validation.All( - validation.StringLenBetween(3, 64), - validation.StringMatch(regexp.MustCompile(`^[a-zA-Z0-9_.-]+$`), - "only alphanumeric characters, hyphens, underscores, and periods are allowed"), - ) + ValidateFunc: validation.StringLenBetween(3, 64), }, "description": { Type: schema.TypeString, diff --git a/website/docs/r/guardduty_filter.html.markdown b/website/docs/r/guardduty_filter.html.markdown index 00da7bd8364..04d90a44f6a 100644 --- a/website/docs/r/guardduty_filter.html.markdown +++ b/website/docs/r/guardduty_filter.html.markdown @@ -49,7 +49,7 @@ resource "aws_guardduty_filter" "MyFilter" { The following arguments are supported: * `detector_id` - (Required) ID of a GuardDuty detector, attached to your account. -* `name` - (Required) The name of your filter. Names can be between 3 and 64 characters long and the valid characters are a-z, A-Z, 0-9, '_' (underscore), '-' (hyphen), and '.' (period). +* `name` - (Required) The name of your filter. * `description` - (Optional) Description of the filter. * `rank` - (Required) Specifies the position of the filter in the list of current filters. Also specifies the order in which this filter is applied to the findings. * `action` - (Required) Specifies the action that is to be applied to the findings that match the filter. Can be one of `ARCHIVE` or `NOOP`. From ef264855627997e6312b7cc5b5f994b1d8358b34 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Tue, 26 Sep 2023 16:43:13 -0400 Subject: [PATCH 08/31] r/aws_guardduty_filter: Alphabetize attributes. --- internal/service/guardduty/filter.go | 56 ++++++++++++++-------------- 1 file changed, 27 insertions(+), 29 deletions(-) diff --git a/internal/service/guardduty/filter.go b/internal/service/guardduty/filter.go index c443cf15c81..0e85cf987c2 100644 --- a/internal/service/guardduty/filter.go +++ b/internal/service/guardduty/filter.go @@ -37,29 +37,27 @@ func ResourceFilter() *schema.Resource { Importer: &schema.ResourceImporter{ StateContext: schema.ImportStatePassthroughContext, }, + Schema: map[string]*schema.Schema{ + "action": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice(guardduty.FilterAction_Values(), false), + }, "arn": { Type: schema.TypeString, Computed: true, }, - "detector_id": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.StringLenBetween(3, 64), - }, "description": { Type: schema.TypeString, Optional: true, ValidateFunc: validation.StringLenBetween(0, 512), }, - names.AttrTags: tftags.TagsSchema(), - names.AttrTagsAll: tftags.TagsSchemaComputed(), + "detector_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, "finding_criteria": { Type: schema.TypeList, MaxItems: 1, @@ -72,21 +70,15 @@ func ResourceFilter() *schema.Resource { Required: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "field": { - Type: schema.TypeString, - Required: true, - }, "equals": { Type: schema.TypeList, Optional: true, MinItems: 1, Elem: &schema.Schema{Type: schema.TypeString}, }, - "not_equals": { - Type: schema.TypeList, - Optional: true, - MinItems: 1, - Elem: &schema.Schema{Type: schema.TypeString}, + "field": { + Type: schema.TypeString, + Required: true, }, "greater_than": { Type: schema.TypeString, @@ -108,24 +100,30 @@ func ResourceFilter() *schema.Resource { Optional: true, ValidateFunc: verify.ValidStringDateOrPositiveInt, }, + "not_equals": { + Type: schema.TypeList, + Optional: true, + MinItems: 1, + Elem: &schema.Schema{Type: schema.TypeString}, + }, }, }, }, }, }, }, - "action": { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.StringInSlice([]string{ - guardduty.FilterActionNoop, - guardduty.FilterActionArchive, - }, false), + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringLenBetween(3, 64), }, "rank": { Type: schema.TypeInt, Required: true, }, + names.AttrTags: tftags.TagsSchema(), + names.AttrTagsAll: tftags.TagsSchemaComputed(), }, CustomizeDiff: verify.SetTagsDiff, From 0c57c34ca901ffbff9422f7b867ce343093c6555 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Tue, 26 Sep 2023 16:52:02 -0400 Subject: [PATCH 09/31] r/aws_guardduty_filter: Add plan-time validation of `name`. --- .changelog/21030.txt | 3 +++ internal/service/guardduty/filter.go | 13 +++++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) create mode 100644 .changelog/21030.txt diff --git a/.changelog/21030.txt b/.changelog/21030.txt new file mode 100644 index 00000000000..8b0aa9a536e --- /dev/null +++ b/.changelog/21030.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +resource/aws_guardduty_filter: Add plan-time validation of `name` +``` \ No newline at end of file diff --git a/internal/service/guardduty/filter.go b/internal/service/guardduty/filter.go index 0e85cf987c2..e773dc93ae3 100644 --- a/internal/service/guardduty/filter.go +++ b/internal/service/guardduty/filter.go @@ -11,6 +11,7 @@ import ( "strings" "time" + "github.com/YakDriver/regexache" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/arn" "github.com/aws/aws-sdk-go/service/guardduty" @@ -113,10 +114,14 @@ func ResourceFilter() *schema.Resource { }, }, "name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.StringLenBetween(3, 64), + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.All( + validation.StringLenBetween(3, 64), + validation.StringMatch(regexache.MustCompile(`^[a-zA-Z0-9_.-]+$`), + "only alphanumeric characters, hyphens, underscores, and periods are allowed"), + ), }, "rank": { Type: schema.TypeInt, From 2178e6faa7a351afa1cf33dce6c05d7b271a33a5 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Tue, 26 Sep 2023 16:59:24 -0400 Subject: [PATCH 10/31] Acceptance test output: % make testacc TESTARGS='-run=TestAccGuardDuty_serial/Filter' PKG=guardduty ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./internal/service/guardduty/... -v -count 1 -parallel 20 -run=TestAccGuardDuty_serial/Filter -timeout 360m === RUN TestAccGuardDuty_serial === PAUSE TestAccGuardDuty_serial === CONT TestAccGuardDuty_serial === RUN TestAccGuardDuty_serial/Filter === RUN TestAccGuardDuty_serial/Filter/basic === RUN TestAccGuardDuty_serial/Filter/update === RUN TestAccGuardDuty_serial/Filter/tags === RUN TestAccGuardDuty_serial/Filter/disappears --- PASS: TestAccGuardDuty_serial (172.71s) --- PASS: TestAccGuardDuty_serial/Filter (172.71s) --- PASS: TestAccGuardDuty_serial/Filter/basic (49.88s) --- PASS: TestAccGuardDuty_serial/Filter/update (38.80s) --- PASS: TestAccGuardDuty_serial/Filter/tags (58.11s) --- PASS: TestAccGuardDuty_serial/Filter/disappears (25.92s) PASS ok github.com/hashicorp/terraform-provider-aws/internal/service/guardduty 177.788s From 774d3746d65099492965251ec53b266b6d27a1fd Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Tue, 26 Sep 2023 17:29:14 -0400 Subject: [PATCH 11/31] guardduty: Add 'FindDetector'. --- internal/service/guardduty/detector.go | 31 +++++++++++++++++++ .../guardduty/finding_ids_data_source_test.go | 8 ++--- internal/service/guardduty/guardduty_test.go | 19 ++++++------ 3 files changed, 45 insertions(+), 13 deletions(-) diff --git a/internal/service/guardduty/detector.go b/internal/service/guardduty/detector.go index 9425c0f4405..2da6457091d 100644 --- a/internal/service/guardduty/detector.go +++ b/internal/service/guardduty/detector.go @@ -656,3 +656,34 @@ func flattenFeaturesAdditionalConfigurationsResult(detectorAdditionalFeatureConf return result } + +func FindDetector(ctx context.Context, conn *guardduty.GuardDuty) (*string, error) { + output, err := findDetectors(ctx, conn) + + if err != nil { + return nil, err + } + + return tfresource.AssertSinglePtrResult(output) +} + +func findDetectors(ctx context.Context, conn *guardduty.GuardDuty) ([]*string, error) { + input := &guardduty.ListDetectorsInput{} + var output []*string + + err := conn.ListDetectorsPagesWithContext(ctx, input, func(page *guardduty.ListDetectorsOutput, lastPage bool) bool { + if page == nil { + return !lastPage + } + + output = append(output, page.DetectorIds...) + + return !lastPage + }) + + if err != nil { + return nil, err + } + + return output, nil +} diff --git a/internal/service/guardduty/finding_ids_data_source_test.go b/internal/service/guardduty/finding_ids_data_source_test.go index 546f6c86424..2c6c5fb0f2e 100644 --- a/internal/service/guardduty/finding_ids_data_source_test.go +++ b/internal/service/guardduty/finding_ids_data_source_test.go @@ -11,12 +11,12 @@ import ( "github.com/hashicorp/terraform-provider-aws/internal/acctest" ) -func TestAccGuardDutyFindingIdsDataSource_basic(t *testing.T) { +func testAccFindingIDsDataSource_basic(t *testing.T) { ctx := acctest.Context(t) dataSourceName := "data.aws_guardduty_finding_ids.test" detectorDataSourceName := "data.aws_guardduty_detector.test" - resource.ParallelTest(t, resource.TestCase{ + resource.Test(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t) testAccPreCheckDetectorExists(ctx, t) @@ -25,7 +25,7 @@ func TestAccGuardDutyFindingIdsDataSource_basic(t *testing.T) { ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, Steps: []resource.TestStep{ { - Config: testAccFindingIdsDataSourceConfig_basic(), + Config: testAccFindingIDsDataSourceConfig_basic(), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttrPair(dataSourceName, "detector_id", detectorDataSourceName, "id"), resource.TestCheckResourceAttrSet(dataSourceName, "has_findings"), @@ -36,7 +36,7 @@ func TestAccGuardDutyFindingIdsDataSource_basic(t *testing.T) { }) } -func testAccFindingIdsDataSourceConfig_basic() string { +func testAccFindingIDsDataSourceConfig_basic() string { return ` data "aws_guardduty_detector" "test" {} diff --git a/internal/service/guardduty/guardduty_test.go b/internal/service/guardduty/guardduty_test.go index 7f4e0dc4a35..1db1fedcbe2 100644 --- a/internal/service/guardduty/guardduty_test.go +++ b/internal/service/guardduty/guardduty_test.go @@ -8,9 +8,10 @@ import ( "os" "testing" - "github.com/aws/aws-sdk-go/service/guardduty" "github.com/hashicorp/terraform-provider-aws/internal/acctest" "github.com/hashicorp/terraform-provider-aws/internal/conns" + tfguardduty "github.com/hashicorp/terraform-provider-aws/internal/service/guardduty" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" ) func TestAccGuardDuty_serial(t *testing.T) { @@ -38,6 +39,9 @@ func TestAccGuardDuty_serial(t *testing.T) { "tags": testAccFilter_tags, "disappears": testAccFilter_disappears, }, + "FindingIDs": { + "datasource_basic": testAccFindingIDsDataSource_basic, + }, "InviteAccepter": { "basic": testAccInviteAccepter_basic, }, @@ -92,17 +96,14 @@ func testAccMemberFromEnv(t *testing.T) (string, string) { return accountID, email } -// testAccPreCheckDetectorExists verifies the current account has a single active -// GuardDuty detector configured. +// testAccPreCheckDetectorExists verifies the current account has a single active GuardDuty detector configured. func testAccPreCheckDetectorExists(ctx context.Context, t *testing.T) { conn := acctest.Provider.Meta().(*conns.AWSClient).GuardDutyConn(ctx) - out, err := conn.ListDetectorsWithContext(ctx, &guardduty.ListDetectorsInput{}) - if out == nil || len(out.DetectorIds) == 0 { - t.Skip("this AWS account must have an existing GuardDuty detector configured") - } - if len(out.DetectorIds) > 1 { - t.Skipf("this AWS account must have a single existing GuardDuty detector configured. Found %d.", len(out.DetectorIds)) + _, err := tfguardduty.FindDetector(ctx, conn) + + if tfresource.NotFound(err) { + t.Skipf("reading this AWS account's single GuardDuty Detector: %s", err) } if err != nil { From c3c684b38431eff7f206402f5c6daa4a6dbf4fd9 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Wed, 27 Sep 2023 08:05:27 -0400 Subject: [PATCH 12/31] guardduty: Add 'testAccPreCheckDetectorNotExists'. --- .../guardduty/detector_data_source_test.go | 10 +++- internal/service/guardduty/detector_test.go | 55 +++++++++++++++---- internal/service/guardduty/filter_test.go | 20 +++++-- internal/service/guardduty/guardduty_test.go | 17 ++++++ .../service/guardduty/invite_accepter_test.go | 1 + internal/service/guardduty/ipset_test.go | 10 +++- internal/service/guardduty/member_test.go | 20 +++++-- .../organization_admin_account_test.go | 1 + .../organization_configuration_test.go | 5 ++ .../guardduty/publishing_destination_test.go | 10 +++- .../service/guardduty/threatintelset_test.go | 10 +++- 11 files changed, 132 insertions(+), 27 deletions(-) diff --git a/internal/service/guardduty/detector_data_source_test.go b/internal/service/guardduty/detector_data_source_test.go index 4b481d9d933..e6321f4e00d 100644 --- a/internal/service/guardduty/detector_data_source_test.go +++ b/internal/service/guardduty/detector_data_source_test.go @@ -14,7 +14,10 @@ import ( func testAccDetectorDataSource_basic(t *testing.T) { ctx := acctest.Context(t) resource.Test(t, resource.TestCase{ - PreCheck: func() { acctest.PreCheck(ctx, t) }, + PreCheck: func() { + acctest.PreCheck(ctx, t) + testAccPreCheckDetectorNotExists(ctx, t) + }, ErrorCheck: acctest.ErrorCheck(t, guardduty.EndpointsID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, PreventPostDestroyRefresh: true, @@ -63,7 +66,10 @@ func testAccDetectorDataSource_basic(t *testing.T) { func testAccDetectorDataSource_ID(t *testing.T) { ctx := acctest.Context(t) resource.Test(t, resource.TestCase{ - PreCheck: func() { acctest.PreCheck(ctx, t) }, + PreCheck: func() { + acctest.PreCheck(ctx, t) + testAccPreCheckDetectorNotExists(ctx, t) + }, ErrorCheck: acctest.ErrorCheck(t, guardduty.EndpointsID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, Steps: []resource.TestStep{ diff --git a/internal/service/guardduty/detector_test.go b/internal/service/guardduty/detector_test.go index 66cbc55dfde..edebb86f5a6 100644 --- a/internal/service/guardduty/detector_test.go +++ b/internal/service/guardduty/detector_test.go @@ -23,7 +23,10 @@ func testAccDetector_basic(t *testing.T) { resourceName := "aws_guardduty_detector.test" resource.Test(t, resource.TestCase{ - PreCheck: func() { acctest.PreCheck(ctx, t) }, + PreCheck: func() { + acctest.PreCheck(ctx, t) + testAccPreCheckDetectorNotExists(ctx, t) + }, ErrorCheck: acctest.ErrorCheck(t, guardduty.EndpointsID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckDetectorDestroy(ctx), @@ -99,7 +102,10 @@ func testAccDetector_tags(t *testing.T) { resourceName := "aws_guardduty_detector.test" resource.Test(t, resource.TestCase{ - PreCheck: func() { acctest.PreCheck(ctx, t) }, + PreCheck: func() { + acctest.PreCheck(ctx, t) + testAccPreCheckDetectorNotExists(ctx, t) + }, ErrorCheck: acctest.ErrorCheck(t, guardduty.EndpointsID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckDetectorDestroy(ctx), @@ -143,7 +149,10 @@ func testAccDetector_datasources_s3logs(t *testing.T) { resourceName := "aws_guardduty_detector.test" resource.Test(t, resource.TestCase{ - PreCheck: func() { acctest.PreCheck(ctx, t) }, + PreCheck: func() { + acctest.PreCheck(ctx, t) + testAccPreCheckDetectorNotExists(ctx, t) + }, ErrorCheck: acctest.ErrorCheck(t, guardduty.EndpointsID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckDetectorDestroy(ctx), @@ -180,7 +189,10 @@ func testAccDetector_datasources_kubernetes_audit_logs(t *testing.T) { resourceName := "aws_guardduty_detector.test" resource.Test(t, resource.TestCase{ - PreCheck: func() { acctest.PreCheck(ctx, t) }, + PreCheck: func() { + acctest.PreCheck(ctx, t) + testAccPreCheckDetectorNotExists(ctx, t) + }, ErrorCheck: acctest.ErrorCheck(t, guardduty.EndpointsID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckDetectorDestroy(ctx), @@ -217,7 +229,10 @@ func testAccDetector_datasources_malware_protection(t *testing.T) { resourceName := "aws_guardduty_detector.test" resource.Test(t, resource.TestCase{ - PreCheck: func() { acctest.PreCheck(ctx, t) }, + PreCheck: func() { + acctest.PreCheck(ctx, t) + testAccPreCheckDetectorNotExists(ctx, t) + }, ErrorCheck: acctest.ErrorCheck(t, guardduty.EndpointsID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckDetectorDestroy(ctx), @@ -257,7 +272,10 @@ func testAccDetector_datasources_all(t *testing.T) { resourceName := "aws_guardduty_detector.test" resource.Test(t, resource.TestCase{ - PreCheck: func() { acctest.PreCheck(ctx, t) }, + PreCheck: func() { + acctest.PreCheck(ctx, t) + testAccPreCheckDetectorNotExists(ctx, t) + }, ErrorCheck: acctest.ErrorCheck(t, guardduty.EndpointsID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckDetectorDestroy(ctx), @@ -328,7 +346,10 @@ func testAccDetector_features_s3_data_events(t *testing.T) { resourceName := "aws_guardduty_detector.test" resource.Test(t, resource.TestCase{ - PreCheck: func() { acctest.PreCheck(ctx, t) }, + PreCheck: func() { + acctest.PreCheck(ctx, t) + testAccPreCheckDetectorNotExists(ctx, t) + }, ErrorCheck: acctest.ErrorCheck(t, guardduty.EndpointsID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckDetectorDestroy(ctx), @@ -409,7 +430,10 @@ func testAccDetector_features_eks_audit_logs(t *testing.T) { resourceName := "aws_guardduty_detector.test" resource.Test(t, resource.TestCase{ - PreCheck: func() { acctest.PreCheck(ctx, t) }, + PreCheck: func() { + acctest.PreCheck(ctx, t) + testAccPreCheckDetectorNotExists(ctx, t) + }, ErrorCheck: acctest.ErrorCheck(t, guardduty.EndpointsID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckDetectorDestroy(ctx), @@ -490,7 +514,10 @@ func testAccDetector_features_ebs_malware_protection(t *testing.T) { resourceName := "aws_guardduty_detector.test" resource.Test(t, resource.TestCase{ - PreCheck: func() { acctest.PreCheck(ctx, t) }, + PreCheck: func() { + acctest.PreCheck(ctx, t) + testAccPreCheckDetectorNotExists(ctx, t) + }, ErrorCheck: acctest.ErrorCheck(t, guardduty.EndpointsID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckDetectorDestroy(ctx), @@ -571,7 +598,10 @@ func testAccDetector_features_rds_login_events(t *testing.T) { resourceName := "aws_guardduty_detector.test" resource.Test(t, resource.TestCase{ - PreCheck: func() { acctest.PreCheck(ctx, t) }, + PreCheck: func() { + acctest.PreCheck(ctx, t) + testAccPreCheckDetectorNotExists(ctx, t) + }, ErrorCheck: acctest.ErrorCheck(t, guardduty.EndpointsID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckDetectorDestroy(ctx), @@ -652,7 +682,10 @@ func testAccDetector_features_eks_runtime_monitoring(t *testing.T) { resourceName := "aws_guardduty_detector.test" resource.Test(t, resource.TestCase{ - PreCheck: func() { acctest.PreCheck(ctx, t) }, + PreCheck: func() { + acctest.PreCheck(ctx, t) + testAccPreCheckDetectorNotExists(ctx, t) + }, ErrorCheck: acctest.ErrorCheck(t, guardduty.EndpointsID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckDetectorDestroy(ctx), diff --git a/internal/service/guardduty/filter_test.go b/internal/service/guardduty/filter_test.go index d390f5c25c1..6a90cf9c387 100644 --- a/internal/service/guardduty/filter_test.go +++ b/internal/service/guardduty/filter_test.go @@ -30,7 +30,10 @@ func testAccFilter_basic(t *testing.T) { endDate := "2020-02-01T00:00:00Z" resource.Test(t, resource.TestCase{ - PreCheck: func() { acctest.PreCheck(ctx, t) }, + PreCheck: func() { + acctest.PreCheck(ctx, t) + testAccPreCheckDetectorNotExists(ctx, t) + }, ErrorCheck: acctest.ErrorCheck(t, guardduty.EndpointsID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckFilterDestroy(ctx), @@ -97,7 +100,10 @@ func testAccFilter_update(t *testing.T) { endDate := "2020-02-01T00:00:00Z" resource.Test(t, resource.TestCase{ - PreCheck: func() { acctest.PreCheck(ctx, t) }, + PreCheck: func() { + acctest.PreCheck(ctx, t) + testAccPreCheckDetectorNotExists(ctx, t) + }, ErrorCheck: acctest.ErrorCheck(t, guardduty.EndpointsID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckFilterDestroy(ctx), @@ -142,7 +148,10 @@ func testAccFilter_tags(t *testing.T) { endDate := "2020-02-01T00:00:00Z" resource.Test(t, resource.TestCase{ - PreCheck: func() { acctest.PreCheck(ctx, t) }, + PreCheck: func() { + acctest.PreCheck(ctx, t) + testAccPreCheckDetectorNotExists(ctx, t) + }, ErrorCheck: acctest.ErrorCheck(t, guardduty.EndpointsID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckFilterDestroy(ctx), @@ -184,7 +193,10 @@ func testAccFilter_disappears(t *testing.T) { endDate := "2020-02-01T00:00:00Z" resource.Test(t, resource.TestCase{ - PreCheck: func() { acctest.PreCheck(ctx, t) }, + PreCheck: func() { + acctest.PreCheck(ctx, t) + testAccPreCheckDetectorNotExists(ctx, t) + }, ErrorCheck: acctest.ErrorCheck(t, guardduty.EndpointsID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckACMPCACertificateAuthorityDestroy(ctx), diff --git a/internal/service/guardduty/guardduty_test.go b/internal/service/guardduty/guardduty_test.go index 1db1fedcbe2..4fc9aa6df69 100644 --- a/internal/service/guardduty/guardduty_test.go +++ b/internal/service/guardduty/guardduty_test.go @@ -110,3 +110,20 @@ func testAccPreCheckDetectorExists(ctx context.Context, t *testing.T) { t.Fatalf("listing GuardDuty Detectors: %s", err) } } + +// testAccPreCheckDetectorNotExists verifies the current account has no active GuardDuty detector configured. +func testAccPreCheckDetectorNotExists(ctx context.Context, t *testing.T) { + conn := acctest.Provider.Meta().(*conns.AWSClient).GuardDutyConn(ctx) + + _, err := tfguardduty.FindDetector(ctx, conn) + + if tfresource.NotFound(err) { + return + } + + if err != nil { + t.Fatalf("listing GuardDuty Detectors: %s", err) + } + + t.Skip("this AWS account has a GuardDuty Detector") +} diff --git a/internal/service/guardduty/invite_accepter_test.go b/internal/service/guardduty/invite_accepter_test.go index 41b98378bb4..c9bab1c33d5 100644 --- a/internal/service/guardduty/invite_accepter_test.go +++ b/internal/service/guardduty/invite_accepter_test.go @@ -28,6 +28,7 @@ func testAccInviteAccepter_basic(t *testing.T) { PreCheck: func() { acctest.PreCheck(ctx, t) acctest.PreCheckAlternateAccount(t) + testAccPreCheckDetectorNotExists(ctx, t) }, ErrorCheck: acctest.ErrorCheck(t, guardduty.EndpointsID), ProtoV5ProviderFactories: acctest.ProtoV5FactoriesAlternate(ctx, t), diff --git a/internal/service/guardduty/ipset_test.go b/internal/service/guardduty/ipset_test.go index 0bb529063cd..ac859203d1f 100644 --- a/internal/service/guardduty/ipset_test.go +++ b/internal/service/guardduty/ipset_test.go @@ -30,7 +30,10 @@ func testAccIPSet_basic(t *testing.T) { resourceName := "aws_guardduty_ipset.test" resource.Test(t, resource.TestCase{ - PreCheck: func() { acctest.PreCheck(ctx, t) }, + PreCheck: func() { + acctest.PreCheck(ctx, t) + testAccPreCheckDetectorNotExists(ctx, t) + }, ErrorCheck: acctest.ErrorCheck(t, guardduty.EndpointsID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckIPSetDestroy(ctx), @@ -70,7 +73,10 @@ func testAccIPSet_tags(t *testing.T) { resourceName := "aws_guardduty_ipset.test" resource.Test(t, resource.TestCase{ - PreCheck: func() { acctest.PreCheck(ctx, t) }, + PreCheck: func() { + acctest.PreCheck(ctx, t) + testAccPreCheckDetectorNotExists(ctx, t) + }, ErrorCheck: acctest.ErrorCheck(t, guardduty.EndpointsID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckIPSetDestroy(ctx), diff --git a/internal/service/guardduty/member_test.go b/internal/service/guardduty/member_test.go index 00c59fcf9dd..c5eb68e86ba 100644 --- a/internal/service/guardduty/member_test.go +++ b/internal/service/guardduty/member_test.go @@ -24,7 +24,10 @@ func testAccMember_basic(t *testing.T) { accountID := "111111111111" resource.Test(t, resource.TestCase{ - PreCheck: func() { acctest.PreCheck(ctx, t) }, + PreCheck: func() { + acctest.PreCheck(ctx, t) + testAccPreCheckDetectorNotExists(ctx, t) + }, ErrorCheck: acctest.ErrorCheck(t, guardduty.EndpointsID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckMemberDestroy(ctx), @@ -54,7 +57,10 @@ func testAccMember_invite_disassociate(t *testing.T) { accountID, email := testAccMemberFromEnv(t) resource.Test(t, resource.TestCase{ - PreCheck: func() { acctest.PreCheck(ctx, t) }, + PreCheck: func() { + acctest.PreCheck(ctx, t) + testAccPreCheckDetectorNotExists(ctx, t) + }, ErrorCheck: acctest.ErrorCheck(t, guardduty.EndpointsID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckMemberDestroy(ctx), @@ -94,7 +100,10 @@ func testAccMember_invite_onUpdate(t *testing.T) { accountID, email := testAccMemberFromEnv(t) resource.Test(t, resource.TestCase{ - PreCheck: func() { acctest.PreCheck(ctx, t) }, + PreCheck: func() { + acctest.PreCheck(ctx, t) + testAccPreCheckDetectorNotExists(ctx, t) + }, ErrorCheck: acctest.ErrorCheck(t, guardduty.EndpointsID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckMemberDestroy(ctx), @@ -135,7 +144,10 @@ func testAccMember_invitationMessage(t *testing.T) { invitationMessage := "inviting" resource.Test(t, resource.TestCase{ - PreCheck: func() { acctest.PreCheck(ctx, t) }, + PreCheck: func() { + acctest.PreCheck(ctx, t) + testAccPreCheckDetectorNotExists(ctx, t) + }, ErrorCheck: acctest.ErrorCheck(t, guardduty.EndpointsID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckMemberDestroy(ctx), diff --git a/internal/service/guardduty/organization_admin_account_test.go b/internal/service/guardduty/organization_admin_account_test.go index 03c50016612..ff05880d3fd 100644 --- a/internal/service/guardduty/organization_admin_account_test.go +++ b/internal/service/guardduty/organization_admin_account_test.go @@ -25,6 +25,7 @@ func testAccOrganizationAdminAccount_basic(t *testing.T) { PreCheck: func() { acctest.PreCheck(ctx, t) acctest.PreCheckOrganizationsAccount(ctx, t) + testAccPreCheckDetectorNotExists(ctx, t) }, ErrorCheck: acctest.ErrorCheck(t, guardduty.EndpointsID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, diff --git a/internal/service/guardduty/organization_configuration_test.go b/internal/service/guardduty/organization_configuration_test.go index 3d600f553cf..5743d933b15 100644 --- a/internal/service/guardduty/organization_configuration_test.go +++ b/internal/service/guardduty/organization_configuration_test.go @@ -21,6 +21,7 @@ func testAccOrganizationConfiguration_basic(t *testing.T) { PreCheck: func() { acctest.PreCheck(ctx, t) acctest.PreCheckOrganizationsAccount(ctx, t) + testAccPreCheckDetectorNotExists(ctx, t) }, ErrorCheck: acctest.ErrorCheck(t, guardduty.EndpointsID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, @@ -62,6 +63,7 @@ func testAccOrganizationConfiguration_autoEnableOrganizationMembers(t *testing.T PreCheck: func() { acctest.PreCheck(ctx, t) acctest.PreCheckOrganizationsAccount(ctx, t) + testAccPreCheckDetectorNotExists(ctx, t) }, ErrorCheck: acctest.ErrorCheck(t, guardduty.EndpointsID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, @@ -160,6 +162,7 @@ func testAccOrganizationConfiguration_s3logs(t *testing.T) { PreCheck: func() { acctest.PreCheck(ctx, t) acctest.PreCheckOrganizationsAccount(ctx, t) + testAccPreCheckDetectorNotExists(ctx, t) }, ErrorCheck: acctest.ErrorCheck(t, guardduty.EndpointsID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, @@ -203,6 +206,7 @@ func testAccOrganizationConfiguration_kubernetes(t *testing.T) { PreCheck: func() { acctest.PreCheck(ctx, t) acctest.PreCheckOrganizationsAccount(ctx, t) + testAccPreCheckDetectorNotExists(ctx, t) }, ErrorCheck: acctest.ErrorCheck(t, guardduty.EndpointsID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, @@ -248,6 +252,7 @@ func testAccOrganizationConfiguration_malwareprotection(t *testing.T) { PreCheck: func() { acctest.PreCheck(ctx, t) acctest.PreCheckOrganizationsAccount(ctx, t) + testAccPreCheckDetectorNotExists(ctx, t) }, ErrorCheck: acctest.ErrorCheck(t, guardduty.EndpointsID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, diff --git a/internal/service/guardduty/publishing_destination_test.go b/internal/service/guardduty/publishing_destination_test.go index 2ce3bfb4830..8967fe67ff1 100644 --- a/internal/service/guardduty/publishing_destination_test.go +++ b/internal/service/guardduty/publishing_destination_test.go @@ -27,7 +27,10 @@ func testAccPublishingDestination_basic(t *testing.T) { kmsKeyResourceName := "aws_kms_key.gd_key" resource.Test(t, resource.TestCase{ - PreCheck: func() { acctest.PreCheck(ctx, t) }, + PreCheck: func() { + acctest.PreCheck(ctx, t) + testAccPreCheckDetectorNotExists(ctx, t) + }, ErrorCheck: acctest.ErrorCheck(t, guardduty.EndpointsID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckPublishingDestinationDestroy(ctx), @@ -56,7 +59,10 @@ func testAccPublishingDestination_disappears(t *testing.T) { bucketName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resource.Test(t, resource.TestCase{ - PreCheck: func() { acctest.PreCheck(ctx, t) }, + PreCheck: func() { + acctest.PreCheck(ctx, t) + testAccPreCheckDetectorNotExists(ctx, t) + }, ErrorCheck: acctest.ErrorCheck(t, guardduty.EndpointsID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckPublishingDestinationDestroy(ctx), diff --git a/internal/service/guardduty/threatintelset_test.go b/internal/service/guardduty/threatintelset_test.go index ca95f676c0a..985c0ea9646 100644 --- a/internal/service/guardduty/threatintelset_test.go +++ b/internal/service/guardduty/threatintelset_test.go @@ -30,7 +30,10 @@ func testAccThreatIntelSet_basic(t *testing.T) { resourceName := "aws_guardduty_threatintelset.test" resource.Test(t, resource.TestCase{ - PreCheck: func() { acctest.PreCheck(ctx, t) }, + PreCheck: func() { + acctest.PreCheck(ctx, t) + testAccPreCheckDetectorNotExists(ctx, t) + }, ErrorCheck: acctest.ErrorCheck(t, guardduty.EndpointsID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckThreatIntelSetDestroy(ctx), @@ -70,7 +73,10 @@ func testAccThreatIntelSet_tags(t *testing.T) { resourceName := "aws_guardduty_threatintelset.test" resource.Test(t, resource.TestCase{ - PreCheck: func() { acctest.PreCheck(ctx, t) }, + PreCheck: func() { + acctest.PreCheck(ctx, t) + testAccPreCheckDetectorNotExists(ctx, t) + }, ErrorCheck: acctest.ErrorCheck(t, guardduty.EndpointsID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckThreatIntelSetDestroy(ctx), From c892dba1462ebf6a895207ffc206e3a0de5351ea Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Wed, 27 Sep 2023 08:07:46 -0400 Subject: [PATCH 13/31] Acceptance test output: % make testacc TESTARGS='-run=TestAccGuardDuty_serial' PKG=guardduty ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./internal/service/guardduty/... -v -count 1 -parallel 20 -run=TestAccGuardDuty_serial -timeout 360m === RUN TestAccGuardDuty_serial === PAUSE TestAccGuardDuty_serial === CONT TestAccGuardDuty_serial === RUN TestAccGuardDuty_serial/InviteAccepter === RUN TestAccGuardDuty_serial/InviteAccepter/basic guardduty_test.go:84: Environment variable AWS_GUARDDUTY_MEMBER_ACCOUNT_ID is not set. To properly test inviting GuardDuty member accounts, a valid AWS account ID must be provided. === RUN TestAccGuardDuty_serial/IPSet === RUN TestAccGuardDuty_serial/IPSet/basic guardduty_test.go:128: this AWS account has a GuardDuty Detector === RUN TestAccGuardDuty_serial/IPSet/tags guardduty_test.go:128: this AWS account has a GuardDuty Detector === RUN TestAccGuardDuty_serial/OrganizationConfiguration === RUN TestAccGuardDuty_serial/OrganizationConfiguration/s3Logs acctest.go:926: skipping tests; this AWS account must not be an existing member of an AWS Organization === RUN TestAccGuardDuty_serial/OrganizationConfiguration/kubernetes acctest.go:926: skipping tests; this AWS account must not be an existing member of an AWS Organization === RUN TestAccGuardDuty_serial/OrganizationConfiguration/malwareProtection acctest.go:926: skipping tests; this AWS account must not be an existing member of an AWS Organization === RUN TestAccGuardDuty_serial/OrganizationConfiguration/basic acctest.go:926: skipping tests; this AWS account must not be an existing member of an AWS Organization === RUN TestAccGuardDuty_serial/OrganizationConfiguration/autoEnableOrganizationMembers acctest.go:926: skipping tests; this AWS account must not be an existing member of an AWS Organization === RUN TestAccGuardDuty_serial/Detector === RUN TestAccGuardDuty_serial/Detector/features_ebs_malware_protection guardduty_test.go:128: this AWS account has a GuardDuty Detector === RUN TestAccGuardDuty_serial/Detector/features_rds_login_events guardduty_test.go:128: this AWS account has a GuardDuty Detector === RUN TestAccGuardDuty_serial/Detector/features_eks_runtime_monitoring guardduty_test.go:128: this AWS account has a GuardDuty Detector === RUN TestAccGuardDuty_serial/Detector/datasource_basic guardduty_test.go:128: this AWS account has a GuardDuty Detector === RUN TestAccGuardDuty_serial/Detector/datasource_id guardduty_test.go:128: this AWS account has a GuardDuty Detector === RUN TestAccGuardDuty_serial/Detector/datasources_malware_protection guardduty_test.go:128: this AWS account has a GuardDuty Detector === RUN TestAccGuardDuty_serial/Detector/datasources_all guardduty_test.go:128: this AWS account has a GuardDuty Detector === RUN TestAccGuardDuty_serial/Detector/features_eks_audit_logs guardduty_test.go:128: this AWS account has a GuardDuty Detector === RUN TestAccGuardDuty_serial/Detector/features_s3_data_events guardduty_test.go:128: this AWS account has a GuardDuty Detector === RUN TestAccGuardDuty_serial/Detector/tags guardduty_test.go:128: this AWS account has a GuardDuty Detector === RUN TestAccGuardDuty_serial/Detector/basic guardduty_test.go:128: this AWS account has a GuardDuty Detector === RUN TestAccGuardDuty_serial/Detector/datasources_s3logs guardduty_test.go:128: this AWS account has a GuardDuty Detector === RUN TestAccGuardDuty_serial/Detector/datasources_kubernetes_audit_logs guardduty_test.go:128: this AWS account has a GuardDuty Detector === RUN TestAccGuardDuty_serial/Filter === RUN TestAccGuardDuty_serial/Filter/basic guardduty_test.go:128: this AWS account has a GuardDuty Detector === RUN TestAccGuardDuty_serial/Filter/update guardduty_test.go:128: this AWS account has a GuardDuty Detector === RUN TestAccGuardDuty_serial/Filter/tags guardduty_test.go:128: this AWS account has a GuardDuty Detector === RUN TestAccGuardDuty_serial/Filter/disappears guardduty_test.go:128: this AWS account has a GuardDuty Detector === RUN TestAccGuardDuty_serial/FindingIDs === RUN TestAccGuardDuty_serial/FindingIDs/datasource_basic === RUN TestAccGuardDuty_serial/OrganizationAdminAccount === RUN TestAccGuardDuty_serial/OrganizationAdminAccount/basic acctest.go:926: skipping tests; this AWS account must not be an existing member of an AWS Organization === RUN TestAccGuardDuty_serial/ThreatIntelSet === RUN TestAccGuardDuty_serial/ThreatIntelSet/basic guardduty_test.go:128: this AWS account has a GuardDuty Detector === RUN TestAccGuardDuty_serial/ThreatIntelSet/tags guardduty_test.go:128: this AWS account has a GuardDuty Detector === RUN TestAccGuardDuty_serial/Member === RUN TestAccGuardDuty_serial/Member/basic guardduty_test.go:128: this AWS account has a GuardDuty Detector === RUN TestAccGuardDuty_serial/Member/inviteOnUpdate guardduty_test.go:84: Environment variable AWS_GUARDDUTY_MEMBER_ACCOUNT_ID is not set. To properly test inviting GuardDuty member accounts, a valid AWS account ID must be provided. === RUN TestAccGuardDuty_serial/Member/inviteDisassociate guardduty_test.go:84: Environment variable AWS_GUARDDUTY_MEMBER_ACCOUNT_ID is not set. To properly test inviting GuardDuty member accounts, a valid AWS account ID must be provided. === RUN TestAccGuardDuty_serial/Member/invitationMessage guardduty_test.go:84: Environment variable AWS_GUARDDUTY_MEMBER_ACCOUNT_ID is not set. To properly test inviting GuardDuty member accounts, a valid AWS account ID must be provided. === RUN TestAccGuardDuty_serial/PublishingDestination === RUN TestAccGuardDuty_serial/PublishingDestination/basic guardduty_test.go:128: this AWS account has a GuardDuty Detector === RUN TestAccGuardDuty_serial/PublishingDestination/disappears guardduty_test.go:128: this AWS account has a GuardDuty Detector --- PASS: TestAccGuardDuty_serial (72.79s) --- PASS: TestAccGuardDuty_serial/InviteAccepter (0.00s) --- SKIP: TestAccGuardDuty_serial/InviteAccepter/basic (0.00s) --- PASS: TestAccGuardDuty_serial/IPSet (1.15s) --- SKIP: TestAccGuardDuty_serial/IPSet/basic (1.03s) --- SKIP: TestAccGuardDuty_serial/IPSet/tags (0.12s) --- PASS: TestAccGuardDuty_serial/OrganizationConfiguration (5.03s) --- SKIP: TestAccGuardDuty_serial/OrganizationConfiguration/s3Logs (0.21s) --- SKIP: TestAccGuardDuty_serial/OrganizationConfiguration/kubernetes (0.11s) --- SKIP: TestAccGuardDuty_serial/OrganizationConfiguration/malwareProtection (1.96s) --- SKIP: TestAccGuardDuty_serial/OrganizationConfiguration/basic (0.11s) --- SKIP: TestAccGuardDuty_serial/OrganizationConfiguration/autoEnableOrganizationMembers (2.64s) --- PASS: TestAccGuardDuty_serial/Detector (1.45s) --- SKIP: TestAccGuardDuty_serial/Detector/features_ebs_malware_protection (0.11s) --- SKIP: TestAccGuardDuty_serial/Detector/features_rds_login_events (0.11s) --- SKIP: TestAccGuardDuty_serial/Detector/features_eks_runtime_monitoring (0.12s) --- SKIP: TestAccGuardDuty_serial/Detector/datasource_basic (0.11s) --- SKIP: TestAccGuardDuty_serial/Detector/datasource_id (0.11s) --- SKIP: TestAccGuardDuty_serial/Detector/datasources_malware_protection (0.11s) --- SKIP: TestAccGuardDuty_serial/Detector/datasources_all (0.12s) --- SKIP: TestAccGuardDuty_serial/Detector/features_eks_audit_logs (0.11s) --- SKIP: TestAccGuardDuty_serial/Detector/features_s3_data_events (0.11s) --- SKIP: TestAccGuardDuty_serial/Detector/tags (0.12s) --- SKIP: TestAccGuardDuty_serial/Detector/basic (0.11s) --- SKIP: TestAccGuardDuty_serial/Detector/datasources_s3logs (0.11s) --- SKIP: TestAccGuardDuty_serial/Detector/datasources_kubernetes_audit_logs (0.10s) --- PASS: TestAccGuardDuty_serial/Filter (0.47s) --- SKIP: TestAccGuardDuty_serial/Filter/basic (0.12s) --- SKIP: TestAccGuardDuty_serial/Filter/update (0.11s) --- SKIP: TestAccGuardDuty_serial/Filter/tags (0.12s) --- SKIP: TestAccGuardDuty_serial/Filter/disappears (0.11s) --- PASS: TestAccGuardDuty_serial/FindingIDs (63.93s) --- PASS: TestAccGuardDuty_serial/FindingIDs/datasource_basic (63.93s) --- PASS: TestAccGuardDuty_serial/OrganizationAdminAccount (0.21s) --- SKIP: TestAccGuardDuty_serial/OrganizationAdminAccount/basic (0.21s) --- PASS: TestAccGuardDuty_serial/ThreatIntelSet (0.22s) --- SKIP: TestAccGuardDuty_serial/ThreatIntelSet/basic (0.11s) --- SKIP: TestAccGuardDuty_serial/ThreatIntelSet/tags (0.11s) --- PASS: TestAccGuardDuty_serial/Member (0.13s) --- SKIP: TestAccGuardDuty_serial/Member/basic (0.13s) --- SKIP: TestAccGuardDuty_serial/Member/inviteOnUpdate (0.00s) --- SKIP: TestAccGuardDuty_serial/Member/inviteDisassociate (0.00s) --- SKIP: TestAccGuardDuty_serial/Member/invitationMessage (0.00s) --- PASS: TestAccGuardDuty_serial/PublishingDestination (0.21s) --- SKIP: TestAccGuardDuty_serial/PublishingDestination/basic (0.11s) --- SKIP: TestAccGuardDuty_serial/PublishingDestination/disappears (0.11s) PASS ok github.com/hashicorp/terraform-provider-aws/internal/service/guardduty 78.326s From 84b6b3cf6b044e6958e8827a2e808607feea3826 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Wed, 27 Sep 2023 08:43:25 -0400 Subject: [PATCH 14/31] r/aws_guardduty_detector: Alphabetize attributes. --- internal/service/guardduty/detector.go | 58 ++++++++++++-------------- 1 file changed, 26 insertions(+), 32 deletions(-) diff --git a/internal/service/guardduty/detector.go b/internal/service/guardduty/detector.go index 2da6457091d..a4a4af24750 100644 --- a/internal/service/guardduty/detector.go +++ b/internal/service/guardduty/detector.go @@ -41,12 +41,10 @@ func ResourceDetector() *schema.Resource { Type: schema.TypeString, Computed: true, }, - "arn": { Type: schema.TypeString, Computed: true, }, - "datasources": { Type: schema.TypeList, MaxItems: 1, @@ -54,20 +52,6 @@ func ResourceDetector() *schema.Resource { Computed: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "s3_logs": { - Type: schema.TypeList, - Optional: true, - Computed: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "enable": { - Type: schema.TypeBool, - Required: true, - }, - }, - }, - }, "kubernetes": { Type: schema.TypeList, Optional: true, @@ -123,51 +107,62 @@ func ResourceDetector() *schema.Resource { }, }, }, + "s3_logs": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enable": { + Type: schema.TypeBool, + Required: true, + }, + }, + }, + }, }, }, }, - "feature": { Type: schema.TypeList, Optional: true, Computed: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Required: true, - }, - "enable": { - Type: schema.TypeBool, - Required: true, - }, "additional_configuration": { Optional: true, Computed: true, Type: schema.TypeList, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Required: true, - }, "enable": { Type: schema.TypeBool, Required: true, }, + "name": { + Type: schema.TypeString, + Required: true, + }, }, }, }, + "enable": { + Type: schema.TypeBool, + Required: true, + }, + "name": { + Type: schema.TypeString, + Required: true, + }, }, }, }, - "enable": { Type: schema.TypeBool, Optional: true, Default: true, }, - // finding_publishing_frequency is marked as Computed:true since // GuardDuty member accounts inherit setting from master account "finding_publishing_frequency": { @@ -175,7 +170,6 @@ func ResourceDetector() *schema.Resource { Optional: true, Computed: true, }, - names.AttrTags: tftags.TagsSchema(), names.AttrTagsAll: tftags.TagsSchemaComputed(), }, From c56ee3d9513c1ec3656f65ced76886c267aa224b Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Wed, 27 Sep 2023 10:07:35 -0400 Subject: [PATCH 15/31] r/aws_guardduty_detector: Add 'FindDetectorByID'. --- internal/service/guardduty/detector.go | 96 +++++++++++---------- internal/service/guardduty/detector_test.go | 40 +++------ 2 files changed, 63 insertions(+), 73 deletions(-) diff --git a/internal/service/guardduty/detector.go b/internal/service/guardduty/detector.go index a4a4af24750..c89fea5b4d6 100644 --- a/internal/service/guardduty/detector.go +++ b/internal/service/guardduty/detector.go @@ -182,15 +182,11 @@ func resourceDetectorCreate(ctx context.Context, d *schema.ResourceData, meta in var diags diag.Diagnostics conn := meta.(*conns.AWSClient).GuardDutyConn(ctx) - input := guardduty.CreateDetectorInput{ + input := &guardduty.CreateDetectorInput{ Enable: aws.Bool(d.Get("enable").(bool)), Tags: getTagsIn(ctx), } - if v, ok := d.GetOk("finding_publishing_frequency"); ok { - input.FindingPublishingFrequency = aws.String(v.(string)) - } - if v, ok := d.GetOk("datasources"); ok && len(v.([]interface{})) > 0 && v.([]interface{})[0] != nil { input.DataSources = expandDataSourceConfigurations(v.([]interface{})[0].(map[string]interface{})) } @@ -199,11 +195,16 @@ func resourceDetectorCreate(ctx context.Context, d *schema.ResourceData, meta in input.Features = expandFeaturesConfigurations(v.([]interface{})) } - log.Printf("[DEBUG] Creating GuardDuty Detector: %s", input) - output, err := conn.CreateDetectorWithContext(ctx, &input) + if v, ok := d.GetOk("finding_publishing_frequency"); ok { + input.FindingPublishingFrequency = aws.String(v.(string)) + } + + output, err := conn.CreateDetectorWithContext(ctx, input) + if err != nil { - return sdkdiag.AppendErrorf(diags, "Creating GuardDuty Detector failed: %s", err) + return sdkdiag.AppendErrorf(diags, "creating GuardDuty Detector: %s", err) } + d.SetId(aws.StringValue(output.DetectorId)) return append(diags, resourceDetectorRead(ctx, d, meta)...) @@ -213,21 +214,19 @@ func resourceDetectorRead(ctx context.Context, d *schema.ResourceData, meta inte var diags diag.Diagnostics conn := meta.(*conns.AWSClient).GuardDutyConn(ctx) - input := guardduty.GetDetectorInput{ - DetectorId: aws.String(d.Id()), + gdo, err := FindDetectorByID(ctx, conn, d.Id()) + + if !d.IsNewResource() && tfresource.NotFound(err) { + log.Printf("[WARN] GuardDuty Detector (%s) not found, removing from state", d.Id()) + d.SetId("") + return diags } - log.Printf("[DEBUG] Reading GuardDuty Detector: %s", input) - gdo, err := conn.GetDetectorWithContext(ctx, &input) if err != nil { - if tfawserr.ErrMessageContains(err, guardduty.ErrCodeBadRequestException, "The request is rejected because the input detectorId is not owned by the current account.") { - log.Printf("[WARN] GuardDuty detector %q not found, removing from state", d.Id()) - d.SetId("") - return diags - } - return sdkdiag.AppendErrorf(diags, "Reading GuardDuty Detector '%s' failed: %s", d.Id(), err) + return sdkdiag.AppendErrorf(diags, "reading GuardDuty Detector (%s): %s", d.Id(), err) } + d.Set("account_id", meta.(*conns.AWSClient).AccountID) arn := arn.ARN{ Partition: meta.(*conns.AWSClient).Partition, Region: meta.(*conns.AWSClient).Region, @@ -237,8 +236,6 @@ func resourceDetectorRead(ctx context.Context, d *schema.ResourceData, meta inte }.String() d.Set("arn", arn) - d.Set("account_id", meta.(*conns.AWSClient).AccountID) - if gdo.DataSources != nil { if err := d.Set("datasources", []interface{}{flattenDataSourceConfigurationsResult(gdo.DataSources)}); err != nil { return sdkdiag.AppendErrorf(diags, "setting datasources: %s", err) @@ -246,7 +243,7 @@ func resourceDetectorRead(ctx context.Context, d *schema.ResourceData, meta inte } else { d.Set("datasources", nil) } - + d.Set("enable", aws.StringValue(gdo.Status) == guardduty.DetectorStatusEnabled) if gdo.Features != nil { if err := d.Set("feature", flattenFeaturesConfigurationsResult(gdo.Features)); err != nil { return sdkdiag.AppendErrorf(diags, "setting feature: %s", err) @@ -254,8 +251,6 @@ func resourceDetectorRead(ctx context.Context, d *schema.ResourceData, meta inte } else { d.Set("feature", nil) } - - d.Set("enable", aws.StringValue(gdo.Status) == guardduty.DetectorStatusEnabled) d.Set("finding_publishing_frequency", gdo.FindingPublishingFrequency) setTagsOut(ctx, gdo.Tags) @@ -268,7 +263,7 @@ func resourceDetectorUpdate(ctx context.Context, d *schema.ResourceData, meta in conn := meta.(*conns.AWSClient).GuardDutyConn(ctx) if d.HasChangesExcept("tags", "tags_all") { - input := guardduty.UpdateDetectorInput{ + input := &guardduty.UpdateDetectorInput{ DetectorId: aws.String(d.Id()), Enable: aws.Bool(d.Get("enable").(bool)), FindingPublishingFrequency: aws.String(d.Get("finding_publishing_frequency").(string)), @@ -282,8 +277,8 @@ func resourceDetectorUpdate(ctx context.Context, d *schema.ResourceData, meta in input.Features = expandFeaturesConfigurations(d.Get("feature").([]interface{})) } - log.Printf("[DEBUG] Update GuardDuty Detector: %s", input) - _, err := conn.UpdateDetectorWithContext(ctx, &input) + _, err := conn.UpdateDetectorWithContext(ctx, input) + if err != nil { return sdkdiag.AppendErrorf(diags, "updating GuardDuty Detector (%s): %s", d.Id(), err) } @@ -296,26 +291,15 @@ func resourceDetectorDelete(ctx context.Context, d *schema.ResourceData, meta in var diags diag.Diagnostics conn := meta.(*conns.AWSClient).GuardDutyConn(ctx) - input := &guardduty.DeleteDetectorInput{ - DetectorId: aws.String(d.Id()), - } - - err := retry.RetryContext(ctx, membershipPropagationTimeout, func() *retry.RetryError { - _, err := conn.DeleteDetectorWithContext(ctx, input) + log.Printf("[DEBUG] Deleting GuardDuty Detector: %s", d.Id()) + _, err := tfresource.RetryWhenAWSErrMessageContains(ctx, membershipPropagationTimeout, func() (interface{}, error) { + return conn.DeleteDetectorWithContext(ctx, &guardduty.DeleteDetectorInput{ + DetectorId: aws.String(d.Id()), + }) + }, guardduty.ErrCodeBadRequestException, "cannot delete detector while it has invited or associated members") - if tfawserr.ErrMessageContains(err, guardduty.ErrCodeBadRequestException, "cannot delete detector while it has invited or associated members") { - return retry.RetryableError(err) - } - - if err != nil { - return retry.NonRetryableError(err) - } - - return nil - }) - - if tfresource.TimedOut(err) { - _, err = conn.DeleteDetectorWithContext(ctx, input) + if tfawserr.ErrMessageContains(err, guardduty.ErrCodeBadRequestException, "The request is rejected because the input detectorId is not owned by the current account.") { + return diags } if err != nil { @@ -651,6 +635,28 @@ func flattenFeaturesAdditionalConfigurationsResult(detectorAdditionalFeatureConf return result } +func FindDetectorByID(ctx context.Context, conn *guardduty.GuardDuty, id string) (*guardduty.GetDetectorOutput, error) { + input := &guardduty.GetDetectorInput{ + DetectorId: aws.String(id), + } + + output, err := conn.GetDetectorWithContext(ctx, input) + + if tfawserr.ErrMessageContains(err, guardduty.ErrCodeBadRequestException, "The request is rejected because the input detectorId is not owned by the current account.") { + return nil, &retry.NotFoundError{ + LastError: err, + LastRequest: input, + } + } + + if err != nil { + return nil, err + } + + return output, nil +} + +// FindDetector returns the ID of the current account's active GuardDuty detector. func FindDetector(ctx context.Context, conn *guardduty.GuardDuty) (*string, error) { output, err := findDetectors(ctx, conn) diff --git a/internal/service/guardduty/detector_test.go b/internal/service/guardduty/detector_test.go index edebb86f5a6..9ccb5563c5a 100644 --- a/internal/service/guardduty/detector_test.go +++ b/internal/service/guardduty/detector_test.go @@ -9,13 +9,13 @@ import ( "testing" "github.com/YakDriver/regexache" - "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/guardduty" - "github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr" "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" + tfguardduty "github.com/hashicorp/terraform-provider-aws/internal/service/guardduty" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" ) func testAccDetector_basic(t *testing.T) { @@ -770,51 +770,35 @@ func testAccCheckDetectorDestroy(ctx context.Context) resource.TestCheckFunc { continue } - input := &guardduty.GetDetectorInput{ - DetectorId: aws.String(rs.Primary.ID), + _, err := tfguardduty.FindDetectorByID(ctx, conn, rs.Primary.ID) + + if tfresource.NotFound(err) { + continue } - _, err := conn.GetDetectorWithContext(ctx, input) if err != nil { - if tfawserr.ErrMessageContains(err, guardduty.ErrCodeBadRequestException, "The request is rejected because the input detectorId is not owned by the current account.") { - return nil - } return err } - return fmt.Errorf("Expected GuardDuty Detector to be destroyed, %s found", rs.Primary.ID) + return fmt.Errorf("GuardDuty Detector %s still exists", rs.Primary.ID) } return nil } } -func testAccCheckDetectorExists(ctx context.Context, name string) resource.TestCheckFunc { +func testAccCheckDetectorExists(ctx context.Context, n string) resource.TestCheckFunc { return func(s *terraform.State) error { - rs, ok := s.RootModule().Resources[name] + rs, ok := s.RootModule().Resources[n] if !ok { - return fmt.Errorf("Not found: %s", name) - } - - if rs.Primary.ID == "" { - return fmt.Errorf("Resource (%s) has empty ID", name) + return fmt.Errorf("Not found: %s", n) } conn := acctest.Provider.Meta().(*conns.AWSClient).GuardDutyConn(ctx) - output, err := conn.GetDetectorWithContext(ctx, &guardduty.GetDetectorInput{ - DetectorId: aws.String(rs.Primary.ID), - }) + _, err := tfguardduty.FindDetectorByID(ctx, conn, rs.Primary.ID) - if err != nil { - return err - } - - if output == nil { - return fmt.Errorf("GuardDuty Detector not found: %s", name) - } - - return nil + return err } } From 3d5208f7c6b70e8eab9e918c441f8e2ae18c5e9e Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Wed, 27 Sep 2023 10:29:17 -0400 Subject: [PATCH 16/31] r/aws_guardduty_detector: Tidy up flex. --- internal/service/guardduty/detector.go | 112 +++++++++--------- .../service/guardduty/detector_data_source.go | 2 +- 2 files changed, 60 insertions(+), 54 deletions(-) diff --git a/internal/service/guardduty/detector.go b/internal/service/guardduty/detector.go index c89fea5b4d6..a99cb7d4401 100644 --- a/internal/service/guardduty/detector.go +++ b/internal/service/guardduty/detector.go @@ -192,7 +192,7 @@ func resourceDetectorCreate(ctx context.Context, d *schema.ResourceData, meta in } if v, ok := d.GetOk("feature"); ok && len(v.([]interface{})) > 0 { - input.Features = expandFeaturesConfigurations(v.([]interface{})) + input.Features = expandDetectorFeatureConfigurations(v.([]interface{})) } if v, ok := d.GetOk("finding_publishing_frequency"); ok { @@ -245,7 +245,7 @@ func resourceDetectorRead(ctx context.Context, d *schema.ResourceData, meta inte } d.Set("enable", aws.StringValue(gdo.Status) == guardduty.DetectorStatusEnabled) if gdo.Features != nil { - if err := d.Set("feature", flattenFeaturesConfigurationsResult(gdo.Features)); err != nil { + if err := d.Set("feature", flattenDetectorFeatureConfigurationResults(gdo.Features)); err != nil { return sdkdiag.AppendErrorf(diags, "setting feature: %s", err) } } else { @@ -274,7 +274,7 @@ func resourceDetectorUpdate(ctx context.Context, d *schema.ResourceData, meta in } if d.HasChange("feature") { - input.Features = expandFeaturesConfigurations(d.Get("feature").([]interface{})) + input.Features = expandDetectorFeatureConfigurations(d.Get("feature").([]interface{})) } _, err := conn.UpdateDetectorWithContext(ctx, input) @@ -316,27 +316,16 @@ func expandDataSourceConfigurations(tfMap map[string]interface{}) *guardduty.Dat apiObject := &guardduty.DataSourceConfigurations{} - if v, ok := tfMap["s3_logs"].([]interface{}); ok && len(v) > 0 { - apiObject.S3Logs = expandS3LogsConfiguration(v[0].(map[string]interface{})) - } if v, ok := tfMap["kubernetes"].([]interface{}); ok && len(v) > 0 { apiObject.Kubernetes = expandKubernetesConfiguration(v[0].(map[string]interface{})) } + if v, ok := tfMap["malware_protection"].([]interface{}); ok && len(v) > 0 { apiObject.MalwareProtection = expandMalwareProtectionConfiguration(v[0].(map[string]interface{})) } - return apiObject -} - -func expandS3LogsConfiguration(tfMap map[string]interface{}) *guardduty.S3LogsConfiguration { - if tfMap == nil { - return nil - } - apiObject := &guardduty.S3LogsConfiguration{} - - if v, ok := tfMap["enable"].(bool); ok { - apiObject.Enable = aws.Bool(v) + if v, ok := tfMap["s3_logs"].([]interface{}); ok && len(v) > 0 { + apiObject.S3Logs = expandS3LogsConfiguration(v[0].(map[string]interface{})) } return apiObject @@ -392,11 +381,11 @@ func expandMalwareProtectionConfiguration(tfMap map[string]interface{}) *guarddu } return &guardduty.MalwareProtectionConfiguration{ - ScanEc2InstanceWithFindings: expandMalwareProtectionScanEC2InstanceWithFindingsConfiguration(m), + ScanEc2InstanceWithFindings: expandScanEc2InstanceWithFindings(m), } } -func expandMalwareProtectionScanEC2InstanceWithFindingsConfiguration(tfMap map[string]interface{}) *guardduty.ScanEc2InstanceWithFindings { +func expandScanEc2InstanceWithFindings(tfMap map[string]interface{}) *guardduty.ScanEc2InstanceWithFindings { if tfMap == nil { return nil } @@ -414,6 +403,7 @@ func expandMalwareProtectionScanEC2InstanceWithFindingsConfiguration(tfMap map[s apiObject := &guardduty.ScanEc2InstanceWithFindings{ EbsVolumes: expandMalwareProtectionEBSVolumesConfiguration(m), } + return apiObject } @@ -431,12 +421,27 @@ func expandMalwareProtectionEBSVolumesConfiguration(tfMap map[string]interface{} return apiObject } -func expandFeaturesConfigurations(items []interface{}) []*guardduty.DetectorFeatureConfiguration { +func expandS3LogsConfiguration(tfMap map[string]interface{}) *guardduty.S3LogsConfiguration { + if tfMap == nil { + return nil + } + + apiObject := &guardduty.S3LogsConfiguration{} + + if v, ok := tfMap["enable"].(bool); ok { + apiObject.Enable = aws.Bool(v) + } + + return apiObject +} + +func expandDetectorFeatureConfigurations(items []interface{}) []*guardduty.DetectorFeatureConfiguration { if items == nil { return nil } detectorFeatureConfigurations := make([]*guardduty.DetectorFeatureConfiguration, 0, len(items)) + for _, l := range items { if l == nil { continue @@ -446,17 +451,17 @@ func expandFeaturesConfigurations(items []interface{}) []*guardduty.DetectorFeat detectorFeatureConfiguration := &guardduty.DetectorFeatureConfiguration{ Name: aws.String(m["name"].(string)), } + if v, ok := m["enable"].(bool); ok { if v { - enabled := guardduty.FeatureStatusEnabled - detectorFeatureConfiguration.Status = &enabled + detectorFeatureConfiguration.Status = aws.String(guardduty.FeatureStatusEnabled) } else { - disabled := guardduty.FeatureStatusDisabled - detectorFeatureConfiguration.Status = &disabled + detectorFeatureConfiguration.Status = aws.String(guardduty.FeatureStatusDisabled) } } + if a, ok := m["additional_configuration"].([]interface{}); ok { - detectorFeatureConfiguration.AdditionalConfiguration = expandFeaturesAdditionalConfigurations(a) + detectorFeatureConfiguration.AdditionalConfiguration = expandDetectorAdditionalConfigurations(a) } detectorFeatureConfigurations = append(detectorFeatureConfigurations, detectorFeatureConfiguration) @@ -465,12 +470,13 @@ func expandFeaturesConfigurations(items []interface{}) []*guardduty.DetectorFeat return detectorFeatureConfigurations } -func expandFeaturesAdditionalConfigurations(items []interface{}) []*guardduty.DetectorAdditionalConfiguration { +func expandDetectorAdditionalConfigurations(items []interface{}) []*guardduty.DetectorAdditionalConfiguration { if items == nil { return nil } detectorFeatureAdditionalConfigurations := make([]*guardduty.DetectorAdditionalConfiguration, 0, len(items)) + for _, l := range items { if l == nil { continue @@ -480,13 +486,12 @@ func expandFeaturesAdditionalConfigurations(items []interface{}) []*guardduty.De detectorFeatureAdditionalConfiguration := &guardduty.DetectorAdditionalConfiguration{ Name: aws.String(m["name"].(string)), } + if v, ok := m["enable"].(bool); ok { if v { - enabled := guardduty.FeatureStatusEnabled - detectorFeatureAdditionalConfiguration.Status = &enabled + detectorFeatureAdditionalConfiguration.Status = aws.String(guardduty.FeatureStatusEnabled) } else { - disabled := guardduty.FeatureStatusDisabled - detectorFeatureAdditionalConfiguration.Status = &disabled + detectorFeatureAdditionalConfiguration.Status = aws.String(guardduty.FeatureStatusDisabled) } } @@ -503,10 +508,6 @@ func flattenDataSourceConfigurationsResult(apiObject *guardduty.DataSourceConfig tfMap := map[string]interface{}{} - if v := apiObject.S3Logs; v != nil { - tfMap["s3_logs"] = []interface{}{flattenS3LogsConfigurationResult(v)} - } - if v := apiObject.Kubernetes; v != nil { tfMap["kubernetes"] = []interface{}{flattenKubernetesConfiguration(v)} } @@ -515,18 +516,8 @@ func flattenDataSourceConfigurationsResult(apiObject *guardduty.DataSourceConfig tfMap["malware_protection"] = []interface{}{flattenMalwareProtectionConfiguration(v)} } - return tfMap -} - -func flattenS3LogsConfigurationResult(apiObject *guardduty.S3LogsConfigurationResult) map[string]interface{} { - if apiObject == nil { - return nil - } - - tfMap := map[string]interface{}{} - - if v := apiObject.Status; v != nil { - tfMap["enable"] = aws.StringValue(v) == guardduty.DataSourceStatusEnabled + if v := apiObject.S3Logs; v != nil { + tfMap["s3_logs"] = []interface{}{flattenS3LogsConfigurationResult(v)} } return tfMap @@ -568,13 +559,13 @@ func flattenMalwareProtectionConfiguration(apiObject *guardduty.MalwareProtectio tfMap := map[string]interface{}{} if v := apiObject.ScanEc2InstanceWithFindings; v != nil { - tfMap["scan_ec2_instance_with_findings"] = []interface{}{flattenMalwareProtectionScanEC2InstanceWithFindingsConfigurationResult(v)} + tfMap["scan_ec2_instance_with_findings"] = []interface{}{flattenScanEc2InstanceWithFindingsResult(v)} } return tfMap } -func flattenMalwareProtectionScanEC2InstanceWithFindingsConfigurationResult(apiObject *guardduty.ScanEc2InstanceWithFindingsResult) map[string]interface{} { +func flattenScanEc2InstanceWithFindingsResult(apiObject *guardduty.ScanEc2InstanceWithFindingsResult) map[string]interface{} { if apiObject == nil { return nil } @@ -582,13 +573,13 @@ func flattenMalwareProtectionScanEC2InstanceWithFindingsConfigurationResult(apiO tfMap := map[string]interface{}{} if v := apiObject.EbsVolumes; v != nil { - tfMap["ebs_volumes"] = []interface{}{flattenMalwareProtectionEBSVolumesConfigurationResult(v)} + tfMap["ebs_volumes"] = []interface{}{flattenEbsVolumesResult(v)} } return tfMap } -func flattenMalwareProtectionEBSVolumesConfigurationResult(apiObject *guardduty.EbsVolumesResult) map[string]interface{} { +func flattenEbsVolumesResult(apiObject *guardduty.EbsVolumesResult) map[string]interface{} { if apiObject == nil { return nil } @@ -602,24 +593,39 @@ func flattenMalwareProtectionEBSVolumesConfigurationResult(apiObject *guardduty. return tfMap } -func flattenFeaturesConfigurationsResult(detectorFeatureConfigurations []*guardduty.DetectorFeatureConfigurationResult) []interface{} { +func flattenS3LogsConfigurationResult(apiObject *guardduty.S3LogsConfigurationResult) map[string]interface{} { + if apiObject == nil { + return nil + } + + tfMap := map[string]interface{}{} + + if v := apiObject.Status; v != nil { + tfMap["enable"] = aws.StringValue(v) == guardduty.DataSourceStatusEnabled + } + + return tfMap +} + +func flattenDetectorFeatureConfigurationResults(detectorFeatureConfigurations []*guardduty.DetectorFeatureConfigurationResult) []interface{} { if len(detectorFeatureConfigurations) == 0 { return []interface{}{} } result := make([]interface{}, len(detectorFeatureConfigurations)) + for i, detectorFeatureConfiguration := range detectorFeatureConfigurations { result[i] = map[string]interface{}{ "name": aws.StringValue(detectorFeatureConfiguration.Name), "enable": aws.StringValue(detectorFeatureConfiguration.Status) == guardduty.FeatureStatusEnabled, - "additional_configuration": flattenFeaturesAdditionalConfigurationsResult(detectorFeatureConfiguration.AdditionalConfiguration), + "additional_configuration": flattenDetectorAdditionalConfigurationResults(detectorFeatureConfiguration.AdditionalConfiguration), } } return result } -func flattenFeaturesAdditionalConfigurationsResult(detectorAdditionalFeatureConfigurations []*guardduty.DetectorAdditionalConfigurationResult) []interface{} { +func flattenDetectorAdditionalConfigurationResults(detectorAdditionalFeatureConfigurations []*guardduty.DetectorAdditionalConfigurationResult) []interface{} { if len(detectorAdditionalFeatureConfigurations) == 0 { return []interface{}{} } diff --git a/internal/service/guardduty/detector_data_source.go b/internal/service/guardduty/detector_data_source.go index b6b1f28d5b4..48685882eaa 100644 --- a/internal/service/guardduty/detector_data_source.go +++ b/internal/service/guardduty/detector_data_source.go @@ -117,7 +117,7 @@ func dataSourceDetectorRead(ctx context.Context, d *schema.ResourceData, meta in d.Set("service_role_arn", getResp.ServiceRole) d.Set("finding_publishing_frequency", getResp.FindingPublishingFrequency) if getResp.Features != nil { - if err := d.Set("features", flattenFeaturesConfigurationsResult(getResp.Features)); err != nil { + if err := d.Set("features", flattenDetectorFeatureConfigurationResults(getResp.Features)); err != nil { return sdkdiag.AppendErrorf(diags, "setting features: %s", err) } } else { From bce6c0c3668612b5f0ec8c025e6c618f309a4774 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Wed, 27 Sep 2023 10:31:16 -0400 Subject: [PATCH 17/31] Add CHANGELOG entry. --- .changelog/31463.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/31463.txt diff --git a/.changelog/31463.txt b/.changelog/31463.txt new file mode 100644 index 00000000000..6ee14703a7e --- /dev/null +++ b/.changelog/31463.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +resource/aws_guardduty_detector: Add `feature` configuration block +``` \ No newline at end of file From 13240271abe26e6a81f35816e46d2a9175316c49 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Thu, 28 Sep 2023 11:54:43 -0400 Subject: [PATCH 18/31] Replace 'aws_guardduty_detector.feature' attribute with new resource 'aws_guardduty_detector_feature'. --- .changelog/31463.txt | 4 +- internal/service/guardduty/detector.go | 149 ------ .../service/guardduty/detector_feature.go | 332 ++++++++++++ internal/service/guardduty/detector_test.go | 502 ------------------ internal/service/guardduty/guardduty_test.go | 5 - .../service/guardduty/service_package_gen.go | 5 + .../docs/r/guardduty_detector.html.markdown | 55 +- .../guardduty_detector_feature.html.markdown | 52 ++ 8 files changed, 394 insertions(+), 710 deletions(-) create mode 100644 internal/service/guardduty/detector_feature.go create mode 100644 website/docs/r/guardduty_detector_feature.html.markdown diff --git a/.changelog/31463.txt b/.changelog/31463.txt index 6ee14703a7e..62022c88082 100644 --- a/.changelog/31463.txt +++ b/.changelog/31463.txt @@ -1,3 +1,3 @@ -```release-note:enhancement -resource/aws_guardduty_detector: Add `feature` configuration block +```release-note:new-resource +aws_guardduty_detector_feature ``` \ No newline at end of file diff --git a/internal/service/guardduty/detector.go b/internal/service/guardduty/detector.go index a99cb7d4401..54f89212a9f 100644 --- a/internal/service/guardduty/detector.go +++ b/internal/service/guardduty/detector.go @@ -124,40 +124,6 @@ func ResourceDetector() *schema.Resource { }, }, }, - "feature": { - Type: schema.TypeList, - Optional: true, - Computed: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "additional_configuration": { - Optional: true, - Computed: true, - Type: schema.TypeList, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "enable": { - Type: schema.TypeBool, - Required: true, - }, - "name": { - Type: schema.TypeString, - Required: true, - }, - }, - }, - }, - "enable": { - Type: schema.TypeBool, - Required: true, - }, - "name": { - Type: schema.TypeString, - Required: true, - }, - }, - }, - }, "enable": { Type: schema.TypeBool, Optional: true, @@ -191,10 +157,6 @@ func resourceDetectorCreate(ctx context.Context, d *schema.ResourceData, meta in input.DataSources = expandDataSourceConfigurations(v.([]interface{})[0].(map[string]interface{})) } - if v, ok := d.GetOk("feature"); ok && len(v.([]interface{})) > 0 { - input.Features = expandDetectorFeatureConfigurations(v.([]interface{})) - } - if v, ok := d.GetOk("finding_publishing_frequency"); ok { input.FindingPublishingFrequency = aws.String(v.(string)) } @@ -244,13 +206,6 @@ func resourceDetectorRead(ctx context.Context, d *schema.ResourceData, meta inte d.Set("datasources", nil) } d.Set("enable", aws.StringValue(gdo.Status) == guardduty.DetectorStatusEnabled) - if gdo.Features != nil { - if err := d.Set("feature", flattenDetectorFeatureConfigurationResults(gdo.Features)); err != nil { - return sdkdiag.AppendErrorf(diags, "setting feature: %s", err) - } - } else { - d.Set("feature", nil) - } d.Set("finding_publishing_frequency", gdo.FindingPublishingFrequency) setTagsOut(ctx, gdo.Tags) @@ -273,10 +228,6 @@ func resourceDetectorUpdate(ctx context.Context, d *schema.ResourceData, meta in input.DataSources = expandDataSourceConfigurations(d.Get("datasources").([]interface{})[0].(map[string]interface{})) } - if d.HasChange("feature") { - input.Features = expandDetectorFeatureConfigurations(d.Get("feature").([]interface{})) - } - _, err := conn.UpdateDetectorWithContext(ctx, input) if err != nil { @@ -435,72 +386,6 @@ func expandS3LogsConfiguration(tfMap map[string]interface{}) *guardduty.S3LogsCo return apiObject } -func expandDetectorFeatureConfigurations(items []interface{}) []*guardduty.DetectorFeatureConfiguration { - if items == nil { - return nil - } - - detectorFeatureConfigurations := make([]*guardduty.DetectorFeatureConfiguration, 0, len(items)) - - for _, l := range items { - if l == nil { - continue - } - - m := l.(map[string]interface{}) - detectorFeatureConfiguration := &guardduty.DetectorFeatureConfiguration{ - Name: aws.String(m["name"].(string)), - } - - if v, ok := m["enable"].(bool); ok { - if v { - detectorFeatureConfiguration.Status = aws.String(guardduty.FeatureStatusEnabled) - } else { - detectorFeatureConfiguration.Status = aws.String(guardduty.FeatureStatusDisabled) - } - } - - if a, ok := m["additional_configuration"].([]interface{}); ok { - detectorFeatureConfiguration.AdditionalConfiguration = expandDetectorAdditionalConfigurations(a) - } - - detectorFeatureConfigurations = append(detectorFeatureConfigurations, detectorFeatureConfiguration) - } - - return detectorFeatureConfigurations -} - -func expandDetectorAdditionalConfigurations(items []interface{}) []*guardduty.DetectorAdditionalConfiguration { - if items == nil { - return nil - } - - detectorFeatureAdditionalConfigurations := make([]*guardduty.DetectorAdditionalConfiguration, 0, len(items)) - - for _, l := range items { - if l == nil { - continue - } - - m := l.(map[string]interface{}) - detectorFeatureAdditionalConfiguration := &guardduty.DetectorAdditionalConfiguration{ - Name: aws.String(m["name"].(string)), - } - - if v, ok := m["enable"].(bool); ok { - if v { - detectorFeatureAdditionalConfiguration.Status = aws.String(guardduty.FeatureStatusEnabled) - } else { - detectorFeatureAdditionalConfiguration.Status = aws.String(guardduty.FeatureStatusDisabled) - } - } - - detectorFeatureAdditionalConfigurations = append(detectorFeatureAdditionalConfigurations, detectorFeatureAdditionalConfiguration) - } - - return detectorFeatureAdditionalConfigurations -} - func flattenDataSourceConfigurationsResult(apiObject *guardduty.DataSourceConfigurationsResult) map[string]interface{} { if apiObject == nil { return nil @@ -607,40 +492,6 @@ func flattenS3LogsConfigurationResult(apiObject *guardduty.S3LogsConfigurationRe return tfMap } -func flattenDetectorFeatureConfigurationResults(detectorFeatureConfigurations []*guardduty.DetectorFeatureConfigurationResult) []interface{} { - if len(detectorFeatureConfigurations) == 0 { - return []interface{}{} - } - - result := make([]interface{}, len(detectorFeatureConfigurations)) - - for i, detectorFeatureConfiguration := range detectorFeatureConfigurations { - result[i] = map[string]interface{}{ - "name": aws.StringValue(detectorFeatureConfiguration.Name), - "enable": aws.StringValue(detectorFeatureConfiguration.Status) == guardduty.FeatureStatusEnabled, - "additional_configuration": flattenDetectorAdditionalConfigurationResults(detectorFeatureConfiguration.AdditionalConfiguration), - } - } - - return result -} - -func flattenDetectorAdditionalConfigurationResults(detectorAdditionalFeatureConfigurations []*guardduty.DetectorAdditionalConfigurationResult) []interface{} { - if len(detectorAdditionalFeatureConfigurations) == 0 { - return []interface{}{} - } - - result := make([]interface{}, len(detectorAdditionalFeatureConfigurations)) - for i, detectorAdditionalFeatureConfiguration := range detectorAdditionalFeatureConfigurations { - result[i] = map[string]interface{}{ - "name": detectorAdditionalFeatureConfiguration.Name, - "enable": aws.StringValue(detectorAdditionalFeatureConfiguration.Status) == guardduty.FeatureStatusEnabled, - } - } - - return result -} - func FindDetectorByID(ctx context.Context, conn *guardduty.GuardDuty, id string) (*guardduty.GetDetectorOutput, error) { input := &guardduty.GetDetectorInput{ DetectorId: aws.String(id), diff --git a/internal/service/guardduty/detector_feature.go b/internal/service/guardduty/detector_feature.go new file mode 100644 index 00000000000..aa2ad9e0ee3 --- /dev/null +++ b/internal/service/guardduty/detector_feature.go @@ -0,0 +1,332 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package guardduty + +import ( + "context" + "fmt" + "log" + "strings" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/guardduty" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" + "github.com/hashicorp/terraform-provider-aws/internal/conns" + "github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag" + tfslices "github.com/hashicorp/terraform-provider-aws/internal/slices" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" +) + +// @SDKResource("aws_guardduty_detector_feature", name="Detector Feature") +func ResourceDetectorFeature() *schema.Resource { + return &schema.Resource{ + CreateWithoutTimeout: resourceDetectorFeaturePut, + ReadWithoutTimeout: resourceDetectorFeatureRead, + UpdateWithoutTimeout: resourceDetectorFeaturePut, + DeleteWithoutTimeout: schema.NoopContext, + + Schema: map[string]*schema.Schema{ + "additional_configuration": { + Optional: true, + ForceNew: true, + Type: schema.TypeList, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice(guardduty.FeatureAdditionalConfiguration_Values(), false), + }, + "status": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice(guardduty.FeatureStatus_Values(), false), + }, + }, + }, + }, + "detector_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice(guardduty.DetectorFeature_Values(), false), + }, + "status": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice(guardduty.FeatureStatus_Values(), false), + }, + }, + } +} + +func resourceDetectorFeaturePut(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + var diags diag.Diagnostics + conn := meta.(*conns.AWSClient).GuardDutyConn(ctx) + + detectorID, name := d.Get("detector_id").(string), d.Get("name").(string) + feature := &guardduty.DetectorFeatureConfiguration{ + Name: aws.String(name), + Status: aws.String(d.Get("status").(string)), + } + + if v, ok := d.GetOk("additional_configuration"); ok && len(v.([]interface{})) > 0 { + feature.AdditionalConfiguration = expandDetectorAdditionalConfigurations(v.([]interface{})) + } + + input := &guardduty.UpdateDetectorInput{ + DetectorId: aws.String(detectorID), + Features: []*guardduty.DetectorFeatureConfiguration{feature}, + } + + _, err := conn.UpdateDetectorWithContext(ctx, input) + + if err != nil { + return sdkdiag.AppendErrorf(diags, "updating GuardDuty Detector (%s) Feature (%s): %s", detectorID, name, err) + } + + if d.IsNewResource() { + d.SetId(detectorFeatureCreateResourceID(detectorID, name)) + } + + return append(diags, resourceDetectorFeatureRead(ctx, d, meta)...) +} + +func resourceDetectorFeatureRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + var diags diag.Diagnostics + conn := meta.(*conns.AWSClient).GuardDutyConn(ctx) + + detectorID, name, err := detectorFeatureParseResourceID(d.Id()) + if err != nil { + return sdkdiag.AppendFromErr(diags, err) + } + + feature, err := FindDetectorFeatureByTwoPartKey(ctx, conn, detectorID, name) + + if !d.IsNewResource() && tfresource.NotFound(err) { + log.Printf("[WARN] GuardDuty Detector Feature (%s) not found, removing from state", d.Id()) + d.SetId("") + return diags + } + + if err != nil { + return sdkdiag.AppendErrorf(diags, "reading GuardDuty Detector Feature (%s): %s", d.Id(), err) + } + + if err := d.Set("additional_configuration", flattenDetectorAdditionalConfigurationResults(feature.AdditionalConfiguration)); err != nil { + return sdkdiag.AppendErrorf(diags, "setting additional_configuration: %s", err) + } + d.Set("detector_id", detectorID) + d.Set("name", feature.Name) + d.Set("status", feature.Status) + + return diags +} + +const detectorFeatureResourceIDSeparator = "/" + +func detectorFeatureCreateResourceID(detectorID, name string) string { + parts := []string{detectorID, name} + id := strings.Join(parts, detectorFeatureResourceIDSeparator) + + return id +} + +func detectorFeatureParseResourceID(id string) (string, string, error) { + parts := strings.Split(id, detectorFeatureResourceIDSeparator) + + if len(parts) == 2 && parts[0] != "" && parts[1] != "" { + return parts[0], parts[1], nil + } + + return "", "", fmt.Errorf("unexpected format for ID (%[1]s), expected DETECTORID%[2]sFEATURENAME", id, detectorFeatureResourceIDSeparator) +} + +func FindDetectorFeatureByTwoPartKey(ctx context.Context, conn *guardduty.GuardDuty, detectorID, name string) (*guardduty.DetectorFeatureConfigurationResult, error) { + output, err := FindDetectorByID(ctx, conn, detectorID) + + if err != nil { + return nil, err + } + + return tfresource.AssertSinglePtrResult(tfslices.Filter(output.Features, func(v *guardduty.DetectorFeatureConfigurationResult) bool { + return aws.StringValue(v.Name) == name + })) +} + +func expandDetectorFeatureConfiguration(tfMap map[string]interface{}) *guardduty.DetectorFeatureConfiguration { + if tfMap == nil { + return nil + } + + apiObject := &guardduty.DetectorFeatureConfiguration{} + + if v, ok := tfMap["additional_configuration"].([]interface{}); ok && len(v) > 0 { + apiObject.AdditionalConfiguration = expandDetectorAdditionalConfigurations(v) + } + + if v, ok := tfMap["name"].(string); ok && v != "" { + apiObject.Name = aws.String(v) + } + + if v, ok := tfMap["status"].(string); ok && v != "" { + apiObject.Status = aws.String(v) + } + + return apiObject +} + +func expandDetectorFeatureConfigurations(tfList []interface{}) []*guardduty.DetectorFeatureConfiguration { + if len(tfList) == 0 { + return nil + } + + var apiObjects []*guardduty.DetectorFeatureConfiguration + + for _, tfMapRaw := range tfList { + tfMap, ok := tfMapRaw.(map[string]interface{}) + + if !ok { + continue + } + + apiObject := expandDetectorFeatureConfiguration(tfMap) + + if apiObject == nil { + continue + } + + apiObjects = append(apiObjects, apiObject) + } + + return apiObjects +} + +func expandDetectorAdditionalConfiguration(tfMap map[string]interface{}) *guardduty.DetectorAdditionalConfiguration { + if tfMap == nil { + return nil + } + + apiObject := &guardduty.DetectorAdditionalConfiguration{} + + if v, ok := tfMap["name"].(string); ok && v != "" { + apiObject.Name = aws.String(v) + } + + if v, ok := tfMap["status"].(string); ok && v != "" { + apiObject.Status = aws.String(v) + } + + return apiObject +} + +func expandDetectorAdditionalConfigurations(tfList []interface{}) []*guardduty.DetectorAdditionalConfiguration { + if len(tfList) == 0 { + return nil + } + + var apiObjects []*guardduty.DetectorAdditionalConfiguration + + for _, tfMapRaw := range tfList { + tfMap, ok := tfMapRaw.(map[string]interface{}) + + if !ok { + continue + } + + apiObject := expandDetectorAdditionalConfiguration(tfMap) + + if apiObject == nil { + continue + } + + apiObjects = append(apiObjects, apiObject) + } + + return apiObjects +} + +func flattenDetectorFeatureConfigurationResult(apiObject *guardduty.DetectorFeatureConfigurationResult) map[string]interface{} { + if apiObject == nil { + return nil + } + + tfMap := map[string]interface{}{} + + if v := apiObject.AdditionalConfiguration; v != nil { + tfMap["additional_configuration"] = flattenDetectorAdditionalConfigurationResults(v) + } + + if v := apiObject.Name; v != nil { + tfMap["name"] = aws.StringValue(v) + } + + if v := apiObject.Status; v != nil { + tfMap["status"] = aws.StringValue(v) + } + + return tfMap +} + +func flattenDetectorFeatureConfigurationResults(apiObjects []*guardduty.DetectorFeatureConfigurationResult) []interface{} { + if len(apiObjects) == 0 { + return nil + } + + var tfList []interface{} + + for _, apiObject := range apiObjects { + if apiObject == nil { + continue + } + + tfList = append(tfList, flattenDetectorFeatureConfigurationResult(apiObject)) + } + + return tfList +} + +func flattenDetectorAdditionalConfigurationResult(apiObject *guardduty.DetectorAdditionalConfigurationResult) map[string]interface{} { + if apiObject == nil { + return nil + } + + tfMap := map[string]interface{}{} + + if v := apiObject.Name; v != nil { + tfMap["name"] = aws.StringValue(v) + } + + if v := apiObject.Status; v != nil { + tfMap["status"] = aws.StringValue(v) + } + + return tfMap +} + +func flattenDetectorAdditionalConfigurationResults(apiObjects []*guardduty.DetectorAdditionalConfigurationResult) []interface{} { + if len(apiObjects) == 0 { + return nil + } + + var tfList []interface{} + + for _, apiObject := range apiObjects { + if apiObject == nil { + continue + } + + tfList = append(tfList, flattenDetectorAdditionalConfigurationResult(apiObject)) + } + + return tfList +} diff --git a/internal/service/guardduty/detector_test.go b/internal/service/guardduty/detector_test.go index 9ccb5563c5a..b2a667e013e 100644 --- a/internal/service/guardduty/detector_test.go +++ b/internal/service/guardduty/detector_test.go @@ -41,28 +41,6 @@ func testAccDetector_basic(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "datasources.#", "1"), resource.TestCheckResourceAttr(resourceName, "datasources.0.s3_logs.0.enable", "true"), resource.TestCheckResourceAttr(resourceName, "datasources.0.kubernetes.0.audit_logs.0.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.#", "9"), - resource.TestCheckResourceAttr(resourceName, "feature.0.name", "CLOUD_TRAIL"), - resource.TestCheckResourceAttr(resourceName, "feature.0.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.1.name", "DNS_LOGS"), - resource.TestCheckResourceAttr(resourceName, "feature.1.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.2.name", "FLOW_LOGS"), - resource.TestCheckResourceAttr(resourceName, "feature.2.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.3.name", "S3_DATA_EVENTS"), - resource.TestCheckResourceAttr(resourceName, "feature.3.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.4.name", "EKS_AUDIT_LOGS"), - resource.TestCheckResourceAttr(resourceName, "feature.4.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.5.name", "EBS_MALWARE_PROTECTION"), - resource.TestCheckResourceAttr(resourceName, "feature.5.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.6.name", "RDS_LOGIN_EVENTS"), - resource.TestCheckResourceAttr(resourceName, "feature.6.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.7.name", "EKS_RUNTIME_MONITORING"), - resource.TestCheckResourceAttr(resourceName, "feature.7.enable", "false"), - resource.TestCheckResourceAttr(resourceName, "feature.7.additional_configuration.#", "1"), - resource.TestCheckResourceAttr(resourceName, "feature.7.additional_configuration.0.name", "EKS_ADDON_MANAGEMENT"), - resource.TestCheckResourceAttr(resourceName, "feature.7.additional_configuration.0.enable", "false"), - resource.TestCheckResourceAttr(resourceName, "feature.8.name", "LAMBDA_NETWORK_LOGS"), - resource.TestCheckResourceAttr(resourceName, "feature.8.enable", "true"), resource.TestCheckResourceAttr(resourceName, "finding_publishing_frequency", "SIX_HOURS"), resource.TestCheckResourceAttr(resourceName, "tags.%", "0"), ), @@ -341,426 +319,6 @@ func testAccDetector_datasources_all(t *testing.T) { }) } -func testAccDetector_features_s3_data_events(t *testing.T) { - ctx := acctest.Context(t) - resourceName := "aws_guardduty_detector.test" - - resource.Test(t, resource.TestCase{ - PreCheck: func() { - acctest.PreCheck(ctx, t) - testAccPreCheckDetectorNotExists(ctx, t) - }, - ErrorCheck: acctest.ErrorCheck(t, guardduty.EndpointsID), - ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: testAccCheckDetectorDestroy(ctx), - Steps: []resource.TestStep{ - { - Config: testAccDetectorConfig_features_s3_data_events(true), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckDetectorExists(ctx, resourceName), - resource.TestCheckResourceAttr(resourceName, "datasources.#", "1"), - resource.TestCheckResourceAttr(resourceName, "datasources.0.s3_logs.#", "1"), - resource.TestCheckResourceAttr(resourceName, "datasources.0.s3_logs.0.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.#", "9"), - resource.TestCheckResourceAttr(resourceName, "feature.0.name", "CLOUD_TRAIL"), - resource.TestCheckResourceAttr(resourceName, "feature.0.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.1.name", "DNS_LOGS"), - resource.TestCheckResourceAttr(resourceName, "feature.1.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.2.name", "FLOW_LOGS"), - resource.TestCheckResourceAttr(resourceName, "feature.2.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.3.name", "S3_DATA_EVENTS"), - resource.TestCheckResourceAttr(resourceName, "feature.3.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.4.name", "EKS_AUDIT_LOGS"), - resource.TestCheckResourceAttr(resourceName, "feature.4.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.5.name", "EBS_MALWARE_PROTECTION"), - resource.TestCheckResourceAttr(resourceName, "feature.5.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.6.name", "RDS_LOGIN_EVENTS"), - resource.TestCheckResourceAttr(resourceName, "feature.6.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.7.name", "EKS_RUNTIME_MONITORING"), - resource.TestCheckResourceAttr(resourceName, "feature.7.enable", "false"), - resource.TestCheckResourceAttr(resourceName, "feature.7.additional_configuration.#", "1"), - resource.TestCheckResourceAttr(resourceName, "feature.7.additional_configuration.0.name", "EKS_ADDON_MANAGEMENT"), - resource.TestCheckResourceAttr(resourceName, "feature.7.additional_configuration.0.enable", "false"), - resource.TestCheckResourceAttr(resourceName, "feature.8.name", "LAMBDA_NETWORK_LOGS"), - resource.TestCheckResourceAttr(resourceName, "feature.8.enable", "true"), - ), - }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: false, - }, - { - Config: testAccDetectorConfig_features_s3_data_events(false), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckDetectorExists(ctx, resourceName), - resource.TestCheckResourceAttr(resourceName, "datasources.#", "1"), - resource.TestCheckResourceAttr(resourceName, "datasources.0.s3_logs.#", "1"), - resource.TestCheckResourceAttr(resourceName, "datasources.0.s3_logs.0.enable", "false"), - resource.TestCheckResourceAttr(resourceName, "feature.#", "9"), - resource.TestCheckResourceAttr(resourceName, "feature.0.name", "CLOUD_TRAIL"), - resource.TestCheckResourceAttr(resourceName, "feature.0.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.1.name", "DNS_LOGS"), - resource.TestCheckResourceAttr(resourceName, "feature.1.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.2.name", "FLOW_LOGS"), - resource.TestCheckResourceAttr(resourceName, "feature.2.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.3.name", "S3_DATA_EVENTS"), - resource.TestCheckResourceAttr(resourceName, "feature.3.enable", "false"), - resource.TestCheckResourceAttr(resourceName, "feature.4.name", "EKS_AUDIT_LOGS"), - resource.TestCheckResourceAttr(resourceName, "feature.4.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.5.name", "EBS_MALWARE_PROTECTION"), - resource.TestCheckResourceAttr(resourceName, "feature.5.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.6.name", "RDS_LOGIN_EVENTS"), - resource.TestCheckResourceAttr(resourceName, "feature.6.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.7.name", "EKS_RUNTIME_MONITORING"), - resource.TestCheckResourceAttr(resourceName, "feature.7.enable", "false"), - resource.TestCheckResourceAttr(resourceName, "feature.7.additional_configuration.#", "1"), - resource.TestCheckResourceAttr(resourceName, "feature.7.additional_configuration.0.name", "EKS_ADDON_MANAGEMENT"), - resource.TestCheckResourceAttr(resourceName, "feature.7.additional_configuration.0.enable", "false"), - resource.TestCheckResourceAttr(resourceName, "feature.8.name", "LAMBDA_NETWORK_LOGS"), - resource.TestCheckResourceAttr(resourceName, "feature.8.enable", "true"), - ), - }, - }, - }) -} - -func testAccDetector_features_eks_audit_logs(t *testing.T) { - ctx := acctest.Context(t) - resourceName := "aws_guardduty_detector.test" - - resource.Test(t, resource.TestCase{ - PreCheck: func() { - acctest.PreCheck(ctx, t) - testAccPreCheckDetectorNotExists(ctx, t) - }, - ErrorCheck: acctest.ErrorCheck(t, guardduty.EndpointsID), - ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: testAccCheckDetectorDestroy(ctx), - Steps: []resource.TestStep{ - { - Config: testAccDetectorConfig_features_eks_audit_logs(true), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckDetectorExists(ctx, resourceName), - resource.TestCheckResourceAttr(resourceName, "datasources.#", "1"), - resource.TestCheckResourceAttr(resourceName, "datasources.0.s3_logs.#", "1"), - resource.TestCheckResourceAttr(resourceName, "datasources.0.s3_logs.0.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.#", "9"), - resource.TestCheckResourceAttr(resourceName, "feature.0.name", "CLOUD_TRAIL"), - resource.TestCheckResourceAttr(resourceName, "feature.0.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.1.name", "DNS_LOGS"), - resource.TestCheckResourceAttr(resourceName, "feature.1.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.2.name", "FLOW_LOGS"), - resource.TestCheckResourceAttr(resourceName, "feature.2.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.3.name", "S3_DATA_EVENTS"), - resource.TestCheckResourceAttr(resourceName, "feature.3.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.4.name", "EKS_AUDIT_LOGS"), - resource.TestCheckResourceAttr(resourceName, "feature.4.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.5.name", "EBS_MALWARE_PROTECTION"), - resource.TestCheckResourceAttr(resourceName, "feature.5.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.6.name", "RDS_LOGIN_EVENTS"), - resource.TestCheckResourceAttr(resourceName, "feature.6.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.7.name", "EKS_RUNTIME_MONITORING"), - resource.TestCheckResourceAttr(resourceName, "feature.7.enable", "false"), - resource.TestCheckResourceAttr(resourceName, "feature.7.additional_configuration.#", "1"), - resource.TestCheckResourceAttr(resourceName, "feature.7.additional_configuration.0.name", "EKS_ADDON_MANAGEMENT"), - resource.TestCheckResourceAttr(resourceName, "feature.7.additional_configuration.0.enable", "false"), - resource.TestCheckResourceAttr(resourceName, "feature.8.name", "LAMBDA_NETWORK_LOGS"), - resource.TestCheckResourceAttr(resourceName, "feature.8.enable", "true"), - ), - }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - }, - { - Config: testAccDetectorConfig_features_s3_data_events(false), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckDetectorExists(ctx, resourceName), - resource.TestCheckResourceAttr(resourceName, "datasources.#", "1"), - resource.TestCheckResourceAttr(resourceName, "datasources.0.s3_logs.#", "1"), - resource.TestCheckResourceAttr(resourceName, "datasources.0.s3_logs.0.enable", "false"), - resource.TestCheckResourceAttr(resourceName, "feature.#", "9"), - resource.TestCheckResourceAttr(resourceName, "feature.0.name", "CLOUD_TRAIL"), - resource.TestCheckResourceAttr(resourceName, "feature.0.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.1.name", "DNS_LOGS"), - resource.TestCheckResourceAttr(resourceName, "feature.1.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.2.name", "FLOW_LOGS"), - resource.TestCheckResourceAttr(resourceName, "feature.2.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.3.name", "S3_DATA_EVENTS"), - resource.TestCheckResourceAttr(resourceName, "feature.3.enable", "false"), - resource.TestCheckResourceAttr(resourceName, "feature.4.name", "EKS_AUDIT_LOGS"), - resource.TestCheckResourceAttr(resourceName, "feature.4.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.5.name", "EBS_MALWARE_PROTECTION"), - resource.TestCheckResourceAttr(resourceName, "feature.5.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.6.name", "RDS_LOGIN_EVENTS"), - resource.TestCheckResourceAttr(resourceName, "feature.6.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.7.name", "EKS_RUNTIME_MONITORING"), - resource.TestCheckResourceAttr(resourceName, "feature.7.enable", "false"), - resource.TestCheckResourceAttr(resourceName, "feature.7.additional_configuration.#", "1"), - resource.TestCheckResourceAttr(resourceName, "feature.7.additional_configuration.0.name", "EKS_ADDON_MANAGEMENT"), - resource.TestCheckResourceAttr(resourceName, "feature.7.additional_configuration.0.enable", "false"), - resource.TestCheckResourceAttr(resourceName, "feature.8.name", "LAMBDA_NETWORK_LOGS"), - resource.TestCheckResourceAttr(resourceName, "feature.8.enable", "true"), - ), - }, - }, - }) -} - -func testAccDetector_features_ebs_malware_protection(t *testing.T) { - ctx := acctest.Context(t) - resourceName := "aws_guardduty_detector.test" - - resource.Test(t, resource.TestCase{ - PreCheck: func() { - acctest.PreCheck(ctx, t) - testAccPreCheckDetectorNotExists(ctx, t) - }, - ErrorCheck: acctest.ErrorCheck(t, guardduty.EndpointsID), - ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: testAccCheckDetectorDestroy(ctx), - Steps: []resource.TestStep{ - { - Config: testAccDetectorConfig_features_ebs_malware_protection(true), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckDetectorExists(ctx, resourceName), - resource.TestCheckResourceAttr(resourceName, "datasources.#", "1"), - resource.TestCheckResourceAttr(resourceName, "datasources.0.s3_logs.#", "1"), - resource.TestCheckResourceAttr(resourceName, "datasources.0.s3_logs.0.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.#", "9"), - resource.TestCheckResourceAttr(resourceName, "feature.0.name", "CLOUD_TRAIL"), - resource.TestCheckResourceAttr(resourceName, "feature.0.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.1.name", "DNS_LOGS"), - resource.TestCheckResourceAttr(resourceName, "feature.1.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.2.name", "FLOW_LOGS"), - resource.TestCheckResourceAttr(resourceName, "feature.2.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.3.name", "S3_DATA_EVENTS"), - resource.TestCheckResourceAttr(resourceName, "feature.3.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.4.name", "EKS_AUDIT_LOGS"), - resource.TestCheckResourceAttr(resourceName, "feature.4.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.5.name", "EBS_MALWARE_PROTECTION"), - resource.TestCheckResourceAttr(resourceName, "feature.5.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.6.name", "RDS_LOGIN_EVENTS"), - resource.TestCheckResourceAttr(resourceName, "feature.6.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.7.name", "EKS_RUNTIME_MONITORING"), - resource.TestCheckResourceAttr(resourceName, "feature.7.enable", "false"), - resource.TestCheckResourceAttr(resourceName, "feature.7.additional_configuration.#", "1"), - resource.TestCheckResourceAttr(resourceName, "feature.7.additional_configuration.0.name", "EKS_ADDON_MANAGEMENT"), - resource.TestCheckResourceAttr(resourceName, "feature.7.additional_configuration.0.enable", "false"), - resource.TestCheckResourceAttr(resourceName, "feature.8.name", "LAMBDA_NETWORK_LOGS"), - resource.TestCheckResourceAttr(resourceName, "feature.8.enable", "true"), - ), - }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - }, - { - Config: testAccDetectorConfig_features_ebs_malware_protection(false), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckDetectorExists(ctx, resourceName), - resource.TestCheckResourceAttr(resourceName, "datasources.#", "1"), - resource.TestCheckResourceAttr(resourceName, "datasources.0.s3_logs.#", "1"), - resource.TestCheckResourceAttr(resourceName, "datasources.0.s3_logs.0.enable", "false"), - resource.TestCheckResourceAttr(resourceName, "feature.#", "9"), - resource.TestCheckResourceAttr(resourceName, "feature.0.name", "CLOUD_TRAIL"), - resource.TestCheckResourceAttr(resourceName, "feature.0.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.1.name", "DNS_LOGS"), - resource.TestCheckResourceAttr(resourceName, "feature.1.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.2.name", "FLOW_LOGS"), - resource.TestCheckResourceAttr(resourceName, "feature.2.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.3.name", "S3_DATA_EVENTS"), - resource.TestCheckResourceAttr(resourceName, "feature.3.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.4.name", "EKS_AUDIT_LOGS"), - resource.TestCheckResourceAttr(resourceName, "feature.4.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.5.name", "EBS_MALWARE_PROTECTION"), - resource.TestCheckResourceAttr(resourceName, "feature.5.enable", "false"), - resource.TestCheckResourceAttr(resourceName, "feature.6.name", "RDS_LOGIN_EVENTS"), - resource.TestCheckResourceAttr(resourceName, "feature.6.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.7.name", "EKS_RUNTIME_MONITORING"), - resource.TestCheckResourceAttr(resourceName, "feature.7.enable", "false"), - resource.TestCheckResourceAttr(resourceName, "feature.7.additional_configuration.#", "1"), - resource.TestCheckResourceAttr(resourceName, "feature.7.additional_configuration.0.name", "EKS_ADDON_MANAGEMENT"), - resource.TestCheckResourceAttr(resourceName, "feature.7.additional_configuration.0.enable", "false"), - resource.TestCheckResourceAttr(resourceName, "feature.8.name", "LAMBDA_NETWORK_LOGS"), - resource.TestCheckResourceAttr(resourceName, "feature.8.enable", "true"), - ), - }, - }, - }) -} - -func testAccDetector_features_rds_login_events(t *testing.T) { - ctx := acctest.Context(t) - resourceName := "aws_guardduty_detector.test" - - resource.Test(t, resource.TestCase{ - PreCheck: func() { - acctest.PreCheck(ctx, t) - testAccPreCheckDetectorNotExists(ctx, t) - }, - ErrorCheck: acctest.ErrorCheck(t, guardduty.EndpointsID), - ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: testAccCheckDetectorDestroy(ctx), - Steps: []resource.TestStep{ - { - Config: testAccDetectorConfig_features_rds_login_events(true), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckDetectorExists(ctx, resourceName), - resource.TestCheckResourceAttr(resourceName, "datasources.#", "1"), - resource.TestCheckResourceAttr(resourceName, "datasources.0.s3_logs.#", "1"), - resource.TestCheckResourceAttr(resourceName, "datasources.0.s3_logs.0.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.#", "9"), - resource.TestCheckResourceAttr(resourceName, "feature.0.name", "CLOUD_TRAIL"), - resource.TestCheckResourceAttr(resourceName, "feature.0.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.1.name", "DNS_LOGS"), - resource.TestCheckResourceAttr(resourceName, "feature.1.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.2.name", "FLOW_LOGS"), - resource.TestCheckResourceAttr(resourceName, "feature.2.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.3.name", "S3_DATA_EVENTS"), - resource.TestCheckResourceAttr(resourceName, "feature.3.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.4.name", "EKS_AUDIT_LOGS"), - resource.TestCheckResourceAttr(resourceName, "feature.4.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.5.name", "EBS_MALWARE_PROTECTION"), - resource.TestCheckResourceAttr(resourceName, "feature.5.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.6.name", "RDS_LOGIN_EVENTS"), - resource.TestCheckResourceAttr(resourceName, "feature.6.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.7.name", "EKS_RUNTIME_MONITORING"), - resource.TestCheckResourceAttr(resourceName, "feature.7.enable", "false"), - resource.TestCheckResourceAttr(resourceName, "feature.7.additional_configuration.#", "1"), - resource.TestCheckResourceAttr(resourceName, "feature.7.additional_configuration.0.name", "EKS_ADDON_MANAGEMENT"), - resource.TestCheckResourceAttr(resourceName, "feature.7.additional_configuration.0.enable", "false"), - resource.TestCheckResourceAttr(resourceName, "feature.8.name", "LAMBDA_NETWORK_LOGS"), - resource.TestCheckResourceAttr(resourceName, "feature.8.enable", "true"), - ), - }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - }, - { - Config: testAccDetectorConfig_features_rds_login_events(false), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckDetectorExists(ctx, resourceName), - resource.TestCheckResourceAttr(resourceName, "datasources.#", "1"), - resource.TestCheckResourceAttr(resourceName, "datasources.0.s3_logs.#", "1"), - resource.TestCheckResourceAttr(resourceName, "datasources.0.s3_logs.0.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.#", "9"), - resource.TestCheckResourceAttr(resourceName, "feature.0.name", "CLOUD_TRAIL"), - resource.TestCheckResourceAttr(resourceName, "feature.0.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.1.name", "DNS_LOGS"), - resource.TestCheckResourceAttr(resourceName, "feature.1.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.2.name", "FLOW_LOGS"), - resource.TestCheckResourceAttr(resourceName, "feature.2.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.3.name", "S3_DATA_EVENTS"), - resource.TestCheckResourceAttr(resourceName, "feature.3.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.4.name", "EKS_AUDIT_LOGS"), - resource.TestCheckResourceAttr(resourceName, "feature.4.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.5.name", "EBS_MALWARE_PROTECTION"), - resource.TestCheckResourceAttr(resourceName, "feature.5.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.6.name", "RDS_LOGIN_EVENTS"), - resource.TestCheckResourceAttr(resourceName, "feature.6.enable", "false"), - resource.TestCheckResourceAttr(resourceName, "feature.7.name", "EKS_RUNTIME_MONITORING"), - resource.TestCheckResourceAttr(resourceName, "feature.7.enable", "false"), - resource.TestCheckResourceAttr(resourceName, "feature.7.additional_configuration.#", "1"), - resource.TestCheckResourceAttr(resourceName, "feature.7.additional_configuration.0.name", "EKS_ADDON_MANAGEMENT"), - resource.TestCheckResourceAttr(resourceName, "feature.7.additional_configuration.0.enable", "false"), - resource.TestCheckResourceAttr(resourceName, "feature.8.name", "LAMBDA_NETWORK_LOGS"), - resource.TestCheckResourceAttr(resourceName, "feature.8.enable", "true"), - ), - }, - }, - }) -} - -func testAccDetector_features_eks_runtime_monitoring(t *testing.T) { - ctx := acctest.Context(t) - resourceName := "aws_guardduty_detector.test" - - resource.Test(t, resource.TestCase{ - PreCheck: func() { - acctest.PreCheck(ctx, t) - testAccPreCheckDetectorNotExists(ctx, t) - }, - ErrorCheck: acctest.ErrorCheck(t, guardduty.EndpointsID), - ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: testAccCheckDetectorDestroy(ctx), - Steps: []resource.TestStep{ - { - Config: testAccDetectorConfig_features_eks_runtime_monitoring(true), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckDetectorExists(ctx, resourceName), - resource.TestCheckResourceAttr(resourceName, "datasources.#", "1"), - resource.TestCheckResourceAttr(resourceName, "datasources.0.s3_logs.#", "1"), - resource.TestCheckResourceAttr(resourceName, "datasources.0.s3_logs.0.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.#", "9"), - resource.TestCheckResourceAttr(resourceName, "feature.0.name", "CLOUD_TRAIL"), - resource.TestCheckResourceAttr(resourceName, "feature.0.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.1.name", "DNS_LOGS"), - resource.TestCheckResourceAttr(resourceName, "feature.1.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.2.name", "FLOW_LOGS"), - resource.TestCheckResourceAttr(resourceName, "feature.2.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.3.name", "S3_DATA_EVENTS"), - resource.TestCheckResourceAttr(resourceName, "feature.3.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.4.name", "EKS_AUDIT_LOGS"), - resource.TestCheckResourceAttr(resourceName, "feature.4.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.5.name", "EBS_MALWARE_PROTECTION"), - resource.TestCheckResourceAttr(resourceName, "feature.5.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.6.name", "RDS_LOGIN_EVENTS"), - resource.TestCheckResourceAttr(resourceName, "feature.6.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.7.name", "EKS_RUNTIME_MONITORING"), - resource.TestCheckResourceAttr(resourceName, "feature.7.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.7.additional_configuration.#", "1"), - resource.TestCheckResourceAttr(resourceName, "feature.7.additional_configuration.0.name", "EKS_ADDON_MANAGEMENT"), - resource.TestCheckResourceAttr(resourceName, "feature.7.additional_configuration.0.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.8.name", "LAMBDA_NETWORK_LOGS"), - resource.TestCheckResourceAttr(resourceName, "feature.8.enable", "true"), - ), - }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - }, - { - Config: testAccDetectorConfig_features_rds_login_events(false), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckDetectorExists(ctx, resourceName), - resource.TestCheckResourceAttr(resourceName, "datasources.#", "1"), - resource.TestCheckResourceAttr(resourceName, "datasources.0.s3_logs.#", "1"), - resource.TestCheckResourceAttr(resourceName, "datasources.0.s3_logs.0.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.#", "9"), - resource.TestCheckResourceAttr(resourceName, "feature.0.name", "CLOUD_TRAIL"), - resource.TestCheckResourceAttr(resourceName, "feature.0.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.1.name", "DNS_LOGS"), - resource.TestCheckResourceAttr(resourceName, "feature.1.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.2.name", "FLOW_LOGS"), - resource.TestCheckResourceAttr(resourceName, "feature.2.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.3.name", "S3_DATA_EVENTS"), - resource.TestCheckResourceAttr(resourceName, "feature.3.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.4.name", "EKS_AUDIT_LOGS"), - resource.TestCheckResourceAttr(resourceName, "feature.4.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.5.name", "EBS_MALWARE_PROTECTION"), - resource.TestCheckResourceAttr(resourceName, "feature.5.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.6.name", "RDS_LOGIN_EVENTS"), - resource.TestCheckResourceAttr(resourceName, "feature.6.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "feature.7.name", "EKS_RUNTIME_MONITORING"), - resource.TestCheckResourceAttr(resourceName, "feature.7.enable", "false"), - resource.TestCheckResourceAttr(resourceName, "feature.7.additional_configuration.#", "1"), - resource.TestCheckResourceAttr(resourceName, "feature.7.additional_configuration.0.name", "EKS_ADDON_MANAGEMENT"), - resource.TestCheckResourceAttr(resourceName, "feature.7.additional_configuration.0.enable", "false"), - resource.TestCheckResourceAttr(resourceName, "feature.8.name", "LAMBDA_NETWORK_LOGS"), - resource.TestCheckResourceAttr(resourceName, "feature.8.enable", "true"), - ), - }, - }, - }) -} - func testAccCheckDetectorDestroy(ctx context.Context) resource.TestCheckFunc { return func(s *terraform.State) error { conn := acctest.Provider.Meta().(*conns.AWSClient).GuardDutyConn(ctx) @@ -911,63 +469,3 @@ resource "aws_guardduty_detector" "test" { } `, enableK8s, enableS3, enableMalware) } - -func testAccDetectorConfig_features_s3_data_events(enable bool) string { - return fmt.Sprintf(` -resource "aws_guardduty_detector" "test" { - feature { - name = "S3_DATA_EVENTS" - enable = %[1]t - } -} -`, enable) -} - -func testAccDetectorConfig_features_eks_audit_logs(enable bool) string { - return fmt.Sprintf(` -resource "aws_guardduty_detector" "test" { - feature { - name = "EKS_AUDIT_LOGS" - enable = %[1]t - } -} -`, enable) -} - -func testAccDetectorConfig_features_ebs_malware_protection(enable bool) string { - return fmt.Sprintf(` -resource "aws_guardduty_detector" "test" { - feature { - name = "EBS_MALWARE_PROTECTION" - enable = %[1]t - } -} -`, enable) -} - -func testAccDetectorConfig_features_rds_login_events(enable bool) string { - return fmt.Sprintf(` -resource "aws_guardduty_detector" "test" { - feature { - name = "RDS_LOGIN_EVENTS" - enable = %[1]t - } -} -`, enable) -} - -func testAccDetectorConfig_features_eks_runtime_monitoring(enable bool) string { - return fmt.Sprintf(` -resource "aws_guardduty_detector" "test" { - feature { - name = "EKS_RUNTIME_MONITORING" - enable = %[1]t - - additional_configuration { - name = "EKS_ADDON_MANAGEMENT" - enable = %[1]t - } - } -} -`, enable) -} diff --git a/internal/service/guardduty/guardduty_test.go b/internal/service/guardduty/guardduty_test.go index 4fc9aa6df69..157dc8d5f87 100644 --- a/internal/service/guardduty/guardduty_test.go +++ b/internal/service/guardduty/guardduty_test.go @@ -24,11 +24,6 @@ func TestAccGuardDuty_serial(t *testing.T) { "datasources_kubernetes_audit_logs": testAccDetector_datasources_kubernetes_audit_logs, "datasources_malware_protection": testAccDetector_datasources_malware_protection, "datasources_all": testAccDetector_datasources_all, - "features_s3_data_events": testAccDetector_features_s3_data_events, - "features_eks_audit_logs": testAccDetector_features_eks_audit_logs, - "features_ebs_malware_protection": testAccDetector_features_ebs_malware_protection, - "features_rds_login_events": testAccDetector_features_rds_login_events, - "features_eks_runtime_monitoring": testAccDetector_features_eks_runtime_monitoring, "tags": testAccDetector_tags, "datasource_basic": testAccDetectorDataSource_basic, "datasource_id": testAccDetectorDataSource_ID, diff --git a/internal/service/guardduty/service_package_gen.go b/internal/service/guardduty/service_package_gen.go index bcd3713e47f..ed2dbc93187 100644 --- a/internal/service/guardduty/service_package_gen.go +++ b/internal/service/guardduty/service_package_gen.go @@ -47,6 +47,11 @@ func (p *servicePackage) SDKResources(ctx context.Context) []*types.ServicePacka IdentifierAttribute: "arn", }, }, + { + Factory: ResourceDetectorFeature, + TypeName: "aws_guardduty_detector_feature", + Name: "Detector Feature", + }, { Factory: ResourceFilter, TypeName: "aws_guardduty_filter", diff --git a/website/docs/r/guardduty_detector.html.markdown b/website/docs/r/guardduty_detector.html.markdown index 6f14903766b..26f20120faf 100644 --- a/website/docs/r/guardduty_detector.html.markdown +++ b/website/docs/r/guardduty_detector.html.markdown @@ -3,50 +3,17 @@ subcategory: "GuardDuty" layout: "aws" page_title: "AWS: aws_guardduty_detector" description: |- - Provides a resource to manage a GuardDuty detector + Provides a resource to manage an Amazon GuardDuty detector --- # Resource: aws_guardduty_detector -Provides a resource to manage a GuardDuty detector. +Provides a resource to manage an Amazon GuardDuty detector. ~> **NOTE:** Deleting this resource is equivalent to "disabling" GuardDuty for an AWS region, which removes all existing findings. You can set the `enable` attribute to `false` to instead "suspend" monitoring and feedback reporting while keeping existing data. See the [Suspending or Disabling Amazon GuardDuty documentation](https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_suspend-disable.html) for more information. ## Example Usage -```terraform -resource "aws_guardduty_detector" "MyDetector" { - enable = true - - feature { - name = "S3_DATA_EVENTS" - enable = true - } - - feature { - name = "EKS_AUDIT_LOGS" - enable = false - } - - feature { - name = "EBS_MALWARE_PROTECTION" - enable = true - } - - feature { - name = "EKS_RUNTIME_MONITORING" - enable = true - - aditional_configuration { - name = "EKS_ADDON_MANAGEMENT" - enable = true - } - } -} -``` - -### Deprecated use of `datasources` - ```terraform resource "aws_guardduty_detector" "MyDetector" { enable = true @@ -77,8 +44,7 @@ This resource supports the following arguments: * `enable` - (Optional) Enable monitoring and feedback reporting. Setting to `false` is equivalent to "suspending" GuardDuty. Defaults to `true`. * `finding_publishing_frequency` - (Optional) Specifies the frequency of notifications sent for subsequent finding occurrences. If the detector is a GuardDuty member account, the value is determined by the GuardDuty primary account and cannot be modified, otherwise defaults to `SIX_HOURS`. For standalone and GuardDuty primary accounts, it must be configured in Terraform to enable drift detection. Valid values for standalone and primary accounts: `FIFTEEN_MINUTES`, `ONE_HOUR`, `SIX_HOURS`. See [AWS Documentation](https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_findings_cloudwatch.html#guardduty_findings_cloudwatch_notification_frequency) for more information. -* `datasources` - (Optional) Describes which data sources will be enabled for the detector. See [Data Sources](#data-sources) below for more details. [Deprecated](https://docs.aws.amazon.com/guardduty/latest/ug/guardduty-feature-object-api-changes-march2023.html) in favor of `feature` blocks. -* `feature` - (Optional) Describes which features will be enabled for the detector. See [Features](#features) below for more details. +* `datasources` - (Optional) Describes which data sources will be enabled for the detector. See [Data Sources](#data-sources) below for more details. [Deprecated](https://docs.aws.amazon.com/guardduty/latest/ug/guardduty-feature-object-api-changes-march2023.html) in favor of [`aws_guardduty_detector_feature` resources](guardduty_detector_feature.html). * `tags` - (Optional) Key-value map 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. ### Data Sources @@ -136,21 +102,6 @@ The `ebs_volumes` block supports the following: * `enable` - (Required) If true, enables [Malware Protection](https://docs.aws.amazon.com/guardduty/latest/ug/malware-protection.html) as data source for the detector. Defaults to `true`. -### Features - -The `feature` block supports the following: - -* `name` - (Required) Name of the feature to configure. See the [AWS GuardDuty documentation](https://docs.aws.amazon.com/guardduty/latest/ug/guardduty-feature-object-api-changes-march2023.html#guardduty-feature-enablement-datasource-relation) for the allowed feature names. -* `enable` - (Required) If true, enables the feature, false to disable the feature. -* `additional_configuration` - (Optional) Additional feature configuration block See [below](#additional-configuration). - -### Additional Configuration - -The `additional_configuration` block supports the following: - -* `name` - (Required) Name of the additional feature configuration. -* `enable` - (Required) If true, enables the additional feature configuration, false to disable the feature. - ## Attribute Reference This resource exports the following attributes in addition to the arguments above: diff --git a/website/docs/r/guardduty_detector_feature.html.markdown b/website/docs/r/guardduty_detector_feature.html.markdown new file mode 100644 index 00000000000..c0cd286daa9 --- /dev/null +++ b/website/docs/r/guardduty_detector_feature.html.markdown @@ -0,0 +1,52 @@ +--- +subcategory: "GuardDuty" +layout: "aws" +page_title: "AWS: aws_guardduty_detector_feature" +description: |- + Provides a resource to manage an Amazon GuardDuty detector feature +--- + +# Resource: aws_guardduty_detector_feature + +Provides a resource to manage a single Amazon GuardDuty [detector feature](https://docs.aws.amazon.com/guardduty/latest/ug/guardduty-features-activation-model.html#guardduty-features). + +~> **NOTE:** Deleting this resource does not disable the detector feature, the resource in simply removed from state instead. + +## Example Usage + +```terraform +resource "aws_guardduty_detector" "example" { + enable = true +} + +resource "aws_guardduty_detector_feature" "eks_runtime_monitoring" { + detector_id = aws_guardduty_detector.example.id + name = "EKS_RUNTIME_MONITORING" + status = "ENABLED" + + additional_configuration { + name = "EKS_ADDON_MANAGEMENT" + status = "ENABLED" + } +} +``` + +## Argument Reference + +This resource supports the following arguments: + +* `detector_id` - (Required) Amazon GuardDuty detector ID. +* `name` - (Required) The name of the detector feature. Valid values: `S3_DATA_EVENTS`, `EKS_AUDIT_LOGS`, `EBS_MALWARE_PROTECTION`, `RDS_LOGIN_EVENTS`, `EKS_RUNTIME_MONITORING`, `LAMBDA_NETWORK_LOGS`. +* `status` - (Required) The status of the detector feature. Valid values: `ENABLED`, `DISABLED`. +* `additional_configuration` - (Optional) Additional feature configuration block. See [below](#additional-configuration). + +### Additional Configuration + +The `additional_configuration` block supports the following: + +* `name` - (Required) The name of the additional configuration. Valid values: `EKS_ADDON_MANAGEMENT`. +* `status` - (Required) The status of the detector feature. Valid values: `ENABLED`, `DISABLED`. + +## Attribute Reference + +This resource exports no additional attributes. From f85835e99d6b0e3d181d67fe8994b27c6b3c6986 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Thu, 28 Sep 2023 12:15:16 -0400 Subject: [PATCH 19/31] r/aws_guardduty_detector_feature: Start to add acceptance tests. --- .../guardduty/detector_feature_test.go | 73 +++++++++++++++++++ internal/service/guardduty/guardduty_test.go | 3 + 2 files changed, 76 insertions(+) create mode 100644 internal/service/guardduty/detector_feature_test.go diff --git a/internal/service/guardduty/detector_feature_test.go b/internal/service/guardduty/detector_feature_test.go new file mode 100644 index 00000000000..e2dd8b32932 --- /dev/null +++ b/internal/service/guardduty/detector_feature_test.go @@ -0,0 +1,73 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package guardduty_test + +import ( + "context" + "fmt" + "testing" + + "github.com/aws/aws-sdk-go/service/guardduty" + "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" + tfguardduty "github.com/hashicorp/terraform-provider-aws/internal/service/guardduty" +) + +func testAccDetectorFeature_basic(t *testing.T) { + ctx := acctest.Context(t) + resourceName := "aws_guardduty_detector_feature.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + testAccPreCheckDetectorNotExists(ctx, t) + }, + ErrorCheck: acctest.ErrorCheck(t, guardduty.EndpointsID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: acctest.CheckDestroyNoop, + Steps: []resource.TestStep{ + { + Config: testAccDetectorFeatureConfig_basic("RDS_LOGIN_EVENTS", "ENABLED"), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckDetectorFeatureExists(ctx, resourceName), + resource.TestCheckResourceAttr(resourceName, "additional_configuration.#", "0"), + resource.TestCheckResourceAttrSet(resourceName, "detector_id"), + resource.TestCheckResourceAttr(resourceName, "name", "RDS_LOGIN_EVENTS"), + resource.TestCheckResourceAttr(resourceName, "status", "ENABLED"), + ), + }, + }, + }) +} + +func testAccCheckDetectorFeatureExists(ctx context.Context, n string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + conn := acctest.Provider.Meta().(*conns.AWSClient).GuardDutyConn(ctx) + + _, err := tfguardduty.FindDetectorFeatureByTwoPartKey(ctx, conn, rs.Primary.Attributes["detector_id"], rs.Primary.Attributes["name"]) + + return err + } +} + +func testAccDetectorFeatureConfig_basic(name, status string) string { + return fmt.Sprintf(` +resource "aws_guardduty_detector" "test" { + enable = true +} + +resource "aws_guardduty_detector_feature" "test" { + detector_id = aws_guardduty_detector.test.id + name = %[1]q + status = %[2]q +} +`, name, status) +} diff --git a/internal/service/guardduty/guardduty_test.go b/internal/service/guardduty/guardduty_test.go index 157dc8d5f87..dc9c427eeb4 100644 --- a/internal/service/guardduty/guardduty_test.go +++ b/internal/service/guardduty/guardduty_test.go @@ -28,6 +28,9 @@ func TestAccGuardDuty_serial(t *testing.T) { "datasource_basic": testAccDetectorDataSource_basic, "datasource_id": testAccDetectorDataSource_ID, }, + "DetectorFeature": { + "basic": testAccDetectorFeature_basic, + }, "Filter": { "basic": testAccFilter_basic, "update": testAccFilter_update, From 497fd2ffec2b10b32ce2335547b0cb52c9a42e56 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Thu, 28 Sep 2023 12:15:33 -0400 Subject: [PATCH 20/31] Acceptance test output: % make testacc TESTARGS='-run=TestAccGuardDuty_serial/DetectorFeature' PKG=guardduty ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./internal/service/guardduty/... -v -count 1 -parallel 20 -run=TestAccGuardDuty_serial/DetectorFeature -timeout 360m === RUN TestAccGuardDuty_serial === PAUSE TestAccGuardDuty_serial === CONT TestAccGuardDuty_serial === RUN TestAccGuardDuty_serial/DetectorFeature === RUN TestAccGuardDuty_serial/DetectorFeature/basic --- PASS: TestAccGuardDuty_serial (26.71s) --- PASS: TestAccGuardDuty_serial/DetectorFeature (26.71s) --- PASS: TestAccGuardDuty_serial/DetectorFeature/basic (26.71s) PASS ok github.com/hashicorp/terraform-provider-aws/internal/service/guardduty 32.307s From 0f6f312ea5deb71c4dfa469e16d09f23c4d3af34 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Thu, 28 Sep 2023 13:46:46 -0400 Subject: [PATCH 21/31] Add 'testAccDetectorFeature_additionalConfiguration'. --- .../guardduty/detector_feature_test.go | 69 +++++++++++++++++++ internal/service/guardduty/guardduty_test.go | 3 +- .../guardduty_detector_feature.html.markdown | 2 +- 3 files changed, 72 insertions(+), 2 deletions(-) diff --git a/internal/service/guardduty/detector_feature_test.go b/internal/service/guardduty/detector_feature_test.go index e2dd8b32932..c3f226e7a38 100644 --- a/internal/service/guardduty/detector_feature_test.go +++ b/internal/service/guardduty/detector_feature_test.go @@ -43,6 +43,56 @@ func testAccDetectorFeature_basic(t *testing.T) { }) } +func testAccDetectorFeature_additionalConfiguration(t *testing.T) { + ctx := acctest.Context(t) + resourceName := "aws_guardduty_detector_feature.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + testAccPreCheckDetectorNotExists(ctx, t) + }, + ErrorCheck: acctest.ErrorCheck(t, guardduty.EndpointsID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: acctest.CheckDestroyNoop, + Steps: []resource.TestStep{ + { + Config: testAccDetectorFeatureConfig_additionalConfiguration("ENABLED", "ENABLED"), + Check: resource.ComposeTestCheckFunc( + testAccCheckDetectorFeatureExists(ctx, resourceName), + resource.TestCheckResourceAttr(resourceName, "additional_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "additional_configuration.0.name", "EKS_ADDON_MANAGEMENT"), + resource.TestCheckResourceAttr(resourceName, "additional_configuration.0.status", "ENABLED"), + resource.TestCheckResourceAttr(resourceName, "name", "EKS_RUNTIME_MONITORING"), + resource.TestCheckResourceAttr(resourceName, "status", "ENABLED"), + ), + }, + { + Config: testAccDetectorFeatureConfig_additionalConfiguration("DISABLED", "DISABLED"), + Check: resource.ComposeTestCheckFunc( + testAccCheckDetectorFeatureExists(ctx, resourceName), + resource.TestCheckResourceAttr(resourceName, "additional_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "additional_configuration.0.name", "EKS_ADDON_MANAGEMENT"), + resource.TestCheckResourceAttr(resourceName, "additional_configuration.0.status", "DISABLED"), + resource.TestCheckResourceAttr(resourceName, "name", "EKS_RUNTIME_MONITORING"), + resource.TestCheckResourceAttr(resourceName, "status", "DISABLED"), + ), + }, + { + Config: testAccDetectorFeatureConfig_additionalConfiguration("ENABLED", "DISABLED"), + Check: resource.ComposeTestCheckFunc( + testAccCheckDetectorFeatureExists(ctx, resourceName), + resource.TestCheckResourceAttr(resourceName, "additional_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "additional_configuration.0.name", "EKS_ADDON_MANAGEMENT"), + resource.TestCheckResourceAttr(resourceName, "additional_configuration.0.status", "DISABLED"), + resource.TestCheckResourceAttr(resourceName, "name", "EKS_RUNTIME_MONITORING"), + resource.TestCheckResourceAttr(resourceName, "status", "ENABLED"), + ), + }, + }, + }) +} + func testAccCheckDetectorFeatureExists(ctx context.Context, n string) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[n] @@ -71,3 +121,22 @@ resource "aws_guardduty_detector_feature" "test" { } `, name, status) } + +func testAccDetectorFeatureConfig_additionalConfiguration(featureStatus, additionalConfigurationStatus string) string { + return fmt.Sprintf(` +resource "aws_guardduty_detector" "test" { + enable = true +} + +resource "aws_guardduty_detector_feature" "test" { + detector_id = aws_guardduty_detector.test.id + name = "EKS_RUNTIME_MONITORING" + status = %[1]q + + additional_configuration { + name = "EKS_ADDON_MANAGEMENT" + status = %[2]q + } +} +`, featureStatus, additionalConfigurationStatus) +} diff --git a/internal/service/guardduty/guardduty_test.go b/internal/service/guardduty/guardduty_test.go index dc9c427eeb4..2e0b6e268a1 100644 --- a/internal/service/guardduty/guardduty_test.go +++ b/internal/service/guardduty/guardduty_test.go @@ -29,7 +29,8 @@ func TestAccGuardDuty_serial(t *testing.T) { "datasource_id": testAccDetectorDataSource_ID, }, "DetectorFeature": { - "basic": testAccDetectorFeature_basic, + "basic": testAccDetectorFeature_basic, + "additional_configuration": testAccDetectorFeature_additionalConfiguration, }, "Filter": { "basic": testAccFilter_basic, diff --git a/website/docs/r/guardduty_detector_feature.html.markdown b/website/docs/r/guardduty_detector_feature.html.markdown index c0cd286daa9..66ee1b5a648 100644 --- a/website/docs/r/guardduty_detector_feature.html.markdown +++ b/website/docs/r/guardduty_detector_feature.html.markdown @@ -45,7 +45,7 @@ This resource supports the following arguments: The `additional_configuration` block supports the following: * `name` - (Required) The name of the additional configuration. Valid values: `EKS_ADDON_MANAGEMENT`. -* `status` - (Required) The status of the detector feature. Valid values: `ENABLED`, `DISABLED`. +* `status` - (Required) The status of the additional configuration. Valid values: `ENABLED`, `DISABLED`. ## Attribute Reference From caddb582c4548d8fa44e20fb711ff9546ff2ea59 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Thu, 28 Sep 2023 14:51:56 -0400 Subject: [PATCH 22/31] Add 'testAccDetectorFeature_multiple'. --- .../guardduty/detector_feature_test.go | 96 +++++++++++++++++++ internal/service/guardduty/guardduty_test.go | 1 + 2 files changed, 97 insertions(+) diff --git a/internal/service/guardduty/detector_feature_test.go b/internal/service/guardduty/detector_feature_test.go index c3f226e7a38..43e5d626489 100644 --- a/internal/service/guardduty/detector_feature_test.go +++ b/internal/service/guardduty/detector_feature_test.go @@ -93,6 +93,76 @@ func testAccDetectorFeature_additionalConfiguration(t *testing.T) { }) } +func testAccDetectorFeature_multiple(t *testing.T) { + ctx := acctest.Context(t) + resource1Name := "aws_guardduty_detector_feature.test1" + resource2Name := "aws_guardduty_detector_feature.test2" + resource3Name := "aws_guardduty_detector_feature.test3" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + testAccPreCheckDetectorNotExists(ctx, t) + }, + ErrorCheck: acctest.ErrorCheck(t, guardduty.EndpointsID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: acctest.CheckDestroyNoop, + Steps: []resource.TestStep{ + { + Config: testAccDetectorFeatureConfig_multiple("ENABLED", "DISABLED", "ENABLED"), + Check: resource.ComposeTestCheckFunc( + testAccCheckDetectorFeatureExists(ctx, resource1Name), + testAccCheckDetectorFeatureExists(ctx, resource2Name), + testAccCheckDetectorFeatureExists(ctx, resource3Name), + resource.TestCheckResourceAttr(resource1Name, "additional_configuration.#", "0"), + resource.TestCheckResourceAttr(resource1Name, "name", "EBS_MALWARE_PROTECTION"), + resource.TestCheckResourceAttr(resource1Name, "status", "ENABLED"), + resource.TestCheckResourceAttr(resource2Name, "additional_configuration.#", "0"), + resource.TestCheckResourceAttr(resource2Name, "name", "LAMBDA_NETWORK_LOGS"), + resource.TestCheckResourceAttr(resource2Name, "status", "DISABLED"), + resource.TestCheckResourceAttr(resource3Name, "additional_configuration.#", "0"), + resource.TestCheckResourceAttr(resource3Name, "name", "S3_DATA_EVENTS"), + resource.TestCheckResourceAttr(resource3Name, "status", "ENABLED"), + ), + }, + { + Config: testAccDetectorFeatureConfig_multiple("DISABLED", "ENABLED", "ENABLED"), + Check: resource.ComposeTestCheckFunc( + testAccCheckDetectorFeatureExists(ctx, resource1Name), + testAccCheckDetectorFeatureExists(ctx, resource2Name), + testAccCheckDetectorFeatureExists(ctx, resource3Name), + resource.TestCheckResourceAttr(resource1Name, "additional_configuration.#", "0"), + resource.TestCheckResourceAttr(resource1Name, "name", "EBS_MALWARE_PROTECTION"), + resource.TestCheckResourceAttr(resource1Name, "status", "DISABLED"), + resource.TestCheckResourceAttr(resource2Name, "additional_configuration.#", "0"), + resource.TestCheckResourceAttr(resource2Name, "name", "LAMBDA_NETWORK_LOGS"), + resource.TestCheckResourceAttr(resource2Name, "status", "ENABLED"), + resource.TestCheckResourceAttr(resource3Name, "additional_configuration.#", "0"), + resource.TestCheckResourceAttr(resource3Name, "name", "S3_DATA_EVENTS"), + resource.TestCheckResourceAttr(resource3Name, "status", "ENABLED"), + ), + }, + { + Config: testAccDetectorFeatureConfig_multiple("DISABLED", "DISABLED", "DISABLED"), + Check: resource.ComposeTestCheckFunc( + testAccCheckDetectorFeatureExists(ctx, resource1Name), + testAccCheckDetectorFeatureExists(ctx, resource2Name), + testAccCheckDetectorFeatureExists(ctx, resource3Name), + resource.TestCheckResourceAttr(resource1Name, "additional_configuration.#", "0"), + resource.TestCheckResourceAttr(resource1Name, "name", "EBS_MALWARE_PROTECTION"), + resource.TestCheckResourceAttr(resource1Name, "status", "DISABLED"), + resource.TestCheckResourceAttr(resource2Name, "additional_configuration.#", "0"), + resource.TestCheckResourceAttr(resource2Name, "name", "LAMBDA_NETWORK_LOGS"), + resource.TestCheckResourceAttr(resource2Name, "status", "DISABLED"), + resource.TestCheckResourceAttr(resource3Name, "additional_configuration.#", "0"), + resource.TestCheckResourceAttr(resource3Name, "name", "S3_DATA_EVENTS"), + resource.TestCheckResourceAttr(resource3Name, "status", "DISABLED"), + ), + }, + }, + }) +} + func testAccCheckDetectorFeatureExists(ctx context.Context, n string) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[n] @@ -140,3 +210,29 @@ resource "aws_guardduty_detector_feature" "test" { } `, featureStatus, additionalConfigurationStatus) } + +func testAccDetectorFeatureConfig_multiple(status1, status2, status3 string) string { + return fmt.Sprintf(` +resource "aws_guardduty_detector" "test" { + enable = true +} + +resource "aws_guardduty_detector_feature" "test1" { + detector_id = aws_guardduty_detector.test.id + name = "EBS_MALWARE_PROTECTION" + status = %[1]q +} + +resource "aws_guardduty_detector_feature" "test2" { + detector_id = aws_guardduty_detector.test.id + name = "LAMBDA_NETWORK_LOGS" + status = %[2]q +} + +resource "aws_guardduty_detector_feature" "test3" { + detector_id = aws_guardduty_detector.test.id + name = "S3_DATA_EVENTS" + status = %[3]q +} +`, status1, status2, status3) +} diff --git a/internal/service/guardduty/guardduty_test.go b/internal/service/guardduty/guardduty_test.go index 2e0b6e268a1..2eed345735d 100644 --- a/internal/service/guardduty/guardduty_test.go +++ b/internal/service/guardduty/guardduty_test.go @@ -31,6 +31,7 @@ func TestAccGuardDuty_serial(t *testing.T) { "DetectorFeature": { "basic": testAccDetectorFeature_basic, "additional_configuration": testAccDetectorFeature_additionalConfiguration, + "multiple": testAccDetectorFeature_multiple, }, "Filter": { "basic": testAccFilter_basic, From 10be4c279b180c5452537ec8b9a7ebd9bbe3b62a Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Thu, 28 Sep 2023 14:58:39 -0400 Subject: [PATCH 23/31] r/aws_guardduty_detector_feature: Serialize calls to UpdateDetector. --- .../service/guardduty/detector_feature.go | 40 ++++++++++++++++++- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/internal/service/guardduty/detector_feature.go b/internal/service/guardduty/detector_feature.go index aa2ad9e0ee3..bc318eb2c45 100644 --- a/internal/service/guardduty/detector_feature.go +++ b/internal/service/guardduty/detector_feature.go @@ -18,6 +18,7 @@ import ( "github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag" tfslices "github.com/hashicorp/terraform-provider-aws/internal/slices" "github.com/hashicorp/terraform-provider-aws/internal/tfresource" + "golang.org/x/exp/slices" ) // @SDKResource("aws_guardduty_detector_feature", name="Detector Feature") @@ -83,12 +84,47 @@ func resourceDetectorFeaturePut(ctx context.Context, d *schema.ResourceData, met feature.AdditionalConfiguration = expandDetectorAdditionalConfigurations(v.([]interface{})) } + // Detector features must be updated as a full set, so use a mutex to ensure + // that multiple features being updated concurrently don't trample on each other. + conns.GlobalMutexKV.Lock(detectorID) + defer conns.GlobalMutexKV.Unlock(detectorID) + + output, err := FindDetectorByID(ctx, conn, detectorID) + + if err != nil { + return sdkdiag.AppendErrorf(diags, "reading GuardDuty Detector (%s): %s", detectorID, err) + } + + // Limit to those features supported on input, removing our feature. + // Also need to transform from output to input types. + features := tfslices.ApplyToAll(tfslices.Filter(output.Features, func(v *guardduty.DetectorFeatureConfigurationResult) bool { + return slices.Contains(tfslices.RemoveAll(guardduty.DetectorFeature_Values(), name), aws.StringValue(v.Name)) + }), func(v *guardduty.DetectorFeatureConfigurationResult) *guardduty.DetectorFeatureConfiguration { + var additionalConfiguration []*guardduty.DetectorAdditionalConfiguration + if len(v.AdditionalConfiguration) > 0 { + additionalConfiguration = tfslices.ApplyToAll(v.AdditionalConfiguration, func(v *guardduty.DetectorAdditionalConfigurationResult) *guardduty.DetectorAdditionalConfiguration { + return &guardduty.DetectorAdditionalConfiguration{ + Name: v.Name, + Status: v.Status, + } + }) + } + + return &guardduty.DetectorFeatureConfiguration{ + AdditionalConfiguration: additionalConfiguration, + Name: v.Name, + Status: v.Status, + } + }) + // Append our feature. + features = append(features, feature) + input := &guardduty.UpdateDetectorInput{ DetectorId: aws.String(detectorID), - Features: []*guardduty.DetectorFeatureConfiguration{feature}, + Features: features, } - _, err := conn.UpdateDetectorWithContext(ctx, input) + _, err = conn.UpdateDetectorWithContext(ctx, input) if err != nil { return sdkdiag.AppendErrorf(diags, "updating GuardDuty Detector (%s) Feature (%s): %s", detectorID, name, err) From 5b427868ab83143dc499ca86917ad4c43a6b48fb Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Thu, 28 Sep 2023 14:58:51 -0400 Subject: [PATCH 24/31] Acceptance test output: % make testacc TESTARGS='-run=TestAccGuardDuty_serial/DetectorFeature/multiple' PKG=guardduty ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./internal/service/guardduty/... -v -count 1 -parallel 20 -run=TestAccGuardDuty_serial/DetectorFeature/multiple -timeout 360m === RUN TestAccGuardDuty_serial === PAUSE TestAccGuardDuty_serial === CONT TestAccGuardDuty_serial === RUN TestAccGuardDuty_serial/DetectorFeature === RUN TestAccGuardDuty_serial/DetectorFeature/multiple --- PASS: TestAccGuardDuty_serial (62.34s) --- PASS: TestAccGuardDuty_serial/DetectorFeature (62.34s) --- PASS: TestAccGuardDuty_serial/DetectorFeature/multiple (62.34s) PASS ok github.com/hashicorp/terraform-provider-aws/internal/service/guardduty 67.776s From f48dc594019c5b09c484f29934a3f396d10a83dd Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Thu, 28 Sep 2023 14:59:15 -0400 Subject: [PATCH 25/31] Revert "r/aws_guardduty_detector_feature: Serialize calls to UpdateDetector." This reverts commit 10be4c279b180c5452537ec8b9a7ebd9bbe3b62a. --- .../service/guardduty/detector_feature.go | 40 +------------------ 1 file changed, 2 insertions(+), 38 deletions(-) diff --git a/internal/service/guardduty/detector_feature.go b/internal/service/guardduty/detector_feature.go index bc318eb2c45..aa2ad9e0ee3 100644 --- a/internal/service/guardduty/detector_feature.go +++ b/internal/service/guardduty/detector_feature.go @@ -18,7 +18,6 @@ import ( "github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag" tfslices "github.com/hashicorp/terraform-provider-aws/internal/slices" "github.com/hashicorp/terraform-provider-aws/internal/tfresource" - "golang.org/x/exp/slices" ) // @SDKResource("aws_guardduty_detector_feature", name="Detector Feature") @@ -84,47 +83,12 @@ func resourceDetectorFeaturePut(ctx context.Context, d *schema.ResourceData, met feature.AdditionalConfiguration = expandDetectorAdditionalConfigurations(v.([]interface{})) } - // Detector features must be updated as a full set, so use a mutex to ensure - // that multiple features being updated concurrently don't trample on each other. - conns.GlobalMutexKV.Lock(detectorID) - defer conns.GlobalMutexKV.Unlock(detectorID) - - output, err := FindDetectorByID(ctx, conn, detectorID) - - if err != nil { - return sdkdiag.AppendErrorf(diags, "reading GuardDuty Detector (%s): %s", detectorID, err) - } - - // Limit to those features supported on input, removing our feature. - // Also need to transform from output to input types. - features := tfslices.ApplyToAll(tfslices.Filter(output.Features, func(v *guardduty.DetectorFeatureConfigurationResult) bool { - return slices.Contains(tfslices.RemoveAll(guardduty.DetectorFeature_Values(), name), aws.StringValue(v.Name)) - }), func(v *guardduty.DetectorFeatureConfigurationResult) *guardduty.DetectorFeatureConfiguration { - var additionalConfiguration []*guardduty.DetectorAdditionalConfiguration - if len(v.AdditionalConfiguration) > 0 { - additionalConfiguration = tfslices.ApplyToAll(v.AdditionalConfiguration, func(v *guardduty.DetectorAdditionalConfigurationResult) *guardduty.DetectorAdditionalConfiguration { - return &guardduty.DetectorAdditionalConfiguration{ - Name: v.Name, - Status: v.Status, - } - }) - } - - return &guardduty.DetectorFeatureConfiguration{ - AdditionalConfiguration: additionalConfiguration, - Name: v.Name, - Status: v.Status, - } - }) - // Append our feature. - features = append(features, feature) - input := &guardduty.UpdateDetectorInput{ DetectorId: aws.String(detectorID), - Features: features, + Features: []*guardduty.DetectorFeatureConfiguration{feature}, } - _, err = conn.UpdateDetectorWithContext(ctx, input) + _, err := conn.UpdateDetectorWithContext(ctx, input) if err != nil { return sdkdiag.AppendErrorf(diags, "updating GuardDuty Detector (%s) Feature (%s): %s", detectorID, name, err) From b470735369e8924cf0445263dd3603f90bf8a3b5 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Thu, 28 Sep 2023 15:03:00 -0400 Subject: [PATCH 26/31] Acceptance test output: % make testacc TESTARGS='-run=TestAccGuardDuty_serial/DetectorFeature/multiple' PKG=guardduty ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./internal/service/guardduty/... -v -count 1 -parallel 20 -run=TestAccGuardDuty_serial/DetectorFeature/multiple -timeout 360m === RUN TestAccGuardDuty_serial === PAUSE TestAccGuardDuty_serial === CONT TestAccGuardDuty_serial === RUN TestAccGuardDuty_serial/DetectorFeature === RUN TestAccGuardDuty_serial/DetectorFeature/multiple --- PASS: TestAccGuardDuty_serial (57.49s) --- PASS: TestAccGuardDuty_serial/DetectorFeature (57.49s) --- PASS: TestAccGuardDuty_serial/DetectorFeature/multiple (57.49s) PASS ok github.com/hashicorp/terraform-provider-aws/internal/service/guardduty 62.908s From 5577fe923766e25481c92b89bd9180ad1c5589f8 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Thu, 28 Sep 2023 16:48:40 -0400 Subject: [PATCH 27/31] d/aws_guardduty_detector: Correct 'features' schema. --- .changelog/31463.txt | 4 ++ .../service/guardduty/detector_data_source.go | 60 +++++++++---------- .../service/guardduty/detector_feature.go | 48 --------------- .../docs/d/guardduty_detector.html.markdown | 9 ++- 4 files changed, 40 insertions(+), 81 deletions(-) diff --git a/.changelog/31463.txt b/.changelog/31463.txt index 62022c88082..8a5bf815242 100644 --- a/.changelog/31463.txt +++ b/.changelog/31463.txt @@ -1,3 +1,7 @@ ```release-note:new-resource aws_guardduty_detector_feature +``` + +```release-note:enhancement +data-source/aws_guardduty_detector: Add `features` attribute ``` \ No newline at end of file diff --git a/internal/service/guardduty/detector_data_source.go b/internal/service/guardduty/detector_data_source.go index 48685882eaa..a32b71abae3 100644 --- a/internal/service/guardduty/detector_data_source.go +++ b/internal/service/guardduty/detector_data_source.go @@ -20,57 +20,55 @@ func DataSourceDetector() *schema.Resource { ReadWithoutTimeout: dataSourceDetectorRead, Schema: map[string]*schema.Schema{ - "id": { - Type: schema.TypeString, - Optional: true, - Computed: true, - }, - "status": { - Type: schema.TypeString, - Computed: true, - }, - "service_role_arn": { - Type: schema.TypeString, - Computed: true, - }, - "finding_publishing_frequency": { - Type: schema.TypeString, - Computed: true, - }, "features": { Type: schema.TypeList, - Optional: true, Computed: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Required: true, - }, - "enable": { - Type: schema.TypeBool, - Required: true, - }, "additional_configuration": { - Optional: true, Computed: true, Type: schema.TypeList, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "name": { Type: schema.TypeString, - Required: true, + Computed: true, }, - "enable": { - Type: schema.TypeBool, - Required: true, + "status": { + Type: schema.TypeString, + Computed: true, }, }, }, }, + "name": { + Type: schema.TypeString, + Computed: true, + }, + "status": { + Type: schema.TypeString, + Computed: true, + }, }, }, }, + "finding_publishing_frequency": { + Type: schema.TypeString, + Computed: true, + }, + "id": { + Type: schema.TypeString, + Optional: true, + Computed: true, + }, + "service_role_arn": { + Type: schema.TypeString, + Computed: true, + }, + "status": { + Type: schema.TypeString, + Computed: true, + }, }, } } diff --git a/internal/service/guardduty/detector_feature.go b/internal/service/guardduty/detector_feature.go index aa2ad9e0ee3..b69ec950975 100644 --- a/internal/service/guardduty/detector_feature.go +++ b/internal/service/guardduty/detector_feature.go @@ -163,54 +163,6 @@ func FindDetectorFeatureByTwoPartKey(ctx context.Context, conn *guardduty.GuardD })) } -func expandDetectorFeatureConfiguration(tfMap map[string]interface{}) *guardduty.DetectorFeatureConfiguration { - if tfMap == nil { - return nil - } - - apiObject := &guardduty.DetectorFeatureConfiguration{} - - if v, ok := tfMap["additional_configuration"].([]interface{}); ok && len(v) > 0 { - apiObject.AdditionalConfiguration = expandDetectorAdditionalConfigurations(v) - } - - if v, ok := tfMap["name"].(string); ok && v != "" { - apiObject.Name = aws.String(v) - } - - if v, ok := tfMap["status"].(string); ok && v != "" { - apiObject.Status = aws.String(v) - } - - return apiObject -} - -func expandDetectorFeatureConfigurations(tfList []interface{}) []*guardduty.DetectorFeatureConfiguration { - if len(tfList) == 0 { - return nil - } - - var apiObjects []*guardduty.DetectorFeatureConfiguration - - for _, tfMapRaw := range tfList { - tfMap, ok := tfMapRaw.(map[string]interface{}) - - if !ok { - continue - } - - apiObject := expandDetectorFeatureConfiguration(tfMap) - - if apiObject == nil { - continue - } - - apiObjects = append(apiObjects, apiObject) - } - - return apiObjects -} - func expandDetectorAdditionalConfiguration(tfMap map[string]interface{}) *guardduty.DetectorAdditionalConfiguration { if tfMap == nil { return nil diff --git a/website/docs/d/guardduty_detector.html.markdown b/website/docs/d/guardduty_detector.html.markdown index 241d578ff49..02eeaa53c4a 100644 --- a/website/docs/d/guardduty_detector.html.markdown +++ b/website/docs/d/guardduty_detector.html.markdown @@ -24,7 +24,12 @@ data "aws_guardduty_detector" "example" {} This data source exports the following attributes in addition to the arguments above: +* `features` - Current configuration of the detector features. + * `additional_configuration` - Additional feature configuration. + * `name` - The name of the additional configuration. + * `status` - The status of the additional configuration. + * `name` - The name of the detector feature. + * `status` - The status of the detector feature. * `finding_publishing_frequency` - The frequency of notifications sent about subsequent finding occurrences. * `service_role_arn` - Service-linked role that grants GuardDuty access to the resources in the AWS account. -* `status` - Current status of the detector. -* `features` - Current configuration of the detector features. +* `status` - Current status of the detector. \ No newline at end of file From cb9532fa2f2fbb3928111cd5b6cf6da7c4b93886 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Thu, 28 Sep 2023 17:03:31 -0400 Subject: [PATCH 28/31] d/aws_guardduty_detector: Tidy up acceptance tests. --- .../service/guardduty/detector_data_source.go | 42 +++----- .../guardduty/detector_data_source_test.go | 102 +++++------------- 2 files changed, 38 insertions(+), 106 deletions(-) diff --git a/internal/service/guardduty/detector_data_source.go b/internal/service/guardduty/detector_data_source.go index a32b71abae3..fb83731ef11 100644 --- a/internal/service/guardduty/detector_data_source.go +++ b/internal/service/guardduty/detector_data_source.go @@ -7,7 +7,6 @@ import ( "context" "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/guardduty" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-provider-aws/internal/conns" @@ -77,50 +76,35 @@ func dataSourceDetectorRead(ctx context.Context, d *schema.ResourceData, meta in var diags diag.Diagnostics conn := meta.(*conns.AWSClient).GuardDutyConn(ctx) - detectorId := d.Get("id").(string) + detectorID := d.Get("id").(string) - if detectorId == "" { - input := &guardduty.ListDetectorsInput{} + if detectorID == "" { + output, err := FindDetector(ctx, conn) - resp, err := conn.ListDetectorsWithContext(ctx, input) if err != nil { - return sdkdiag.AppendErrorf(diags, "listing GuardDuty Detectors: %s", err) + return sdkdiag.AppendErrorf(diags, "reading this account's single GuardDuty Detector: %s", err) } - if resp == nil || len(resp.DetectorIds) == 0 { - return sdkdiag.AppendErrorf(diags, "no GuardDuty Detectors found") - } - if len(resp.DetectorIds) > 1 { - return sdkdiag.AppendErrorf(diags, "multiple GuardDuty Detectors found; please use the `id` argument to look up a single detector") - } - - detectorId = aws.StringValue(resp.DetectorIds[0]) + detectorID = aws.StringValue(output) } - getInput := &guardduty.GetDetectorInput{ - DetectorId: aws.String(detectorId), - } + gdo, err := FindDetectorByID(ctx, conn, detectorID) - getResp, err := conn.GetDetectorWithContext(ctx, getInput) if err != nil { - return sdkdiag.AppendErrorf(diags, "reading GuardDuty Detector (%s): %s", detectorId, err) - } - - if getResp == nil { - return sdkdiag.AppendErrorf(diags, "reading GuardDuty Detector (%s): empty result", detectorId) + return sdkdiag.AppendErrorf(diags, "reading GuardDuty Detector (%s): %s", detectorID, err) } - d.SetId(detectorId) - d.Set("status", getResp.Status) - d.Set("service_role_arn", getResp.ServiceRole) - d.Set("finding_publishing_frequency", getResp.FindingPublishingFrequency) - if getResp.Features != nil { - if err := d.Set("features", flattenDetectorFeatureConfigurationResults(getResp.Features)); err != nil { + d.SetId(detectorID) + if gdo.Features != nil { + if err := d.Set("features", flattenDetectorFeatureConfigurationResults(gdo.Features)); err != nil { return sdkdiag.AppendErrorf(diags, "setting features: %s", err) } } else { d.Set("features", nil) } + d.Set("finding_publishing_frequency", gdo.FindingPublishingFrequency) + d.Set("service_role_arn", gdo.ServiceRole) + d.Set("status", gdo.Status) return diags } diff --git a/internal/service/guardduty/detector_data_source_test.go b/internal/service/guardduty/detector_data_source_test.go index e6321f4e00d..0b20056ef19 100644 --- a/internal/service/guardduty/detector_data_source_test.go +++ b/internal/service/guardduty/detector_data_source_test.go @@ -13,6 +13,9 @@ import ( func testAccDetectorDataSource_basic(t *testing.T) { ctx := acctest.Context(t) + datasourceName := "data.aws_guardduty_detector.test" + resourceName := "aws_guardduty_detector.test" + resource.Test(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t) @@ -23,40 +26,13 @@ func testAccDetectorDataSource_basic(t *testing.T) { PreventPostDestroyRefresh: true, Steps: []resource.TestStep{ { - Config: testAccDetectorDataSourceConfig_basicResource(), - Check: resource.ComposeTestCheckFunc(), - }, - { - Config: testAccDetectorDataSourceConfig_basicResource2(), - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttrPair("data.aws_guardduty_detector.test", "id", "aws_guardduty_detector.test", "id"), - resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "status", "ENABLED"), - acctest.CheckResourceAttrGlobalARN("data.aws_guardduty_detector.test", "service_role_arn", "iam", "role/aws-service-role/guardduty.amazonaws.com/AWSServiceRoleForAmazonGuardDuty"), - resource.TestCheckResourceAttrPair("data.aws_guardduty_detector.test", "finding_publishing_frequency", "aws_guardduty_detector.test", "finding_publishing_frequency"), - resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.#", "9"), - resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.0.name", "CLOUD_TRAIL"), - resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.0.enable", "true"), - resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.1.name", "DNS_LOGS"), - resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.1.enable", "true"), - resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.2.name", "FLOW_LOGS"), - resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.2.enable", "true"), - resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.3.name", "S3_DATA_EVENTS"), - resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.3.enable", "true"), - resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.4.name", "EKS_AUDIT_LOGS"), - resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.4.enable", "true"), - resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.5.name", "EBS_MALWARE_PROTECTION"), - resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.5.enable", "true"), - resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.6.name", "RDS_LOGIN_EVENTS"), - resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.6.enable", "true"), - resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.7.name", "EKS_RUNTIME_MONITORING"), - resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.7.enable", "false"), - resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.7.additional_configuration.#", "1"), - resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.7.additional_configuration.0.name", "EKS_ADDON_MANAGEMENT"), - resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.7.additional_configuration.0.enable", "false"), - resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.8.name", "LAMBDA_NETWORK_LOGS"), - resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.8.enable", "true"), - resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "finding_publishing_frequency", "SIX_HOURS"), - resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "tags.%", "0"), + Config: testAccDetectorDataSourceConfig_basic, + Check: resource.ComposeAggregateTestCheckFunc( + acctest.CheckResourceAttrGreaterThanValue(datasourceName, "features.#", 0), + resource.TestCheckResourceAttrPair(datasourceName, "finding_publishing_frequency", resourceName, "finding_publishing_frequency"), + resource.TestCheckResourceAttrPair(datasourceName, "id", resourceName, "id"), + acctest.CheckResourceAttrGlobalARN(datasourceName, "service_role_arn", "iam", "role/aws-service-role/guardduty.amazonaws.com/AWSServiceRoleForAmazonGuardDuty"), + resource.TestCheckResourceAttr(datasourceName, "status", "ENABLED"), ), }, }, @@ -65,6 +41,9 @@ func testAccDetectorDataSource_basic(t *testing.T) { func testAccDetectorDataSource_ID(t *testing.T) { ctx := acctest.Context(t) + datasourceName := "data.aws_guardduty_detector.test" + resourceName := "aws_guardduty_detector.test" + resource.Test(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t) @@ -74,62 +53,31 @@ func testAccDetectorDataSource_ID(t *testing.T) { ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, Steps: []resource.TestStep{ { - Config: testAccDetectorDataSourceConfig_explicit(), - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttrPair("data.aws_guardduty_detector.test", "id", "aws_guardduty_detector.test", "id"), - resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "status", "ENABLED"), - acctest.CheckResourceAttrGlobalARN("data.aws_guardduty_detector.test", "service_role_arn", "iam", "role/aws-service-role/guardduty.amazonaws.com/AWSServiceRoleForAmazonGuardDuty"), - resource.TestCheckResourceAttrPair("data.aws_guardduty_detector.test", "finding_publishing_frequency", "aws_guardduty_detector.test", "finding_publishing_frequency"), - resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.#", "9"), - resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.0.name", "CLOUD_TRAIL"), - resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.0.enable", "true"), - resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.1.name", "DNS_LOGS"), - resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.1.enable", "true"), - resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.2.name", "FLOW_LOGS"), - resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.2.enable", "true"), - resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.3.name", "S3_DATA_EVENTS"), - resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.3.enable", "true"), - resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.4.name", "EKS_AUDIT_LOGS"), - resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.4.enable", "true"), - resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.5.name", "EBS_MALWARE_PROTECTION"), - resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.5.enable", "true"), - resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.6.name", "RDS_LOGIN_EVENTS"), - resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.6.enable", "true"), - resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.7.name", "EKS_RUNTIME_MONITORING"), - resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.7.enable", "false"), - resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.7.additional_configuration.#", "1"), - resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.7.additional_configuration.0.name", "EKS_ADDON_MANAGEMENT"), - resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.7.additional_configuration.0.enable", "false"), - resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.8.name", "LAMBDA_NETWORK_LOGS"), - resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "features.8.enable", "true"), - resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "finding_publishing_frequency", "SIX_HOURS"), - resource.TestCheckResourceAttr("data.aws_guardduty_detector.test", "tags.%", "0"), + Config: testAccDetectorDataSourceConfig_id, + Check: resource.ComposeAggregateTestCheckFunc( + acctest.CheckResourceAttrGreaterThanValue(datasourceName, "features.#", 0), + resource.TestCheckResourceAttrPair(datasourceName, "finding_publishing_frequency", resourceName, "finding_publishing_frequency"), + resource.TestCheckResourceAttrPair(datasourceName, "id", resourceName, "id"), + acctest.CheckResourceAttrGlobalARN(datasourceName, "service_role_arn", "iam", "role/aws-service-role/guardduty.amazonaws.com/AWSServiceRoleForAmazonGuardDuty"), + resource.TestCheckResourceAttr(datasourceName, "status", "ENABLED"), ), }, }, }) } -func testAccDetectorDataSourceConfig_basicResource() string { - return ` -resource "aws_guardduty_detector" "test" {} -` -} - -func testAccDetectorDataSourceConfig_basicResource2() string { - return ` +const testAccDetectorDataSourceConfig_basic = ` resource "aws_guardduty_detector" "test" {} -data "aws_guardduty_detector" "test" {} -` +data "aws_guardduty_detector" "test" { + depends_on = [aws_guardduty_detector.test] } +` -func testAccDetectorDataSourceConfig_explicit() string { - return ` +const testAccDetectorDataSourceConfig_id = ` resource "aws_guardduty_detector" "test" {} data "aws_guardduty_detector" "test" { id = aws_guardduty_detector.test.id } ` -} From c7205542c2b681ee45d77433272d05ee85851b99 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Thu, 28 Sep 2023 17:06:36 -0400 Subject: [PATCH 29/31] Acceptance test output: % make testacc TESTARGS='-run=TestAccGuardDuty_serial/^Detector$$/datasource_' PKG=guardduty ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./internal/service/guardduty/... -v -count 1 -parallel 20 -run=TestAccGuardDuty_serial/^Detector$/datasource_ -timeout 360m === RUN TestAccGuardDuty_serial === PAUSE TestAccGuardDuty_serial === CONT TestAccGuardDuty_serial === RUN TestAccGuardDuty_serial/Detector === RUN TestAccGuardDuty_serial/Detector/datasource_basic === RUN TestAccGuardDuty_serial/Detector/datasource_id --- PASS: TestAccGuardDuty_serial (43.59s) --- PASS: TestAccGuardDuty_serial/Detector (43.59s) --- PASS: TestAccGuardDuty_serial/Detector/datasource_basic (22.86s) --- PASS: TestAccGuardDuty_serial/Detector/datasource_id (20.73s) PASS ok github.com/hashicorp/terraform-provider-aws/internal/service/guardduty 48.907s From 5a114e42295cd136bfd0670191b776cb173a64a8 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Thu, 28 Sep 2023 17:26:40 -0400 Subject: [PATCH 30/31] Fix markdownlint 'MD047/single-trailing-newline Files should end with a single newline character'. --- website/docs/d/guardduty_detector.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/d/guardduty_detector.html.markdown b/website/docs/d/guardduty_detector.html.markdown index 02eeaa53c4a..bce278dcdbf 100644 --- a/website/docs/d/guardduty_detector.html.markdown +++ b/website/docs/d/guardduty_detector.html.markdown @@ -32,4 +32,4 @@ This data source exports the following attributes in addition to the arguments a * `status` - The status of the detector feature. * `finding_publishing_frequency` - The frequency of notifications sent about subsequent finding occurrences. * `service_role_arn` - Service-linked role that grants GuardDuty access to the resources in the AWS account. -* `status` - Current status of the detector. \ No newline at end of file +* `status` - Current status of the detector. From 1eaf3c50b207236e5d5ba946d9c3a1bffcc6e9b2 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 29 Sep 2023 08:20:16 -0400 Subject: [PATCH 31/31] Fix semgrep 'ci.caps3-in-func-name'. --- internal/service/guardduty/detector.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/service/guardduty/detector.go b/internal/service/guardduty/detector.go index 54f89212a9f..239a2294c44 100644 --- a/internal/service/guardduty/detector.go +++ b/internal/service/guardduty/detector.go @@ -336,7 +336,7 @@ func expandMalwareProtectionConfiguration(tfMap map[string]interface{}) *guarddu } } -func expandScanEc2InstanceWithFindings(tfMap map[string]interface{}) *guardduty.ScanEc2InstanceWithFindings { +func expandScanEc2InstanceWithFindings(tfMap map[string]interface{}) *guardduty.ScanEc2InstanceWithFindings { // nosemgrep:ci.caps3-in-func-name if tfMap == nil { return nil } @@ -450,7 +450,7 @@ func flattenMalwareProtectionConfiguration(apiObject *guardduty.MalwareProtectio return tfMap } -func flattenScanEc2InstanceWithFindingsResult(apiObject *guardduty.ScanEc2InstanceWithFindingsResult) map[string]interface{} { +func flattenScanEc2InstanceWithFindingsResult(apiObject *guardduty.ScanEc2InstanceWithFindingsResult) map[string]interface{} { // nosemgrep:ci.caps3-in-func-name if apiObject == nil { return nil } @@ -464,7 +464,7 @@ func flattenScanEc2InstanceWithFindingsResult(apiObject *guardduty.ScanEc2Instan return tfMap } -func flattenEbsVolumesResult(apiObject *guardduty.EbsVolumesResult) map[string]interface{} { +func flattenEbsVolumesResult(apiObject *guardduty.EbsVolumesResult) map[string]interface{} { // nosemgrep:ci.caps3-in-func-name if apiObject == nil { return nil }