How can I get terraforms extern to execute `ssh-keygen -y -f ~/.ssh/id_rsa`? I seem to be confused about how external works. I tried:

data "external" "local_key" {
  program = [
    "ssh-keygen", "-y", "-f ~/.ssh/id_rsa"
  ]
}


This gives me:


  failed to execute "ssh-keygen":  ~/.ssh/id_rsa: No such file or directory


Which presumably happens because ~ expansion doesn't. ssh-keygen -y -f ~/.ssh/id_rsa works normally. So instead I tried invoking bash like:

data "external" "local_key" {
  program = [
    "bash"
  ]

  query {
    "-c" = "ssh-keygen -y -f ~/.ssh/id_rsa"
  }
}


I'm still getting the same issue. I realize I can just pass the output as a var to terraform from the outside, but I'm still curious what the solution is.
So what happens in first case is, as Dan's already said, there's no shell used and as such nothing to expand the ~. Quoting the documentation about program:


  Terraform does not execute the program through a shell


On the second case, bash receive in stdin something like this:

{ "-c": "ssh-keygen -y -f ~/.ssh/id_rsa" }


And this looks like a command block for bash, but -c is not a valid command.

What could work could be this kind of program (assuming no specific input):

jq -n --arg pubkey "$(ssh-keygen -y -f ~/.ssh/id_rsa)" '{"pubkey":$pubkey}'


So something like this should work to get the key in local_key["pubkey"] if I understand the documentation properly:

data "external" "local_key" {
  program = [
    "bash", "-c jq -n --arg pubkey \"$(ssh-keygen -y -f ~/.ssh/id_rsa)\" '{\"pubkey\":$pubkey}'"
  ]
}


There's a need to use bash for a one liner to take advantage of command subsitution. You can also do a .sh script like:

#!/bin/sh
jq -n --arg pubkey "$(ssh-keygen -y -f ~/.ssh/id_rsa)" '{\"pubkey\":$pubkey}'


And call this script in the program parameter.