I'm trying to pass null value for adding users with the below try block, but it fails
│ Error: Missing required argument │
│ with module.entragroups.azuread_privileged_access_group_eligibility_schedule.eligible-pim-assignment["group_01"],
│ on .terraform/modules/entragroups/entra/groups/main.tf line 53, in resource "azuread_privileged_access_group_eligibility_schedule" "eligible-pim-assignment":
│ 53: principal_id = try(data.azuread_users.eligible-pim-users[each.key].object_ids[0], null)
│
│ The argument "principal_id" is required, but no definition was fou
The source code:
resource "azuread_privileged_access_group_eligibility_schedule" "eligible-pim-assignment" {
for_each = var.entra_groups
group_id = azuread_group.group[each.key].object_id
principal_id = try(data.azuread_users.eligible-pim-users[each.key].object_ids[0], null)
assignment_type = each.value.assignment_type
# duration = each.value.duration
justification = each.value.justification
start_date = each.value.start_date
expiration_date = each.value.expiration_date
permanent_assignment = each.value.permanent_assignment_active
}
data "azuread_users" "eligible-pim-users" {
for_each = var.entra_groups
user_principal_names = each.value.eligible_pim_assignment_users
ignore_missing = true
}
variable "entra_groups" {
description = "entra groups"
type = map(object({
display_name = string
security_enabled = optional(bool)
assignable_to_role = optional(bool)
security_group_owners = optional(list(string), [])
active_pim_assignment_spn = optional(list(string), [])
assignment_type = optional(string)
duration = optional(string)
eligible_pim_assignment_users = optional(list(string), [])
active_pim_assignment_users = optional(list(string), [])
permanent_assignment_schedule = optional(bool)
permanent_assignment_active = optional(bool)
justification = optional(string)
start_date = optional(string)
expiration_date = optional(string)
}))
default = {}
}
group_01 = {
display_name = "test"
description = ""
security_enabled = true
assignable_to_role = true
active_pim_assignment_spn = []
assignment_type = "member"
duration = ""
eligible_pim_assignment_users = []
active_pim_assignment_users = []
permanent_assignment_schedule = false
start_date = "2025-03-07T01:02:03Z"
expiration_date = "2026-03-01T01:02:03Z"
permanent_assignment_active = true
justification = "as requested"
}
Null values are how Terraform represents that one of the arguments of a resource hasn't been set. Setting principal_id = null
is equivalent to not setting that argument at all.
If the provider considers a particular argument to be required, then it must not be set to null
. That is true regardless of whether you explicitly assign null
to it or if you just omit its definition so that Terraform sets it to null automatically.
If your goal is for instances of azuread_privileged_access_group_eligibility_schedule.eligible-pim-assignment
to be declared only when there is a matching instance of data.azuread_users.eligible-pim-users
then you could potentially represent that by adding an extra filtering condition to the for_each
argument for that resource:
resource "azuread_privileged_access_group_eligibility_schedule" "eligible-pim-assignment" {
for_each = {
for k, v in var.entra_groups : k => v
if length(data.azuread_users.eligible-pim-users[k].object_ids) != 0
}
# ...
principal_id = data.azuread_users.eligible-pim-users[each.key].object_ids[0]
# ...
}
This new for_each
definition uses a for
expression that includes an if
clause that therefore filters out any elements of var.entra_groups
which don't have any "eligible users".
Therefore the principal_id
argument no longer needs the try
function, because that argument will be evaluated only for each.key
values where object_ids
has at least one element, and therefore the [0]
operation should always succeed.
Bonus tip: If you have a list that might have either zero or one elements and you want to turn that into a single value that is either set or null
, a more concise way to represent that is using the one
function.
For example, instead of try(data.azuread_users.eligible-pim-users[each.key].object_ids[0], null)
you can write one(data.azuread_users.eligible-pim-users[each.key].object_ids)
. If there are no elements in object_ids
then this will return null
, but if there is exactly one element in object_ids
then this will return that one element.
This extra technique is appropriate only when you expect that there will be a maximum of one element in the given list. one
will fail with an error if the list has more than one element.