Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

resource/aws_guardduty_detector: add support for datasources and s3_logs #19954

Merged
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 93 additions & 1 deletion aws/resource_aws_guardduty_detector.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,32 @@ func resourceAwsGuardDutyDetector() *schema.Resource {
Optional: true,
Computed: true,
},

"datasources": {
Type: schema.TypeList,
MaxItems: 1,
Optional: true,
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,
},
},
},
},
},
},
},

"tags": tagsSchema(),

"tags_all": tagsSchemaComputed(),
Expand All @@ -67,6 +93,10 @@ func resourceAwsGuardDutyDetectorCreate(d *schema.ResourceData, meta interface{}
input.FindingPublishingFrequency = aws.String(v.(string))
}

if v, ok := d.GetOk("datasources"); ok {
input.DataSources = expandDataSourceConfigurations(v.([]interface{}))
}

if len(tags) > 0 {
input.Tags = tags.IgnoreAws().GuarddutyTags()
}
Expand Down Expand Up @@ -114,6 +144,10 @@ func resourceAwsGuardDutyDetectorRead(d *schema.ResourceData, meta interface{})
d.Set("enable", *gdo.Status == guardduty.DetectorStatusEnabled)
d.Set("finding_publishing_frequency", gdo.FindingPublishingFrequency)

if err := d.Set("datasources", flattenDataSourceConfigurations(gdo.DataSources)); err != nil {
return fmt.Errorf("error setting datasources: %s", err)
}

tags := keyvaluetags.GuarddutyKeyValueTags(gdo.Tags).IgnoreAws().IgnoreConfig(ignoreTagsConfig)

//lintignore:AWSR002
Expand All @@ -131,13 +165,17 @@ func resourceAwsGuardDutyDetectorRead(d *schema.ResourceData, meta interface{})
func resourceAwsGuardDutyDetectorUpdate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).guarddutyconn

