Authentication and Provider Debugging

Scenario: A plan works fine on an engineer's laptop, quietly reusing their personal administrator credentials cached from an earlier login, then fails in CI with a terse, unhelpful authorization error.

Provider authentication - how a plugin proves its identity to the real service's API - is entirely provider-specific, but it's almost never something you should hardcode directly into a provider block or a .tfvars file. Instead, credentials are typically sourced from environment variables, an ambient "workload identity" the runtime environment already provides, or a dedicated secrets broker that hands out short-lived tokens on demand. Prefer that last pattern - short-lived, narrowly-scoped credentials - wherever the provider supports it, because a leaked long-lived key is a much bigger, longer-lasting incident than a leaked token that expires in minutes.

When authentication or authorization fails, work through it systematically rather than guessing: run terraform providers to confirm which provider and version is actually in play, check the provider's schema/documentation for the exact credential fields it expects, look at provider-level debug logs (TF_LOG), and cross-reference the target API's own audit logs for the rejected request. Set TF_LOG and TF_LOG_PATH only temporarily while actively debugging, and always sanitize the resulting file before sharing it - debug logs frequently contain full request bodies, which can include the very credentials you're troubleshooting.

Analogy: Credentials are a building access badge, not part of the architectural blueprint. The blueprint (your configuration) can state which door a worker should use; the actual badge granting entry should be issued to that worker at the moment they show up to work, not baked permanently into the drawings where anyone who ever sees the plans could reuse it.

A worked configuration

provider "fakecloud" {
  # credentials are discovered from the runtime environment
}

# TF_LOG=DEBUG terraform plan
# unset TF_LOG immediately afterward

In CI, identity should be attributable to the specific automated run that used it, never a shared human credential borrowed for convenience - if something goes wrong, you need to trace "which pipeline run did this" instantly, not interview everyone who has ever had admin access. Where a provider supports it, separate the permissions needed to plan (mostly read access) from those needed to apply (write/create/destroy access), so a compromised or misconfigured planning stage can't itself cause damage. Provider debug logs and any exported state should be handled as sensitive incident evidence, kept in a controlled location - never pasted into a public ticket or shared channel.

Common mistakes in production

Goal: Marking a Terraform variable sensitive = true only redacts it from the normal CLI display. It does not stop that value from being written into state, sent as part of a real provider API request, appearing in a TF_LOG=DEBUG log, or sitting inside a saved plan file. Treat all of those artifacts as equally sensitive regardless of the sensitive flag. Reinforce this lesson in the tf-sensitive-outputs Terraform lab. Open /labs/terraform and choose slug tf-sensitive-outputs; the lab runs real Terraform against the offline FakeCloud provider.