From b73756a6943bc4d060c5b174e93aa837079039b3 Mon Sep 17 00:00:00 2001 From: Anshuman Biswas Date: Thu, 1 Oct 2026 09:48:53 -0400 Subject: [PATCH 1/2] database-monitoring: agent and ED 0.1.8; ED's metrics port is on loopback (0.2.1) --- database-monitoring/terraform/.module.toml | 2 +- database-monitoring/terraform/README.md | 60 +++++++++---------- database-monitoring/terraform/main.tf | 10 +--- .../terraform/tests/module.tftest.hcl | 6 +- database-monitoring/terraform/variables.tf | 4 +- 5 files changed, 39 insertions(+), 43 deletions(-) diff --git a/database-monitoring/terraform/.module.toml b/database-monitoring/terraform/.module.toml index 0b32659..beaa8cf 100644 --- a/database-monitoring/terraform/.module.toml +++ b/database-monitoring/terraform/.module.toml @@ -1,6 +1,6 @@ [module] name = "aws-elastio-database-monitoring-agent" -version = "0.2.0" +version = "0.2.1" description = "Terraform module that runs the Elastio database monitoring agent on AWS Fargate" type = "terraform" diff --git a/database-monitoring/terraform/README.md b/database-monitoring/terraform/README.md index 4aa5ab1..4135823 100644 --- a/database-monitoring/terraform/README.md +++ b/database-monitoring/terraform/README.md @@ -63,14 +63,14 @@ A security group with the usual allow-all egress already allows all three. The d - a task-role policy that allows `elasticfilesystem:ClientMount` and `ClientWrite` on the file system, only through that access point. - a file system policy that refuses anonymous clients and denies every mount that does not use that access point or TLS. Other roles in the account with their own EFS permissions can still mount through the access point if the network admits them, so keep `security_group_ids` for the agent only. - A Fargate task definition of `task_cpu` and `task_memory` (by default 0.25 vCPU and 0.5 GB), ARM64, with a read-only root filesystem. The task runs as the image's non-root user, with `GOMEMLIMIT` set to 80% of the agent's memory: `task_memory`, less 384 MiB with `content_analysis = true`. -- With `content_analysis = true`, a second container in the same task, running Elastio's encryption detector (`ed_image`) as the agent's non-root user. Its gRPC port is on loopback only. Its Prometheus metrics port, TCP 50052, listens on all interfaces of the task, so `security_group_ids` must not allow inbound traffic on it. The agent needs no inbound rules at all. It reads a task-local scratch volume at `/var/lib/elastio-dbmon-ed`, read-only; see **Content analysis** below. +- With `content_analysis = true`, a second container in the same task, running Elastio's encryption detector (`ed_image`) as the agent's non-root user. Its gRPC and metrics ports listen on loopback only. The agent needs no inbound rules at all. It reads a task-local scratch volume at `/var/lib/elastio-dbmon-ed`, read-only; see **Content analysis** below. - A service with `desired_count = 1`. Its deployment policy (minimum healthy 0%, maximum 100%) stops the old task before it starts the new one. A replication slot allows only one consumer at a time, and the agent's state allows only one writer. Don't raise the maximum. ## Content analysis When rows are rewritten in place and no rewrite limit is declared for the table, the agent can't tell a migration from an attacker encrypting the data: both look the same in the change stream. With `content_analysis = true`, Elastio's encryption detector (ED) runs beside the agent and settles it. If the new values are ciphertext, the window becomes a high-severity finding that names the encrypted columns. -- **Off by default.** It needs agent 0.1.7 or later and `task_memory` of at least 1024. ED takes 384 MiB of the task and the agent gets the rest, so with `task_memory = 1024` the agent has 640 MiB and a `GOMEMLIMIT` of 512 MiB. +- **Off by default.** It needs agent 0.1.7 or later (0.1.8 binds the detector's metrics port to loopback too) and `task_memory` of at least 1024. ED takes 384 MiB of the task and the agent gets the rest, so with `task_memory = 1024` the agent has 640 MiB and a `GOMEMLIMIT` of 512 MiB. - **What it does with your data.** The agent samples the rewritten values in memory, at most 4 MiB. When a window closes, it writes the sample to task-local storage for ED to read and removes it once ED answers. Values never reach the agent's EFS state, its log, or Elastio. Only the verdict does, as part of the finding. - **Where ED comes from.** `ed_image` is built for ARM64 and x86-64 from the ED version the agent release was tested with. Each module version defaults to the matching pair. - **If ED stops.** The agent keeps running. The windows it judges in the meantime get no verdict, which can raise a finding and never withholds one. ECS restarts ED. @@ -190,36 +190,36 @@ No modules. ## Inputs -| Name | Description | Type | Default | Required | -| --------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------- | ------------------------------------------------------------------ | :------: | -| [api_key](#input_api_key) | Bearer token the agent presents to the server. Stored in Secrets Manager, never in the task definition. | `string` | n/a | yes | -| [assign_public_ip](#input_assign_public_ip) | Give the task a public IP. Needed only when the subnets have no NAT gateway and the server URL is on the internet. | `bool` | `false` | no | -| [content_analysis](#input_content_analysis) | Run Elastio's encryption detector beside the agent, so a table whose rows are overwritten with ciphertext is reported as a high-severity finding even where no rewrite limit is declared. The agent samples the rewritten values in memory and on task-local storage only, for the detector to read; only the verdict leaves the task. Needs agent 0.1.7 or later and task_memory of at least 1024. | `bool` | `false` | no | -| [database_url](#input_database_url) | postgres:// URL of the database to watch, for a role with REPLICATION. Stored in Secrets Manager, never in the task definition. | `string` | n/a | yes | -| [ed_image](#input_ed_image) | Encryption detector image, used when content_analysis is true: Elastio's ED gRPC server, built for amd64 and arm64 from the elastio/ed commit the agent release pins. The default is the one released with the default agent image. | `string` | `"public.ecr.aws/elastio/elastio-database-monitoring-ed:0.1.7"` | no | -| [image](#input_image) | Agent image. The default is the agent release this module version was tested with. Pin a version; :latest moves. Needs 0.1.5 or later: older agents read only the QUELL\_\* variable names. | `string` | `"public.ecr.aws/elastio/elastio-database-monitoring-agent:0.1.7"` | no | -| [log_retention_days](#input_log_retention_days) | How long CloudWatch keeps the agent's log. | `number` | `7` | no | -| [name](#input_name) | What the product shows for this agent. Also the ECS cluster, service and task family name, sanitised to the characters ECS allows. | `string` | n/a | yes | -| [persistent_ledger](#input_persistent_ledger) | Keep the agent's state on an encrypted EFS file system so it persists across task replacement. When false, the state is on the task's ephemeral storage and every replacement starts it empty. | `bool` | `true` | no | -| [publication](#input_publication) | Name of the publication whose tables are streamed. | `string` | `"elastio_monitor"` | no | -| [security_group_ids](#input_security_group_ids) | Security groups attached to the task. The database's own security group must admit them on its port. | `list(string)` | n/a | yes | -| [server_url](#input_server_url) | Base URL of the server the agent reports to. | `string` | n/a | yes | -| [slot](#input_slot) | Name of the existing pgoutput replication slot. The agent never creates or drops one. | `string` | `"elastio_monitor"` | no | -| [subnet_ids](#input_subnet_ids) | Subnets the task runs in. They must reach the database and the server URL. | `list(string)` | n/a | yes | -| [tags](#input_tags) | Tags applied to every resource the module creates. | `map(string)` | `{}` | no | -| [task_cpu](#input_task_cpu) | CPU units for the Fargate task: 256 (0.25 vCPU), 512, 1024 or 2048. Together with task_memory it must be a size Fargate runs on ARM64; see Sizing in the README. | `number` | `256` | no | -| [task_memory](#input_task_memory) | Memory for the Fargate task, in MiB. With task_cpu 256: 512, 1024 or 2048. With 512: 1024 to 4096. With 1024: 2048 to 8192. With 2048: 4096 to 16384. Above 512, in steps of 1024. The agent's Go memory limit follows it. Raise it when the Elastio UI recommends a larger size. | `number` | `512` | no | +| Name | Description | Type | Default | Required | +| ----------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------- | ------------------------------------------------------------------ | :------: | +| [api\_key](#input_api_key) | Bearer token the agent presents to the server. Stored in Secrets Manager, never in the task definition. | `string` | n/a | yes | +| [assign\_public\_ip](#input_assign_public_ip) | Give the task a public IP. Needed only when the subnets have no NAT gateway and the server URL is on the internet. | `bool` | `false` | no | +| [content\_analysis](#input_content_analysis) | Run Elastio's encryption detector beside the agent, so a table whose rows are overwritten with ciphertext is reported as a high-severity finding even where no rewrite limit is declared. The agent samples the rewritten values in memory and on task-local storage only, for the detector to read; only the verdict leaves the task. Needs agent 0.1.7 or later and task\_memory of at least 1024. | `bool` | `false` | no | +| [database\_url](#input_database_url) | postgres:// URL of the database to watch, for a role with REPLICATION. Stored in Secrets Manager, never in the task definition. | `string` | n/a | yes | +| [ed\_image](#input_ed_image) | Encryption detector image, used when content\_analysis is true: Elastio's ED gRPC server, built for amd64 and arm64 from the elastio/ed commit the agent release pins. The default is the one released with the default agent image. | `string` | `"public.ecr.aws/elastio/elastio-database-monitoring-ed:0.1.8"` | no | +| [image](#input_image) | Agent image. The default is the agent release this module version was tested with. Pin a version; :latest moves. Needs 0.1.5 or later: older agents read only the QUELL\_* variable names. | `string` | `"public.ecr.aws/elastio/elastio-database-monitoring-agent:0.1.8"` | no | +| [log\_retention\_days](#input_log_retention_days) | How long CloudWatch keeps the agent's log. | `number` | `7` | no | +| [name](#input_name) | What the product shows for this agent. Also the ECS cluster, service and task family name, sanitised to the characters ECS allows. | `string` | n/a | yes | +| [persistent\_ledger](#input_persistent_ledger) | Keep the agent's state on an encrypted EFS file system so it persists across task replacement. When false, the state is on the task's ephemeral storage and every replacement starts it empty. | `bool` | `true` | no | +| [publication](#input_publication) | Name of the publication whose tables are streamed. | `string` | `"elastio_monitor"` | no | +| [security\_group\_ids](#input_security_group_ids) | Security groups attached to the task. The database's own security group must admit them on its port. | `list(string)` | n/a | yes | +| [server\_url](#input_server_url) | Base URL of the server the agent reports to. | `string` | n/a | yes | +| [slot](#input_slot) | Name of the existing pgoutput replication slot. The agent never creates or drops one. | `string` | `"elastio_monitor"` | no | +| [subnet\_ids](#input_subnet_ids) | Subnets the task runs in. They must reach the database and the server URL. | `list(string)` | n/a | yes | +| [tags](#input_tags) | Tags applied to every resource the module creates. | `map(string)` | `{}` | no | +| [task\_cpu](#input_task_cpu) | CPU units for the Fargate task: 256 (0.25 vCPU), 512, 1024 or 2048. Together with task\_memory it must be a size Fargate runs on ARM64; see Sizing in the README. | `number` | `256` | no | +| [task\_memory](#input_task_memory) | Memory for the Fargate task, in MiB. With task\_cpu 256: 512, 1024 or 2048. With 512: 1024 to 4096. With 1024: 2048 to 8192. With 2048: 4096 to 16384. Above 512, in steps of 1024. The agent's Go memory limit follows it. Raise it when the Elastio UI recommends a larger size. | `number` | `512` | no | ## Outputs -| Name | Description | -| -------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | -| [cluster_arn](#output_cluster_arn) | ARN of the ECS cluster the agent runs in. | -| [execution_role_arn](#output_execution_role_arn) | IAM role ECS uses to pull the image, read the three secrets and write logs. | -| [hash_secret_arn](#output_hash_secret_arn) | ARN of the Secrets Manager secret holding the agent's key. It must stay stable for the life of the agent's state. | -| [ledger_file_system_id](#output_ledger_file_system_id) | ID of the EFS file system holding the agent's state, or null when persistent_ledger is false. | -| [log_group_name](#output_log_group_name) | CloudWatch log group the agent writes to. | -| [service_name](#output_service_name) | Name of the ECS service. | -| [task_role_arn](#output_task_role_arn) | IAM role the running container assumes. The agent has no AWS code; with persistent state the role may mount the state file system, and nothing else. | +| Name | Description | +| ----------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | +| [cluster\_arn](#output_cluster_arn) | ARN of the ECS cluster the agent runs in. | +| [execution\_role\_arn](#output_execution_role_arn) | IAM role ECS uses to pull the image, read the three secrets and write logs. | +| [hash\_secret\_arn](#output_hash_secret_arn) | ARN of the Secrets Manager secret holding the agent's key. It must stay stable for the life of the agent's state. | +| [ledger\_file\_system\_id](#output_ledger_file_system_id) | ID of the EFS file system holding the agent's state, or null when persistent\_ledger is false. | +| [log\_group\_name](#output_log_group_name) | CloudWatch log group the agent writes to. | +| [service\_name](#output_service_name) | Name of the ECS service. | +| [task\_role\_arn](#output_task_role_arn) | IAM role the running container assumes. The agent has no AWS code; with persistent state the role may mount the state file system, and nothing else. | diff --git a/database-monitoring/terraform/main.tf b/database-monitoring/terraform/main.tf index 2bdf3dc..8f90615 100644 --- a/database-monitoring/terraform/main.tf +++ b/database-monitoring/terraform/main.tf @@ -129,13 +129,9 @@ locals { # costs a window its verdict and nothing else -- the agent judges without # one and says so -- and ECS restarts it. # - # The gRPC port is bound to loopback, so only the agent reaches it. The - # Prometheus metrics port is NOT: ED's Python server starts it with - # start_http_server(port) and no address, so it listens on every interface - # of the task ENI whatever --host says (verified on the image, ED 624e66b; - # still so on ED master). It serves counters and timings, never values, - # and the task's security groups are what keep it in: they must not admit - # inbound TCP 50052. The agent needs no inbound rule at all. + # Both ports, gRPC and Prometheus metrics, are bound to loopback, so only + # the agent reaches them (ED from ce003e0, elastio/ed#42; earlier ED bound + # metrics to every interface). The agent needs no inbound rule at all. ed_container = { name = "${local.prefix}-ed" image = var.ed_image diff --git a/database-monitoring/terraform/tests/module.tftest.hcl b/database-monitoring/terraform/tests/module.tftest.hcl index 49936e1..ab1fbda 100644 --- a/database-monitoring/terraform/tests/module.tftest.hcl +++ b/database-monitoring/terraform/tests/module.tftest.hcl @@ -135,8 +135,8 @@ run "names_and_image" { error_message = "secrets must be named elastio-dbmon//..." } assert { - condition = strcontains(aws_ecs_task_definition.this.container_definitions, "\"image\":\"public.ecr.aws/elastio/elastio-database-monitoring-agent:0.1.7\"") - error_message = "the default image must be Elastio's public ECR image of agent 0.1.7, the first that can ask the encryption detector" + condition = strcontains(aws_ecs_task_definition.this.container_definitions, "\"image\":\"public.ecr.aws/elastio/elastio-database-monitoring-agent:0.1.8\"") + error_message = "the default image must be Elastio's public ECR image of agent 0.1.8" } } @@ -328,7 +328,7 @@ run "content_analysis_runs_the_detector_beside_the_agent" { error_message = "the scratch volume must be task-local, never EFS" } assert { - condition = strcontains(aws_ecs_task_definition.this.container_definitions, "elastio-database-monitoring-ed:0.1.7") + condition = strcontains(aws_ecs_task_definition.this.container_definitions, "elastio-database-monitoring-ed:0.1.8") error_message = "the detector defaults to the image released with the default agent" } } diff --git a/database-monitoring/terraform/variables.tf b/database-monitoring/terraform/variables.tf index 0ef45c7..7614337 100644 --- a/database-monitoring/terraform/variables.tf +++ b/database-monitoring/terraform/variables.tf @@ -58,7 +58,7 @@ variable "security_group_ids" { variable "image" { description = "Agent image. The default is the agent release this module version was tested with. Pin a version; :latest moves. Needs 0.1.5 or later: older agents read only the QUELL_* variable names." type = string - default = "public.ecr.aws/elastio/elastio-database-monitoring-agent:0.1.7" + default = "public.ecr.aws/elastio/elastio-database-monitoring-agent:0.1.8" } variable "content_analysis" { @@ -77,7 +77,7 @@ variable "content_analysis" { variable "ed_image" { description = "Encryption detector image, used when content_analysis is true: Elastio's ED gRPC server, built for amd64 and arm64 from the elastio/ed commit the agent release pins. The default is the one released with the default agent image." type = string - default = "public.ecr.aws/elastio/elastio-database-monitoring-ed:0.1.7" + default = "public.ecr.aws/elastio/elastio-database-monitoring-ed:0.1.8" } variable "task_cpu" { From 3c223a6ec374dfb34692513225974aed71c96a60 Mon Sep 17 00:00:00 2001 From: Anshuman Biswas Date: Thu, 1 Oct 2026 09:54:31 -0400 Subject: [PATCH 2/2] database-monitoring: README formatted with the repo's prettier --- database-monitoring/terraform/README.md | 56 ++++++++++++------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/database-monitoring/terraform/README.md b/database-monitoring/terraform/README.md index 4135823..864b844 100644 --- a/database-monitoring/terraform/README.md +++ b/database-monitoring/terraform/README.md @@ -190,36 +190,36 @@ No modules. ## Inputs -| Name | Description | Type | Default | Required | -| ----------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------- | ------------------------------------------------------------------ | :------: | -| [api\_key](#input_api_key) | Bearer token the agent presents to the server. Stored in Secrets Manager, never in the task definition. | `string` | n/a | yes | -| [assign\_public\_ip](#input_assign_public_ip) | Give the task a public IP. Needed only when the subnets have no NAT gateway and the server URL is on the internet. | `bool` | `false` | no | -| [content\_analysis](#input_content_analysis) | Run Elastio's encryption detector beside the agent, so a table whose rows are overwritten with ciphertext is reported as a high-severity finding even where no rewrite limit is declared. The agent samples the rewritten values in memory and on task-local storage only, for the detector to read; only the verdict leaves the task. Needs agent 0.1.7 or later and task\_memory of at least 1024. | `bool` | `false` | no | -| [database\_url](#input_database_url) | postgres:// URL of the database to watch, for a role with REPLICATION. Stored in Secrets Manager, never in the task definition. | `string` | n/a | yes | -| [ed\_image](#input_ed_image) | Encryption detector image, used when content\_analysis is true: Elastio's ED gRPC server, built for amd64 and arm64 from the elastio/ed commit the agent release pins. The default is the one released with the default agent image. | `string` | `"public.ecr.aws/elastio/elastio-database-monitoring-ed:0.1.8"` | no | -| [image](#input_image) | Agent image. The default is the agent release this module version was tested with. Pin a version; :latest moves. Needs 0.1.5 or later: older agents read only the QUELL\_* variable names. | `string` | `"public.ecr.aws/elastio/elastio-database-monitoring-agent:0.1.8"` | no | -| [log\_retention\_days](#input_log_retention_days) | How long CloudWatch keeps the agent's log. | `number` | `7` | no | -| [name](#input_name) | What the product shows for this agent. Also the ECS cluster, service and task family name, sanitised to the characters ECS allows. | `string` | n/a | yes | -| [persistent\_ledger](#input_persistent_ledger) | Keep the agent's state on an encrypted EFS file system so it persists across task replacement. When false, the state is on the task's ephemeral storage and every replacement starts it empty. | `bool` | `true` | no | -| [publication](#input_publication) | Name of the publication whose tables are streamed. | `string` | `"elastio_monitor"` | no | -| [security\_group\_ids](#input_security_group_ids) | Security groups attached to the task. The database's own security group must admit them on its port. | `list(string)` | n/a | yes | -| [server\_url](#input_server_url) | Base URL of the server the agent reports to. | `string` | n/a | yes | -| [slot](#input_slot) | Name of the existing pgoutput replication slot. The agent never creates or drops one. | `string` | `"elastio_monitor"` | no | -| [subnet\_ids](#input_subnet_ids) | Subnets the task runs in. They must reach the database and the server URL. | `list(string)` | n/a | yes | -| [tags](#input_tags) | Tags applied to every resource the module creates. | `map(string)` | `{}` | no | -| [task\_cpu](#input_task_cpu) | CPU units for the Fargate task: 256 (0.25 vCPU), 512, 1024 or 2048. Together with task\_memory it must be a size Fargate runs on ARM64; see Sizing in the README. | `number` | `256` | no | -| [task\_memory](#input_task_memory) | Memory for the Fargate task, in MiB. With task\_cpu 256: 512, 1024 or 2048. With 512: 1024 to 4096. With 1024: 2048 to 8192. With 2048: 4096 to 16384. Above 512, in steps of 1024. The agent's Go memory limit follows it. Raise it when the Elastio UI recommends a larger size. | `number` | `512` | no | +| Name | Description | Type | Default | Required | +| --------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------- | ------------------------------------------------------------------ | :------: | +| [api_key](#input_api_key) | Bearer token the agent presents to the server. Stored in Secrets Manager, never in the task definition. | `string` | n/a | yes | +| [assign_public_ip](#input_assign_public_ip) | Give the task a public IP. Needed only when the subnets have no NAT gateway and the server URL is on the internet. | `bool` | `false` | no | +| [content_analysis](#input_content_analysis) | Run Elastio's encryption detector beside the agent, so a table whose rows are overwritten with ciphertext is reported as a high-severity finding even where no rewrite limit is declared. The agent samples the rewritten values in memory and on task-local storage only, for the detector to read; only the verdict leaves the task. Needs agent 0.1.7 or later and task_memory of at least 1024. | `bool` | `false` | no | +| [database_url](#input_database_url) | postgres:// URL of the database to watch, for a role with REPLICATION. Stored in Secrets Manager, never in the task definition. | `string` | n/a | yes | +| [ed_image](#input_ed_image) | Encryption detector image, used when content_analysis is true: Elastio's ED gRPC server, built for amd64 and arm64 from the elastio/ed commit the agent release pins. The default is the one released with the default agent image. | `string` | `"public.ecr.aws/elastio/elastio-database-monitoring-ed:0.1.8"` | no | +| [image](#input_image) | Agent image. The default is the agent release this module version was tested with. Pin a version; :latest moves. Needs 0.1.5 or later: older agents read only the QUELL\_\* variable names. | `string` | `"public.ecr.aws/elastio/elastio-database-monitoring-agent:0.1.8"` | no | +| [log_retention_days](#input_log_retention_days) | How long CloudWatch keeps the agent's log. | `number` | `7` | no | +| [name](#input_name) | What the product shows for this agent. Also the ECS cluster, service and task family name, sanitised to the characters ECS allows. | `string` | n/a | yes | +| [persistent_ledger](#input_persistent_ledger) | Keep the agent's state on an encrypted EFS file system so it persists across task replacement. When false, the state is on the task's ephemeral storage and every replacement starts it empty. | `bool` | `true` | no | +| [publication](#input_publication) | Name of the publication whose tables are streamed. | `string` | `"elastio_monitor"` | no | +| [security_group_ids](#input_security_group_ids) | Security groups attached to the task. The database's own security group must admit them on its port. | `list(string)` | n/a | yes | +| [server_url](#input_server_url) | Base URL of the server the agent reports to. | `string` | n/a | yes | +| [slot](#input_slot) | Name of the existing pgoutput replication slot. The agent never creates or drops one. | `string` | `"elastio_monitor"` | no | +| [subnet_ids](#input_subnet_ids) | Subnets the task runs in. They must reach the database and the server URL. | `list(string)` | n/a | yes | +| [tags](#input_tags) | Tags applied to every resource the module creates. | `map(string)` | `{}` | no | +| [task_cpu](#input_task_cpu) | CPU units for the Fargate task: 256 (0.25 vCPU), 512, 1024 or 2048. Together with task_memory it must be a size Fargate runs on ARM64; see Sizing in the README. | `number` | `256` | no | +| [task_memory](#input_task_memory) | Memory for the Fargate task, in MiB. With task_cpu 256: 512, 1024 or 2048. With 512: 1024 to 4096. With 1024: 2048 to 8192. With 2048: 4096 to 16384. Above 512, in steps of 1024. The agent's Go memory limit follows it. Raise it when the Elastio UI recommends a larger size. | `number` | `512` | no | ## Outputs -| Name | Description | -| ----------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | -| [cluster\_arn](#output_cluster_arn) | ARN of the ECS cluster the agent runs in. | -| [execution\_role\_arn](#output_execution_role_arn) | IAM role ECS uses to pull the image, read the three secrets and write logs. | -| [hash\_secret\_arn](#output_hash_secret_arn) | ARN of the Secrets Manager secret holding the agent's key. It must stay stable for the life of the agent's state. | -| [ledger\_file\_system\_id](#output_ledger_file_system_id) | ID of the EFS file system holding the agent's state, or null when persistent\_ledger is false. | -| [log\_group\_name](#output_log_group_name) | CloudWatch log group the agent writes to. | -| [service\_name](#output_service_name) | Name of the ECS service. | -| [task\_role\_arn](#output_task_role_arn) | IAM role the running container assumes. The agent has no AWS code; with persistent state the role may mount the state file system, and nothing else. | +| Name | Description | +| -------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | +| [cluster_arn](#output_cluster_arn) | ARN of the ECS cluster the agent runs in. | +| [execution_role_arn](#output_execution_role_arn) | IAM role ECS uses to pull the image, read the three secrets and write logs. | +| [hash_secret_arn](#output_hash_secret_arn) | ARN of the Secrets Manager secret holding the agent's key. It must stay stable for the life of the agent's state. | +| [ledger_file_system_id](#output_ledger_file_system_id) | ID of the EFS file system holding the agent's state, or null when persistent_ledger is false. | +| [log_group_name](#output_log_group_name) | CloudWatch log group the agent writes to. | +| [service_name](#output_service_name) | Name of the ECS service. | +| [task_role_arn](#output_task_role_arn) | IAM role the running container assumes. The agent has no AWS code; with persistent state the role may mount the state file system, and nothing else. |