Shell script containing Terraform Directives causing an error

Hi @apparentlymart , thanks for your reponse! I actually found a workaround for this problem. I removed the for loop inside the .hcl file, and worked on a shell script to replace this part. I’ll attach the whole userdata.sh file for those who will be curious. controllers = [ $NEW_VAR ] is the part that replaced the for loop.

#!/bin/bash

# Installing essential packages
apt update -y
apt install -y \
  unzip

# Values from Terraform
BOUNDARY_TLS_KEY_PATH="/etc/pki/tls/boundary/boundary.key"
BOUNDARY_TLS_CERT_PATH="/etc/pki/tls/boundary/boundary.cert"
BOUNDARY_TLS_DISABLED=${conf_tls_disabled}
BOUNDARY_KMS_TYPE=${conf_kms_type}
BOUNDARY_KMS_WORKER_AUTH_KEY_ID=${conf_kms_worker_auth_key_id}

BOUNDARY_CONTROLLER_IPS=${conf_controller_ips}
BOUNDARY_NAME_SUFFIX=${conf_name_suffix}
BOUNDARY_PUBLIC_IP=$(curl http://169.254.169.254/latest/meta-data/public-ipv4)
BOUNDARY_PRIVATE_IP=$(curl http://169.254.169.254/latest/meta-data/local-ipv4)

IFS="," read -a controller_ips <<< $BOUNDARY_CONTROLLER_IPS
NEW_VAR=$(printf "\"%s\",,\n" $${controller_ips[@]} | sed 's/.$//')

sudo mkdir -p /etc/pki/tls/boundary
cat > $BOUNDARY_TLS_KEY_PATH << EOF
${conf_tls_private_key}
EOF
cat > $BOUNDARY_TLS_CERT_PATH << EOF
${conf_tls_self_signed_cert}
EOF

curl https://releases.hashicorp.com/boundary/0.1.2/boundary_0.1.2_linux_amd64.zip --output /home/ubuntu/boundary.zip && unzip /home/ubuntu/boundary.zip -d /home/ubuntu
sudo mv /home/ubuntu/boundary /usr/local/bin/boundary
sudo chmod 0755 /usr/local/bin/boundary

cat > /home/ubuntu/boundary-worker.hcl << EOF
listener "tcp" {
  address = "$BOUNDARY_PRIVATE_IP:9202"
	purpose = "proxy"
%{ if "$BOUNDARY_TLS_DISABLED" == true }
	tls_disable                       = true
%{ else }
  tls_disable   = false
  tls_cert_file = "$BOUNDARY_TLS_CERT_PATH"  
  tls_key_file  = "$BOUNDARY_TLS_KEY_PATH"
%{ endif }

	#proxy_protocol_behavior = "allow_authorized"
	#proxy_protocol_authorized_addrs = "127.0.0.1"
}

worker {
  # Name attr must be unique
	public_addr = "$BOUNDARY_PUBLIC_IP"
	name = "demo-worker-$BOUNDARY_NAME_SUFFIX"
	description = "A default worker created for demonstration"
	controllers = [
	$NEW_VAR
  ]
}

%{ if "$BOUNDARY_KMS_TYPE" == "aws" }
kms "awskms" {
	purpose    = "worker-auth"
	key_id     = "global_root"
  kms_key_id = "$BOUNDARY_KMS_WORKER_AUTH_KEY_ID"
}
%{ else }
kms "aead" {
	purpose = "worker-auth"
	aead_type = "aes-gcm"
	key = "8fZBjCUfN0TzjEGLQldGY4+iE9AkOvCfjh7+p0GtRBQ="
	key_id = "global_worker-auth"
}
%{ endif }
EOF

sudo mv /home/ubuntu/boundary-worker.hcl /etc/boundary-worker.hcl

TYPE=worker
NAME=boundary

sudo cat << EOF > /etc/systemd/system/$NAME-$TYPE.service
[Unit]
Description=$NAME $TYPE
[Service]
ExecStart=/usr/local/bin/$NAME server -config /etc/$NAME-$TYPE.hcl
User=boundary
Group=boundary
LimitMEMLOCK=infinity
Capabilities=CAP_IPC_LOCK+ep
CapabilityBoundingSet=CAP_SYSLOG CAP_IPC_LOCK
[Install]
WantedBy=multi-user.target
EOF

# Add the boundary system user and group to ensure we have a no-login
# user capable of owning and running Boundary
sudo adduser --system --group boundary || true
sudo chown boundary:boundary /etc/$NAME-$TYPE.hcl
sudo chown boundary:boundary /usr/local/bin/boundary

# Make sure to initialize the DB before starting the service. This will result in
# a database already initizalized warning if another controller or worker has done this 
# already, making it a lazy, best effort initialization
if [ "$TYPE" = "controller" ]; then
  sudo /usr/local/bin/boundary database init -skip-auth-method-creation -skip-host-resources-creation -skip-scopes-creation -skip-target-creation -config /etc/$NAME-$TYPE.hcl || true
fi

sudo chmod 664 /etc/systemd/system/$NAME-$TYPE.service
sudo systemctl daemon-reload
sudo systemctl enable $NAME-$TYPE
sudo systemctl start $NAME-$TYPE

The ec2.tf that is using the userdata script above is as below.

resource "aws_instance" "worker" {
  count                       = var.num_workers
  ami                         = data.aws_ami.ubuntu.id
  instance_type               = "t3.micro"
  iam_instance_profile        = aws_iam_instance_profile.boundary.name
  subnet_id                   = data.terraform_remote_state.network.outputs.tokyo_vpc_main.public_subnet_ids[count.index]
  key_name                    = aws_key_pair.boundary.key_name
  vpc_security_group_ids      = [aws_security_group.worker.id]
  associate_public_ip_address = true

  user_data = base64encode(templatefile(
    "${path.module}/userdata_worker.sh", {
      conf_tls_private_key        = tls_private_key.boundary.private_key_pem
      conf_tls_self_signed_cert   = tls_self_signed_cert.boundary.cert_pem
      conf_tls_key_path           = var.tls_key_path
      conf_tls_cert_path          = var.tls_cert_path
      conf_controller_ips         = join(",", aws_instance.controller.*.private_ip)
      conf_name_suffix            = count.index
      conf_tls_disabled           = var.tls_disabled
      conf_kms_type               = var.kms_type
      conf_kms_worker_auth_key_id = aws_kms_key.worker_auth.id
    }
  ))

  tags = merge(local.common_tags, {
    Name = "boundary-${terraform.workspace}-worker-instance"
  })

  depends_on = [aws_instance.controller]
}

Though I found a workaround to the for loop problem in this post, I’m now having trouble with if statement inside .hcl file, where the problem was hidden due to the for loop.

I posted this new problem on a separate issue, HCL in userdata.sh unable to interpret shell script variables

Thank you very much ! :smile: