Skip to content

Latest commit

Β 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ”΅ F5OS Logging Terraform Module

Manages remote logging configuration (f5os_logging) on an F5OS platform β€” VELOS chassis partition or rSeries appliance β€” targeting the F5Networks/f5os provider ~> 1.10 (verified against v1.12.0).

Terraform Provider Module Type Resources Posture


🧩 Overview

  • 🏷️ Manages exactly one f5os_logging resource β€” remote log server destinations, CA bundles for TLS validation, TLS certificate material, remote log forwarding to on-box files, and hostname inclusion in emitted log messages.
  • 🧱 Standalone module: single keystone resource named this, no children, no for_each inside the module boundary. servers, ca_bundles, remote_forwarding, and tls are Plugin-Framework nested Attributes on this one resource, not sibling resources β€” there is no genuine child collection to iterate over.
  • 🌐 Applies identically to a VELOS chassis partition or an rSeries appliance β€” the f5os_logging schema carries no platform-specific argument.
  • πŸ”’ tls.key is split into its own sensitive variable (tls_key) β€” Terraform cannot mark a single nested attribute of an object-typed variable sensitive, so the TLS private key never rides inside var.logging alongside non-secret fields.
  • 🚫 No dynamic blocks. The live schema models every nested collection as a Plugin-Framework Attribute, not a classic HCL block β€” servers/ca_bundles/remote_forwarding/tls are passed through as whole values via =, exactly like terraform-f5os-auth.

πŸ’‘ Why it matters: remote logging is the platform's own audit and troubleshooting trail β€” get server destinations, TLS validation, and forwarding right once, here, understanding that f5os_logging is a system-singleton resource (exactly one logging configuration per F5OS target) with no caller-assigned name to reference elsewhere.


❀️ 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
 LOGGING["terraform-f5os-logging"]:::this
 SNMP["terraform-f5os-snmp"]:::sibling
 QKVIEW["terraform-f5os-qkview"]:::sibling
 CONFIGBACKUP["terraform-f5os-config-backup"]:::sibling
 PLATFORM["F5OS platform (VELOS chassis partition or rSeries appliance)"]:::target

 LOGGING -->|"configured directly against"| PLATFORM
 SNMP -->|"configured directly against"| PLATFORM
 QKVIEW -->|"configured directly against"| PLATFORM
 CONFIGBACKUP -->|"configured directly against"| PLATFORM
 LOGGING -.->|"shares observability-diagnostics domain with"| SNMP
 LOGGING -.->|"shares observability-diagnostics domain with"| QKVIEW
 LOGGING -.->|"shares observability-diagnostics domain with"| CONFIGBACKUP

 classDef this fill:#E4002B,color:#ffffff,stroke:#8f0016,stroke-width:1px;
 classDef target fill:#1B2A4A,color:#ffffff,stroke:#0d1626,stroke-width:1px;
 classDef sibling fill:#E8E8E8,color:#1a1a1a,stroke:#b5b5b5,stroke-width:1px;
Loading

terraform-f5os-logging (red) sits in the "observability-diagnostics" domain alongside terraform-f5os-snmp, terraform-f5os-qkview, and terraform-f5os-config-backup (being authored in parallel). None of the four modules owns or references another's resource β€” each is an independent, platform-wide system setting configured directly against whichever VELOS chassis partition or rSeries appliance the in-scope f5os provider instance targets. The dotted edges indicate a shared conceptual domain in the module catalog, not a Terraform dependency.


🧬 What this builds

