TL;DR – Terraform is blocked by Storage Account firewall (if enabled) when deploying File Share. Current solution: deploy file share with template.
Future solution: establish agent pool inside network boundaries.
I have been doing lots of cool stuff lately, and one of the more interesting is digging in to Terraform IaC on Azure with Azure DevOps. I know Azure DevOps is being deprecated in 4-5 years. That’s why GitHub Workflows and Actions are my next new areas of learning!
From earlier, I have worked long hours on ARM Templates, and have some kind of handle on the IaC principle. I have also been using ARM Templates more efficiently, as I am using linked templates with custom modules, but that is another story.
This post came to mind one winter afternoon when I was out and about. Since I have been working mostly with Terraform lately, a number of previously unknown quirks regarding the framework has ambushed me.
Terraform is a great tool! I will not go into detail on basic stuff here, as several others before me have covered this quite nicely. Just try some quick searches, and there is gold in lots of blogs(This blog series, and this paywall medium article, just to name a couple).
This post is about a particular issue I stumbled into; creating an Azure Storage Account with network rules and a file share. Sounds simple enough, and before the Storage Account “firewall” is enabled, this can be a breeze. I deployed using a local customized version of this module, which deploys both the storage account, network rules and file share.
Already there were issues, as the trouble begins when enabling the Storage Account “firewall” before creating the file share. Terraform creates resources by using go-plugins, and therefore executes from wherever the Terraform executable is run.
At the moment, this is an Azure DevOps pipeline validating, planning, and deploying the infrastructure. This means that the Terraform executable runs on a Microsoft Hosted Agent (because I do not want to keep my own build agents at the moment). This complicated things, as there are over 160 public IP ranges to add in an IP rule on the Storage Account for AzDO West Europe. Each Storage Account supports up to 200 IP rules, so I could in theory put them there. The list changes, though, so I would have to use some automation/script/etc. Also running a VM Scale Set for AzDO agents, could be used, but not an option in my case.
All of this, means that when the Terraform tries to add the file share, it fails beacuse “Not authorized”. The firewall blocks access to this account, because source public IP is not explicitly allowed.
My solution: deploy the Azure File Share from an ARM Template, as this is not blocked by firewall. Template can be found here. Could also have been deployed by Az CLI or PowerShell in a Terraform Null Resource Local-Exec to bypass Storage Account firewall.
Then another issue hit me:
Original Error: Code="InvalidTemplate" Message="Deployment template validation failed: 'Template parameter JToken type is not valid. Expected 'Integer'. Actual 'String'.
Turns out the ARM Template deployment I used, only passes parameters as strings. The qouta-parameter required integer because I set this in the template. Did a few hours troubleshooting before I checked that. Had to use an explicit type cast in an intermediate variable in the template.
Now I see that there is a new deployment resource: azurerm_resource_group_template_deployment, but I have not tried this. This maybe supports passing parameters as something else than strings, but I can not find any doc on it. Only “doc” I found on the other template deployment resource, was a post from someone in stackoverflow. Then I checked my pipeline logs, and saw that the number passed in to template was enclosed in quotes.
My conclusion: a better solution is to deploy vm scale set build agents, or a different Vnet-connected agent, which run the Terraform from inside customer network. This way you are never blocked by firewall. I did not have the time in this case, and will consider it for future Terraform pipeline work.