Free HashiCorp Terraform Associate 004 practice test

20 questions for the HashiCorp Terraform Associate (004) exam, taken from our 282-question bank and spread across its 8domains by their weighting. No sign-up needed: pick an answer to check it, or open “Show answer & explanation” under any question.

What this test covers

Question 1 · Infrastructure as Code (IaC) with Terraform

A Terraform configuration creates an Azure Virtual Network. An engineer runs terraform apply and the network is created successfully. Two days later, another engineer manually resizes the address space via the Azure portal. When the first engineer runs terraform apply again without changing any configuration files, what is the MOST likely outcome?

Show answer & explanation

Correct answer: B

  • B. Terraform will detect the drift between the desired state in the configuration and the actual state in Azure, and will modify the Virtual Network to match the configuration.

Option B is correct: this is Terraform's idempotency in action. On the second apply, Terraform refreshes state, detects that the live resource differs from the desired configuration, and generates a plan to reconcile the drift by updating the address space back to the configured value. Option A is wrong; Terraform does not simply skip existing resources — it compares current state to desired state on every apply. Option C is incorrect; Terraform does not destroy and recreate an entire resource group for a single attribute change unless the specific attribute forces replacement. Option D is false; Terraform handles drift reconciliation automatically and does not redirect users to the console.

Question 2 · Infrastructure as Code (IaC) with Terraform

A DevOps team currently provisions AWS resources by manually clicking through the AWS Management Console. A senior engineer argues they should migrate to Terraform. Which TWO benefits of Infrastructure as Code directly address the risks of manual console-based provisioning?

Select 2 answers.

Show answer & explanation

Correct answers: A, C

  • A. Configurations can be stored in version control, providing a full history of every infrastructure change.
  • C. Infrastructure changes are consistent and repeatable, eliminating configuration drift caused by human error.

Correct (A, C): Version control (A) solves the auditability problem — every change is tracked, attributed, and reversible, which is impossible with manual console clicks. Consistency and repeatability (C) solve configuration drift — the same Terraform configuration always produces the same infrastructure, whereas humans clicking through a console make mistakes and produce subtly different environments. (B) is wrong — Terraform does not analyze or select cloud regions based on cost; that is outside its scope. (D) is wrong — Terraform does not natively compress or encrypt S3 state files; encryption must be configured at the S3 bucket level or via a KMS key in the backend config. (E) is wrong — Terraform produces no compliance PDF reports; that is the domain of separate audit/compliance tools.

Question 3 · Infrastructure as Code (IaC) with Terraform

A team runs terraform apply on Monday and successfully creates an S3 bucket. On Wednesday, a developer manually deletes the bucket via the AWS CLI. On Thursday, the team runs terraform apply again with the exact same configuration file and no code changes. What will Terraform do?

Show answer & explanation

Correct answer: A

  • A. Terraform will detect that the bucket is missing compared to the desired state and will recreate it to match the configuration.

Correct (A): This scenario demonstrates Terraform's idempotency. On the second terraform apply, Terraform runs a refresh (comparing the real infrastructure to the state file), detects that the S3 bucket no longer exists, and creates it again to reconcile the real world with the desired state. The configuration has not changed, but the actual infrastructure has drifted. (C) is wrong — Terraform does not compare configuration-to-configuration; it compares desired state to actual state, so it will detect the drift. (B) is wrong — a missing resource does not cause an error during plan/apply; Terraform treats it as a resource that needs to be created. (D) is wrong — Terraform does not require manual user intervention for missing resources; it handles recreation automatically.

Question 4 · Terraform fundamentals

An engineer runs terraform plan and sees the + symbol next to several resources. What does this symbol indicate?

Show answer & explanation

Correct answer: C

  • C. The resource does not yet exist and will be created when terraform apply is run.

Correct: C. The + symbol in a Terraform plan output means the resource is planned for creation — it does not currently exist in the Terraform state and will be provisioned when apply is executed. A is wrong — removing a resource from state without destroying infrastructure is done with terraform state rm, which does not appear as + in a plan. B is wrong — destroy-and-recreate is represented by the -/+ symbol, not +. D is wrong — in-place updates to existing resources are represented by the ~ symbol.

