Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🔴 F5 BIG-IP LTM Cookie Persistence Profile Terraform Module

terraform-bigip-ltm-persistence-profile-cookie manages a single bigip_ltm_persistence_profile_cookie resource against the F5Networks/bigip Terraform provider ~> 1.28 (TMOS >= v12.1.1).

Terraform Provider Module Version Module Type Resources


🧩 Overview

  • Configures a BIG-IP LTM cookie persistence profile (bigip_ltm_persistence_profile_cookie) — the object a virtual server references to keep a client's requests pinned to the same pool member by inserting, rewriting, or hashing an HTTP cookie.
  • Exposes the full 1:1 provider argument set (17 scalar arguments) with no house-invented renames — field names, optionality, and types mirror the live provider schema exactly, including app_service, an argument present in the live schema but missing from the rendered Terraform Registry Argument Reference page (see "Schema notes that bite" below).
  • Emits name (full path) and id for consumption by terraform-bigip-ltm-virtual-server's persistence-profile input, or by another terraform-bigip-ltm-persistence-profile-cookie instance's defaults_from.

💡 Why it matters: Cookie persistence is what lets a stateful application (shopping cart, authenticated session, in-memory session data on one specific app server) survive across multiple requests from the same client without requiring shared session storage on the backend. Because this profile is referenced by full path from every virtual server that uses it, one profile instance is frequently shared across many applications — get the cookie name, expiration, and encryption policy right once, and every consuming virtual server inherits them consistently.


❤️ Support this project

If these Terraform modules have been helpful to you or your organization, I'd appreciate your support in any of the following ways:

Whether it's a star, a professional connection, or a coffee, every gesture helps keep these modules actively maintained and continually improving. Thank you for being part of the community!


🗺️ Where this fits

graph LR
 COOKIE["terraform-bigip-ltm-persistence-profile-cookie"]:::this
 VS["terraform-bigip-ltm-virtual-server"]:::keystone
 SRCADDR["terraform-bigip-ltm-persistence-profile-srcaddr"]:::sibling
 DSTADDR["terraform-bigip-ltm-persistence-profile-dstaddr"]:::sibling
 SSLP["terraform-bigip-ltm-persistence-profile-ssl"]:::sibling
 HTTP["terraform-bigip-ltm-profile-http"]:::sibling
 CSSL["terraform-bigip-ltm-profile-client-ssl"]:::sibling
 MON["terraform-bigip-ltm-monitor"]:::sibling
 POOL["terraform-bigip-ltm-pool"]:::sibling
 COMMON["/Common/cookie built-in profile"]:::external

 COOKIE -->|"persistence-profile full-path reference"| VS
 SRCADDR -->|"persistence-profile full-path reference"| VS
 DSTADDR -->|"persistence-profile full-path reference"| VS
 SSLP -->|"persistence-profile full-path reference"| VS
 HTTP -->|"profile_names full-path reference"| VS
 CSSL -->|"profile_names full-path reference"| VS
 MON -->|"monitors full-path reference"| POOL
 POOL -->|"pool full-path reference"| VS
 COMMON -->|"defaults_from optional inheritance"| COOKIE

 classDef this fill:#E4002B,color:#ffffff,stroke:#333333;
 classDef keystone fill:#000000,color:#ffffff,stroke:#333333;
 classDef sibling fill:#D9D9D9,color:#000000,stroke:#333333;
 classDef external fill:#EFEFEF,color:#000000,stroke:#333333,stroke-dasharray: 3 3;
Loading

This module (terraform-bigip-ltm-persistence-profile-cookie, red) sits alongside the rest of the LTM Persistence Profiles family (_srcaddr, _dstaddr, _ssl) as a sibling input consumed by full-path name into terraform-bigip-ltm-virtual-server (black), the same way an HTTP or client-SSL profile is consumed. defaults_from optionally points at either BIG-IP's built-in /Common/cookie profile or another instance of this same module.


🧬 What this builds

