Posted: Wednesday, January 11, 2023
Word Count: 766
Reading Time: 4 minutes
Azure storage is a cost affordable option for hosting static websites, and fairly easy to setup. This lab was created to deploy a static website on Azure Storage leverage terraform code.
Utility | Link |
---|---|
Azure Storage Static Website Repository | Click Here |
Visual Studio Code | Click Here |
The cost assumes the following:
Resources | Cost Estimate Per Month |
---|---|
Storage Account (LRS) | $0.30 |
100,000 write operations | $0.50 |
100,000 list and create operations | $0.50 |
1,000,000 read operations | $0.40 |
300,000 remaining operations | $0.12 |
Total Monthly Estimate | $1.82 |
I’m a fan of modularization, and although this could have been deployed into a single tf file, creating modules allows more versatility and personalization to the deployment. I realize that not everything needs to be modularized; however, I also know that when I’m searching for code, I’ve come to appreciate those who create modules. It allows me to grab what I need versus sifting through 1000+ lines of code. For this lab, I created 7 terraform modules.
Modules | Description |
---|---|
currentInfo.tf | Contains information regarding current subscription id, client id and external IP address. |
randomid.tf | used to generate random id for storage account name |
uploadprovisioner.tf | runs a task to upload a test index.html File into the $web folder |
storageAccount.tf | Provisions a static web enabled storage account |
storageAccountNetworkRules | Applies an Access list to the storage account |
The contents of each module are provided in this section.
The only thing this lab leverages is the bolded resource. However it’s a module that I use quite often and simply copy as is it to the required deployment.
data "http" "ip" {
url = "http://ipv4.icanhazip.com"
}
data "azurerm_client_config" "current" {}
output "MyextIP" {
value = chomp(data.http.ip.response_body)
}
output "myextIPCIDR" {
value = "${chomp(data.http.ip.response_body)}/32"
}
output "tenant_id" {
value = data.azurerm_client_config.current.tenant_id
}
output "subscription_id" {
value = data.azurerm_client_config.current.subscription_id
}
output "object_id" {
value = data.azurerm_client_config.current.object_id
}
output "client_id" {
value = data.azurerm_client_config.current.client_id
}
Its sole purpose is to generate a random value that can be appended to the storage account name since storage account names are required to be globally unique.
resource "random_id" "randomId" {
byte_length = 4
}
output "id" {
value = random_id.randomId.id
}
output "hex" {
value = random_id.randomId.hex
}
This module is executed after the creation of the storage account and uploads the embedded index.html file into the $web directory.
resource "null_resource" "fileUpload" {
provisioner "local-exec" {
command = <<Settings
$resourceGroupName = "${var.resource_group_name}"
$storageAccountName = "${var.storage_account_name}"
$storageAccount = Get-AzStorageAccount -StorageAccountName $storageAccountName -ResourceGroupName $resourceGroupName
$context = $storageAccount.context
$HTMLUL = @{
File = 'index.html'
Container = '$web'
Blob = 'index.html'
Context = $context
StandardBlobTier = 'Hot'
}
Set-AzStorageBlobContent @HTMLUL -Properties @{"ContentType" = "text/html"} -Verbose
Settings
interpreter = ["PowerShell", "-Command"]
}
}
Provisions the storage account and enables static web hosting.
resource "azurerm_storage_account" "storage_account" {
name = var.storage_account_name
location = var.location
tags = var.tags
account_kind = var.account_kind
public_network_access_enabled = var.public_network_access_enabled
resource_group_name = var.resource_group_name
account_tier = var.account_tier
account_replication_type = var.account_replication_type
access_tier = var.access_tier
enable_https_traffic_only = var.enable_https_traffic_only
static_website {
index_document = var.index_document
}
}
output "URL" {
value = azurerm_storage_account.storage_account.primary_web_endpoint
}
Creates an access list that only allows access to the website from the originating external IP.
resource "azurerm_storage_account_network_rules" "saNetworkRules" {
storage_account_id = var.storage_account_id
default_action = var.default_action
ip_rules = [var.ip_rules]
}
Provisions the resource group that the resources will be contained within.
resource "azurerm_resource_group" "RG" {
name = var.resource_group_name
location = var.location
tags = var.tags
}
output "resource_group_name" {
value = azurerm_resource_group.RG.name
}
Once the script has completed, the storage account should be provisioned, the $web folder created, and the index.html file uploaded. The URL should be immediately accessible. You will find the URL apart of the outputs once the script has completed.