From version 2.0 the AzureAD provider exclusively uses Microsoft Graph to connect to Azure Active Directory and has ceased to support using the Azure Active Directory Graph API.
Due to differences between the two APIs, some schema deprecations have already been introduced prior to v2.0 and several fields have been renamed, removed or otherwise changed in v2.0. Please consult the following guide to determine any configuration changes you will need to make in order to upgrade to version 2.0.
We take semantic versioning very seriously which is why these changes have been introduced in a new major version of the provider. You can read up the background behind the API migration and proposed development path in this GitHub issue, and follow along with the work being done for v2.0 in the GitHub milestone
In version 1.5.0 or later of the AzureAD provider, limited beta support for Microsoft Graph can be enabled. See Beta support for Microsoft Graph for more details.
We recommend pinning the version of each provider you use in Terraform. You can do this using the version
attribute in the required_providers
block of your terraform
configuration block.
To pin to a specific version of the AzureAD provider:
terraform {
required_providers {
azuread = {
source = "hashicorp/azuread"
version = "= 1.5.1"
}
}
}
To pin to any 1.5 release:
terraform {
required_providers {
azuread = {
source = "hashicorp/azuread"
version = "~> 1.5.0"
}
}
}
Older versions of Terraform (0.12.x) can pin the provider version using the version
attribute within the provider
block:
provider "azuread" {
version = "~> 1.5.0"
}
This will enable you to upgrade to version 2.0 at your convenience, by simply advancing the desired target version in your configuration. See the Lock and Upgrade Provider Versions guide on HashiCorp Learn for more details.
Existing authentication methods will continue to work unchanged, whether you authenticate with a service principal (client certificate or client secret), managed identity, or using Azure CLI.
However, you may need to assign new API permissions depending on your configuration and authentication scenario.
The default Azure public cloud, which was previously specified as public
, has been renamed to global
. Existing environment names will continue to work in version 2.0.
For users connecting to national clouds (e.g. germany, china and usgovernment), these are all supported using the existing provider configuration property environment
, or the environment variable ARM_ENVIRONMENT
. The usgovernment
environment has been split into two environments usgovernmentl4
and usgovernmentl5
- see this post for more information. Specifying the usgovernment
environment will use the usgovernmentl4
cloud.
If you are using Client Certificate authentication, it's now possible to specify the certificate bundle data as an inline variable, in addition to the pre-existing method of specifying the filesystem path for a .pfx
file. This may be useful when running Terraform in a non-interactive context, such as CI/CD pipelines.
For more information, consult the Client Certificate Authentication Guide.
Microsoft Graph is a different web service to Azure Active Directory Graph, and as such if you are authenticating using a service principal, you may need to assign new permissions to your authenticated principal.
If you are using directory roles to assign effective permissions to your authenticated principal, you may not necessarily need to assign new API permissions.
Whilst assigning directory roles is the recommended approach for user principals, if you are authenticating using a service principal, we recommend assigning permissions using app roles as detailed below. Note that this differs from our advice for earlier (v0.x and v1.x) releases, where we recommend the use of directory roles for service principals due to bugs previously encountered with Azure Active Directory Graph that do not occur with Microsoft Graph.
To assign permissions to your Application for use with Service Principal authentication, navigate to the Azure Active Directory overview within the Azure Portal and select the App Registrations blade. Locate your registered application and click on its display name to manage it.
Go to the API Permissions pane for the Application and click the "Add a permission" button. In the pane that opens, select Microsoft Graph.
Choose "Application Permissions" for the permission type, and check the permissions you would like to assign. The permissions you need will depend on which directory objects you wish to manage with Terraform. The following table show the required permissions for some common resources:
Resource(s) | Role Name(s) |
---|---|
data.azuread_application data.azuread_service_principal |
Application.Read.All |
data.azuread_domains |
Domain.Read.All |
data.azuread_group data.azuread_groups |
Group.Read.All |
data.azuread_user data.azuread_users |
User.Read.All |
azuread_application azuread_application_certificate azuread_application_password azuread_service_principal azuread_service_principal_certificate azuread_service_principal_password |
Application.ReadWrite.All |
azuread_group azuread_group_member |
Group.ReadWrite.All |
azuread_user |
User.ReadWrite.All |
Depending on the configuration of your AAD tenant, you may also need to grant the Directory.Read.All and/or Directory.ReadWrite.All roles.
After assigning permissions, you will need to grant consent for the service principal to utilise them. The easiest way to do this is by clicking the Grant Admin Consent button in the same API Permissions pane, which will create the necessary app role assignments for the Service Principal.
Due to differences between the Azure Active Directory Graph API and the Microsoft Graph API, you may encounter some constraints after upgrading. These are due to implementation changes within Azure, and are outside the control of the provider, but where known these are detailed here for your convenience.
Microsoft 365 groups are required to have at least one owner that is a user principal, i.e. not a service principal. When creating or managing Microsoft 365 groups, you should explicitly assign at least one user to be an owner of the group in your Terraform configuration. Note that whilst this requirement officially pertains to Microsoft 365 groups, you may encounter this constraint with newly created "traditional" security groups, such as the type supported by the AzureAD provider prior to version 2.0.
When executing Terraform with a user principal, we recommend assigning the directory role Groups Administrator
or a role with the same effective permissions, when managing groups using the AzureAD provider.
azuread_group
The mail_enabled
and security_enabled
fields are no longer read-only, and at least one of these fields must be set to true
in order to create a new group.
The following attributes/properties were deprecated in the AzureAD provider, and have now been removed in version 2.0.
The deprecated field metadata_host
is no longer used and has been removed.
azuread_application
The deprecated field name
has been replaced by the display_name
field and has been removed.
The deprecated field is_enabled
in the app_roles
block has been replaced by the enabled
field and has been removed.
The deprecated field available_to_other_tenants
has been replaced by the sign_in_audience
field and has been removed.
The deprecated field homepage
has been replaced by the homepage_url
field in the web
block and has been removed.
The deprecated field logout_url
has been replaced by the logout_url
field in the web
block and has been removed.
The deprecated field oauth2_allow_implicit_flow
has been replaced by the access_token_issuance_enabled
field in the implicit_grant
block and has been removed.
The deprecated oauth2_permissions
block has been replaced by the oauth2_permission_scopes
block within the api
block and has been removed.
The deprecated field reply_urls
has been replaced by the redirect_uris
field in the web
block and has been removed.
The legacy type
field is deprecated and has been removed.
azuread_group
The deprecated field name
has been replaced by the display_name
field and has been removed.
azuread_groups
The deprecated field names
has been replaced by the display_names
field and has been removed.
azuread_user
The deprecated field immutable_id
has been replaced by the onpremises_immutable_id
field and has been removed.
The deprecated field physical_delivery_office_name
has been replaced by the office_location
field and has been removed.
The deprecated field mobile
has been replaced by the mobile_phone
field and has been removed.
azuread_users
The deprecated field immutable_id
in the users
block has been replaced by the onpremises_immutable_id
field and has been removed.
azuread_application
The deprecated field name
has been replaced by the display_name
field and has been removed.
The deprecated field is_enabled
in the app_role
block has been replaced by the enabled
field and has been removed.
The deprecated field available_to_other_tenants
has been replaced by the sign_in_audience
field and has been removed.
The deprecated field homepage
has been replaced by the homepage_url
field in the web
block and has been removed.
The deprecated field logout_url
has been replaced by the logout_url
field in the web
block and has been removed.
The deprecated field oauth2_allow_implicit_flow
has been replaced by the access_token_issuance_enabled
field in the implicit_grant
block and has been removed.
The deprecated field is_enabled
in the app_role
block has been replaced by the enabled
field and has been removed.
The deprecated oauth2_permissions
block has been replaced by the oauth2_permission_scope
block within the api
block and has been removed.
The deprecated field public_client
has been replaced by the fallback_public_client_enabled
field. The new public_client
block now contains settings for public client applications.
The deprecated field reply_urls
has been replaced by the redirect_uris
field in the web
block and has been removed.
The legacy type
field is deprecated and has been removed.
azuread_application_app_role
This resource has been removed in version 2.0 of the provider. Limitations of the azuread_application
resource, that previously necessitated use of this resource, have been resolved in version 2.0. See this pull request for more information about this change.
azuread_application_oauth2_permission
and azuread_application_oauth2_permission_scope
In version 1.5.0 of the provider, the azuread_application_oauth2_permission
resource was deprecated and replaced by the azuread_application_oauth2_permission_scope
resource.
However, in version 2.0 of the provider, both of these resources have been removed. Limitations of the azuread_application
resource, that previously necessitated use of these resources, have been resolved in version 2.0. See this pull request for more information about this change.
azuread_application_password
The deprecated field description
has been replaced by the display_name
field and has been removed.
The azuread_application_password
resource no longer supports importing.
The key_id
field has become read-only as Azure Active Directory no longer allows user-specified key IDs for passwords.
The value
field has become read-only as Azure Active Directory no longer accepts user-supplied password values. Passwords are instead auto-generated by Azure and exported with the value
attribute by the resource.
azuread_group
The deprecated field name
has been replaced by the display_name
field and has been removed.
azuread_service_principal_password
The deprecated field description
has been replaced by the display_name
field and has been removed.
The azuread_service_principal_password
resource no longer supports importing.
The key_id
field has become read-only as Azure Active Directory no longer allows user-specified key IDs for passwords.
The value
field has become read-only as Azure Active Directory no longer accepts user-supplied password values. Passwords are instead auto-generated by Azure and exported with the value
attribute by the resource.
The display_name
, start_date
and end_date
fields are no longer respected by the API and have been made read-only. Accordingly the end_date_relative
field has been removed.
azuread_user
The deprecated field immutable_id
has been replaced by the onpremises_immutable_id
field and has been removed.
The deprecated field physical_delivery_office_name
has been replaced by the office_location
field and has been removed.
The deprecated field mobile
has been replaced by the mobile_phone
field and has been removed.
Several fields that were previously optional or read-only are now required in version 2.0. Currently, these fields are optionally (or always) autogenerated by the provider, as not all users need to be able to set these fields to specific values.
In v2.0, you can achieve the same behaviour by using the Random provider, for example:
resource "random_uuid" "example_role_id" {}
resource "azuread_application" "example" {
display_name = "example"
app_role {
id = random_uuid.example_role_id.result
# additional properties...
}
}
Requiring these properties will enable more predictable and less disruptive management of app roles and OAuth 2.0 permission scopes such that existing roles/scopes will not be disabled or overwritten to accommodate changes in an application's configuration.
azuread_application
The id
field in the app_role
block was previously currently Computed (read-only) but is now Required.
The id
field in the deprecated oauth2_permissions
block was previously Computed (read-only) but its replacement field id
in the oauth2_permission_scope
block is Required.
In previous version of the provider, many fields were introduced as Optional + Computed fields. This meant that omitting such fields would cause Terraform to ignore them and not attempt to manage them. However, this approach has many side effects including the inability to unset or clear these fields, and sometimes being forced to accept an undesired default value.
To resolve these issues, many of these fields are no longer Computed in version 2.0 of the provider. This means that Terraform will manage these fields and if you do not specify their values in your configuration, they will be unset or set to their default or zero values. In some cases it's appropriate for a field to be Computed, particularly where it helps prevent disruption to services or users.
Additionally, some fields have been updated in ways that may break existing configurations, for example changing their type.
Accordingly, in version 2.0 of the provider the following fields have changed.
azuread_application
The display_name
property is now matched case-insensitively which mirrors the behaviour of Azure Active Directory.
The group_membership_claims
property was previously a single string value but has been changed to a list of strings. In some cases this may cause the following error to appear when running terraform plan
or terraform refresh
after upgrading:
Error: .group_membership_claims: missing expected [
If you encounter this error, you will need to perform one of the following workarounds:
terraform state rm data.azuread_application.example
to remove the data source(s) from your state file.terraform refresh
, and lastly uncomment the data source(s)."group_membership_claims": ""
to "group_membership_claims": []
(not recommended unless you are confident and the other two options are infeasible).azuread_application
The app_role
block is no longer Computed, omitting this block will cause Terraform to remove any app roles published by an application.
The value
field in the app_role
block is no longer Computed, omitting this field will cause Terraform to clear this field for an app role.
The fallback_public_client_enabled
field is no longer Computed, omitting this field will cause Terraform to default this value to false
.
The group_membership_claims
property was previously a single string value but has been changed to a list of strings. If this property is present in your configuration, you will need to update it. For example:
From:
group_membership_claims = "All"
To:
group_membership_claims = ["All"]
Note the square brackets to denote a list for the value. This change means that you can now specify multiple claims for this property.
The identifier_uris
field was previously a List type field and is now a Set type field. This is due to API ordering and means you can no longer reference this field and index it sequentially without first converting it to a list. Additional, this field is no longer Computed, so omitting this field will cause Terraform to remove any identifier URIs configured for an application.
The oauth2_permission_scope
block is no longer Computed, omitting this block will cause Terraform to remove any OAuth2 permission scopes published by an application.
The owners
field is no longer Computed, omitting this field will cause Terraform to remove any owners for an application. It's recommended to specify the object ID of the authenticated principal running Terraform, to ensure sufficient permissions that the application can be subsequently updated.
The sign_in_audience
field is no longer Computed, omitting this field will cause Terraform to default this value to AzureADMyOrg
.
The web
block is no longer Computed, omitting this field will cause Terraform to remove all field values contained in this block, including the homepage_url
, logout_url
, redirect_uris
and access_token_issuance_enabled
fields.
azuread_user
The password
field is now Optional + Computed, which makes it possible to import existing users without forcibly resetting their password.
The city
field is no longer Computed, omitting this field will cause Terraform to remove this value for a user.
The company_name
field is no longer Computed, omitting this field will cause Terraform to remove this value for a user.
The country
field is no longer Computed, omitting this field will cause Terraform to remove this value for a user.
The department
field is no longer Computed, omitting this field will cause Terraform to remove this value for a user.
The given_name
field is no longer Computed, omitting this field will cause Terraform to remove this value for a user.
The job_title
field is no longer Computed, omitting this field will cause Terraform to remove this value for a user.
The mobile_phone
field is no longer Computed, omitting this field will cause Terraform to remove this value for a user.
The office_location
field is no longer Computed, omitting this field will cause Terraform to remove this value for a user.
The postal_code
field is no longer Computed, omitting this field will cause Terraform to remove this value for a user.
The state
field is no longer Computed, omitting this field will cause Terraform to remove this value for a user.
The street_address
field is no longer Computed, omitting this field will cause Terraform to remove this value for a user.
The surname
field is no longer Computed, omitting this field will cause Terraform to remove this value for a user.
The usage_location
field is no longer Computed, omitting this field will cause Terraform to remove this value for a user.
In order to determine the assigned value of a given UUID-type property where you had previously not defined one, you can use the terraform state show
command to inspect your existing application(s), and then add the current value to your configuration.
$ terraform state show azuread_application.example
# azuread_application.example:
resource "azuread_application" "example" {
app_role = [
{
allowed_member_types = [
"User",
]
description = "Just an example"
display_name = "Example Role"
id = "3dbd749f-c2ba-4796-0d33-273878f8a31b"
is_enabled = true
value = ""
},
]
application_id = "cd986e6e-5a90-42f0-8c01-82f0da5b286c"
display_name = "example-app"
id = "61a9d04a-6694-497a-afe8-6303aa3435df"
oauth2_permissions = [
{
admin_consent_description = "Allow the application to access example-app on behalf of the signed-in user."
admin_consent_display_name = "Access example-app"
id = "c32d857d-02d9-4887-af7a-cb1f1fd61b9a"
is_enabled = true
type = "User"
user_consent_description = "Allow the application to access example-app on your behalf."
user_consent_display_name = "Access example-app"
value = "user_impersonation"
},
]
object_id = "61a9d04a-6694-497a-afe8-6303aa3435df"
}
user_impersonation
scope for applicationsWith AzureAD v1.x using Azure Active Directory Graph (or using the beta support for Microsoft Graph), newly created applications are assigned a default user_impersonation
scope which enables users to sign in to your application.
With AzureAD v2.0 and later using Microsoft Graph, this default scope is not automatically granted to your application, and you will need to specify it in your configuration. The following example can be used to replicate the earlier behaviour.
resource "random_uuid" "example_app_user_impersonation_scope" {}
resource "azuread_application" "example" {
display_name = "example-app"
api {
oauth2_permission_scope {
admin_consent_description = "Allow the application to access example-app on behalf of the signed-in user."
admin_consent_display_name = "Access example-app"
id = random_uuid.example_app_user_impersonation_scope.result
enabled = true
type = "User"
user_consent_description = "Allow the application to access example-app on your behalf."
user_consent_display_name = "Access example-app"
value = "user_impersonation"
}
}
}
In version 1.5.0 or later of the AzureAD provider, beta support for Microsoft Graph can be enabled in the provider block.
With this feature enabled, most requests will be sent to Microsoft Graph, however for compatibility some requests may still be sent to Azure Active Directory Graph. You should therefore ensure your authenticated principal is assigned the required permissions for both APIs.
To enable this support, set the following in your provider block:
provider "azuread" {
use_microsoft_graph = true
}
Alternatively, you can enable the beta by setting the following environment variable to any non-empty value:
# sh
export AAD_USE_MICROSOFT_GRAPH=1
# PowerShell
$env:AAD_USE_MICROSOFT_GRAPH = 1
We appreciate any feedback you might have whilst using beta support for Microsoft Graph. Bug reports and feature requests can be logged on our GitHub issue tracker, and you can also check out the project README for information on how to get in touch with the maintainers. If you encounter an issue that has already been reported, please upvote it and comment to add any additional context you might have.