graph TD
 subgraph Inputs["Inputs"]
 NAME["var.name required"]
 DEFAULTS["var.defaults_from required"]
 CORE["core cookie and match settings 12 scalar vars"]
 SECRET["var.cookie_encryption_passphrase sensitive"]
 APPSVC["var.app_service optional"]
 end

 RES["bigip_ltm_persistence_profile_cookie.this"]:::keystone

 NAME --> RES
 DEFAULTS --> RES
 CORE --> RES
 SECRET -->|"lifecycle ignore_changes"| RES
 APPSVC --> RES

 RES --> OUT_NAME["output: name"]
 RES --> OUT_ID["output: id"]

 classDef keystone fill:#000000,color:#ffffff,stroke:#333333;
Loading

Resource inventory

Resource / block Count Notes
bigip_ltm_persistence_profile_cookie.this 1 (keystone) The cookie persistence profile itself — the module's only Terraform resource.
lifecycle.ignore_changes 1 static block Pinned to [cookie_encryption_passphrase] — suppresses the perpetual diff BIG-IP's server-side re-encryption of this field would otherwise produce on every plan.

No for_each-keyed child collections and no dynamic blocks exist: every argument on bigip_ltm_persistence_profile_cookie is a flat scalar in the live provider schema, so main.tf is a single resource block, not a composite renderer.


✅ Provider / Versions

Requirement Value
Terraform >= 1.12.0
Provider F5Networks/bigip ~> 1.28 — re-verify this pin against the current Terraform Registry listing before each new module wave
Provider block None — the caller's root module configures address/username/password/token_value
BIG-IP / TMOS floor >= v12.1.1 (provider floor; no AWAF/ASM version gate applies to this resource family)

Schema notes that bite

  • name is the full path (/Partition/name) and is the effective primary key — renaming it or moving it between partitions is a destroy/recreate operation, not an in-place update.
  • app_service is present in the live provider schema but absent from the rendered Terraform Registry Argument Reference page for this resource — added here from the schema fallback, described consistently with the same attribute on terraform-bigip-ltm-profile-http and terraform-bigip-net-ike-peer.
  • The rendered doc's name description ("Name of the virtual address") is a copy/paste artifact from an unrelated resource's doc page — the live schema's own description ("Name of the persistence profile") is used in this module instead.
  • The rendered doc's timeout entry is prefixed "(enabled or disabled)" even though the field is a numeric second count (the doc's own Example Usage sets timeout = 3600, and the live schema types it number) — that parenthetical is a copy/paste artifact from the surrounding enabled/disabled fields; this module types timeout as number.
  • cookie_encryption_passphrase is re-encrypted server-side and always returns a different value than what was set — main.tf carries a static lifecycle { ignore_changes = [cookie_encryption_passphrase] } to suppress the resulting perpetual diff, matching the provider's own documented Example Usage for this resource.
  • method's accepted values are not a verifiable closed set — the provider documents a default of "insert" but never enumerates a complete allow-list in either the rendered doc or the live schema, so this module deliberately does not enforce a validation{} block against it.
  • Every other optional field (match_across_pools, match_across_services, match_across_virtuals, mirror, override_conn_limit, timeout, always_send, cookie_name, expiration, hash_length, hash_offset) is Optional+Computed with no literal provider-side default documented anywhere — left null in this module so the defaults_from parent profile's own value applies, rather than this module inventing a value the provider itself does not commit to.

🔑 Required BIG-IP User Role / Partition Access

Manager role scoped to the target partition is sufficient; Administrator is not required for this application-layer LTM object.


🖥️ F5 BIG-IP Prerequisites

  • iControl REST enabled and reachable on the target device.
  • TMOS >= v12.1.1 (provider floor).
  • Target partition must already exist — this module never creates a partition.
  • The parent cookie persistence profile named in defaults_from (e.g. /Common/cookie) must already exist on the device before this module applies.

📁 Module Structure

terraform-bigip-ltm-persistence-profile-cookie/
├── providers.tf # Terraform + F5Networks/bigip ~> 1.28 requirement — no provider {} block
├── variables.tf # 1:1-mapped bigip_ltm_persistence_profile_cookie input schema
├── main.tf # bigip_ltm_persistence_profile_cookie.this + lifecycle.ignore_changes
├── outputs.tf # name (first), id
├── SCOPE.md # cross-module contract (this module's consumes/emits + role/prereqs)
└── README.md # this file

