From 978a9413ee30cf012ad283af83e423e3dc4fdd14 Mon Sep 17 00:00:00 2001 From: Benjamin Edwards Date: Fri, 24 May 2024 15:24:15 -0400 Subject: [PATCH] kinesis logging destination module (#19269) Create a Kinesis Logging Terraform Module similar to the existing Firehose Logging Terraform Module. - [X] Manual QA for all new/changed functionality relates to https://github.com/fleetdm/confidential/issues/6548 --- .../.header.md | 6 + .../kinesis/.header.md | 28 ++++ .../kinesis/.terraform-docs.yml | 1 + .../kinesis/README.md | 70 ++++++++++ .../kinesis/iam.tf | 11 ++ .../kinesis/outputs.tf | 20 +++ .../kinesis/variables.tf | 30 +++++ .../kinesis/version.tf | 10 ++ .../target-account/.header.md | 83 ++++++++++++ .../target-account/.terraform-docs.yml | 1 + .../target-account/.terraform.lock.hcl | 25 ++++ .../target-account/README.md | 127 ++++++++++++++++++ .../target-account/iam.tf | 57 ++++++++ .../target-account/kinesis.tf | 15 +++ .../target-account/outputs.tf | 13 ++ .../target-account/variables.tf | 44 ++++++ .../target-account/version.tf | 10 ++ 17 files changed, 551 insertions(+) create mode 100644 terraform/addons/byo-kinesis-logging-destination/.header.md create mode 100644 terraform/addons/byo-kinesis-logging-destination/kinesis/.header.md create mode 100644 terraform/addons/byo-kinesis-logging-destination/kinesis/.terraform-docs.yml create mode 100644 terraform/addons/byo-kinesis-logging-destination/kinesis/README.md create mode 100644 terraform/addons/byo-kinesis-logging-destination/kinesis/iam.tf create mode 100644 terraform/addons/byo-kinesis-logging-destination/kinesis/outputs.tf create mode 100644 terraform/addons/byo-kinesis-logging-destination/kinesis/variables.tf create mode 100644 terraform/addons/byo-kinesis-logging-destination/kinesis/version.tf create mode 100644 terraform/addons/byo-kinesis-logging-destination/target-account/.header.md create mode 100644 terraform/addons/byo-kinesis-logging-destination/target-account/.terraform-docs.yml create mode 100644 terraform/addons/byo-kinesis-logging-destination/target-account/.terraform.lock.hcl create mode 100644 terraform/addons/byo-kinesis-logging-destination/target-account/README.md create mode 100644 terraform/addons/byo-kinesis-logging-destination/target-account/iam.tf create mode 100644 terraform/addons/byo-kinesis-logging-destination/target-account/kinesis.tf create mode 100644 terraform/addons/byo-kinesis-logging-destination/target-account/outputs.tf create mode 100644 terraform/addons/byo-kinesis-logging-destination/target-account/variables.tf create mode 100644 terraform/addons/byo-kinesis-logging-destination/target-account/version.tf diff --git a/terraform/addons/byo-kinesis-logging-destination/.header.md b/terraform/addons/byo-kinesis-logging-destination/.header.md new file mode 100644 index 0000000000..e29d62d1cf --- /dev/null +++ b/terraform/addons/byo-kinesis-logging-destination/.header.md @@ -0,0 +1,6 @@ +# Logging Destination: Kinesis +This addon provides a Kinesis Data Stream logging destination for Fleet. + +First apply the `target-account` module which will provision the necessary data streams, KMS key, and policies. + +Then apply the `kinesis` module with the required variables. diff --git a/terraform/addons/byo-kinesis-logging-destination/kinesis/.header.md b/terraform/addons/byo-kinesis-logging-destination/kinesis/.header.md new file mode 100644 index 0000000000..441c86e5ed --- /dev/null +++ b/terraform/addons/byo-kinesis-logging-destination/kinesis/.header.md @@ -0,0 +1,28 @@ +# Kinesis Data Stream Logging Destination Setup + +## Usage + +After `./target-account` module is applied you might use this module in the following manner: + +```hcl +module "kinesis" { + source = "../../../../fleet/terraform/addons/byo-kinesis-logging-destination/kinesis" + kinesis_results_name = "testing-log-stream" + kinesis_status_name = "testing-log-stream" + kinesis_audit_name = "testing-log-stream" + iam_role_arn = "arn:aws:iam::123456789:role/terraform-20240524165353382600000001" + region = "us-east-2" +} +``` + +And then supply the outputs to the `fleet_config` definition: +```hcl +fleet_config = { + image = local.fleet_image + extra_iam_policies = concat(module.kinesis.fleet_extra_iam_policies) + extra_environment_variables = merge( + local.extra_environment_variables, + module.kinesis.fleet_extra_environment_variables, + ) + } +``` diff --git a/terraform/addons/byo-kinesis-logging-destination/kinesis/.terraform-docs.yml b/terraform/addons/byo-kinesis-logging-destination/kinesis/.terraform-docs.yml new file mode 100644 index 0000000000..1d139ddb40 --- /dev/null +++ b/terraform/addons/byo-kinesis-logging-destination/kinesis/.terraform-docs.yml @@ -0,0 +1 @@ +header-from: .header.md diff --git a/terraform/addons/byo-kinesis-logging-destination/kinesis/README.md b/terraform/addons/byo-kinesis-logging-destination/kinesis/README.md new file mode 100644 index 0000000000..2eedf9bc92 --- /dev/null +++ b/terraform/addons/byo-kinesis-logging-destination/kinesis/README.md @@ -0,0 +1,70 @@ +# Kinesis Data Stream Logging Destination Setup + +## Usage + +After `./target-account` module is applied you might use this module in the following manner: + +```hcl +module "kinesis" { + source = "../../../../fleet/terraform/addons/byo-kinesis-logging-destination/kinesis" + kinesis_results_name = "testing-log-stream" + kinesis_status_name = "testing-log-stream" + kinesis_audit_name = "testing-log-stream" + iam_role_arn = "arn:aws:iam::123456789:role/terraform-20240524165353382600000001" + region = "us-east-2" +} +``` + +And then supply the outputs to the `fleet_config` definition: +```hcl +fleet_config = { + image = local.fleet_image + extra_iam_policies = concat(module.kinesis.fleet_extra_iam_policies) + extra_environment_variables = merge( + local.extra_environment_variables, + module.kinesis.fleet_extra_environment_variables, + ) + } +``` + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.3.7 | +| [aws](#requirement\_aws) | >= 4.52.0 | + +## Providers + +| Name | Version | +|------|---------| +| [aws](#provider\_aws) | >= 4.52.0 | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [aws_iam_policy.fleet-assume-role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | +| [aws_iam_policy_document.fleet-assume-role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [iam\_role\_arn](#input\_iam\_role\_arn) | IAM Role ARN to use for Kinesis destination logging | `string` | n/a | yes | +| [kinesis\_audit\_name](#input\_kinesis\_audit\_name) | name of the kinesis data stream for fleet audit logs | `string` | n/a | yes | +| [kinesis\_results\_name](#input\_kinesis\_results\_name) | name of the kinesis data stream for osquery results logs | `string` | n/a | yes | +| [kinesis\_status\_name](#input\_kinesis\_status\_name) | name of the kinesis data stream for osquery status logs | `string` | n/a | yes | +| [region](#input\_region) | region the target kinesis data stream(s) is in | `string` | n/a | yes | +| [sts\_external\_id](#input\_sts\_external\_id) | Optional unique identifier that can be used by the principal assuming the role to assert its identity. | `string` | `""` | no | + +## Outputs + +| Name | Description | +|------|-------------| +| [fleet\_extra\_environment\_variables](#output\_fleet\_extra\_environment\_variables) | n/a | +| [fleet\_extra\_iam\_policies](#output\_fleet\_extra\_iam\_policies) | n/a | diff --git a/terraform/addons/byo-kinesis-logging-destination/kinesis/iam.tf b/terraform/addons/byo-kinesis-logging-destination/kinesis/iam.tf new file mode 100644 index 0000000000..d394ab86ae --- /dev/null +++ b/terraform/addons/byo-kinesis-logging-destination/kinesis/iam.tf @@ -0,0 +1,11 @@ +data "aws_iam_policy_document" "fleet-assume-role" { + statement { + effect = "Allow" + actions = ["sts:AssumeRole"] + resources = [var.iam_role_arn] + } +} + +resource "aws_iam_policy" "fleet-assume-role" { + policy = data.aws_iam_policy_document.fleet-assume-role.json +} \ No newline at end of file diff --git a/terraform/addons/byo-kinesis-logging-destination/kinesis/outputs.tf b/terraform/addons/byo-kinesis-logging-destination/kinesis/outputs.tf new file mode 100644 index 0000000000..9aa68fbc84 --- /dev/null +++ b/terraform/addons/byo-kinesis-logging-destination/kinesis/outputs.tf @@ -0,0 +1,20 @@ +output "fleet_extra_environment_variables" { + value = { + FLEET_KINESIS_STATUS_STREAM = var.kinesis_status_name + FLEET_KINESIS_RESULT_STREAM = var.kinesis_results_name + FLEET_KINESIS_AUDIT_STREAM = var.kinesis_audit_name + FLEET_KINESIS_STS_ASSUME_ROLE_ARN = var.iam_role_arn + FLEET_KINESIS_STS_EXTERNAL_ID = var.sts_external_id + FLEET_KINESIS_REGION = var.region + FLEET_OSQUERY_STATUS_LOG_PLUGIN = "kinesis" + FLEET_OSQUERY_RESULT_LOG_PLUGIN = "kinesis" + FLEET_ACTIVITY_ENABLE_AUDIT_LOG = length(var.kinesis_audit_name) > 0 ? "true" : "false" + FLEET_ACTIVITY_AUDIT_LOG_PLUGIN = "kinesis" # only has an effect if ^ is true + } +} + +output "fleet_extra_iam_policies" { + value = [ + aws_iam_policy.fleet-assume-role.arn + ] +} diff --git a/terraform/addons/byo-kinesis-logging-destination/kinesis/variables.tf b/terraform/addons/byo-kinesis-logging-destination/kinesis/variables.tf new file mode 100644 index 0000000000..c1c1df3051 --- /dev/null +++ b/terraform/addons/byo-kinesis-logging-destination/kinesis/variables.tf @@ -0,0 +1,30 @@ +variable "iam_role_arn" { + type = string + description = "IAM Role ARN to use for Kinesis destination logging" +} + +variable "kinesis_results_name" { + type = string + description = "name of the kinesis data stream for osquery results logs" +} + +variable "kinesis_status_name" { + type = string + description = "name of the kinesis data stream for osquery status logs" +} + +variable "kinesis_audit_name" { + type = string + description = "name of the kinesis data stream for fleet audit logs" +} + +variable "region" { + type = string + description = "region the target kinesis data stream(s) is in" +} + +variable "sts_external_id" { + type = string + description = "Optional unique identifier that can be used by the principal assuming the role to assert its identity." + default = "" +} diff --git a/terraform/addons/byo-kinesis-logging-destination/kinesis/version.tf b/terraform/addons/byo-kinesis-logging-destination/kinesis/version.tf new file mode 100644 index 0000000000..529d9d07ac --- /dev/null +++ b/terraform/addons/byo-kinesis-logging-destination/kinesis/version.tf @@ -0,0 +1,10 @@ +terraform { + required_version = ">= 1.3.7" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.29.0" + } + } +} \ No newline at end of file diff --git a/terraform/addons/byo-kinesis-logging-destination/target-account/.header.md b/terraform/addons/byo-kinesis-logging-destination/target-account/.header.md new file mode 100644 index 0000000000..478b757f09 --- /dev/null +++ b/terraform/addons/byo-kinesis-logging-destination/target-account/.header.md @@ -0,0 +1,83 @@ +# Kinesis Data Stream Logging Destination Setup + +## How to use + +Below is an example of defining the module to use a single Kinesis Data Stream for all log types (results, status, and audit): +```hcl +module "kinesis" { + source = "github.com/fleetdm/fleet//terraform/addons/byo-kinesis-logging-destination/target-account" + + fleet_iam_role_arn = "arn:aws:iam::123456789:role/fleet-server-role" # this is the ARN of the IAM (ECS-task) role the fleet servers are running as + log_destinations = { + test = { + name = "unified-log-stream" + shard_count = 0 # shard count only matters if `stream_mode` is `PROVISIONED` + stream_mode = "ON_DEMAND" # valid values are `ON_DEMAND` or `PROVISIONED` + retention_period = 24 # number of hours you want the data to be retained on the stream + shard_level_metrics = [] # IncomingBytes IncomingRecords OutgoingBytes OutgoingRecords WriteProvisionedThroughputExceeded ReadProvisionedThroughputExceeded IteratorAgeMilliseconds + } + } +} + +output "kinesis_logging_destination" { + value = module.kinesis +} +``` + +If you desired a Kinesis Data Stream per "topic": +```hcl +module "kinesis" { + source = "github.com/fleetdm/fleet//terraform/addons/byo-kinesis-logging-destination/target-account" + + fleet_iam_role_arn = "arn:aws:iam::123456789:role/fleet-server-role" # this is the ARN of the IAM (ECS-task) role the fleet servers are running as + log_destinations = { + results = { + name = "osquery-results" + shard_count = 0 # shard count only matters if `stream_mode` is `PROVISIONED` + stream_mode = "ON_DEMAND" # valid values are `ON_DEMAND` or `PROVISIONED` + retention_period = 24 # number of hours you want the data to be retained on the stream + shard_level_metrics = [] # IncomingBytes IncomingRecords OutgoingBytes OutgoingRecords WriteProvisionedThroughputExceeded ReadProvisionedThroughputExceeded IteratorAgeMilliseconds + } + status = { + name = "osquery-status" + shard_count = 0 # shard count only matters if `stream_mode` is `PROVISIONED` + stream_mode = "ON_DEMAND" # valid values are `ON_DEMAND` or `PROVISIONED` + retention_period = 24 # number of hours you want the data to be retained on the stream + shard_level_metrics = [] # IncomingBytes IncomingRecords OutgoingBytes OutgoingRecords WriteProvisionedThroughputExceeded ReadProvisionedThroughputExceeded IteratorAgeMilliseconds + } + audit = { + name = "fleet-audit" + shard_count = 0 # shard count only matters if `stream_mode` is `PROVISIONED` + stream_mode = "ON_DEMAND" # valid values are `ON_DEMAND` or `PROVISIONED` + retention_period = 24 # number of hours you want the data to be retained on the stream + shard_level_metrics = [] # IncomingBytes IncomingRecords OutgoingBytes OutgoingRecords WriteProvisionedThroughputExceeded ReadProvisionedThroughputExceeded IteratorAgeMilliseconds + } + } +} + +output "kinesis_logging_destination" { + value = module.kinesis +} +``` + +1. **Variables:** + - `fleet_iam_role_arn`: A string variable that holds the ARN of the IAM role which will assume the role defined in this module to gain permissions for writing to the Kinesis Data Streams. + - `sts_external_id`: An optional string variable that can be used as a unique identifier for the principal assuming the role to assert its identity. Default is an empty string. + - `log_destinations`: A map variable that contains configurations for multiple Kinesis Data Streams. Each stream configuration includes its name, shard count, stream mode, retention period, and shard-level metrics. Default values are provided for three streams: `osquery_results`, `osquery_status`, and `fleet_audit`. + +2. **IAM Role:** + - `aws_iam_role.fleet_role`: Creates an IAM role with a trust policy that allows the specified IAM role ARN (`fleet_iam_role_arn`) to assume this role. If `sts_external_id` is provided, it adds a condition to the trust policy to require this external ID for the assume role operation. + +3. **IAM Policy Documents:** + - `data.aws_iam_policy_document.assume_role`: Defines the assume role policy for the IAM role. It allows the specified actions (`sts:AssumeRole`) for the specified principals. + - `data.aws_iam_policy_document.kinesis`: Defines the policy document allowing the IAM role to perform Kinesis and KMS actions. It allows the IAM role to describe, put records into the Kinesis streams (defined in `log_destinations`), and use KMS keys for encryption. + +4. **IAM Policy and Attachment:** + - `aws_iam_policy.fleet_kinesis`: Creates an IAM policy using the defined policy document (`data.aws_iam_policy_document.kinesis`). + - `aws_iam_role_policy_attachment.fleet_kinesis`: Attaches the created IAM policy to the IAM role (`aws_iam_role.fleet_role`). + +5. **KMS Key:** + - `aws_kms_key.kinesis_key`: Creates a KMS key for encrypting the Kinesis Data Streams. + +6. **Kinesis Data Streams:** + - `aws_kinesis_stream.fleet_log_destination`: Provisions Kinesis Data Streams based on the configurations defined in `log_destinations`. Each stream is created with the specified name, encryption type (using the KMS key), shard-level metrics, shard count (if the stream mode is not "ON_DEMAND"), and stream mode. diff --git a/terraform/addons/byo-kinesis-logging-destination/target-account/.terraform-docs.yml b/terraform/addons/byo-kinesis-logging-destination/target-account/.terraform-docs.yml new file mode 100644 index 0000000000..1d139ddb40 --- /dev/null +++ b/terraform/addons/byo-kinesis-logging-destination/target-account/.terraform-docs.yml @@ -0,0 +1 @@ +header-from: .header.md diff --git a/terraform/addons/byo-kinesis-logging-destination/target-account/.terraform.lock.hcl b/terraform/addons/byo-kinesis-logging-destination/target-account/.terraform.lock.hcl new file mode 100644 index 0000000000..d5b523dfe5 --- /dev/null +++ b/terraform/addons/byo-kinesis-logging-destination/target-account/.terraform.lock.hcl @@ -0,0 +1,25 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/hashicorp/aws" { + version = "5.51.0" + constraints = ">= 5.29.0" + hashes = [ + "h1:AUyje9jt9NYDbdFJwxLYtMEodb3PZptGsftpuB0xSgQ=", + "zh:049a4292dbf6afc2445d9fc796258ae33a989fd9a68b84f6e51c42c46dc2e45d", + "zh:0c1cd2d0e58727afe037d4ba0daeac0be3e0076d971ffa019cd4a03e1e8e7d50", + "zh:16ac968deddd08bd0e164532bfa961ef27785cb7beb57373637fb54eebbcef4f", + "zh:1740a6393e48a7ee357f53ac75025bb7eb56e21887cd28fbd996bb7c405fad85", + "zh:1e6667f3fca893cb3d333027f15e5965e45b29343a23b4d84ee787d2af732fc2", + "zh:543c8b780051623cb3a8558d9ed1f2ee51a801f839777a8f97e854e0b67e745e", + "zh:784d7e1791c75e10ff457ff75836bb3230b63c72f41cd63dc021381984661820", + "zh:857b37528e40a0ffe4f06ce9580bc4f88209bb9a0864f482c898ce8494b7347f", + "zh:94d15a0f4662a04c88cba1ba2710aed506331b47aaad36f36734fcba64d64294", + "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", + "zh:ba78a03cdc2bf56f48c19e2a37930f4bb8dfe818fc21f039fb785a22221d1fcf", + "zh:c9681a67ba51540905031063217fd8e48888c5ed3c9394d571d7d7ee333a5fbd", + "zh:d5d15bae5357854bd8df7490628ca949ef4c61481d3f4c3c535b0142261f93e4", + "zh:d96b28f58af08ab4d9057611e612634e96cafacaacf481dc08caf4dff06bbeee", + "zh:ed7652b4da81f2e7efe4821460aa77ba811e94afb4ef02afe067c1f166ee37d1", + ] +} diff --git a/terraform/addons/byo-kinesis-logging-destination/target-account/README.md b/terraform/addons/byo-kinesis-logging-destination/target-account/README.md new file mode 100644 index 0000000000..e54c0b4f4e --- /dev/null +++ b/terraform/addons/byo-kinesis-logging-destination/target-account/README.md @@ -0,0 +1,127 @@ +# Kinesis Data Stream Logging Destination Setup + +## How to use + +Below is an example of defining the module to use a single Kinesis Data Stream for all log types (results, status, and audit): +```hcl +module "kinesis" { + source = "github.com/fleetdm/fleet//terraform/addons/byo-kinesis-logging-destination/target-account" + + fleet_iam_role_arn = "arn:aws:iam::123456789:role/fleet-server-role" # this is the ARN of the IAM (ECS-task) role the fleet servers are running as + log_destinations = { + test = { + name = "unified-log-stream" + shard_count = 0 # shard count only matters if `stream_mode` is `PROVISIONED` + stream_mode = "ON_DEMAND" # valid values are `ON_DEMAND` or `PROVISIONED` + retention_period = 24 # number of hours you want the data to be retained on the stream + shard_level_metrics = [] # IncomingBytes IncomingRecords OutgoingBytes OutgoingRecords WriteProvisionedThroughputExceeded ReadProvisionedThroughputExceeded IteratorAgeMilliseconds + } + } +} + +output "kinesis_logging_destination" { + value = module.kinesis +} +``` + +If you desired a Kinesis Data Stream per "topic": +```hcl +module "kinesis" { + source = "github.com/fleetdm/fleet//terraform/addons/byo-kinesis-logging-destination/target-account" + + fleet_iam_role_arn = "arn:aws:iam::123456789:role/fleet-server-role" # this is the ARN of the IAM (ECS-task) role the fleet servers are running as + log_destinations = { + results = { + name = "osquery-results" + shard_count = 0 # shard count only matters if `stream_mode` is `PROVISIONED` + stream_mode = "ON_DEMAND" # valid values are `ON_DEMAND` or `PROVISIONED` + retention_period = 24 # number of hours you want the data to be retained on the stream + shard_level_metrics = [] # IncomingBytes IncomingRecords OutgoingBytes OutgoingRecords WriteProvisionedThroughputExceeded ReadProvisionedThroughputExceeded IteratorAgeMilliseconds + } + status = { + name = "osquery-status" + shard_count = 0 # shard count only matters if `stream_mode` is `PROVISIONED` + stream_mode = "ON_DEMAND" # valid values are `ON_DEMAND` or `PROVISIONED` + retention_period = 24 # number of hours you want the data to be retained on the stream + shard_level_metrics = [] # IncomingBytes IncomingRecords OutgoingBytes OutgoingRecords WriteProvisionedThroughputExceeded ReadProvisionedThroughputExceeded IteratorAgeMilliseconds + } + audit = { + name = "fleet-audit" + shard_count = 0 # shard count only matters if `stream_mode` is `PROVISIONED` + stream_mode = "ON_DEMAND" # valid values are `ON_DEMAND` or `PROVISIONED` + retention_period = 24 # number of hours you want the data to be retained on the stream + shard_level_metrics = [] # IncomingBytes IncomingRecords OutgoingBytes OutgoingRecords WriteProvisionedThroughputExceeded ReadProvisionedThroughputExceeded IteratorAgeMilliseconds + } + } +} + +output "kinesis_logging_destination" { + value = module.kinesis +} +``` + +1. **Variables:** + - `fleet_iam_role_arn`: A string variable that holds the ARN of the IAM role which will assume the role defined in this module to gain permissions for writing to the Kinesis Data Streams. + - `sts_external_id`: An optional string variable that can be used as a unique identifier for the principal assuming the role to assert its identity. Default is an empty string. + - `log_destinations`: A map variable that contains configurations for multiple Kinesis Data Streams. Each stream configuration includes its name, shard count, stream mode, retention period, and shard-level metrics. Default values are provided for three streams: `osquery_results`, `osquery_status`, and `fleet_audit`. + +2. **IAM Role:** + - `aws_iam_role.fleet_role`: Creates an IAM role with a trust policy that allows the specified IAM role ARN (`fleet_iam_role_arn`) to assume this role. If `sts_external_id` is provided, it adds a condition to the trust policy to require this external ID for the assume role operation. + +3. **IAM Policy Documents:** + - `data.aws_iam_policy_document.assume_role`: Defines the assume role policy for the IAM role. It allows the specified actions (`sts:AssumeRole`) for the specified principals. + - `data.aws_iam_policy_document.kinesis`: Defines the policy document allowing the IAM role to perform Kinesis and KMS actions. It allows the IAM role to describe, put records into the Kinesis streams (defined in `log_destinations`), and use KMS keys for encryption. + +4. **IAM Policy and Attachment:** + - `aws_iam_policy.fleet_kinesis`: Creates an IAM policy using the defined policy document (`data.aws_iam_policy_document.kinesis`). + - `aws_iam_role_policy_attachment.fleet_kinesis`: Attaches the created IAM policy to the IAM role (`aws_iam_role.fleet_role`). + +5. **KMS Key:** + - `aws_kms_key.kinesis_key`: Creates a KMS key for encrypting the Kinesis Data Streams. + +6. **Kinesis Data Streams:** + - `aws_kinesis_stream.fleet_log_destination`: Provisions Kinesis Data Streams based on the configurations defined in `log_destinations`. Each stream is created with the specified name, encryption type (using the KMS key), shard-level metrics, shard count (if the stream mode is not "ON\_DEMAND"), and stream mode. + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.3.7 | +| [aws](#requirement\_aws) | >= 5.29.0 | + +## Providers + +| Name | Version | +|------|---------| +| [aws](#provider\_aws) | 5.51.0 | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [aws_iam_policy.fleet_kinesis](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | +| [aws_iam_role.fleet_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | +| [aws_iam_role_policy_attachment.fleet_kinesis](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | +| [aws_kinesis_stream.fleet_log_destination](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kinesis_stream) | resource | +| [aws_kms_key.kinesis_key](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_key) | resource | +| [aws_iam_policy_document.assume_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_policy_document.kinesis](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [fleet\_iam\_role\_arn](#input\_fleet\_iam\_role\_arn) | The ARN of the IAM role that will be assuming into the IAM role defined in this module to gain permissions required to write to the Kinesis Data Stream(s). | `string` | n/a | yes | +| [log\_destinations](#input\_log\_destinations) | A map of configurations for Kinesis data streams. |
map(object({
name = string
shard_count = number
stream_mode = string
retention_period = number
shard_level_metrics = list(string)
}))
|
{
"audit": {
"name": "fleet_audit",
"retention_period": 24,
"shard_count": 0,
"shard_level_metrics": [],
"stream_mode": "ON_DEMAND"
},
"results": {
"name": "osquery_results",
"retention_period": 24,
"shard_count": 0,
"shard_level_metrics": [],
"stream_mode": "ON_DEMAND"
},
"status": {
"name": "osquery_status",
"retention_period": 24,
"shard_count": 0,
"shard_level_metrics": [],
"stream_mode": "ON_DEMAND"
}
}
| no | +| [sts\_external\_id](#input\_sts\_external\_id) | Optional unique identifier that can be used by the principal assuming the role to assert its identity. | `string` | `""` | no | + +## Outputs + +| Name | Description | +|------|-------------| +| [kinesis\_iam\_role](#output\_kinesis\_iam\_role) | n/a | +| [kinesis\_streams](#output\_kinesis\_streams) | A map of Kinesis streams with their names and ARNs. | diff --git a/terraform/addons/byo-kinesis-logging-destination/target-account/iam.tf b/terraform/addons/byo-kinesis-logging-destination/target-account/iam.tf new file mode 100644 index 0000000000..95671c43e1 --- /dev/null +++ b/terraform/addons/byo-kinesis-logging-destination/target-account/iam.tf @@ -0,0 +1,57 @@ +resource "aws_iam_role" "fleet_role" { + assume_role_policy = data.aws_iam_policy_document.assume_role.json +} + +data "aws_iam_policy_document" "assume_role" { + statement { + effect = "Allow" + actions = ["sts:AssumeRole"] + principals { + identifiers = [var.fleet_iam_role_arn] + type = "AWS" + } + dynamic "condition" { + for_each = length(var.sts_external_id) > 0 ? [1] : [] + content { + test = "StringEquals" + variable = "sts:ExternalId" + values = [var.sts_external_id] + } + } + } +} + +data "aws_iam_policy_document" "kinesis" { + statement { + effect = "Allow" + actions = [ + "kinesis:DescribeStreamSummary", + "kinesis:DescribeStream", + "kinesis:PutRecord", + "kinesis:PutRecords" + ] + resources = [ + for stream in aws_kinesis_stream.fleet_log_destination : stream.arn + ] + } + + statement { + effect = "Allow" + actions = [ + "kms:Decrypt", + "kms:GenerateDataKey", + ] + resources = [ + aws_kms_key.kinesis_key.arn + ] + } +} + +resource "aws_iam_policy" "fleet_kinesis" { + policy = data.aws_iam_policy_document.kinesis.json +} + +resource "aws_iam_role_policy_attachment" "fleet_kinesis" { + policy_arn = aws_iam_policy.fleet_kinesis.arn + role = aws_iam_role.fleet_role.name +} \ No newline at end of file diff --git a/terraform/addons/byo-kinesis-logging-destination/target-account/kinesis.tf b/terraform/addons/byo-kinesis-logging-destination/target-account/kinesis.tf new file mode 100644 index 0000000000..4271d13061 --- /dev/null +++ b/terraform/addons/byo-kinesis-logging-destination/target-account/kinesis.tf @@ -0,0 +1,15 @@ +resource "aws_kms_key" "kinesis_key" { + description = "KMS key for encrypting Kinesis Data Streams for Fleet logging destinations." +} + +resource "aws_kinesis_stream" "fleet_log_destination" { + for_each = var.log_destinations + name = each.value.name + encryption_type = "KMS" + kms_key_id = aws_kms_key.kinesis_key.id + shard_level_metrics = each.value.shard_level_metrics + shard_count = each.value.stream_mode == "ON_DEMAND" ? null : each.value.shard_count + stream_mode_details { + stream_mode = each.value.stream_mode + } +} diff --git a/terraform/addons/byo-kinesis-logging-destination/target-account/outputs.tf b/terraform/addons/byo-kinesis-logging-destination/target-account/outputs.tf new file mode 100644 index 0000000000..21a83a3192 --- /dev/null +++ b/terraform/addons/byo-kinesis-logging-destination/target-account/outputs.tf @@ -0,0 +1,13 @@ +output "kinesis_iam_role" { + value = aws_iam_role.fleet_role.arn +} + +output "kinesis_streams" { + description = "A map of Kinesis streams with their names and ARNs." + value = { + for k, stream in aws_kinesis_stream.fleet_log_destination : k => { + stream_name = stream.name + stream_arn = stream.arn + } + } +} diff --git a/terraform/addons/byo-kinesis-logging-destination/target-account/variables.tf b/terraform/addons/byo-kinesis-logging-destination/target-account/variables.tf new file mode 100644 index 0000000000..b65a6c86d7 --- /dev/null +++ b/terraform/addons/byo-kinesis-logging-destination/target-account/variables.tf @@ -0,0 +1,44 @@ +variable "fleet_iam_role_arn" { + type = string + description = "The ARN of the IAM role that will be assuming into the IAM role defined in this module to gain permissions required to write to the Kinesis Data Stream(s)." +} + +variable "sts_external_id" { + type = string + description = "Optional unique identifier that can be used by the principal assuming the role to assert its identity." + default = "" +} + +variable "log_destinations" { + description = "A map of configurations for Kinesis data streams." + type = map(object({ + name = string + shard_count = number + stream_mode = string + retention_period = number + shard_level_metrics = list(string) + })) + default = { + results = { + name = "osquery_results" + shard_count = 0 + stream_mode = "ON_DEMAND" + retention_period = 24 + shard_level_metrics = [] + }, + status = { + name = "osquery_status" + shard_count = 0 + stream_mode = "ON_DEMAND" + retention_period = 24 + shard_level_metrics = [] + }, + audit = { + name = "fleet_audit" + shard_count = 0 + stream_mode = "ON_DEMAND" + retention_period = 24 + shard_level_metrics = [] + } + } +} \ No newline at end of file diff --git a/terraform/addons/byo-kinesis-logging-destination/target-account/version.tf b/terraform/addons/byo-kinesis-logging-destination/target-account/version.tf new file mode 100644 index 0000000000..529d9d07ac --- /dev/null +++ b/terraform/addons/byo-kinesis-logging-destination/target-account/version.tf @@ -0,0 +1,10 @@ +terraform { + required_version = ">= 1.3.7" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.29.0" + } + } +} \ No newline at end of file