Hashicorp Terraform Associate (003) Exam Guide Hashicorp Terraform Associate (003) Exam Guide

Page content

A complete study guide for Hashicorp Terraform Associate Certification Exam (003).

About Exam

  • Terraform Associate certification is a specialty certification in Terraform conducted by Hashicorp.
  • This exam is recommended for Cloud, DevOps, and SRE engineers.
  • The Terraform Associate 003 exam detail is available here
  • You have to answer 57 questions within 60 minutes from your laptop under the supervision of an online proctor.
  • You need to get “around” 70% to pass the exam so you can afford to get 17 questions wrong.
  • The exam costs you 70 USD and there is no free retake.
  • The exam can be taken in English language only.
  • You should expect different types of questions format such as Multiple Choice, Multiple Answers, True or false, and Text Match where you have to type the answer to fill in the blank.
  • You get the exam result instantly and receive an email with the same result.
  • This certification is valid for 2 years.
  • This exam is targeted for Terraform version 1.0 and higher.
  • Recommended studying for 1-2 hours a day for 2-4 weeks depending upon your daily commitment.
  • You can register for the exam here

Exam Preparation

To be honest, their documentation is more than enough for this exam. They have a very good Exam study guide and exam review guide. I would suggest you go through these links in order and would highly recommend you practice while going through these materials.

Free study material:-

Paid study materials:-

Exam Notes

Infrastructure as Code

  • Terraform is an Infrastructure as Code (IaC) tool that is Declarative and Cloud Agnostic
  • Infrastructure lifecycle:-
    1. “Day 0” code provisions and configures your initial infrastructure.
    2. “Day 1” refers to OS and application configurations you apply after you’ve initially built your infrastructure.
  • IaC enhances the Infrasture lifecycle:
    1. Reliability: IaC makes changes idempotent, consistent, repeatable, and predicable
    2. Manageability
    3. Sensibility
  • Popular Infrastructure as Code (IaC) tools:
    ARM Templates, Azure Blueprintsonly Microsoft Azure
    CloudFormationonly Amazon AWS
    Cloud Deployment Manageronly Google Cloud Platform GCP
    TerraformAWS, Azure, GCP, and on-prem
  • Terraform is written in HashiCorp Configuration Language (HCL). HCL is designed to strike a balance between human-readable and machine-parsable

Terraform Workflow

The core Terraform workflow consists of these stages:-

  1. Write: Define infrastructure in a configuration file e.g. main.tf
  2. Initialize: Prepares the working directory so Terraform can run the configuration using terraform init command
  3. Plan: Review the changes Terraform will make to your infrastructure using terraform plan command
  4. Apply: Terraform provisions your infrastructure and update the state file using terraform apply command

Terraform Provider

  • Provider is a plugin that allows Terraform to interact with a specific cloud provider or service
  • Provider provides abstraction above the upstream API and is responsible for understanding API interactions and exposing resources.
  • Major cloud vendors and non-cloud vendors can write, maintain, or collaborate on Terraform providers
  • At least one provider block is required in terraform configuration.
  • Supports multiple provider instances using alias e.g. multiple aws provides with a different region

Input Variables

  1. The name of a variable can be any valid identifier except the following:- source, version, providers, count, for_each, lifecycle, depends_on, locals.
  2. The type of a variable can be string, number, bool, list, set, map, object, and tuple.
  3. The nullable argument in variable block can be set to false to not allow null values. Default is true.
  4. The validation argument in variable block can be used to apply custom validation on the value
  5. The sensitive argument in variable block can be set to true to prevent from showing its value in the plan and apply output