⚙️ Quick Start

# Root module — caller configures the provider; never inside this module.
provider "bigip" {
  address  = var.bigip_address
  username = var.bigip_username
  password = var.bigip_password
}

module "cookie_persistence" {
  source = "git::https://github.com/microsoftexpert/terraform-bigip-ltm-persistence-profile-cookie.git?ref=v1.0.0"

  name          = "/Common/my-cookie-persistence"
  defaults_from = "/Common/cookie"
}

name and defaults_from are the only two required inputs — every other field defers to the defaults_from parent profile's own value when left unset.


🔌 Cross-Module Contract

Consumes

Input Type Source module
defaults_from string (full path) Another terraform-bigip-ltm-persistence-profile-cookie instance, or BIG-IP's built-in /Common/cookie
cookie_encryption_passphrase (optional, sensitive) string Out-of-band secret store (Terraform Cloud/Vault-sourced variable) — never a sibling module output

Emits

Output Description Consumed by
name Full-path name (/Partition/name) of the cookie persistence profile — the practical cross-reference key terraform-bigip-ltm-virtual-server's persistence-profile input
id Provider-internal id — identical value to name for this resource (no separate numeric id) Rarely consumed directly; diagnostics only

📚 Example Library

1 · Minimal profile inheriting from the built-in parent
module "cookie_persistence" {
  source = "git::https://github.com/microsoftexpert/terraform-bigip-ltm-persistence-profile-cookie.git?ref=v1.0.0"

  name          = "/Common/app01-cookie-persistence"
  defaults_from = "/Common/cookie"
}

ℹ️ Every field besides name/defaults_from is left null (the module default), so the /Common/cookie parent profile's own values apply.

2 · Named cookie with an explicit expiration
module "cookie_persistence" {
  source = "git::https://github.com/microsoftexpert/terraform-bigip-ltm-persistence-profile-cookie.git?ref=v1.0.0"

  name          = "/Common/app01-session-cookie"
  defaults_from = "/Common/cookie"
  cookie_name   = "APP01SESSIONID"
  expiration    = "1:0:0:0"
}

💡 expiration uses BIG-IP's DAY:HOUR:MIN:SECONDS format — "1:0:0:0" is one day.

3 · Explicit insert-mode cookie processing
module "cookie_persistence" {
  source = "git::https://github.com/microsoftexpert/terraform-bigip-ltm-persistence-profile-cookie.git?ref=v1.0.0"

  name          = "/Common/app02-cookie-persistence"
  defaults_from = "/Common/cookie"
  method        = "insert"
}

ℹ️ method has no validation{} allow-list in this module — the provider's own documentation does not enumerate a complete, verifiable accepted-value set. Pass the literal value your BIG-IP version expects.

4 · Encrypted cookie with an out-of-band passphrase
variable "cookie_persistence_passphrase" {
  type      = string
  sensitive = true
}

module "cookie_persistence" {
  source = "git::https://github.com/microsoftexpert/terraform-bigip-ltm-persistence-profile-cookie.git?ref=v1.0.0"

  name                         = "/Common/app03-encrypted-cookie-persistence"
  defaults_from                = "/Common/cookie"
  cookie_encryption            = "required"
  cookie_encryption_passphrase = var.cookie_persistence_passphrase
}

🔒 cookie_encryption_passphrase must come from an out-of-band secret store (Terraform Cloud workspace variable, Vault-sourced input) — never a literal in version control. Expect the plan to otherwise show a perpetual diff on this field; main.tf's lifecycle.ignore_changes suppresses it.

5 · Preferred (not mandatory) cookie encryption
module "cookie_persistence" {
  source = "git::https://github.com/microsoftexpert/terraform-bigip-ltm-persistence-profile-cookie.git?ref=v1.0.0"

