From 0092e8d0152e7d731c59d697709884bbd0be4f28 Mon Sep 17 00:00:00 2001 From: Henry Buckle Date: Sun, 17 Dec 2017 22:50:00 +0000 Subject: [PATCH 1/8] allow auth via msi --- azurerm/config.go | 18 +++++++++++++++++- azurerm/helpers/authentication/config.go | 2 ++ azurerm/helpers/authentication/validation.go | 16 ++++++++++++++++ azurerm/provider.go | 19 ++++++++++++++++++- 4 files changed, 53 insertions(+), 2 deletions(-) diff --git a/azurerm/config.go b/azurerm/config.go index be57c9f5da66..dd9d9fe37667 100644 --- a/azurerm/config.go +++ b/azurerm/config.go @@ -228,6 +228,23 @@ func getAuthorizationToken(c *authentication.Config, oauthConfig *adal.OAuthConf return auth, nil } + if c.UseMsi { + useCustomEndpoint := c.MsiEndpoint != "" + if !useCustomEndpoint { + msiEndpoint, err := adal.GetMSIVMEndpoint() + if err != nil { + return nil, err + } + c.MsiEndpoint = msiEndpoint + } + spt, err := adal.NewServicePrincipalTokenFromMSI(c.MsiEndpoint, endpoint) + if err != nil { + return nil, err + } + auth := autorest.NewBearerAuthorizer(spt) + return auth, nil + } + if c.IsCloudShell { // load the refreshed tokens from the Azure CLI err := c.LoadTokensFromAzureCLI() @@ -240,7 +257,6 @@ func getAuthorizationToken(c *authentication.Config, oauthConfig *adal.OAuthConf if err != nil { return nil, err } - auth := autorest.NewBearerAuthorizer(spt) return auth, nil } diff --git a/azurerm/helpers/authentication/config.go b/azurerm/helpers/authentication/config.go index eb276c2e29d2..93bbf66d761c 100644 --- a/azurerm/helpers/authentication/config.go +++ b/azurerm/helpers/authentication/config.go @@ -28,6 +28,8 @@ type Config struct { // Bearer Auth AccessToken *adal.Token IsCloudShell bool + UseMsi bool + MsiEndpoint string } func (c *Config) LoadTokensFromAzureCLI() error { diff --git a/azurerm/helpers/authentication/validation.go b/azurerm/helpers/authentication/validation.go index 8c777145a2cd..68c9ed758366 100644 --- a/azurerm/helpers/authentication/validation.go +++ b/azurerm/helpers/authentication/validation.go @@ -49,3 +49,19 @@ func (c *Config) ValidateServicePrincipal() error { return err.ErrorOrNil() } + +func (c *Config) ValidateMsi() error { + var err *multierror.Error + + if c.SubscriptionID == "" { + err = multierror.Append(err, fmt.Errorf("Subscription ID must be configured for the AzureRM provider")) + } + if c.TenantID == "" { + err = multierror.Append(err, fmt.Errorf("Tenant ID must be configured for the AzureRM provider")) + } + if c.Environment == "" { + err = multierror.Append(err, fmt.Errorf("Environment must be configured for the AzureRM provider")) + } + + return err.ErrorOrNil() +} diff --git a/azurerm/provider.go b/azurerm/provider.go index eea804a46705..112ac2f89f5a 100644 --- a/azurerm/provider.go +++ b/azurerm/provider.go @@ -62,6 +62,16 @@ func Provider() terraform.ResourceProvider { Optional: true, DefaultFunc: schema.EnvDefaultFunc("ARM_SKIP_PROVIDER_REGISTRATION", false), }, + "use_msi": { + Type: schema.TypeBool, + Optional: true, + DefaultFunc: schema.EnvDefaultFunc("ARM_USE_MSI", false), + }, + "msi_endpoint": { + Type: schema.TypeString, + Optional: true, + DefaultFunc: schema.EnvDefaultFunc("ARM_MSI_ENDPOINT", ""), + }, }, DataSourcesMap: map[string]*schema.Resource{ @@ -190,9 +200,16 @@ func providerConfigure(p *schema.Provider) schema.ConfigureFunc { Environment: d.Get("environment").(string), SkipCredentialsValidation: d.Get("skip_credentials_validation").(bool), SkipProviderRegistration: d.Get("skip_provider_registration").(bool), + UseMsi: d.Get("use_msi").(bool), + MsiEndpoint: d.Get("msi_endpoint").(string), } - if config.ClientSecret != "" { + if config.UseMsi { + log.Printf("[DEBUG] ARM_USE_MSI specified - using MSI Authentication") + if err := config.ValidateMsi(); err != nil { + return nil, err + } + } else if config.ClientSecret != "" { log.Printf("[DEBUG] Client Secret specified - using Service Principal for Authentication") if err := config.ValidateServicePrincipal(); err != nil { return nil, err From 988fc2dc3f04f505a3a7225b4a52b6ab7683bd9c Mon Sep 17 00:00:00 2001 From: Henry Buckle Date: Sun, 17 Dec 2017 23:00:00 +0000 Subject: [PATCH 2/8] tweaks --- azurerm/config.go | 1 + azurerm/provider.go | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/azurerm/config.go b/azurerm/config.go index dd9d9fe37667..729c79d358dc 100644 --- a/azurerm/config.go +++ b/azurerm/config.go @@ -257,6 +257,7 @@ func getAuthorizationToken(c *authentication.Config, oauthConfig *adal.OAuthConf if err != nil { return nil, err } + auth := autorest.NewBearerAuthorizer(spt) return auth, nil } diff --git a/azurerm/provider.go b/azurerm/provider.go index 112ac2f89f5a..4e66bd0ac1c5 100644 --- a/azurerm/provider.go +++ b/azurerm/provider.go @@ -205,7 +205,7 @@ func providerConfigure(p *schema.Provider) schema.ConfigureFunc { } if config.UseMsi { - log.Printf("[DEBUG] ARM_USE_MSI specified - using MSI Authentication") + log.Printf("[DEBUG] use_msi specified - using MSI Authentication") if err := config.ValidateMsi(); err != nil { return nil, err } From 9e671ec947fffd31ea4161b27e61413edca75c91 Mon Sep 17 00:00:00 2001 From: Henry Buckle Date: Mon, 18 Dec 2017 15:50:33 +0000 Subject: [PATCH 3/8] get endpoint during provider setup --- azurerm/config.go | 8 --- azurerm/helpers/authentication/validation.go | 3 + .../helpers/authentication/validation_test.go | 72 +++++++++++++++++++ azurerm/provider.go | 8 +++ 4 files changed, 83 insertions(+), 8 deletions(-) diff --git a/azurerm/config.go b/azurerm/config.go index 729c79d358dc..f7e458ad3bf5 100644 --- a/azurerm/config.go +++ b/azurerm/config.go @@ -229,14 +229,6 @@ func getAuthorizationToken(c *authentication.Config, oauthConfig *adal.OAuthConf } if c.UseMsi { - useCustomEndpoint := c.MsiEndpoint != "" - if !useCustomEndpoint { - msiEndpoint, err := adal.GetMSIVMEndpoint() - if err != nil { - return nil, err - } - c.MsiEndpoint = msiEndpoint - } spt, err := adal.NewServicePrincipalTokenFromMSI(c.MsiEndpoint, endpoint) if err != nil { return nil, err diff --git a/azurerm/helpers/authentication/validation.go b/azurerm/helpers/authentication/validation.go index 68c9ed758366..460441065515 100644 --- a/azurerm/helpers/authentication/validation.go +++ b/azurerm/helpers/authentication/validation.go @@ -62,6 +62,9 @@ func (c *Config) ValidateMsi() error { if c.Environment == "" { err = multierror.Append(err, fmt.Errorf("Environment must be configured for the AzureRM provider")) } + if c.MsiEndpoint == "" { + err = multierror.Append(err, fmt.Errorf("MSI endpoint must be configured for the AzureRM provider")) + } return err.ErrorOrNil() } diff --git a/azurerm/helpers/authentication/validation_test.go b/azurerm/helpers/authentication/validation_test.go index 99cab000e609..f69594b4bad1 100644 --- a/azurerm/helpers/authentication/validation_test.go +++ b/azurerm/helpers/authentication/validation_test.go @@ -164,3 +164,75 @@ func TestAzureValidateServicePrincipal(t *testing.T) { } } } + +func TestAzureValidateMsi(t *testing.T) { + cases := []struct { + Description string + Config Config + ExpectError bool + }{ + { + Description: "Empty Configuration", + Config: Config{}, + ExpectError: true, + }, + { + Description: "Missing Subscription ID", + Config: Config{ + MsiEndpoint: "http://localhost:50342/oauth2/token", + TenantID: "9834f8d0-24b3-41b7-8b8d-c611c461a129", + Environment: "public", + }, + ExpectError: true, + }, + { + Description: "Missing Tenant ID", + Config: Config{ + MsiEndpoint: "http://localhost:50342/oauth2/token", + SubscriptionID: "8e8b5e02-5c13-4822-b7dc-4232afb7e8c2", + Environment: "public", + }, + ExpectError: true, + }, + { + Description: "Missing Environment", + Config: Config{ + MsiEndpoint: "http://localhost:50342/oauth2/token", + SubscriptionID: "8e8b5e02-5c13-4822-b7dc-4232afb7e8c2", + TenantID: "9834f8d0-24b3-41b7-8b8d-c611c461a129", + }, + ExpectError: true, + }, + { + Description: "Missing MSI Endpoint", + Config: Config{ + SubscriptionID: "8e8b5e02-5c13-4822-b7dc-4232afb7e8c2", + TenantID: "9834f8d0-24b3-41b7-8b8d-c611c461a129", + Environment: "public", + }, + ExpectError: true, + }, + { + Description: "Valid Configuration", + Config: Config{ + MsiEndpoint: "http://localhost:50342/oauth2/token", + SubscriptionID: "8e8b5e02-5c13-4822-b7dc-4232afb7e8c2", + TenantID: "9834f8d0-24b3-41b7-8b8d-c611c461a129", + Environment: "public", + }, + ExpectError: false, + }, + } + + for _, v := range cases { + err := v.Config.ValidateMsi() + + if v.ExpectError && err == nil { + t.Fatalf("Expected an error for %q: didn't get one", v.Description) + } + + if !v.ExpectError && err != nil { + t.Fatalf("Expected there to be no error for %q - but got: %v", v.Description, err) + } + } +} diff --git a/azurerm/provider.go b/azurerm/provider.go index 4e66bd0ac1c5..1e596d7b6664 100644 --- a/azurerm/provider.go +++ b/azurerm/provider.go @@ -10,6 +10,7 @@ import ( "sync" "github.com/Azure/azure-sdk-for-go/arm/resources/resources" + "github.com/Azure/go-autorest/autorest/adal" "github.com/hashicorp/terraform/helper/mutexkv" "github.com/hashicorp/terraform/helper/schema" "github.com/hashicorp/terraform/terraform" @@ -206,6 +207,13 @@ func providerConfigure(p *schema.Provider) schema.ConfigureFunc { if config.UseMsi { log.Printf("[DEBUG] use_msi specified - using MSI Authentication") + if config.MsiEndpoint == "" { + msiEndpoint, err := adal.GetMSIVMEndpoint() + if err != nil { + return nil, err + } + config.MsiEndpoint = msiEndpoint + } if err := config.ValidateMsi(); err != nil { return nil, err } From 03667c14997ca5dc17bc58fad553c0e5538d19b7 Mon Sep 17 00:00:00 2001 From: Henry Buckle Date: Mon, 18 Dec 2017 19:51:35 +0000 Subject: [PATCH 4/8] docs --- .../docs/authenticating_via_msi.html.markdown | 71 +++++++++++++++++++ website/docs/index.html.markdown | 7 ++ 2 files changed, 78 insertions(+) create mode 100644 website/docs/authenticating_via_msi.html.markdown diff --git a/website/docs/authenticating_via_msi.html.markdown b/website/docs/authenticating_via_msi.html.markdown new file mode 100644 index 000000000000..f12bbec31353 --- /dev/null +++ b/website/docs/authenticating_via_msi.html.markdown @@ -0,0 +1,71 @@ +--- +layout: "azurerm" +page_title: "AzureRM: Authenticating via Managed Service Identity" +sidebar_current: "docs-azurerm-index-authentication-msi" +description: |- + The Azure Resource Manager provider supports authenticating via multiple means. This guide will cover creating a Managed Service Identity which can be used to access Azure Resource Manager. + +--- + +# Authenticating to Azure Resource Manager using Managed Service Identity + +Terraform supports authenticating to Azure through Managed Service Identity, Service Principal or the Azure CLI. + +We recommend using Managed Service Identity when running in a Shared Environment (such as within a CI server/automation) - and [authenticating via the Azure CLI](authenticating_via_azure_cli.html) when you're running Terraform locally. + +## Configuring Managed Service Identity + +Managed Service Identity allows an Azure virtual machine to retrieve a token to access the Azure API without needing to pass in credentials. This works by creating a service principal in Azure Active Directory that is associated to a virtual machine. This service principal can then be granted permissions to Azure resources. + +### Configuring Managed Service Identity using Terraform + +~> **Note**: if you're using the **China**, **German** or **Government** Azure Clouds - you'll need to first configure the Azure CLI to work with that Cloud. You can do this by running: + +```shell +$ az cloud set --name AzureChinaCloud|AzureGermanCloud|AzureUSGovernment +``` + +--- + +Firstly, login to the Azure CLI using: + +```shell +$ az login +``` + + +Once logged in - it's possible to list the Subscriptions associated with the account via: + +```shell +$ az account list +``` + +The output (similar to below) will display one or more Subscriptions - with the `ID` field being the `subscription_id` field referenced above. + +```json +[ + { + "cloudName": "AzureCloud", + "id": "00000000-0000-0000-0000-000000000000", + "isDefault": true, + "name": "PAYG Subscription", + "state": "Enabled", + "tenantId": "00000000-0000-0000-0000-000000000000", + "user": { + "name": "user@example.com", + "type": "user" + } + } +] +``` + +Should you have more than one Subscription, you can specify the Subscription to use via the following command: + +```shell +$ az account set --subscription="SUBSCRIPTION_ID" +``` + + + +### Creating Managed Service Identity in the Azure Portal + diff --git a/website/docs/index.html.markdown b/website/docs/index.html.markdown index 58d7d31d96e7..6121a474f6b3 100644 --- a/website/docs/index.html.markdown +++ b/website/docs/index.html.markdown @@ -77,6 +77,13 @@ The following arguments are supported: * `tenant_id` - (Optional) The tenant ID to use. It can also be sourced from the `ARM_TENANT_ID` environment variable. +* `use_msi` - (Optional) Set to true to authenticate using managed service identity. + It can also be sourced from the `ARM_USE_MSI` environment variable. + +* `msi_endpoint` - (Optional) The REST endpoint to retrieve an MSI token from. Terraform + will attempt to discover this automatically but it can be specified manually here. + It can also be sourced from the `ARM_MSI_ENDPOINT` environment variable. + * `environment` - (Optional) The cloud environment to use. It can also be sourced from the `ARM_ENVIRONMENT` environment variable. Supported values are: * `public` (default) From d5a5e8bd0c63efd37aa1540e2d533a2872845b0c Mon Sep 17 00:00:00 2001 From: Henry Buckle Date: Mon, 18 Dec 2017 20:21:31 +0000 Subject: [PATCH 5/8] update error msg --- azurerm/provider.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/azurerm/provider.go b/azurerm/provider.go index 1e596d7b6664..70d478720cee 100644 --- a/azurerm/provider.go +++ b/azurerm/provider.go @@ -210,10 +210,12 @@ func providerConfigure(p *schema.Provider) schema.ConfigureFunc { if config.MsiEndpoint == "" { msiEndpoint, err := adal.GetMSIVMEndpoint() if err != nil { - return nil, err + return nil, fmt.Errorf("Could not retrieve MSI endpoint from VM settings."+ + "Ensure the VM has MSI enabled, or try setting the msi_endpoint setting. Error: %s", err) } config.MsiEndpoint = msiEndpoint } + log.Printf("[DEBUG] Using MSI endpoint %s", config.MsiEndpoint) if err := config.ValidateMsi(); err != nil { return nil, err } From d0000970e138e9c18564f3c0ceda4cf8f86fac8f Mon Sep 17 00:00:00 2001 From: Henry Buckle Date: Mon, 18 Dec 2017 20:40:19 +0000 Subject: [PATCH 6/8] docs --- website/azurerm.erb | 4 + .../docs/authenticating_via_msi.html.markdown | 108 +++++++++++------- 2 files changed, 71 insertions(+), 41 deletions(-) diff --git a/website/azurerm.erb b/website/azurerm.erb index a7ddf17dc84f..34bc793f3072 100644 --- a/website/azurerm.erb +++ b/website/azurerm.erb @@ -17,6 +17,10 @@ > Authenticating via a Service Principal (Shared Account) + + > + Authenticating via Managed Service Identity + diff --git a/website/docs/authenticating_via_msi.html.markdown b/website/docs/authenticating_via_msi.html.markdown index f12bbec31353..93db404e6759 100644 --- a/website/docs/authenticating_via_msi.html.markdown +++ b/website/docs/authenticating_via_msi.html.markdown @@ -3,7 +3,7 @@ layout: "azurerm" page_title: "AzureRM: Authenticating via Managed Service Identity" sidebar_current: "docs-azurerm-index-authentication-msi" description: |- - The Azure Resource Manager provider supports authenticating via multiple means. This guide will cover creating a Managed Service Identity which can be used to access Azure Resource Manager. + The Azure Resource Manager provider supports authenticating via multiple means. This guide will cover configuring a Managed Service Identity which can be used to access Azure Resource Manager. --- @@ -11,61 +11,87 @@ description: |- Terraform supports authenticating to Azure through Managed Service Identity, Service Principal or the Azure CLI. -We recommend using Managed Service Identity when running in a Shared Environment (such as within a CI server/automation) - and [authenticating via the Azure CLI](authenticating_via_azure_cli.html) when you're running Terraform locally. +We recommend using Managed Service Identity when running in a Shared Environment (such as within a CI server/automation) that you do not wish to configure credentials for - and [authenticating via the Azure CLI](authenticating_via_azure_cli.html) when you're running Terraform locally. Note that managed service identity is only available for virtual machines within Azure. ## Configuring Managed Service Identity Managed Service Identity allows an Azure virtual machine to retrieve a token to access the Azure API without needing to pass in credentials. This works by creating a service principal in Azure Active Directory that is associated to a virtual machine. This service principal can then be granted permissions to Azure resources. +There are various ways to configure managed service identity - see the [Microsoft documentation](https://docs.microsoft.com/en-us/azure/active-directory/msi-overview) for details. +You can then run Terraform from the MSI enable virtual machine by setting the use_msi provider option to true. ### Configuring Managed Service Identity using Terraform -~> **Note**: if you're using the **China**, **German** or **Government** Azure Clouds - you'll need to first configure the Azure CLI to work with that Cloud. You can do this by running: +Managed service identity can also be configured using Terraform. The following template shows how. Note that for a Linux VM you must use the ManagedIdentityExtensionForLinux. -```shell -$ az cloud set --name AzureChinaCloud|AzureGermanCloud|AzureUSGovernment -``` +```hcl +resource "azurerm_virtual_machine" "virtual_machine" { + name = "test" + location = "${var.location}" + resource_group_name = "test" + network_interface_ids = ["${azurerm_network_interface.test.id}"] + vm_size = "Standard_DS1_v2" ---- - -Firstly, login to the Azure CLI using: - -```shell -$ az login -``` - - -Once logged in - it's possible to list the Subscriptions associated with the account via: - -```shell -$ az account list -``` + identity = { + type = "SystemAssigned" + } -The output (similar to below) will display one or more Subscriptions - with the `ID` field being the `subscription_id` field referenced above. + storage_image_reference { + publisher = "MicrosoftWindowsServer" + offer = "WindowsServer" + sku = "2016-Datacenter-smalldisk" + version = "latest" + } -```json -[ - { - "cloudName": "AzureCloud", - "id": "00000000-0000-0000-0000-000000000000", - "isDefault": true, - "name": "PAYG Subscription", - "state": "Enabled", - "tenantId": "00000000-0000-0000-0000-000000000000", - "user": { - "name": "user@example.com", - "type": "user" - } + storage_os_disk { + name = "test" + caching = "ReadWrite" + create_option = "FromImage" + managed_disk_type = "Standard_LRS" } -] -``` -Should you have more than one Subscription, you can specify the Subscription to use via the following command: + os_profile { + computer_name = "test" + admin_username = "username" + admin_password = "password" + } -```shell -$ az account set --subscription="SUBSCRIPTION_ID" -``` + os_profile_windows_config { + provision_vm_agent = true + enable_automatic_upgrades = false + } +} + +resource "azurerm_virtual_machine_extension" "virtual_machine_extension" { + name = "test" + location = "${var.location}" + resource_group_name = "test" + virtual_machine_name = "${azurerm_virtual_machine.virtual_machine.name}" + publisher = "Microsoft.ManagedIdentity" + type = "ManagedIdentityExtensionForWindows" + type_handler_version = "1.0" + + settings = < Date: Mon, 18 Dec 2017 20:47:31 +0000 Subject: [PATCH 7/8] tidy --- azurerm/provider.go | 6 +++--- website/docs/authenticating_via_msi.html.markdown | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/azurerm/provider.go b/azurerm/provider.go index 70d478720cee..eee1c6838c40 100644 --- a/azurerm/provider.go +++ b/azurerm/provider.go @@ -199,10 +199,10 @@ func providerConfigure(p *schema.Provider) schema.ConfigureFunc { ClientSecret: d.Get("client_secret").(string), TenantID: d.Get("tenant_id").(string), Environment: d.Get("environment").(string), + UseMsi: d.Get("use_msi").(bool), + MsiEndpoint: d.Get("msi_endpoint").(string), SkipCredentialsValidation: d.Get("skip_credentials_validation").(bool), SkipProviderRegistration: d.Get("skip_provider_registration").(bool), - UseMsi: d.Get("use_msi").(bool), - MsiEndpoint: d.Get("msi_endpoint").(string), } if config.UseMsi { @@ -211,7 +211,7 @@ func providerConfigure(p *schema.Provider) schema.ConfigureFunc { msiEndpoint, err := adal.GetMSIVMEndpoint() if err != nil { return nil, fmt.Errorf("Could not retrieve MSI endpoint from VM settings."+ - "Ensure the VM has MSI enabled, or try setting the msi_endpoint setting. Error: %s", err) + "Ensure the VM has MSI enabled, or try setting msi_endpoint. Error: %s", err) } config.MsiEndpoint = msiEndpoint } diff --git a/website/docs/authenticating_via_msi.html.markdown b/website/docs/authenticating_via_msi.html.markdown index 93db404e6759..1c5589c3669e 100644 --- a/website/docs/authenticating_via_msi.html.markdown +++ b/website/docs/authenticating_via_msi.html.markdown @@ -17,7 +17,7 @@ We recommend using Managed Service Identity when running in a Shared Environment Managed Service Identity allows an Azure virtual machine to retrieve a token to access the Azure API without needing to pass in credentials. This works by creating a service principal in Azure Active Directory that is associated to a virtual machine. This service principal can then be granted permissions to Azure resources. There are various ways to configure managed service identity - see the [Microsoft documentation](https://docs.microsoft.com/en-us/azure/active-directory/msi-overview) for details. -You can then run Terraform from the MSI enable virtual machine by setting the use_msi provider option to true. +You can then run Terraform from the MSI enabled virtual machine by setting the use_msi provider option to true. ### Configuring Managed Service Identity using Terraform From b65c8cde78b50b4d45fef0f3721fcda739b4decc Mon Sep 17 00:00:00 2001 From: Henry Buckle Date: Wed, 14 Feb 2018 06:26:27 +0000 Subject: [PATCH 8/8] update docs --- website/docs/authenticating_via_msi.html.markdown | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/website/docs/authenticating_via_msi.html.markdown b/website/docs/authenticating_via_msi.html.markdown index 1c5589c3669e..4060f94b7810 100644 --- a/website/docs/authenticating_via_msi.html.markdown +++ b/website/docs/authenticating_via_msi.html.markdown @@ -11,17 +11,17 @@ description: |- Terraform supports authenticating to Azure through Managed Service Identity, Service Principal or the Azure CLI. -We recommend using Managed Service Identity when running in a Shared Environment (such as within a CI server/automation) that you do not wish to configure credentials for - and [authenticating via the Azure CLI](authenticating_via_azure_cli.html) when you're running Terraform locally. Note that managed service identity is only available for virtual machines within Azure. +Managed Service Identity can be used to access other Azure Services from within a Virtual Machine in Azure instead of specifying a Service Principal or Azure CLI credentials. ## Configuring Managed Service Identity Managed Service Identity allows an Azure virtual machine to retrieve a token to access the Azure API without needing to pass in credentials. This works by creating a service principal in Azure Active Directory that is associated to a virtual machine. This service principal can then be granted permissions to Azure resources. There are various ways to configure managed service identity - see the [Microsoft documentation](https://docs.microsoft.com/en-us/azure/active-directory/msi-overview) for details. -You can then run Terraform from the MSI enabled virtual machine by setting the use_msi provider option to true. +You can then run Terraform from the MSI enabled virtual machine by setting the `use_msi` provider option to `true`. ### Configuring Managed Service Identity using Terraform -Managed service identity can also be configured using Terraform. The following template shows how. Note that for a Linux VM you must use the ManagedIdentityExtensionForLinux. +Managed service identity can also be configured using Terraform. The following template shows how. Note that for a Linux VM you must use the `ManagedIdentityExtensionForLinux` extension. ```hcl resource "azurerm_virtual_machine" "virtual_machine" { @@ -85,7 +85,6 @@ data "azurerm_builtin_role_definition" "builtin_role_definition" { # Grant the VM identity contributor rights to the current subscription resource "azurerm_role_assignment" "role_assignment" { - name = "${uuid()}" scope = "${data.azurerm_subscription.subscription.id}" role_definition_id = "${data.azurerm_subscription.subscription.id}${data.azurerm_builtin_role_definition.builtin_role_definition.id}" principal_id = "${lookup(azurerm_virtual_machine.virtual_machine.identity[0], "principal_id")}"