From dc7f2677588b5f0db2c454836471d23673d7fad2 Mon Sep 17 00:00:00 2001 From: Paul Stack Date: Wed, 22 Feb 2017 18:26:35 +0200 Subject: [PATCH] provider/azurerm: Auto base64encode virtual_machine custom data (#12164) Reported by @sethvargo - we auto encode for AWS, we should follow a similar pattern for Azure. In order to escape the double encoding, we check that it's not already encoded before encoding --- .../azurerm/resource_arm_virtual_machine.go | 16 ++++++++++++- .../resource_arm_virtual_machine_scale_set.go | 24 ++++++++++++++++++- .../azurerm/r/virtual_machine.html.markdown | 2 +- .../virtual_machine_scale_sets.html.markdown | 2 +- 4 files changed, 40 insertions(+), 4 deletions(-) diff --git a/builtin/providers/azurerm/resource_arm_virtual_machine.go b/builtin/providers/azurerm/resource_arm_virtual_machine.go index 197a10e22..3ba431a22 100644 --- a/builtin/providers/azurerm/resource_arm_virtual_machine.go +++ b/builtin/providers/azurerm/resource_arm_virtual_machine.go @@ -2,6 +2,7 @@ package azurerm import ( "bytes" + "encoding/base64" "fmt" "log" "net/http" @@ -886,7 +887,14 @@ func flattenAzureRmVirtualMachineOsProfile(osProfile *compute.OSProfile) []inter result["computer_name"] = *osProfile.ComputerName result["admin_username"] = *osProfile.AdminUsername if osProfile.CustomData != nil { - result["custom_data"] = *osProfile.CustomData + var data string + if isBase64Encoded(*osProfile.CustomData) { + decodedData, _ := base64.StdEncoding.DecodeString(*osProfile.CustomData) + data = string(decodedData) + } else { + data = *osProfile.CustomData + } + result["custom_data"] = data } return []interface{}{result} @@ -1039,6 +1047,12 @@ func expandAzureRmVirtualMachineOsProfile(d *schema.ResourceData) (*compute.OSPr } if v := osProfile["custom_data"].(string); v != "" { + if isBase64Encoded(v) { + log.Printf("[WARN] Future Versions of Terraform will automatically base64encode custom_data") + } else { + v = base64Encode(v) + } + profile.CustomData = &v } diff --git a/builtin/providers/azurerm/resource_arm_virtual_machine_scale_set.go b/builtin/providers/azurerm/resource_arm_virtual_machine_scale_set.go index 9a6ef36ab..02389f670 100644 --- a/builtin/providers/azurerm/resource_arm_virtual_machine_scale_set.go +++ b/builtin/providers/azurerm/resource_arm_virtual_machine_scale_set.go @@ -2,6 +2,7 @@ package azurerm import ( "bytes" + "encoding/base64" "fmt" "log" "net/http" @@ -651,7 +652,14 @@ func flattenAzureRMVirtualMachineScaleSetOsProfile(profile *compute.VirtualMachi result["admin_username"] = *profile.AdminUsername if profile.CustomData != nil { - result["custom_data"] = *profile.CustomData + var data string + if isBase64Encoded(*profile.CustomData) { + decodedData, _ := base64.StdEncoding.DecodeString(*profile.CustomData) + data = string(decodedData) + } else { + data = *profile.CustomData + } + result["custom_data"] = data } return []interface{}{result} @@ -853,6 +861,15 @@ func expandAzureRmVirtualMachineScaleSetNetworkProfile(d *schema.ResourceData) * } } +func base64Encode(data string) string { + return base64.StdEncoding.EncodeToString([]byte(data)) +} + +func isBase64Encoded(data string) bool { + _, err := base64.StdEncoding.DecodeString(data) + return err == nil +} + func expandAzureRMVirtualMachineScaleSetsOsProfile(d *schema.ResourceData) (*compute.VirtualMachineScaleSetOSProfile, error) { osProfileConfigs := d.Get("os_profile").(*schema.Set).List() @@ -872,6 +889,11 @@ func expandAzureRMVirtualMachineScaleSetsOsProfile(d *schema.ResourceData) (*com } if customData != "" { + if isBase64Encoded(customData) { + log.Printf("[WARN] Future Versions of Terraform will automatically base64encode custom_data") + } else { + customData = base64Encode(customData) + } osProfile.CustomData = &customData } diff --git a/website/source/docs/providers/azurerm/r/virtual_machine.html.markdown b/website/source/docs/providers/azurerm/r/virtual_machine.html.markdown index 094aa85bc..baf478bd2 100644 --- a/website/source/docs/providers/azurerm/r/virtual_machine.html.markdown +++ b/website/source/docs/providers/azurerm/r/virtual_machine.html.markdown @@ -266,7 +266,7 @@ For more information on the different example configurations, please check out t * `computer_name` - (Required) Specifies the name of the virtual machine. * `admin_username` - (Required) Specifies the name of the administrator account. * `admin_password` - (Required) Specifies the password of the administrator account. -* `custom_data` - (Optional) Specifies a base-64 encoded string of custom data. The base-64 encoded string is decoded to a binary array that is saved as a file on the Virtual Machine. The maximum length of the binary array is 65535 bytes. +* `custom_data` - (Optional) Specifies custom data to supply to the machine. On linux-based systems, this can be used as a cloud-init script. On other systems, this will be copied as a file on disk. Internally, Terraform will base64 encode this value before sending it to the API. The maximum length of the binary array is 65535 bytes. ~> **NOTE:** `admin_password` must be between 6-72 characters long and must satisfy at least 3 of password complexity requirements from the following: 1. Contains an uppercase character diff --git a/website/source/docs/providers/azurerm/r/virtual_machine_scale_sets.html.markdown b/website/source/docs/providers/azurerm/r/virtual_machine_scale_sets.html.markdown index 2b37a54a7..fe30e7b90 100644 --- a/website/source/docs/providers/azurerm/r/virtual_machine_scale_sets.html.markdown +++ b/website/source/docs/providers/azurerm/r/virtual_machine_scale_sets.html.markdown @@ -136,7 +136,7 @@ The following arguments are supported: * `computer_name_prefix` - (Required) Specifies the computer name prefix for all of the virtual machines in the scale set. Computer name prefixes must be 1 to 15 characters long. * `admin_username` - (Required) Specifies the administrator account name to use for all the instances of virtual machines in the scale set. * `admin_password` - (Required) Specifies the administrator password to use for all the instances of virtual machines in a scale set.. -* `custom_data` - (Optional) Specifies a base-64 encoded string of custom data. The base-64 encoded string is decoded to a binary array that is saved as a file on all the Virtual Machines in the scale set. The maximum length of the binary array is 65535 bytes. +* `custom_data` - (Optional) Specifies custom data to supply to the machine. On linux-based systems, this can be used as a cloud-init script. On other systems, this will be copied as a file on disk. Internally, Terraform will base64 encode this value before sending it to the API. The maximum length of the binary array is 65535 bytes. `os_profile_secrets` supports the following: