Home Linux & Systems Cybersecurity Cloud & DevOps Networks & Infrastructure SIEM & Monitoring DFIR & Threat Intel Development & Other All categories Projects About Tools

Deploying Storage Account with Terraform and Terragrunt

Leer en espanol
Deploying Storage Account with Terraform and Terragrunt

Table of contents

In this project, an organized structure for the deployment of an infrastructure in Azure using Terraform and Terragrunt is presented. The solution makes it easy to create and manage ===

Introduction

In this project, an organized structure for the deployment of an infrastructure in Azure using Terraform and Terragrunt is presented. The solution makes it easy to create and manage Storage Account resources, optimizing configuration reuse between different environments, such as development and production, through well-structured configuration files.

The project structure allows for a modular and reusable implementation, separating the configuration of specific environments from the main deployment files. Terraform and Terragrunt offer a robust approach to managing common and environment-specific variables and state, facilitating infrastructure management and scalability in enterprise environments.

Project Structure

The organization of the project is as follows:

CODE
├── env
│   ├── code
│   │   └── storage
│   │       └── 00
│   │           ├── backend.tf
│   │           ├── data.tf
│   │           ├── endpoint.tf
│   │           ├── locals.tf
│   │           ├── main.tf
│   │           ├── outputs.tf
│   │           ├── provider.tf
│   │           └── variables.tf
│   └── dev
│       ├── storage
│       │   └── 00
│       │       ├── terragrunt.hcl
│       │       └── vars.tfvars
│       └── varEnvironment.hcl
├── varCommon.hcl
└── varDataState.hcl

The folder env contains environment-specific settings, while code hosts the Terraform configuration files for the Storage Account deployment. The folder dev contains configuration files specific to the development environment. terragrunt.hclvarCommon.hcl and varDataState.hcl They are configuration files for Terragrunt and common variables.

Terraform Configuration

Now, let's dive into the Terraform configuration files needed to deploy Storage Account.

backend.tf

TERRAFORM
terraform {
  backend "azurerm" {
  }
  required_version = "~>0.14"
  required_providers {
    azurerm = {
      source = "hashicorp/azurerm"
      version = "3.47.0"
    }
  }
}

data.tf

The file data.tf contains data blocks that allow Terraform to access information from existing resources in Azure. These blocks are essential for reusing existing infrastructure and ensuring that new resources are deployed consistently.

CODE
data "terraform_remote_state" "rg" {
  backend = "azurerm"
  config = {
    subscription_id             = var.lz_subscription_id
    resource_group_name         = var.lz_resource_group_name
    storage_account_name        = var.lz_storage_account_name
    container_name              = var.lz_container_name
    key                         = "${var.ProjectName}/${var.ServiceName}/env/${var.Environment}/${var.mapProjectPathKey.rg}/terraform.tfstate"
  }
}

data "azurerm_resource_group" "rg_net" {
  name = var.rg_net_name
}

#State Vnet
data "azurerm_virtual_network" "vnet" {
  name = var.vnet_net_name
  resource_group_name = data.azurerm_resource_group.rg_net.name 
}

data "azurerm_subnet" "sbn_data" {
  name                 = var.sbn_data_net_name 
  virtual_network_name = data.azurerm_virtual_network.vnet.name
  resource_group_name  = data.azurerm_resource_group.rg_net.name
}

data "azurerm_resource_group" "hub_rg" {
  provider = azurerm.hub
  name     = var.hub_resource_group_name
}

data "azurerm_private_dns_zone" "zone_01" {
  provider            = azurerm.hub
  name                = var.private_dns_zone_name_01
  resource_group_name = data.azurerm_resource_group.hub_rg.name
}

data "azurerm_private_dns_zone" "zone_02" {
  provider            = azurerm.hub
  name                = var.private_dns_zone_name_02 
  resource_group_name = data.azurerm_resource_group.hub_rg.name
}

Explanation:

1. data “terraform_remote_state” “rg”

This block accesses the remote state of Terraform to reuse configurations already existing elsewhere (for example, resources defined in a different project). It is commonly used in multi-modular configurations.

  • backend: Defines the type of backend (in this case, Azure Resource Manager, azurerm) where the Terraform state is stored.
  • config: Contains the configuration necessary to connect to the remote state:
    • subscription_id- ID of the Azure subscription where the status is located.
    • resource_group_name: Name of the resource group that contains the storage account.
    • storage_account_name: Name of the storage account that hosts the state.
    • container_name: Name of the blob container within the storage account.
    • key: Specific path to the remote state file, organized using variables such as the project, service, environment, and a path mapping (mapProjectPathKey).

2. data “azurerm_resource_group” “rg_net”

This block retrieves information about an existing resource group in Azure.

  • yam: Name of the resource group you want to consult. It is defined by the variable var.rg_net_name.

3. data “azurerm_virtual_network” “vnet”

Gets details about a specific virtual network.

  • yam: Name of the target virtual network, defined by var.vnet_net_name.
  • resource_group_name: Name of the resource group where this virtual network is located. It is obtained dynamically from data.azurerm_resource_group.rg_net.name.

4. data “azurerm_subnet” “sbn_data”

