Inspector de Variables Terraform
Inspecciona y valida definiciones de variables Terraform, defaults, tipos y patrones de uso
Terraform Variable Inspection and Analysis
Terraform variables define the input interface of a module — they are the parameters that consumers
must provide (or may optionally override) when calling module "x" { ... }. A well-designed
variable interface makes a module self-documenting: each variable has a clear type constraint, a
meaningful description, sensible defaults for optional parameters, validation rules that reject invalid
inputs early, and sensitivity markers that prevent secrets from leaking into logs or state output.
However, as modules grow in complexity, the variable interface can become difficult to reason about.
A module with 40+ variables, nested object types, and conditional defaults requires careful inspection
to understand what inputs are actually required, what shapes they expect, and what guardrails exist.
A Terraform variable inspector parses variable blocks from HCL configuration files and
extracts structured metadata: the variable name, its type constraint (from simple primitives like
string and number to complex types like map(object({...}))),
its default value (which determines whether the variable is required or optional), its description
(critical for documentation and IDE support), any validation blocks with custom rules,
and whether the variable is marked sensitive = true. This structured extraction enables
module consumers to quickly understand how to configure a module, documentation generators to produce
accurate input tables, and linting tools to detect missing descriptions, overly permissive
any types, or required variables without clear documentation explaining what value to provide.
Variable Types and Type Constraints in Terraform
Terraform's type system for variables ranges from simple primitives to deeply nested structural types. Understanding the full type hierarchy is essential for inspecting module interfaces:
-
Primitive types:
string,number, andboolrepresent scalar values. These are the simplest variable types and accept direct literal values. A variable declared astype = stringwill accept any string and reject numbers or booleans unless explicitly converted. -
Collection types:
list(type),set(type), andmap(type)represent homogeneous collections where every element shares the same type. For example,list(string)accepts["a", "b", "c"]but rejects["a", 1, true]. Maps are particularly common for tagging patterns:type = map(string)for resource tags. -
Structural types:
object({...})andtuple([...])define exact shapes with per-attribute types. Objects are the most powerful type constraint —object({ name = string, port = number, enabled = bool })enforces that callers provide exactly those attributes with those types. Optional attributes useoptional(type, default)in Terraform 1.3+. -
The
anytype: Disables type checking entirely. While sometimes necessary for pass-through values, overuse ofanyweakens the module interface by deferring type errors to apply-time rather than catching them at plan-time. An inspector flagsanyusage as a potential code smell requiring justification. -
Nested complex types: Real-world modules often use deeply nested types like
map(object({ rules = list(object({ port = number, cidr = string })) })). These complex types are hard to read inline in HCL — an inspector presents them in a structured, navigable format that makes the expected shape immediately clear.
Required vs Optional Variables and Default Values
The presence or absence of a default argument in a variable block is what determines
whether a variable is required or optional. This distinction is fundamental to understanding a
module's input contract:
-
Required variables (no default): A variable without a
defaultvalue must be explicitly provided by the caller. If omitted, Terraform will prompt interactively (in CLI mode) or fail with an error (in automation). Required variables represent the minimum configuration a module needs to function — the essential parameters without which the module cannot provision infrastructure. -
Optional variables (with default): Variables with a
defaultvalue can be omitted by callers, in which case the default is used. Defaults should represent the most common or safest configuration. For example,default = truefor an encryption flag ensures encryption is enabled unless explicitly disabled — a secure-by-default pattern. -
Nullable variables: Since Terraform 1.1, variables can be declared with
nullable = falseto rejectnullas a value even when a default exists. This prevents callers from accidentally nullifying a variable that has a meaningful default. An inspector surfaces this attribute to clarify whethernullis a valid input. -
Empty defaults as sentinels: Some modules use
default = ""ordefault = nullas sentinels, with conditional logic inside the module that behaves differently based on whether the variable was explicitly set. An inspector detecting empty or null defaults alongside complex conditional usage can flag these as potentially confusing interface patterns that deserve documentation.
A variable inspector categorizes every variable as required or optional, groups them accordingly, and highlights cases where the default value may be surprising (empty strings, null, empty lists) or where a required variable lacks a description explaining what value to provide.
Validation Rules and Input Constraints
Terraform validation blocks define custom rules that inputs must satisfy beyond their
type constraint. These rules catch invalid values at terraform plan time rather than
at apply-time (or worse, creating broken infrastructure that fails silently):
-
Condition expressions: Each validation block has a
conditionthat must evaluate totruefor the input to be accepted. Conditions can use any Terraform expression —length(),regex(),can(),contains(), numeric comparisons, and more. For example,condition = length(var.name) >= 3 && length(var.name) <= 63enforces name length bounds. -
Error messages: The
error_messagestring explains what the caller did wrong when the condition fails. Good error messages are specific and actionable: "Environment must be one of: dev, staging, prod" is far more helpful than "Invalid value". An inspector extracts and displays these messages to document the allowed value space. -
Multiple validation blocks: A single variable can have multiple validation
blocks, each checking a different constraint. For instance, a CIDR variable might have one
validation for format (
can(cidrhost(var.cidr, 0))) and another for prefix length (tonumber(split("/", var.cidr)[1]) >= 16). An inspector lists all validations to give a complete picture of the accepted input space. -
Pattern-based validation: The
regex()function is commonly used for validating naming conventions, DNS labels, ARN formats, and other structured strings. For example,condition = can(regex("^[a-z][a-z0-9-]{1,61}[a-z0-9]$", var.bucket_name))enforces S3 bucket naming rules. An inspector recognizes regex patterns and can display the allowed format clearly.
By extracting all validation rules, an inspector enables module consumers to understand what values are accepted without reading module source code — the validation rules, combined with type constraints and error messages, fully document the allowed input space.
Sensitive Variables and Security Considerations
Variables marked with sensitive = true receive special treatment throughout the
Terraform workflow. Understanding which variables are sensitive is critical for security reviews
and compliance:
-
Output suppression: Sensitive variable values are redacted from CLI output,
plan diffs, and
terraform outputdisplays. Instead of showing the actual value, Terraform displays(sensitive value). This prevents accidental exposure in CI/CD logs, terminal recordings, and shared plan outputs. -
State file exposure: Despite output suppression, sensitive values are still
stored in plaintext in the Terraform state file. The
sensitivemarker is a UI protection, not an encryption mechanism. An inspector that identifies sensitive variables can recommend additional controls: encrypted state backends, restricted state access policies, and secrets management integration (Vault, AWS Secrets Manager). -
Common sensitive variables: Database passwords, API keys, TLS private keys,
OAuth client secrets, and encryption keys should always be marked sensitive. An inspector
can flag variables with names matching patterns like
*_password,*_secret,*_key, or*_tokenthat are NOT marked sensitive — a potential security oversight. -
Propagation rules: When a sensitive variable is used in a resource attribute,
the entire resource attribute becomes sensitive in plan output. If passed to an output value,
that output must also be marked
sensitive = trueor Terraform will error. An inspector traces sensitivity propagation to identify where sensitive data flows through the module.
Code Examples
Terraform Variable Definitions with Types, Defaults, Validations, and Sensitivity
# Required variable — no default, must be provided by caller
variable "environment" {
type = string
description = "Deployment environment (dev, staging, prod)"
validation {
condition = contains(["dev", "staging", "prod"], var.environment)
error_message = "Environment must be one of: dev, staging, prod."
}
}
# Optional variable with sensible default
variable "instance_type" {
type = string
description = "EC2 instance type for the application servers"
default = "t3.medium"
validation {
condition = can(regex("^[a-z][a-z0-9]*\\.[a-z0-9]+$", var.instance_type))
error_message = "Instance type must be a valid AWS format (e.g., t3.medium, m5.xlarge)."
}
}
# Complex object type with nested structure
variable "vpc_config" {
type = object({
cidr_block = string
availability_zones = list(string)
private_subnets = list(string)
public_subnets = list(string)
enable_nat_gateway = optional(bool, true)
single_nat_gateway = optional(bool, false)
})
description = "VPC network configuration including CIDR, subnets, and NAT settings"
validation {
condition = can(cidrhost(var.vpc_config.cidr_block, 0))
error_message = "vpc_config.cidr_block must be a valid CIDR notation (e.g., 10.0.0.0/16)."
}
validation {
condition = length(var.vpc_config.availability_zones) >= 2
error_message = "At least 2 availability zones are required for high availability."
}
}
# Sensitive variable — value redacted from CLI output
variable "database_password" {
type = string
description = "Master password for the RDS PostgreSQL instance"
sensitive = true
validation {
condition = length(var.database_password) >= 16
error_message = "Database password must be at least 16 characters for security compliance."
}
validation {
condition = can(regex("[A-Z]", var.database_password)) && can(regex("[0-9]", var.database_password))
error_message = "Database password must contain at least one uppercase letter and one digit."
}
}
# Map type for flexible tagging
variable "tags" {
type = map(string)
description = "Resource tags applied to all provisioned infrastructure"
default = {}
validation {
condition = alltrue([for k, v in var.tags : length(k) <= 128 && length(v) <= 256])
error_message = "Tag keys must be ≤128 chars and values ≤256 chars (AWS limits)."
}
}
# Variable with nullable = false (Terraform 1.1+)
variable "log_retention_days" {
type = number
description = "CloudWatch log retention period in days"
default = 30
nullable = false
validation {
condition = contains([1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365], var.log_retention_days)
error_message = "Log retention must be a valid CloudWatch retention value."
}
}Standards & Specifications
- Terraform Input Variables Documentation — Official HashiCorp documentation covering variable declarations, types, defaults, validation, and sensitivity markers
- Terraform Type Constraints Reference — Complete reference for Terraform type system including primitives, collections, structural types, and the any keyword
- Terraform Custom Validation Rules — Documentation for writing condition expressions and error messages in variable validation blocks
- HCL Native Syntax Specification — Formal specification of HCL syntax including block structure, attribute definitions, and expression grammar
Preguntas Frecuentes
What does the Terraform Variable Inspector check?
The inspector analyzes each variable block in your Terraform HCL code, reporting the name, type constraint, default value, description, sensitive flag, and any validation rules. It also detects common issues like missing types, missing descriptions, overly permissive 'any' types, and variables that likely hold secrets but lack the sensitive flag.
Why should I add type constraints to variables?
Type constraints (e.g., type = string, type = number, type = list(string)) allow Terraform to validate input values before applying changes. Without a type, any value is accepted, which can lead to confusing runtime errors. Explicit types catch mistakes early during terraform plan.
What does the sensitive flag do in Terraform?
When sensitive = true is set on a variable, Terraform redacts its value from CLI output, plan output, and logs. This prevents accidental exposure of passwords, tokens, and API keys. The inspector warns when a variable name suggests it contains secrets but lacks this flag.
Is my Terraform code sent to any server?
No. All parsing and analysis happens entirely in your browser using JavaScript. Your Terraform code — which may contain variable names, default values, and infrastructure details — never leaves your device. No data is stored, logged, or transmitted.
What Terraform variable attributes are detected?
The inspector recognizes all standard variable attributes: type (type constraint), default (default value), description (documentation string), sensitive (redaction flag), and validation blocks (with condition and error_message). Nullable and ephemeral attributes are also parsed if present.
Why does the inspector warn about type 'any'?
Using type = any disables Terraform's type checking for that variable. While occasionally necessary for generic modules, it prevents early error detection and makes code harder to understand. The inspector flags it as a warning so you can evaluate whether a more specific type would be appropriate.
Can I inspect variables from multiple .tf files?
The inspector processes one input at a time. For multi-file configurations, paste the contents of each file separately or concatenate them. The HCL parser handles multiple variable blocks in a single input without issues.
What is the maximum input size supported?
The inspector accepts Terraform files up to 2MB. Files between 200KB and 2MB will show a warning that processing may be slow. For typical Terraform configurations under 200KB, analysis is instant.