Given the following terraform script, how can I grant the app_registration
permission to the API it defines?
I’ve tried adding a required_resource_access
section but I cannot set resource_app_id
to the id of my app because it gives a circular reference error.
data "azuread_client_config" "current" {}
data "azuread_application_published_app_ids" "well_known" {}
resource "random_uuid" "app_scope_id" {}
resource "azuread_service_principal" "msgraph" {
application_id = data.azuread_application_published_app_ids.well_known.result.MicrosoftGraph
use_existing = true
}
resource "azuread_application" "app_registration" {
display_name = "My app name"
identifier_uris = ["api://${var.environment}productname"]
owners = [data.azuread_client_config.current.object_id]
sign_in_audience = "AzureADMultipleOrgs"
api {
mapped_claims_enabled = true
# requested_access_token_version = 2
oauth2_permission_scope {
admin_consent_description = "Allow the application to access a user's name and email address."
admin_consent_display_name = "Access user name and email address"
enabled = true
id = random_uuid.app_scope_id.result
type = "User"
user_consent_description = "Allow the application to access your name and email address."
user_consent_display_name = "Access your name and email address"
value = "access_as_user"
}
}
required_resource_access {
resource_app_id = data.azuread_application_published_app_ids.well_known.result.MicrosoftGraph // "00000003-0000-0000-c000-000000000000"
resource_access {
id = azuread_service_principal.msgraph.oauth2_permission_scope_ids["User.Read"] // "e1fe6dd8-ba31-4d61-89e7-88639da4683d"
type = "Scope"
}
resource_access {
id = azuread_service_principal.msgraph.oauth2_permission_scope_ids["email"] // "37f7f235-527c-4136-accd-4a02d197296e"
type = "Scope"
}
resource_access {
id = azuread_service_principal.msgraph.oauth2_permission_scope_ids["openid"] // "64a6cdd6-aab1-4aaf-94b8-3cc8405e90d0"
type = "Scope"
}
}
web {
homepage_url = "https://${var.environment}productname.azurewebsites.net"
logout_url = "https://${var.environment}productname.azurewebsites.net/logout"
redirect_uris = ["https://${var.environment}productname.azurewebsites.net//authentication/login-callback"]
implicit_grant {
access_token_issuance_enabled = true
id_token_issuance_enabled = true
}
}
}
The steps in Azure would be
- Go to portal.azure.com
- Switch to the directory where your app is
- Select "Azure Active Directory" from the burger menu at the top left of the page
- Click "App registrations"
- Click the application
- Click "API permissions"
- Click "Add a permission"
- Select "My APIs" tab
- Click your app in the list
- Tick the permission "access_as_user"
- Click "Add permissions"
I would also like to set identifier_uris
to the apps UUID, but that doesn’t seem possible either.
2
Answers
There is a work-around I can employ.
The first time the script is executed for a new environment, it must be run twice. Once to create everything, and a second time to add the permissions.
Terraform doesn't have a conditional block of code so we can't optionally include a block, but we can use a ternary statement to make a local variable an empty array or an array with a single element, and then use
for_each
First, add a variable
Next, define a data-source to retrieve the existing
application_id
, but only if the parameters say we should (i.e. it is the 2nd+ execution of the script).Finally, use a
dynamic
block with afor_each
that will iterate over 1 element (if the 2nd+ execution of the script) or over an empty array (i.e. not execute).First time you run your script
All subsequent runs
If anyone can give an answer that doesn't require at least two executions for a new environment, I will be happy to accept it.
As you used, adding the
required_resource_access
block to theazuread_application
resource grants the "app registration permission" to the API it defines. You can specify theresource_app_id
as theapplication id
of theazuread_service_principal
resource that represents the API in this block.So, I’ve given resource app id as:
I modified your script as below and it registered an app successfully with the required API permissions.
main.tf:
var.tf
:Executed
terraform init
:Validated the configuration using
terraform validate
:Executed
terraform plan
:Executed
terraform apply
:Deployment succeeded and got the expected output:
Note: Regarding
random_uuid
, it is not possible to set theidentifier_uris
to theapp's UUID
directly in Terraform. However, you can generate a UUID with therandom_uuid
resource and use it in theidentifier_uris
list.