  name              = "/Common/app04-cookie-persistence"
  defaults_from     = "/Common/cookie"
  cookie_encryption = "preferred"
}
6 · Matching persistence across every pool behind a virtual server
module "cookie_persistence" {
  source = "git::https://github.com/microsoftexpert/terraform-bigip-ltm-persistence-profile-cookie.git?ref=v1.0.0"

  name               = "/Common/multi-pool-cookie-persistence"
  defaults_from      = "/Common/cookie"
  match_across_pools = "enabled"
}

⚠️ Enabling match_across_pools changes failover behavior for persisted clients — confirm the application team expects a client's session to follow it across pools before enabling.

7 · Mirroring persistence records to the HA peer
module "cookie_persistence" {
  source = "git::https://github.com/microsoftexpert/terraform-bigip-ltm-persistence-profile-cookie.git?ref=v1.0.0"

  name          = "/Common/ha-mirrored-cookie-persistence"
  defaults_from = "/Common/cookie"
  mirror        = "enabled"
}
8 · Overriding pool member connection limits for persisted clients
module "cookie_persistence" {
  source = "git::https://github.com/microsoftexpert/terraform-bigip-ltm-persistence-profile-cookie.git?ref=v1.0.0"

  name                = "/Common/burst-tolerant-cookie-persistence"
  defaults_from       = "/Common/cookie"
  override_conn_limit = "enabled"
}

⚠️ Enabling override_conn_limit allows a persisted client to exceed a pool member's configured connection_limit — treat as a deliberate capacity decision, not a default to enable casually (this module suite's "Persistence / connection limits" secure-default guidance).

9 · Custom timeout and always-send cookie behavior
module "cookie_persistence" {
  source = "git::https://github.com/microsoftexpert/terraform-bigip-ltm-persistence-profile-cookie.git?ref=v1.0.0"

  name          = "/Common/app05-cookie-persistence"
  defaults_from = "/Common/cookie"
  timeout       = 3600
  always_send   = "enabled"
}

ℹ️ timeout is typed number in this module (seconds) — the rendered Terraform Registry doc page mislabels this field as "(enabled or disabled)"; see "Schema notes that bite" above.

10 · Hashing the cookie value
module "cookie_persistence" {
  source = "git::https://github.com/microsoftexpert/terraform-bigip-ltm-persistence-profile-cookie.git?ref=v1.0.0"

  name          = "/Common/hashed-cookie-persistence"
  defaults_from = "/Common/cookie"
  hash_length   = 8
  hash_offset   = 0
}
11 · HttpOnly cookie to block client-side script access
module "cookie_persistence" {
  source = "git::https://github.com/microsoftexpert/terraform-bigip-ltm-persistence-profile-cookie.git?ref=v1.0.0"

  name          = "/Common/httponly-cookie-persistence"
  defaults_from = "/Common/cookie"
  httponly      = "enabled"
}
12 · Matching persistence across services and virtuals sharing a destination
module "cookie_persistence" {
  source = "git::https://github.com/microsoftexpert/terraform-bigip-ltm-persistence-profile-cookie.git?ref=v1.0.0"

  name                  = "/Common/shared-destination-cookie-persistence"
  defaults_from         = "/Common/cookie"
  match_across_services = "enabled"
  match_across_virtuals = "enabled"
}
13 · iApp-managed profile via app_service
module "cookie_persistence" {
  source = "git::https://github.com/microsoftexpert/terraform-bigip-ltm-persistence-profile-cookie.git?ref=v1.0.0"

  name          = "/Common/iapp-managed-cookie-persistence"
  defaults_from = "/Common/cookie"
  app_service   = "/Common/my-iapp.app/my-iapp"
}

ℹ️ app_service is present in the live provider schema but omitted from the rendered Terraform Registry Argument Reference for this resource — see "Schema notes that bite" above.

14 · Partition-scoped profile for a dedicated tenant
module "cookie_persistence" {
  source = "git::https://github.com/microsoftexpert/terraform-bigip-ltm-persistence-profile-cookie.git?ref=v1.0.0"