graph LR
 subgraph Inputs["Inputs"]
 VAR["var.logging { include_hostname, servers, ca_bundles, tls, remote_forwarding }"]
 VARKEY["var.tls_key (sensitive)"]
 end

 RES["f5os_logging.this"]:::this

 subgraph Outputs["Outputs"]
 OUT_ID["id"]
 OUT_HOST["include_hostname"]
 OUT_SERVERS["servers"]
 OUT_CA["ca_bundles"]
 OUT_RF["remote_forwarding"]
 OUT_TLS["tls_certificate"]
 end

 VAR -->|"include_hostname, servers, ca_bundles, remote_forwarding"| RES
 VARKEY -->|"tls.key"| RES
 RES -->|"exposes"| OUT_ID
 RES -->|"exposes"| OUT_HOST
 RES -->|"exposes"| OUT_SERVERS
 RES -->|"exposes"| OUT_CA
 RES -->|"exposes"| OUT_RF
 RES -->|"exposes"| OUT_TLS

 classDef this fill:#E4002B,color:#ffffff,stroke:#8f0016,stroke-width:1px;
Loading

Resource inventory

Resource Terraform address Cardinality
f5os_logging f5os_logging.this Exactly 1 per module call β€” one logging configuration per authenticated f5os provider target

βœ… Provider / Versions

Item Value
Terraform floor >= 1.12.0
Provider pin F5Networks/f5os ~> 1.10 β€” verified against the live Terraform Registry listing; terraform init resolved v1.12.0 during authoring, which satisfies this constraint
Provider block None in this module β€” the caller configures provider "f5os" {} once, in the root module, targeting a single already-authenticated VELOS chassis controller or rSeries appliance
Platform context Both β€” VELOS chassis partition and rSeries appliance. f5os_logging's schema carries no partition-specific or appliance-specific argument; behavior is identical on either target

Schema notes that bite (verified against the live f5os_logging Argument/Attributes Reference, provider_doc_id 12473306):

  • servers, ca_bundles, remote_forwarding, and tls are Plugin-Framework nested Attributes, not classic nested blocks. The schema marks them (Attributes List) / (Attributes) β€” assigned via = in HCL, not rendered with a dynamic block. This module passes each through with try(..., null), exactly like terraform-f5os-auth's remote_roles/password_policy.
  • tls.key is Required within tls, and is Sensitive per the schema β€” but it is intentionally not a field of var.logging.tls in this module. Terraform cannot mark a single nested attribute of an object-typed variable sensitive, so the key is split into its own top-level sensitive = true variable, tls_key, and stitched back into the resource's tls object in main.tf. Setting logging.tls without also supplying tls_key fails terraform validate via this module's own cross-field validation {} block β€” it never reaches apply.
  • servers[*].protocol is a genuinely closed enum β€” the schema states "(tcp or udp)" β€” enforced by this module's validation {} block. remote_forwarding.logs[*].facility is also genuinely closed β€” "(local0 or authpriv)" β€” and is separately enforced. Both use an explicit "or" in the provider's own text, distinguishing them from the fields below.
  • servers[*].logs[*].facility and both logs[*].severity fields (servers and remote_forwarding) are documented only with "e.g." example lists, not a stated exhaustive set ("e.g., local0, authpriv"; "e.g., debug, informational, notice, warning, error, critical, alert, emergency"). This module does not enforce a validation {} block against them β€” matching the precedent set by terraform-f5os-lag's mode/interval fields, which carry the same "e.g., not confirmed exhaustive" documentation pattern. remote_forwarding.logs[*].severity in particular carries no example list at all in the fetched docs.
  • servers[*].authentication reads as TCP-only in intent β€” "Whether authentication is enabled for TCP protocol" β€” but the provider's docs do not explicitly state that pairing it with protocol = "udp" is rejected. This module documents the relationship in variables.tf but does not enforce it with a validation {} block, since the constraint is inferred from field wording, not an explicit "required when"/"forbidden when" statement (contrast with terraform-f5os-lag's mode/interval, which the provider explicitly scopes to lag_type = "LACP").
  • servers[*].port has a documented range of 1-65535 β€” enforced by this module's validation {} block, the type system alone cannot express a numeric range.
  • No documented full-replace-on-update or destroy-safety NOTE is present in the fetched Attributes Reference for f5os_logging β€” unlike f5os_dns, whose docs explicitly state full-replace-on-update semantics and a destroy-is-state-only guarantee. This module does not assert or assume either behavior for f5os_logging; verify actual update/destroy semantics against a real terraform plan/apply before assuming parity with f5os_dns.
  • No name attribute. Like f5os_auth and f5os_dns, f5os_logging exposes only a computed id β€” "Unique identifier for the logging resource." There is no separate human-readable name.

