-
Notifications
You must be signed in to change notification settings - Fork 4.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow authentication via managed service identity #639
Changes from all commits
cf4e46f
e25b50b
5c9d01b
0092e8d
988fc2d
9e671ec
03667c1
d5a5e8b
d000097
d1bfd42
86594ad
b65c8cd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,6 +11,7 @@ import ( | |
"sync" | ||
|
||
"github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2017-05-10/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" | ||
|
@@ -63,6 +64,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", ""), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we change the default environment variable to "AZURE_MSI_ENDPOINT", coz this endpoint is not just for getting tokens for ARM, but also for graph/datalake/keyvault. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (same here) - given the prefix for the other Environment Variables is There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should this be defaulted to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agree. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @tombuildsstuff by leaving it blank then the endpoint should be auto-discovered using GetMSIVMEndpoint(). I only put the option there in case the endpoint can't be discovered (such as when running in a container) |
||
}, | ||
}, | ||
|
||
DataSourcesMap: map[string]*schema.Resource{ | ||
|
@@ -196,11 +207,27 @@ 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), | ||
} | ||
|
||
if config.ClientSecret != "" { | ||
if config.UseMsi { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shall we use the same if-else logic as in the azurerm/config.go ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you mean from getAuthorizationToken ? I think the logic is slightly different in each There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, I mean why we don't check if ClientSecret exists firstly. |
||
log.Printf("[DEBUG] use_msi specified - using MSI Authentication") | ||
if config.MsiEndpoint == "" { | ||
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 msi_endpoint. Error: %s", err) | ||
} | ||
config.MsiEndpoint = msiEndpoint | ||
} | ||
log.Printf("[DEBUG] Using MSI endpoint %s", config.MsiEndpoint) | ||
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 | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
--- | ||
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 configuring 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. | ||
|
||
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`. | ||
|
||
### 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` extension. | ||
|
||
```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" | ||
|
||
identity = { | ||
type = "SystemAssigned" | ||
} | ||
|
||
storage_image_reference { | ||
publisher = "MicrosoftWindowsServer" | ||
offer = "WindowsServer" | ||
sku = "2016-Datacenter-smalldisk" | ||
version = "latest" | ||
} | ||
|
||
storage_os_disk { | ||
name = "test" | ||
caching = "ReadWrite" | ||
create_option = "FromImage" | ||
managed_disk_type = "Standard_LRS" | ||
} | ||
|
||
os_profile { | ||
computer_name = "test" | ||
admin_username = "username" | ||
admin_password = "password" | ||
} | ||
|
||
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 = <<SETTINGS | ||
{ | ||
"port": 50342 | ||
} | ||
SETTINGS | ||
} | ||
|
||
data "azurerm_subscription" "subscription" {} | ||
|
||
data "azurerm_builtin_role_definition" "builtin_role_definition" { | ||
name = "Contributor" | ||
} | ||
|
||
# Grant the VM identity contributor rights to the current subscription | ||
resource "azurerm_role_assignment" "role_assignment" { | ||
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")}" | ||
|
||
lifecycle { | ||
ignore_changes = ["name"] | ||
} | ||
} | ||
``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Change to "USE_MSI".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
given all the other Environment Variables are prefixed with
ARM
- we should leave this asARM_USE_MSI
for consistency (we may change this forAZURE_USE_MSI
in future, but it should be consistent for now)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree.