Skip to content

Commit

Permalink
Merge pull request #482 from hbuckle/managed_service_identity
Browse files Browse the repository at this point in the history
Support for managed service identity
  • Loading branch information
tombuildsstuff committed Dec 4, 2017
2 parents c664ac6 + ea22063 commit a9a362d
Show file tree
Hide file tree
Showing 3 changed files with 189 additions and 0 deletions.
54 changes: 54 additions & 0 deletions azurerm/resource_arm_virtual_machine.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,29 @@ func resourceArmVirtualMachine() *schema.Resource {
},
},

"identity": {
Type: schema.TypeList,
Optional: true,
Computed: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"type": {
Type: schema.TypeString,
Required: true,
DiffSuppressFunc: ignoreCaseDiffSuppressFunc,
ValidateFunc: validation.StringInSlice([]string{
"SystemAssigned",
}, true),
},
"principal_id": {
Type: schema.TypeString,
Computed: true,
},
},
},
},

"license_type": {
Type: schema.TypeString,
Optional: true,
Expand Down Expand Up @@ -558,6 +581,11 @@ func resourceArmVirtualMachineCreate(d *schema.ResourceData, meta interface{}) e
Tags: expandedTags,
}

if _, ok := d.GetOk("identity"); ok {
vmIdentity := expandAzureRmVirtualMachineIdentity(d)
vm.Identity = vmIdentity
}

if _, ok := d.GetOk("plan"); ok {
plan, err := expandAzureRmVirtualMachinePlan(d)
if err != nil {
Expand Down Expand Up @@ -616,6 +644,8 @@ func resourceArmVirtualMachineRead(d *schema.ResourceData, meta interface{}) err
}
}

d.Set("identity", flattenAzureRmVirtualMachineIdentity(resp.Identity))

if resp.VirtualMachineProperties.AvailabilitySet != nil {
d.Set("availability_set_id", strings.ToLower(*resp.VirtualMachineProperties.AvailabilitySet.ID))
}
Expand Down Expand Up @@ -844,6 +874,20 @@ func flattenAzureRmVirtualMachineImageReference(image *compute.ImageReference) [
return []interface{}{result}
}

func flattenAzureRmVirtualMachineIdentity(identity *compute.VirtualMachineIdentity) []interface{} {
if identity == nil {
return make([]interface{}, 0)
}

result := make(map[string]interface{})
result["type"] = string(identity.Type)
if identity.PrincipalID != nil {
result["principal_id"] = *identity.PrincipalID
}

return []interface{}{result}
}

func flattenAzureRmVirtualMachineDiagnosticsProfile(profile *compute.BootDiagnostics) []interface{} {
result := make(map[string]interface{})

Expand Down Expand Up @@ -1036,6 +1080,16 @@ func expandAzureRmVirtualMachinePlan(d *schema.ResourceData) (*compute.Plan, err
}, nil
}

func expandAzureRmVirtualMachineIdentity(d *schema.ResourceData) *compute.VirtualMachineIdentity {
v := d.Get("identity")
identities := v.([]interface{})
identity := identities[0].(map[string]interface{})
identityType := identity["type"].(string)
return &compute.VirtualMachineIdentity{
Type: compute.ResourceIdentityType(identityType),
}
}

func expandAzureRmVirtualMachineOsProfile(d *schema.ResourceData) (*compute.OSProfile, error) {
osProfiles := d.Get("os_profile").(*schema.Set).List()

Expand Down
104 changes: 104 additions & 0 deletions azurerm/resource_arm_virtual_machine_managed_disks_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,110 @@ func TestAccAzureRMVirtualMachine_multipleNICs(t *testing.T) {
})
}

func TestAccAzureRMVirtualMachine_managedServiceIdentity(t *testing.T) {
var vm compute.VirtualMachine
match := regexp.MustCompile("^(\\{{0,1}([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}\\}{0,1})$")
resourceName := "azurerm_virtual_machine.test"
ri := acctest.RandInt()
config := testAccAzureRMVirtualMachine_withManagedServiceIdentity(ri, testLocation())
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testCheckAzureRMVirtualMachineDestroy,
Steps: []resource.TestStep{
{
Config: config,
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMVirtualMachineExists(resourceName, &vm),
resource.TestCheckResourceAttr(resourceName, "identity.0.type", "SystemAssigned"),
resource.TestMatchResourceAttr(resourceName, "identity.0.principal_id", match),
resource.TestMatchOutput("principal_id", match),
),
},
},
})
}