πŸ”‘ Required F5OS User Role / Chassis Partition Access

Least-privilege role: operator, per the f5os_user resource's documented role set (role β€” "Specifies primary role assigned to the user (e.g., admin, operator, user)"). Logging configuration privilege scoped to the target chassis partition (VELOS) or the appliance itself (rSeries) is sufficient for routine remote-logging lifecycle operations; admin is not required. No role name beyond operator/admin/user is asserted here β€” those are the only values the provider's own documentation shows as examples. Confirm the live RBAC role catalog on the target platform before granting access, since it may differ per F5OS release.

F5OS Prerequisites

  • F5OS provider F5Networks/f5os ~> 1.10; Terraform >= 1.12.0.
  • Applies to both platform contexts β€” no partition or appliance-specific prerequisite exists for f5os_logging itself.
  • No F5OS release-specific minimum version is called out in the fetched provider documentation for this resource β€” confirm against the target device's running F5OS release notes if a specific minimum matters for your deployment.
  • If logging.tls is set, tls_key must be supplied out of band (secret manager / CI-injected sensitive variable) β€” never a literal in a committed .tfvars file.
  • No image, VLAN, chassis partition, or tenant needs to be staged before this module β€” logging is a platform-level system setting with no dependency on any other F5OS object in this catalog.
  • The single, already-authenticated f5os provider instance in scope must target the chassis partition or appliance whose logging configuration should be managed.

πŸ“ Module Structure

terraform-f5os-logging/
β”œβ”€β”€ providers.tf # required_version, F5Networks/f5os ~> 1.10 β€” no provider {} block
β”œβ”€β”€ variables.tf # var.logging { include_hostname, servers, ca_bundles, tls, remote_forwarding }
β”‚ # + var.tls_key (sensitive) β€” 1:1 mapped to the real f5os_logging schema
β”œβ”€β”€ main.tf # f5os_logging.this β€” the module's single keystone resource
β”œβ”€β”€ outputs.tf # id, include_hostname, servers, ca_bundles, remote_forwarding, tls_certificate
β”œβ”€β”€ SCOPE.md # lightweight standalone contract β€” RBAC, prerequisites, emits, gotchas
└── README.md # this file β€” worked example configurations live in πŸ“š Example Library below

No separate examples/ directory ships with this module β€” every worked configuration is captured inline in the πŸ“š Example Library below, using the module's real variable names.


βš™οΈ Quick Start

# The caller configures the provider once, elsewhere in the root module:
# provider "f5os" {
# host = var.f5os_host
# username = var.f5os_username
# password = var.f5os_password
# }

module "logging" {
  source = "git::https://github.com/microsoftexpert/terraform-f5os-logging.git?ref=v1.0.0"

  logging = {
    servers = [
      {
        address  = "10.10.0.100"
        port     = 514
        protocol = "udp"
      }
    ]
  }
}

πŸ”Œ Cross-Module Contract

Consumes

Input Type Source module
β€” β€” None. This is a leaf module in the F5OS catalog; it has no upstream dependency on another terraform-f5os-* module's output.

Emits

Output Description Consumed by
id Synthetic identifier for the f5os_logging resource; system-singleton, not a per-instance value Informational / import use β€” not typically referenced by sibling modules
include_hostname Whether the device hostname is included in emitted log messages, if set Informational; no documented sibling-module argument currently references it
servers The configured list of remote logging servers, if any Informational; no documented sibling-module argument currently references it
ca_bundles The configured list of CA bundles for TLS validation, if any Informational; no documented sibling-module argument currently references it
remote_forwarding The configured remote forwarding configuration, if set Informational; no documented sibling-module argument currently references it
tls_certificate The configured TLS certificate for secure logging, if logging.tls was set Informational; no documented sibling-module argument currently references it