Question 5 · Terraform fundamentals

A senior engineer is auditing a Terraform project and finds the following locals block:

locals {
  env_prefix = "${var.environment}-${var.region}"
  full_name  = "${local.env_prefix}-app"
}

Which of the following statements about this configuration is correct?

Show answer & explanation

Correct answer: C

  • C. This is valid; local values may reference input variables and other local values defined in the same block.

Option C is correct: Terraform's locals block supports arbitrary expressions including references to var.*, data.*, and other local.* values. Terraform resolves locals using dependency ordering, so full_name depending on env_prefix within the same block is perfectly valid — Terraform figures out the correct evaluation order automatically. Option A is wrong — locals can freely reference input variables. Option B is wrong — cross-references within the same locals block are allowed as long as there are no cycles. Option D is wrong — there is no requirement to split dependent locals across separate blocks; a single block is fine.

Question 6 · Terraform fundamentals

Which of the following statements about the terraform block (the special top-level block) are TRUE? (Select TWO)

Select 2 answers.

Show answer & explanation

Correct answers: A, C

  • A. The terraform block can be used to configure the required Terraform CLI version using the required_version argument.
  • C. The terraform block is used to configure the backend, specifying where Terraform stores its state file.

Correct: A and C. The terraform block serves two primary purposes relevant here: (A) It accepts a required_version constraint that enforces which versions of the Terraform CLI can be used with the configuration, preventing accidental use with incompatible versions. (C) It accepts a backend block (nested within the terraform block) that configures where state is stored (e.g., S3, Azure Blob, HCP Terraform). B is wrong — default_tags is an argument supported within the AWS provider configuration block (under provider "aws"), not in the terraform block itself. D is wrong — the terraform block cannot contain resource definitions; resources are declared in separate top-level resource blocks. E is wrong — required_providers can reference providers from any source, including third-party registries and even local filesystem paths, not only the official HashiCorp registry.

Question 7 · Core Terraform workflow

A Terraform engineer is troubleshooting a situation where two resources have a dependency that cannot be expressed through attribute references. The configuration manages an AWS Lambda function and an S3 bucket policy. The Lambda reads from the bucket, but the bucket policy ARN is not directly referenced in the Lambda configuration. The engineer adds depends_on to the Lambda resource pointing to the bucket policy. What is a known side effect of using depends_on on a resource (as opposed to expressing the dependency through a reference)?

Show answer & explanation

Correct answer: C

  • C. When depends_on is used on a resource, Terraform treats all attributes of that resource as unknown during planning if the dependency has any pending changes, which can cause a more conservative and less informative plan.

Option C is correct. When depends_on is applied to a resource (or module), Terraform cannot use its normal fine-grained dependency analysis. If the depends_on target has any pending changes, Terraform must treat the dependent resource's attributes as unknown during planning — because any side effect could theoretically change what values are produced. This results in a less informative plan where values show as (known after apply) even when they could otherwise be known. Option B is wrong — depends_on is purely a planning-time directive; Terraform does not pre-validate the existence of the target in real infrastructure. Option A is partially related but is specifically a behavior of depends_on on modules, not resources, and the mechanism described is not quite accurate. Option D is wrong — depends_on does not cause unconditional replacement; it only affects ordering and planning granularity.

Question 8 · Core Terraform workflow

A team's Terraform configuration has the following two resources. The aws_security_group is referenced by the aws_instance via its ID attribute:

resource "aws_security_group" "web" { ... }

resource "aws_instance" "web" {
  security_groups = [aws_security_group.web.id]
  ...
}

A senior engineer suggests also adding an explicit depends_on = [aws_security_group.web] to the aws_instance. What is the impact of adding this explicit dependency?

Show answer & explanation

Correct answer: B

  • B. It is redundant because Terraform already infers the dependency from the attribute reference; adding depends_on has no functional effect but may cause Terraform to be more conservative in planning

