GuardDuty GovCloud

Hi all,

I’m trying to deploy AWS GuardDuty to an organization with administration of the service delegated to a particular account. I have this working in an organization of accounts in the commercial partition but in this GovCloud organization I just get BadRequestException: The request is rejected because an invalid or out-of-range value is specified as an input parameter.

I understand that malware_protection is not available in GovCloud and I have it disabled in the datasources block in aws_guardduty_detector. I also have auto-enable set to false in aws_guardduty_organization_configuration. I always get the same error. If I remove all mention of malware_protection I still get the error. Any Idea what I’m missing?

Here’s what I’m trying to run in the administration account:

resource "aws_guardduty_detector" "comm_detector" {
  count  = var.govcloud ? 0 : 1
  enable = true

  datasources {
    s3_logs {
      enable = true
    }
    kubernetes {
      audit_logs {
        enable = false
      }
    }
    malware_protection {
      scan_ec2_instance_with_findings {
        ebs_volumes {
          enable = true
        }
      }
    }
  }
}

resource "aws_guardduty_detector" "govcloud_detector" {
  count  = var.govcloud ? 1 : 0
  enable = true

  datasources {
    s3_logs {
      enable = true
    }
    kubernetes {
      audit_logs {
        enable = false
      }
    }
    malware_protection {
      scan_ec2_instance_with_findings {
        ebs_volumes {
          enable = false
        }
      }
    }
  }
}

resource "aws_guardduty_organization_configuration" "comm_config" {
  count                            = var.govcloud ? 0 : 1
  auto_enable_organization_members = "ALL"
  detector_id                      = aws_guardduty_detector.comm_detector[0].id

  datasources {
    s3_logs {
      auto_enable = true
    }
    malware_protection {
      scan_ec2_instance_with_findings {
        ebs_volumes {
          auto_enable = true
        }
      }
    }
  }
}

resource "aws_guardduty_organization_configuration" "govcloud_config" {
  count                            = var.govcloud ? 1 : 0
  auto_enable_organization_members = "ALL"
  detector_id                      = aws_guardduty_detector.govcloud_detector[0].id

  datasources {
    s3_logs {
      auto_enable = true
    }
    malware_protection {
      scan_ec2_instance_with_findings {
        ebs_volumes {
          auto_enable = false
        }
      }
    }
  }
}

resource "aws_guardduty_member" "members" {
  detector_id = var.govcloud ? aws_guardduty_detector.govcloud_detector[0].id : aws_guardduty_detector.comm_detector[0].id
  account_id  = element(keys(var.accounts_emails), count.index)
  email       = element(values(var.accounts_emails), count.index)
  invite      = true
  count       = length(keys(var.accounts_emails))
}

Some more specific questions.

  1. I have configured GuardDuty the way I want it through the console. Running get-detector CLI command I’m given a list of datasources and a list of features. Running the describe-organization-configuration command I get different lists of datasources and features. I know this is not a Terraform question but maybe someone can help me understand the difference between the two?
aws guardduty get-detector --detector-id xxxxxxxxxxxxxxxx
{
    "CreatedAt": "2023-11-06T14:05:45.374Z",
    "FindingPublishingFrequency": "SIX_HOURS",
    "ServiceRole": "arn:aws-us-gov:iam::614497914326:role/aws-service-role/guardduty.amazonaws.com/AWSServiceRoleForAmazonGuardDuty",
    "Status": "ENABLED",
    "UpdatedAt": "2023-11-06T14:51:53.334Z",
    "DataSources": {
        "CloudTrail": {
            "Status": "ENABLED"
        },
        "DNSLogs": {
            "Status": "ENABLED"
        },
        "FlowLogs": {
            "Status": "ENABLED"
        },
        "S3Logs": {
            "Status": "ENABLED"
        },
        "Kubernetes": {
            "AuditLogs": {
                "Status": "ENABLED"
            }
        }
    },
    "Tags": {},
    "Features": [
        {
            "Name": "CLOUD_TRAIL",
            "Status": "ENABLED",
            "UpdatedAt": "2023-11-07T09:51:40+00:00"
        },
        {
            "Name": "DNS_LOGS",
            "Status": "ENABLED",
            "UpdatedAt": "2023-11-07T09:51:40+00:00"
        },
        {
            "Name": "FLOW_LOGS",
            "Status": "ENABLED",
            "UpdatedAt": "2023-11-07T09:51:40+00:00"
        },
        {
            "Name": "S3_DATA_EVENTS",
            "Status": "ENABLED",
            "UpdatedAt": "2023-11-06T14:50:05+00:00"
        },
        {
            "Name": "EKS_AUDIT_LOGS",
            "Status": "ENABLED",
            "UpdatedAt": "2023-11-06T14:50:47+00:00"
        },
        {
            "Name": "LAMBDA_NETWORK_LOGS",
            "Status": "ENABLED",
            "UpdatedAt": "2023-11-06T14:51:53+00:00"
        }
    ]
}

aws guardduty describe-organization-configuration --detector-id xxxxxxxxxxxxxxxx
{
    "AutoEnable": true,
    "MemberAccountLimitReached": false,
    "DataSources": {
        "S3Logs": {
            "AutoEnable": true
        },
        "Kubernetes": {
            "AuditLogs": {
                "AutoEnable": true
            }
        }
    },
    "Features": [
        {
            "Name": "S3_DATA_EVENTS",
            "AutoEnable": "ALL"
        },
        {
            "Name": "LAMBDA_NETWORK_LOGS",
            "AutoEnable": "ALL"
        },
        {
            "Name": "EKS_AUDIT_LOGS",
            "AutoEnable": "ALL"
        }
    ],
    "AutoEnableOrganizationMembers": "ALL"
}
  1. The datasources can be set in both of the Terraform resources aws_guardduty_detector and aws_guardduty_organization_configuration. The example in the docs for aws_guardduty_organization_configuration show a detector but without datasources. When would datasources need to be specified in the detector?

  2. The datasources and features output above differ from what the Terraform docs say is available in the aws_guardduty_detector resource (i.e. CLOUD_TRAIL, DNS_LOGS). This this an omission in the docs or are these datasources/features not available through Terraform?

  3. When applying an aws_guardduty_detector or aws_guardduty_organization_configuration, if malware_protection is left out, Terraform appears to try to enable it due to the default settings enable = true (detector) and auto_enable = true (detector config). This is not available in GovCloud. If both are set to false I get the BadRequestException error in my last comment. Is Terraform trying to configure a feature that the AWS API does not recognise, i.e. malware_protection in GovCloud?

More testing.

  1. Ran a destroy in two GovCloud regions to start from the start.
  2. Set up GuardDuty through the console for one region.
  3. Imported detector and configuration resources into the state.
  4. Ran targeted apply on detector and configuration resources. Plans showed no changes. This validates the Terraform code as being in line with what I need deployed on AWS platform.
  5. Ran targeted apply on detector and configuration resources in second region without first setting it up in the console and importing. Detector created successfully, configuration throws BadRequestException error.

My conclusion from this is that Terraform cannot be used to create a GuardDuty detector configuration in the GovCloud partition. If the config is created through the console and imported, the apply sees the resource in the state and makes and doesn’t attempt to create it. Terraform, when creating it, send values (default or otherwise) for attributes relating to malware protection. These are not recognised in GovCloud and the result is the API request generates an error.

Sooo. Whatcha think?