func testAccAzureRMVirtualMachine_withManagedServiceIdentity(rInt int, location string) string {
return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
name = "acctestRG-%d"
location = "%s"
}
resource "azurerm_virtual_network" "test" {
name = "acctvn-%d"
address_space = ["10.0.0.0/16"]
location = "${azurerm_resource_group.test.location}"
resource_group_name = "${azurerm_resource_group.test.name}"
}
resource "azurerm_subnet" "test" {
name = "acctsub-%d"
resource_group_name = "${azurerm_resource_group.test.name}"
virtual_network_name = "${azurerm_virtual_network.test.name}"
address_prefix = "10.0.2.0/24"
}
resource "azurerm_network_interface" "test" {
name = "acctni-%d"
location = "${azurerm_resource_group.test.location}"
resource_group_name = "${azurerm_resource_group.test.name}"
ip_configuration {
name = "testconfiguration1"
subnet_id = "${azurerm_subnet.test.id}"
private_ip_address_allocation = "dynamic"
}
}
resource "azurerm_virtual_machine" "test" {
name = "acctvm-%d"
location = "${azurerm_resource_group.test.location}"
resource_group_name = "${azurerm_resource_group.test.name}"
network_interface_ids = ["${azurerm_network_interface.test.id}"]
vm_size = "Standard_D1_v2"
identity = {
type = "SystemAssigned"
}
storage_image_reference {
publisher = "Canonical"
offer = "UbuntuServer"
sku = "16.04-LTS"
version = "latest"
}
storage_os_disk {
name = "osd-%d"
caching = "ReadWrite"
create_option = "FromImage"
disk_size_gb = "50"
managed_disk_type = "Standard_LRS"
}
os_profile {
computer_name = "hn%d"
admin_username = "testadmin"
admin_password = "Password1234!"
}
os_profile_linux_config {
disable_password_authentication = false
}
tags {
environment = "Production"
cost-center = "Ops"
}
}
output "principal_id" {
value = "${lookup(azurerm_virtual_machine.test.identity[0], "principal_id")}"
}
`, rInt, location, rInt, rInt, rInt, rInt, rInt, rInt)
}

func testAccAzureRMVirtualMachine_basicLinuxMachine_managedDisk_explicit(rInt int, location string) string {
return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
Expand Down
31 changes: 31 additions & 0 deletions website/docs/r/virtual_machine.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,7 @@ The following arguments are supported:
* `storage_data_disk` - (Optional) A list of Storage Data disk blocks as referenced below.
* `delete_data_disks_on_termination` - (Optional) Flag to enable deletion of storage data disk VHD blobs or managed disks when the VM is deleted, defaults to `false`
* `os_profile` - (Optional) An OS Profile block as documented below. Required when `create_option` in the `storage_os_disk` block is set to `FromImage`.
* `identity` - (Optional) An identity block as documented below.

* `license_type` - (Optional, when a Windows machine) Specifies the Windows OS license type. The only allowable value, if supplied, is `Windows_Server`.
* `os_profile_windows_config` - (Required, when a Windows machine) A Windows config block as documented below.
Expand Down Expand Up @@ -323,6 +324,36 @@ resource "azurerm_virtual_machine" "test" {
3. Contains a numeric digit
4. Contains a special character

`identity` supports the following:

* `type` - (Required) Specifies the identity type of the virtual machine. The only allowable value is `SystemAssigned`. To enable Managed Service Identity the virtual machine extension "ManagedIdentityExtensionForWindows" or "ManagedIdentityExtensionForLinux" must also be added to the virtual machine. The Principal ID can be retrieved after the virtual machine has been created, e.g.

```hcl
resource "azurerm_virtual_machine" "test" {
name = "test"
identity = {
type = "SystemAssigned"
}
}
resource "azurerm_virtual_machine_extension" "test" {
name = "test"
virtual_machine_name = "${azurerm_virtual_machine.test.name}"
publisher = "Microsoft.ManagedIdentity"
type = "ManagedIdentityExtensionForWindows"
type_handler_version = "1.0"
settings = <<SETTINGS
{
"port": 50342
}
SETTINGS
}
output "principal_id" {
value = "${lookup(azurerm_virtual_machine.test.identity[0], "principal_id")}"
}
```

`os_profile_windows_config` supports the following:

* `provision_vm_agent` - (Optional) This value defaults to false.
Expand Down

0 comments on commit a9a362d

Please sign in to comment.