skip to Main Content

When I am deploying Azure Storage account using terraform, I am getting error like – Error: retrieving static website properties for Storage Account (Subscription: *** : context deadline exceeded.

When I am removing the code for private endpoint creation, the Storage account is getting deployed. But when I am using all the code together for storage account and private endpoint, my pipeline is failing with above error mentioned.

my main.tf file code provided below –

resource "azurerm_storage_account" "saflow" {
  name                     = .......
  resource_group_name      = data.azurerm_resource_group.rg.name
  location                 = data.azurerm_resource_group.rg.location
  account_tier             = "Standard"
  account_replication_type = "LRS"
  min_tls_version         = "TLS1_2"
  allow_nested_items_to_be_public = false
  identity {
    type = "SystemAssigned"
  }
  
  blob_properties {
    delete_retention_policy {
      days = 30
    }
    container_delete_retention_policy {
      days = 30
    }
    versioning_enabled = true
  }


queue_properties  {
    logging {
        delete                = true
        read                  = true
        write                 = true
        version               = "1.0"
        retention_policy_days = 10
    }
    hour_metrics {
      enabled                   = true
      include_apis              = true
      retention_policy_days     = 10
      version                   = "1.0"

    }
    minute_metrics {
      enabled                  = true
      include_apis             = true
      retention_policy_days    = 10
      version                  = "1.0"

      
    }
    
  }
}

resource "azurerm_storage_container" "container" {
  count                 = "${length(var.containername)}"
  name                  = "${element(var.containername,count.index)}"
  storage_account_name  = azurerm_storage_account.saflow.name
  container_access_type = "private"
  depends_on = [azurerm_storage_account.saflow]

}

resource "null_resource" "log_enabler" {
  triggers = {
  always_run = "${timestamp()}"
  }
  depends_on = [
    azurerm_storage_account.saflow
  ]
  provisioner "local-exec" {
    command = "az storage logging update --log rwd --retention 30 --services qtb --account-name ${azurerm_storage_account.saflow.name} --account-key ${azurerm_storage_account.saflow.primary_access_key}"
  } 
}

resource "azurerm_private_endpoint" "endpoint" {
   
  name                     = .......
  resource_group_name      = data.azurerm_resource_group.rgnetwork.name
  location                 = data.azurerm_resource_group.rgnetwork.location
  subnet_id                = data.azurerm_subnet.subnet.id
  private_dns_zone_group {
    name                 = ....
    private_dns_zone_ids = [data.azurerm_private_dns_zone.dns.id]
  }
  private_service_connection {
    name                           = ....
    is_manual_connection           = false
    private_connection_resource_id = azurerm_storage_account.saflow.id
    subresource_names              = ["blob"]
  }

  depends_on = [azurerm_storage_container.container]
}

resource "azurerm_private_dns_a_record" recordglobal {
  provider            = "azurerm.globalsub"
  name                = azurerm_storage_account.saflow.name
  zone_name           = data.azurerm_private_dns_zone.dns.name
  resource_group_name = data.azurerm_resource_group.rgglobal.name
  ttl                 = 10
  records             = [azurerm_private_endpoint.endpoint.private_service_connection[0].private_ip_address]
  depends_on = [azurerm_private_endpoint.endpoint]
}

resource azurerm_storage_account_network_rules networkrule {
  
   storage_account_id       = azurerm_storage_account.saflow.id
  default_action             = "Deny"
  virtual_network_subnet_ids = data.azurerm_subnet.subnet.id,data.azurerm_subnet.subnet-global.id
  bypass                     = ["AzureServices"]
  depends_on = [azurerm_private_endpoint.endpoint, azurerm_private_dns_a_record.recordglobal]
}

Please help if there is anything wrong with this terraform code.

I removed the code for private endpoint and the storage account got created. Then post that I added the code for private endpoint and private endpoint got created. But why it is not getting created when I have both the codes together for storage account and private endpoint.

2

Answers


  1. Terraform: Error: retrieving static website properties for Storage Account (Subscription: *** : context deadline exceeded

    The context deadline exceeded occurs when the request made by Terraform takes longer than the default timeout value. You can try increasing the timeout value to resolve this issue. when the storage account is created, it might not be immediately ready to accept a private endpoint connection, leading to errors.

    To address this issue, you can add a depends_on attribute for the azurerm_private_endpoint resource and add timeout block in the storage account block. This ensures that it waits until the null_resource.log_enabler is fully executed, thereby ensuring that the storage account is completely set up before the private endpoint creation begins

    Here is the updated Terraform code to create a storage account, a private endpoint, and other resources in a single run.

    provider "azurerm" {
      features {}
    }
    
    data "azurerm_resource_group" "rg" {
      name = "RG_Name"
    }
    
    resource "azurerm_private_dns_zone" "example" {
      name                = "mydomain.com"
      resource_group_name = data.azurerm_resource_group.rg.name
    }
    
    resource "azurerm_virtual_network" "example" {
      name                = "storage-vnet"
      address_space       = ["10.0.0.0/16"]
      location            = data.azurerm_resource_group.rg.location
      resource_group_name = data.azurerm_resource_group.rg.name
    
      depends_on = [azurerm_private_dns_zone.example]
    }
    
    resource "azurerm_subnet" "example" {
      name                 = "storage-subnet"
      resource_group_name  = data.azurerm_resource_group.rg.name
      virtual_network_name = azurerm_virtual_network.example.name
      address_prefixes     = ["10.0.2.0/24"]
      service_endpoints    = ["Microsoft.Storage"]
    
    
      depends_on = [azurerm_virtual_network.example]
    }
    
    resource "azurerm_storage_account" "saflow" {
      name                     = "thejastorage"
      resource_group_name      = data.azurerm_resource_group.rg.name
      location                 = data.azurerm_resource_group.rg.location
      account_tier             = "Standard"
      account_replication_type = "LRS"
      min_tls_version          = "TLS1_2"
      allow_nested_items_to_be_public = false
      identity {
        type = "SystemAssigned"
      }
      timeouts {
        create = "30m"
        update = "30m"
        delete = "30m"
      }
    
      blob_properties {
        delete_retention_policy {
          days = 30
        }
        container_delete_retention_policy {
          days = 30
        }
        versioning_enabled = true
      }
    
      queue_properties {
        logging {
          delete                = true
          read                  = true
          write                 = true
          version               = "1.0"
          retention_policy_days = 10
        }
        hour_metrics {
          enabled                   = true
          include_apis              = true
          retention_policy_days     = 10
          version                   = "1.0"
        }
        minute_metrics {
          enabled                  = true
          include_apis             = true
          retention_policy_days    = 10
          version                  = "1.0"
        }
      }
    }
    
    resource "azurerm_storage_container" "container" {
      name                  = "thejacontainer"
      storage_account_name  = azurerm_storage_account.saflow.name
      container_access_type = "private"
      depends_on = [azurerm_storage_account.saflow]
    }
    
    resource "null_resource" "log_enabler" {
      provisioner "local-exec" {
        command = <<EOT
        az storage account keys list --account-name ${azurerm_storage_account.saflow.name} --resource-group ${azurerm_storage_account.saflow.resource_group_name} --query '[0].value' --output tsv > key.txt
        az storage logging update --log rwd --retention 30 --services qtb --account-name ${azurerm_storage_account.saflow.name} --account-key $(cat key.txt)
        rm key.txt
        EOT
      }
    
      depends_on = [
        azurerm_storage_container.container
      ]
    }
    
    resource "azurerm_private_endpoint" "endpoint" {
      name                = "storageendpoint"
      resource_group_name = data.azurerm_resource_group.rg.name
      location            = data.azurerm_resource_group.rg.location
      subnet_id           = azurerm_subnet.example.id
    
      private_dns_zone_group {
        name                 = "storagedns"
        private_dns_zone_ids = [azurerm_private_dns_zone.example.id]
      }
    
      private_service_connection {
        name                           = "storageconnection"
        is_manual_connection           = false
        private_connection_resource_id = azurerm_storage_account.saflow.id
        subresource_names              = ["blob"]
      }
    
      depends_on = [null_resource.log_enabler]
    }
    
    provider "azurerm" {
      alias    = "globalsub"
      features {}
    }
    
    resource "azurerm_private_dns_a_record" "recordglobal" {
      name                = azurerm_storage_account.saflow.name
      zone_name           = azurerm_private_dns_zone.example.name
      resource_group_name = data.azurerm_resource_group.rg.name
      ttl                 = 10
      records             = [azurerm_private_endpoint.endpoint.private_service_connection[0].private_ip_address]
      depends_on = [azurerm_private_endpoint.endpoint]
    }
    
    resource "azurerm_storage_account_network_rules" "networkrule" {
      storage_account_id         = azurerm_storage_account.saflow.id
      default_action             = "Deny"
      virtual_network_subnet_ids = [azurerm_subnet.example.id]
      bypass                     = ["AzureServices"]
      depends_on = [azurerm_private_dns_a_record.recordglobal]
    }
    

    Terraform apply

    enter image description here

    Portal result

    enter image description here

    Refer the link to resolve Context Deadline Exceeded Error

    Login or Signup to reply.
  2. You are experiencing issues what is caused by the underlying design of Azure APIs and the AzureRM provider for Terraform. There is extensive discussion on the topic here.

    The problem: you are executing Terraform from a network that does not have network connectivity to the private endpoint of that storage account AND you have not allowed your public IP address to access the storage account.

    Possible solution 1: You grant a firewall exception to the public IP where you are executing your Terraform from. Might be against the security requirements you are working with

    Possible solution 2 You execute your terraform in a place, that has visibility to the private endpoint (e.g. a VM running in the same VNET, through a VPN or similar)

    Notes: This is not a timeout issue, the request just says timeout as its blocked by the blob storage Firewall. Also the first Terraform always succeeds as Terraform just notices that there is no existing Blob Storage -> no need to refresh its status.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search