Variables
Declaring variables, overriding them at run time, and how empty values behave.
On this page
Variables let one profile serve several environments without forking it. This page covers declaring them, the rules for overriding them, and what happens when a value is empty. The function set available in expressions is on the Functions page.
Declaring a variable
variable "ntp_servers" {
description = "Approved NTP servers"
type = "list(string)"
default = ["time1.example.org", "time2.example.org"]
validation {
condition = length(var.ntp_servers) > 0
error_message = "At least one NTP server must be configured."
}
}The supported types are string, which is the default, number, bool, and
list(string). Anything else is a load-time error.
validation conditions are evaluated against the finished variable context, so
a condition may reference any variable, not only its own. The first failing rule
stops the load.
Resolution order
Per variable: an override if one exists, otherwise the declared default,
otherwise "" for an untyped or string variable. A non-string variable with
neither a default nor an override is a load-time error.
Overrides come from two places.
refpoint run baseline --var-file production.rpvar --var max_password_age=60--var-file keeps native HCL types, so numbers, bools, and lists arrive as
themselves, and a null value is rejected. --var is always a string, and for a
list target a comma-separated string is split and trimmed. --var wins over
--var-file.
Overrides for variables the profile never declared pass through with their native type. Dependency profiles rely on this.
Coercion is not type checking
Conversion is coercion. A false assigned to a type = "string" variable
becomes the string "false". The type guarantee is real only for number,
bool, and list(string) targets. Use validation blocks to reject coercion
artifacts rather than assuming the declared type rejected them for you.
Empty variables skip a check
If a check attribute draws on a profile variable and evaluates to nothing, an empty or whitespace-only string, or an empty collection, the check is skipped and the attribute is named in the reason.
The reason is that an empty pattern matches anything and an empty expected hash matches nothing. Both silently misreport.
A literal "" written in the profile is left alone, because the author said it
explicitly. An interpolation that still yields text, such as
"prefix-${var.suffix}", runs normally.
Using a variable in a check
variable "sshd_config_path" {
type = "string"
default = "/etc/ssh/sshd_config"
}
control "ssh-02" {
title = "SSH protocol settings are managed"
impact = 0.7
check "config-owner" "file" {
path = var.sshd_config_path
owner = "root"
mode = "0600"
}
}Only the address attribute, path here, is evaluated with the variable
context at load time. The remaining assertions are decoded by the file
provider when the check runs.