Retrieves information about a subnet within a specific virtual network.

  • yam: Name of the subnet, specified by var.sbn_data_net_name.
  • virtual_network_name: Name of the virtual network associated with the subnet. It is extracted from data.azurerm_virtual_network.vnet.name.
  • resource_group_name: Virtual network resource group. It is obtained from data.azurerm_resource_group.rg_net.name.

5. data “azurerm_resource_group” “hub_rg”

Gets information from a group of resources that acts as hub.

  • provider: Associates a specific provider for operations related to this resource group (azurerm.hub).
  • yam: Name of the hub resource group, defined by var.hub_resource_group_name.

6. data “azurerm_private_dns_zone” “zone_01”

Gets information about a private DNS zone to resolve internal domain names.

  • provider: Use the provider configured as azurerm.hub to perform operations in this DNS zone.
  • yam: Name of the private DNS zone, defined by var.private_dns_zone_name_01.
  • resource_group_name: Resource group that hosts the private DNS zone. Obtained from the resource data.azurerm_resource_group.hub_rg.name.

7. data “azurerm_private_dns_zone” “zone_02”

Another block similar to the previous one, but for a second private DNS zone.

  • provider: Same as above, use azurerm.hub.
  • yam: Defines the name of the private DNS zone (for example, privatelink.web.core.windows.net) through var.private_dns_zone_name_02.
  • resource_group_name: Associated with the resource group data.azurerm_resource_group.hub_rg.name.

endpoint.tf

This file defines the resource Private Endpoint, allowing private connection to the Storage Account. This Private Endpoint is associated with the specified subnet and private DNS zone.

NGINX
resource "azurerm_private_endpoint" "pren_01" {
  name                = upper(join("-", [ var.Environment, var.BussinessUnitExtended, var.Provider, var.ServiceName, var.storage_account_name, "pren-01"])) 
  resource_group_name = data.terraform_remote_state.rg.outputs.name
  location            = var.region
  subnet_id           = data.azurerm_subnet.sbn_data.id

  private_service_connection {
    name                           = upper(join("-", [ var.Environment, var.BussinessUnitExtended, var.Provider, var.ServiceName, var.storage_account_name, "pren-01"]))
    private_connection_resource_id = azurerm_storage_account.storage_01.id
    is_manual_connection           = false
    subresource_names              = ["blob"]
  }

  private_dns_zone_group {
    name                 = data.azurerm_private_dns_zone.zone_01.name
    private_dns_zone_ids = [data.azurerm_private_dns_zone.zone_01.id]
  }

  tags = local.tags

  lifecycle {
    ignore_changes = [
      tags["CreationDate"]
    ]
  }
}

Explanation:

resource “azurerm_private_endpoint” “pren_01”:


This resource defines a Private Endpoint which allows a secure and private connection to a storage account in Azure.

  • yam:
    Name of the Private Endpoint, dynamically generated from several variables (Environment, BussinessUnitExtended, Provider, ServiceName, storage_account_name). This format ensures consistency with corporate nomenclature. Converted to uppercase using upper().
  • resource_group_name:
    Specifies the resource group where the Private Endpoint.
    Obtained from the Terraform remote state (data.terraform_remote_state.rg.outputs.name), which centralizes the definition of the resource group.
  • location:
    Region where the Private Endpoint.
    It is defined through the variable var.region.
  • subnet_id:
    ID of the subnet where the Private Endpoint.
    It is obtained from data.azurerm_subnet.sbn_data.id, which retrieves the details of the corresponding subnet.

Block private_service_connection

Configures the private connection to the target resource, in this case, a storage account.

  • yam:
    Name of the private connection, generated in a similar way to the name of the Private Endpoint.
  • private_connection_resource_id:
    ID of the destination resource to which the Private Endpoint.
    In this case, it corresponds to the storage account ID (azurerm_storage_account.storage_01.id).
  • is_manual_connection:
    Established as false, indicating that the private connection is automatically managed by Azure.
  • subresource_names:
    Specifies the subresource within the service to connect to.
    In this case, it is the subresource blob of the storage account.

Block private_dns_zone_group

Defines the relationship between the Private Endpoint and a private DNS zone to resolve internal domain names.

  • yam:
    Name of the private DNS zone, obtained from data.azurerm_private_dns_zone.zone_01.name.
  • private_dns_zone_ids:
    List of private DNS zone IDs associated with the Private Endpoint.
    Here the ID is used data.azurerm_private_dns_zone.zone_01.id.

tags

Applies tags defined in local.tags, which makes it easier to organize and track the resource within the environment.

Block lifecycle

Configure Terraform's behavior regarding changes to the resource.

locals.tf

The file locals.tf defines local variables that can be reused in multiple parts of Terraform code. Local variables are useful for centralizing values ​​that are used across multiple resources, improving code clarity and maintainability.

CODE
locals {
  storage_name = lower(join("", [var.Environment, var.BussinessUnitExtended, var.Provider, var.ServiceName, "st01"]))
  tags = var.tags
}

Explanation:

Defines a dynamic name for a resource, in this case probably a storage account.