πŸ“š Example Library

1 Β· Minimal / empty logging (safe no-op default)

Every field in the provider's schema is Optional β€” an empty call is valid and configures no remote logging destination.

module "logging_empty" {
  source = "git::https://github.com/microsoftexpert/terraform-f5os-logging.git?ref=v1.0.0"

  # logging intentionally omitted β€” defaults to {}
}

πŸ’‘ Matches this module suite's "the empty call must produce the safe resource" principle β€” no remote log-shipping target is assumed implicitly.

2 Β· Single remote syslog server (UDP)
module "logging_single_udp" {
  source = "git::https://github.com/microsoftexpert/terraform-f5os-logging.git?ref=v1.0.0"

  logging = {
    servers = [
      {
        address  = "10.10.0.100"
        port     = 514
        protocol = "udp"
      }
    ]
  }
}
3 Β· Multiple remote servers, mixed protocols
module "logging_multi_server" {
  source = "git::https://github.com/microsoftexpert/terraform-f5os-logging.git?ref=v1.0.0"

  logging = {
    servers = [
      {
        address  = "10.10.0.100"
        port     = 514
        protocol = "udp"
      },
      {
        address  = "10.10.0.101"
        port     = 6514
        protocol = "tcp"
      }
    ]
  }
}

ℹ️ Each server entry is independent β€” no shared defaults are applied across entries.

4 Β· TCP server with authentication enabled
module "logging_tcp_auth" {
  source = "git::https://github.com/microsoftexpert/terraform-f5os-logging.git?ref=v1.0.0"

  logging = {
    servers = [
      {
        address        = "10.10.0.102"
        port           = 6514
        protocol       = "tcp"
        authentication = true
      }
    ]
  }
}

⚠️ authentication reads as TCP-only in intent per the provider's own field description β€” this module does not block pairing authentication = true with protocol = "udp", since that constraint is not explicitly stated as enforced in the fetched docs. Keep authentication paired with protocol = "tcp" per the documented intent regardless.

5 Β· Log selectors (facility/severity) per server
module "logging_selectors" {
  source = "git::https://github.com/microsoftexpert/terraform-f5os-logging.git?ref=v1.0.0"

  logging = {
    servers = [
      {
        address  = "10.10.0.100"
        port     = 514
        protocol = "udp"
        logs = [
          {
            facility = "local0"
            severity = "debug"
          },
          {
            facility = "authpriv"
            severity = "emergency"
          }
        ]
      }
    ]
  }
}

ℹ️ logs[*].facility/logs[*].severity on servers are documented only with "e.g." example values β€” this module does not enforce a closed set here, unlike remote_forwarding.logs[*].facility below.

6 Β· CA bundle for TLS validation
module "logging_ca_bundle" {
  source = "git::https://github.com/microsoftexpert/terraform-f5os-logging.git?ref=v1.0.0"

  logging = {
    ca_bundles = [
      {
        name    = "fcfp-internal-ca"
        content = file("${path.module}/certs/fcfp-internal-ca.pem")
      }
    ]
  }
}

πŸ”’ ca_bundles[*].content is public CA trust material, not a private secret β€” it is not marked sensitive in this module, unlike tls_key below.

7 Β· TLS secure logging (certificate + sensitive key)
module "logging_tls" {
  source = "git::https://github.com/microsoftexpert/terraform-f5os-logging.git?ref=v1.0.0"

  logging = {
    tls = {
      certificate = file("${path.module}/certs/logging.crt")
    }
  }

  tls_key = var.logging_tls_key # sourced out of band β€” secret manager / CI variable
}

⚠️ logging.tls.certificate alone is not sufficient β€” tls_key must also be supplied whenever logging.tls is set, or terraform validate fails via this module's cross-field validation {} block. Never hardcode tls_key as a literal.

8 Β· Remote forwarding to on-box files
module "logging_remote_forwarding" {
  source = "git::https://github.com/microsoftexpert/terraform-f5os-logging.git?ref=v1.0.0"