variable "image_id" {
  type        = string
  description = "The id of the machine image (AMI) to use for the server."
  default     = ami-abc123
  nullable    = false
  sensitive   = false

  validation {
    condition     = length(var.image_id) > 4 && substr(var.image_id, 0, 4) == "ami-"
    error_message = "The image_id value must be a valid AMI id, starting with \"ami-\"."

The loading of a variable goes from highest precedence (1) to lowest (5):-

  1. Command line flag - specify in command using -var e.g. terraform plan -var=environment="prod"
  2. Configuration file - set in your terraform.tfvars file
  3. Environment variable - part of your shell environment e.g. TF_VAR_environment=prod
  4. Default Config - default value in variables.tf
  5. User manual entry - if not specified, prompt the user for entry

Terraform Backend

  • A backend defines where Terraform stores its state data files. There are two backend types: local and remote.
  • By default, Terraform uses a backend called local, which stores state as a local file on disk.
  • Terraform v1.4.x supports the following backend types:- local, remote, azurerm, consul, cos, gcs, http, kubernetes, oss, pg, s3
  • Terraform v1.2.x also supports following backend types:- artifactory, etcd, etcdv3, manta, swift
  • Backend types support state locking:- local, remote, azurerm, consul, cos, gcs, http, kubernetes, oss, pg, s3, etcdv3, manta, swift
  • Backend types doesn’t support state locking:- artifactory, etcd
  • A terraform configuration terraform block can only have one backend block.
    terraform {
      backend "remote" {
        organization = "example_corp"
        workspaces {
          name = "my-app-prod"
  • Terraform Cloud automatically manages state in the workspaces. If your configuration includes a cloud block, it cannot include a backend block.
    terraform {
      cloud {
        organization = "example_corp"
        ## Required for Terraform Enterprise; Defaults to app.terraform.io for Terraform Cloud
        hostname = "app.terraform.io"
        workspaces {
          tags = ["app"]
  • It is recommended to provide credentials and sensitive data using the credential file or environment variable supported by the remote backend type.
  • You must run terraform init when you change backend configuration or backend type. Terraform auto-detects the changes and can migrate from existing state to new configuration.

Terraform Type Constraints

CategoryTypeExampleReference Value
Primitivestringvariable "image_id" { type=string default="ami-abc123"}var.image_id
Primitivenumbervariable "threads" { type=number default=10 }var.threads
Primitiveboolvariable "set_password" { type=bool default=false }var.set_password
Collectionlistvariable "az_names" { type=list(string) default=["us-west-1a", "us-west-2a"]}var.az_names[0]
Collectionsetvariable "az_names" { type=set(string) default=["us-west-1a", "us-west-2a"]}var.az_names[0]
Collectionmapvariable "amis" { type="map" default={ "us-east-1"="ami-b374d5a5" "us-west-2"="ami-4b32be2b" }}var.amis["us-east-1"]
Structuralobjectvariable "user_info" { type=object({ name=string address=string })}var.user_info.name
Structuraltuplevariable "var1" { type=tuple([string, number, bool]) default=["a", 15, true] }var.var1[0]

Source: https://developer.hashicorp.com/terraform/language/expressions/type-constraints

References to Named Values

Input Variablevar.<NAME>var.ami
Local Valueslocal.<NAME>local.ami
Resources<RESOURCE TYPE>.<NAME>.<ATTRIBUTE>aws_instance.example.ami
Data Sourcesdata.<DATA TYPE>.<NAME>.<ATTRIBUTE>data.aws_ami.ubuntu.id
Child Module Outputsmodule.<MODULE NAME>.<OUTPUT NAME>module.prod_subnet.subnet_id

Source: https://developer.hashicorp.com/terraform/language/expressions/references

Environment Variables

Environment VariableExample
TF_LOGTF_LOG=trace|debug|info|warn|error to enable logs at different log level
TF_LOG=off to disable logs
TF_LOG=json to generate logs in JSON format
TF_LOG_COREto enable/disable logging separately for terraform core, values same as TF_LOG
TF_LOG_PROVIDERto enable/disable logging separately for terraform providers, values same as TF_LOG
TF_LOG_PATHto specify where the log should persist its output to e.g. TF_LOG_PATH=./terraform.log , by default logs appear on stderr
TF_VAR_nameto set the variables e.g. region variable TF_VAR_region=us-east1

Terraform Commands

Command ▼Description
terraform init1. First command to run. Safe to run it multiple times
2. Initialize a working directory that contains terraform configuration files:-
- create hidden .terraform directory
- configure backend, download and install provider plugins into .terraform/providers
- download modules into .terraform/modules
- create dependency lock file.terraform.lock.hcl
3. Use terraform init -from-module=MODULE-SOURCE to check out the configuration from VCS and initialize the current working directory.
4. Use terraform init -backend-config=PATH for partial backend configuration, in situations where the backend settings are dynamic or sensitive and so cannot be statically specified in the configuration file.
terraform getUse to download and update modules mentioned into a .terraform subdirectory of the current working directory.
terraform plan1. Creates an execution plan, which lets you preview the changes that Terraform plans to make to your infrastructure
2. Reads the current state of any already-existing remote objects to make sure that the Terraform state is up-to-date.
3. Compares the current configuration to the prior state and noting any differences.
4. Proposes a set of change actions that should, if applied, make the remote objects match the configuration.
5. You can use the optional -out=FILE option to save the generated plan to a file on disk
6. Terraform has two alernative planning modes: -destroy and -refresh-only
7. Terraform has following planning options:- -refresh=false, -replace=ADDRESS, -target=ADDRESS, -var 'NAME=VALUE', and -var-file=FILENAME
8. Terraform planning mode and planning options are available for both terraform plan and terraform apply
terraform apply1. Apply the execution plan to provision the resources
2. You can pass the -auto-approve option to instruct Terraform to apply the plan without asking for confirmation.
terraform destroy1. Destroy all remote objects managed by a particular Terraform configuration.
2. This command is effectively an alias for terraform apply -destroy
terraform login1. terraform login [hostname] is used to automatically obtain and save an API token for Terraform Cloud, Terraform Enterprise, or any other host that offers Terraform services.
2. If you don’t provide an explicit hostname, Terraform will assume you want to log in to Terraform Cloud at app.terraform.io
terraform logout1. terraform logout [hostname] is used to remove credentials stored by terraform login. These credentials are API tokens for Terraform Cloud, Terraform Enterprise, or any other host that offers Terraform services.
2. If you don’t provide an explicit hostname, Terraform will assume you want to log out of Terraform Cloud at app.terraform.io
terraform consoleProvides an interactive command-line console for evaluating and experimenting with expressions.
terraform fmt1. Format code in terrform style convention
2. Indent two space for each nesting level and align equals signs at same nesting level
3. terraform fmt -diff displays diff of formatting changes
terraform validate1. Validates the configuration files in a directory, referring only to the configuration and not accessing any remote services such as remote state, provider APIs, etc.
2. Verify whether a configuration is syntactically valid and internally consistent, regardless of any provided variables or existing state
3. terraform validate -json produce validation result in JSON format
terraform graph1. Used to generate a visual representation of either a configuration or execution plan. The output is in the DOT format, which can be used by GraphViz to generate image or charts e.g. terraform graph | dot -Tsvg > graph.svg
2. Use optional -plan tfplan option to render graph using specified plan file
terraform output1. Used to extract the value of an output variable from the state file.
2. Use optional -json and -raw option for output to formatted as JSON and String format. Any sensitive values in Terraform state will be displayed in plain text.
terraform show1. Used to provide human-readable output from a state or plan file
2. Use optional -json option for JSON representation of plan, configuration, and current state
terraform state1. The terraform state command and its subcommands can be used for various tasks related to the Terraform state.
2. The terraform state pull and terraform state push subcommands can be used to retrieve and upload the Terraform state from and to a remote backend, respectively. This is useful when multiple users or systems are working with the same Terraform configuration.
terraform state mvUsed in the less common situation where you wish to retain an existing remote object but track it as a different resource instance address in Terraform, such as if you have renamed a resource block or you have moved it into a different module in your configuration.
terraform state rmUsed in the less common situation where you wish to remove a binding to an existing remote object without first destroying it, which will effectively make Terraform “forget” the object while it continues to exist in the remote system.
terraform state replace-providerUsed to replace the provider for resources in a Terraform state e.g. terraform state replace-provider hashicorp/aws registry.acme.corp/acme/aws replaces the hashicorp/aws provider by achme
terraform state listUsed to list resources within a Terraform state.
terraform state showUsed to show attributes of a single resource in the terraform state e.g. terraform state show aws_instance.foo
terraform refresh1. This command read the remote infrastructure and update the terraform state file to match with remote objects.
2. This won’t modify your real remote objects, but it will modify the terraform state file.
3. This command is here primarily for backward compatibility, but we don’t recommend using it because it provides no opportunity to review the effects of the operation before updating the state.
4. Equivalent command in Terraform v0.15.4 or later is terraform apply -refresh-only -auto-approve
5. It is recommended to use terraform apply -refresh-only or terraform plan -refresh-only instead, which gives an opportunity to review the changes.
terraform taint1. Informs Terraform that a particular object has become degraded or damaged. Terraform represents this by marking the object as “tainted” in the Terraform state, and Terraform will propose to replace it in the next plan you create.
2. Use the -replace option with terraform apply For Terraform v0.15.2 and later
terraform force-unlock1. Manually unlock the state for the defined configuration.
2. This command removes the lock on the state for the current configuration. The behavior of this lock is dependent on the backend being used
terraform workspace1. Terraform workspace command is used to manage worsspaces
2. State files for each workspace are stored in the directory terraform.tfstate.d
3. terraform workspace list to list all existing workspaces
4. terraform workspace select prod to switch to existing workspace with name prod
5. terraform workspace new uat to create and switch to new workspace with name uat
6. terraform workspace delete dev to delete existing workspace with name dev and it must not be your current workspace
7. terraform workspace show to show current workspace
terraform importUsed to import the existing remote resources into the Terraform state file. This allows Terraform to manage resources that were created outside of Terraform.

terraform import command used using below three steps:-

//1. first write empty resource block in config *.tf* file
resource "aws_instance" "example" {
  # ...instance configuration...

//2. then run command to import existing remote aws instance with id i-abcd1234 to state *.tfstate* file
$ terraform import aws_instance.example i-abcd1234

//3. copy the required configuration manually from state .tfstate file to config *.tf* file

Source: https://developer.hashicorp.com/terraform/cli

Terraform Functions

Function TypeFunction Name
Numericabs(-12.4) = 12.4
ceil(5.1) = 6
floor(4.9) = 4
log(16, 2) = 4
max(12, 54, 3) = 54
min(12, 54, 3) = 3
parseint("100", 10) = 100 and parseint("FF", 16) = 255
pow(3, 2) = 9
signum(-13) = -1, signum(0) = 0, and signum(344) = 1
Stringchomp("hello\r\n") = hello
startswith("hello world", "hello") = true
endswith("hello world", "world") = true
format("There are %d lights", 4) = There are 4 lights
formatlist("Hello, %s!", ["Olivia", "Sam"]) = ["Hello, Olivia!", "Hello, Sam!"]
indent(5, "hello") = ・・・・・"hello"
join("-", ["foo", "bar", "baz"]) = foo-bar-baz
lower("HELLO") = hello
upper("hello") = HELLO
regex("[a-z]+", "53453453.345345aaabbbccc23454") = aaabbbccc
regexall("[a-z]+", "1234abcd5678efgh9") = ["abcd", "efgh"]
replace("1 + 2 + 3", "+", "-") = 1-2-3
split(",", "foo,bar,baz") = ["foo","bar","baz"]
strrev("hello") = olleh
substr("hello world", 1, 4) = ello
title("hello world") = Hello World
trim("foobar", "far") = oob
trimprefix("helloworld", "hello") = world
trimsuffix("helloworld", "world") = hello
trimspace(" hello\n\n") = hello
Collectionalltrue(["true", true]) = true
anytrue([true, false]) = true
coalesce("a", "b") = a and coalesce("", "b") = b
coalescelist(["a", "b"], ["c", "d"]) = ["a", "b"] and coalescelist([], ["c", "d"]) = ["c", "d"]
compact(["a", "", "b", "c"]) = ["a", "b", "c"]
concat(["a", ""], ["b", "c"]) = ["a", "", "b", "c"]
contains(["a", "b", "c"], "a") = true
distinct(["a", "b", "a", "c", "d", "b"]) = ["a", "b", "c", "d"]
element(["a", "b", "c"], 1) = b
flatten([["a", "b"], [], ["c"]]) = ["a", "b", "c"]
index(["a", "b", "c"], "b") = 1
keys({a=1, c=2, d=3}) = ["a", "b", "d"]
length(["a", "b"]) = 2
tolist([a, b, c]) converts to list
tomap({a = "b" c = "d"}) converts to map
range(3) = [0, 1, 2] and range(1, 4) = [1, 2, 3]
reverse([1, 2, 3]) = [3, 2, 1]
setintersection(["a", "b"], ["b", "c"], ["b", "d"]) = ["b"]
setsubtract(["a", "b", "c"], ["a", "c"]) = ["b"]
setunion(["a", "b"], ["b", "c"], ["d"]) = ["d", "b", "c", "a"]
slice(["a", "b", "c", "d"], 1, 3) = ["b", "c"]
sort(["e", "d", "a", "x"]) = ["a", "b", "e", "x"]
sum([10, 13, 6, 4.5]) = 33.5
values({a=3, c=2, d=1}) = [3, 2, 1]
zipmap(["a", "b"], [1, 2]) = {"a"=1 "b"=2}
Encodingbase64encode("Hello World") = SGVsbG8gV29ybGQ=
base64decode("SGVsbG8gV29ybGQ=") = Hello World
textencodebase64("Hello World", "UTF-16LE") = SABlAGwAbABvACAAVwBvAHIAbABkAA==
textdecodebase64("SABlAGwAbABvACAAVwBvAHIAbABkAA==", "UTF-16LE") = Hello World
urlencode("Hello World!") = Hello+World%21
Filesystemabspath(path.root) = /home/user/some/terraform/root
dirname("foo/bar/baz.txt") = foo/bar
pathexpand("~/.ssh/id_rsa") = /home/steve/.ssh/id_rsa
basename("foo/bar/baz.txt") = baz.txt
file("${path.module}/hello.txt") = Hello World
fileexists("${path.module}/hello.txt") = true
fileset(path.module, "files/*.txt") = ["files/hello.txt", "files/world.txt"]
filebase64("${path.module}/hello.txt") = SGVsbG8gV29ybGQ=
templatefile(path, vars)
Date and Timeformatdate("DD MMM YYYY hh:mm ZZZ", "2018-01-02T23:12:01Z") = 02 Jan 2018 23:12 UTC
timeadd("2017-11-22T00:00:00Z", "10m") = 2017-11-22T00:10:00Z
timecmp("2017-11-22T00:00:00Z", "2017-11-22T01:00:00Z") = -1
timestamp() = 2023-05-13T07:44:12Z
Hash and Cryptobase64sha256("hello world") = uU0nuZNNPgilLlLX2n2r+sSE7+N6U4DukIj3rOLvzek=
base64sha512("hello world") = MJ7MSJwS1utMxA9QyQLytNDtd+5RGnx6m808qG1M2G+YndNbxf9JlnDaNCVbRbDP2DDoH2Bdz33FVC6TrpzXbw==
md5("hello world") = 5eb63bbbe01eeed093cb22bb8f5acdc3
sha1("hello world") = 2aae6c35c94fcfb415dbe95f408b9ce91ee846ed
sha256("hello world") = b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9
sha512("hello world") = 309ecc489c12d6eb4cc40f50c902f2b4d0ed77ee511a7c7a9bcd3ca86d4cd86f989dd35bc5ff499670da34255b45b0cfd830e81f60
bcrypt("hello world") = $2a$10$D5grTTzcsqyvAeIAnY/mYOIqliCoG7eAMX0/oFcuD.iErkksEbcAa
rsadecrypt(filebase64("${path.module}/ciphertext"), file("privatekey.pem")) = hello world
uuid() = b5ee72a3-54dd-c4b8-551c-4bdc0204cedb
uuidv5("dns", "www.terraform.io") = a5008fae-b28c-5ba5-96cd-82b4c53552d6
IP Networkcidrhost, cidrnetmask, cidrsubnet, cidrsubnets
Type Conversioncan, nonsensitive, sensitive, tobool, tolist, tomap, tonumber, toset, tostring, try, type

Source: https://developer.hashicorp.com/terraform/language/functions

Terraform Tiers

Feature ▼OSS (Open Source)Cloud FreeCloud Team & GovernanceCloud BusinessEnterprise
Infrastructure as code (HCL)
Runs (separate plan and apply)
Resource graph
Public registry
Remote state storage
Secure variable storage
Remote runs (plan & apply)
Private registry
Dynamic provider credentials
Run triggers
VCS connection
Workspace management
Team management
Cost estimation
Policy as code (Sentinel)
Policy as code (OPA)
Run tasks: Advisory enforcement
Run tasks: Hard enforcement
Policy enforcement level: Advisory
Policy enforcement level: Soft/hard mandatory
No-code provisioning
Configuration designer
SSO (Single Sign On)
Support for ServiceNow integration
Drift detection
Audit logging
Concurrent Runs12(Add-on)Pay to customize
Self-hosted agentsPay to customize
Cross-organization registry sharing
Runtime metrics (Prometheus)
Air gap network deployment
Application-level logging
Log forwarding
Clustered Horizontal Scaling

Source: https://www.hashicorp.com/products/terraform/pricing

Practice Exam Questions

Follow the next post for 200+ Practice questions:- Hashicorp Terraform Associate (003) Exam Questions