From 7ca75d29d51017334501c1f881598ca2f75e6c03 Mon Sep 17 00:00:00 2001 From: Segev Elmalech Date: Sun, 1 Feb 2026 16:57:46 +0200 Subject: [PATCH 1/2] feat: add EIP pool support for predictable IP addresses Add support for using pre-allocated Elastic IP pools instead of randomly created EIPs. This allows CI/CD runners and external systems to whitelist specific IP addresses for SSH access, improving security by avoiding 0.0.0.0/0 firewall rules. Changes: Base Modules: - Add optional eip_allocation_id parameter to sonar-base-instance, dam-base-instance, ciphertrust-manager, cte-ddc-agent, and dra-admin - When eip_allocation_id is provided, use existing EIP instead of creating new - When null (default), create and manage new EIP (backward compatible) Wrapper Modules: - Add pass-through eip_allocation_id parameter to hub, mx, agentless-gw, and agent-gw modules Deployment Example: - Add use_eip_pool and eip_pool_tag variables - Add eip_pool.tf with pool query logic and allocation ID distribution - Add validation to ensure sufficient IPs are available in pool - Add time_sleep resource to handle CipherTrust provider timing with pooled EIPs - Update all module calls to pass allocation IDs when pooled mode enabled Benefits: - Predictable IP addresses for CI/CD firewall whitelisting - IPs survive terraform destroy and can be reused - Fully backward compatible (default behavior unchanged) - Deployment-level pool management (base modules stay simple) Co-Authored-By: Claude --- examples/aws/poc/dsf_deployment/cm.tf | 23 +++- .../aws/poc/dsf_deployment/cte_ddc_agents.tf | 1 + examples/aws/poc/dsf_deployment/dam.tf | 1 + examples/aws/poc/dsf_deployment/dra.tf | 4 +- examples/aws/poc/dsf_deployment/eip_pool.tf | 108 ++++++++++++++++++ examples/aws/poc/dsf_deployment/sonar.tf | 2 + examples/aws/poc/dsf_deployment/variables.tf | 25 ++++ modules/aws/agent-gw/main.tf | 1 + modules/aws/agent-gw/variables.tf | 16 +++ modules/aws/agentless-gw/main.tf | 1 + modules/aws/agentless-gw/variables.tf | 16 +++ modules/aws/ciphertrust-manager/main.tf | 37 ++++-- modules/aws/ciphertrust-manager/variables.tf | 16 +++ modules/aws/cte-ddc-agent/main.tf | 33 +++++- modules/aws/cte-ddc-agent/variables.tf | 16 +++ modules/aws/dam-base-instance/main.tf | 33 +++++- modules/aws/dam-base-instance/variables.tf | 16 +++ modules/aws/dra-admin/main.tf | 33 +++++- modules/aws/dra-admin/variables.tf | 16 +++ modules/aws/hub/main.tf | 1 + modules/aws/hub/variables.tf | 16 +++ modules/aws/mx/main.tf | 1 + modules/aws/mx/variables.tf | 15 +++ modules/aws/sonar-base-instance/main.tf | 33 +++++- modules/aws/sonar-base-instance/variables.tf | 16 +++ 25 files changed, 450 insertions(+), 30 deletions(-) create mode 100644 examples/aws/poc/dsf_deployment/eip_pool.tf diff --git a/examples/aws/poc/dsf_deployment/cm.tf b/examples/aws/poc/dsf_deployment/cm.tf index f4425fc4..d0d6f349 100644 --- a/examples/aws/poc/dsf_deployment/cm.tf +++ b/examples/aws/poc/dsf_deployment/cm.tf @@ -5,9 +5,9 @@ locals { } module "ciphertrust_manager" { - source = "imperva/dsf-ciphertrust-manager/aws" - version = "1.7.34" # latest release tag - count = local.ciphertrust_manager_count + source = "imperva/dsf-ciphertrust-manager/aws" + version = "1.7.34" # latest release tag + count = local.ciphertrust_manager_count ciphertrust_manager_version = var.ciphertrust_manager_version ami = var.ciphertrust_manager_ami_id == null ? null : { id = var.ciphertrust_manager_ami_id @@ -20,6 +20,7 @@ module "ciphertrust_manager" { subnet_id = local.ciphertrust_manager_subnet_id cm_password = local.password attach_persistent_public_ip = true + eip_allocation_id = length(local.ciphertrust_manager_eip_allocation_ids) > 0 ? local.ciphertrust_manager_eip_allocation_ids[count.index] : null key_pair = module.key_pair.key_pair.key_pair_name allowed_web_console_and_api_cidrs = concat(local.workstation_cidr, var.web_console_cidr) allowed_ssh_cidrs = concat(local.workstation_cidr, var.allowed_ssh_cidrs) @@ -33,7 +34,20 @@ module "ciphertrust_manager" { ] } +# When using pooled EIPs, the public IP is known immediately but the association takes time +# Add a delay to ensure the EIP is associated before the provider tries to connect +resource "time_sleep" "wait_for_ciphertrust_eip" { + count = local.ciphertrust_manager_count > 0 && var.use_eip_pool ? 1 : 0 + + depends_on = [ + module.ciphertrust_manager + ] + + create_duration = "30s" +} + provider "ciphertrust" { + # Use public IP for connectivity from local Mac/CI runners address = local.ciphertrust_manager_count > 0 ? "https://${coalesce(module.ciphertrust_manager[0].public_ip, module.ciphertrust_manager[0].private_ip)}" : null username = local.ciphertrust_manager_web_console_username password = local.password @@ -46,7 +60,8 @@ resource "ciphertrust_trial_license" "trial_license" { flag = "activate" depends_on = [ - module.ciphertrust_manager + module.ciphertrust_manager, + time_sleep.wait_for_ciphertrust_eip # Ensure EIP is associated before connecting ] } diff --git a/examples/aws/poc/dsf_deployment/cte_ddc_agents.tf b/examples/aws/poc/dsf_deployment/cte_ddc_agents.tf index 657f82aa..8de17cce 100644 --- a/examples/aws/poc/dsf_deployment/cte_ddc_agents.tf +++ b/examples/aws/poc/dsf_deployment/cte_ddc_agents.tf @@ -95,6 +95,7 @@ module "cte_ddc_agents" { } os_type = each.value.os_type attach_persistent_public_ip = true + eip_allocation_id = lookup(local.cte_agent_eip_allocation_ids, each.key, null) use_public_ip = true allowed_ssh_cidrs = concat(local.workstation_cidr, var.allowed_ssh_cidrs) allowed_rdp_cidrs = each.value.os_type == "Windows" ? concat(local.workstation_cidr, var.allowed_ssh_cidrs) : [] diff --git a/examples/aws/poc/dsf_deployment/dam.tf b/examples/aws/poc/dsf_deployment/dam.tf index fd067215..6daa7c56 100644 --- a/examples/aws/poc/dsf_deployment/dam.tf +++ b/examples/aws/poc/dsf_deployment/dam.tf @@ -30,6 +30,7 @@ module "mx" { port = 8443 } : null attach_persistent_public_ip = true + eip_allocation_id = local.mx_eip_allocation_id large_scale_mode = var.large_scale_mode.mx create_server_group = length(var.simulation_db_types_for_agent) > 0 diff --git a/examples/aws/poc/dsf_deployment/dra.tf b/examples/aws/poc/dsf_deployment/dra.tf index cd684852..4f371001 100644 --- a/examples/aws/poc/dsf_deployment/dra.tf +++ b/examples/aws/poc/dsf_deployment/dra.tf @@ -21,6 +21,7 @@ module "dra_admin" { allowed_hub_cidrs = local.hub_cidr_list allowed_ssh_cidrs = concat(local.workstation_cidr, var.allowed_ssh_cidrs) attach_persistent_public_ip = true + eip_allocation_id = local.dra_admin_eip_allocation_id tags = local.tags depends_on = [ @@ -31,8 +32,7 @@ module "dra_admin" { module "dra_analytics" { source = "imperva/dsf-dra-analytics/aws" version = "1.7.34" # latest release tag - - count = local.dra_analytics_count + count = local.dra_analytics_count name = join("-", [local.deployment_name_salted, "dra", "analytics", count.index]) subnet_id = local.dra_analytics_subnet_id dra_version = module.globals.dra_version diff --git a/examples/aws/poc/dsf_deployment/eip_pool.tf b/examples/aws/poc/dsf_deployment/eip_pool.tf new file mode 100644 index 00000000..82a48405 --- /dev/null +++ b/examples/aws/poc/dsf_deployment/eip_pool.tf @@ -0,0 +1,108 @@ +# Query AWS for all EIPs in the pool +data "aws_eips" "pool" { + count = var.use_eip_pool ? 1 : 0 + + filter { + name = "tag:Pool" + values = [var.eip_pool_tag] + } +} + +# Create locals to distribute allocation IDs to resources +locals { + # Get list of allocation IDs from pool (only unassociated ones to avoid conflicts) + eip_pool_all_allocation_ids = var.use_eip_pool ? data.aws_eips.pool[0].allocation_ids : [] + + # Calculate how many IPs we need + eip_count_needed = ( + (var.enable_sonar ? 1 : 0) + # hub_main + (var.enable_sonar && var.hub_hadr ? 1 : 0) + # hub_dr + (var.enable_dam ? 1 : 0) + # mx + (var.enable_dra ? 1 : 0) + # dra_admin + (var.enable_ciphertrust ? var.ciphertrust_manager_count : 0) + # ciphertrust_managers + (var.enable_ciphertrust ? ( # cte/ddc agents + var.cte_ddc_agents_linux_count + + var.cte_agents_linux_count + + var.ddc_agents_linux_count + + var.cte_ddc_agents_windows_count + + var.cte_agents_windows_count + + var.ddc_agents_windows_count + ) : 0) + ) + + # Validate we have enough IPs + eip_pool_valid = !var.use_eip_pool || length(local.eip_pool_all_allocation_ids) >= local.eip_count_needed + + # Distribute allocation IDs to resources + # Use null if use_eip_pool is false (modules will create new EIPs) + + # Index counter for distributing IPs + hub_main_eip_index = 0 + hub_dr_eip_index = var.enable_sonar ? 1 : 0 + mx_eip_index = (var.enable_sonar ? 1 : 0) + (var.enable_sonar && var.hub_hadr ? 1 : 0) + dra_admin_eip_index = ( + (var.enable_sonar ? 1 : 0) + + (var.enable_sonar && var.hub_hadr ? 1 : 0) + + (var.enable_dam ? 1 : 0) + ) + ciphertrust_manager_eip_start_index = ( + (var.enable_sonar ? 1 : 0) + + (var.enable_sonar && var.hub_hadr ? 1 : 0) + + (var.enable_dam ? 1 : 0) + + (var.enable_dra ? 1 : 0) + ) + cte_agent_eip_start_index = ( + (var.enable_sonar ? 1 : 0) + + (var.enable_sonar && var.hub_hadr ? 1 : 0) + + (var.enable_dam ? 1 : 0) + + (var.enable_dra ? 1 : 0) + + (var.enable_ciphertrust ? var.ciphertrust_manager_count : 0) + ) + + # Assign specific allocation IDs to each resource + hub_main_eip_allocation_id = var.use_eip_pool && var.enable_sonar ? local.eip_pool_all_allocation_ids[local.hub_main_eip_index] : null + hub_dr_eip_allocation_id = var.use_eip_pool && var.enable_sonar && var.hub_hadr ? local.eip_pool_all_allocation_ids[local.hub_dr_eip_index] : null + mx_eip_allocation_id = var.use_eip_pool && var.enable_dam ? local.eip_pool_all_allocation_ids[local.mx_eip_index] : null + dra_admin_eip_allocation_id = var.use_eip_pool && var.enable_dra ? local.eip_pool_all_allocation_ids[local.dra_admin_eip_index] : null + + # For CipherTrust Managers, create a list of allocation IDs + ciphertrust_manager_eip_allocation_ids = var.use_eip_pool && var.enable_ciphertrust ? [ + for i in range(var.ciphertrust_manager_count) : + local.eip_pool_all_allocation_ids[local.ciphertrust_manager_eip_start_index + i] + ] : [] + + # For CTE/DDC agents, create a map of allocation IDs keyed by agent ID + # This matches the structure of local.all_agent_instances_map from cte_ddc_agents.tf + cte_agent_eip_allocation_ids = var.use_eip_pool && var.enable_ciphertrust ? { + for idx, instance_id in keys(local.all_agent_instances_map) : + instance_id => local.eip_pool_all_allocation_ids[local.cte_agent_eip_start_index + idx] + } : {} +} + +# Validation check +resource "null_resource" "eip_pool_validation" { + count = var.use_eip_pool ? 1 : 0 + + lifecycle { + precondition { + condition = local.eip_pool_valid + error_message = <" +EOF +} + +variable "eip_pool_tag" { + type = string + default = "dsf-eip-pool" + description = < 0 ? aws_eip.dsf_instance_eip[0].public_ip : null) : - aws_instance.cipthertrust_manager_instance.public_ip) - public_dns = (var.attach_persistent_public_ip ? - (length(aws_eip.dsf_instance_eip) > 0 ? aws_eip.dsf_instance_eip[0].public_dns : null) : - aws_instance.cipthertrust_manager_instance.public_dns) + # Determine public IP/DNS based on whether using existing EIP or created EIP + public_ip = var.attach_persistent_public_ip ? ( + var.eip_allocation_id != null ? + data.aws_eip.existing[0].public_ip : # From existing EIP + (length(aws_eip.dsf_instance_eip) > 0 ? aws_eip.dsf_instance_eip[0].public_ip : null) # From created EIP + ) : aws_instance.cipthertrust_manager_instance.public_ip + + public_dns = var.attach_persistent_public_ip ? ( + var.eip_allocation_id != null ? + data.aws_eip.existing[0].public_dns : + (length(aws_eip.dsf_instance_eip) > 0 ? aws_eip.dsf_instance_eip[0].public_dns : null) + ) : aws_instance.cipthertrust_manager_instance.public_dns + private_ip = length(aws_network_interface.eni.private_ips) > 0 ? tolist(aws_network_interface.eni.private_ips)[0] : null cm_address = coalesce(local.public_ip, local.private_ip) + + # Determine which allocation ID to use + eip_allocation_id = var.attach_persistent_public_ip ? ( + var.eip_allocation_id != null ? + var.eip_allocation_id : # Use provided allocation ID + aws_eip.dsf_instance_eip[0].id # Use created EIP + ) : null +} + +# Data source to lookup existing EIP (when allocation ID provided) +data "aws_eip" "existing" { + count = var.attach_persistent_public_ip && var.eip_allocation_id != null ? 1 : 0 + id = var.eip_allocation_id } +# Create new EIP (only when allocation ID NOT provided) resource "aws_eip" "dsf_instance_eip" { - count = var.attach_persistent_public_ip ? 1 : 0 + count = var.attach_persistent_public_ip && var.eip_allocation_id == null ? 1 : 0 domain = "vpc" tags = merge(var.tags, { Name = var.friendly_name }) } @@ -26,7 +47,7 @@ resource "aws_eip" "dsf_instance_eip" { resource "aws_eip_association" "eip_assoc" { count = var.attach_persistent_public_ip ? 1 : 0 instance_id = aws_instance.cipthertrust_manager_instance.id - allocation_id = aws_eip.dsf_instance_eip[0].id + allocation_id = local.eip_allocation_id } resource "aws_instance" "cipthertrust_manager_instance" { diff --git a/modules/aws/ciphertrust-manager/variables.tf b/modules/aws/ciphertrust-manager/variables.tf index 747894da..38daf53f 100644 --- a/modules/aws/ciphertrust-manager/variables.tf +++ b/modules/aws/ciphertrust-manager/variables.tf @@ -158,6 +158,22 @@ variable "attach_persistent_public_ip" { description = "Create public elastic IP for the instance" } +variable "eip_allocation_id" { + type = string + default = null + description = < 0 ? tolist(aws_network_interface.eni.private_ips)[0] : null instance_address = var.use_public_ip ? local.public_ip : local.private_ip @@ -27,10 +38,24 @@ locals { target_platform = var.os_type == "Windows" ? "windows" : null dummy_file_path = "${path.module}/dummy.txt" + + # Determine which allocation ID to use + eip_allocation_id = var.attach_persistent_public_ip ? ( + var.eip_allocation_id != null ? + var.eip_allocation_id : # Use provided allocation ID + aws_eip.dsf_instance_eip[0].id # Use created EIP + ) : null +} + +# Data source to lookup existing EIP (when allocation ID provided) +data "aws_eip" "existing" { + count = var.attach_persistent_public_ip && var.eip_allocation_id != null ? 1 : 0 + id = var.eip_allocation_id } +# Create new EIP (only when allocation ID NOT provided) resource "aws_eip" "dsf_instance_eip" { - count = var.attach_persistent_public_ip ? 1 : 0 + count = var.attach_persistent_public_ip && var.eip_allocation_id == null ? 1 : 0 domain = "vpc" tags = merge(var.tags, { Name = var.friendly_name }) } @@ -38,7 +63,7 @@ resource "aws_eip" "dsf_instance_eip" { resource "aws_eip_association" "eip_assoc" { count = var.attach_persistent_public_ip ? 1 : 0 instance_id = aws_instance.cte_ddc_agent.id - allocation_id = aws_eip.dsf_instance_eip[0].id + allocation_id = local.eip_allocation_id } resource "aws_network_interface" "eni" { diff --git a/modules/aws/cte-ddc-agent/variables.tf b/modules/aws/cte-ddc-agent/variables.tf index a76c6dab..de68bd33 100644 --- a/modules/aws/cte-ddc-agent/variables.tf +++ b/modules/aws/cte-ddc-agent/variables.tf @@ -46,6 +46,22 @@ variable "security_group_ids" { default = [] } +variable "eip_allocation_id" { + type = string + default = null + description = < 0 ? tolist(aws_network_interface.eni.private_ips)[0] : null security_group_ids = concat( @@ -23,10 +34,24 @@ locals { agent-gw = "gateway" } } + + # Determine which allocation ID to use + eip_allocation_id = var.attach_persistent_public_ip ? ( + var.eip_allocation_id != null ? + var.eip_allocation_id : # Use provided allocation ID + aws_eip.dsf_instance_eip[0].id # Use created EIP + ) : null +} + +# Data source to lookup existing EIP (when allocation ID provided) +data "aws_eip" "existing" { + count = var.attach_persistent_public_ip && var.eip_allocation_id != null ? 1 : 0 + id = var.eip_allocation_id } +# Create new EIP (only when allocation ID NOT provided) resource "aws_eip" "dsf_instance_eip" { - count = var.attach_persistent_public_ip ? 1 : 0 + count = var.attach_persistent_public_ip && var.eip_allocation_id == null ? 1 : 0 domain = "vpc" tags = merge(var.tags, { Name = var.name }) } @@ -34,7 +59,7 @@ resource "aws_eip" "dsf_instance_eip" { resource "aws_eip_association" "eip_assoc" { count = var.attach_persistent_public_ip ? 1 : 0 instance_id = aws_instance.dsf_base_instance.id - allocation_id = aws_eip.dsf_instance_eip[0].id + allocation_id = local.eip_allocation_id } resource "aws_instance" "dsf_base_instance" { diff --git a/modules/aws/dam-base-instance/variables.tf b/modules/aws/dam-base-instance/variables.tf index 560a01d8..48b379e5 100644 --- a/modules/aws/dam-base-instance/variables.tf +++ b/modules/aws/dam-base-instance/variables.tf @@ -42,6 +42,22 @@ variable "attach_persistent_public_ip" { description = "Create and attach elastic public IP for the instance" } +variable "eip_allocation_id" { + type = string + default = null + description = < 0 ? tolist(aws_network_interface.eni.private_ips)[0] : null security_group_ids = concat( @@ -16,10 +27,24 @@ locals { readiness_script = templatefile("${path.module}/readiness.tftpl", { admin_server_public_ip = try(local.public_ip, local.private_ip) }) + + # Determine which allocation ID to use + eip_allocation_id = var.attach_persistent_public_ip ? ( + var.eip_allocation_id != null ? + var.eip_allocation_id : # Use provided allocation ID + aws_eip.dsf_instance_eip[0].id # Use created EIP + ) : null +} + +# Data source to lookup existing EIP (when allocation ID provided) +data "aws_eip" "existing" { + count = var.attach_persistent_public_ip && var.eip_allocation_id != null ? 1 : 0 + id = var.eip_allocation_id } +# Create new EIP (only when allocation ID NOT provided) resource "aws_eip" "dsf_instance_eip" { - count = var.attach_persistent_public_ip ? 1 : 0 + count = var.attach_persistent_public_ip && var.eip_allocation_id == null ? 1 : 0 domain = "vpc" tags = merge(var.tags, { Name = var.name }) } @@ -27,7 +52,7 @@ resource "aws_eip" "dsf_instance_eip" { resource "aws_eip_association" "eip_assoc" { count = var.attach_persistent_public_ip ? 1 : 0 instance_id = aws_instance.dsf_base_instance.id - allocation_id = aws_eip.dsf_instance_eip[0].id + allocation_id = local.eip_allocation_id } resource "aws_instance" "dsf_base_instance" { diff --git a/modules/aws/dra-admin/variables.tf b/modules/aws/dra-admin/variables.tf index cfae03e9..dbb1bfe6 100644 --- a/modules/aws/dra-admin/variables.tf +++ b/modules/aws/dra-admin/variables.tf @@ -169,6 +169,22 @@ variable "allowed_all_cidrs" { default = [] } +variable "eip_allocation_id" { + type = string + default = null + description = < 0 ? tolist(aws_network_interface.eni.private_ips)[0] : null # root volume details @@ -22,10 +33,24 @@ locals { # If the binaries_location.s3_key is "file.zip", then the installation_s3_prefix will be null installation_s3_prefix = try(regex("^(.*)/[^/]+", var.binaries_location.s3_key)[0], null) installation_s3_bucket_and_prefix = local.installation_s3_prefix != null ? join("/", [var.binaries_location.s3_bucket, local.installation_s3_prefix]) : var.binaries_location.s3_bucket + + # Determine which allocation ID to use + eip_allocation_id = var.attach_persistent_public_ip ? ( + var.eip_allocation_id != null ? + var.eip_allocation_id : # Use provided allocation ID + aws_eip.dsf_instance_eip[0].id # Use created EIP + ) : null +} + +# Data source to lookup existing EIP (when allocation ID provided) +data "aws_eip" "existing" { + count = var.attach_persistent_public_ip && var.eip_allocation_id != null ? 1 : 0 + id = var.eip_allocation_id } +# Create new EIP (only when allocation ID NOT provided) resource "aws_eip" "dsf_instance_eip" { - count = var.attach_persistent_public_ip ? 1 : 0 + count = var.attach_persistent_public_ip && var.eip_allocation_id == null ? 1 : 0 domain = "vpc" tags = merge(var.tags, { Name = var.name }) } @@ -33,7 +58,7 @@ resource "aws_eip" "dsf_instance_eip" { resource "aws_eip_association" "eip_assoc" { count = var.attach_persistent_public_ip ? 1 : 0 instance_id = aws_instance.dsf_base_instance.id - allocation_id = aws_eip.dsf_instance_eip[0].id + allocation_id = local.eip_allocation_id } resource "aws_instance" "dsf_base_instance" { diff --git a/modules/aws/sonar-base-instance/variables.tf b/modules/aws/sonar-base-instance/variables.tf index b96da1ce..b3a2ccca 100644 --- a/modules/aws/sonar-base-instance/variables.tf +++ b/modules/aws/sonar-base-instance/variables.tf @@ -47,6 +47,22 @@ variable "attach_persistent_public_ip" { description = "Create and attach elastic public IP for the instance" } +variable "eip_allocation_id" { + type = string + default = null + description = < Date: Mon, 2 Feb 2026 09:44:16 +0200 Subject: [PATCH 2/2] feat: add support for Elastic IP pool in AWS deployments --- README.md | 9 +++++++++ examples/aws/poc/dsf_deployment/README.md | 2 ++ 2 files changed, 11 insertions(+) diff --git a/README.md b/README.md index 447f89ac..f47ca4ff 100644 --- a/README.md +++ b/README.md @@ -633,6 +633,15 @@ The following table lists the _latest_ DSF Kit releases, their release date and 2. Improvements and bug fixes. + + TBD + + 1.7.35 + + 1. Added support for Elastic IP (EIP) pool for AWS deployments. Set 'use_eip_pool' to true and specify 'eip_pool_tag' to use pre-allocated EIPs with predictable IP addresses. +
2. Improvements and bug fixes. + + diff --git a/examples/aws/poc/dsf_deployment/README.md b/examples/aws/poc/dsf_deployment/README.md index 17cf71f1..0b786661 100644 --- a/examples/aws/poc/dsf_deployment/README.md +++ b/examples/aws/poc/dsf_deployment/README.md @@ -108,6 +108,8 @@ Several variables in the `variables.tf` file are important for configuring the d ### Networking - `subnet_ids`: IDs of the subnets for the deployment. If not specified, a new vpc is created. +- `use_eip_pool`: Set to `true` to use pre-allocated Elastic IPs from a pool instead of creating new ones. Default: `false` +- `eip_pool_tag`: AWS tag value to identify the EIP pool (e.g., `dsf-eip-pool`). Only used when `use_eip_pool = true`. EIPs must be tagged with `Pool=` in AWS before deployment. ### Audit Sources for Simulation Purposes - `simulation_db_types_for_agentless`: Types of databases to provision and onboard to an Agentless Gateway