Components:

  • lower()- Converts the generated value to lowercase to comply with resource name restrictions in Azure (for example, storage account names must be lowercase).
  • join("", [...]): Combines the values ​​in a list into a single string, without separators.
  • List of values ​​used:
    • var.Environment: Variable that represents the environment, such as "dev", "prod", etc.
    • var.BussinessUnitExtended: Identifies the business unit.
    • var.Provider: Specifies the provider or technology used, such as "azr" for Azure.
    • var.ServiceName: Name of the service related to the resource.
    • "st01": Fixed suffix to indicate that this is a storage account.

 

main.tf

in the file main.tf The main infrastructure resources are defined. In this case, an Azure Storage Account resource is being created that will serve to store secrets and other sensitive values, thus ensuring the security of the information.

NGINX
resource "azurerm_storage_account" "storage_01" {
  name                     = local.storage_name
  resource_group_name      = data.terraform_remote_state.rg.outputs.name
  location                 = var.region
  account_tier             = var.storage_account_tier 
  account_replication_type = var.storage_account_replication_type
  access_tier              = var.storage_account_access_tier 
  min_tls_version          = var.storage_account_min_tls_version 
  account_kind             = var.storage_account_kind
  is_hns_enabled           = var.storage_account_is_nhs_enabled 
  public_network_access_enabled = false
  tags                     = local.tags


  lifecycle {
    ignore_changes = [
      tags["CreationDate"]
    ]
  }

  blob_properties {
    container_delete_retention_policy {
      days = 7
    }
    delete_retention_policy {
      days = 7
    }
  }
}

Explanation

1. Resource definition

  • resource "azurerm_storage_account" "storage_01": Defines a resource of type azurerm_storage_account (Azure Storage Account) in Terraform.
    The identifier storage_01 is used to reference this resource in other parts of the code.

2. Main attributes

  • name:
    Build storage account name using local variable local.storage_name, which dynamically combines values ​​such as the environment, business unit, provider and service. This guarantees a unique and standard name.
    (Example: devfinanceazrbackupst01)
  • resource_group_name:
    Specifies the resource group where the storage account will be created.
    The name is obtained from the Terraform remote state (terraform_remote_state.rg.outputs.name), ensuring consistency with other resources that share the same group.
  • location:
    Defines the region where the storage account will be located, specified by the variable var.region.
    (Example: eastus)
  • account_tier:
    Defines the performance level of the storage account.
    Could be Standard either Premium, depending on the intended use.
    (Example: Standard)
  • account_replication_type:
    Specifies the type of replication to ensure redundancy.
    Possible values: LRS, GRS, ZRS, etc.
    (Example: LRS)
  • access_tier:
    Determines whether the data is accessed frequently (Hot) or sporadically (Cool).
    (Example: Hot)
  • min_tls_version:
    Configures the minimum TLS version allowed for connections. Improves security by only accepting modern versions.
    (Example: TLS1_2)
  • account_kind:
    Storage account type.
    (Example: StorageV2)
  • is_hns_enabled:
    Enables support for Azure Data Lake Storage Gen2, enabling a hierarchical access model for Big Data.
    (Example: true)
  • public_network_access_enabled:
    Established in false to restrict access from public networks, improving security by limiting use to private networks or private endpoints.

3. Advanced settings

  • tags:
    Applies tags defined in local.tags to organize the resource. These tags help with classification and search in Azure.
    (Example: { Environment = "dev", Owner = "John Doe" })
  • lifecycle:
    The block lifecycle indicates that Terraform should ignore any changes to the label CreationDate. This prevents unnecessary updates from being made to the resource when only this tag changes.

4. Blob properties

The block blob_properties defines policies for data lifecycle management:

  • container_delete_retention_policy: Retains deleted containers for 7 days, allowing them to be recovered.
  • delete_retention_policy: Retains deleted blobs for 7 days before final deletion.

outputs.tf

The file outputs.tf exposes relevant information about the resource azurerm_storage_account for ease of use in other modules or to provide key data to Terraform users. This includes endpoints, locations, access keys, among others.

NGINX
# IDs
output "id" {
    value = azurerm_storage_account.storage_01.id
    description = "The ID of the Storage Account."
}

output "primary_location" {
    value = azurerm_storage_account.storage_01.primary_location
    description = "The primary location of the storage account"
}

output "secondary_location" {
    value = azurerm_storage_account.storage_01.secondary_location
    description = "The secondary location of the storage account"
}

output "primary_blob_endpoint" {
    value = azurerm_storage_account.storage_01.primary_blob_endpoint
    description = "The primary blob endpoint of the storage account"
}

output "primary_blob_host" {
    value = azurerm_storage_account.storage_01.primary_blob_host
    description = "The primary blob host of the storage account"
}

output "secondary_blob_endpoint" {
    value = azurerm_storage_account.storage_01.secondary_blob_endpoint
    description = "The secondary blob endpoint of the storage account"
}

output "secondary_blob_host" {
    value = azurerm_storage_account.storage_01.secondary_blob_host
    description = "The secondary blob host of the storage account"
}

output "primary_access_key" {
    value = azurerm_storage_account.storage_01.primary_access_key
    description = "The primary access key of the storage account"
}

