From de888d3cb37640ed3ab6974908859593ecf8974d Mon Sep 17 00:00:00 2001 From: Robert Fairburn <8029478+rfairburn@users.noreply.github.com> Date: Wed, 22 Feb 2023 10:07:12 -0600 Subject: [PATCH] Initial Terraform ALB Loggin Module (#10010) --- terraform/addons/logging-alb/.header.md | 46 +++++ .../addons/logging-alb/.terraform-docs.yml | 1 + terraform/addons/logging-alb/README.md | 91 ++++++++++ terraform/addons/logging-alb/main.tf | 162 ++++++++++++++++++ terraform/addons/logging-alb/outputs.tf | 3 + terraform/addons/logging-alb/variables.tf | 30 ++++ terraform/byo-vpc/byo-db/main.tf | 1 + 7 files changed, 334 insertions(+) create mode 100644 terraform/addons/logging-alb/.header.md create mode 100644 terraform/addons/logging-alb/.terraform-docs.yml create mode 100644 terraform/addons/logging-alb/README.md create mode 100644 terraform/addons/logging-alb/main.tf create mode 100644 terraform/addons/logging-alb/outputs.tf create mode 100644 terraform/addons/logging-alb/variables.tf diff --git a/terraform/addons/logging-alb/.header.md b/terraform/addons/logging-alb/.header.md new file mode 100644 index 0000000000..31d566b0ba --- /dev/null +++ b/terraform/addons/logging-alb/.header.md @@ -0,0 +1,46 @@ +# ALB Logging Addon +This addon creates alb logging bucket(s) in s3 and optionally an athena database for those logs. + +# Example Configuration + +This assumes your fleet module is `main` and is configured with it's default documentation. + +See https://github.com/fleetdm/fleet/blob/main/terraform/example/main.tf for details. + +``` +module "main" { + source = "github.com/fleetdm/fleet//terraform?ref=main" + certificate_arn = module.acm.acm_certificate_arn + vpc = { + name = random_pet.main.id + } + fleet_config = { + extra_environment_variables = module.firehose-logging.fleet_extra_environment_variables + extra_iam_policies = module.firehose-logging.fleet_extra_iam_policies + } + alb_config = { + access_logs = { + bucket = module.logging_alb.log_s3_bucket_id + prefix = "fleet" + enabled = true + } + } +} + +module "logging_alb" { + source = "github.com/fleetdm/fleet//terraform/addons/logging-alb?ref=main" + prefix = "fleet" + enable_athena = true +} +``` + +# Additional Information + +Once this terraform is applied, the Athena table will need to be created. See https://docs.aws.amazon.com/athena/latest/ug/application-load-balancer-logs.html for help with creating the table. + +For this implementation, the S3 pattern for the `CREATE TABLE` query should look like this: + +``` +s3://your-alb-logs-bucket//AWSLogs//elasticloadbalancing// +``` + diff --git a/terraform/addons/logging-alb/.terraform-docs.yml b/terraform/addons/logging-alb/.terraform-docs.yml new file mode 100644 index 0000000000..1d139ddb40 --- /dev/null +++ b/terraform/addons/logging-alb/.terraform-docs.yml @@ -0,0 +1 @@ +header-from: .header.md diff --git a/terraform/addons/logging-alb/README.md b/terraform/addons/logging-alb/README.md new file mode 100644 index 0000000000..20cc1a2693 --- /dev/null +++ b/terraform/addons/logging-alb/README.md @@ -0,0 +1,91 @@ +# ALB Logging Addon +This addon creates alb logging bucket(s) in s3 and optionally an athena database for those logs. + +# Example Configuration + +This assumes your fleet module is `main` and is configured with it's default documentation. + +See https://github.com/fleetdm/fleet/blob/main/terraform/example/main.tf for details. + +``` +module "main" { + source = "github.com/fleetdm/fleet//terraform?ref=main" + certificate_arn = module.acm.acm_certificate_arn + vpc = { + name = random_pet.main.id + } + fleet_config = { + extra_environment_variables = module.firehose-logging.fleet_extra_environment_variables + extra_iam_policies = module.firehose-logging.fleet_extra_iam_policies + } + alb_config = { + access_logs = { + bucket = module.logging_alb.log_s3_bucket_id + prefix = "fleet" + enabled = true + } + } +} + +module "logging_alb" { + source = "github.com/fleetdm/fleet//terraform/addons/logging-alb?ref=main" + prefix = "fleet" + enable_athena = true +} +``` + +# Additional Information + +Once this terraform is applied, the Athena table will need to be created. See https://docs.aws.amazon.com/athena/latest/ug/application-load-balancer-logs.html for help with creating the table. + +For this implementation, the S3 pattern for the `CREATE TABLE` query should look like this: + +``` +s3://your-alb-logs-bucket//AWSLogs//elasticloadbalancing// +``` + +## Requirements + +No requirements. + +## Providers + +| Name | Version | +|------|---------| +| [aws](#provider\_aws) | n/a | + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [athena-s3-bucket](#module\_athena-s3-bucket) | terraform-aws-modules/s3-bucket/aws | 3.6.0 | +| [s3\_bucket\_for\_logs](#module\_s3\_bucket\_for\_logs) | terraform-aws-modules/s3-bucket/aws | 3.6.0 | + +## Resources + +| Name | Type | +|------|------| +| [aws_athena_database.logs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/athena_database) | resource | +| [aws_athena_workgroup.logs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/athena_workgroup) | resource | +| [aws_kms_alias.logs_alias](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_alias) | resource | +| [aws_kms_key.logs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_key) | resource | +| [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | +| [aws_iam_policy_document.kms](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_region.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [enable\_athena](#input\_enable\_athena) | n/a | `bool` | `true` | no | +| [prefix](#input\_prefix) | n/a | `string` | `"fleet"` | no | +| [s3\_expiration\_days](#input\_s3\_expiration\_days) | n/a | `number` | `90` | no | +| [s3\_newer\_noncurrent\_versions](#input\_s3\_newer\_noncurrent\_versions) | n/a | `number` | `5` | no | +| [s3\_noncurrent\_version\_expiration\_days](#input\_s3\_noncurrent\_version\_expiration\_days) | n/a | `number` | `30` | no | +| [s3\_transition\_days](#input\_s3\_transition\_days) | n/a | `number` | `30` | no | + +## Outputs + +| Name | Description | +|------|-------------| +| [log\_s3\_bucket\_id](#output\_log\_s3\_bucket\_id) | n/a | diff --git a/terraform/addons/logging-alb/main.tf b/terraform/addons/logging-alb/main.tf new file mode 100644 index 0000000000..4758278871 --- /dev/null +++ b/terraform/addons/logging-alb/main.tf @@ -0,0 +1,162 @@ +data "aws_caller_identity" "current" {} + +data "aws_region" "current" {} + +data "aws_iam_policy_document" "kms" { + statement { + actions = ["kms:*"] + principals { + type = "AWS" + identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"] + } + resources = ["*"] + } + statement { + actions = [ + "kms:Encrypt*", + "kms:Decrypt*", + "kms:ReEncrypt*", + "kms:GenerateDataKey*", + "kms:Describe*", + ] + resources = ["*"] + principals { + type = "Service" + identifiers = ["logs.${data.aws_region.current.name}.amazonaws.com"] + } + } +} + +resource "aws_kms_key" "logs" { + policy = data.aws_iam_policy_document.kms.json + enable_key_rotation = true +} + +resource "aws_kms_alias" "logs_alias" { + name_prefix = "alias/${var.prefix}-logs" + target_key_id = aws_kms_key.logs.id +} + +module "s3_bucket_for_logs" { + source = "terraform-aws-modules/s3-bucket/aws" + version = "3.6.0" + + bucket = "${var.prefix}-alb-logs" + acl = "log-delivery-write" + + # Allow deletion of non-empty bucket + force_destroy = true + + attach_elb_log_delivery_policy = true # Required for ALB logs + attach_lb_log_delivery_policy = true # Required for ALB/NLB logs + attach_deny_insecure_transport_policy = true + attach_require_latest_tls_policy = true + block_public_acls = true + block_public_policy = true + ignore_public_acls = true + restrict_public_buckets = true + server_side_encryption_configuration = { + rule = { + apply_server_side_encryption_by_default = { + kms_master_key_id = aws_kms_key.logs.arn + sse_algorithm = "aws:kms" + } + } + } + lifecycle_rule = [ + { + id = "log" + enabled = true + + transition = [ + { + days = var.s3_transition_days + storage_class = "ONEZONE_IA" + } + ] + expiration = { + days = var.s3_expiration_days + expired_object_delete_marker = true + } + noncurrent_version_expiration = { + newer_noncurrent_versions = var.s3_newer_noncurrent_versions + days = var.s3_noncurrent_version_expiration_days + } + } + ] +} + +resource "aws_athena_database" "logs" { + count = var.enable_athena == true ? 1 : 0 + name = replace("${var.prefix}-alb-logs", "-", "_") + bucket = module.athena-s3-bucket[0].s3_bucket_id +} + +module "athena-s3-bucket" { + count = var.enable_athena == true ? 1 : 0 + source = "terraform-aws-modules/s3-bucket/aws" + version = "3.6.0" + + bucket = "${var.prefix}-alb-logs-athena" + acl = "log-delivery-write" + + # Allow deletion of non-empty bucket + force_destroy = true + + attach_elb_log_delivery_policy = true # Required for ALB logs + attach_lb_log_delivery_policy = true # Required for ALB/NLB logs + attach_deny_insecure_transport_policy = true + attach_require_latest_tls_policy = true + block_public_acls = true + block_public_policy = true + ignore_public_acls = true + restrict_public_buckets = true + server_side_encryption_configuration = { + rule = { + apply_server_side_encryption_by_default = { + kms_master_key_id = aws_kms_key.logs.arn + sse_algorithm = "aws:kms" + } + } + } + lifecycle_rule = [ + { + id = "log" + enabled = true + + transition = [ + { + days = var.s3_transition_days + storage_class = "ONEZONE_IA" + } + ] + expiration = { + days = var.s3_expiration_days + expired_object_delete_marker = true + } + noncurrent_version_expiration = { + newer_noncurrent_versions = var.s3_newer_noncurrent_versions + days = var.s3_noncurrent_version_expiration_days + } + } + ] +} + +resource "aws_athena_workgroup" "logs" { + count = var.enable_athena == true ? 1 : 0 + name = "${var.prefix}-logs" + + configuration { + enforce_workgroup_configuration = true + publish_cloudwatch_metrics_enabled = true + + result_configuration { + output_location = "s3://${module.athena-s3-bucket[0].s3_bucket_id}/output/" + + encryption_configuration { + encryption_option = "SSE_KMS" + kms_key_arn = aws_kms_key.logs.arn + } + } + } +} diff --git a/terraform/addons/logging-alb/outputs.tf b/terraform/addons/logging-alb/outputs.tf new file mode 100644 index 0000000000..df11006e44 --- /dev/null +++ b/terraform/addons/logging-alb/outputs.tf @@ -0,0 +1,3 @@ +output "log_s3_bucket_id" { + value = module.s3_bucket_for_logs.s3_bucket_id +} diff --git a/terraform/addons/logging-alb/variables.tf b/terraform/addons/logging-alb/variables.tf new file mode 100644 index 0000000000..e68d8137fa --- /dev/null +++ b/terraform/addons/logging-alb/variables.tf @@ -0,0 +1,30 @@ +variable "prefix" { + type = string + default = "fleet" +} + +variable "enable_athena" { + type = bool + default = true +} + +variable "s3_transition_days" { + type = number + default = 30 +} + +variable "s3_expiration_days" { + type = number + default = 90 +} + +variable "s3_newer_noncurrent_versions" { + type = number + default = 5 +} + +variable "s3_noncurrent_version_expiration_days" { + type = number + default = 30 +} + diff --git a/terraform/byo-vpc/byo-db/main.tf b/terraform/byo-vpc/byo-db/main.tf index e31a6a2fe8..4c045dfed4 100644 --- a/terraform/byo-vpc/byo-db/main.tf +++ b/terraform/byo-vpc/byo-db/main.tf @@ -35,6 +35,7 @@ module "alb" { vpc_id = var.vpc_id subnets = var.alb_config.subnets security_groups = concat(var.alb_config.security_groups, [aws_security_group.alb.id]) + access_logs = var.alb_config.access_logs target_groups = [ {