diff --git a/infrastructure/guardduty/.terraform.lock.hcl b/infrastructure/guardduty/.terraform.lock.hcl new file mode 100644 index 000000000..4c5bfa545 --- /dev/null +++ b/infrastructure/guardduty/.terraform.lock.hcl @@ -0,0 +1,22 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/hashicorp/aws" { + version = "4.10.0" + constraints = "~> 4.10.0" + hashes = [ + "h1:S6xGPRL08YEuBdemiYZyIBf/YwM4OCvzVuaiuU6kLjc=", + "zh:0a2a7eabfeb7dbb17b7f82aff3fa2ba51e836c15e5be4f5468ea44bd1299b48d", + "zh:23409c7205d13d2d68b5528e1c49e0a0455d99bbfec61eb0201142beffaa81f7", + "zh:3adad2245d97816f3919778b52c58fb2de130938a3e9081358bfbb72ec478d9a", + "zh:5bf100aba6332f24b1ffeae7536d5d489bb907bf774a06b95f2183089eaf1a1a", + "zh:63c3a24c0c229a1d3390e6ea2454ba4d8ace9b94e086bee1dbdcf665ae969e15", + "zh:6b76f5ffd920f0a750da3a4ff1d00eab18d9cd3731b009aae3df4135613bad4d", + "zh:8cd6b1e6b51e8e9bbe2944bb169f113d20d1d72d07ccd1b7b83f40b3c958233e", + "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", + "zh:c5c31f58fb5bd6aebc6c662a4693640ec763cb3399cce0b592101cf24ece1625", + "zh:cc485410be43d6ad95d81b9e54cc4d2117aadf9bf5941165a9df26565d9cce42", + "zh:cebb89c74b6a3dc6780824b1d1e2a8d16a51e75679e14ad0b830d9f7da1a3a67", + "zh:e7dc427189cb491e1f96e295101964415cbf8630395ee51e396d2a811f365237", + ] +} diff --git a/infrastructure/guardduty/README.md b/infrastructure/guardduty/README.md new file mode 100644 index 000000000..7da167d57 --- /dev/null +++ b/infrastructure/guardduty/README.md @@ -0,0 +1,3 @@ +basing the architecture off of https://docs.aws.amazon.com/prescriptive-guidance/latest/patterns/use-terraform-to-automatically-enable-amazon-guardduty-for-an-organization.html but using workspaces instead of templates. + +Use apply.sh to automatically apply the terraform code in all regions. There is an apply.sh in both this folder and the members folder. The findings folder exists in only one region, so just do a normal apply there. diff --git a/infrastructure/guardduty/apply.sh b/infrastructure/guardduty/apply.sh new file mode 100755 index 000000000..a3ff1b8d9 --- /dev/null +++ b/infrastructure/guardduty/apply.sh @@ -0,0 +1,5 @@ +#!/bin/bash +for region in $(aws ec2 describe-regions | jq -r '.Regions[] | .RegionName'); do + terraform workspace select $region || break + terraform apply -auto-approve || break +done diff --git a/infrastructure/guardduty/findings/.terraform.lock.hcl b/infrastructure/guardduty/findings/.terraform.lock.hcl new file mode 100644 index 000000000..4c5bfa545 --- /dev/null +++ b/infrastructure/guardduty/findings/.terraform.lock.hcl @@ -0,0 +1,22 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/hashicorp/aws" { + version = "4.10.0" + constraints = "~> 4.10.0" + hashes = [ + "h1:S6xGPRL08YEuBdemiYZyIBf/YwM4OCvzVuaiuU6kLjc=", + "zh:0a2a7eabfeb7dbb17b7f82aff3fa2ba51e836c15e5be4f5468ea44bd1299b48d", + "zh:23409c7205d13d2d68b5528e1c49e0a0455d99bbfec61eb0201142beffaa81f7", + "zh:3adad2245d97816f3919778b52c58fb2de130938a3e9081358bfbb72ec478d9a", + "zh:5bf100aba6332f24b1ffeae7536d5d489bb907bf774a06b95f2183089eaf1a1a", + "zh:63c3a24c0c229a1d3390e6ea2454ba4d8ace9b94e086bee1dbdcf665ae969e15", + "zh:6b76f5ffd920f0a750da3a4ff1d00eab18d9cd3731b009aae3df4135613bad4d", + "zh:8cd6b1e6b51e8e9bbe2944bb169f113d20d1d72d07ccd1b7b83f40b3c958233e", + "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", + "zh:c5c31f58fb5bd6aebc6c662a4693640ec763cb3399cce0b592101cf24ece1625", + "zh:cc485410be43d6ad95d81b9e54cc4d2117aadf9bf5941165a9df26565d9cce42", + "zh:cebb89c74b6a3dc6780824b1d1e2a8d16a51e75679e14ad0b830d9f7da1a3a67", + "zh:e7dc427189cb491e1f96e295101964415cbf8630395ee51e396d2a811f365237", + ] +} diff --git a/infrastructure/guardduty/findings/main.tf b/infrastructure/guardduty/findings/main.tf new file mode 100644 index 000000000..457f90f59 --- /dev/null +++ b/infrastructure/guardduty/findings/main.tf @@ -0,0 +1,158 @@ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 4.10.0" + } + } + backend "s3" { + bucket = "fleet-terraform-state20220408141538466600000002" + key = "root/guardduty/findings/terraform.tfstate" # This should be set to account_alias/unique_key/terraform.tfstate + workspace_key_prefix = "root" # This should be set to the account alias + region = "us-east-2" + encrypt = true + kms_key_id = "9f98a443-ffd7-4dbe-a9c3-37df89b2e42a" + dynamodb_table = "tf-remote-state-lock" + role_arn = "arn:aws:iam::353365949058:role/terraform-root" + } +} + +provider "aws" { + region = "us-east-2" + assume_role { + role_arn = "arn:aws:iam::353365949058:role/admin" + } + default_tags { + tags = { + environment = "guardduty-${terraform.workspace}" + terraform = "https://github.com/fleetdm/fleet/tree/main/infrastructure/guardduty/findings" + state = "s3://fleet-terraform-state20220408141538466600000002/root/guardduty/findings/terraform.tfstate" + } + } +} + +data "aws_caller_identity" "current" {} + +data "aws_region" "current" {} + +data "aws_iam_policy_document" "bucket_pol" { + statement { + sid = "Allow PutObject" + actions = [ + "s3:PutObject" + ] + + resources = [ + "${aws_s3_bucket.gd_bucket.arn}/*" + ] + + principals { + type = "Service" + identifiers = ["guardduty.amazonaws.com"] + } + } + + statement { + sid = "Allow GetBucketLocation" + actions = [ + "s3:GetBucketLocation" + ] + + resources = [ + aws_s3_bucket.gd_bucket.arn + ] + + principals { + type = "Service" + identifiers = ["guardduty.amazonaws.com"] + } + } +} + +data "aws_iam_policy_document" "kms_pol" { + + statement { + sid = "Allow GuardDuty to encrypt findings" + actions = [ + "kms:GenerateDataKey" + ] + + resources = [ + "arn:aws:kms:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:key/*" + ] + + principals { + type = "Service" + identifiers = ["guardduty.amazonaws.com"] + } + } + + statement { + sid = "Allow all users to modify/delete key (test only)" + actions = [ + "kms:*" + ] + + resources = [ + "arn:aws:kms:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:key/*" + ] + + principals { + type = "AWS" + identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"] + } + } + +} + +resource "aws_s3_bucket" "gd_bucket" { + bucket = "fleet-guardduty-findings" + force_destroy = true +} + +resource "aws_s3_bucket_acl" "gd_bucket_acl" { + bucket = aws_s3_bucket.gd_bucket.id + acl = "private" +} + +resource "aws_s3_bucket_policy" "gd_bucket_policy" { + bucket = aws_s3_bucket.gd_bucket.id + policy = data.aws_iam_policy_document.bucket_pol.json +} + +resource "aws_kms_key" "gd_key" { + description = "Temporary key for AccTest of TF" + deletion_window_in_days = 7 + policy = data.aws_iam_policy_document.kms_pol.json +} + +output "kms_key" { + value = aws_kms_key.gd_key +} + +resource "aws_s3_bucket_public_access_block" "access_good_1" { + bucket = aws_s3_bucket.gd_bucket.id + + block_public_acls = true + block_public_policy = true + ignore_public_acls = true + restrict_public_buckets = true +} + +resource "aws_s3_bucket_server_side_encryption_configuration" "main" { + bucket = aws_s3_bucket.gd_bucket.bucket + + rule { + apply_server_side_encryption_by_default { + kms_master_key_id = aws_kms_key.gd_key.arn + sse_algorithm = "aws:kms" + } + } +} + +resource "aws_s3_bucket_versioning" "main" { + bucket = aws_s3_bucket.gd_bucket.id + versioning_configuration { + status = "Enabled" + } +} diff --git a/infrastructure/guardduty/main.tf b/infrastructure/guardduty/main.tf new file mode 100644 index 000000000..95e4589d9 --- /dev/null +++ b/infrastructure/guardduty/main.tf @@ -0,0 +1,173 @@ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 4.10.0" + } + } + backend "s3" { + bucket = "fleet-terraform-state20220408141538466600000002" + key = "root/guardduty/terraform.tfstate" # This should be set to account_alias/unique_key/terraform.tfstate + workspace_key_prefix = "root" # This should be set to the account alias + region = "us-east-2" + encrypt = true + kms_key_id = "9f98a443-ffd7-4dbe-a9c3-37df89b2e42a" + dynamodb_table = "tf-remote-state-lock" + role_arn = "arn:aws:iam::353365949058:role/terraform-root" + } +} + +data "terraform_remote_state" "findings" { + backend = "s3" + config = { + bucket = "fleet-terraform-state20220408141538466600000002" + key = "root/guardduty/findings/terraform.tfstate" # This should be set to account_alias/unique_key/terraform.tfstate + workspace_key_prefix = "root" # This should be set to the account alias + region = "us-east-2" + encrypt = true + kms_key_id = "9f98a443-ffd7-4dbe-a9c3-37df89b2e42a" + dynamodb_table = "tf-remote-state-lock" + role_arn = "arn:aws:iam::353365949058:role/terraform-root" + } +} + +provider "aws" { + region = terraform.workspace + default_tags { + tags = { + environment = "guardduty-${terraform.workspace}" + terraform = "https://github.com/fleetdm/fleet/tree/main/infrastructure/guardduty" + state = "s3://fleet-terraform-state20220408141538466600000002/root/guardduty/terraform.tfstate" + } + } +} + +provider "aws" { + region = "us-east-2" + alias = "security" + assume_role { + role_arn = "arn:aws:iam::353365949058:role/admin" + } + default_tags { + tags = { + environment = "guardduty-${terraform.workspace}" + terraform = "https://github.com/fleetdm/fleet/tree/main/infrastructure/guardduty" + state = "s3://fleet-terraform-state20220408141538466600000002/root/guardduty/terraform.tfstate" + } + } +} + +provider "aws" { + region = terraform.workspace + alias = "security-region" + assume_role { + role_arn = "arn:aws:iam::353365949058:role/admin" + } + default_tags { + tags = { + environment = "guardduty-${terraform.workspace}" + terraform = "https://github.com/fleetdm/fleet/tree/main/infrastructure/guardduty" + state = "s3://fleet-terraform-state20220408141538466600000002/root/guardduty/terraform.tfstate" + } + } +} + +resource "aws_guardduty_organization_admin_account" "main" { + admin_account_id = "353365949058" +} + +data "aws_guardduty_detector" "main" { + provider = aws.security-region +} + +data "aws_s3_bucket" "findings" { + provider = aws.security + bucket = "fleet-guardduty-findings" +} + +resource "aws_guardduty_publishing_destination" "main" { + provider = aws.security-region + detector_id = data.aws_guardduty_detector.main.id + destination_arn = data.aws_s3_bucket.findings.arn + kms_key_arn = data.terraform_remote_state.findings.outputs.kms_key.arn +} + +resource "aws_guardduty_detector" "root" {} + +data "aws_organizations_organization" "main" {} + +resource "aws_guardduty_member" "root" { + provider = aws.security-region + account_id = aws_guardduty_detector.root.account_id + detector_id = data.aws_guardduty_detector.main.id + email = data.aws_organizations_organization.main.master_account_email + disable_email_notification = true + invite = true +} + +resource "aws_guardduty_organization_configuration" "main" { + provider = aws.security-region + auto_enable = true + detector_id = data.aws_guardduty_detector.main.id +} + +resource "aws_cloudwatch_event_rule" "console" { + name = "guardduty-${terraform.workspace}" + + event_pattern = < i.email } +} + +data "aws_organizations_organization" "main" { + provider = aws.root +} + +resource "aws_guardduty_member" "member" { + provider = aws.security + account_id = aws_guardduty_detector.member.account_id + detector_id = data.aws_guardduty_detector.security.id + email = local.accounts[local.account_id] + disable_email_notification = true + invite = true + lifecycle { + ignore_changes = [email] + } +} + +resource "aws_guardduty_detector" "member" { + provider = aws.member +} + +data "aws_guardduty_detector" "security" { + provider = aws.security +} + +data "aws_caller_identity" "security" {}