GitHub Actions中Terraform传递敏感变量至ECS任务定义遇JSON错误
错误原因
你碰到的invalid character 'v' looking for beginning of value错误,说白了就是Terraform没把var.CONTAINER_CONFIG的实际值插到heredoc的JSON里,反而把var.CONTAINER_CONFIG这个字符串直接写进了JSON,导致JSON解析器读到开头的'v'就报错了。常见问题要么是GitHub Actions里环境变量没设对,要么是Terraform里的插值方式不对。
分步解决办法
1. 确认GitHub Actions的环境变量设置
在你的Actions配置yml里,要保证TF_VAR_CONTAINER_CONFIG正确引用了Secrets,而且Secrets里存的是原始的JSON字符串(不用额外转义,GitHub Secrets会自动处理):
jobs: terraform-apply: runs-on: ubuntu-latest steps: - name: 拉取代码 uses: actions/checkout@v4 - name: 配置Terraform环境 uses: hashicorp/setup-terraform@v3 - name: 执行Terraform Apply env: TF_VAR_CONTAINER_CONFIG: ${{ secrets.CONTAINER_CONFIG }} AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} run: terraform apply -auto-approve
2. 修正Terraform里container_definitions的写法
方法一:用jsonencode和jsondecode处理(推荐,最稳妥)
如果var.CONTAINER_CONFIG本身是合法的JSON字符串(比如{"key": "secret-value"}),别直接往heredoc里插,先把它解析成JSON对象,再用jsonencode生成合法的JSON:
# vars.tf 里的变量定义 variable "CONTAINER_CONFIG" { type = string sensitive = true description = "容器的敏感配置JSON字符串" } # main.tf 里的ECS任务定义资源 resource "aws_ecs_task_definition" "my_task" { family = "my-task" network_mode = "awsvpc" requires_compatibilities = ["FARGATE"] cpu = "256" memory = "512" execution_role_arn = aws_iam_role.ecs_execution_role.arn task_role_arn = aws_iam_role.ecs_task_role.arn # 先把字符串变量解析成JSON对象,再整体编码成合法的container_definitions JSON container_definitions = jsonencode([ { name = "my-container" image = "my-image:latest" essential = true # 直接用解析后的JSON对象 environment = jsondecode(var.CONTAINER_CONFIG) # 如果是其他字段比如secrets、command,按需替换就行 } ]) }
这种方式完全避开了heredoc的插值坑,用Terraform自带的JSON工具函数保证格式绝对合法。
方法二:修正heredoc插值(不推荐,容易踩坑)
要是非得用heredoc,得保证var.CONTAINER_CONFIG是不带外层引号的纯JSON内容(比如{"KEY": "VALUE"},不是"{\"KEY\": \"VALUE\"}"这种带转义引号的字符串),然后直接插:
container_definitions = <<EOF [ { "name": "my-container", "image": "my-image:latest", "essential": true, "environment": ${var.CONTAINER_CONFIG} } ] EOF
⚠️ 注意:如果你的GitHub Secrets里存的是带转义引号的字符串,得先在Terraform里用jsondecode(var.CONTAINER_CONFIG)处理后再插,不然还是会报错。
3. 验证变量是否正确传递
在GitHub Actions里加个调试步骤,确认变量有没有传对(注意敏感信息别直接echo):
- name: 验证Terraform变量 env: TF_VAR_CONTAINER_CONFIG: ${{ secrets.CONTAINER_CONFIG }} run: terraform console -var="CONTAINER_CONFIG=$TF_VAR_CONTAINER_CONFIG" <<< "jsondecode(var.CONTAINER_CONFIG)"
如果输出是合法的JSON对象,说明变量传递没问题。
重要提醒
- 敏感变量一定要在
vars.tf里加sensitive = true,防止Terraform输出敏感内容 - 处理JSON相关的变量,尽量用
jsonencode和jsondecode,手动拼JSON很容易出格式错误 - GitHub Secrets里存JSON的时候,直接存原始JSON就行,不用额外转义引号
内容的提问来源于stack exchange,提问作者x89