Option B is correct: attribute references (e.g., aws_security_group.web.id) implicitly create dependency ordering in Terraform's graph. Adding depends_on on top of an already-implied dependency is redundant. However, Terraform's documentation notes that depends_on can cause Terraform to be more conservative—when depends_on is present, Terraform may replace resources more aggressively if the dependency changes, which is why it is recommended to use depends_on only when necessary. Option D is incorrect: attribute references do create implicit ordering. Option C is incorrect: depends_on does not trigger replacement; it only affects ordering. Option A is a partial truth—Terraform does serialize work when dependencies exist, but adding an already-implied depends_on does not newly prevent parallelism that was not already prevented by the reference.

Question 9 · Core Terraform workflow

A Terraform configuration manages both an aws_security_group and an aws_instance. The aws_instance resource references the security group's ID using an expression (vpc_security_group_ids = [aws_security_group.web.id]). A team member suggests adding an explicit depends_on = [aws_security_group.web] to the aws_instance block as well. Which of the following BEST describes the impact of adding this explicit dependency?

Show answer & explanation

Correct answer: D

  • D. Adding depends_on is redundant but harmless; Terraform already infers the dependency from the reference expression, and the explicit depends_on does not change ordering behavior.

Correct: B. When a resource expression references another resource's attribute (e.g., aws_security_group.web.id), Terraform automatically infers an ordering dependency. Adding an explicit depends_on for the same resource is therefore redundant—the ordering is already established. The duplicate depends_on does not alter the plan or apply behavior. A is wrong because Terraform's reference-based implicit dependency is sufficient for ordering; depends_on is only needed when a dependency exists that cannot be expressed through references (e.g., a hidden side effect). C is wrong because depends_on affects ordering, not the set of attributes tracked for change detection; it does not cause unnecessary replacements. D is wrong because switching from an implicit to an explicit dependency (or having both) does not trigger a replace—the resource configuration itself has not changed.

Question 10 · Terraform configuration

A developer is configuring an AWS Auto Scaling group and wants to dynamically generate tag blocks based on a variable map, rather than hardcoding each tag block. The number of tags varies per environment. Which Terraform feature is best suited for this?

Show answer & explanation

Correct answer: A

  • A. A dynamic block with a for_each argument iterating over the tags map.

Option A is correct: dynamic blocks are specifically designed to programmatically generate repeated nested blocks (like tag blocks in aws_autoscaling_group) based on a collection. Using for_each within the dynamic block iterates over the map and produces one tag block per entry.

Option B is wrong: count controls how many instances of the entire resource are created, not how many nested blocks exist within a single resource instance.

Option C is wrong: multiple locals blocks do not generate nested blocks inside a resource. They only define reusable values within a module.

Option D is wrong: a for expression can produce a list or map value, but the tag argument in aws_autoscaling_group requires repeated blocks, not a list value. You cannot substitute a for expression for repeated block syntax — that is exactly what dynamic blocks solve.

Question 11 · Terraform configuration

A team stores a list of allowed CIDR blocks in a variable and needs to pass a set of unique CIDRs to an AWS security group resource that expects type = set(string). The variable is declared as type = list(string). Which built-in function converts the list to a set, removing any duplicate entries?

Show answer & explanation

Correct answer: A

  • A. toset()

Option A is correct: toset() converts a list (or other collection) to a set, automatically removing duplicate values and dropping order, which matches the set(string) type expected by the resource.

Option C is wrong: distinct() removes duplicate elements from a list but returns a list, not a set. The resource still expects a set(string), so a type mismatch would occur.

Option B is wrong: tolist() converts a set or tuple to a list — it goes in the opposite direction of what is needed here.

Option D is wrong: compact() removes empty strings from a list of strings but does not remove non-empty duplicates, and it returns a list, not a set.

Question 12 · Terraform modules

A root module calls a child module and needs to pass a complex object as an input. The child module's variables.tf declares the following:

variable "tags" {
  type = map(string)
  default = {}
}

Which module call correctly passes a tags map to this variable?

Show answer & explanation