output "secondary_access_key" {
    value = azurerm_storage_account.storage_01.secondary_access_key
    description = "The secondary access key of the storage account"
}

output "primary_web_endpoint" {
    value = azurerm_storage_account.storage_01.primary_web_endpoint
    description = "The primary web endpoint of the storage account"
}

output "primary_web_host" {
    value = azurerm_storage_account.storage_01.primary_web_host
    description = "The primary web host of the storage account"
}

output "secondary_web_endpoint" {
    value = azurerm_storage_account.storage_01.secondary_web_endpoint
    description = "The secondary web endpoint of the storage account"
}

output "secondary_web_host" {
    value = azurerm_storage_account.storage_01.secondary_web_host
    description = "The secondary web host of the storage account"
}

output "primary_connection_string" {
    value = azurerm_storage_account.storage_01.primary_connection_string
    description = "The primary connection string of the storage account"
}

output "secondary_connection_string" {
    value = azurerm_storage_account.storage_01.secondary_connection_string
    description = "The secondary connection string of the storage account"
}

output "identity" {
    value = azurerm_storage_account.storage_01.identity
    description = "The identity of the storage account"
}

Explanation

  • output "id"

    • Provides the unique ID of the Azure Storage Account resource.
    • Useful for cross-referencing or integrations with other Azure services.
      (Example: /subscriptions/{subscription-id}/resourceGroups/{rg-name}/providers/Microsoft.Storage/storageAccounts/{storage-name})
  • output "primary_location" and output "secondary_location"

    • They indicate the primary and secondary location of the storage account.
    • Relevant in configurations with geographic replication to identify the regions in use.
      (Example: eastus, westus)
  • output "primary_blob_endpoint" and output "secondary_blob_endpoint"

    • They show the primary and secondary endpoints of the Blob service.
    • These are used to access and manage blobs stored in the account.
      (Example: https://{storage-name}.blob.core.windows.net/)
  • output "primary_blob_host" and output "secondary_blob_host"

    • They expose the host names associated with the Blob endpoints.
      (Example: {storage-name}.blob.core.windows.net)
  • output "primary_access_key" and output "secondary_access_key"

    • They return the primary and secondary access keys for the account.
    • These keys are essential for authentication when managed identity is not used.
      (Note: Handle with caution and access to this output should be restricted in sensitive environments.)
  • output "primary_web_endpoint" and output "secondary_web_endpoint"

    • They provide the primary and secondary endpoints for the associated web service.
      (Example: https://{storage-name}.web.core.windows.net/)
  • output "primary_connection_string" and output "secondary_connection_string"

    • They contain the primary and secondary connection strings, used by applications to interact with the storage account.
      (Example: DefaultEndpointsProtocol=https;AccountName={storage-name};AccountKey={key};EndpointSuffix=core.windows.net)
  • output "identity"

    • Exposes the managed identity associated with the storage account, if configured.
      (Example: {"principal_id": "...", "tenant_id": "...", "type": "SystemAssigned"})

provider.tf

in the file provider.tf infrastructure providers are configured, in this case the Azure provider (azurerm). Here you define two configurations for the Azure provider, one by default and one with an alias. This allows working with multiple Azure subscriptions within the same Terraform project

TERRAFORM
provider "azurerm" {
  subscription_id = var.Subscription
  tenant_id       = var.Tenant
  features {}
}

provider "azurerm" {
  alias           = "hub"
  subscription_id = var.subscription_hub_id
  tenant_id       = var.Tenant
  features {}
}

Explanation:

  • First block provider "azurerm":
    • subscription_id: This property defines the Azure subscription ID which will be used to provision and manage resources. It is obtained from the variable var.Subscription, which must be previously configured.
    • tenant_id: He Azure Active Directory tenant ID to which the Azure provider should be associated. In this case, it is taken from var.Tenant.
    • features {}: A block required by the Azure provider (azurerm) which may contain additional settings. Although in this case it is empty, it is necessary to correctly initialize the provider.
  • Second block provider "azurerm" with alias hub:
    • alias: The alias "hub" allows you to create a second Azure provider within the same Terraform configuration, which is useful when you need to work with multiple subscriptions. By assigning an alias, you can reference this specific provider later in your resources or data so that it can be differentiated from the default provider.
    • subscription_id: Similar to the first block, this property is defined via var.subscription_hub_id, which represents the Azure subscription ID for the hub configuration.
    • tenant_id: He tenant ID remains the same and is taken from var.Tenant to maintain consistency in the environment.
    • features {}: Like the first block, this block is required even if it does not contain additional settings.

variables.tf

in the file variables.tf All variables used throughout the Terraform infrastructure are defined. This file centralizes configurable parameters that can change depending on the environment, subscription, resource name, etc. This allows code reuse and makes it easier to manage.

TERRAFORM
######################
# VARIABLES COMUNES  #
######################

variable "lz_subscription_id" {
  type        = string
  description = "ID de la susbcriptcion de los tfstate"
  default     = ""
}

variable "lz_resource_group_name" {
  type        = string
  description = "Nombre del resoruce group de los tfstate"
  default     = ""
}

variable "lz_storage_account_name" {
  type        = string
  description = "Nombre del storage account de los tfstate"
  default     = ""
}

variable "lz_container_name" {
  type        = string
  description = "Nombre del container name de los tfstate"
  default     = ""
}

variable "Tenant" {
  type        = string
  description = "Nombre del tenant"
  default     = ""
}

variable "Subscription" {
  type        = string
  description = "Nombre de la subscripcion"
  default     = ""
}

variable "Provider" {
  type        = string
  description = "Nombre del Provider cloud"
  default     = ""
}

variable "Environment" {
  type        = string
  description = "(Required) Specifies the Environment where the Resources should exist."
  default     = ""
}

variable "BussinessUnit" {
  type        = string
  description = "(Required) Bussiness Unit."
  default     = ""
}

variable "BussinessUnitExtended" {
  type        = string
  description = "(Required) Bussiness Unit Extended."
  default     = ""
}


variable "ProjectName" {
  type        = string
  description = "(Required) ProjectName."
  default     = ""
}

variable "ServiceName" {
  type        = string
  description = "(Required) ServiceName."
  default     = ""
}

variable "mapProjectPathKey" {
  type        = map(string)
  default     = {}
  description = "Mapa de rutas de los elementos"
}

variable "region" {
  type        = string
  description = "(Required) Region Name"
  default     = ""
}

#############################
#   VARIABLES DATAS         #
#############################

variable "rg_net_name" {
  type        = string
  description = "Name rg of net"
  default = ""
}

variable "vnet_net_name" {
  type        = string
  description = "Name of vnet of net"
  default = ""
}

variable "sbn_data_net_name" {
  type        = string
  description = "Name of Subnet Data of net"
  default = ""
}

variable "rg_bkp_name" {
  type        = string
  description = "Name of resource group of bkp"
  default = ""
}

variable "st_bkp_name" {
  type        = string
  description = "Name of storage Account of bkp"
  default = ""
}

variable "EntityName" {
  type        = string
  description = "(Required) Entity Name."
  default     = ""
}

#############################
# VARIABLES Storage Account #
#############################

variable "storage_account_name" {
  type        = string
  description = "Nombre del storage account"
  default     = ""
}


variable "storage_account_tier" {
  type = string
  description = "Tier of storage account"
  default = ""
}

variable "storage_account_replication_type" {
  type = string
  description = "Replication type of storage account"
  default = ""
}

variable "storage_account_access_tier" {
  type = string
  description = "Access tier storage account"
  default = ""
}

variable "storage_account_min_tls_version" {
  type = string
  description = "Min tls version storage account"
  default = ""
}


variable "storage_account_kind" {
  type = string
  description = "Storage account kind"
  default = ""
}


variable "storage_account_is_nhs_enabled" {
  type = bool
  description = "is nhs storage account enabled"
  default = true
}

######################
#   VARIABLE TAGS    #
######################

variable "tags" {
  type        = map(string)
  default     = {}
  description = "(Optional) A mapping of tags which should be assigned to the Resource Group."
}

##########################
# Variables Provider HUB #
##########################

variable "hub_resource_group_name" {
  type    = string
  default = ""
  description = "Nombre del resource group de HUB"
}

variable "private_dns_zone_name_01" {
  type    = string
  default = ""
  description = "Nombre del private dns zone name de HUB"
}

variable "private_dns_zone_name_02" {
  type    = string
  default = ""
  description = "Nombre del private dns zone name de HUB"
}

variable "virtual_network_appgw_name" {
  type    = string
  default = ""
  description = "Nombre del network appgw de HUB"
}

variable "subnet_appgw_name" {
  type    = string
  default = ""
  description = "Nombre del subnet appgw de HUB"
}

variable "subscription_hub_id" {
  type    = string
  default = ""
  description = "Nombre de la subscripcion de HUB"
}

Explanation:

1. Common variables

These variables allow you to set basic settings for remote state, subscription, and other key parameters:

  • lz_subscription_id and lz_resource_group_name

    • Subscription ID and name of the resource group where the remote state will be stored.
    • They facilitate the management of remote backend in Terraform, typically stored in Azure Storage.
  • lz_storage_account_name and lz_container_name

    • Configuration of the Storage Account and container used to store remote state (tfstate).
  • Tenant, Subscription, Provider

    • Information related to the Azure tenant, the subscription and the provider in use.
  • Environment, BussinessUnit, ProjectName and ServiceName

    • They detail the environment, business unit, project name, and service associated with the deployment.
    • These values ​​are usually used in the tag definition (tags) or in resource names.
  • region

    • Defines the Azure region where the resources will be deployed.
    • (Example: eastus, westeurope)

2. Network specific variables (DATAS)

These variables are necessary to configure the environment network:

  • rg_net_name: Name of the resource group that contains the virtual network.
  • vnet_net_name: Name of the associated virtual network.
  • sbn_data_net_name: Name of the subnet within the virtual network.
  • rg_bkp_name and st_bkp_name: Resources related to backups, such as resource group and Storage Account.
  • EntityName: Identifier name of the entity associated with the deployment.

3. Variables for the Storage Account

These variables allow you to customize the storage configuration:

  • storage_account_name

    • Name of the Storage Account. (Example: stproject001)
    • This value usually has to be globally unique.
  • storage_account_tier

    • Determines the level of performance, such as Standard either Premium.
  • storage_account_replication_type

    • Replication type: LRS, GRS, ZRS, etc.
    • (Example: LRS for local replication, GRS for geographic replication).
  • storage_account_access_tier

    • Access to data in storage: Hot either Cool.
  • storage_account_min_tls_version

    • Minimum TLS version for secure connections. (Example: TLS1_2)
  • storage_account_kind

    • Account type: Storage, StorageV2, etc.
  • storage_account_is_nhs_enabled

    • Indicates whether storage is enabled for NHS (Network Hierarchy Storage).

4. Tag variables

  • tags
    • Optional mapping to assign tags to resources.
    • Makes it easy to organize and filter resources in Azure. (Example: {"Environment" = "Dev", "Owner" = "TeamA"})

5. HUB provider specific variables

These variables are useful when the deployment involves integration or communication with a secondary subscription of type HUB (shared network, App Gateway, etc.):

  • hub_resource_group_name

    • HUB Resource Group.
  • private_dns_zone_name_01 and private_dns_zone_name_02

    • Private DNS zones used in the HUB environment. (Example: privatelink.blob.core.windows.net)
  • virtual_network_appgw_name and subnet_appgw_name

    • Network and subnet configuration for an Application Gateway.
  • subscription_hub_id

    • ID of the subscription associated with the HUB.

terragrunt.hcl

The file terragrunt.hcl What you provide sets up an environment to manage infrastructure using Terragrunt, which is a tool for managing Terraform configurations in a modular way. Here is a detailed breakdown of what this file does:

TERRAFORM
dependencies {
  paths = [
    "../../rg/00/"
  ]
}

include "varEnvironment" {
  path = find_in_parent_folders("varEnvironment.hcl")
  expose = true
}

include "varCommon" {
  path = find_in_parent_folders("varCommon.hcl")
  expose = true
}

include "varDataState" {
  path = find_in_parent_folders("varDataState.hcl")
  expose = true
}

locals {
  mapProjectPathKey = jsonencode(include.varEnvironment.inputs.mapProjectPathKey)
  tags = jsonencode(merge({
    Managed_By = "Terraform"
    Provider = "AZR"
  },
  include.varCommon.inputs.globalTags,
  include.varEnvironment.inputs.environmentTags
  ))
}

generate "backend"{
  path      = "backend.tfvars"
  if_exists = "overwrite" # "overwrite" "skip" "overwrite_terragrunt" 
  contents = <<EOF
subscription_id = "${include.varDataState.inputs.lz_subscription_id}"
key = "${include.varCommon.inputs.ProjectName}/${include.varCommon.inputs.ServiceName}/${get_path_from_repo_root()}/terraform.tfstate"
resource_group_name = "${include.varDataState.inputs.lz_resource_group_name}"
storage_account_name =  "${include.varDataState.inputs.lz_storage_account_name}"
container_name = "${include.varDataState.inputs.lz_container_name}"
EOF
}

generate "vars"{
  path      = "vars.tfvars"
  if_exists = "overwrite"
  contents = <<EOF
###############################
#    VALORES DATA DataState     #
###############################
lz_subscription_id             = "${include.varDataState.inputs.lz_subscription_id}"
lz_resource_group_name         = "${include.varDataState.inputs.lz_resource_group_name}" 
lz_storage_account_name        = "${include.varDataState.inputs.lz_storage_account_name}" 
lz_container_name              = "${include.varDataState.inputs.lz_container_name}" 

###############################
#     VALORES GENERALES       #
###############################
region  = "${include.varEnvironment.inputs.region}"
Environment = "${include.varEnvironment.inputs.Environment}"
BussinessUnit = "${include.varCommon.inputs.BussinessUnit}"
ProjectName = "${include.varCommon.inputs.ProjectName}"
ServiceName = "${include.varCommon.inputs.ServiceName}"
Subscription = "${include.varEnvironment.inputs.Subscription}"
Tenant = "${include.varCommon.inputs.Tenant}"
# ApplicationName = null
mapProjectPathKey = ${local.mapProjectPathKey}

##################################
# Valores Container Provider HUB #
##################################

hub_resource_group_name = "PRO-NWHUB-RGP-01"
private_dns_zone_name_01 = "privatelink.blob.core.windows.net"
private_dns_zone_name_02 = "privatelink.web.core.windows.net"
subscription_hub_id = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"

##############################
# Valores Storage Account    #
##############################

rg_net_name = "${include.varEnvironment.inputs.NetworkResourceGroup}"
vnet_net_name = "${include.varEnvironment.inputs.Network}"
sbn_data_net_name = "${include.varEnvironment.inputs.SubnetworkFront}"

storage_account_name = "st01"

storage_account_tier = "Standard"
storage_account_replication_type = "LRS"
storage_account_access_tier = "Hot"
storage_account_min_tls_version = "TLS1_2"
storage_account_is_nhs_enabled = "false"
storage_account_kind = "StorageV2"

###########################
#       VALORES TAGS      #
###########################

tags = ${local.tags}

EOF
}

terraform {
  source = "../../..//code/storage/00/"

  before_hook "print_tags" {
    commands = ["plan", "apply"] #["${get_terraform_commands_that_need_vars()}"]
    execute  = ["echo", "tags", "=", "${local.tags}", ">", "vars.tfvars"]
  }

  before_hook "copy_vars" {
    commands = ["plan", "apply"] #["${get_terraform_commands_that_need_vars()}"]
    execute  = ["cp", "-f", "vars.tfvars", "${get_original_terragrunt_dir()}/vars.tfvars"]
  }

  extra_arguments "backend_vars" {
    commands = ["init"]
    arguments = [
      "-backend-config=backend.tfvars"
    ]
  }
  extra_arguments "vars_vars" {
    commands = ["plan", "apply", "destroy", "import"]

    arguments = [
      "-var-file=vars.tfvars"
    ]
  }
}

Explanation:

  • dependencies: This block defines the Terragrunt dependencies. In this case, no dependency paths are specified, since the block paths It is empty.
  • include: These blocks include external variable files (varEnvironment.hclvarCommon.hclvarDataState.hcl) in Terragrunt. The included files can expose their variables to be used in this Terragrunt file.
  • locals: This block defines local variables that are used within this Terragrunt file.
  • mapProjectPathKey: Encode the map as JSON mapProjectPathKey from the file varEnvironment.hcl.
  • tagsJSON-encodes a set of tags by combining a fixed set of tags (Managed_By and Provider), the global labels defined in varCommon.hcl and the environment-specific tags defined in varEnvironment.hcl.
  • generate "backend": This block generates a file called backend.tfvars. This file is used to configure the Terraform backend. It contains variables like subscription_idkeyresource_group_namestorage_account_name, and container_name. The values ​​of these variables are obtained from the included files (varDataState.hcl and varCommon.hcl).
  • generate "vars": This block generates a file called vars.tfvars. This file is used to provide variable values ​​to Terraform. Contains values ​​for specific variables defined in the included files (varDataState.hclvarCommon.hclvarEnvironment.hcl). The values ​​are interpolated from the included variables.
  • terraform: This block provides additional settings for Terraform.
  • source: Specifies the source path of the Terraform module. In this case, the origin is set to a relative directory ../../..//code/rg/00/.
  • before_hookThis block defines execution hooks that will be executed before certain Terraform commands, such as plan and apply. In this case, two hooks are executed: print_tags and copy_vars.
  • extra_arguments: This block specifies additional arguments to be passed to Terraform commands (initplanapplydestroyimport). In this case, additional arguments are specified for the backend configuration (backend_vars) and for the variables (vars_vars).

varEnvironment.hcl

JAVA
locals {
  region               = "northeurope"
  Environment          = "dev"
  EnvironmentLetter    = "d"
  Subscription         = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
  NetworkResourceGroup = "DEV-REDORBITA-RG-01"
  Network              = "DEV-REDORBITA-NET-01"
  SubnetworkFront      = "DEV-REDORBITA-SBN-01"
  SubnetworkVint       = "DEV-REDORBITA-VINT-SBN-01"
  mapProjectPathKey = {
    rg                          = "rg/00",
    sbnVint00                   = "networking/sbn/vint00",
	storage                     = "storage/00"
   }
}

inputs = {
  region               = local.region
  Environment          = local.Environment
  EnvironmentLetter    = local.EnvironmentLetter
  Subscription         = local.Subscription
  NetworkResourceGroup = local.NetworkResourceGroup
  Network              = local.Network
  SubnetworkFront      = local.SubnetworkFront
  SubnetworkVint      = local.SubnetworkVint
  environmentTags = {
    Enviroment       = "${upper(local.Environment)}"
  }
  mapProjectPathKey = local.mapProjectPathKey
 }
}

varCommon.hcl

This file contains a structured definition of local values and common entries which are used to organize and parameterize resources within Terraform. The combination of locals and inputs allows configurations to be separated by environment and facilitates code reuse across multiple projects. Each section is detailed below:

TERRAFORM
locals {
  EntityName              = "RO"
  ProjectName             = "RedOrbita"
  ServiceName             = "RedOrbita"
  BussinessUnit           = "XX"
  Subscription            = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
  Tenant                  = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
  Provider                = "azr"
  required_version = "~>0.14"
  globalTags = {
      Company             = "Red-Orbita"
      Owner               = "xxxx@redorbita.com"
      ProjectName         = "XXXX"
      "Service Description" = "XXXX"
      Status              = "Implementacion"
      Provider            = "Azure"
      Cluster             = "N/A"
      "Operating System"  = "N/A"
      Temporal            = "NO"
      "App ID"              = "N/A"
    }
  storage_account          = "protfdata"
  container_name           = "iasearch" 
  subscription_hub_id2     = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
  location                 = "northeurope"
}



inputs = {
  ##############################
  #  VARIABLES COMMON          #
  ##############################

  EntityName              = local.EntityName
  ProjectName             = local.ProjectName
  ServiceName             = local.ServiceName
  BussinessUnit           = local.BussinessUnit
  Subscription            = local.Subscription
  Tenant                  = local.Tenant
  Provider                = local.Provider
  required_version        = local.required_version
  globalTags              = local.globalTags
}



inputs = {
  ##############################
  #  VARIABLES COMMON          #
  ##############################

  EntityName              = local.EntityName
  ProjectName             = local.ProjectName
  ServiceName             = local.ServiceName
  BussinessUnit           = local.BussinessUnit
  # Subscription            = local.Subscription
  # Subscription_pro        = local.Subscription_pro
  Tenant                  = local.Tenant
  Provider                = local.Provider
  required_version        = local.required_version
  id_project              = local.id_project
  globalTags              = local.globalTags
}
  • Block locals

    In this block, local variables are defined within the file that can be used within the file itself or by other Terraform modules:

    • EntityName: It is the name of the entity associated with the project, in this case, "RO". It is generally used as an identifier for a project or unit within the organization.
    • ProjectName: The name of the project, in this case, "RedOrbita", which identifies the name of the initiative under which the resources are managed.
    • ServiceName: The name of the service related to the project, here it is also defined as "RedOrbita". Refers to the main service or solution that will be implemented.
    • BusinessUnit: Specifies the business unit associated with the project, here represented by "XX".
    • Subscription- The ID of the Azure subscription associated with the project. It is a single value that is used to manage resources within the Azure subscription.
    • Tenant- The Azure tenant ID, which represents a unique directory within Azure Active Directory.
    • Provider: The infrastructure provider to use. In this case, "azr" refers to Azure.
    • required_version: Specifies the version of Terraform required to run this file. In this case, any version compatible with “0.14.x” is required.
    • globalTags: Defines a set of global tags that will be applied to all resources. Tags include details such as company name, project owner, project status, service description, infrastructure provider, etc.
    • storage_account: The name of the Azure storage account, in this case “protfdata”.
    • container_name: The name of the container within the Azure storage account, “iasearch”.
    • subscription_hub_id2: A second subscription ID, possibly related to the network hub or specific resources.
    • location: Specifies the Azure region where the resources will be deployed, in this case, "northeurope."
  • Block inputs

    The block of inputs takes the values ​​defined in the block locals and passes them as inputs to be used in other modules or resources within the project. The common variables defined in locals They are referenced here to ensure consistency of values ​​throughout the project. In this case, the same entries are repeated for the defined variables, allowing their reuse in other Terraform modules.

    • EntityName, ProjectName, ServiceName, BusinessUnit, Subscription, Tenant, Provider, required_version, globalTags: These inputs are assigned directly to the local variables defined above, ensuring that the values ​​are consistent throughout the project.

    • project_id: Reference is made to a variable called id_project, although this is not defined in the premises. This suggests that this variable can be defined elsewhere or used for specific projects.

varDataState.hcl

This file varDataState.hcl It is used to define and organize variables related to the state of Terraform data and infrastructure in the workbench. This file contains configurations for storing Terraform state in Azure, which is crucial for managing infrastructure resources and their persistence. The purpose and use of the settings defined in this file are explained below:

 

CODE

locals {
 lz_subscription_id = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
 lz_resource_group_name = "PRO-HUB-01"
 lz_storage_account_name = "storage"
 lz_container_name = "storage"
 path_resources_terraform_state = jsonencode({
 rg = "rg/00"

})
}

inputs = {
##############################
# VARIABLES FOR DATA STATES #
##############################
lz_subscription_id = local.lz_subscription_id
lz_resource_group_name = local.lz_resource_group_name
lz_storage_account_name = local.lz_storage_account_name
lz_container_name = local.lz_container_name
path_resources_terraform_state = local.path_resources_terraform_state
}

1. Block locals

The block locals defines local variables within this file, which can be reused within the file or in other Terraform modules. Local variables defined here include:

  • lz_subscription_id: The ID of the Azure subscription used to manage resources in the infrastructure. This value is unique for each Azure subscription.
  • lz_resource_group_name: The name of the Azure resource group that will be used to store the Terraform resources, in this case PRO-HUB-01. Resource groups are logical units that group related resources in Azure.
  • lz_storage_account_name: The name of the Azure storage account, in this case storage, which will be used to store Terraform state and other persistent resources.
  • lz_container_name: The name of the container within the Azure storage account, here named storage, where the Terraform state files will be stored.
  • path_resources_terraform_state: A value in JSON format that defines the path within the storage container where Terraform state files will be saved. In this case, the route is defined as rg/00.

2. Block inputs

The block inputs It is used to define the inputs of the variables that will be passed to the Terraform modules. These entries correspond to the local variables that were previously defined and will be used to configure Terraform state storage in Azure. The input variables are:

  • lz_subscription_id- The ID of the Azure subscription that is passed as input to the modules.
  • lz_resource_group_name: The name of the resource group to pass as input.
  • lz_storage_account_name: The name of the storage account that will be used to manage the state.
  • lz_container_name: The name of the container where the state will be stored.
  • path_resources_terraform_state: The path where the Terraform state will be stored within the container.

:wq!

Comments