  name          = "/Tenant-A/tenant-a-cookie-persistence"
  defaults_from = "/Common/cookie"
}

ℹ️ Partition is encoded in name's full path (/Tenant-A/...) — house convention, not a provider requirement. The target partition (/Tenant-A) must already exist before this module runs.

15 · 🏗️ End-to-end composition — cookie persistence + HTTP profile + pool + virtual server
module "http_monitor" {
  source = "git::https://github.com/microsoftexpert/terraform-bigip-ltm-monitor.git?ref=v1.0.0"

  name = "/Common/app01-http-monitor"
  #... monitor-specific arguments
}

module "http_profile" {
  source = "git::https://github.com/microsoftexpert/terraform-bigip-ltm-profile-http.git?ref=v1.0.0"

  name = "/Common/app01-http"
}

module "cookie_persistence" {
  source = "git::https://github.com/microsoftexpert/terraform-bigip-ltm-persistence-profile-cookie.git?ref=v1.0.0"

  name          = "/Common/app01-cookie-persistence"
  defaults_from = "/Common/cookie"
  cookie_name   = "APP01SESSIONID"
  expiration    = "1:0:0:0"
}

module "app01_pool" {
  source = "git::https://github.com/microsoftexpert/terraform-bigip-ltm-pool.git?ref=v1.0.0"

  name     = "/Common/app01-pool"
  monitors = [module.http_monitor.name]
  members = {
    "10.10.1.11:8080" = { address = "10.10.1.11", port = 8080 }
    "10.10.1.12:8080" = { address = "10.10.1.12", port = 8080 }
  }
}

module "app01_virtual_server" {
  source = "git::https://github.com/microsoftexpert/terraform-bigip-ltm-virtual-server.git?ref=v1.0.0"

  name                = "/Common/app01-vs"
  destination         = "10.20.30.40"
  port                = 443
  pool                = module.app01_pool.name
  profile_names       = [module.http_profile.name]
  persistence_profile = module.cookie_persistence.name
}

💡 Record ordering matters here purely through Terraform's own dependency graph: the monitor is referenced by name into the pool, and the pool, HTTP profile, and cookie persistence profile are all referenced by name into the virtual server — Terraform resolves the apply order automatically because each reference is a real module.<x>.name expression, not a hardcoded string repeated across modules.


📥 Inputs

Grouped summary

Name Type Default Required
name string yes
defaults_from string yes
match_across_pools string (enum) null (provider-computed) no
match_across_services string (enum) null (provider-computed) no
match_across_virtuals string (enum) null (provider-computed) no
mirror string (enum) null (provider-computed) no
override_conn_limit string (enum) null (provider-computed) no
timeout number null (provider-computed) no
always_send string (enum) null (provider-computed) no
method string null (provider-computed; documented default "insert") no
cookie_name string null (provider-computed) no
cookie_encryption string (enum) null (provider-computed) no
cookie_encryption_passphrase string, sensitive null no
expiration string null (provider-computed) no
hash_length number null (provider-computed) no
hash_offset number null (provider-computed) no
httponly string (enum) null (provider-computed) no
app_service string null no
Full variable declarations (closed-enum validation{} blocks)
variable "match_across_pools" {
  type    = string
  default = null
  # validation: contains(["enabled", "disabled"], var.match_across_pools)
}

variable "match_across_services" {
  type    = string
  default = null
  # validation: contains(["enabled", "disabled"], var.match_across_services)
}

variable "match_across_virtuals" {
  type    = string
  default = null
  # validation: contains(["enabled", "disabled"], var.match_across_virtuals)
}

variable "mirror" {
  type    = string
  default = null
  # validation: contains(["enabled", "disabled"], var.mirror)
}

variable "override_conn_limit" {
  type    = string
  default = null
  # validation: contains(["enabled", "disabled"], var.override_conn_limit)
}

variable "always_send" {
  type    = string
  default = null
  # validation: contains(["enabled", "disabled"], var.always_send)
}

variable "cookie_encryption" {
  type    = string
  default = null
  # validation: contains(["required", "preferred", "disabled"], var.cookie_encryption)
}