  logging = {
    remote_forwarding = {
      enabled = true
      logs = [
        {
          facility = "local0"
          severity = "error"
        },
        {
          facility = "authpriv"
          severity = "critical"
        }
      ]
      files = [
        { name = "rseries_debug.log" },
        { name = "rseries_audit.log" }
      ]
    }
  }
}

πŸ”’ remote_forwarding.logs[*].facility is a genuinely closed enum β€” only "local0" or "authpriv" β€” enforced by this module's validation {} block, narrower than the example-only servers[*].logs[*].facility field above.

9 Β· Including the device hostname in log messages
module "logging_hostname" {
  source = "git::https://github.com/microsoftexpert/terraform-f5os-logging.git?ref=v1.0.0"

  logging = {
    include_hostname = true
    servers = [
      {
        address  = "10.10.0.100"
        port     = 514
        protocol = "udp"
      }
    ]
  }
}
10 Β· Failure mode: invalid protocol (documented deliberately)
module "logging_bad_protocol" {
  source = "git::https://github.com/microsoftexpert/terraform-f5os-logging.git?ref=v1.0.0"

  logging = {
    servers = [
      {
        address  = "10.10.0.100"
        port     = 514
        protocol = "tls" # invalid β€” not "tcp" or "udp"
      }
    ]
  }
}

⚠️ This fails terraform validate β€” servers[*].protocol must be "tcp" or "udp" per this module's validation {} block, which mirrors the provider's own documented closed set.

11 Β· Failure mode: tls set without tls_key (documented deliberately)
module "logging_tls_missing_key" {
  source = "git::https://github.com/microsoftexpert/terraform-f5os-logging.git?ref=v1.0.0"

  logging = {
    tls = {
      certificate = file("${path.module}/certs/logging.crt")
    }
  }

  # tls_key intentionally omitted
}

⚠️ This fails terraform validate β€” tls_key is required whenever logging.tls is set, per this module's cross-field validation {} block on var.tls_key.

12 Β· VELOS chassis partition target context

The module call itself is identical to the rSeries case β€” only the caller's provider "f5os" {} block (outside this module) changes to point at the VELOS chassis controller partition's management endpoint.

# provider "f5os" {
# host = var.velos_partition_mgmt_ip
# username = var.f5os_username
# password = var.f5os_password
# }

module "logging_velos" {
  source = "git::https://github.com/microsoftexpert/terraform-f5os-logging.git?ref=v1.0.0"

  logging = {
    servers = [
      {
        address  = "10.10.1.100"
        port     = 514
        protocol = "udp"
      }
    ]
  }
}
13 Β· rSeries appliance target context
# provider "f5os" {
# host = var.rseries_appliance_mgmt_ip
# username = var.f5os_username
# password = var.f5os_password
# }

module "logging_rseries" {
  source = "git::https://github.com/microsoftexpert/terraform-f5os-logging.git?ref=v1.0.0"

  logging = {
    servers = [
      {
        address  = "10.20.0.100"
        port     = 514
        protocol = "udp"
      }
    ]
  }
}

πŸ’‘ f5os_logging behaves identically on VELOS and rSeries β€” there is no platform-context branch inside this module.

14 Β· Externalizing input via terraform.tfvars
# logging.auto.tfvars
logging = {
  servers = [
    {
      address  = "10.10.0.100"
      port     = 514
      protocol = "udp"
    }
  ]
  include_hostname = true
}
# main.tf (caller)
module "logging_from_tfvars" {
  source = "git::https://github.com/microsoftexpert/terraform-f5os-logging.git?ref=v1.0.0"

  logging = var.logging
}

πŸ”’ Never place tls_key in a .tfvars file that is committed to version control β€” source it from a secret manager or CI-injected sensitive variable and pass it as a separate -var / environment-backed input.

πŸ—οΈ 15 Β· End-to-end composition

