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

Guardduty: organization malware protection configuration #25992 #25997

Merged
3 changes: 3 additions & 0 deletions .changelog/25992.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
resource/aws_guardduty_organization_configuration: Add `malware_protection` attribute to the `datasources` configuration block
```
7 changes: 4 additions & 3 deletions internal/service/guardduty/guardduty_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,10 @@ func TestAccGuardDuty_serial(t *testing.T) {
"basic": testAccOrganizationAdminAccount_basic,
},
"OrganizationConfiguration": {
"basic": testAccOrganizationConfiguration_basic,
"s3Logs": testAccOrganizationConfiguration_s3logs,
"kubernetes": testAccOrganizationConfiguration_kubernetes,
"basic": testAccOrganizationConfiguration_basic,
"s3Logs": testAccOrganizationConfiguration_s3logs,
"kubernetes": testAccOrganizationConfiguration_kubernetes,
"malwareProtection": testAccOrganizationConfiguration_malwareprotection,
},
"ThreatIntelSet": {
"basic": testAccThreatintelset_basic,
Expand Down
135 changes: 135 additions & 0 deletions internal/service/guardduty/organization_configuration.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,38 @@ func ResourceOrganizationConfiguration() *schema.Resource {
},
},
},
"malware_protection": {
Type: schema.TypeList,
Optional: true,
Computed: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"scan_ec2_instance_with_findings": {
Type: schema.TypeList,
Required: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"ebs_volumes": {
Type: schema.TypeList,
Required: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"auto_enable": {
Type: schema.TypeBool,
Required: true,
},
},
},
},
},
},
},
},
},
},
},
},
},
Expand Down Expand Up @@ -165,6 +197,10 @@ func expandOrganizationDataSourceConfigurations(tfMap map[string]interface{}) *g
apiObject.Kubernetes = expandOrganizationKubernetesConfiguration(v[0].(map[string]interface{}))
}

if v, ok := tfMap["malware_protection"].([]interface{}); ok && len(v) > 0 {
apiObject.MalwareProtection = expandOrganizationMalwareProtectionConfiguration(v[0].(map[string]interface{}))
}

return apiObject
}

Expand Down Expand Up @@ -202,6 +238,60 @@ func expandOrganizationKubernetesConfiguration(tfMap map[string]interface{}) *gu
}
}

func expandOrganizationMalwareProtectionConfiguration(tfMap map[string]interface{}) *guardduty.OrganizationMalwareProtectionConfiguration {
if tfMap == nil {
return nil
}

l, ok := tfMap["scan_ec2_instance_with_findings"].([]interface{})
if !ok || len(l) == 0 {
return nil
}

m, ok := l[0].(map[string]interface{})
if !ok {
return nil
}

return &guardduty.OrganizationMalwareProtectionConfiguration{
ScanEc2InstanceWithFindings: expandOrganizationScanEC2InstanceWithFindingsConfiguration(m),
}
}

func expandOrganizationScanEC2InstanceWithFindingsConfiguration(tfMap map[string]interface{}) *guardduty.OrganizationScanEc2InstanceWithFindings {
if tfMap == nil {
return nil
}

l, ok := tfMap["ebs_volumes"].([]interface{})
if !ok || len(l) == 0 {
return nil
}

m, ok := l[0].(map[string]interface{})
if !ok {
return nil
}

return &guardduty.OrganizationScanEc2InstanceWithFindings{
EbsVolumes: expandOrganizationEBSVolumesConfiguration(m),
}
}

func expandOrganizationEBSVolumesConfiguration(tfMap map[string]interface{}) *guardduty.OrganizationEbsVolumes {
if tfMap == nil {
return nil
}

apiObject := &guardduty.OrganizationEbsVolumes{}

if v, ok := tfMap["auto_enable"].(bool); ok {
apiObject.AutoEnable = aws.Bool(v)
}

return apiObject
}

func expandOrganizationKubernetesAuditLogsConfiguration(tfMap map[string]interface{}) *guardduty.OrganizationKubernetesAuditLogsConfiguration {
if tfMap == nil {
return nil
Expand Down Expand Up @@ -229,6 +319,9 @@ func flattenOrganizationDataSourceConfigurationsResult(apiObject *guardduty.Orga
if v := apiObject.Kubernetes; v != nil {
tfMap["kubernetes"] = []interface{}{flattenOrganizationKubernetesConfigurationResult(v)}
}
if v := apiObject.MalwareProtection; v != nil {
tfMap["malware_protection"] = []interface{}{flattenOrganizationMalwareProtectionConfigurationResult(v)}
}
return tfMap
}

Expand Down Expand Up @@ -273,3 +366,45 @@ func flattenOrganizationKubernetesAuditLogsConfiguration(apiObject *guardduty.Or

return tfMap
}

func flattenOrganizationMalwareProtectionConfigurationResult(apiObject *guardduty.OrganizationMalwareProtectionConfigurationResult) map[string]interface{} {
if apiObject == nil {
return nil
}

tfMap := map[string]interface{}{}

if v := apiObject.ScanEc2InstanceWithFindings; v != nil {
tfMap["scan_ec2_instance_with_findings"] = []interface{}{flattenOrganizationMalwareProtectionScanEC2InstanceWithFindingsResult(v)}
}

return tfMap
}

func flattenOrganizationMalwareProtectionScanEC2InstanceWithFindingsResult(apiObject *guardduty.OrganizationScanEc2InstanceWithFindingsResult) map[string]interface{} {
if apiObject == nil {
return nil
}

tfMap := map[string]interface{}{}

if v := apiObject.EbsVolumes; v != nil {
tfMap["ebs_volumes"] = []interface{}{flattenOrganizationMalwareProtectionEBSVolumesResult(v)}
}

return tfMap
}

func flattenOrganizationMalwareProtectionEBSVolumesResult(apiObject *guardduty.OrganizationEbsVolumesResult) map[string]interface{} {
if apiObject == nil {
return nil
}

tfMap := map[string]interface{}{}

if v := apiObject.AutoEnable; v != nil {
tfMap["auto_enable"] = aws.BoolValue(v)
}

return tfMap
}
84 changes: 84 additions & 0 deletions internal/service/guardduty/organization_configuration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,52 @@ func testAccOrganizationConfiguration_kubernetes(t *testing.T) {
})
}

func testAccOrganizationConfiguration_malwareprotection(t *testing.T) {
detectorResourceName := "aws_guardduty_detector.test"
resourceName := "aws_guardduty_organization_configuration.test"

resource.Test(t, resource.TestCase{
PreCheck: func() {
acctest.PreCheck(t)
acctest.PreCheckOrganizationsAccount(t)
},
ErrorCheck: acctest.ErrorCheck(t, guardduty.EndpointsID),
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
CheckDestroy: testAccCheckDetectorDestroy,
Steps: []resource.TestStep{
{
Config: testAccOrganizationConfigurationConfig_malwareprotection(true),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(resourceName, "auto_enable", "true"),
resource.TestCheckResourceAttr(resourceName, "datasources.#", "1"),
resource.TestCheckResourceAttr(resourceName, "datasources.0.malware_protection.#", "1"),
resource.TestCheckResourceAttr(resourceName, "datasources.0.malware_protection.0.scan_ec2_instance_with_findings.#", "1"),
resource.TestCheckResourceAttr(resourceName, "datasources.0.malware_protection.0.scan_ec2_instance_with_findings.0.ebs_volumes.#", "1"),
resource.TestCheckResourceAttr(resourceName, "datasources.0.malware_protection.0.scan_ec2_instance_with_findings.0.ebs_volumes.0.auto_enable", "true"),
resource.TestCheckResourceAttrPair(resourceName, "detector_id", detectorResourceName, "id"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
{
Config: testAccOrganizationConfigurationConfig_malwareprotection(false),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(resourceName, "auto_enable", "true"),
resource.TestCheckResourceAttr(resourceName, "datasources.#", "1"),
resource.TestCheckResourceAttr(resourceName, "datasources.0.malware_protection.#", "1"),
resource.TestCheckResourceAttr(resourceName, "datasources.0.malware_protection.0.scan_ec2_instance_with_findings.#", "1"),
resource.TestCheckResourceAttr(resourceName, "datasources.0.malware_protection.0.scan_ec2_instance_with_findings.0.ebs_volumes.#", "1"),
resource.TestCheckResourceAttr(resourceName, "datasources.0.malware_protection.0.scan_ec2_instance_with_findings.0.ebs_volumes.0.auto_enable", "false"),
resource.TestCheckResourceAttrPair(resourceName, "detector_id", detectorResourceName, "id"),
),
},
},
})
}

func testAccOrganizationConfigurationConfig_autoEnable(autoEnable bool) string {
return fmt.Sprintf(`
data "aws_caller_identity" "current" {}
Expand Down Expand Up @@ -230,3 +276,41 @@ resource "aws_guardduty_organization_configuration" "test" {
}
`, autoEnable)
}

func testAccOrganizationConfigurationConfig_malwareprotection(autoEnable bool) string {
return fmt.Sprintf(`
data "aws_caller_identity" "current" {}