variable "httponly" {
  type    = string
  default = null
  # validation: contains(["enabled", "disabled"], var.httponly)
}

method intentionally carries no validation{} block — the provider documents a default of "insert" but never enumerates a complete, verifiable closed set of accepted values. All other scalar fields (timeout, cookie_name, cookie_encryption_passphrase [sensitive], expiration, hash_length, hash_offset, app_service) are plain typed string/number variables with no enum constraint.


🧾 Outputs

Output Description Sensitive
name Full-path name of the cookie persistence profile, e.g. /Common/my-cookie-persistence. Consumed by full-path name from terraform-bigip-ltm-virtual-server. no
id Provider-internal id of the cookie persistence profile — the same full-path value as name (no separate numeric identifier). no

No output is sensitive = true — the only sensitive input, cookie_encryption_passphrase, is never echoed back through an output.


🧠 Architecture Notes

  • Flat keystone, no children, no dynamic blocks. Every argument on bigip_ltm_persistence_profile_cookie is a flat scalar in the live provider schema — main.tf is a single resource block plus one static lifecycle block, with no for_each and no dynamic {} rendering.
  • lifecycle.ignore_changes on cookie_encryption_passphrase is load-bearing. Because BIG-IP re-encrypts this value server-side and always returns something different than what was set, omitting the ignore_changes entry would produce a perpetual diff on every terraform plan even when the caller-supplied passphrase hasn't changed.
  • method has no closed-set enforcement by design, not by omission. Unlike cookie_encryption, httponly, or the four match_across_*/mirror/override_conn_limit fields — all of which document a genuinely complete enum — method's only documented value is its default ("insert"), with no enumerated alternative set. Adding a validation{} allow-list here would risk rejecting a legitimate device-accepted value this module's authoring pass didn't discover.
  • Full-path identity drives ordering. This module's name output is consumed by terraform-bigip-ltm-virtual-server's persistence-profile input and by any other terraform-bigip-ltm-persistence-profile-cookie instance's defaults_from — Terraform's own dependency graph (via module.<this>.name references) enforces that this profile is created before anything that references it, with no explicit depends_on needed.
  • No for_each key-stability concern here. Because there are no child collections, the key-stability rules that matter for composite modules (e.g. keying pool members by ip:port) do not apply to this module.

🧱 Design Principles

Concern Secure default in this module Opt-out (caller must type extra)
Persistence / connection limits override_conn_limit defaults to null (provider-computed, i.e. inherits from defaults_from) rather than this module inventing an "enabled" default that would let persisted clients exceed a pool member's connection_limit Caller explicitly sets override_conn_limit = "enabled" to accept that risk
Secrets cookie_encryption_passphrase is sensitive = true and carries no literal default — it must be sourced from an out-of-band secret store, never hardcoded in a .tfvars file N/A — this is a hard rule, not a toggle
Partition scope No implicit partition default is invented; the module never defaults or infers a partition — partition is whatever the caller encodes in name's full path Caller sets a non-/Common full path in name explicitly for any tenant-scoped object
Cookie encryption policy cookie_encryption defaults to null (provider-computed, deferring to defaults_from) rather than this module silently forcing "required" or "disabled" Caller explicitly sets cookie_encryption = "required" or "preferred" to opt into encryption

Concerns from this module suite's house-wide secure-by-default table that do not apply to this resource (TLS certificate validation, virtual-server destination, AS3/DO declarations, monitor/health-check requirements) are omitted above — bigip_ltm_persistence_profile_cookie exposes none of those arguments.


🚀 Runbook

cd C:\GitHubCode\newf5modules\bigip\terraform-bigip-ltm-persistence-profile-cookie
terraform init -backend=false
terraform validate
terraform fmt -check

Pin consumption at ?ref=v1.0.0 in every caller until a new tagged release is validated:

source = "git::https://github.com/microsoftexpert/terraform-bigip-ltm-persistence-profile-cookie.git?ref=v1.0.0"

🧪 Testing