Logging configured once at the platform level, alongside DNS, a VLAN, and a tenant deployed into a VELOS chassis partition β€” illustrating how a platform-wide observability setting like logging coexists with the rest of the F5OS catalog even though it has no direct cross-module reference of its own.

module "dns_platform" {
  source = "git::https://github.com/microsoftexpert/terraform-f5os-dns.git?ref=v1.0.0"

  dns = {
    dns_servers = ["10.10.0.53", "10.10.0.54"]
    dns_domains = ["fcfp.internal"]
  }
}

module "logging_platform" {
  source = "git::https://github.com/microsoftexpert/terraform-f5os-logging.git?ref=v1.0.0"

  logging = {
    include_hostname = true
    servers = [
      {
        address  = "10.10.0.200"
        port     = 6514
        protocol = "tcp"
        logs = [
          { facility = "local0", severity = "error" }
        ]
      }
    ]
    remote_forwarding = {
      enabled = true
      logs = [
        { facility = "authpriv", severity = "critical" }
      ]
      files = [
        { name = "platform_audit.log" }
      ]
    }
  }
}

module "vlan_app_data" {
  source = "git::https://github.com/microsoftexpert/terraform-f5os-vlan.git?ref=v1.0.0"

  vlan = {
    vlan_id = 500
    name    = "vlan500-app-data"
  }
}

module "partition_appA" {
  source = "git::https://github.com/microsoftexpert/terraform-f5os-partition.git?ref=v1.0.0"

  # Illustrative β€” consult terraform-f5os-partition's own README for its full variable schema.
}

module "tenant_appA" {
  source = "git::https://github.com/microsoftexpert/terraform-f5os-tenant.git?ref=v1.0.0"

  # Illustrative β€” consult terraform-f5os-tenant's own README.
  # vlans = [module.vlan_app_data.vlan_id]
  # partition_name = module.partition_appA.name # VELOS only

  depends_on = [module.dns_platform, module.logging_platform]
}

πŸ’‘ Why it matters: logging (like DNS) has no cross-module reference of its own β€” it is a platform-wide prerequisite every other F5OS object implicitly benefits from (audit trail for tenant/partition/VLAN changes). Sequence it early via depends_on in the root module, even though no .tf value flows from it into the VLAN/partition/tenant modules.


πŸ“₯ Inputs

Name Type Required Description
logging object({ include_hostname, servers, ca_bundles, tls, remote_forwarding }) (all fields optional) No (defaults to {}) Logging configuration, 1:1 mapped to the f5os_logging provider schema (minus tls.key).
tls_key string, sensitive Conditionally β€” required whenever logging.tls is set TLS private key for secure logging. Never place in a committed .tfvars file.
Full logging object schema
variable "logging" {
  type = object({
    include_hostname = optional(bool)

    servers = optional(list(object({
      address        = string         # Required. IP address or hostname.
      port           = number         # Required. 1-65535.
      protocol       = string         # Required. "tcp" or "udp".
      authentication = optional(bool) # Optional. TCP-only in intent.
      logs = optional(list(object({
        facility = string # Required. e.g. "local0", "authpriv" (not exhaustive).
        severity = string # Required. e.g. the 8 standard syslog levels (not exhaustive).
      })))
    })))

    ca_bundles = optional(list(object({
      name    = string # Required. CA bundle name.
      content = string # Required. PEM-encoded content (public, not sensitive).
    })))

    tls = optional(object({
      certificate = string # Required within this object. (key supplied via var.tls_key)
    }))

    remote_forwarding = optional(object({
      enabled = bool # Required within this object.
      logs = optional(list(object({
        facility = string # Required. "local0" or "authpriv" β€” genuinely closed.
        severity = string # Required. No example list documented for this field.
      })))
      files = optional(list(object({
        name = string # Required. File name for log output.
      })))
    }))
  })
  default = {}
}

No default is invented for any field beyond the provider's own null/unset behavior β€” an empty {} call is a valid, safe no-op.


🧾 Outputs

