Introduction Link to heading
We want to manage our Azure IaC with terraform so we have as little manual work as we can. I was working one day and got the request from developers, the application is trying to access blob storage but it’s blocked by CORS rules. Off course I got to the work and came up with this terraform module I will share now.
Terraform time Link to heading
First as usual I have everything as modules. Terraform modules allow us to group multiple resources into one .tf file which can be later used in some other .tf files like your project files. To mention I also keep modules in one git repo and the project terraform files in another. This approach gives me easy way to update my modules.
Let’s start now by looking at storage module
resource "azurerm_storage_account" "main" {
name = var.name
location = var.location
resource_group_name = var.resource_group_name
account_kind = "StorageV2"
account_tier = var.account_tier
account_replication_type = var.replication
access_tier = var.access_tier
min_tls_version = "TLS1_2"
blob_properties {
last_access_time_enabled = var.blob_last_access_time
versioning_enabled = var.blob_versioning
delete_retention_policy {
days = var.blob_delete_retention
}
container_delete_retention_policy {
days = var.container_delete_retention
}
dynamic "cors_rule" {
for_each = var.cors_rules
content {
allowed_origins = cors_rule.value.allowed_origins
allowed_methods = cors_rule.value.allowed_methods
allowed_headers = cors_rule.value.allowed_headers
exposed_headers = cors_rule.value.exposed_headers
max_age_in_seconds = cors_rule.value.max_age_in_seconds
}
}
}
share_properties {
dynamic "cors_rule" {
for_each = var.cors_rules
content {
allowed_origins = cors_rule.value.allowed_origins
allowed_methods = cors_rule.value.allowed_methods
allowed_headers = cors_rule.value.allowed_headers
exposed_headers = cors_rule.value.exposed_headers
max_age_in_seconds = cors_rule.value.max_age_in_seconds
}
}
}
tags = var.tags
}
resource "azurerm_storage_container" "main" {
for_each = var.containers
name = each.key
storage_account_name = azurerm_storage_account.main.name
container_access_type = each.value
}
resource "azurerm_storage_queue" "main" {
for_each = var.queues
name = each.value
storage_account_name = azurerm_storage_account.main.name
}
resource "azurerm_storage_table" "main" {
for_each = var.tables
name = each.value
storage_account_name = azurerm_storage_account.main.name
}
resource "azurerm_management_lock" "storage_account" {
name = var.name
scope = resource.azurerm_storage_account.main.id
lock_level = "CanNotDelete"
notes = "Locked to avoid accidental removal"
}
This is what I came up as a module for all blob storages in my environments.
In this module we have two cors_rules, first is dynamic cors_rule
and another is under share_properties
.
This is because the first cors_rules are for blob_service
and the share_properties is for file_service
.
To see full module with variables you can go to my github account here
Next, I have my project setup
storage.tf
module "main_storage" {
source = "git@github.com:dewa55/terraform/modules.git"
name = "myblobstorage"
location = azurerm_resource_group.main.location
resource_group_name = azurerm_resource_group.main.name
account_tier = "Standard"
replication = "LRS"
access_tier = "Hot"
cors_rules = local.api_cors
tags = merge(
tomap(
{
environment = var.environment
}
),
var.tags
)
containers = {
"my-container" = "private"
}
}
locals.tf
locals {
api_cors = var.environment == "dev" ? [
{
allowed_origins = ["https://localhost:4200", "http://localhost:4200"]
allowed_methods = ["GET", "DELETE", "POST", "PUT", "OPTIONS"]
allowed_headers = ["*"]
exposed_headers = ["*"]
max_age_in_seconds = 10
}
] : []
}
That would be it :)