Skip to content

Commit

Permalink
Store TF Vars in a Storage Container
Browse files Browse the repository at this point in the history
  • Loading branch information
DrizzlyOwl committed Mar 18, 2024
1 parent 63e805b commit 316dfca
Show file tree
Hide file tree
Showing 7 changed files with 201 additions and 14 deletions.
40 changes: 29 additions & 11 deletions .terraform.lock.hcl

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,14 @@ key = "terraform.tstate"
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.6.1 |
| <a name="requirement_azurerm"></a> [azurerm](#requirement\_azurerm) | >= 3.51.0 |
| <a name="requirement_null"></a> [null](#requirement\_null) | 3.2.2 |

## Providers

| Name | Version |
|------|---------|
| <a name="provider_azurerm"></a> [azurerm](#provider\_azurerm) | 3.90.0 |
| <a name="provider_null"></a> [null](#provider\_null) | 3.2.2 |

## Modules

Expand All @@ -63,6 +65,11 @@ key = "terraform.tstate"

| Name | Type |
|------|------|
| [azurerm_storage_account.tfvars](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/storage_account) | resource |
| [azurerm_storage_account_network_rules.tfvars](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/storage_account_network_rules) | resource |
| [azurerm_storage_blob.tfvars](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/storage_blob) | resource |
| [azurerm_storage_container.tfvars](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/storage_container) | resource |
| [null_resource.tfvars](https://registry.terraform.io/providers/hashicorp/null/3.2.2/docs/resources/resource) | resource |
| [azurerm_container_app.container_apps](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/container_app) | data source |
| [azurerm_linux_web_app.web_apps](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/linux_web_app) | data source |
| [azurerm_resource_group.container_apps](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/resource_group) | data source |
Expand All @@ -88,6 +95,8 @@ key = "terraform.tstate"
| <a name="input_project_name"></a> [project\_name](#input\_project\_name) | Project name. Will be used along with `environment` as a prefix for all resources. | `string` | n/a | yes |
| <a name="input_response_request_timeout"></a> [response\_request\_timeout](#input\_response\_request\_timeout) | Azure CDN Front Door response or App Gateway V2 request timeout in seconds | `number` | n/a | yes |
| <a name="input_tags"></a> [tags](#input\_tags) | Tags to be applied to all resources | `map(string)` | n/a | yes |
| <a name="input_tfvars_access_ipv4"></a> [tfvars\_access\_ipv4](#input\_tfvars\_access\_ipv4) | List of IPv4 Addresses that are permitted to access the tfvars Storage Account | `list(string)` | `[]` | no |
| <a name="input_tfvars_filename"></a> [tfvars\_filename](#input\_tfvars\_filename) | Name of the TF Vars file | `string` | `"terraform.tfvars"` | no |
| <a name="input_waf_application"></a> [waf\_application](#input\_waf\_application) | Which product to apply the WAF to. Must be either CDN or AppGatewayV2 | `string` | n/a | yes |
| <a name="input_waf_custom_rules"></a> [waf\_custom\_rules](#input\_waf\_custom\_rules) | Map of all Custom rules you want to apply to the WAF | <pre>map(object({<br> priority : number,<br> action : string<br> match_conditions : map(object({<br> match_variable : string,<br> match_values : optional(list(string), []),<br> operator : optional(string, "Any"),<br> selector : optional(string, ""),<br> }))<br> }))</pre> | `{}` | no |
| <a name="input_waf_mode"></a> [waf\_mode](#input\_waf\_mode) | WAF mode | `string` | n/a | yes |
Expand Down
10 changes: 7 additions & 3 deletions locals.tf
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
locals {
environment = var.environment
project_name = var.project_name
azure_location = var.azure_location
environment = var.environment
project_name = var.project_name
azure_location = var.azure_location
resource_prefix = "${local.environment}${local.project_name}"

key_vault_app_gateway_certificates_access_users = var.key_vault_app_gateway_certificates_access_users
key_vault_app_gateway_certificates_access_ipv4 = var.key_vault_app_gateway_certificates_access_ipv4
key_vault_app_gateway_certificates_access_subnet_ids = var.key_vault_app_gateway_certificates_access_subnet_ids

tfvars_filename = var.tfvars_filename
tfvars_access_ipv4 = var.tfvars_access_ipv4

existing_logic_app_workflow = var.existing_logic_app_workflow
monitor_email_receivers = var.monitor_email_receivers

Expand Down
93 changes: 93 additions & 0 deletions scripts/check-tfvars-against-remote.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
#!/bin/bash

# exit on failures
set -e
set -o pipefail

usage() {
echo "Usage: $(basename "$0") [OPTIONS]" 1>&2
echo " -h - help"
echo " -a <storage_account> - Azure Storage Account name"
echo " -c <storage_container> - Azure Storage Container name"
echo " -f <tfvars_filename> - Name of the tfvars file with file extension"
exit 1
}

# if there are not arguments passed exit with usage
if [ $# -eq 0 ]
then
usage
fi

while getopts "a:c:f:h" opt; do
case $opt in
a)
STORAGE_ACCOUNT_NAME=$OPTARG
;;
c)
STORAGE_CONTAINER_NAME=$OPTARG
;;
f)
TFVARS_FILE_NAME=$OPTARG
;;
h)
usage
;;
*)
usage
;;
esac
done

if [[
-z "$STORAGE_ACCOUNT_NAME" ||
-z "$STORAGE_CONTAINER_NAME" ||
-z "$TFVARS_FILE_NAME"
]]
then
usage
fi

set +e
STORAGE_CHECK=$(az storage blob list --account-name "$STORAGE_ACCOUNT_NAME" --container-name "$STORAGE_CONTAINER_NAME" 2>&1)
set -e

if ! jq -r >/dev/null 2>&1 <<< "$STORAGE_CHECK"
then
exit 0
fi

LAST_UPDATED=$(jq -r \
--arg name "$TFVARS_FILE_NAME" \
'.[] | select(.name==$name) | .properties.lastModified' \
<<< "$STORAGE_CHECK")

if [ -z "$LAST_UPDATED" ]
then
exit 0
fi

LAST_UPDATED=$(echo "$LAST_UPDATED" | cut -d'+' -f1)
LAST_UPDATED_SECONDS=$(date -j -f "%Y-%m-%dT%H:%M:%S" "$LAST_UPDATED" "+%s")

if [ "$LAST_UPDATED_SECONDS" -gt "$(date -r "$TFVARS_FILE_NAME" +%s)" ]
then
echo ""
echo ""
echo "Error: Your local tfvars file is older than the remote!"
echo ""
echo "Ensure you have the latest tfvars by running:"
echo ""
echo " mv $TFVARS_FILE_NAME $TFVARS_FILE_NAME.old"
echo " az storage blob download \\"
echo " --file $TFVARS_FILE_NAME \\"
echo " --container-name $STORAGE_CONTAINER_NAME \\"
echo " --account-name $STORAGE_ACCOUNT_NAME \\"
echo " --name $TFVARS_FILE_NAME"
echo ""
echo "Or if you are sure your local tfvars are correct, just update the modified time by running:"
echo ""
echo " touch $TFVARS_FILE_NAME"
echo ""
exit 1
fi
47 changes: 47 additions & 0 deletions tfvars-storage.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
resource "azurerm_storage_account" "tfvars" {
name = "${replace(local.resource_prefix, "-", "")}tfvars"
resource_group_name = local.resource_prefix
location = local.azure_location
account_tier = "Standard"
account_replication_type = "LRS"
min_tls_version = "TLS1_2"
enable_https_traffic_only = true
public_network_access_enabled = true

tags = local.tags
}

resource "azurerm_storage_container" "tfvars" {
name = "${local.resource_prefix}-tfvars"
storage_account_name = azurerm_storage_account.tfvars.name
container_access_type = "private"
}

resource "azurerm_storage_blob" "tfvars" {
name = local.tfvars_filename
storage_account_name = azurerm_storage_account.tfvars.name
storage_container_name = azurerm_storage_container.tfvars.name
type = "Block"
source = local.tfvars_filename
content_md5 = filemd5(local.tfvars_filename)
access_tier = "Cool"
}

resource "azurerm_storage_account_network_rules" "tfvars" {
storage_account_id = azurerm_storage_account.tfvars.id
default_action = length(local.tfvars_access_ipv4) > 0 ? "Deny" : "Allow"
bypass = []
virtual_network_subnet_ids = []
ip_rules = local.tfvars_access_ipv4
}

resource "null_resource" "tfvars" {
provisioner "local-exec" {
interpreter = ["/bin/bash", "-c"]
command = "./scripts/check-tfvars-against-remote.sh -c \"${azurerm_storage_container.tfvars.name}\" -a \"${azurerm_storage_account.tfvars.name}\" -f \"${local.tfvars_filename}\""
}

triggers = {
tfvar_file_md5 = filemd5(local.tfvars_filename)
}
}
12 changes: 12 additions & 0 deletions variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -186,3 +186,15 @@ variable "monitor_email_receivers" {
type = list(string)
default = []
}

variable "tfvars_filename" {
description = "Name of the TF Vars file"
default = "terraform.tfvars"
type = string
}

variable "tfvars_access_ipv4" {
description = "List of IPv4 Addresses that are permitted to access the tfvars Storage Account"
default = []
type = list(string)
}
4 changes: 4 additions & 0 deletions versions.tf
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,9 @@ terraform {
source = "hashicorp/azurerm"
version = ">= 3.51.0"
}
null = {
source = "hashicorp/null"
version = "3.2.2"
}
}
}

0 comments on commit 316dfca

Please sign in to comment.