data "aws_partition" "current" {}

resource "aws_organizations_organization" "test" {
aws_service_access_principals = ["guardduty.${data.aws_partition.current.dns_suffix}", "malware-protection.guardduty.${data.aws_partition.current.dns_suffix}"]
feature_set = "ALL"
}

resource "aws_guardduty_detector" "test" {}

resource "aws_guardduty_organization_admin_account" "test" {
depends_on = [aws_organizations_organization.test]

admin_account_id = data.aws_caller_identity.current.account_id
}

resource "aws_guardduty_organization_configuration" "test" {
depends_on = [aws_guardduty_organization_admin_account.test]

auto_enable = true
detector_id = aws_guardduty_detector.test.id

datasources {
malware_protection {
scan_ec2_instance_with_findings {
ebs_volumes {
auto_enable = %[1]t
}
}
}
}
}
`, autoEnable)
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,13 @@ resource "aws_guardduty_organization_configuration" "example" {
enable = true
}
}
malware_protection {
scan_ec2_instance_with_findings {
ebs_volumes {
auto_enable = true
}
}
}
}
}
```
Expand All @@ -48,6 +55,7 @@ The following arguments are supported:

* `s3_logs` - (Optional) Enable S3 Protection automatically for new member accounts.
* `kubernetes` - (Optional) Enable Kubernetes Audit Logs Monitoring automatically for new member accounts.
* `malware_protection` - (Optional) Enable Malware Protection automatically for new member accounts.

### S3 Logs

Expand All @@ -68,6 +76,24 @@ The `audit_logs` block supports the following:
* `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`.

### Malware Protection
`malware_protection` block supports the following:

* `scan_ec2_instance_with_findings` - (Required) Configure whether [Malware Protection](https://docs.aws.amazon.com/guardduty/latest/ug/malware-protection.html) for EC2 instances with findings should be auto-enabled for new members joining the organization.
See [Scan EC2 instance with findings](#scan-ec2-instance-with-findings) below for more details.

#### Scan EC2 instance with findings
The `scan_ec2_instance_with_findings` block supports the following:

* `ebs_volumes` - (Required) Configure whether scanning EBS volumes should be auto-enabled for new members joining the organization
See [EBS volumes](#ebs-volumes) below for more details.

#### EBS volumes
The `ebs_volumes` block supports the following:

* `auto_enable` - (Required) If true, enables [Malware Protection](https://docs.aws.amazon.com/guardduty/latest/ug/malware-protection.html) for all new accounts joining the organization.
Defaults to `true`.

## Attributes Reference

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