So the idea is to create resource health alert for multiple storage accounts using terraform. It's fairly simple for one storage account as one would pass the value
output "id" {
description = "Id of the storage account created."
value = azurerm_storage_account.storage.id
}
to the resource_id or hardcode the resource id with the resource actual id. But my ask here is how I can setup one single alert block for all the storage accounts provisioned by the terraform. I have been trying to use the above data block but the name variable would take only strings. Please provide a sample example as to how you would do it.
locals {
activity_log_alerts = {
resource_health_alerts= {
environment = var.environment
resource_group_name = var.rgp
enabled = "true"
** scopes = module.main.storage_account_name["storage_name"] **
alert_name = “Resource health alert for storage accounts”
description = format(“The state of the azure resource is unknown”}
category = "ResourceHealth"
level = "Critical"
operation_name = null
resource_health = [
{
current = ["Unknown"]
previous = ["Available"]
reason = ["PlatformInitiated"]
}
]
The error I received is this: Error: Null value found in list
scopes = tolist([var.resource_id])
UPDATE: Another Approach With this approach I was hoping to get all the resource under the same RG and subscription but got the same error
data "azurerm_subscription" "current" {
subscription_id = var.subscription_id
}
locals {
activity_log_alerts = {
resource_health_alerts= {
environment = var.environment
resource_group_name = var.rgp
enabled = "true"
scopes = [data.azurerm_subscription.current.id]
alert_name = “Resource health alert for storage accounts”
description = format(“The state of the azure resource is unknown”}
category = "ResourceHealth"
level = "Critical"
operation_name = null
resource_health = [
{
current = ["Unknown"]
previous = ["Available"]
reason = ["PlatformInitiated"]
}
]
The error I received is this: Error: Null value found in list
scopes = tolist([var.resource_id])
Related
I am trying to create a new Azure CosmosDB account in terraform account using:
create_mode = "Restore"
Basically I am trying to restore from an existing DB, and the code needs another input attribute, of the source DB:
"source_cosmosdb_account_id" = "/subscriptions/33f91226-e87e-4cdf67a1dae4e/providers/Microsoft.DocumentDB/locations/westeu/restorableDatabaseAccounts/test-source-db-name"
I am following the format indicated by the docs:
The example is /subscriptions/{subscriptionId}/providers/Microsoft.DocumentDB/locations/{location}/restorableDatabaseAccounts/{restorableDatabaseAccountName}
However when I apply the code, I get the following error:
Code="BadRequest" Message="Failed to parse uri
/subscriptions/33f91226-e87e-4ca1dae4e/providers/Microsoft.DocumentDB/locations/westeu/restorableDatabaseAccounts/test-source-db-name
The issue seems to be the way I write the location inside the source ID, but I can't find any relevant info on how is the correct way.
I would really appreciate an example of source_cosmosdb_account_id if anyone did this successfully in terraform.
Thanks
Configuration used:
backup = [
{
type = "Continuous"
interval_in_minutes = null
retention_in_hours = null
storage_redundancy = null
}
]
restore = [
{
"source_cosmosdb_account_id" = "/subscriptions/33f6-e87e-4cdf-9480-7b1dae/providers/Microsoft.DocumentDB/locations/westeu/restorableDatabaseAccounts/test-source-db-name"
"restore_timestamp_in_utc" = "2022-11-18T14:00:00.00Z"
"database" = []
}
]
I've recently faced same issue and discovered that terraform documentation is outdated.
You need to have create_mode = "Restore"
Backup should be configured like this
backup = [
{
type = "Continuous"
interval_in_minutes = 0
retention_in_hours = 0
storage_redundancy = "Geo"
}
]
Format /subscriptions/{subscriptionId}/providers/Microsoft.DocumentDB/locations/{location}/restorableDatabaseAccounts/{restorableDatabaseAccountName}
is not correct
Try with /subscriptions/{subscriptionId}/providers/Microsoft.DocumentDB/locations/{location}/restorableDatabaseAccounts/{**instanceId**}
You can find cosmos instanceId in json view
I tried to reproduce the issue in my environment.
I got the same error , Failed to parse uri /subscriptions/xxxx/providers/Microsoft.DocumentDB/locations/westeu/restorableDatabaseAccounts/test-source-db-name
with:
resource "azurerm_cosmosdb_account" "db" {
name = "tfex-cosmos-db-31960"
location = "westus2"
resource_group_name = data.azurerm_resource_group.example.name
offer_type = "Standard"
kind = "MongoDB"
create_mode = "Restore"
restore { source_cosmosdb_account_id=data.azurerm_cosmosdb_restorable_database_accounts.example.id
source_cosmosdb_account_id="/subscriptions/xxxxx/providers/Microsoft.DocumentDB/locations/westeurope/restorableDatabaseAccounts/tfex-cosmos-db-31960?api-version=2022-05-15"
restore_timestamp_in_utc="2022-11-25T22:06:00Z"
}
...
}
If I tried with westeu as the location you gave , in my case I am getting below error , as it must be westeurope as supported by azure .
Also please check
Note from cosmosdb_account | terraform registry: Database account
with Continuous type (or deleted account in last 30 days) are the
restorable accounts and there cannot be Create/Update/Delete
operations on the restorable database accounts. They can only be read and be retrieved by azurerm_cosmosdb_restorable_database_accounts.
Restore the cosmos db account is supported in azure portal , powershell,Azure CLI , ARM template as in restore-account-continuous-backup | Microsoft Learn
With azurerm provider , i can only read it through below with continuous backup type :
resource "azurerm_cosmosdb_account" "db" {
name = "tfex-cosmos-db-31960"
location = "westus2"
resource_group_name = data.azurerm_resource_group.example.name
offer_type = "Standard"
kind = "MongoDB"
enable_automatic_failover = true
capabilities {
name = "EnableAggregationPipeline"
}
capabilities {
name = "mongoEnableDocLevelTTL"
}
capabilities {
name = "MongoDBv3.4"
}
capabilities {
name = "EnableMongo"
}
consistency_policy {
consistency_level = "BoundedStaleness"
max_interval_in_seconds = 300
max_staleness_prefix = 100000
}
geo_location {
location = "eastus"
failover_priority = 0
}
backup{
type = "Continuous"
//interval_in_minutes=60
}
data "azurerm_cosmosdb_restorable_database_accounts" "example" {
name = azurerm_cosmosdb_account.db.name
location = "West Europe"
}
output "name" {
value=data.azurerm_cosmosdb_restorable_database_accounts.example.name
}
output "id" {
value = data.azurerm_cosmosdb_restorable_database_accounts.example.id
}
Output:
Try checking the same with azapi_resource block in terraform :
as it requires parameters like api version , source account id which has to come from cosmosdb_restorable_database_accounts
list and must form uri like https://management.azure.com/subscriptions/subid/providers/Microsoft.DocumentDB/locations/West US/restorableDatabaseAccounts/d9b2xxx10d?api-version=2022-05-15 which is compatible in api resource.
I have created an Activity Log Alert in Azure using the following Terraform Code
// We need to define the action group for Security Alerts
resource "azurerm_monitor_action_group" "monitor_action_group_soc" {
name = "sec-alert"
resource_group_name = data.azurerm_resource_group.tenant-global.name
short_name = "sec-alert"
email_receiver {
name = "sendtoAdmin"
email_address = var.email_address
use_common_alert_schema = true
}
}
data "azurerm_monitor_action_group" "monitor_action_group_soc" {
name = "sec-alert"
resource_group_name = var.tenant-global-rg
depends_on = [
azurerm_monitor_action_group.monitor_action_group_soc
]
}
// Monitor Activity Log and Alert
resource "azurerm_monitor_activity_log_alert" "activity_log_alert_cu_security_group" {
name = "Activity Log Alert for Create or Update Security Group"
resource_group_name = data.azurerm_resource_group.ipz12-dat-np-mgmt-rg.name
scopes = [data.azurerm_subscription.current.id]
description = "Monitoring for Create or Update Network Security Group events gives insight into network access changes and may reduce the time it takes to detect suspicious activity"
criteria {
category = "Security"
operation_name = "Microsoft.Network/networkSecurityGroups/write"
}
action {
action_group_id = data.azurerm_monitor_action_group.monitor_action_group_soc.id
}
}
I have created the Network Security Group, added a Rule, deleted the Rule and finally deleted the Network Security Group but I didn't receive any Alerts.
Azure Activity Log Alerts are not working:
These are the modifications I made to your code to achieve the expected result.
provider "azurerm" {
features {}
}
resource "azurerm_resource_group" "<resourcegroup>"{
name = "<resourcegroup>"
location = "Central US"
}
resource "azurerm_monitor_action_group" "<actiongroup>" {
name = "sec-alert"
resource_group_name = "<resourcegroup>"
short_name = "sec-alert"
email_receiver {
name = "xxxxx"
email_address = "xxxxxxx#gmail.com"
use_common_alert_schema = true
}
}
data "azurerm_monitor_action_group" "<actiongroup>" {
name = "sec-alert"
resource_group_name = "<resourcegroup>"
depends_on = [
azurerm_monitor_action_group.<actiongroup>
]
}
resource "azurerm_monitor_activity_log_alert" "azurerm_monitor_activity_log_alert_securitygroup" {
name = "Activity Log Alert for Create or Update Security Group"
resource_group_name = "<resourcegroup>"
scopes = [data.azurerm_subscription.current.id] #My scope is /subscriptions/<subscriptionID>/resourceGroups/<resourcegroup>/providers/Microsoft.Network/networkSecurityGroups/<NetworkSecurityGroup>
description = "Monitoring for Create or Update Network Security Group events gives insight into network access changes and may reduce the time it takes to detect suspicious activity"
criteria {
category = "Security"
operation_name = "Microsoft.Network/networkSecurityGroups/write"
}
action {
action_group_id = data.azurerm_monitor_action_group.<actiongroup>.id
}
}
Created Security alert by running "terraform apply" in AzCLI :
Received a mail once it is added to the Network Security Group:
Trying to add the Event status in Resource health block (not accepting it)
Tried adding the resource_type variable as mentioned in terraform documentation to
select the resource types to get this alert apply on.but its omitting
conflicting error msg is
"criteria.. resource health": conflicts with criteria.o.resource type
resource "azurerm_monitor_activity_log_alert" "reshealthalert" {
name = "resourceHealthFromMain "
resource_group_name = azurerm_resource_group.rg.name
scopes = ["/subscriptions/${data.azurerm_subscription.current.subscription_id}"]
description = var.monitor_activity_log_alert_description
criteria {
category = var.criteria_resource_health
# resource_type = "Storage account"
resource_health {
current = var.current_resource_status
previous = var.previous_resource_status
# events = var.resource_health_events
reason = var.reason_type
#event_status = var.resource_health_events
} }
action {
action_group_id = azurerm_monitor_action_group.email_alert.id } }
Please check the below terraform code.
Please make sure to give resource_type before category and give resourceId
format of storage account in the form resource_type= "Microsoft.Storage/storageAccounts"
main.tf
resource "azurerm_monitor_activity_log_alert" "reshealthalert" {
name = "ka-resource-Health "
resource_group_name = azurerm_resource_group.example.name
scopes = ["/subscriptions/xxxxxxxxxx"]
description = "This alert will monitor a specific storage account updates."
resource_type= "Microsoft.Storage/storageAccounts"
#resource_type = "Storage account"
criteria {
category = var.criteria_resource_health
...
}
Reference:
azurerm_monitor_activity_log_alert | Resources | hashicorp/azurerm | Terraform Registry
I want to deploy multiple azure cloud resources with terraform. My problem is with the terraform script for an azure IoT Hub, exspecially the ip restriction rules. According to the documentation I can do something like this
resource "azurerm_iothub" "iothubname" {
name = "somename"
resource_group_name = azurerm_resource_group.someresourcegroup
location = azurerm_resource_group.somelocation
sku {
name = "B2"
capacity = "2"
}
fallback_route {
enabled = true
}
ip_filter_rule {
action = "Accept"
ip_mask ="some_ip_range_1"
name = "some_name_1"
}
ip_filter_rule {
action = "Accept"
ip_mask ="some_ip_range_2"
name = "some_name_2" }
ip_filter_rule {
action = "Accept"
ip_mask ="some_ip_range_3"
name = "some_name_3"
}
ip_filter_rule {
action = "Reject"
ip_mask ="0.0.0.0/0"
name = "everything_else"
}
}
Everything works fine, ecept that the ordering of the ip rules is not the same as above and in my case I definitely want the last rule to be the the one with the lowest priority on azure. Azure IoT hub applies the filter rules in order.
How can I enforce a certain ordering of ip filter?
You can try to use dynamic blocks
https://www.terraform.io/docs/configuration/expressions/dynamic-blocks.html
File main.tf
resource "azurerm_iothub" "iothubname" {
name = "somename"
resource_group_name = azurerm_resource_group.someresourcegroup
location = azurerm_resource_group.somelocation
sku {
name = "B2"
capacity = "2"
}
fallback_route {
enabled = true
}
dynamic "ip_filter_rule" {
for_each = var.ip_filter_rule_list
content {
action = ip_filter_rule.value.action
ip_mask = ip_filter_rule.value.ip_mask
name = ip_filter_rule.value.name
}
}
}
File variables.tf
variable "ip_filter_rule_list" {
type = list
default = []
}
Update
Bug is fixed in terraform provider azurerm v2.57.0
https://github.com/terraform-providers/terraform-provider-azurerm/pull/11390
Is there any way to skip the terraform block/file if defined variable is empty or null. Instead of throwing error.
I have created tow terraform script for azure.
For azure automation creation, runbook creation.
For event grid creation.
After executing the first step I have to generate a webhook URL manually (there no such automation support for webhook generation). after generating of webhook URL I need to define it in second resource. If I defined empty/null or invalid URL then terraform throw the error.
below is the terraform code.
data "local_file" "runbook_script" {
filename = "${path.module}/envent-grid-runbook.ps1"
}
resource "azurerm_automation_runbook" "runbook" {
name = "event-gird-notification"
location = var.location
resource_group_name = var.resource_group_name
automation_account_name = azurerm_automation_account.CreateAutomation.name
log_verbose = true
log_progress = true
description = "This runbook is creted for event grid notification"
runbook_type = "PowerShell"
content = data.local_file.runbook_script.content
publish_content_link {
uri = ""
}
}
resource "azurerm_eventgrid_event_subscription" "key-vault" {
name = "test"
scope = "/subscriptions/xxxxxxxxxxxxxxxxxxxxxx/xxxxxxxxxxxxxxxxxxxx/name"
topic_name = "/subscriptions/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/xxxxxx/vault"
webhook_endpoint {
url = var.webhook_url
}
included_event_types = [
"Microsoft.KeyVault.SecretNewVersionCreated",
"Microsoft.KeyVault.SecretNearExpiry",
"Microsoft.KeyVault.SecretExpired"
]
event_delivery_schema = "EventGridSchema"
}
If I defined null/empty var for webhook ULR variable. then getting below error.
Error: "webhook_endpoint.0.url": required field is not set
I have created a Jenkins job, where all terraform code to run in a single job. if the code fails, then entire job is getting failed. That's why looking for a solution to skip the specific block/file if var is empty or null.
I assume that you want to make entire azurerm_eventgrid_event_subscription resource optional, based on var.webhook_url you can use count.
For example:
resource "azurerm_eventgrid_event_subscription" "key-vault" {
count = var.webhook_url == "" ? 0 : 1
name = "test"
scope = "/subscriptions/xxxxxxxxxxxxxxxxxxxxxx/xxxxxxxxxxxxxxxxxxxx/name"
topic_name = "/subscriptions/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/xxxxxx/vault"
webhook_endpoint" {
url = var.webhook_url
}
included_event_types = [
"Microsoft.KeyVault.SecretNewVersionCreated",
"Microsoft.KeyVault.SecretNearExpiry",
"Microsoft.KeyVault.SecretExpired"
]
event_delivery_schema = "EventGridSchema"
}
In the above example, you may need to adjust the condition based on what values var.webhook_url can actually have to be consider correct or incorrect.