Correct answer: B

  • B. module "app" { source = "./modules/app" tags = { env = "prod" team = "platform" } }

Option B is correct: a map(string) variable is assigned using HCL object literal syntax with key-value pairs inside curly braces. Option D is wrong because it passes a list of strings (using square brackets), which does not match the map(string) type and will cause a type mismatch error. Option A is wrong because module input arguments are specified by the variable name alone (without the var. prefix); var.tags = ... is not valid syntax in a module block. Option C is wrong because passing a single comma-delimited string does not match the map(string) type constraint.

Question 13 · Terraform modules

A root module calls a child module named database. The child module exposes an output called connection_string. How does the root module correctly reference this output to pass it as an input to another module called app?

Show answer & explanation

Correct answer: D

  • D. module.database.connection_string

Option D is correct: child module outputs are referenced using the syntax module.<MODULE_NAME>.<OUTPUT_NAME>. Option C is wrong because var. references input variables, not module outputs. Option A is wrong because the .outputs. segment is not part of the reference syntax — Terraform does not use that intermediate key. Option B is wrong because output. is not a valid reference prefix for accessing another module's outputs from the root module.

Question 14 · Terraform state management

A HCP Terraform workspace is configured with a remote backend. A developer runs terraform state pull from their local machine. What does this command do, and what format is the output?

Show answer & explanation

Correct answer: B

  • B. It downloads the current state file from the remote backend and prints it to stdout in raw JSON format

terraform state pull retrieves the current state from the configured backend (including remote backends like HCP Terraform) and prints it to stdout as raw JSON. This is useful for inspecting state, piping it to tools like jq, or creating a local backup. Option C is wrong: state pull does not perform a diff; it simply retrieves and prints the current state. Option D is wrong: state pull is a read-only operation and does not acquire a lock (state-modifying commands like apply acquire locks). Option A is wrong: state pull writes to stdout, not to a file; if you want to save it, you redirect stdout (e.g., terraform state pull > backup.tfstate).

Question 15 · Terraform state management

A Terraform configuration manages a fleet of aws_instance resources using for_each with the following map variable:

variable "servers" {
  default = {
    web  = "t3.micro"
    api  = "t3.small"
    jobs = "t3.medium"
  }
}

resource "aws_instance" "fleet" {
  for_each      = var.servers
  instance_type = each.value
  ami           = "ami-0abcdef1234567890"
}

A team member removes the web key from the map variable and runs terraform apply. What happens?

Show answer & explanation

Correct answer: C

  • C. Terraform destroys aws_instance.fleet["web"] and leaves the other instances untouched

Option C is correct: with for_each, each resource instance is keyed by the map key ("web", "api", "jobs"). Removing "web" causes Terraform to plan the destruction of only aws_instance.fleet["web"]; the other keyed instances are unaffected because their keys remain stable. Option A is incorrect: this behavior describes the problem with count-based indexing, not for_each. Option D is also a count misconception—index shifting does not apply to for_each. Option B is incorrect: there is no requirement to manually terraform state rm before removing a for_each key; Terraform handles the removal through a normal plan/apply cycle.

Question 16 · Maintain infrastructure with Terraform

A team wants to upgrade all providers used in their configuration to the newest versions permitted by their existing version constraints, and update the dependency lock file accordingly. Which command should they run?

Show answer & explanation

Correct answer: D

  • D. terraform init -upgrade

Option D is correct. terraform init -upgrade re-resolves provider (and module) version selections to the newest versions allowed by the configuration's constraints, updating .terraform.lock.hcl to record the new selections. Option A is incorrect — terraform providers upgrade is not a real subcommand; terraform providers on its own just reports the provider requirements tree. Option C is incorrect — apply has no -upgrade-providers flag; provider resolution happens during init, not apply. Option B is a real but riskier path — deleting the lock file does force Terraform to re-resolve on the next init, but terraform validate does not perform provider installation or lock-file writing at all, so this sequence wouldn't actually upgrade or re-lock anything by itself.

Question 17 · Maintain infrastructure with Terraform

