Skip to content

Built-in functions

Tales extends HCL2 with a small set of helper functions tuned for integration testing: looking up env vars, generating data, encoding payloads, signing requests, and pulling values out of text.

This page documents the helpers that are not matchers. For assertion matchers (contains, optional, is_string, etc.), see Matchers.

Reads an environment variable.

config {
base_url = env("BASE_URL", "http://localhost:1337")
api_key = env("API_KEY") // no default, empty string if unset
}
ArgumentTypeNotes
namestringEnv var name.
defaultanyOptional fallback when the var is unset or empty. Omit for "".

Common patterns:

url = "${env("API_URL", "http://localhost:1337")}/users"
debug = env("DEBUG", "0") == "1"

Calls a generator by name and returns its value. See Generators for declaration and types.

generate("user_email") // string
generate("demo_person").first_name // string

Output is deterministic given (seed, scenario, step, generator name, expression path). Two calls in the same step return different values, the expression path differs. Capture or store in vars to reuse.

Serialises any HCL value to a canonical JSON string. Object keys are sorted alphabetically; sets are sorted by encoded form; numbers preserve json.Number precision.

vars {
body = jsonencode({
id = "evt-1"
type = "ping"
data = { user = "[email protected]" }
})
}

The deterministic key ordering matters for any signing scheme, the same payload always produces the same byte sequence, so HMAC and SHA-256 signatures stay stable across runs.

URL-encodes a string (component-style encoding, suitable for query parameters or path segments).

url = "${config.base_url}/search?q=${url_encode("hello world")}"
// → "hello%20world"

Returns the current Unix timestamp (seconds, integer) as observed at evaluation time. Non-deterministic by design.

vars {
ts = now_unix() // 1716822000
}

Same idea, RFC3339 UTC string format.

vars {
created_at = now_rfc3339() // "2026-05-27T18:30:00Z"
}

Seven sha*_hex variants are exposed, each hashing the UTF-8 bytes of its single string argument and returning the lowercase hex digest. Errors never embed the input.

FunctionAlgorithmDigest length (hex chars)
sha1_hexSHA-140
sha224_hexSHA-22456
sha256_hexSHA-25664
sha384_hexSHA-38496
sha512_hexSHA-512128
sha512_224_hexSHA-512/22456
sha512_256_hexSHA-512/25664
vars {
digest = sha256_hex("hello")
// digest = "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824"
}

The same seven variants are exposed as keyed HMACs. Each takes (secret, message) (both strings) and returns the lowercase hex digest. Secrets and messages are never embedded in error messages.

FunctionAlgorithm
hmac_sha1_hexHMAC-SHA-1
hmac_sha224_hexHMAC-SHA-224
hmac_sha256_hexHMAC-SHA-256
hmac_sha384_hexHMAC-SHA-384
hmac_sha512_hexHMAC-SHA-512
hmac_sha512_224_hexHMAC-SHA-512/224
hmac_sha512_256_hexHMAC-SHA-512/256
vars {
sig = hmac_sha256_hex(config.webhook_secret, "${vars.ts}.${vars.body}")
}
request {
headers = { X-Signature = "t=${vars.ts},v1=${vars.sig}" }
body { raw = vars.body }
}

hmac_sha256_hex is the recommended default for new signing code. hmac_sha1_hex is kept available because RFC 6238 TOTP and a few legacy signing schemes still mandate it. Pair any HMAC with jsonencode for a stable canonical signed payload, see the Signing webhooks guide for a full recipe.

Encodes the UTF-8 bytes of the input string using the RFC 4648 URL-safe alphabet (- and _ instead of + and /) without padding.

vars {
segment = base64url_encode("hello")
// segment = "aGVsbG8"
}

Derives an RFC 7636 PKCE code_challenge from a code_verifier.

vars {
verifier = "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk"
challenge = pkce_challenge(vars.verifier)
// challenge = "E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM"
}

pkce_challenge(verifier) defaults to the S256 method. Supply an options object to change behaviour:

OptionTypeDefaultNotes
methodstring"S256"Either "S256" or "plain". Unknown methods error.

For S256, the function computes base64url(sha256(ASCII(verifier))), encoding the raw 32 hash bytes, not the hex string. plain returns the verifier unchanged. Unknown option keys and unsupported methods fail explicitly without embedding the verifier.

The code_verifier JSON field name is treated as sensitive by Tales’ report masking; bodies that send it under that key will not leak the value into JSONL / HTML / console reports.

Computes an RFC 6238 TOTP code from a Base32-encoded secret.

vars {
ts = now_unix()
code = totp(config.mfa_secret, {
period = 30
digits = 6
algorithm = "SHA1"
timestamp = vars.ts
})
}

totp(secret) without options is equivalent to passing every option at its default value:

OptionTypeDefaultNotes
periodnumber30Window size in seconds; must be > 0.
digitsnumber6Code length; must be > 0 and <= 10.
algorithmstring"SHA1"Only SHA1 is supported in V1; other values raise an explicit error.
timestampnumbernow_unix()Unix seconds; must be >= 0.

The default timestamp reads the wall clock, so two calls inside the same expression may straddle a window boundary. Capture now_unix() into a step-local vars.ts and pass it as timestamp whenever stability matters, exactly as in the example above.

The secret is Base32; the function normalizes user-friendly variants (lower/upper case, spaces, hyphens, missing padding). Invalid secrets fail with an opaque invalid TOTP base32 secret message, the raw input is never echoed.

Extracts the first regex match from a string. With group = 0 (default) returns the full match; with group = N returns the N-th capture group.

capture {
// body contains "verification code is A1B2C3"
code = regex_find(response.body, "verification code is ([A-Z0-9]{6})", 1)
}
ArgumentTypeNotes
valuestringSubject string to search.
patternstringGo regexp syntax (RE2). Compiled at evaluation time.
groupnumberOptional capture group index (default 0, the full match).

Returns an error if the pattern doesn’t match the value. Wrap in can(...) (see Matchers) if you want a soft probe.

In addition to the helpers above, Tales exposes the standard HCL2 function set: format, formatlist, join, split, lower, upper, trim, length, concat, merge, keys, values, range, tonumber, tostring, jsondecode, coalesce, try, and more. See the Terraform language docs for a comprehensive reference, they share the same go-cty function library.