From 541607e4479bf57e3ba35ffd363d2243c08869e8 Mon Sep 17 00:00:00 2001 From: Nick Cronin Date: Tue, 1 Feb 2022 11:12:28 +1100 Subject: [PATCH 01/12] Update GuardDuty resource to add Kubernetes audit log data source --- internal/service/guardduty/detector.go | 52 ++++++++++++++++++- internal/service/guardduty/detector_test.go | 48 +++++++++++++++++ internal/service/guardduty/guardduty_test.go | 11 ++-- .../docs/r/guardduty_detector.html.markdown | 10 ++++ 4 files changed, 115 insertions(+), 6 deletions(-) diff --git a/internal/service/guardduty/detector.go b/internal/service/guardduty/detector.go index fa5ca2a51bb..265204d5c3a 100644 --- a/internal/service/guardduty/detector.go +++ b/internal/service/guardduty/detector.go @@ -40,7 +40,7 @@ func ResourceDetector() *schema.Resource { "datasources": { Type: schema.TypeList, - MaxItems: 1, + MaxItems: 2, Optional: true, Computed: true, Elem: &schema.Resource{ @@ -59,6 +59,20 @@ func ResourceDetector() *schema.Resource { }, }, }, + "kubernetes_audit_logs": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enable": { + Type: schema.TypeBool, + Required: true, + }, + }, + }, + }, }, }, }, @@ -246,6 +260,9 @@ func expandGuardDutyDataSourceConfigurations(tfMap map[string]interface{}) *guar if v, ok := tfMap["s3_logs"].([]interface{}); ok && len(v) > 0 { apiObject.S3Logs = expandGuardDutyS3LogsConfiguration(v[0].(map[string]interface{})) } + if v, ok := tfMap["kubernetes_audit_logs"].([]interface{}); ok && len(v) > 0 { + apiObject.Kubernetes = expandGuardDutyKubernetesAuditLogsConfiguration(v[0].(map[string]interface{})) + } return apiObject } @@ -264,6 +281,21 @@ func expandGuardDutyS3LogsConfiguration(tfMap map[string]interface{}) *guardduty return apiObject } +func expandGuardDutyKubernetesAuditLogsConfiguration(tfMap map[string]interface{}) *guardduty.KubernetesConfiguration { + if tfMap == nil { + return nil + } + + apiObject := &guardduty.KubernetesConfiguration{} + + if v, ok := tfMap["enable"].(bool); ok { + apiObject.AuditLogs = &guardduty.KubernetesAuditLogsConfiguration{} + apiObject.AuditLogs.Enable = aws.Bool(v) + } + + return apiObject +} + func flattenGuardDutyDataSourceConfigurationsResult(apiObject *guardduty.DataSourceConfigurationsResult) map[string]interface{} { if apiObject == nil { return nil @@ -275,6 +307,10 @@ func flattenGuardDutyDataSourceConfigurationsResult(apiObject *guardduty.DataSou tfMap["s3_logs"] = []interface{}{flattenGuardDutyS3LogsConfigurationResult(v)} } + if v := apiObject.Kubernetes; v != nil { + tfMap["kubernetes_audit_logs"] = []interface{}{flattenGuardDutyKubernetesAuditLogsConfiguration(v)} + } + return tfMap } @@ -291,3 +327,17 @@ func flattenGuardDutyS3LogsConfigurationResult(apiObject *guardduty.S3LogsConfig return tfMap } + +func flattenGuardDutyKubernetesAuditLogsConfiguration(apiObject *guardduty.KubernetesConfigurationResult) map[string]interface{} { + if apiObject == nil { + return nil + } + + tfMap := map[string]interface{}{} + + if v := apiObject.AuditLogs.Status; v != nil { + tfMap["enable"] = aws.StringValue(v) == guardduty.DataSourceStatusEnabled + } + + return tfMap +} diff --git a/internal/service/guardduty/detector_test.go b/internal/service/guardduty/detector_test.go index b597d95dfd5..ddf83b6569c 100644 --- a/internal/service/guardduty/detector_test.go +++ b/internal/service/guardduty/detector_test.go @@ -143,6 +143,42 @@ func testAccDetector_datasources_s3logs(t *testing.T) { }) } +func testAccDetector_datasources_kubernetes_audit_logs(t *testing.T) { + resourceName := "aws_guardduty_detector.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, guardduty.EndpointsID), + Providers: acctest.Providers, + CheckDestroy: testAccCheckDetectorDestroy, + Steps: []resource.TestStep{ + { + Config: testAccGuardDutyDetectorConfigDatasourcesKubernetesAuditLogs(true), + Check: resource.ComposeTestCheckFunc( + testAccCheckDetectorExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "datasources.#", "1"), + resource.TestCheckResourceAttr(resourceName, "datasources.0.kubernetes_audit_logs.#", "1"), + resource.TestCheckResourceAttr(resourceName, "datasources.0.kubernetes_audit_logs.0.enable", "true"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccGuardDutyDetectorConfigDatasourcesKubernetesAuditLogs(false), + Check: resource.ComposeTestCheckFunc( + testAccCheckDetectorExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "datasources.#", "1"), + resource.TestCheckResourceAttr(resourceName, "datasources.0.kubernetes_audit_logs.#", "1"), + resource.TestCheckResourceAttr(resourceName, "datasources.0.kubernetes_audit_logs.0.enable", "false"), + ), + }, + }, + }) +} + func testAccCheckDetectorDestroy(s *terraform.State) error { conn := acctest.Provider.Meta().(*conns.AWSClient).GuardDutyConn @@ -234,3 +270,15 @@ resource "aws_guardduty_detector" "test" { } `, enable) } + +func testAccGuardDutyDetectorConfigDatasourcesKubernetesAuditLogs(enable bool) string { + return fmt.Sprintf(` +resource "aws_guardduty_detector" "test" { + datasources { + kubernetes_audit_logs { + enable = %[1]t + } + } +} +`, enable) +} diff --git a/internal/service/guardduty/guardduty_test.go b/internal/service/guardduty/guardduty_test.go index 95f1f646367..6892426b0f7 100644 --- a/internal/service/guardduty/guardduty_test.go +++ b/internal/service/guardduty/guardduty_test.go @@ -8,11 +8,12 @@ import ( func TestAccGuardDuty_serial(t *testing.T) { testCases := map[string]map[string]func(t *testing.T){ "Detector": { - "basic": testAccDetector_basic, - "datasources_s3logs": testAccDetector_datasources_s3logs, - "tags": testAccDetector_tags, - "datasource_basic": testAccDetectorDataSource_basic, - "datasource_id": testAccDetectorDataSource_ID, + "basic": testAccDetector_basic, + "datasources_s3logs": testAccDetector_datasources_s3logs, + "datasources_kubernetes_audit_logs": testAccDetector_datasources_kubernetes_audit_logs, + "tags": testAccDetector_tags, + "datasource_basic": testAccDetectorDataSource_basic, + "datasource_id": testAccDetectorDataSource_ID, }, "Filter": { "basic": testAccFilter_basic, diff --git a/website/docs/r/guardduty_detector.html.markdown b/website/docs/r/guardduty_detector.html.markdown index 846e6ddd03b..85640140ae8 100644 --- a/website/docs/r/guardduty_detector.html.markdown +++ b/website/docs/r/guardduty_detector.html.markdown @@ -22,6 +22,9 @@ resource "aws_guardduty_detector" "MyDetector" { s3_logs { enable = true } + kubernetes_audit_logs { + enabled = false + } } } ``` @@ -40,6 +43,7 @@ The following arguments are supported: The `datasources` block supports the following: * `s3_logs` - (Optional) Describes whether S3 data event logs are enabled as a data source. See [S3 Logs](#s3-logs) below for more details. +* `kubernetes_audit_logs` - (Optional) Describes whether Kubernetes audit log events are enabled as a data source. See [Kubernetes Audit Logs](#kubernetes-audit-logs) below for more details. ### S3 Logs @@ -47,6 +51,12 @@ This `s3_logs` block supports the following: * `enable` - (Required) If true, enables [S3 Protection](https://docs.aws.amazon.com/guardduty/latest/ug/s3_detection.html). Defaults to `true`. +### Kubernetes Audit Logs + +This `kubernetes_audit_logs` block supports the following: + +* `enable` - (Required) If true, enables [Kubernetes Protection](https://docs.aws.amazon.com/guardduty/latest/ug/kubernetes-protection.html). Defaults to `true`. + ## Attributes Reference In addition to all arguments above, the following attributes are exported: From 24156a4c7528b90fb9f7724f7b207d3036972edd Mon Sep 17 00:00:00 2001 From: Graham Davison Date: Tue, 31 May 2022 13:15:29 -0700 Subject: [PATCH 02/12] Improves basic test names --- internal/service/guardduty/detector_test.go | 16 ++++++++-------- internal/service/guardduty/member_test.go | 6 +++--- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/internal/service/guardduty/detector_test.go b/internal/service/guardduty/detector_test.go index 915566bd4c6..67bb0aac00b 100644 --- a/internal/service/guardduty/detector_test.go +++ b/internal/service/guardduty/detector_test.go @@ -24,7 +24,7 @@ func testAccDetector_basic(t *testing.T) { CheckDestroy: testAccCheckDetectorDestroy, Steps: []resource.TestStep{ { - Config: testAccDetectorConfig_basic1, + Config: testAccDetectorConfig_basic, Check: resource.ComposeTestCheckFunc( testAccCheckDetectorExists(resourceName), resource.TestCheckResourceAttrSet(resourceName, "account_id"), @@ -40,21 +40,21 @@ func testAccDetector_basic(t *testing.T) { ImportStateVerify: true, }, { - Config: testAccDetectorConfig_basic2, + Config: testAccDetectorConfig_disable, Check: resource.ComposeTestCheckFunc( testAccCheckDetectorExists(resourceName), resource.TestCheckResourceAttr(resourceName, "enable", "false"), ), }, { - Config: testAccDetectorConfig_basic3, + Config: testAccDetectorConfig_enable, Check: resource.ComposeTestCheckFunc( testAccCheckDetectorExists(resourceName), resource.TestCheckResourceAttr(resourceName, "enable", "true"), ), }, { - Config: testAccDetectorConfig_basic4, + Config: testAccDetectorConfig_findingPublishingFrequency, Check: resource.ComposeTestCheckFunc( testAccCheckDetectorExists(resourceName), resource.TestCheckResourceAttr(resourceName, "finding_publishing_frequency", "FIFTEEN_MINUTES"), @@ -216,23 +216,23 @@ func testAccCheckDetectorExists(name string) resource.TestCheckFunc { } } -const testAccDetectorConfig_basic1 = ` +const testAccDetectorConfig_basic = ` resource "aws_guardduty_detector" "test" {} ` -const testAccDetectorConfig_basic2 = ` +const testAccDetectorConfig_disable = ` resource "aws_guardduty_detector" "test" { enable = false } ` -const testAccDetectorConfig_basic3 = ` +const testAccDetectorConfig_enable = ` resource "aws_guardduty_detector" "test" { enable = true } ` -const testAccDetectorConfig_basic4 = ` +const testAccDetectorConfig_findingPublishingFrequency = ` resource "aws_guardduty_detector" "test" { finding_publishing_frequency = "FIFTEEN_MINUTES" } diff --git a/internal/service/guardduty/member_test.go b/internal/service/guardduty/member_test.go index abe977738a6..c527b3d0c8d 100644 --- a/internal/service/guardduty/member_test.go +++ b/internal/service/guardduty/member_test.go @@ -234,7 +234,7 @@ resource "aws_guardduty_member" "test" { detector_id = aws_guardduty_detector.test.id email = "%[3]s" } -`, testAccDetectorConfig_basic1, accountID, email) +`, testAccDetectorConfig_basic, accountID, email) } func testAccMemberConfig_invite(accountID, email string, invite bool) string { @@ -248,7 +248,7 @@ resource "aws_guardduty_member" "test" { email = "%[3]s" invite = %[4]t } -`, testAccDetectorConfig_basic1, accountID, email, invite) +`, testAccDetectorConfig_basic, accountID, email, invite) } func testAccMemberConfig_invitationMessage(accountID, email, invitationMessage string) string { @@ -263,5 +263,5 @@ resource "aws_guardduty_member" "test" { invitation_message = "%[4]s" invite = true } -`, testAccDetectorConfig_basic1, accountID, email, invitationMessage) +`, testAccDetectorConfig_basic, accountID, email, invitationMessage) } From 30bca89192dd6727637be152c4715349543bc05a Mon Sep 17 00:00:00 2001 From: Graham Davison Date: Tue, 31 May 2022 13:34:11 -0700 Subject: [PATCH 03/12] Actually check for existence --- internal/service/guardduty/detector_test.go | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/internal/service/guardduty/detector_test.go b/internal/service/guardduty/detector_test.go index 67bb0aac00b..5327aec6d17 100644 --- a/internal/service/guardduty/detector_test.go +++ b/internal/service/guardduty/detector_test.go @@ -207,11 +207,29 @@ func testAccCheckDetectorDestroy(s *terraform.State) error { func testAccCheckDetectorExists(name string) resource.TestCheckFunc { return func(s *terraform.State) error { - _, ok := s.RootModule().Resources[name] + rs, ok := s.RootModule().Resources[name] if !ok { return fmt.Errorf("Not found: %s", name) } + if rs.Primary.ID == "" { + return fmt.Errorf("Resource (%s) has empty ID", name) + } + + conn := acctest.Provider.Meta().(*conns.AWSClient).GuardDutyConn + + output, err := conn.GetDetector(&guardduty.GetDetectorInput{ + DetectorId: aws.String(rs.Primary.ID), + }) + + if err != nil { + return err + } + + if output == nil { + return fmt.Errorf("GuardDuty Detector not found: %s", name) + } + return nil } } From f5953327ef55343e62d07e1fcacd8b8593b24d3d Mon Sep 17 00:00:00 2001 From: Graham Davison Date: Tue, 31 May 2022 13:38:38 -0700 Subject: [PATCH 04/12] Adds `datasources` to the basic test --- internal/service/guardduty/detector_test.go | 25 ++++++++++++--------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/internal/service/guardduty/detector_test.go b/internal/service/guardduty/detector_test.go index 5327aec6d17..afc73f0df67 100644 --- a/internal/service/guardduty/detector_test.go +++ b/internal/service/guardduty/detector_test.go @@ -25,11 +25,14 @@ func testAccDetector_basic(t *testing.T) { Steps: []resource.TestStep{ { Config: testAccDetectorConfig_basic, - Check: resource.ComposeTestCheckFunc( + Check: resource.ComposeAggregateTestCheckFunc( testAccCheckDetectorExists(resourceName), resource.TestCheckResourceAttrSet(resourceName, "account_id"), acctest.MatchResourceAttrRegionalARN(resourceName, "arn", "guardduty", regexp.MustCompile("detector/.+$")), resource.TestCheckResourceAttr(resourceName, "enable", "true"), + resource.TestCheckResourceAttr(resourceName, "datasources.#", "1"), + resource.TestCheckResourceAttr(resourceName, "datasources.0.s3_logs.0.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "datasources.0.kubernetes_audit_logs.0.enable", "true"), resource.TestCheckResourceAttr(resourceName, "finding_publishing_frequency", "SIX_HOURS"), resource.TestCheckResourceAttr(resourceName, "tags.%", "0"), ), @@ -41,21 +44,21 @@ func testAccDetector_basic(t *testing.T) { }, { Config: testAccDetectorConfig_disable, - Check: resource.ComposeTestCheckFunc( + Check: resource.ComposeAggregateTestCheckFunc( testAccCheckDetectorExists(resourceName), resource.TestCheckResourceAttr(resourceName, "enable", "false"), ), }, { Config: testAccDetectorConfig_enable, - Check: resource.ComposeTestCheckFunc( + Check: resource.ComposeAggregateTestCheckFunc( testAccCheckDetectorExists(resourceName), resource.TestCheckResourceAttr(resourceName, "enable", "true"), ), }, { Config: testAccDetectorConfig_findingPublishingFrequency, - Check: resource.ComposeTestCheckFunc( + Check: resource.ComposeAggregateTestCheckFunc( testAccCheckDetectorExists(resourceName), resource.TestCheckResourceAttr(resourceName, "finding_publishing_frequency", "FIFTEEN_MINUTES"), ), @@ -75,7 +78,7 @@ func testAccDetector_tags(t *testing.T) { Steps: []resource.TestStep{ { Config: testAccDetectorConfig_tags1("key1", "value1"), - Check: resource.ComposeTestCheckFunc( + Check: resource.ComposeAggregateTestCheckFunc( testAccCheckDetectorExists(resourceName), resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1"), @@ -88,7 +91,7 @@ func testAccDetector_tags(t *testing.T) { }, { Config: testAccDetectorConfig_tags2("key1", "value1updated", "key2", "value2"), - Check: resource.ComposeTestCheckFunc( + Check: resource.ComposeAggregateTestCheckFunc( testAccCheckDetectorExists(resourceName), resource.TestCheckResourceAttr(resourceName, "tags.%", "2"), resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1updated"), @@ -97,7 +100,7 @@ func testAccDetector_tags(t *testing.T) { }, { Config: testAccDetectorConfig_tags1("key2", "value2"), - Check: resource.ComposeTestCheckFunc( + Check: resource.ComposeAggregateTestCheckFunc( testAccCheckDetectorExists(resourceName), resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), resource.TestCheckResourceAttr(resourceName, "tags.key2", "value2"), @@ -118,7 +121,7 @@ func testAccDetector_datasources_s3logs(t *testing.T) { Steps: []resource.TestStep{ { Config: testAccDetectorConfig_datasourcesS3Logs(true), - Check: resource.ComposeTestCheckFunc( + Check: resource.ComposeAggregateTestCheckFunc( testAccCheckDetectorExists(resourceName), resource.TestCheckResourceAttr(resourceName, "datasources.#", "1"), resource.TestCheckResourceAttr(resourceName, "datasources.0.s3_logs.#", "1"), @@ -132,7 +135,7 @@ func testAccDetector_datasources_s3logs(t *testing.T) { }, { Config: testAccDetectorConfig_datasourcesS3Logs(false), - Check: resource.ComposeTestCheckFunc( + Check: resource.ComposeAggregateTestCheckFunc( testAccCheckDetectorExists(resourceName), resource.TestCheckResourceAttr(resourceName, "datasources.#", "1"), resource.TestCheckResourceAttr(resourceName, "datasources.0.s3_logs.#", "1"), @@ -154,7 +157,7 @@ func testAccDetector_datasources_kubernetes_audit_logs(t *testing.T) { Steps: []resource.TestStep{ { Config: testAccGuardDutyDetectorConfigDatasourcesKubernetesAuditLogs(true), - Check: resource.ComposeTestCheckFunc( + Check: resource.ComposeAggregateTestCheckFunc( testAccCheckDetectorExists(resourceName), resource.TestCheckResourceAttr(resourceName, "datasources.#", "1"), resource.TestCheckResourceAttr(resourceName, "datasources.0.kubernetes_audit_logs.#", "1"), @@ -168,7 +171,7 @@ func testAccDetector_datasources_kubernetes_audit_logs(t *testing.T) { }, { Config: testAccGuardDutyDetectorConfigDatasourcesKubernetesAuditLogs(false), - Check: resource.ComposeTestCheckFunc( + Check: resource.ComposeAggregateTestCheckFunc( testAccCheckDetectorExists(resourceName), resource.TestCheckResourceAttr(resourceName, "datasources.#", "1"), resource.TestCheckResourceAttr(resourceName, "datasources.0.kubernetes_audit_logs.#", "1"), From 7a53e95072ba1447c363acfebc6ca6babddf3962 Mon Sep 17 00:00:00 2001 From: Graham Davison Date: Tue, 31 May 2022 16:19:07 -0700 Subject: [PATCH 05/12] Updates schema to match AWS API --- internal/service/guardduty/detector.go | 68 +++++++++++++++++---- internal/service/guardduty/detector_test.go | 24 ++++---- 2 files changed, 68 insertions(+), 24 deletions(-) diff --git a/internal/service/guardduty/detector.go b/internal/service/guardduty/detector.go index 043bf158481..106431787fe 100644 --- a/internal/service/guardduty/detector.go +++ b/internal/service/guardduty/detector.go @@ -40,7 +40,7 @@ func ResourceDetector() *schema.Resource { "datasources": { Type: schema.TypeList, - MaxItems: 2, + MaxItems: 1, Optional: true, Computed: true, Elem: &schema.Resource{ @@ -59,16 +59,25 @@ func ResourceDetector() *schema.Resource { }, }, }, - "kubernetes_audit_logs": { + "kubernetes": { Type: schema.TypeList, Optional: true, Computed: true, MaxItems: 1, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "enable": { - Type: schema.TypeBool, + "audit_logs": { + Type: schema.TypeList, Required: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enable": { + Type: schema.TypeBool, + Required: true, + }, + }, + }, }, }, }, @@ -260,8 +269,8 @@ func expandDataSourceConfigurations(tfMap map[string]interface{}) *guardduty.Dat if v, ok := tfMap["s3_logs"].([]interface{}); ok && len(v) > 0 { apiObject.S3Logs = expandS3LogsConfiguration(v[0].(map[string]interface{})) } - if v, ok := tfMap["kubernetes_audit_logs"].([]interface{}); ok && len(v) > 0 { - apiObject.Kubernetes = expandKubernetesAuditLogsConfiguration(v[0].(map[string]interface{})) + if v, ok := tfMap["kubernetes"].([]interface{}); ok && len(v) > 0 { + apiObject.Kubernetes = expandKubernetesConfiguration(v[0].(map[string]interface{})) } return apiObject @@ -281,16 +290,35 @@ func expandS3LogsConfiguration(tfMap map[string]interface{}) *guardduty.S3LogsCo return apiObject } -func expandKubernetesAuditLogsConfiguration(tfMap map[string]interface{}) *guardduty.KubernetesConfiguration { +func expandKubernetesConfiguration(tfMap map[string]interface{}) *guardduty.KubernetesConfiguration { if tfMap == nil { return nil } - apiObject := &guardduty.KubernetesConfiguration{} + l, ok := tfMap["audit_logs"].([]interface{}) + if !ok || len(l) == 0 { + return nil + } + + m, ok := l[0].(map[string]interface{}) + if !ok { + return nil + } + + return &guardduty.KubernetesConfiguration{ + AuditLogs: expandKubernetesAuditLogsConfiguration(m), + } +} + +func expandKubernetesAuditLogsConfiguration(tfMap map[string]interface{}) *guardduty.KubernetesAuditLogsConfiguration { + if tfMap == nil { + return nil + } + + apiObject := &guardduty.KubernetesAuditLogsConfiguration{} if v, ok := tfMap["enable"].(bool); ok { - apiObject.AuditLogs = &guardduty.KubernetesAuditLogsConfiguration{} - apiObject.AuditLogs.Enable = aws.Bool(v) + apiObject.Enable = aws.Bool(v) // This can be flattened a ton } return apiObject @@ -308,7 +336,7 @@ func flattenDataSourceConfigurationsResult(apiObject *guardduty.DataSourceConfig } if v := apiObject.Kubernetes; v != nil { - tfMap["kubernetes_audit_logs"] = []interface{}{flattenKubernetesAuditLogsConfiguration(v)} + tfMap["kubernetes"] = []interface{}{flattenKubernetesConfiguration(v)} } return tfMap @@ -328,14 +356,28 @@ func flattenS3LogsConfigurationResult(apiObject *guardduty.S3LogsConfigurationRe return tfMap } -func flattenKubernetesAuditLogsConfiguration(apiObject *guardduty.KubernetesConfigurationResult) map[string]interface{} { +func flattenKubernetesConfiguration(apiObject *guardduty.KubernetesConfigurationResult) map[string]interface{} { if apiObject == nil { return nil } tfMap := map[string]interface{}{} - if v := apiObject.AuditLogs.Status; v != nil { + if v := apiObject.AuditLogs; v != nil { + tfMap["audit_logs"] = []interface{}{flattenKubernetesAuditLogsConfiguration(v)} + } + + return tfMap +} + +func flattenKubernetesAuditLogsConfiguration(apiObject *guardduty.KubernetesAuditLogsConfigurationResult) 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 } diff --git a/internal/service/guardduty/detector_test.go b/internal/service/guardduty/detector_test.go index afc73f0df67..02557e0ee3e 100644 --- a/internal/service/guardduty/detector_test.go +++ b/internal/service/guardduty/detector_test.go @@ -32,7 +32,7 @@ func testAccDetector_basic(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "enable", "true"), resource.TestCheckResourceAttr(resourceName, "datasources.#", "1"), resource.TestCheckResourceAttr(resourceName, "datasources.0.s3_logs.0.enable", "true"), - resource.TestCheckResourceAttr(resourceName, "datasources.0.kubernetes_audit_logs.0.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "datasources.0.kubernetes.0.audit_logs.0.enable", "true"), resource.TestCheckResourceAttr(resourceName, "finding_publishing_frequency", "SIX_HOURS"), resource.TestCheckResourceAttr(resourceName, "tags.%", "0"), ), @@ -150,18 +150,18 @@ func testAccDetector_datasources_kubernetes_audit_logs(t *testing.T) { resourceName := "aws_guardduty_detector.test" resource.Test(t, resource.TestCase{ - PreCheck: func() { acctest.PreCheck(t) }, - ErrorCheck: acctest.ErrorCheck(t, guardduty.EndpointsID), - Providers: acctest.Providers, - CheckDestroy: testAccCheckDetectorDestroy, + PreCheck: func() { acctest.PreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, guardduty.EndpointsID), + ProviderFactories: acctest.ProviderFactories, + CheckDestroy: testAccCheckDetectorDestroy, Steps: []resource.TestStep{ { Config: testAccGuardDutyDetectorConfigDatasourcesKubernetesAuditLogs(true), Check: resource.ComposeAggregateTestCheckFunc( testAccCheckDetectorExists(resourceName), resource.TestCheckResourceAttr(resourceName, "datasources.#", "1"), - resource.TestCheckResourceAttr(resourceName, "datasources.0.kubernetes_audit_logs.#", "1"), - resource.TestCheckResourceAttr(resourceName, "datasources.0.kubernetes_audit_logs.0.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "datasources.0.kubernetes.0.audit_logs.#", "1"), + resource.TestCheckResourceAttr(resourceName, "datasources.0.kubernetes.0.audit_logs.0.enable", "true"), ), }, { @@ -174,8 +174,8 @@ func testAccDetector_datasources_kubernetes_audit_logs(t *testing.T) { Check: resource.ComposeAggregateTestCheckFunc( testAccCheckDetectorExists(resourceName), resource.TestCheckResourceAttr(resourceName, "datasources.#", "1"), - resource.TestCheckResourceAttr(resourceName, "datasources.0.kubernetes_audit_logs.#", "1"), - resource.TestCheckResourceAttr(resourceName, "datasources.0.kubernetes_audit_logs.0.enable", "false"), + resource.TestCheckResourceAttr(resourceName, "datasources.0.kubernetes.0.audit_logs.#", "1"), + resource.TestCheckResourceAttr(resourceName, "datasources.0.kubernetes.0.audit_logs.0.enable", "false"), ), }, }, @@ -296,8 +296,10 @@ func testAccGuardDutyDetectorConfigDatasourcesKubernetesAuditLogs(enable bool) s return fmt.Sprintf(` resource "aws_guardduty_detector" "test" { datasources { - kubernetes_audit_logs { - enable = %[1]t + kubernetes { + audit_logs { + enable = %[1]t + } } } } From 2cae0165234c5365953b2a280f45b2bfb5c07f73 Mon Sep 17 00:00:00 2001 From: Graham Davison Date: Tue, 31 May 2022 16:59:13 -0700 Subject: [PATCH 06/12] Fixes error messages --- internal/service/guardduty/detector.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/internal/service/guardduty/detector.go b/internal/service/guardduty/detector.go index 106431787fe..bcf893d9ef3 100644 --- a/internal/service/guardduty/detector.go +++ b/internal/service/guardduty/detector.go @@ -132,7 +132,7 @@ func resourceDetectorCreate(d *schema.ResourceData, meta interface{}) error { log.Printf("[DEBUG] Creating GuardDuty Detector: %s", input) output, err := conn.CreateDetector(&input) if err != nil { - return fmt.Errorf("Creating GuardDuty Detector failed: %s", err.Error()) + return fmt.Errorf("Creating GuardDuty Detector failed: %w", err) } d.SetId(aws.StringValue(output.DetectorId)) @@ -156,7 +156,7 @@ func resourceDetectorRead(d *schema.ResourceData, meta interface{}) error { d.SetId("") return nil } - return fmt.Errorf("Reading GuardDuty Detector '%s' failed: %s", d.Id(), err.Error()) + return fmt.Errorf("Reading GuardDuty Detector '%s' failed: %w", d.Id(), err) } arn := arn.ARN{ @@ -212,7 +212,7 @@ func resourceDetectorUpdate(d *schema.ResourceData, meta interface{}) error { log.Printf("[DEBUG] Update GuardDuty Detector: %s", input) _, err := conn.UpdateDetector(&input) if err != nil { - return fmt.Errorf("Updating GuardDuty Detector '%s' failed: %s", d.Id(), err.Error()) + return fmt.Errorf("Updating GuardDuty Detector '%s' failed: %w", d.Id(), err) } } @@ -220,7 +220,7 @@ func resourceDetectorUpdate(d *schema.ResourceData, meta interface{}) error { o, n := d.GetChange("tags_all") if err := UpdateTags(conn, d.Get("arn").(string), o, n); err != nil { - return fmt.Errorf("error updating GuardDuty Detector (%s) tags: %s", d.Get("arn").(string), err) + return fmt.Errorf("error updating GuardDuty Detector (%s) tags: %w", d.Get("arn").(string), err) } } From 3c0da4312a4f8667ed702b3464ead233fa9edff8 Mon Sep 17 00:00:00 2001 From: Graham Davison Date: Tue, 31 May 2022 16:59:43 -0700 Subject: [PATCH 07/12] Adds test for setting both S3 and Kubernetes configs --- internal/service/guardduty/detector_test.go | 79 +++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/internal/service/guardduty/detector_test.go b/internal/service/guardduty/detector_test.go index 02557e0ee3e..5d485c0d3b3 100644 --- a/internal/service/guardduty/detector_test.go +++ b/internal/service/guardduty/detector_test.go @@ -182,6 +182,68 @@ func testAccDetector_datasources_kubernetes_audit_logs(t *testing.T) { }) } +func testAccDetector_datasources_all(t *testing.T) { + resourceName := "aws_guardduty_detector.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, guardduty.EndpointsID), + ProviderFactories: acctest.ProviderFactories, + CheckDestroy: testAccCheckDetectorDestroy, + Steps: []resource.TestStep{ + { + Config: testAccGuardDutyDetectorConfigDatasourcesAll(true, false), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckDetectorExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "datasources.#", "1"), + resource.TestCheckResourceAttr(resourceName, "datasources.0.kubernetes.0.audit_logs.#", "1"), + resource.TestCheckResourceAttr(resourceName, "datasources.0.kubernetes.0.audit_logs.0.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "datasources.0.s3_logs.#", "1"), + resource.TestCheckResourceAttr(resourceName, "datasources.0.s3_logs.0.enable", "false"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccGuardDutyDetectorConfigDatasourcesAll(true, true), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckDetectorExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "datasources.#", "1"), + resource.TestCheckResourceAttr(resourceName, "datasources.0.kubernetes.0.audit_logs.#", "1"), + resource.TestCheckResourceAttr(resourceName, "datasources.0.kubernetes.0.audit_logs.0.enable", "true"), + resource.TestCheckResourceAttr(resourceName, "datasources.0.s3_logs.#", "1"), + resource.TestCheckResourceAttr(resourceName, "datasources.0.s3_logs.0.enable", "true"), + ), + }, + { + Config: testAccGuardDutyDetectorConfigDatasourcesAll(false, false), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckDetectorExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "datasources.#", "1"), + resource.TestCheckResourceAttr(resourceName, "datasources.0.kubernetes.0.audit_logs.#", "1"), + resource.TestCheckResourceAttr(resourceName, "datasources.0.kubernetes.0.audit_logs.0.enable", "false"), + resource.TestCheckResourceAttr(resourceName, "datasources.0.s3_logs.#", "1"), + resource.TestCheckResourceAttr(resourceName, "datasources.0.s3_logs.0.enable", "false"), + ), + }, + { + Config: testAccGuardDutyDetectorConfigDatasourcesAll(false, true), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckDetectorExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "datasources.#", "1"), + resource.TestCheckResourceAttr(resourceName, "datasources.0.kubernetes.0.audit_logs.#", "1"), + resource.TestCheckResourceAttr(resourceName, "datasources.0.kubernetes.0.audit_logs.0.enable", "false"), + resource.TestCheckResourceAttr(resourceName, "datasources.0.s3_logs.#", "1"), + resource.TestCheckResourceAttr(resourceName, "datasources.0.s3_logs.0.enable", "true"), + ), + }, + }, + }) +} + func testAccCheckDetectorDestroy(s *terraform.State) error { conn := acctest.Provider.Meta().(*conns.AWSClient).GuardDutyConn @@ -305,3 +367,20 @@ resource "aws_guardduty_detector" "test" { } `, enable) } + +func testAccGuardDutyDetectorConfigDatasourcesAll(enableK8s, enableS3 bool) string { + return fmt.Sprintf(` +resource "aws_guardduty_detector" "test" { + datasources { + kubernetes { + audit_logs { + enable = %[1]t + } + } + s3_logs { + enable = %[2]t + } + } +} +`, enableK8s, enableS3) +} From e4b1679395549a1f916e7aaaaccbb6ec3164459a Mon Sep 17 00:00:00 2001 From: Graham Davison Date: Wed, 1 Jun 2022 12:15:46 -0700 Subject: [PATCH 08/12] Fixes acceptance test indentation --- internal/service/guardduty/detector_test.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/internal/service/guardduty/detector_test.go b/internal/service/guardduty/detector_test.go index 5d485c0d3b3..6bed3ec0028 100644 --- a/internal/service/guardduty/detector_test.go +++ b/internal/service/guardduty/detector_test.go @@ -359,9 +359,9 @@ func testAccGuardDutyDetectorConfigDatasourcesKubernetesAuditLogs(enable bool) s resource "aws_guardduty_detector" "test" { datasources { kubernetes { - audit_logs { + audit_logs { enable = %[1]t - } + } } } } @@ -373,14 +373,14 @@ func testAccGuardDutyDetectorConfigDatasourcesAll(enableK8s, enableS3 bool) stri resource "aws_guardduty_detector" "test" { datasources { kubernetes { - audit_logs { + audit_logs { enable = %[1]t - } + } } s3_logs { - enable = %[2]t - } - } + enable = %[2]t + } + } } `, enableK8s, enableS3) } From 3126962ca574518930d3aefa8a3f123db0f0eab0 Mon Sep 17 00:00:00 2001 From: Graham Davison Date: Wed, 1 Jun 2022 12:16:07 -0700 Subject: [PATCH 09/12] Updates documentation --- .../docs/r/guardduty_detector.html.markdown | 29 ++++++++++++++----- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/website/docs/r/guardduty_detector.html.markdown b/website/docs/r/guardduty_detector.html.markdown index 85640140ae8..23b8e440471 100644 --- a/website/docs/r/guardduty_detector.html.markdown +++ b/website/docs/r/guardduty_detector.html.markdown @@ -22,8 +22,10 @@ resource "aws_guardduty_detector" "MyDetector" { s3_logs { enable = true } - kubernetes_audit_logs { - enabled = false + kubernetes { + audit_logs { + enable = false + } } } } @@ -42,20 +44,31 @@ The following arguments are supported: The `datasources` block supports the following: -* `s3_logs` - (Optional) Describes whether S3 data event logs are enabled as a data source. See [S3 Logs](#s3-logs) below for more details. -* `kubernetes_audit_logs` - (Optional) Describes whether Kubernetes audit log events are enabled as a data source. See [Kubernetes Audit Logs](#kubernetes-audit-logs) below for more details. +* `s3_logs` - (Optional) Configures [S3 protection](https://docs.aws.amazon.com/guardduty/latest/ug/s3-protection.html). + See [S3 Logs](#s3-logs) below for more details. +* `kubernetes` - (Optional) Configures [Kubernetes protection](https://docs.aws.amazon.com/guardduty/latest/ug/kubernetes-protection.html). + See [Kubernetes](#kubernetes) and [Kubernetes Audit Logs](#kubernetes-audit-logs) below for more details. ### S3 Logs -This `s3_logs` block supports the following: +The `s3_logs` block supports the following: -* `enable` - (Required) If true, enables [S3 Protection](https://docs.aws.amazon.com/guardduty/latest/ug/s3_detection.html). Defaults to `true`. +* `enable` - (Required) If true, enables [S3 protection](https://docs.aws.amazon.com/guardduty/latest/ug/s3-protection.html). + Defaults to `true`. + +### Kubernetes + +The `kubernetes` block supports the following: + +* `audit_logs` - (Required) Configures Kubernetes audit logs as a data source for [Kubernetes protection](https://docs.aws.amazon.com/guardduty/latest/ug/kubernetes-protection.html). + See [Kubernetes Audit Logs](#kubernetes-audit-logs) below for more details. ### Kubernetes Audit Logs -This `kubernetes_audit_logs` block supports the following: +The `audit_logs` block supports the following: -* `enable` - (Required) If true, enables [Kubernetes Protection](https://docs.aws.amazon.com/guardduty/latest/ug/kubernetes-protection.html). Defaults to `true`. +* `enable` - (Required) If true, enables Kubernetes audit logs as a data source for [Kubernetes protection](https://docs.aws.amazon.com/guardduty/latest/ug/kubernetes-protection.html). + Defaults to `true`. ## Attributes Reference From 864209dd7cd212f9befc174ec109790c4b3a3812 Mon Sep 17 00:00:00 2001 From: Graham Davison Date: Wed, 1 Jun 2022 12:28:24 -0700 Subject: [PATCH 10/12] Adds CHANGELOG entry --- .changelog/22859.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/22859.txt diff --git a/.changelog/22859.txt b/.changelog/22859.txt new file mode 100644 index 00000000000..2af56bc2ef4 --- /dev/null +++ b/.changelog/22859.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +resource/aws_guardduty_detector: Add `kubernetes` attribute to the `datasources` configuration block +``` From 407e7c2eb5b546498602df95937180e36fefc021 Mon Sep 17 00:00:00 2001 From: Graham Davison Date: Wed, 1 Jun 2022 13:19:55 -0700 Subject: [PATCH 11/12] Adds missing test to suite --- internal/service/guardduty/guardduty_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/service/guardduty/guardduty_test.go b/internal/service/guardduty/guardduty_test.go index 6892426b0f7..6c4317d839d 100644 --- a/internal/service/guardduty/guardduty_test.go +++ b/internal/service/guardduty/guardduty_test.go @@ -11,6 +11,7 @@ func TestAccGuardDuty_serial(t *testing.T) { "basic": testAccDetector_basic, "datasources_s3logs": testAccDetector_datasources_s3logs, "datasources_kubernetes_audit_logs": testAccDetector_datasources_kubernetes_audit_logs, + "datasources_all": testAccDetector_datasources_all, "tags": testAccDetector_tags, "datasource_basic": testAccDetectorDataSource_basic, "datasource_id": testAccDetectorDataSource_ID, From 52217ed9ff7593f1929d73711a453868d41a9463 Mon Sep 17 00:00:00 2001 From: Graham Davison Date: Wed, 1 Jun 2022 14:51:40 -0700 Subject: [PATCH 12/12] Clean up --- internal/service/guardduty/detector.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/service/guardduty/detector.go b/internal/service/guardduty/detector.go index bcf893d9ef3..57a82afb505 100644 --- a/internal/service/guardduty/detector.go +++ b/internal/service/guardduty/detector.go @@ -318,7 +318,7 @@ func expandKubernetesAuditLogsConfiguration(tfMap map[string]interface{}) *guard apiObject := &guardduty.KubernetesAuditLogsConfiguration{} if v, ok := tfMap["enable"].(bool); ok { - apiObject.Enable = aws.Bool(v) // This can be flattened a ton + apiObject.Enable = aws.Bool(v) } return apiObject