A team decommissions a Terraform-managed Redis cache but wants to keep it running in production, managed manually going forward, while removing it from Terraform's purview entirely. Which command accomplishes exactly this?

Show answer & explanation

Correct answer: B

  • B. terraform state rm aws_elasticache_cluster.cache

Option B is correct. terraform state rm deletes a resource's entry from state while leaving the real infrastructure completely untouched, which is exactly 'stop managing this, but don't delete it.' The resource block should also be removed from configuration afterward so a future plan doesn't try to recreate it. Option A is incorrect and dangerous here — terraform destroy -target would delete the actual Redis cluster, not just stop tracking it. Option D is incorrect — -replace destroys and recreates the resource, which is not the goal. Option C is incorrect — terraform state mv only renames or relocates the state entry; the resource would remain fully managed by Terraform under a new address, not released from management.

Question 18 · HCP Terraform

An operator is reviewing a failed HCP Terraform run. The run log shows: 'Policy check soft failed.' The operator does not have the 'Manage Policy Overrides' permission. What will happen to this run?

Show answer & explanation

Correct answer: C

  • C. The run is paused at the policy check stage and requires a user with the 'Manage Policy Overrides' permission to override it before the apply can proceed.

Option C is correct. A soft-mandatory Sentinel policy failure pauses the run and requires a user with the 'Manage Policy Overrides' permission to explicitly override the failure before the apply step is unlocked. The current operator cannot unblock it themselves due to lacking that permission. Option A is wrong because the run is not discarded—it stays in a paused/needs-override state. Option B is wrong because soft-mandatory failures DO block the run; only advisory failures are non-blocking. Option D is wrong because the apply gating is based on the override permission, not on whether the plan produces changes.

Question 19 · HCP Terraform

When HCP Terraform performs cost estimation for a plan, which statement accurately describes its behavior and limitations?

Show answer & explanation

Correct answer: B

  • B. Cost estimation provides a monthly cost delta between the prior state and the planned state for a supported subset of AWS, Azure, and GCP resources, and is shown before the Sentinel policy check stage.

Option B is correct. HCP Terraform's cost estimation feature calculates a projected monthly cost delta—showing the estimated cost before and after the planned changes—for a supported subset of resource types across AWS, Azure, and Google Cloud. Importantly, it is inserted into the run pipeline after the plan but before Sentinel policy checks, allowing policies to act on cost data (e.g., rejecting plans that exceed a cost threshold). Option C is wrong because coverage is not complete for all resource types and does not use real-time billing API queries; it uses static pricing tables. Option A is wrong because cost estimation is prospective (pre-apply), not retrospective. Option D is wrong because cost estimation supports AWS, Azure, and GCP, and does not require any cloud credentials or IAM roles—it works from the plan's resource definitions.

Question 20 · HCP Terraform

A Sentinel policy set is attached to an HCP Terraform organization. A new workspace is created, and its first run fails a policy in that policy set with an 'advisory' enforcement level. Which of the following correctly describes the outcome?

Show answer & explanation

Correct answer: C

  • C. The policy failure is logged and visible in the run details, but the run continues to the apply stage without interruption.

Option C is correct. Advisory enforcement level is purely informational. When an advisory Sentinel policy fails, the failure is recorded and surfaced in the run's policy check section, but it does not gate or pause the run—execution proceeds unimpeded to the apply phase. This level is useful for raising awareness without enforcing hard blockers. Option A is wrong because blocking behavior belongs to soft-mandatory and hard-mandatory levels, not advisory. Option B is wrong because advisory policies never block runs regardless of who is reviewing them. Option D is wrong because HCP Terraform does not have an automatic post-apply rollback mechanism tied to advisory policy violations; Terraform applies are intentionally non-reversible without a separate destroy/re-apply.

Pick an answer on each question to check it. 20 questions in this test.

262 more HashiCorp Terraform Associate 004 questions

Sign up free to start practising, or subscribe (from $4.97/mo) for the full 282-question bank, flashcards and timed mock exams.

HashiCorp Terraform Associate course overview and study guides →