26

I want my lambda to call APIs, and that requires an API token. I want to place the API token into a lambda environment variable. How can I have terraform do this instead? Or am I approaching this the wrong way?

Strawberry
  • 66,024
  • 56
  • 149
  • 197
  • This may help [using SSM parameter store and hiding values](https://stackoverflow.com/questions/63572467/how-to-hide-terraform-aws-ssm-parameter-values) – SNR Aug 26 '20 at 05:34

4 Answers4

26

The Documentation here gives a pretty good example. Basically it's a environment block with a variables block. Then whatever key value pairs you want. Assuming you're using nodejs you can then refer to these variables in your lambda code by doing process.env.api_key. These values would be stored in plain text in your terraform code as well as the terraform state file. AWS encrypts the environment variables but you do need to concern yourself with how those values get there. If you are uncomfortable with them being stored in git and whatever storage you use for your state file then you can add them in manually through the console.

resource "aws_lambda_function" "test_lambda" {
  filename         = "lambda_function_payload.zip"
  function_name    = "lambda_function_name"
  runtime          = "nodejs8.10"
  ...

  environment {
    variables = {
      api_key = "super_secret"
    }
  }
}
Jarred Olson
  • 3,075
  • 1
  • 19
  • 34
  • Do I just have to go into the AWS control panel through a browser to add the environmental variables? – Strawberry Oct 27 '18 at 13:46
  • Wait, I don't understand. If I set "super_secret" in the terraform file and commit it then its commited into git? – Strawberry Oct 27 '18 at 13:47
  • Yes it would then be in git. Even if you use a [variable file](https://www.terraform.io/intro/getting-started/variables.html) that you do not check in, the value would be stored (in plaintext) in your terraform state file. You could use [AWS KMS](https://aws.amazon.com/kms/) to store the secret and retrieve it from there via your lambda. – Jarred Olson Oct 27 '18 at 14:08
  • 1
    You can add the variable file and terraform state file to gitignore and this solves the problem. – Mithilesh_Kunal Oct 30 '18 at 06:18
  • In terraform v0.12.16 (and probably earlier versions) the `=` in `environment = {` is not required, and will result in an error of `"An argument named "environment" is not expected here. Did you mean to define a block of type "environment"?"` – James P McGrath Feb 24 '20 at 05:13
  • 2
    @JamesPMcGrath Looking at the documentation it appears it should be `environment {` and not `environment = {` I updated the code sample, can you verify that works for you? – Jarred Olson Feb 25 '20 at 01:36
  • @JarredOlson LGTM! :shipit: – James P McGrath Feb 25 '20 at 07:23
  • Hehe I also feel for the environment = thing. Pretty weird that its a sub-ressource https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_function#example-usage – Dukeatcoding Feb 22 '23 at 07:57
6

You can use aws secret manager to store your data. more info. to use them in your terraform follow below steps:

  1. Store your sensitive data such as passwords and api keys.
  2. Add "aws_secretsmanager_secret" data to your terraform, more info
  3. Add "aws_secretsmanager_secret_version" based on the secret from the previous step. more info
  4. Assuming your secret are stored in a key-value structure use

${jsondecode(data.aws_secretsmanager_secret_version.secrets.secret_string)["YOUR_KEY"]}

Ahmad Alhyari
  • 111
  • 2
  • 3
2

If you want to pass a super_secret_value in terraform then instead passing through a tfvars file, you might want to consider using Vault or AWS Secret Manager.

But, even if you use Vault or AWS Secret Manager, secrets maybe be visible in tfstate file. But to mitigate the risk, you can encrypt the tfstate file on S3 and put restrict policy so that only required people can access this state file.

Pradeep Bhadani
  • 4,435
  • 6
  • 29
  • 48
2

If you have, like for most traditional NodeJS app, en .env file that is loaded with dotenv locally, here is a trick to proxy those variables into your Terraform files as variables:

env $(sed -e 's/^/TF_VAR_/' ../../.env.preproduction) terraform plan \
 -out=terraform-preproduction.plan

Then, just declare the env vars as variables and use them:

variable "SECRET" {
  description = "The application SECRET env var"
}

resource "aws_lambda_function" "test_lambda" {
  filename         = "lambda_function_payload.zip"
  function_name    = "lambda_function_name"
  runtime          = "nodejs8.10"
  ...

  environment {
    variables = {
      api_key = "${var.SECRET}"
    }
  }
}
nfroidure
  • 1,531
  • 12
  • 20
  • 1
    use `environment {...} ` instead of `environment = { ...` – Mobigital Aug 26 '20 at 16:52
  • 1
    Thanks. FYI, I went a bit further in the automation by also generating the env vars map: https://github.com/nfroidure/whook/pull/54/files#diff-2a66f75ad5e713df773ad171190ef5edR93-R98 The list is generated via a script used as a data source : https://github.com/nfroidure/whook/pull/54/files#diff-2a66f75ad5e713df773ad171190ef5edR67-R69 – nfroidure Aug 30 '20 at 14:05