if d.HasChanges("enable", "finding_publishing_frequency") {
if d.HasChanges("enable", "finding_publishing_frequency", "datasources") {
input := guardduty.UpdateDetectorInput{
DetectorId: aws.String(d.Id()),
Enable: aws.Bool(d.Get("enable").(bool)),
FindingPublishingFrequency: aws.String(d.Get("finding_publishing_frequency").(string)),
}

if d.HasChange("datasources") {
input.DataSources = expandDataSourceConfigurations(d.Get("datasources").([]interface{}))
}

log.Printf("[DEBUG] Update GuardDuty Detector: %s", input)
_, err := conn.UpdateDetector(&input)
if err != nil {
Expand Down Expand Up @@ -187,3 +225,57 @@ func resourceAwsGuardDutyDetectorDelete(d *schema.ResourceData, meta interface{}

return nil
}

func expandDataSourceConfigurations(dsc []interface{}) *guardduty.DataSourceConfigurations {
if len(dsc) < 1 || dsc[0] == nil {
return nil
}

m := dsc[0].(map[string]interface{})

dataSourceConfigurations := &guardduty.DataSourceConfigurations{}

if v, ok := m["s3_logs"]; ok && v != "" && (len(v.([]interface{})) > 0 && v.([]interface{})[0] != nil) {
dataSourceConfigurations.S3Logs = expandS3LogsConfiguration(v.([]interface{}))
}

return dataSourceConfigurations
}

func expandS3LogsConfiguration(slc []interface{}) *guardduty.S3LogsConfiguration {
if len(slc) < 1 || slc[0] == nil {
return nil
}

m := slc[0].(map[string]interface{})

s3LogsConfiguration := &guardduty.S3LogsConfiguration{
Enable: aws.Bool(m["enable"].(bool)),
}

return s3LogsConfiguration
}

func flattenDataSourceConfigurations(dsc *guardduty.DataSourceConfigurationsResult) []interface{} {
if dsc == nil {
return []interface{}{}
}

m := map[string]interface{}{
"s3_logs": flattenS3LogsConfiguration(dsc.S3Logs),
}

return []interface{}{m}
}

func flattenS3LogsConfiguration(slc *guardduty.S3LogsConfigurationResult) []interface{} {
if slc == nil {
return []interface{}{}
}

m := map[string]interface{}{
"enable": aws.StringValue(slc.Status) == guardduty.DataSourceStatusEnabled,
}

return []interface{}{m}
}
48 changes: 48 additions & 0 deletions aws/resource_aws_guardduty_detector_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,42 @@ func testAccAwsGuardDutyDetector_tags(t *testing.T) {
})
}

func testAccAwsGuardDutyDetector_datasources_s3logs(t *testing.T) {
resourceName := "aws_guardduty_detector.test"

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ErrorCheck: testAccErrorCheck(t, guardduty.EndpointsID),
Providers: testAccProviders,
CheckDestroy: testAccCheckAwsGuardDutyDetectorDestroy,
Steps: []resource.TestStep{
{
Config: testAccGuardDutyDetectorConfigDatasourcesS3Logs(true),
Check: resource.ComposeTestCheckFunc(
testAccCheckAwsGuardDutyDetectorExists(resourceName),
resource.TestCheckResourceAttr(resourceName, "datasources.#", "1"),
resource.TestCheckResourceAttr(resourceName, "datasources.0.s3_logs.#", "1"),
resource.TestCheckResourceAttr(resourceName, "datasources.0.s3_logs.0.enable", "true"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
{
Config: testAccGuardDutyDetectorConfigDatasourcesS3Logs(false),
Check: resource.ComposeTestCheckFunc(
testAccCheckAwsGuardDutyDetectorExists(resourceName),
resource.TestCheckResourceAttr(resourceName, "datasources.#", "1"),
resource.TestCheckResourceAttr(resourceName, "datasources.0.s3_logs.#", "1"),
resource.TestCheckResourceAttr(resourceName, "datasources.0.s3_logs.0.enable", "false"),
),
},
},
})
}

func testAccCheckAwsGuardDutyDetectorDestroy(s *terraform.State) error {
conn := testAccProvider.Meta().(*AWSClient).guarddutyconn

Expand Down Expand Up @@ -239,3 +275,15 @@ resource "aws_guardduty_detector" "test" {
}
`, tagKey1, tagValue1, tagKey2, tagValue2)
}

func testAccGuardDutyDetectorConfigDatasourcesS3Logs(enable bool) string {
return fmt.Sprintf(`
resource "aws_guardduty_detector" "test" {
datasources {
s3_logs {
enable = %[1]t
}
}
}
`, enable)
}
9 changes: 5 additions & 4 deletions aws/resource_aws_guardduty_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@ import (
func TestAccAWSGuardDuty_serial(t *testing.T) {
testCases := map[string]map[string]func(t *testing.T){
"Detector": {
"basic": testAccAwsGuardDutyDetector_basic,
"tags": testAccAwsGuardDutyDetector_tags,
"datasource_basic": testAccAWSGuarddutyDetectorDataSource_basic,
"datasource_id": testAccAWSGuarddutyDetectorDataSource_Id,
"basic": testAccAwsGuardDutyDetector_basic,
"datasources_s3logs": testAccAwsGuardDutyDetector_datasources_s3logs,
"tags": testAccAwsGuardDutyDetector_tags,
"datasource_basic": testAccAWSGuarddutyDetectorDataSource_basic,
"datasource_id": testAccAWSGuarddutyDetectorDataSource_Id,
},
"Filter": {
"basic": testAccAwsGuardDutyFilter_basic,
Expand Down
19 changes: 19 additions & 0 deletions website/docs/r/guardduty_detector.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ Provides a resource to manage a GuardDuty detector.
```terraform
resource "aws_guardduty_detector" "MyDetector" {
enable = true

datasources {
s3_logs {
enable = true
}
}
}
```

Expand All @@ -26,8 +32,21 @@ 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.
* `tags` - (Optional) Key-value map of resource tags. If configured with a provider [`default_tags` configuration block](/docs/providers/aws/index.html#default_tags-configuration-block) present, tags with matching keys will overwrite those defined at the provider-level.

### Data Sources

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.

### S3 Logs

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`.

## Attributes Reference

In addition to all arguments above, the following attributes are exported:
Expand Down