How to fix Error: Error creating CloudFront Distribution: AccessDenied in Terraform

TerraformINTERMEDIATEHIGHUpdated Dec 31, 2025ยท 132 views

CloudFront AccessDenied errors occur when your AWS credentials lack required permissions. This guide covers IAM permission issues, S3 bucket policies for origins, and certificate permissions needed for successful distribution creation.

Quick fix

Fixes AccessDenied

# Check environment variables
echo $AWS_ACCESS_KEY_ID
echo $AWS_SECRET_ACCESS_KEY
echo $AWS_PROFILE

# Or verify which profile is active
aws sts get-caller-identity
  1. Verify your AWS credentials and active profile
  2. Add CloudFront permissions to your IAM policy
  3. Grant S3 origin access permissions
  4. Configure Origin Access Control (OAC) for S3
terraform โ€” error
# Check environment variables
echo $AWS_ACCESS_KEY_ID
echo $AWS_SECRET_ACCESS_KEY
echo $AWS_PROFILE
# Or verify which profile is active
aws sts get-caller-identity
Error: Error creating CloudFront Distribution: AccessDenied

What this error means

When Terraform attempts to create a CloudFront distribution, AWS returns an AccessDenied error if your credentials don't have the necessary CloudFront permissions. This is a credential/IAM issue rather than a Terraform configuration problem. CloudFront requires multiple permission levels: permissions to create the distribution itself, permissions to access origins (like S3 buckets), and permissions for any SSL/TLS certificates you're using. The error occurs during plan or apply when Terraform tries to communicate with AWS CloudFront APIs.

Typical symptoms

  • Terraform plan fails with 'Error creating CloudFront Distribution: AccessDenied'
  • Error occurs even though the Terraform configuration looks correct
  • Similar operations work fine for other AWS services but CloudFront fails
  • Running apply doesn't prompt for bucket creation - fails immediately

Common causes

  1. IAM user or role lacks cloudfront:CreateDistribution permission
  2. Missing S3 origin access permissions or bucket policy for CloudFront
  3. ACM certificate permissions not granted to the IAM role
  4. Using wrong AWS profile or credentials with insufficient privileges

How to fix "Error: Error creating CloudFront Distribution: AccessDenied"

1Verify your AWS credentials and active profile

Check which AWS credentials Terraform is using by examining environment variables and the Terraform AWS provider configuration.

bash
# Check environment variables
echo $AWS_ACCESS_KEY_ID
echo $AWS_SECRET_ACCESS_KEY
echo $AWS_PROFILE

# Or verify which profile is active
aws sts get-caller-identity

The output shows the account ID and IAM user/role being used. Note this for the next step.

2Add CloudFront permissions to your IAM policy

Attach a policy to your IAM user or role that grants CloudFront permissions. The minimal policy includes cloudfront:CreateDistribution, cloudfront:UpdateDistribution, and related actions.

json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "cloudfront:CreateDistribution",
        "cloudfront:UpdateDistribution",
        "cloudfront:GetDistribution",
        "cloudfront:ListDistributions",
        "cloudfront:DeleteDistribution",
        "cloudfront:GetDistributionConfig",
        "cloudfront:TagResource"
      ],
      "Resource": "*"
    }
  ]
}

Go to the AWS IAM console, find your user/role, and attach this policy (or add these statements to an existing policy).

3Grant S3 origin access permissions

If your CloudFront distribution uses an S3 bucket as an origin, your IAM role needs S3 permissions. Additionally, the S3 bucket policy must allow CloudFront to access objects.

Create or update the S3 bucket policy to allow CloudFront's Origin Access Control:

hcl
resource "aws_s3_bucket_policy" "cloudfront_access" {
  bucket = aws_s3_bucket.origin.id
  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Sid       = "AllowCloudFrontAccess"
        Effect    = "Allow"
        Principal = {
          Service = "cloudfront.amazonaws.com"
        }
        Action   = "s3:GetObject"
        Resource = "${aws_s3_bucket.origin.arn}/*"
        Condition = {
          StringEquals = {
            "AWS:SourceArn" = "arn:aws:cloudfront::${data.aws_caller_identity.current.account_id}:distribution/${aws_cloudfront_distribution.main.id}"
          }
        }
      }
    ]
  })
}

Also add S3 permissions to your IAM policy if creating or modifying bucket policies.

4Configure Origin Access Control (OAC) for S3

If using S3 as an origin, use Origin Access Control (OAC) instead of the deprecated Origin Access Identity (OAI). This provides better security and requires fewer manual bucket policy updates.

hcl
resource "aws_cloudfront_origin_access_control" "s3" {
  name                              = "s3-oac"
  origin_access_control_origin_type = "s3"
  signing_behavior                  = "always"
  signing_protocol                  = "sigv4"
}

resource "aws_cloudfront_distribution" "main" {
  # ... other config ...
  origin {
    domain_name              = aws_s3_bucket.origin.bucket_regional_domain_name
    origin_access_control_id = aws_cloudfront_origin_access_control.s3.id
    origin_id                = "s3-origin"
  }
}

This approach is more maintainable and requires fewer permissions than OAI.

5Add ACM certificate permissions if using HTTPS

If your distribution uses a custom domain with an ACM certificate, add ACM permissions to your IAM policy:

json
{
  "Effect": "Allow",
  "Action": [
    "acm:DescribeCertificate",
    "acm:ListCertificates"
  ],
  "Resource": "*"
}

Also ensure your certificate is in the us-east-1 region, as CloudFront only uses certificates from that region.

6Test with terraform plan after permissions are applied

After updating IAM permissions, wait 2-5 minutes for AWS to propagate the changes. Then test with Terraform:

bash
terraform plan

If permissions are still not working, run aws sts get-caller-identity again to confirm you're using the right credentials. Permissions can take a few minutes to become effective in AWS.

Advanced notes

CloudFront permissions are separate from S3 and other service permissions. Even if you have full S3 access, CloudFront requires its own IAM permissions. For cross-account access scenarios where your CloudFront is in one AWS account and the S3 bucket is in another, you'll need additional trust relationship configurations. Always use Origin Access Control (OAC) with SigV4 signing for S3 origins rather than the legacy OAI method - it's more secure and requires less manual bucket policy management.

Frequently asked questions

What does "AccessDenied" mean?
When Terraform attempts to create a CloudFront distribution, AWS returns an AccessDenied error if your credentials don't have the necessary CloudFront permissions. This is a credential/IAM issue rather than a Terraform configuration problem. CloudFront requires multiple permission levels: permissions to create the distribution itself, permissions to access origins (like S3 buckets), and permissions for any SSL/TLS certificates you're using.
How do I fix "AccessDenied"?
CloudFront AccessDenied errors occur when your AWS credentials lack required permissions. This guide covers IAM permission issues, S3 bucket policies for origins, and certificate permissions needed for successful distribution creation.
What causes "AccessDenied"?
IAM user or role lacks cloudfront:CreateDistribution permission Missing S3 origin access permissions or bucket policy for CloudFront ACM certificate permissions not granted to the IAM role
Is the "AccessDenied" error serious?
Yes. This is a high-severity error that usually blocks work until it is fixed, but the steps above resolve it.

Official resources & further reading