Offline proof gate (what this repo's CI can verify without a live BIG-IP):

  • terraform init -backend=false — resolves the F5Networks/bigip ~> 1.28 provider requirement.
  • terraform validate — confirms the eight closed-enum validation{} blocks (match_across_pools, match_across_services, match_across_virtuals, mirror, override_conn_limit, always_send, cookie_encryption, httponly) compile and reject out-of-set literals at plan time.
  • terraform fmt -check — confirms canonical formatting.

What only terraform plan/apply against a real device exercises:

  • Whether the target partition in name's full path actually exists on the device.
  • Whether defaults_from resolves to a parent profile that already exists on the device.
  • The device's own computed defaults for every field left null in this module (e.g. timeout, cookie_name, expiration) — these are provider/device behavior, not something validate can confirm offline.
  • The cookie_encryption_passphrase server-side re-encryption behavior that lifecycle.ignore_changes suppresses.
  • Whether an unvalidated method literal (e.g. a typo) is actually accepted by the target BIG-IP version — this module does not enforce an allow-list on method.

💬 Example Output

$ terraform apply

Terraform will perform the following actions:

 # module.cookie_persistence.bigip_ltm_persistence_profile_cookie.this will be created
 + resource "bigip_ltm_persistence_profile_cookie" "this" {
 + name = "/Common/app01-cookie-persistence"
 + defaults_from = "/Common/cookie"
 + cookie_name = "APP01SESSIONID"
 + expiration = "1:0:0:0"
 + id = (known after apply)
 }

Plan: 1 to add, 0 to change, 0 to destroy.

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

Outputs:

id = "/Common/app01-cookie-persistence"
name = "/Common/app01-cookie-persistence"

🔍 Troubleshooting

Symptom Cause Fix
terraform plan shows cookie_encryption_passphrase changing on every run despite no source change Known provider write-only/re-encryption field idempotency quirk Expected behavior; lifecycle.ignore_changes in main.tf already suppresses this — confirm the actual device-side value out of band rather than trusting the plan diff
Apply fails with a partition-not-found style error Target partition in name's full path (e.g. /Tenant-A/...) does not exist yet Create the partition first (via terraform-bigip-partition or an out-of-band step) — this module never creates one
Apply fails because defaults_from cannot be resolved The parent cookie persistence profile named in defaults_from (e.g. /Common/cookie) does not exist on the device Confirm the parent profile exists, or reference another terraform-bigip-ltm-persistence-profile-cookie instance's name output instead of a raw string
terraform validate fails on match_across_pools, mirror, cookie_encryption, httponly, or similar Value outside this module's closed-enum validation{} list Use one of the documented enabled/disabled (or cookie_encryption's required/preferred/disabled) values
BIG-IP rejects the applied method value at apply time even though terraform validate passed This module does not enforce a closed set on method — the provider itself has no complete documented enum Re-check clouddocs.f5.com or the device's own accepted values for the target TMOS version; correct the literal and re-apply
connection refused on port 443 during terraform apply Target is a single-NIC BIG-IP in a public cloud (AWS/Azure/GCP) reachable only on a non-443 management port Set port (or BIGIP_PORT) on the provider block in the root module — not a concern of this module
Virtual server doesn't pick up a persistence-behavior change after terraform apply here The consuming terraform-bigip-ltm-virtual-server call was not re-applied, or references a different full-path name Confirm the virtual server's persistence-profile input contains this module's exact name output and re-apply that module

🔗 Related Docs

  • F5Networks/bigip provider registry docs — bigip_ltm_persistence_profile_cookie resource (registry.terraform.io).
  • clouddocs.f5.com — LTM cookie persistence profile concepts (insert/rewrite/hash modes, encryption policy).
  • This module's SCOPE.md — cross-module contract, required role, and prerequisites.
  • Sibling: terraform-bigip-ltm-virtual-server — consumes this module's name output via its persistence-profile input.
  • Sibling family: terraform-bigip-ltm-persistence-profile-srcaddr, terraform-bigip-ltm-persistence-profile-dstaddr, terraform-bigip-ltm-persistence-profile-ssl.

Releases

Packages

Contributors

Languages