Output Description Sensitive
id Synthetic identifier for the f5os_logging resource (system-singleton) No
include_hostname Whether the device hostname is included in emitted log messages, if set No
servers The configured list of remote logging servers, if any No
ca_bundles The configured list of CA bundles for TLS validation, if any No
remote_forwarding The configured remote forwarding configuration, if set No
tls_certificate The configured TLS certificate for secure logging, if logging.tls was set β€” the private key is never output No

🧠 Architecture Notes

  • Single keystone resource, no for_each. f5os_logging's nested collections (servers, ca_bundles, remote_forwarding.logs, remote_forwarding.files) are all Plugin-Framework Attributes on the one resource, not sibling resources with an independent lifecycle β€” there is no genuine child to iterate over inside this module's boundary.
  • No dynamic blocks β€” passed through via =. Because the schema models these collections as Attributes (not classic nested blocks), main.tf assigns each with try(var.logging.<field>, null), exactly mirroring terraform-f5os-auth's remote_roles/password_policy pattern. dynamic blocks are an HCL construct for repeated nested blocks; they do not apply here.
  • tls_key kept out of var.logging.tls entirely. main.tf stitches var.logging.tls.certificate and var.tls_key back together into the single tls object the resource expects (tls = var.logging.tls == null ? null: { certificate =..., key = var.tls_key }) β€” this is the only way to get true field-level sensitive = true redaction on the key without marking every field of logging (including the public certificate) sensitive.
  • try(x, null) guards every optional top-level field reference, consistent with terraform-f5os-vlan/terraform-f5os-dns/terraform-f5os-auth's established pattern for optional nested field references, even where referencing a null value would not itself raise an error.
  • validation {} scoped to provider-confirmed closed sets and documented ranges only. servers[*].protocol ("tcp or udp"), servers[*].port (1-65535), and remote_forwarding.logs[*].facility ("local0 or authpriv") are enforced. Facility/severity fields documented only with "e.g." example lists are deliberately left unvalidated, per the terraform-f5os-lag precedent (mode/interval).
  • No VELOS-vs-rSeries branching. Unlike f5os_partition (VELOS-only) or f5os_tenant (platform-specific partition_name input), f5os_logging behaves identically on both platform contexts β€” there is nothing in this module's main.tf that varies by target.
  • No output is currently consumed by a sibling module. Like terraform-f5os-dns and terraform-f5os-auth, logging configuration is a terminal, platform-wide setting β€” outputs are emitted for informational/audit/import use, not because a sibling module's input references them.

🧱 Design Principles

Concern Secure default Opt-out (caller must type extra)
Remote log destinations No default remote log server assumed β€” servers is left unset (no log shipping) unless the caller explicitly configures it; matches the house-wide rule against implicit network defaults Caller explicitly supplies servers
TLS private key handling tls_key is a dedicated, sensitive = true variable, never a field of var.logging, and never sourced with a plaintext default Caller supplies tls_key out of band (secret manager / CI-injected variable) whenever logging.tls is set
CA bundle content Not treated as sensitive β€” CA bundles are public trust material by design, so no redaction is applied, keeping terraform plan output legible for review N/A β€” this reflects the actual security properties of a CA certificate, not a policy choice
Facility/severity enforcement This module does not fabricate a closed-set validation {} for fields the provider itself documents only as examples ("e.g.") β€” avoiding false confidence about an unconfirmed exhaustive set Caller consults the live provider docs/device behavior before relying on a value outside the documented examples
Hostname inclusion Left to the provider's own default rather than this module forcing a value β€” include_hostname is optional(bool) with no fabricated default Caller explicitly sets include_hostname per their log-correlation requirements
Credentials / secrets tls_key is sensitive = true; never accepted as a plaintext default; expects out-of-band provisioning, matching the house-wide rule for remote_password/key_passphrase-shaped fields N/A

πŸš€ Runbook

