Skip to content

Latest commit

Β 

History

1 Commit

Folders and files

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

Repository files navigation

☁️ Azure Automation Variable (Bool) Terraform Module

Creates an Azure Automation boolean variable β€” a shared state asset runbooks read and write β€” for hashicorp/azurerm ~> 4.0.

Terraform azurerm Module Type Resources

🧩 Overview

  • Creates a single azurerm_automation_variable_bool (the keystone this) β€” a typed boolean asset inside an existing Automation account.
  • Holds shared true/false state that runbooks read and write between jobs β€” a feature flag, a "maintenance mode" gate, a "last run succeeded" marker.
  • Accepts an optional value (leave it null to create the variable without one), an optional description, and an encrypted toggle that defaults to false.
  • When encrypted is true, the module wraps the value sensitive so it never surfaces in plan output, and the Azure API does not return it on read.
  • Emits the variable id and name; it emits no secret.

πŸ’‘ Why it matters: Automation variables are the durable memory between runbook jobs. Declaring one as a typed module input means a non-boolean value is a plan-time type error, not a failed apply, and the encrypted toggle wires the sensitive-handling correctly without the caller having to remember to.

❀️ Support this project

If this module saves you time:

πŸ—ΊοΈ Where this fits in the family

flowchart LR
  aa["terraform-azurerm-automation-account"]
  me["terraform-azurerm-automation-variable-bool"]
  v["azurerm_automation_variable_bool"]
  s1["terraform-azurerm-automation-variable-datetime"]
  s2["terraform-azurerm-automation-variable-int"]
  s3["terraform-azurerm-automation-variable-object"]
  s4["terraform-azurerm-automation-variable-string"]
  rb["runbooks read/write the variable"]
  aa -->|"automation_account_name"| me
  aa -->|"also parents"| s1
  aa -->|"also parents"| s2
  aa -->|"also parents"| s3
  aa -->|"also parents"| s4
  me -->|"creates"| v
  v -.->|"shared state"| rb
  classDef me fill:#0078D4,stroke:#004578,color:#ffffff;
  classDef target fill:#004578,stroke:#002d4d,color:#ffffff;
  classDef ext fill:#f2f2f2,stroke:#c8c8c8,color:#111111;
  class me me;
  class v target;
  class aa,s1,s2,s3,s4,rb ext;
Loading

🧬 What this module builds

flowchart TB
  in["name + automation_account_name + value(bool) + encrypted"]
  this["azurerm_automation_variable_bool.this"]
  out["Outputs: id, name"]
  in --> this
  this --> out
  classDef target fill:#004578,stroke:#002d4d,color:#ffffff;
  classDef ext fill:#f2f2f2,stroke:#c8c8c8,color:#111111;
  class this target;
  class in,out ext;
Loading

Resource inventory

Resource Role Cardinality
azurerm_automation_variable_bool keystone this single

βœ… Provider / Versions

Requirement Value
Terraform >= 1.12.0
azurerm provider ~> 4.0
Provider block None β€” the caller configures provider "azurerm" { features {} }, auth, and subscription

Schema notes that bite (verified against the live schema):

  • Three fields are force-new. name, resource_group_name, and automation_account_name are immutable β€” changing any of them replaces the variable. value, encrypted, and description all update in place.
  • value is a real bool. The resource is the typed boolean variant, so value is true/false, never a stringified "true". Passing anything else is a plan-time type error.
  • encrypted changes read behavior. With encrypted = true, Azure stores the value encrypted and does not return it on subsequent reads; Terraform therefore cannot detect drift on the value itself. The module wraps the value sensitive in this case so it stays out of plan output.
  • value is optional. Leave it null to create the variable as a named placeholder that a runbook populates at run time.
  • No tags. This resource type does not support tags, so the module omits the variable β€” the universal tail is timeouts only.

