diff --git a/builtin/providers/aws/resource_aws_instance.go b/builtin/providers/aws/resource_aws_instance.go index f19cd42049..b99cb0c0b6 100644 --- a/builtin/providers/aws/resource_aws_instance.go +++ b/builtin/providers/aws/resource_aws_instance.go @@ -1058,14 +1058,7 @@ func buildAwsInstanceOpts( user_data := d.Get("user_data").(string) - // Check whether the user_data is already Base64 encoded; don't double-encode - _, base64DecodeError := base64.StdEncoding.DecodeString(user_data) - - if base64DecodeError == nil { - opts.UserData64 = aws.String(user_data) - } else { - opts.UserData64 = aws.String(base64.StdEncoding.EncodeToString([]byte(user_data))) - } + opts.UserData64 = aws.String(base64Encode([]byte(user_data))) // check for non-default Subnet, and cast it to a String subnet, hasSubnet := d.GetOk("subnet_id") diff --git a/builtin/providers/aws/resource_aws_launch_configuration.go b/builtin/providers/aws/resource_aws_launch_configuration.go index 4a166d2bbf..269ac77353 100644 --- a/builtin/providers/aws/resource_aws_launch_configuration.go +++ b/builtin/providers/aws/resource_aws_launch_configuration.go @@ -3,7 +3,6 @@ package aws import ( "bytes" "crypto/sha1" - "encoding/base64" "encoding/hex" "fmt" "log" @@ -310,7 +309,7 @@ func resourceAwsLaunchConfigurationCreate(d *schema.ResourceData, meta interface } if v, ok := d.GetOk("user_data"); ok { - userData := base64.StdEncoding.EncodeToString([]byte(v.(string))) + userData := base64Encode([]byte(v.(string))) createLaunchConfigurationOpts.UserData = aws.String(userData) } diff --git a/builtin/providers/aws/resource_aws_spot_fleet_request.go b/builtin/providers/aws/resource_aws_spot_fleet_request.go index 2d321d0f87..36db3ad416 100644 --- a/builtin/providers/aws/resource_aws_spot_fleet_request.go +++ b/builtin/providers/aws/resource_aws_spot_fleet_request.go @@ -324,7 +324,7 @@ func buildSpotFleetLaunchSpecification(d map[string]interface{}, meta interface{ if v, ok := d["user_data"]; ok { opts.UserData = aws.String( - base64.StdEncoding.EncodeToString([]byte(v.(string)))) + base64Encode([]byte(v.(string)))) } if v, ok := d["key_name"]; ok { diff --git a/builtin/providers/aws/utils.go b/builtin/providers/aws/utils.go new file mode 100644 index 0000000000..db341bf28a --- /dev/null +++ b/builtin/providers/aws/utils.go @@ -0,0 +1,19 @@ +package aws + +import "encoding/base64" + +// Base64Encode encodes data if the input isn't already encoded using base64.StdEncoding.EncodeToString. +// If the input is already base64 encoded, return the original input unchanged. +func base64Encode(data []byte) string { + // Check whether the data is already Base64 encoded; don't double-encode + if isBase64Encoded(data) { + return string(data) + } + // data has not been encoded encode and return + return base64.StdEncoding.EncodeToString(data) +} + +func isBase64Encoded(data []byte) bool { + _, err := base64.StdEncoding.DecodeString(string(data)) + return err == nil +} diff --git a/builtin/providers/aws/utils_test.go b/builtin/providers/aws/utils_test.go new file mode 100644 index 0000000000..c051b6f722 --- /dev/null +++ b/builtin/providers/aws/utils_test.go @@ -0,0 +1,22 @@ +package aws + +import "testing" + +var base64encodingTests = []struct { + in []byte + out string +}{ + // normal encoding case + {[]byte("data should be encoded"), "ZGF0YSBzaG91bGQgYmUgZW5jb2RlZA=="}, + // base64 encoded input should result in no change of output + {[]byte("ZGF0YSBzaG91bGQgYmUgZW5jb2RlZA=="), "ZGF0YSBzaG91bGQgYmUgZW5jb2RlZA=="}, +} + +func TestBase64Encode(t *testing.T) { + for _, tt := range base64encodingTests { + out := base64Encode(tt.in) + if out != tt.out { + t.Errorf("base64Encode(%s) => %s, want %s", tt.in, out, tt.out) + } + } +}