cd C:\GitHubCode\newf5modules\f5os\terraform-f5os-logging
terraform init -backend=false
terraform validate
terraform fmt -check
Remove-Item -Recurse -Force.terraform,.terraform.lock.hcl -ErrorAction SilentlyContinue

Pin every consumer to a specific release: ?ref=v1.0.0.


πŸ§ͺ Testing

This is a plan-only proof gate β€” it never touches a real chassis or appliance.

Check Catches Does not catch
terraform validate Missing required nested fields (address/port/protocol/name/content/enabled), wrong type on any field, an invalid protocol/remote_forwarding.logs[*].facility value, an out-of-range port, logging.tls set without tls_key, malformed HCL Malformed IP/hostname strings; the "e.g."-documented facility/severity values that aren't actually accepted by a real device; RBAC/permission failures; whether TLS certificate/key material is actually valid PEM
terraform fmt -check Formatting drift from canonical style Anything semantic
terraform plan (human-run, against real infra) The above gaps β€” a real F5OS structured error surfaces at plan/apply time β€”

πŸ’¬ Example Output

$ terraform output
ca_bundles = null
id = "logging"
include_hostname = true
remote_forwarding = {
 "enabled" = true
 "files" = [
 {
 "name" = "platform_audit.log"
 },
 ]
 "logs" = [
 {
 "facility" = "authpriv"
 "severity" = "critical"
 },
 ]
}
servers = [
 {
 "address" = "10.10.0.200"
 "authentication" = null
 "logs" = [
 {
 "facility" = "local0"
 "severity" = "error"
 },
 ]
 "port" = 6514
 "protocol" = "tcp"
 },
]
tls_certificate = null

ℹ️ The exact id value is illustrative β€” the fetched documentation states only that it is a "Unique identifier for the logging resource" without spelling out the exact literal/algorithm; read the real value from terraform output/terraform state show against your own target.


πŸ” Troubleshooting

Symptom Cause Fix
terraform validate fails: logging.servers[*].protocol must be one of... protocol set to something other than "tcp"/"udp" Correct protocol to "tcp" or "udp" (see Example 10)
terraform validate fails: logging.remote_forwarding.logs[*].facility must be one of... facility set to something other than "local0"/"authpriv" within remote_forwarding.logs Correct the facility value β€” note this closed set is narrower than servers[*].logs[*].facility
terraform validate fails: tls_key is required whenever logging.tls is set logging.tls configured without a corresponding tls_key value Supply tls_key out of band (see Example 11)
apply fails with an out-of-range port error servers[*].port outside 1-65535 β€” not enforced beyond this module's own validation {} block if bypassed via -target/state manipulation Correct port to the documented range
apply fails with a malformed server address error servers[*].address accepts any string; format is not enforced by Terraform's type system Correct the IP/hostname format per F5OS platform requirements
Permission denied / RBAC error at apply The authenticated user's role lacks logging-configuration privilege on the target chassis partition or appliance Grant at least the operator role scoped to that partition/appliance
init cannot resolve provider version ~> 1.10 no longer matches the current Terraform Registry listing Re-verify the pin against the registry and update providers.tf
Plan shows unexpected diff on servers/remote_forwarding/tls_certificate with no caller change A previous out-of-band change was made directly on the F5OS platform Reconcile via terraform import or terraform plan -refresh-only before applying

πŸ”— Related Docs

  • f5os_logging resource reference β€” F5Networks/f5os provider docs (provider_doc_id 12473306)
  • f5os_user resource reference β€” source of the confirmed RBAC role examples (admin, operator, user)
  • Sibling modules in the "observability-diagnostics" domain: terraform-f5os-snmp, terraform-f5os-qkview, terraform-f5os-config-backup
  • Structurally related modules: terraform-f5os-auth (same Plugin-Framework Attributes pass-through pattern), terraform-f5os-tls-cert-key and terraform-f5os-tenant-image (same sensitive-nested-field-split pattern)
  • This module's SCOPE.md

πŸ’™ "Infrastructure as Code should be standardized, consistent, and secure."

Releases

Packages

Contributors

Languages