πŸ”‘ Required Azure RBAC Roles / Permissions

  • Automation Contributor (or an equivalent custom role carrying Microsoft.Automation/automationAccounts/variables/*) on the parent Automation account.

Azure Prerequisites

  • An existing Automation account to hold the variable.
  • The caller configures the provider "azurerm" { features {} } block, authentication, and subscription β€” this module declares none of them.

πŸ“ Module Structure

terraform-azurerm-automation-variable-bool/
β”œβ”€β”€ providers.tf   # required_version + azurerm ~> 4.0 pin; no provider block
β”œβ”€β”€ variables.tf   # keystone inputs, value/encrypted/description, timeouts (no tags)
β”œβ”€β”€ main.tf        # azurerm_automation_variable_bool.this
β”œβ”€β”€ outputs.tf     # id first, then name
β”œβ”€β”€ README.md      # this document
β”œβ”€β”€ SCOPE.md       # cross-module contract
β”œβ”€β”€ LICENSE        # MIT
└── .gitignore

βš™οΈ Quick Start

The smallest real call creates a boolean variable in an existing Automation account:

module "flag" {
  source                  = "git::https://github.com/microsoftexpert/terraform-azurerm-automation-variable-bool.git?ref=v1.0.0"
  name                    = "maintenance-mode"
  resource_group_name     = "rg-automation-eastus"
  automation_account_name = "aa-contoso"
  value                   = false
}

ℹ️ The caller configures provider "azurerm" { features {} }, authentication, and the subscription β€” this module declares none of them. The Automation account must already exist.

πŸ”Œ Cross-Module Contract

Consumes

Input Type Source module
resource_group_name string terraform-azurerm-resource-group (name)
automation_account_name string terraform-azurerm-automation-account (name)

Emits

Output Description
id Variable Resource ID (first)
name Variable name β€” the key a runbook uses with Get-AutomationVariable

πŸ“š Example Library

1 Β· Value true
module "flag" {
  source                  = "git::https://github.com/microsoftexpert/terraform-azurerm-automation-variable-bool.git?ref=v1.0.0"
  name                    = "auto-shutdown-enabled"
  resource_group_name     = "rg-automation-eastus"
  automation_account_name = "aa-contoso"
  value                   = true
}

πŸ’‘ A runbook reads this with Get-AutomationVariable -Name "auto-shutdown-enabled" and branches on the boolean.

2 Β· Value false
module "flag" {
  source                  = "git::https://github.com/microsoftexpert/terraform-azurerm-automation-variable-bool.git?ref=v1.0.0"
  name                    = "maintenance-mode"
  resource_group_name     = "rg-automation-eastus"
  automation_account_name = "aa-contoso"
  value                   = false
}

ℹ️ value is a genuine bool β€” pass false, never the string "false".

3 Β· No value (null placeholder)
module "flag" {
  source                  = "git::https://github.com/microsoftexpert/terraform-azurerm-automation-variable-bool.git?ref=v1.0.0"
  name                    = "last-run-succeeded"
  resource_group_name     = "rg-automation-eastus"
  automation_account_name = "aa-contoso"
  # value omitted β†’ created without a value
}

πŸ’‘ Leave value null to create a named placeholder that a runbook sets at run time with Set-AutomationVariable.

4 Β· Encrypted variable
module "flag" {
  source                  = "git::https://github.com/microsoftexpert/terraform-azurerm-automation-variable-bool.git?ref=v1.0.0"
  name                    = "byok-rotation-active"
  resource_group_name     = "rg-automation-eastus"
  automation_account_name = "aa-contoso"
  value                   = true
  encrypted               = true
}

πŸ”’ With encrypted = true the module wraps the value sensitive, so it never appears in plan output. Azure does not return the value on read, so Terraform cannot detect drift on the value once set.

5 Β· With a description
module "flag" {
  source                  = "git::https://github.com/microsoftexpert/terraform-azurerm-automation-variable-bool.git?ref=v1.0.0"
  name                    = "cost-guard-enabled"
  resource_group_name     = "rg-automation-eastus"
  automation_account_name = "aa-contoso"
  value                   = true
  description             = "When true, the nightly cost-guard runbook deallocates idle VMs."
}

ℹ️ description updates in place β€” you can retune it without replacing the variable.

6 Β· Encrypted with a description
module "flag" {
  source                  = "git::https://github.com/microsoftexpert/terraform-azurerm-automation-variable-bool.git?ref=v1.0.0"
  name                    = "failover-armed"
  resource_group_name     = "rg-automation-eastus"
  automation_account_name = "aa-contoso"
  value                   = false
  encrypted               = true
  description             = "Set true only during a controlled DR drill."
}

πŸ”’ The description is metadata and remains visible; only the boolean value is protected by encrypted = true.

7 Β· Several variables with for_each
locals {
  flags = {
    auto-shutdown-enabled = { value = true, description = "Nightly VM auto-shutdown." }
    maintenance-mode      = { value = false, description = "Pauses scheduled runbooks." }
    verbose-logging       = { value = false, description = "Extra diagnostics in runbook output." }
  }
}

module "flag" {
  source                  = "git::https://github.com/microsoftexpert/terraform-azurerm-automation-variable-bool.git?ref=v1.0.0"
  for_each                = local.flags
  name                    = each.key
  resource_group_name     = "rg-automation-eastus"
  automation_account_name = "aa-contoso"
  value                   = each.value.value
  description             = each.value.description
}

πŸ’‘ A keyed for_each at the module level keeps each variable stable when you add or remove one β€” no re-indexing.

8 Β· Encrypted flags at scale
locals {
  gates = {
    dr-armed        = true
    byok-rotating   = false
    break-glass-on  = false
  }
}

module "flag" {
  source                  = "git::https://github.com/microsoftexpert/terraform-azurerm-automation-variable-bool.git?ref=v1.0.0"
  for_each                = local.gates
  name                    = each.key
  resource_group_name     = "rg-automation-eastus"
  automation_account_name = "aa-contoso"
  value                   = each.value
  encrypted               = true
}

πŸ”’ Every entry is encrypted at rest. The map key is the variable name a runbook references.

9 Β· Referenced by a runbook
module "flag" {
  source                  = "git::https://github.com/microsoftexpert/terraform-azurerm-automation-variable-bool.git?ref=v1.0.0"
  name                    = "auto-shutdown-enabled"
  resource_group_name     = "rg-automation-eastus"
  automation_account_name = "aa-contoso"
  value                   = true
}

module "runbook" {
  source                  = "git::https://github.com/microsoftexpert/terraform-azurerm-automation-runbook.git?ref=v1.0.0"

  location              = "eastus2"

  runbook_type          = "PowerShell"
  name                    = "Invoke-CostGuard"
  resource_group_name     = "rg-automation-eastus"
  automation_account_name = "aa-contoso"
}

ℹ️ Runbook and variable share the Automation account. Inside the runbook, Get-AutomationVariable -Name module.flag.name reads the boolean; Terraform manages the asset, the runbook manages the value at run time.

10 Β· Flipping a value in place
module "flag" {
  source                  = "git::https://github.com/microsoftexpert/terraform-azurerm-automation-variable-bool.git?ref=v1.0.0"
  name                    = "maintenance-mode"
  resource_group_name     = "rg-automation-eastus"
  automation_account_name = "aa-contoso"
  value                   = true # was false; this is an in-place update, not a replace
}

πŸ’‘ value updates in place. Only the three identity fields (name, resource_group_name, automation_account_name) force a replacement.

11 Β· Custom timeouts
module "flag" {
  source                  = "git::https://github.com/microsoftexpert/terraform-azurerm-automation-variable-bool.git?ref=v1.0.0"
  name                    = "slow-region-flag"
  resource_group_name     = "rg-automation-eastus"
  automation_account_name = "aa-contoso"
  value                   = false
  timeouts = {
    create = "30m"
    delete = "30m"
  }
}

ℹ️ timeouts is the module's only universal-tail input β€” this resource type carries no tags.

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

Stand up a resource group, an Automation account, and a boolean variable a runbook consumes as shared state:

module "rg" {
  source   = "git::https://github.com/microsoftexpert/terraform-azurerm-resource-group.git?ref=v1.0.0"
  name     = "rg-automation-eastus"
  location = "eastus"
}

module "automation" {
  source              = "git::https://github.com/microsoftexpert/terraform-azurerm-automation-account.git?ref=v1.0.0"
  name                = "aa-contoso"
  resource_group_name = module.rg.name
  location            = module.rg.location
}

module "maintenance_flag" {
  source                  = "git::https://github.com/microsoftexpert/terraform-azurerm-automation-variable-bool.git?ref=v1.0.0"
  name                    = "maintenance-mode"
  resource_group_name     = module.rg.name                 # from terraform-azurerm-resource-group
  automation_account_name = module.automation.name         # from terraform-azurerm-automation-account
  value                   = false
  description             = "Nightly runbooks skip work while true."
}

πŸ’‘ The Automation account is the parent; this variable is a leaf that a runbook reads. Reference sibling name outputs so renames propagate rather than silently detaching the variable from a renamed account.

πŸ“₯ Inputs

Required: name, resource_group_name, automation_account_name. Optional: value, encrypted, description. Universal tail: timeouts (no tags β€” the resource does not support them).

Full schemas
name                    = string # required, force-new
resource_group_name     = string # required, force-new
automation_account_name = string # required, force-new

value       = optional(bool)   # null = create the variable without a value; updates in place
encrypted   = optional(bool)   # default false; when true the value is wrapped sensitive and not returned on read
description  = optional(string) # updates in place

timeouts = optional(object({
  create = optional(string) # Go duration, e.g. "30m"
  read   = optional(string)
  update = optional(string)
  delete = optional(string)
}))

🧾 Outputs

Output Description Kind
id Resource ID of the Automation Bool variable Passthrough
name Name of the variable, as created Passthrough
automation_account_name Name of the parent Automation account this variable belongs to Passthrough
resource_group_name Name of the resource group holding the parent Automation account Passthrough
variable_type Constant "Bool" Derived
is_encrypted Whether the value is encrypted at rest Passthrough
has_value Whether a value was supplied Derived
value_is_readable_by_terraform False when the variable is encrypted Derived
has_description Whether a description was set Derived
renaming_this_variable_destroys_its_value Constant true Constant
is_scoped_to_one_automation_account Constant true Constant
value_is_not_emitted_by_design Constant true Constant

No secret is emitted. When encrypted is true the value is wrapped sensitive and never surfaces in output.

🧠 Architecture Notes

  • Identity fields are force-new. name, resource_group_name, and automation_account_name are immutable β€” changing any of them destroys and recreates the variable, which momentarily removes the shared state a runbook may depend on. value, encrypted, and description all update in place.
  • encrypted governs sensitive handling. The module renders value = var.encrypted ? sensitive(var.value) : var.value, so an encrypted variable's value stays out of plan output. Because Azure does not return an encrypted value on read, Terraform cannot detect drift on the value once it is set β€” a runbook that later changes it via Set-AutomationVariable will not show as a diff.
  • value is optional by design. A null value creates a named placeholder, which is the right shape when a runbook, not Terraform, owns the value at run time.
  • No tags, and no secret emitted. The resource type does not support tags; the universal tail is timeouts only. The module emits 12 outputs -- identity, parentage and derived facts -- but never the value itself; has_value reports presence instead.
  • features {} dependence. The provider will not initialize without a caller-side features {} block β€” expected, and owned by the root module.

🧱 Design Principles

Concern Secure default Opt-out (caller must type it)
Value confidentiality value wrapped sensitive and encrypted at rest when encrypted = true leave encrypted = false (the default) for a plaintext boolean
Secret emission emits no secret; only id and name are output β€”
Value presence value null β†’ named placeholder a runbook populates set an explicit true/false
Drift visibility plaintext value is diff-visible encrypted = true hides the value from reads (by design)

πŸš€ Runbook

terraform init -backend=false
terraform validate
terraform fmt -check

Pin the module by immutable tag (?ref=v1.0.0), never a branch. This is plan-only; a human applies from CI.

πŸ§ͺ Testing

  • terraform validate + fmt -check prove the type contract offline β€” that value is a bool, that encrypted is a bool, and that the required identity fields are present β€” before any Azure call.
  • Only terraform plan against a subscription exercises the existence of the Automation account and the API's acceptance of the variable name; the force-new behavior of the identity fields shows up in a plan as a replacement.

πŸ’¬ Example Output

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

Outputs:

id   = "/subscriptions/.../resourceGroups/rg-automation-eastus/providers/Microsoft.Automation/automationAccounts/aa-contoso/variables/maintenance-mode"
name = "maintenance-mode"

πŸ” Troubleshooting

Symptom Cause Fix
Inappropriate value for attribute "value": a bool is required Passed a string such as "true" Pass a genuine boolean true / false
Variable replaced on a rename Changed name, resource_group_name, or automation_account_name (force-new) Expected β€” these identity fields replace the resource; value/encrypted/description update in place
Encrypted value shows no drift after a runbook changed it Azure does not return an encrypted value on read Expected β€” Terraform manages the asset, not the run-time value; treat runbook-set values as out of Terraform's view
Apply fails: parent account not found The Automation account does not exist, or automation_account_name/resource_group_name is wrong Create the Automation account first and pass its name and resource group
Value visible in plan output when it should be hidden encrypted left at its default false Set encrypted = true to wrap the value sensitive and encrypt it at rest

πŸ”— Related Docs

  • azurerm_automation_variable_bool
  • Sibling modules: terraform-azurerm-automation-account, terraform-azurerm-automation-variable-string, terraform-azurerm-automation-variable-int, terraform-azurerm-automation-variable-datetime, terraform-azurerm-automation-variable-object
  • This module's SCOPE.md

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