Search code examples
bashterraformterraform-provider-awsterraform-template-file

Terraform template file escape bash variable for user data


I have a pretty simple user data script:

#!/bin/bash

# Create script that will be executed as cron
cat > generate_rds_password.sh <<EOF
export AWS_DEFAULT_REGION=${region}

echo "Generating password"
export PGPASSWORD="$(aws rds generate-db-auth-token --hostname ${rds_host} --port 5432 --region ${region} --username ${pgusername})"
echo "$${PGPASSWORD}"
EOF

# Make it executable
chmod +x generate_rds_password.sh

What this does is create a script, and make it executable. It does some other things, but not relevant to the question.

The way I call generate this script with Terraform:

resource "aws_launch_template" "rds_bastion" {
  <...>
  user_data = base64encode(templatefile("${path.module}/bastion_userdata/startup.sh", {
    rds_host        = data.aws_db_instance.rds_instance[count.index].address
    pgusername      = var.pgmonitor_user
    region          = var.region
    environment     = var.environment
  }))
}

Now, for some reasons, I cannot echo the $PGPASSWORD. The TF plan show me the correct command (echo "${PGPASSWORD}"), but when I cat the file from the instance, the echo is empty although the PGPASSWORD is correclty generated:

export PGPASSWORD="xxxx.asdsadsad.eu-central-1.rds.amazonaws.com:5432/?Action=connect&DBUser=asdasd&X-Amz-Algorithm=...."
echo ""

What am I missing here? From this thread, it seems to be the correct way?


Solution

  • So, after reading this blog post, it seems the variables are escaped differently if you create a script from a script.

    What worked for me is a combination of \$ and \$$

    cat > generate_rds_password.sh <<EOF
    export AWS_DEFAULT_REGION=${region}
    
    echo "Generating password"
    TF_PGPASSWORD="\$(aws rds generate-db-auth-token --hostname ${rds_host} --port 5432 --region ${region} --username ${pgusername})"
    echo \$${TF_PGPASSWORD}
    EOF