【问题标题】:terraform data source external with bash script throwing error with JSON structure使用 bash 脚本在 JSON 结构中抛出错误的 terraform 数据源外部
【发布时间】:2021-12-02 15:34:48
【问题描述】:

通过外部 terraform 数据源执行我的 (bash) shell 脚本时出现错误。 这是我的地形代码

resource "random_id" "win_serv" {
  byte_length = 4
}

locals {
  username = "kerbuser1"
}

resource "google_compute_instance" "win_serv_instance" {
  project      = "burnished-fold-328804"
  name         = "krb-test-${random_id.win_serv.hex}"
  machine_type = "e2-standard-2"
  zone         = "us-central1-b"

  metadata = {
    windows-startup-script-ps1 = <<EOT
# Installing IIS
Import-Module servermanager
Install-WindowsFeature Web-Server -IncludeAllSubFeature

# Ensure the directory exists
if (-not (Test-Path("C:\inetpub\wwwroot"))) {New-Item "C:\inetpub\wwwroot" -Type Directory}

# Write the expanded string out to the file, overwriting the file if it already exists.
"<html><body><p>Windows startup script added directly.</p></body></html>" | Out-File -FilePath C:\inetpub\wwwroot\index.html -Encoding ascii -Force
EOT
  }

  boot_disk {
    initialize_params {
      image = "windows-server-2004-dc-core-v20211115"
      size  = "50"
      type = "pd-ssd"
    }
  }

  allow_stopping_for_update = true

  network_interface {
    network = "default"
  }

  service_account {
    email  = "292284418153-compute@developer.gserviceaccount.com"
    scopes = ["cloud-platform"]
  }
}

data "external" "kerb_auth" {
  program = [ "bash", "${path.module}/kerb_auth.sh" ]
  query = {
    ZONE     = "us-central1-b"
    ID       = "burnished-fold-328804"
    HOSTNAME = "${google_compute_instance.win_serv_instance.name}"
  }
}

这是我的 bash shell 脚本

#!/bin/bash

USERNAME="kerbuser1"
USER_EMAIL="kerbuser1@f5lbu.com"
EXPIRE_DATE=$(date --date='now +10 minutes' +%Y-%m-%dT%H:%M:%SZ)
WORKING_DIR="/tmp/krbloc"

#Variables provided in external block query format of the instance tf template
eval "$(jq -r '@sh "HOSTNAME=\(.HOSTNAME) ZONE=\(.ZONE) ID=\(.ID)"')"

# generate rsa public and private keys
mkdir -p ${WORKING_DIR}
cd ${WORKING_DIR}
openssl genrsa -out private_key 2048 > /dev/null 2>&1
openssl rsa -pubout -in private_key -out public_key > /dev/null 2>&1
openssl rsa -in public_key -pubin -text -noout

MODULUS=$(cat public_key | grep -v -- ----- | base64 -d | dd bs=1 skip=33 count=256 2>/dev/null | base64 -w 0; echo)
EXPONENT=$(cat public_key | grep -v -- ----- | base64 -d | dd bs=1 skip=291 count=3 2>/dev/null | base64)

printf '{"userName": "%s", "modulus": "%s", "exponent": "%s", "expireOn": "%s", "email": "%s"}' "${USERNAME}" "${MODULUS}" "${EXPONENT}" "${EXPIRE_DATE}" "${USER_EMAIL}" > metadata_payload.json

if [[ -f metadata_payload.json ]]; then
  gcloud compute instances add-metadata ${HOSTNAME} --project ${ID} --zone ${ZONE} --metadata-from-file="windows-keys=metadata_payload.json"

else
  echo "Payload file not found."
fi

KRB=$(gcloud compute instances get-serial-port-output ${HOSTNAME} --project=${ID} --zone=${ZONE} --port=4 | jq -r -c --arg MODULUS $MODULUS 'select(.modulus == $MODULUS) | .encryptedPassword')

PAS=$(echo $KRB | base64 -d | openssl rsautl -decrypt -inkey private_key -oaep)

jq -n --arg passwd "$PAS" '{"password":$passwd}'

手动执行脚本时,我没有发现任何问题。 但是从 terraform 执行时出现错误 我怀疑这是因为我在 shell 脚本中返回的密码有特殊字符。 我尝试过更改引号和转义字符,但没有成功。

data.external.kerb_auth: Reading...
╷
│ Error: command "bash" produced invalid JSON: invalid character 'R' looking for beginning of value
│
│   with data.external.kerb_auth,
│   on main.tf line 76, in data "external" "kerb_auth":
│   76: data "external" "kerb_auth" {
│
╵

【问题讨论】:

  • 你试过什么?您是否尝试过隔离问题?尝试创建一个最小示例stackoverflow.com/help/minimal-reproducible-example jq 看起来不错,您的脚本似乎更有可能在运行 jq 之前输出额外的东西。但我不能为你调试所有这些。

标签: terraform jq


【解决方案1】:

对不起,详细的问题...但感谢您的线索... 我发现了这个问题,如果你通过外部数据源从 terraform 运行 shell 脚本,那么它期望脚本的输出应该用 Json 格式化。
我的脚本从几个 gcloud 命令返回一个输出

-问题-1

openssl rsa -in public_key -pubin -text -noout 


它返回 private 的编码版本,但我从这个命令中获取任何输入,所以我从脚本中删除了这个命令。

-问题2

gcloud compute instances add-metadata ${HOSTNAME} --project ${ID} --zone ${ZONE} --metadata-from-file="windows-keys=metadata_payload.json"


它返回一个更新状态,我更新如下

gcloud compute instances add-metadata ${HOSTNAME} --project ${ID} --zone ${ZONE} --metadata-from-file="windows-keys=metadata_payload.json" >/dev/null 2>&1

-问题3

gcloud compute instances get-serial-port-output ${HOSTNAME} --project=${ID} --zone=${ZONE} --port=4


它返回一个异常,我对此进行了如下更新

gcloud compute instances get-serial-port-output ${HOSTNAME} --project=${ID} --zone=${ZONE} --port=4 2>/dev/null

【讨论】:

    猜你喜欢
    • 2021-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-07
    • 2018-08-18
    • 1970-01-01
    相关资源
    最近更新 更多