Getting Error related to Azure App Registration using Terraform - azure

I am trying to do Azure AD app registration using Terraform
My code is given below
locals {
app_roles = {
application-administrator = {
display_name = "Application administrator"
description = "Application administrators have the ability to administer the application."
allowed_member_types = ["User", "Application"]
}
BusinessAdmin = {
display_name = "BusinessAdmin"
description = "Business Administrator"
allowed_member_types = ["User"]
}
mulesoft-integration = {
display_name = "Mulesoft Integration"
description = "Allows MuleSoft Integration to talk to the APIs."
allowed_member_types = ["Application"]
}
}
oauth2_permissions = {
read-and-write = {
user_consent_description = "read-and-write"
admin_consent_display_name = "Read and write data"
admin_consent_description = "Allows the app to read and write data"
user_consent_display_name = "Allows the app to read and write data"
type = "User"
}
}
}
data "azuread_application_published_app_ids" "well_known" {}
data "azuread_service_principal" "msgraph" {
application_id = data.azuread_application_published_app_ids.well_known.result.MicrosoftGraph
}
resource "random_uuid" "prodstats" {}
resource "azuread_application" "app_prodstats" {
display_name = format("app-%s-%s", var.project.name, var.project.environment.name)
owners = [data.azuread_client_config.default.object_id]
identifier_uris = [format("https://contoso.onmicrosoft.com/%s-%s", var.project.name, var.project.environment.name)]
api {
oauth2_permission_scope {
admin_consent_description = "Allows the app to read and write data"
admin_consent_display_name = local.oauth2_permissions.read-and-write.admin_consent_display_name
enabled = true
id = random_uuid.prodstats.result
type = "User"
value = "read-and-write"
}
}
dynamic "app_role" {
for_each = local.app_roles
content {
allowed_member_types = app_role.value.allowed_member_types
description = app_role.value.description
display_name = app_role.value.display_name
enabled = true
id = app_role.value.id
value = app_role.key
}
}
web {
logout_url = format("https://app-%s-%s", var.project.name, var.project.environment.name)
redirect_uris = []
implicit_grant {
access_token_issuance_enabled = true
id_token_issuance_enabled = true
}
}
required_resource_access {
resource_app_id = data.azuread_application_published_app_ids.well_known.result.MicrosoftGraph
resource_access {
id = data.azuread_service_principal.msgraph.app_role_ids["User.Read.All"]
type = "Role"
}
}
}
I get this error related to id :
Error: Unsupported attribute
│
│ on resources.appreg.tf line 27, in resource "azuread_application" "app_prodstats":
│ 27: id = app_role.value.id
│ ├────────────────
│ │ app_role.value is object with 3 attributes
│
│ This object does not have an attribute named "id".
╵
╷
│ Error: Unsupported attribute
│
│ on resources.appreg.tf line 27, in resource "azuread_application" "app_prodstats":
│ 27: id = app_role.value.id
│ ├────────────────
│ │ app_role.value is object with 3 attributes
│
│ This object does not have an attribute named "id".
╵
╷
│ Error: Unsupported attribute
│
│ on resources.appreg.tf line 27, in resource "azuread_application" "app_prodstats":
│ 27: id = app_role.value.id
│ ├────────────────
│ │ app_role.value is object with 3 attributes
│
│ This object does not have an attribute named "id".
╵
Even if i give id = app_role.value.app_role_ids, i get the error that app_role_ids is not the correct attribute.
Any idea what i shall put in id in the app_role ?
If i put id = random_uuid.prod.result i get the error that it is duplicate ID
│ Error: checking for duplicate app roles / OAuth2.0 permission scopes: validation failed: duplicate ID found: "635bfe4c-29a5-4497-925b-2a9af3bf84a3" │ │ with azuread_application.app_prodstats, │ on resources.appreg.tf line 5, in resource "azuread_application" "app_prodstats": │ 5: resource "azuread_application" "app_prodstats" {

From the TF docs, the random_uuid ID can be random_uuid:
resource "random_uuid" "id" {
for_each = local.app_roles
}
Then
dynamic "app_role" {
for_each = local.app_roles
content {
allowed_member_types = app_role.value.allowed_member_types
description = app_role.value.description
display_name = app_role.value.display_name
enabled = true
id = random_uuid.id[each.key].result
value = app_role.key
}
}

Related

how to use dynamic block in terraform?

main.tf
resource "azurerm_cdn_endpoint" "default" {
for_each = {
for cdn_endpoint in var.cdn_endpoints : cdn_endpoint.endpoint_name => cdn_endpoint
}
name = each.value.endpoint_name
location = coalesce(var.location, data.azurerm_resource_group.current.location)
resource_group_name = data.azurerm_resource_group.current.name
profile_name = azurerm_cdn_profile.default.name
tags = var.resource_tags
origin {
name = random_id.id[each.key].hex
host_name = each.value.origin_host_name
}
dynamic "delivery_rule" {
for_each = {
for deliveryrule in var.delivery_rules : deliveryrule.order => deliveryrule
}
content {
name = delivery_rule.value.name
order = delivery_rule.value.order
request_scheme_condition {
operator = delivery_rule.value.operator
match_values = delivery_rule.value.match_values
}
url_redirect_action {
redirect_type = delivery_rule.value.redirect_type #"Found"
protocol = delivery_rule.value.protocol #"Https"
}
}
}
}
variable.tf
variable "delivery_rules" {
default = {
name = "test"
order = 1
request_scheme_condition = {
match_values = ["HTTP"]
operator = "Equal"
}
}
type = object(
{
name = string
order = number
request_scheme_condition = object({
match_values = list(string)
operator = string
})
})
}
I'm trying to create rule engine for the azure cdn.
getting below error
Error: Unsupported attribute
│
│ on ../../main.tf line 86, in resource "azurerm_cdn_endpoint" "default":
│ 86: protocol = delivery_rule.value.protocol #"Https"
│ ├────────────────
│ │ delivery_rule.value is "test"
│
│ This value does not have any attributes.
╵
╷

Terraform throwing error while trying to create Azure service bus subscription filters

I would like to create three Azure service bus subscriptions and then two of the subscriptions need to have filters on them. My code is given below
resource "azurerm_servicebus_topic" "default" {
resource_group_name = azurerm_servicebus_namespace.default.resource_group_name
namespace_name = azurerm_servicebus_namespace.default.name
name = module.names-default.environment.servicebus_topic.name_unique
enable_partitioning = false
}
resource "azurerm_servicebus_subscription" "new-subscr" {
for_each = local.svc_bus_subscr
resource_group_name = azurerm_servicebus_topic.default.resource_group_name
namespace_name = azurerm_servicebus_topic.default.namespace_name
default_message_ttl = "P35D"
topic_name = azurerm_servicebus_topic.default.name
max_delivery_count = 5
name = each.value["name"]
requires_session = each.value["requires_session"]
}
locals {
svc_bus_subscr = {
sub-1 = {
name = format("sbs-%s-%s-%s", var.resource_group_name, (var.resource_group_environment != "main") ? var.resource_group_environment : "dev", "b214")
requires_session = false
}
sub-2 = {
name = format("sbs-%s-%s-%s", var.resource_group_name, (var.resource_group_environment != "main") ? var.resource_group_environment : "dev", "ef14")
requires_session = true
}
sub-3 = {
name = format("sbs-%s-%s-%s", var.resource_group_name, (var.resource_group_environment != "main") ? var.resource_group_environment : "dev", "ck89")
requires_session = true
}
}
}
These are the filters for two of the subscriptions
locals {
svc_bus_subscr_filter = {
filter-b214 = {
name = ""
id = ""
label = ""
}
filter-ef14 = {
name = "MinestarQbEvents"
id = "minestarqb"
label = "red"
}
filter-ck89 = {
name = "WencoHvcEvents"
id = "wencohvc"
label = "red"
}
}
}
resource "azurerm_servicebus_subscription_rule" "filter" {
for_each = { for n in local.svc_bus_subscr : n.name => n }
subscription_name = lookup(local.svc_bus_subscr[each.value.name], "name", null)
name = local.svc_bus_subscr_filter.value.filter_name
resource_group_name = azurerm_servicebus_namespace.default.resource_group_name
topic_name = azurerm_servicebus_topic.default.name
namespace_name = azurerm_servicebus_namespace.default.name
filter_type = "CorrelationFilter"
correlation_filter {
correlation_id = local.svc_bus_subscr_filter.value.id
label = local.svc_bus_subscr_filter.value.label
properties = {
customProperty = "value"
}
}
}
The errors that i get are :
Error: Unsupported attribute
│
│ on resources.sb.tf line 149, in resource "azurerm_servicebus_subscription_rule" "filter":
│ 149: name = local.svc_bus_subscr_filter.value.filter_name
│ ├────────────────
│ │ local.svc_bus_subscr_filter is object with 3 attributes
│
│ This object does not have an attribute named "value".
╵
╷
│ Error: Unsupported attribute
│
│ on resources.sb.tf line 156, in resource "azurerm_servicebus_subscription_rule" "filter":
│ 156: correlation_id = local.svc_bus_subscr_filter.value.id
│ ├────────────────
│ │ local.svc_bus_subscr_filter is object with 3 attributes
│
│ This object does not have an attribute named "value".
╵
╷
│ Error: Unsupported attribute
│
│ on resources.sb.tf line 157, in resource "azurerm_servicebus_subscription_rule" "filter":
│ 157: label = local.svc_bus_subscr_filter.value.label
│ ├────────────────
│ │ local.svc_bus_subscr_filter is object with 3 attributes
│
│ This object does not have an attribute named "value".

Getting error while using Terraform for_each for App Registration

I am trying to do app registration and have few app roles that i would like to assign.
My code is given below
resource "random_uuid" "prod" {}
resource "azuread_application" "app_prod" {
display_name = format("app-%s-%s", var.project.name, var.project.environment.name)
owners = [data.azuread_client_config.default.object_id]
identifier_uris = [format("https://contoso.onmicrosoft.com/%s-%s", var.project.name, var.project.environment.name)]
api {
oauth2_permission_scope {
for_each = toset(local.oauth2_permissions)
admin_consent_description = each.value.admin_consent_description
admin_consent_display_name = each.value.admin_consent_display_name
enabled = true
id = random_uuid.prod.result
type = each.value.type
value = each.key
}
}
app_role {
for_each = toset(local.app_roles)
allowed_member_types = each.value.allowed_member_types
description = each.value.description
display_name = each.value.display_name
enabled = true
id = random_uuid.prod.result
value = each.key
}
web {
logout_url = format("https://app-%s-%s", var.project.name, var.project.environment.name)
redirect_uris = []
implicit_grant {
access_token_issuance_enabled = true
id_token_issuance_enabled = true
}
}
required_resource_access {
resource_app_id = data.azuread_application_published_app_ids.well_known.result.MicrosoftGraph
resource_access {
id = data.azuread_service_principal.msgraph.app_role_ids["User.Read.All"]
type = "Role"
}
}
}
locals {
app_roles = {
application-administrator = {
display_name = "Application administrator"
description = "Application administrators have the ability to administer the application."
allowed_member_types = ["User", "Application"]
}
BusinessAdmin = {
display_name = "BusinessAdmin"
description = "Business Administrator"
allowed_member_types = ["User"]
}
mulesoft-integration = {
display_name = "Mulesoft Integration"
description = "Allows MuleSoft Integration to talk to the APIs."
allowed_member_types = ["Application"]
}
}
oauth2_permissions = {
read-and-write = {
user_consent_description = "read-and-write"
admin_consent_display_name = "Read and write data"
admin_consent_description = "Allows the app to read and write data"
user_consent_display_name = "Allows the app to read and write data"
type = "User"
}
}
}
data "azuread_application_published_app_ids" "well_known" {}
data "azuread_service_principal" "msgraph" {
application_id = data.azuread_application_published_app_ids.well_known.result.MicrosoftGraph
}
The error that i get while doing terraform apply is :
Error: each.value cannot be used in this context
│
│ on resources.appreg.tf line 24, in resource "azuread_application" "app_prodstats":
│ 24: description = each.value.description
│
│ A reference to "each.value" has been used in a context in which it
│ unavailable, such as when the configuration no longer contains the value in
│ its "for_each" expression. Remove this reference to each.value in your
│ configuration to work around this error.
╵
╷
│ Error: each.value cannot be used in this context
│
│ on resources.appreg.tf line 25, in resource "azuread_application" "app_prodstats":
│ 25: display_name = each.value.display_name
│
│ A reference to "each.value" has been used in a context in which it
│ unavailable, such as when the configuration no longer contains the value in
│ its "for_each" expression. Remove this reference to each.value in your
│ configuration to work around this error.
╵
╷
│ Error: Reference to "each" in context without for_each
│
│ on resources.appreg.tf line 28, in resource "azuread_application" "app_prodstats":
│ 28: value = each.key
│
│ The "each" object can be used only in "module" or "resource" blocks, and
│ only when the "for_each" argument is set.
╵
You need content block if you are using dynamic blocks:
dynamic "app_role" {
for_each = toset(local.app_roles)
content {
allowed_member_types = app_role.value.allowed_member_types
description = app_role.value.description
display_name = app_role.value.display_name
enabled = true
id = random_uuid.prod.result
value = app_role.key
}
}
You have to make similar changes as above to other parts of your code where you get that error.

How to set the route_table_id

main.tf
private_nat_cidrs = {
test-prod-ec2-1 = {
subnet = "10.1.0.0/23"
name = "test-prod-ec2-1"
az = "ap-northeast-1a"
}
test-prod-ec2-2 = {
subnet = "10.1.2.0/23"
name = "test-prod-ec2-2"
az = "ap-northeast-1c"
}
test-prod-ec2-3 = {
subnet = "10.1.4.0/23"
name = "test-prod-ec2-3"
az = "ap-northeast-1d"
}
}
subnet.tf
/**
* private subnet(NAT)
*/
resource "aws_subnet" "nat" {
for_each = var.private_nat_cidrs
vpc_id = aws_vpc.test.id
availability_zone = lookup(each.value, "az")
cidr_block = lookup(each.value, "subnet")
map_public_ip_on_launch = true
tags = merge(
local.tags,
{
Name = format("%s_%s", var.env_prefix, lookup(each.value, "name"))
}
)
lifecycle {
prevent_destroy = false
}
}
nat.tf
resource "aws_nat_gateway" "private" {
for_each = var.public_subnet_cidrs
allocation_id = aws_eip.nat_gateway.id
subnet_id = aws_subnet.public[each.key].id
tags = merge(
local.tags,
{
Name = format("%s_%s_%s", var.env_prefix, var.env_name, "nat-gateway")
}
)
lifecycle {
prevent_destroy = false
}
}
route_table.tf
resource "aws_route_table" "private" {
for_each = aws_nat_gateway.private
vpc_id = aws_vpc.dandori.id
tags = merge(
local.tags,
{
Name = format("%s_%s", var.env_prefix, var.env_name)
}
)
route {
cidr_block = "0.0.0.0/0"
nat_gateway_id = each.value["id"]
}
lifecycle {
prevent_destroy = false
}
}
resource "aws_route_table_association" "private" {
for_each = aws_subnet.nat
subnet_id = each.value["id"]
route_table_id = aws_route_table.private[each.key].id
lifecycle {
prevent_destroy = false
}
}
【Error】
╷
│ Error: Invalid index
│
│ on ../modules/aws/vpc/route_table.tf line 69, in resource "aws_route_table_association" "private":
│ 69: route_table_id = aws_route_table.private[each.key].id
│ ├────────────────
│ │ aws_route_table.private is object with 1 attribute "test-prod-nat"
│ │ each.key is "test-prod-ec2-1"
│
│ The given key does not identify an element in this collection value.
╵
╷
│ Error: Invalid index
│
│ on ../modules/aws/vpc/route_table.tf line 69, in resource "aws_route_table_association" "private":
│ 69: route_table_id = aws_route_table.private[each.key].id
│ ├────────────────
│ │ aws_route_table.private is object with 1 attribute "test-prod-nat"
│ │ each.key is "test-prod-ec2-2"
│
│ The given key does not identify an element in this collection value.
╵
╷
│ Error: Invalid index
│
│ on ../modules/aws/vpc/route_table.tf line 69, in resource "aws_route_table_association" "private":
│ 69: route_table_id = aws_route_table.private[each.key].id
│ ├────────────────
│ │ aws_route_table.private is object with 1 attribute "test-prod-nat"
│ │ each.key is "test-prod-ec2-3"
│
│ The given key does not identify an element in this collection value.
I want to set the route_table_id to aws_route_table.private.id, but I don't know how to set it.
I've set the aws_route_table.private.id, but I can't set the aws_route_table.private.id directly because I'm looping through for_each.
I've tried everything, but I can't solve it.
Please give me some advice.

Terraform error while fetching value of subnet in oci

I have this code where I am trying to fetch the id of subnet via subnet name:
The code looks like this :
resource "oci_containerengine_node_pool" "node_pool" {
for_each = var.nodepools
cluster_id = oci_containerengine_cluster.cluster[0].id
compartment_id = var.compartment_id
depends_on = [oci_containerengine_cluster.cluster]
kubernetes_version = var.cluster_kubernetes_version
name = each.value["name"]
node_config_details {
placement_configs {
availability_domain = var.availability_domain
subnet_id = oci_core_subnet.snet-workers[each.value.subnet_name].id
}
size = each.value["size"]
}
node_shape = each.value["node_shape"]
node_shape_config {
#Optional
memory_in_gbs = each.value["memory"]
ocpus = each.value["ocpus"]
}
node_source_details {
image_id = each.value["image_id"]
source_type = "IMAGE"
}
ssh_public_key = file(var.ssh_public_key_path)
}
My subnet code looks like:
resource "oci_core_subnet" "snet-workers" {
cidr_block = lookup(var.subnets["snet-workers"], "subnet_cidr")
compartment_id = var.compartment_id
vcn_id = oci_core_virtual_network.base_vcn.id
display_name = lookup(var.subnets["snet-workers"], "display_name")
dns_label = lookup(var.subnets["snet-workers"], "dns_label")
prohibit_public_ip_on_vnic = true
security_list_ids = [oci_core_security_list.private_worker_nodes.id]
route_table_id = oci_core_route_table.rt-nat.id
}
variables looks like:
variable "subnets" {
description = "List of subnets to create for an environment"
type = map(object({
subnet_cidr = string
display_name = string
dns_label = string
}))
}
my tfvars looks like
nodepools = {
np1 = {
name = "np1"
size = 3
ocpus = 8
memory = 120
image_id = "test"
node_shape = "VM.Standard2.8"
subnet_name = "snet-worker1"
}
np2 = {
name = "np2"
size = 2
ocpus = 8
memory = 120
image_id = "test"
node_shape = "VM.Standard2.8"
subnet_name = "snet-worker2"
}
}
But in terraform plan I am getting error as
Error: Invalid index
│
│ on ../modules/oke/oke.tf line 39, in resource "oci_containerengine_node_pool" "node_pool":
│ 39: subnet_id = oci_core_subnet.snet-workers[each.value.subnet_name].id
│ ├────────────────
│ │ each.value.subnet_name is "snet-worker2"
│ │ oci_core_subnet.snet-workers is object with 22 attributes
│
│ The given key does not identify an element in this collection value.
╵
╷
│ Error: Invalid index
│
│ on ../modules/oke/oke.tf line 39, in resource "oci_containerengine_node_pool" "node_pool":
│ 39: subnet_id = oci_core_subnet.snet-workers[each.value.subnet_name].id
│ ├────────────────
│ │ each.value.subnet_name is "snet-worker1"
│ │ oci_core_subnet.snet-workers is object with 22 attributes
│
│ The given key does not identify an element in this collection value.
Can someone help
The following:
subnet_id = oci_core_subnet.snet-workers[each.value.subnet_name].id
would only work if you had used for_each while creating oci_core_subnet.snet-workers. Since you are not using for_each, it should be:
subnet_id = oci_core_subnet.snet-workers.id
UPDATE
To keep using original version:
resource "oci_core_subnet" "snet-workers" {
for_each = var.subnets
cidr_block = each.value["subnet_cidr"]
compartment_id = var.compartment_id
vcn_id = oci_core_virtual_network.base_vcn.id
display_name = leach.value[""display_name"]
dns_label = each.value["dns_label"]
prohibit_public_ip_on_vnic = true
security_list_ids = [oci_core_security_list.private_worker_nodes.id]
route_table_id = oci_core_route_table.rt-nat.id
}
You have to define a "oci_core_subnet" for each entry in "subnets" variable. Something like this:
resource "oci_core_subnet" "snet-workers" {
for_each = var.subnets
cidr_block = each.value.subnet_cidr
...
}

Resources