What's Actually Happening
Terraform can't authenticate with your cloud provider. The provider plugin attempts to use configured credentials but receives an authentication failure, preventing any infrastructure operations from proceeding.
The Error You'll See
For AWS:
``` Error: error configuring Terraform AWS Provider: no valid credential sources for Terraform AWS Provider found.
Error: error configuring Terraform AWS Provider: error validating provider credentials: error calling sts:GetCallerIdentity: InvalidClientTokenId: The security token included in the request is invalid. status code: 403, request id: a1b2c3d4-e5f6-7890-abcd-ef1234567890 ```
For Azure:
Error: building AzureRM Client: obtain subscription() from Azure CLI: parsing json result from the Azure CLI: waiting for the Azure CLI: exit status 1: ERROR: Please run 'az login' to setup account.For GCP:
Error: google: error getting token: google: could not find default credentials. See https://developers.google.com/accounts/docs/application-default-credentials for more information.Generic provider error:
Error: Failed to query available provider packages
Could not retrieve the list of available versions for provider hashicorp/aws: could not connect to registry.terraform.io: failed to request discovery document: 403 ForbiddenWhy This Happens
The most common authentication failure causes:
- 1.Expired credentials - AWS temporary credentials expired, Azure tokens refreshed
- 2.Missing environment variables -
AWS_ACCESS_KEY_ID,ARM_CLIENT_IDnot set - 3.Incorrect credential files - Pointing to wrong AWS profile or Azure subscription
- 4.MFA requirements - Session requires multi-factor authentication
- 5.Permission boundaries - Credentials lack necessary IAM permissions
- 6.Clock skew - System time significantly different from provider servers
Step 1: Check Current Credential Configuration
Verify what Terraform is using:
```bash # For AWS - check what profile is being used echo $AWS_PROFILE echo $AWS_ACCESS_KEY_ID
# Test credentials directly aws sts get-caller-identity
# For Azure az account show echo $ARM_CLIENT_ID echo $ARM_SUBSCRIPTION_ID
# For GCP gcloud auth list echo $GOOGLE_APPLICATION_CREDENTIALS ```
Enable Terraform debug logging to see authentication attempts:
export TF_LOG=DEBUG
export TF_LOG_PATH=./terraform-debug.log
terraform plan 2>&1 | grep -i authStep 2: Fix AWS Authentication
Configure AWS credentials properly:
```bash # Option 1: Use AWS CLI to configure aws configure # Enter your access key, secret key, region, and output format
# Option 2: Set environment variables directly export AWS_ACCESS_KEY_ID="AKIAIOSFODNN7EXAMPLE" export AWS_SECRET_ACCESS_KEY="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY" export AWS_REGION="us-east-1"
# Option 3: Use a specific profile from ~/.aws/credentials export AWS_PROFILE="production"
# For temporary credentials (STS, SSO) export AWS_SESSION_TOKEN="FwoGZXIvYXdzEBYa..." ```
Verify your AWS credentials work:
```bash # Test basic connectivity aws sts get-caller-identity
# Check credential expiration aws sts get-session-token --query 'Credentials.Expiration' --output text
# If using SSO, re-authenticate aws sso login --profile my-sso-profile ```
Step 3: Fix Azure Authentication
Configure Azure credentials:
```bash # Option 1: Azure CLI login (interactive) az login az account set --subscription "my-subscription-id"
# Option 2: Service Principal with client secret export ARM_CLIENT_ID="00000000-0000-0000-0000-000000000000" export ARM_CLIENT_SECRET="my-client-secret" export ARM_SUBSCRIPTION_ID="00000000-0000-0000-0000-000000000000" export ARM_TENANT_ID="00000000-0000-0000-0000-000000000000"
# Option 3: Use managed identity (on Azure VMs/Functions) export ARM_USE_MSI=true
# Option 4: Service Principal with certificate export ARM_CLIENT_CERTIFICATE_PASSWORD="cert-password" export ARM_CLIENT_CERTIFICATE_PATH="/path/to/cert.pfx" ```
Authenticate and verify:
```bash # Verify you're logged in az account show --output table
# List available subscriptions az account list --query "[].{Name:name, ID:id}" --output table
# If token expired, refresh az account get-access-token --resource https://management.azure.com ```
Step 4: Fix GCP Authentication
Set up Google Cloud credentials:
```bash # Option 1: Application Default Credentials via gcloud gcloud auth application-default login
# Option 2: Service account key export GOOGLE_APPLICATION_CREDENTIALS="/path/to/service-account-key.json"
# Option 3: Set project explicitly export GOOGLE_PROJECT="my-project-id"
# Option 4: Use gcloud CLI auth gcloud auth login gcloud config set project my-project-id ```
Verify GCP authentication:
```bash # Test authentication gcloud auth list
# Verify application default credentials gcloud auth application-default print-access-token
# Test API access gcloud compute instances list --project my-project-id ```
Step 5: Handle Provider Configuration in Code
Explicitly configure providers to avoid ambiguity:
```hcl provider "aws" { region = "us-east-1"
# Use specific profile profile = "production"
# Or use static credentials (not recommended for production) # access_key = var.aws_access_key # secret_key = var.aws_secret_key
# Or assume role assume_role { role_arn = "arn:aws:iam::123456789012:role/TerraformRole" session_name = "terraform-session" } }
provider "azurerm" { features {}
subscription_id = var.subscription_id client_id = var.client_id client_secret = var.client_secret tenant_id = var.tenant_id }
provider "google" { project = "my-project-id" region = "us-central1"
credentials = file(var.credentials_file) } ```
Step 6: Resolve MFA Requirements
When multi-factor authentication is required:
```bash # AWS with MFA aws sts get-session-token \ --serial-number arn:aws:iam::123456789012:mfa/user \ --token-code 123456
# Export the returned credentials export AWS_ACCESS_KEY_ID="ASIAT..." export AWS_SECRET_ACCESS_KEY="..." export AWS_SESSION_TOKEN="..." ```
Verify the Fix
Test authentication with a simple operation:
```bash # AWS - test plan terraform plan -target=aws_vpc.main
# Azure - test plan terraform plan -target=azurerm_resource_group.main
# GCP - test plan terraform plan -target=google_compute_network.main ```
You should see:
Plan: 1 to add, 0 to change, 0 to destroy.No authentication errors should appear.
Security Best Practices
Never commit credentials to version control:
```bash # Add to .gitignore echo "*.pem" >> .gitignore echo "credentials.json" >> .gitignore echo ".env" >> .gitignore echo "secrets.tfvars" >> .gitignore
# Use environment variables or secret managers # AWS Secrets Manager, Azure Key Vault, GCP Secret Manager ```
Use short-lived credentials when possible:
# AWS - use IAM roles with session duration
# Azure - use managed identities
# GCP - use workload identity