hashicorp / terraform

Terraform enables you to safely and predictably create, change, and improve infrastructure. It is a source-available tool that codifies APIs into declarative configuration files that can be shared amongst team members, treated as code, edited, reviewed, and versioned.
https://www.terraform.io/
Other
42.29k stars 9.49k forks source link

ssh provisioner connection doesn't allow specification of no key for bastion connection #17393

Open lexelby opened 6 years ago

lexelby commented 6 years ago

Terraform Version

0.11.2

Terraform Configuration Files

resource "google_compute_instance" "myhost" {
  ...
  provisioner "chef" {
    connection {
      type = "ssh"

      private_key = "key for connection to the host"

      // no way to specify that ssh-agent should be used
      bastion_private_key = "?"
    }
  }
}

Expected Behavior

I'd like to be able to specify an SSH key for the connection to the actual host, but not specify one for the connection to the bastion. The bastion connection should use a key from my ssh agent.

Actual Behavior

Due to the way the SSH provisioner connection code is written, specifying no bastion_private_key or specifying bastion_private_key = "" both cause the main private_key to be used for the bastion connection.

apparentlymart commented 6 years ago

Hi @lexelby! Sorry things aren't quite right here.

Currently Terraform struggles in general with situations where you want to override its defaults with the absence of a value. This should get better in the forthcoming configuration language improvements we're working on right now (which allow you to assign null to an attribute), though we may need to do some follow-up work on the provisioners in particular to make them aware of the new capability.

In the mean time, I'm curious to know what the actual behavior is for you right now. I would expect that the bastion host would just ignore the mismatching key and proceed with some other possible authentication mechanism, but I assume that isn't actually working in this case. It may be possible for us to make a more tactical short-term change to address whatever is preventing the automatic fallback to other authentication modes.

lexelby commented 6 years ago

Ah! I was wondering about a null. Thanks for explaining the situation to me.

Actual behavior I observed was that it attempted to connect to the bastion host using the main private_key multiple times, failing each time. It appeared not to attempt to try the key in my SSH agent, but I am not certain of this. It's possible that my main key had timed out in my SSH agent, making it unavailable. I switched to putting the key for the end host into my ssh agent and not specifying a private_key or bastion_private_key and that worked. Sorry I don't have complete confidence on this information.

apparentlymart commented 6 years ago

Hi @lexelby!

Ahh... SSH agents in the mix does make things trickier, since we'll only ever try one key and, as you've seen, we apparently try the wrong one.

Unfortunately addressing that will probably require a breaking change, at least if we want to make it work as you expected within the current syntax.

Another option would be to implement this in conjunction with introducing a new bastion nested config block as discussed in #16933. Since that introduces an entirely new syntax, we are free to introduce new behavior along with it. I think it'd make sense for the bastion blocks to never inherit key information from the main block automatically and instead just have the user specify the same private_key value for both the connection attribute and the bastion block attribute if they are the same, under the principle that explicit is better than implicit.

connection {
  # ...
  private_key = "${file("${path.module}/private_key")}"

  bastion {
    host        = "bastion.example.com"
    private_key = "${file("${path.module}/private_key")}"
  }
}

Being able to add this new nested block is dependent on some other changes to how the configuration is processed, so we won't be able to act on this immediately.

In the mean time I suppose we could add a bastion_agent = true option to force use of agent for the bastion, so we don't need to block waiting for the configuration language capabilities to catch up. We could then deprecate that along with the other bastion_* options once the bastion config block is introduced. The Terraform team at HashiCorp won't be able to work on this in the near future due to our focus being elsewhere, but we'd be happy to review a pull request if you or someone else has the time and motivation to implement it.

lexelby commented 6 years ago

I think it'd make sense for the bastion blocks to never inherit key information from the main block automatically and instead just have the user specify the same private_key value for both the connection attribute and the bastion block attribute if they are the same, under the principle that explicit is better than implicit.

That sounds ideal!

Since I found a workaround, I don't need your bastion_agent solution, but thanks for the suggestion. I'm satisfied with waiting for the bastion sub-block you outlined above.

jan-g commented 2 years ago

Was there ever any movement on this?

I'd also like my bastion to default to ssh-agent settings, and the target host to use alternative credentials supplied by this configuration.