title: How to securely allow access to AWS Secrets Manager with Terraform and cloud-init
body: <p>I have the situation whereby I am having Terraform create a random password and store it into AWS Secrets Manager.
  My Terraform password and secrets manager config:</p>
  <pre><code>resource &quot;random_password&quot; &quot;my_password&quot; {
    length = 16
    lower = true
    upper = true
    number = true
    special = true
    override_special = &quot;@#$%&quot;
  }
  
  resource &quot;aws_secretsmanager_secret&quot; &quot;my_password_secret&quot; {
    name = &quot;/development/my_password&quot;
  }
  
  resource &quot;aws_secretsmanager_secret_version&quot; &quot;my_password_secret_version&quot; {
    secret_id     = aws_secretsmanager_secret.my_password_secret.id
    secret_string = random_password.my_password.result
  }
  </code></pre>
  <p>The above works well. However I am not clear on how to achieve my final goal...</p>
  <p>I have an AWS EC2 Instance which is also configured via Terraform, when the system boots it executes some cloud-init config which runs a setup script (Bash script). The Bash setup script needs to install some server software and set a password for that server software. I am not certain how to securely access <code>my_password</code> from that Bash script during setup.</p>
  <p>My Terraform config for the instance and cloud-init config:</p>
  <pre><code>resource &quot;aws_instance&quot; &quot;my_instance_1&quot; {
    ami           = data.aws_ami.amazon_linux_2.id
    instance_type = &quot;m5a.2xlarge&quot;
  
    user_data = data.cloudinit_config.my_instance_1.rendered
  
    ...
  
  }
  
  
  data &quot;cloudinit_config&quot; &quot;my_instance_1&quot; {
    gzip = true
    base64_encode = true
  
    part {
      content_type = &quot;text/x-shellscript&quot;
      filename = &quot;setup-script.sh&quot;
      content = &lt;&lt;EOF
  #!/usr/bin/env bash
  my_password=`&lt;MY PASSWORD IS NEEDED HERE&gt;`  # TODO retrieve via cURL call to Secrets Manager API?
  server_password=$my_password /opt/srv/bin/install.sh
  EOF
    }
  }
  </code></pre>
  <p>I need to be able to securely retrieve the password from the AWS Secrets Manager when the cloud-init script runs, as I have read that embedding it in the bash script is considered insecure.</p>
  <p>I have also read that AWS has the notion of Temporary Credentials, and that these can be associated with an EC2 instance - <a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp.html" rel="nofollow noreferrer">https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp.html</a></p>
  <p>Using Terraform can I create temporary credentials (say 10 minutes TTL) and grant them to my AWS EC2 instance, so that when my Bash script runs during cloud-init it can retrieve the password from the AWS Secrets Manager?</p>
  <p>I have seen that on the Terraform <code>aws_instance</code> resource, I can associate a <code>iam_instance_profile</code> and I have started by trying something like:</p>
  <pre><code>resource &quot;aws_iam_instance_profile&quot; &quot;my_instance_iam_instance_profile&quot; {
    name = &quot;my_instance_iam_instance_profile&quot;
    path = &quot;/development/&quot;
    
    role = aws_iam_role.my_instance_iam_role.name
    
    tags = {
      Environment = &quot;dev&quot;
    }
  }
  
  resource &quot;aws_iam_role&quot; &quot;my_instance_iam_role&quot; {
    name = &quot;my_instance_iam_role&quot;
    path = &quot;/development/&quot;
  
    // TODO - what how to specify a temporary credential access to a specific secret in AWS Secrets Manager from EC2???
  
    tags = {
      Environment = &quot;dev&quot;
    }
  }
  
  resource &quot;aws_instance&quot; &quot;my_instance_1&quot; {
    ami           = data.aws_ami.amazon_linux_2.id
    instance_type = &quot;m5a.2xlarge&quot;
  
    user_data = data.cloudinit_config.my_instance_1.rendered
  
    iam_instance_profile = join(&quot;&quot;, [aws_iam_instance_profile.my_instance_iam_instance_profile.path, aws_iam_instance_profile.my_instance_iam_instance_profile.name])
  
    ...
  
  }
  </code></pre>
  <p>Unfortunately I can't seem to find any details on what I should put in the Terraform <code>aws_iam_role</code> which would allow my EC2 instance to access the Secret in the AWS Secrets Manager for a temporary period of time.</p>
  <p>Can anyone advise? I would also be open to alternative approaches as long as they are also secure.</p>
  <p>Thanks</p>