Manage Microsoft Entra ID users and groups
Microsoft Entra ID (previously Azure active directory) is an enterprise identity service that manages your organization's user lifecycle. The Entra ID Terraform provider lets organization administrators manage users, groups, service principals, and applications as code. Terraform provides several benefits over using the Azure Portal to manage your organization's Active Directory:
Safety and consistency Defining your Active Directory infrastructure as code (IaC) reduces the risk of human error. With IaC, you can version control your configuration and ensure that the proper reviewers approve changes before merging them. IaC allows you to track and revert changes to your AD resources as your organization evolves.
Improved automation Terraform can create, update, and delete tracked resources without requiring you to keep track of each resource's dependencies. With Terraform, you can develop modules for your users, groups, applications, and service principals that comply with your organization's policies. For example, you can use Terraform to ensure that the security team has access to every new AD group.
In this tutorial, you will create new users in your Entra ID with data populated from a CSV file. Then, you will create new AD groups and dynamically assign users to their respective groups based on their roles. Finally, you will create additional new users by updating the CSV file. In the process, you will learn Terraform's configuration language, the Terraform Entra ID provider, and how to leverage both to simplify and automate your workflows.
Prerequisites
For this tutorial, you will need:
- the Terraform 1.0.4+ CLI installed locally.
- an Azure account with an Entra ID tenant.
- a configured Azure CLI.
You must have an Entra ID tenant to follow this tutorial. An Entra ID tenant represents an organization that allows you to use the Microsoft identity platform in your applications for identity and access management. Refer to this tenant setup quickstart page to verify you have an existing Entra ID tenant or to create a new one.
Authenticate Entra ID provider
The Entra ID provider needs to authenticate to Azure to manage your resources. There are multiple ways to authenticate the Entra ID provider. In this tutorial, you will authenticate the provider using the Azure CLI.
First, log in to the Azure CLI and follow the instructions in the prompt. Since
Entra ID tenants can exist without a subscription, use the
--allow-no-subscriptions
flag to list all tenants.
The login
command outputs a list of subscriptions and tenants associated with
the account. The provider will automatically select the tenant ID from your
default Azure CLI account. If you have more than one tenant, specify the tenant
by setting the ARM_TENANT_ID
environment variable to your preferred tenant ID
(tenantId
field from the previous command's output).
Clone example repository
Clone the example repository, which contains configuration to create new users in your Entra ID tenant.
Change into the repository directory.
Review users CSV file
Open users.csv
. This CSV file contains a list of user information that
Terraform will use to configure AD users.
The first line is the header. Each field in the header is a key for the corresponding value in the same position in the remaining rows. Each remaining row represents a user and must contain the same number of fields as the header. These header key names allow you to reference a specific user attribute in your Terraform configuration.
Review configuration
Open versions.tf
. This file contains a terraform {}
block that defines
Terraform settings, including the required providers Terraform will use to
provision your infrastructure. A provider is a plugin that Terraform uses to
interact with APIs. The source
attribute defines an optional hostname, a
namespace, and the provider type for each provider. Terraform installs providers
from the Terraform Registry by default. This
example configuration defines the azuread
provider's source as
hashicorp/azuread
, which is shorthand for
registry.terraform.io/hashicorp/azuread
.
You can also set a version constraint for each provider defined in the
required_providers
block. The version
attribute is optional, but we
recommend using it to constrain the provider version so that Terraform does not
install a provider version that does not work with your configuration. If you
do not specify a provider version, Terraform will automatically download
the version listed in the .terraform.lock.hcl
file. If neither exist,
Terraform will download the latest version during initialization.
Open main.tf
to review the Terraform configuration that will create the users
defined in your CSV file. Terraform configuration consists of blocks of code
written in Terraform configuration language. Review each block below to learn
what this Terraform configuration defines.
Provider block
To use the Entra ID provider, you must define a provider block in your configuration.
The azuread
provider block is empty because it uses the credentials
configured by the Azure CLI for authentication. You can configure other
optional, provider-specific settings
in this block, like client ID, environment, or tenant ID. This provider
automatically uses your default tenant ID if you do not set the ARM_TENANT_ID
environment variable.
Data source block
Data sources allow you to retrieve information from the provider.
This azuread_domains
data source retrieves your primary Entra ID tenant domain. Terraform will use
this to create user principal names for your users.
Local values
The locals
block allows you to define values that you reference throughout
your configuration. Locals capture common values to make your configuration
easier to read and less repetitive.
This locals
block defines two values:
The
domain_name
local value stores the Entra ID tenant domain name retrieved by theazuread_domains.default
data source. This allows you to uselocal.domain_name
instead of parsing the data source every time you reference it.The
users
local value parses theusers.csv
file using thecsvdecode
andfile
functions. Thecsvdecode
function converts the file contents into a list of maps, allowing Terraform to reference the values in the CSV file in the configuration.
Resources
Resource blocks are the primary way you interact with the provider to manage its components.
Resource blocks have two strings in the first line of the block: the resource
type and the resource name. The first resource block defines a random_pet
resource named suffix
, which generates a random pet name. This configuration
uses this resource to ensure that your users have unique principal names.
Now, find the first two lines of the AzureAD users resource block.
This azuread_user
resource block is named users
. The for_each
meta-argument tells Terraform that this block defines multiple users, each one
mapped to a user in the local.users
value. By storing information about your users in a CSV file and using the for_each
meta-argument to iterate over the decoded contents, you avoid creating unique resource blocks for each user, which
can become difficult to manage as you add more users.
Each resource has required or optional arguments that Terraform uses to configure the resource to your specifications. Refer to the resource's documentation in Terraform Registry to find a complete list of arguments.
The azuread_user
resource requires the user_principal_name
, password
, and
display_name
arguments.
Tip
This block references a specific user's information by using
each.value.attribute_name
. The attribute_name
maps to the header row in
the CSV file. For example, each.value.first_name
maps to the user's first
name.
The user_principal_name
and password
arguments use the
format()
function to generate these values from the user's first name, last name, and
the Entra ID tenant's domain name (local.domain_name
).
For example, if your user is named "Jim Halpert", their user principal name
would be jhalpert@domain_name
, where the domain name is your AD tenant's
domain name, and their password would be halpertj3!
.
The password
argument sets the user's initial password. Azure will force them
to change it after the initial sign-in.
The display_name
argument uses Terraform interpolation (${}
) to generate a string from the user's
first and last name.
The configuration also sets the job_title
and department
attributes, which are optional for
the azuread_user
resource.
Create AD users
Initialize the Terraform configuration. Initializing a configuration directory
downloads and installs the providers defined in the configuration, which in
this case is the azuread
provider.
Next, apply the configuration. Respond yes
when prompted to create your AD users.
Notice that Terraform created three users, one for each row defined in your
users.csv
file. Using the for_each
meta-argument, you created three unique
users using a single resource block.
Use the Terraform state
command to list all resources managed by Terraform.
Retrieve Pam's AD user information.
Verify user creation
Use the Azure CLI to retrieve your newly created users. This command filters users that are in the "Education" department.
You will find three users, as defined in users.csv
.
Create AD groups and assign members
Now that you have created AD users, you will create groups and assign users to them based on their attributes.
Create a new file named groups.tf
with the following configuration.
This configuration creates three groups and assigns the appropriate users based on their department or job title.
The
azuread_group.education
resource creates a new group named "Education Department". Theazuread_group
requires either themail_enabled
orsecurity_enabled
argument. Theazuread_group_member.education
resource assigns all users in the Education department to this group.This resource uses the
for_each
meta-argument to loop through all users created byazuread_user.users
. This creates an implicit dependency and ensures that the user exists in your AD tenant before assigning it to the group. Thefor_each
meta-argument usesu.mail_nickname
as the key. This maps each member to a member association in the resource ID. For example,azuread_group_member.education[\"jhalpert-artistic-coyote\"]
maps to Jim Halpert's education member association.The
azuread_group.managers
creates a new group named "Education - Managers". Theazuread_group_member.managers
resource loops through all created users and assigns all managers to the group.The
azuread_group.engineers
creates a new group named "Education - Engineers". Theazuread_group_member.engineers
resource loops through all created users and assigns all engineers to the group.
Apply the configuration. Respond yes
when prompted to create your AD groups
and assign users to the appropriate ones.
Verify group creation and user assignment
Use the Azure CLI to verify that Terraform created the three groups you defined.
List all the users in the Education department group.
List all the users in the managers group.
List all the users in the engineers group.
Manage new users
Add the following new users to your users.csv
file.
Tip
Make sure to remove any trailing white space from each user's job title.
Add a new group
Since Kelly Kapoor is a customer success engineer, Terraform will only assign Kelly to the "Education Department" group.
In groups.tf
, add the following configuration to create a new group named
"Education - Customer Success" and assign all accountants to the group.
Create new users
Since the azuread_group_member
resources rely on the azuread_user.users
resource to determine the number of group/user assignments, you need to create
the users resource first.
Apply the configuration using the -target
flag to create the new users first.
The -target
flag instructs Terraform to only change a single resource rather
than all resources in the current directory. When you apply your configuration,
Terraform will create three new AD users and add the new users to their
respective teams. Respond yes
when prompted to add the new users.
Update group assignments
Now, apply the configuration again. Respond yes
when prompted to create the
Customer Success group and update the group assignments.
Verify resource creation and user assignment
Use the Azure CLI to retrieve your newly created users. You will find a total of six users.
Verify that Terraform created the groups you defined. You will find four groups, including the new Customer Success group.
List all the users in the Education department group. You will find a total of six users.
List all the users in the engineers group. You will find a total of four users.
Finally, list all the users in the customer success group. You will find Kelly Kapoor.
Clean up resources
Before moving on, destroy the resources you created in this tutorial. Respond
yes
when prompted to destroy all AD users and groups.
Next steps
In this tutorial, you created new users in your Entra ID with
data populated from a CSV file. Then, you created new AD groups and dynamically
assigned users to their respective groups based on their roles. Finally, you
created new users by updating the CSV file and created a new group for customer
success. In the process, you used a wide variety of Terraform's configuration
language elements and functions like resource blocks, locals, and the csvdecode()
function. In
addition, you learned about the resources the Entra ID provider can manage.
For more information on topics covered in this tutorial, check out the following resources:
Learn more about input variables and dynamic expressions, which you used in this tutorial.
Complete the Reuse Configuration with Modules tutorials to learn how to create reusable modules to enable repeatable workflows.
Visit the Entra ID provider documentation to learn more about the Entra ID resources and data sources you can manage using Terraform.