A Service Principal is an application within Azure Active Directory whose authentication tokens can be used as the client_id
, client_secret
, and tenant_id
fields needed by Terraform (subscription_id
can be independently recovered from your Azure account details).
It's possible to complete this task in either the Azure CLI or in the Azure Portal - in both we'll create a Service Principal which has Contributor
rights to the subscription. It's also possible to assign other rights depending on your configuration.
$ az cloud set --name AzureChinaCloud|AzureGermanCloud|AzureUSGovernment
Firstly, login to the Azure CLI using:
$ az login
Once logged in - it's possible to list the Subscriptions associated with the account via:
$ az account list --out table
The output (similar to below) will display one or more Subscriptions - with the SubscriptionId
column being the SUBSCRIPTION_ID
field referenced below.
Name CloudName SubscriptionId State IsDefault
----------------------------- ----------- ------------------------------------ ------- -----------
PAYG Subscription AzureCloud 00000000-0000-0000-0000-000000000000 Enabled False
Contoso Sales AzureCloud 00000000-0000-1000-0000-000000000000 Enabled False
Contoso Dev AzureCloud 00000000-0000-1000-2000-000000000000 Enabled True
Contoso Dogfood AzureCloud 00000000-3000-0000-0070-000000000000 Enabled False
Contoso Prod AzureCloud 00000000-0400-0000-0070-000000000000 Enabled False
Should you have more than one Subscription, you can specify the Subscription to use via the following command:
$ az account set --subscription="SUBSCRIPTION_ID"
We can now create the Service Principal which will have permissions to manage resources in the specified Subscription using the following command:
$ az ad sp create-for-rbac --role="Contributor" --scopes="/subscriptions/SUBSCRIPTION_ID"
This command will output 5 values:
{
"appId": "00000000-0000-0000-0000-000000000000",
"displayName": "azure-cli-2017-06-05-10-41-15",
"name": "http://azure-cli-2017-06-05-10-41-15",
"password": "0000-0000-0000-0000-000000000000",
"tenant": "00000000-0000-0000-0000-000000000000"
}
These values map to the Terraform variables like so:
appId
is the client_id
defined above.password
is the client_secret
defined above.tenant
is the tenant_id
defined above.Finally, it's possible to test these values work as expected by first logging in:
$ az login --service-principal -u CLIENT_ID -p CLIENT_SECRET --tenant TENANT_ID
Once logged in as the Service Principal - we should be able to list the VM sizes by specifying an Azure region, for example here we use the West US
region:
$ az vm list-sizes --location westus
$ az account list-locations
Finally, since we're logged into the Azure CLI as a Service Principal we recommend logging out of the Azure CLI (but you can instead log in using your user account):
$ az logout
Information on how to configure the Provider block using the newly created Service Principal credentials can be found below.
There are three tasks necessary to create a Service Principal using the Azure Portal:
Firstly navigate to the Azure Active Directory overview within the Azure Portal - then select the App Registration blade. Click the New registration button at the top to add a new Application within Azure Active Directory. On this page, set the following values then press Create:
At this point the newly created Azure Active Directory application should be visible on-screen - if it's not, navigate to the the App Registration blade and select the Azure Active Directory application.
At the top of this page, you'll need to take note of the "Application (client) ID" and the "Directory (tenant) ID", which you can use for the values of client_id
and tenant_id
respectively.
Now that the Azure Active Directory Application exists we can create a Client Secret which can be used for authentication - to do this select Certificates & secrets. This screen displays the Certificates and Client Secrets (i.e. passwords) which are associated with this Azure Active Directory Application.
On this screen, we can generate a new Client Secret by clicking the New client secret button, then entering a Description and selecting an Expiry Date, and then pressing Add. Once the Client Secret has been generated it will be displayed on screen - _this is only displayed once_ so be sure to copy it now (otherwise you will need to regenerate a new secret). This value is the client_secret
you will need it.
Once the Application exists in Azure Active Directory - we can grant it permissions to modify resources in the Subscription. To do this, navigate to the Subscriptions blade within the Azure Portal, then select the Subscription you wish to use, then click Access Control (IAM), and finally Add > Add role assignment.
Firstly, specify a Role which grants the appropriate permissions needed for the Service Principal (for example, Contributor
will grant Read/Write on all resources in the Subscription). There's more information about the built in roles available here.
Secondly, search for and select the name of the Service Principal created in Azure Active Directory to assign it this role - then press Save.
As we've obtained the credentials for this Service Principal - it's possible to configure them in a few different ways.
When storing the credentials as Environment Variables, for example:
$ export ARM_CLIENT_ID="00000000-0000-0000-0000-000000000000"
$ export ARM_CLIENT_SECRET="00000000-0000-0000-0000-000000000000"
$ export ARM_SUBSCRIPTION_ID="00000000-0000-0000-0000-000000000000"
$ export ARM_TENANT_ID="00000000-0000-0000-0000-000000000000"
The following Terraform and Provider blocks can be specified - where 0.1.0
is the version of the Azure Provider that you'd like to use:
terraform {
required_providers {
azapi = {
source = "azure/azapi"
version = "=0.1.0"
}
}
}
provider "azapi" {
}
More information on the fields supported in the Provider block can be found here.
At this point running either terraform plan
or terraform apply
should allow Terraform to run using the Service Principal to authenticate.
It's also possible to configure these variables either in-line or from using variables in Terraform (as the client_secret
is in this example), like so:
variable "client_secret" {
}
terraform {
required_providers {
azapi = {
source = "azure/azapi"
version = "=0.1.0"
}
}
}
provider "azapi" {
subscription_id = "00000000-0000-0000-0000-000000000000"
client_id = "00000000-0000-0000-0000-000000000000"
client_secret = var.client_secret
tenant_id = "00000000-0000-0000-0000-000000000000"
}
More information on the fields supported in the Provider block can be found here.
At this point running either terraform plan
or terraform apply
should allow Terraform to run using the Service Principal to authenticate.