diff --git a/.gitignore b/.gitignore
index 8fffac4ae..e9851b0b7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -24,4 +24,12 @@ myip-default
__pycache__/
upgrade_status.json
.coverage
-
+.vscode/*
+*.log
+*.txt
+*.bin
+*.exe
+*.rpm
+examples/azure/poc/dsf_deployment/y/*
+*.msi
+*.tfstate*
\ No newline at end of file
diff --git a/README.md b/README.md
index 447f89ace..f47ca4ffa 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 17cf71f1e..5f84ee0a9 100644
--- a/examples/aws/poc/dsf_deployment/README.md
+++ b/examples/aws/poc/dsf_deployment/README.md
@@ -108,6 +108,15 @@ 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.
+
+> **EIP Pool — Fixed Slot Distribution**: The pool uses fixed slot positions to ensure IP stability:
+> - Slot 0: Hub Main, Slot 1: Hub DR, Slot 2: MX, Slot 3: DRA Admin, Slots 4+: CipherTrust Managers, then CTE/DDC Agents.
+> - Enabling/disabling modules (sonar, dam, dra) does **not** shift EIPs for other resources.
+> - The pool must contain enough EIPs to cover through the highest used slot (some lower slots may be unused).
+> - Changing `ciphertrust_manager_count` will shift agent EIP assignments; for full stability, supply specific `eip_allocation_id` values directly to each module.
+> - All pool EIPs must be unassociated before the first deployment. A validation check will warn if any pool EIPs are already associated to non-managed resources.
### Audit Sources for Simulation Purposes
- `simulation_db_types_for_agentless`: Types of databases to provision and onboard to an Agentless Gateway
diff --git a/examples/aws/poc/dsf_deployment/cm.tf b/examples/aws/poc/dsf_deployment/cm.tf
index f4425fc40..d0d6f349a 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 657f82aa4..8de17cce7 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 fd0672155..6daa7c565 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 cd6848526..4f371001d 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 000000000..914699fe5
--- /dev/null
+++ b/examples/aws/poc/dsf_deployment/eip_pool.tf
@@ -0,0 +1,162 @@
+# Query AWS for all EIPs in the pool (associated and unassociated)
+# We need ALL pool EIPs for distribution since on subsequent applies our own
+# associations make them "associated". The aws_eip_association resource is
+# idempotent - associating an EIP to the same instance it's already on is a no-op.
+data "aws_eips" "pool" {
+ count = var.use_eip_pool ? 1 : 0
+
+ filter {
+ name = "tag:Pool"
+ values = [var.eip_pool_tag]
+ }
+}
+
+# Query only UNASSOCIATED pool EIPs for validation purposes.
+# This catches user errors like tagging an EIP that's already in use by
+# a non-managed resource. On first deploy all pool EIPs should be unassociated.
+# On subsequent applies, pool EIPs associated to our instances are expected.
+data "aws_eips" "pool_available" {
+ count = var.use_eip_pool ? 1 : 0
+
+ filter {
+ name = "tag:Pool"
+ values = [var.eip_pool_tag]
+ }
+
+ filter {
+ name = "association-id"
+ values = [""] # Empty association-id means unassociated
+ }
+}
+
+# Create locals to distribute allocation IDs to resources
+locals {
+ # Get sorted list of ALL allocation IDs from pool.
+ # Sort ensures stable ordering across API calls - same EIP always gets same index.
+ eip_pool_all_allocation_ids = var.use_eip_pool ? sort(data.aws_eips.pool[0].allocation_ids) : []
+
+ # Count of unassociated EIPs in the pool (for validation)
+ eip_pool_available_count = var.use_eip_pool ? length(data.aws_eips.pool_available[0].allocation_ids) : 0
+
+ # Count of already-associated EIPs in the pool
+ eip_pool_associated_count = var.use_eip_pool ? (
+ length(local.eip_pool_all_allocation_ids) - local.eip_pool_available_count
+ ) : 0
+
+ # Total pool EIPs available
+ eip_pool_total_count = length(local.eip_pool_all_allocation_ids)
+
+ # ============================================================================
+ # Fixed slot positions for singleton resources
+ # These positions NEVER change regardless of which modules are enabled/disabled.
+ # This ensures that enabling/disabling sonar, dam, or dra does not shift the
+ # EIP assigned to other resources.
+ #
+ # Slot layout:
+ # 0: hub_main
+ # 1: hub_dr
+ # 2: mx
+ # 3: dra_admin
+ # 4+: ciphertrust_managers (up to ciphertrust_manager_count)
+ # 4+cm_count+: cte/ddc agents
+ #
+ # Trade-off: Some pool slots may be unused if a module is disabled, but
+ # positions are guaranteed stable across configuration changes.
+ #
+ # Note: Changing ciphertrust_manager_count will shift agent positions.
+ # This is acceptable as CM count changes are rare in practice.
+ # ============================================================================
+ hub_main_eip_index = 0
+ hub_dr_eip_index = 1
+ mx_eip_index = 2
+ dra_admin_eip_index = 3
+ ciphertrust_manager_eip_start_index = 4
+ cte_agent_eip_start_index = 4 + (var.enable_ciphertrust ? var.ciphertrust_manager_count : 0)
+
+ # Total agents count
+ total_agent_count = (
+ 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
+ )
+
+ # Calculate the highest slot index needed (for pool size validation)
+ # We use max() to find the highest slot that's actually in use
+ eip_pool_highest_slot = max(
+ var.enable_sonar ? local.hub_main_eip_index : -1,
+ var.enable_sonar && var.hub_hadr ? local.hub_dr_eip_index : -1,
+ var.enable_dam ? local.mx_eip_index : -1,
+ var.enable_dra ? local.dra_admin_eip_index : -1,
+ var.enable_ciphertrust && var.ciphertrust_manager_count > 0 ? (
+ local.ciphertrust_manager_eip_start_index + var.ciphertrust_manager_count - 1
+ ) : -1,
+ var.enable_ciphertrust && local.total_agent_count > 0 ? (
+ local.cte_agent_eip_start_index + local.total_agent_count - 1
+ ) : -1,
+ )
+
+ # Pool needs enough EIPs to cover through the highest used slot
+ eip_count_needed = local.eip_pool_highest_slot + 1
+
+ # Validate we have enough IPs
+ eip_pool_valid = !var.use_eip_pool || local.eip_pool_total_count >= local.eip_count_needed
+
+ # Assign specific allocation IDs to each resource using fixed slot positions
+ 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
+ # Sort keys to ensure stable ordering - same agent always gets same pool EIP
+ cte_agent_eip_allocation_ids = var.use_eip_pool && var.enable_ciphertrust ? {
+ for idx, instance_id in sort(keys(local.all_agent_instances_map)) :
+ instance_id => local.eip_pool_all_allocation_ids[local.cte_agent_eip_start_index + idx]
+ } : {}
+}
+
+# Validation checks
+resource "null_resource" "eip_pool_validation" {
+ count = var.use_eip_pool ? 1 : 0
+
+ lifecycle {
+ # Validate pool has enough EIPs for the fixed slot layout
+ 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 747894da5..38daf53fc 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/sg.tf b/modules/aws/cte-ddc-agent/sg.tf
index 2cbb730ea..98ba73ba9 100644
--- a/modules/aws/cte-ddc-agent/sg.tf
+++ b/modules/aws/cte-ddc-agent/sg.tf
@@ -38,7 +38,7 @@ data "aws_subnet" "subnet" {
resource "aws_security_group" "dsf_agent_sg" {
for_each = { for idx, config in local._security_groups_config : idx => config }
- name = join("-", [var.friendly_name, join("-", each.value.name)])
+ name_prefix = join("-", [var.friendly_name, join("-", each.value.name), ""])
vpc_id = data.aws_subnet.subnet.vpc_id
description = format("%s - %s ingress access", var.friendly_name, join(" ", each.value.name))
@@ -72,4 +72,8 @@ resource "aws_security_group" "dsf_agent_sg" {
}
tags = merge(var.tags, { Name = join("-", [var.friendly_name, join("-", each.value.name)]) })
-}
\ No newline at end of file
+
+ lifecycle {
+ create_before_destroy = true
+ }
+}
diff --git a/modules/aws/cte-ddc-agent/variables.tf b/modules/aws/cte-ddc-agent/variables.tf
index a76c6dab1..de68bd33a 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 560a01d8f..48b379e5d 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 cfae03e97..dbb1bfe65 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 b96da1ce2..b3a2cccaf 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 = <