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.72k stars 9.55k forks source link

Tries to connect to $SSH_AUTH_SOCK even when private key provided #29074

Open camscale opened 3 years ago

camscale commented 3 years ago

When using the file provisioner with an SSH connection, terraform will attempt to connect to the ssh-agent specified in $SSH_AUTH_SOCK even if the private key is provided via the private_key field of the provisioner.connection block. Sometimes my $SSH_AUTH_SOCK is invalid (I have reconnected to a tmux session from elsewhere), but this should make no difference as the private key (unencrypted) is explicitly provided and not in the ssh-agent keystore.

If I unset the $SSH_AUTH_SOCK environment variable, terraform successfully provisions the file via ssh.

Terraform Version

Terraform v1.0.1
on linux_amd64
+ provider registry.terraform.io/hashicorp/aws v3.47.0

Terraform Configuration Files

terraform {
  backend "local" {
  }
}

provider "aws" {
  region = "us-east-1"
}

data "aws_ami" "ubuntu" {
  filter {
    name   = "name"
    values = ["ubuntu/images/hvm-ssd/ubuntu-bionic-18.04-amd64-server-20200810"]
  }
  owners = ["099720109477"] # Canonical
}

resource "aws_key_pair" "test" {
  key_name   = "test"
  public_key = file("id_rsa.pub")
}

resource "aws_security_group" "test" {
  name        = "test"
  description = "Allow inbound SSH"

  ingress {
    from_port        = 22
    to_port          = 22
    protocol         = "tcp"
    cidr_blocks      = ["0.0.0.0/0"]
    ipv6_cidr_blocks = ["::/0"]
  }
}

resource "aws_instance" "test" {
  instance_type = "t3a.medium"
  ami           = data.aws_ami.ubuntu.id
  key_name      = aws_key_pair.test.key_name

  vpc_security_group_ids = [aws_security_group.test.id]

  provisioner "file" {
    destination = "/home/ubuntu/testfile"
    content     = "testfile\n"
    connection {
      type        = "ssh"
      user        = "ubuntu"
      private_key = file("id_rsa")
      host        = self.public_ip
    }
  }
}

Debug Output

[...]
Plan: 3 to add, 0 to change, 0 to destroy.
aws_key_pair.test: Creating...
aws_security_group.test: Creating...
aws_key_pair.test: Creation complete after 2s [id=test]
aws_security_group.test: Creation complete after 8s [id=sg-0586eadd2536fcdeb]
aws_instance.test: Creating...
aws_instance.test: Still creating... [10s elapsed]
aws_instance.test: Still creating... [20s elapsed]
aws_instance.test: Provisioning with 'file'...
╷
│ Error: file provisioner error
│
│   with aws_instance.test,
│   on main.tf line 43, in resource "aws_instance" "test":
│   43:   provisioner "file" {
│
│ Error connecting to SSH_AUTH_SOCK: dial unix /non-existent: connect: no such file or
│ directory
╵

Expected Behavior

Terraform should use the provided ssh key in the provider block and not try to connect to the ssh-agent specified in $SSH_AUTH_SOCK.

Actual Behavior

Terraform fails to provision a file using the file provisioner and exits with an error.

Steps to Reproduce

$ ssh-keygen -t rsa -b 4096 -N '' -C 'default-login' -f id_rsa
[...]
$ export SSH_AUTH_SOCK=/non-existent
$ terraform-1.0.1 init
[...]
$ terraform-1.0.1 apply -auto-approve
[...]
kamorozov commented 2 years ago

Hello, I have the same problem when trying to create droplet and after set password for user.

resource "digitalocean_droplet" "test" {
  count = var.number_of_vps
  image  = "ubuntu-18-04-x64"
  name   = "kamorozov-test-1"
  region = data.digitalocean_regions.available.regions[0].slug
  size   = "s-1vcpu-1gb"
  ssh_keys = [data.digitalocean_ssh_keys.rebrain_key.ssh_keys[0].id, digitalocean_ssh_key.kamorozov.id]
  tags = ["devops", local.email_for_tag]

  connection {
    type = "ssh"
    host = self.ipv4_address
    # private_key = file(var.path_to_personal_private_key)
  }

  provisioner "remote-exec" {
    inline = [
      # "echo \"root:${var.root_pwd}\" | sudo chpasswd"
      "cat /etc/os-*"
    ]
  }
}

│ Error: remote-exec provisioner error
│ 
│   with digitalocean_droplet.test[1],
│   on main.tf line 68, in resource "digitalocean_droplet" "test":
│   68:   provisioner "remote-exec" {
│ 
│ Error connecting to SSH_AUTH_SOCK: dial unix
│ /private/tmp/com.apple.launchd.N8U5ixswMY/Listeners: connect: no such file
│ or directory
╵
╷
│ Error: remote-exec provisioner error
│ 
│   with digitalocean_droplet.test[0],
│   on main.tf line 68, in resource "digitalocean_droplet" "test":
│   68:   provisioner "remote-exec" {
│ 
│ Error connecting to SSH_AUTH_SOCK: dial unix
│ /private/tmp/com.apple.launchd.N8U5ixswMY/Listeners: connect: no such file
│ or directory

What is wrong?

adysahu90 commented 2 years ago

I tried restarting macbook and magically it started working.

ravan commented 2 years ago

I added agent = false to get it working.

connection {
      type        = "ssh"
      host        = self.public_ip
      user        = "xxx"
      agent       = false
      private_key = file("xxx.pem")
      timeout     = "4m"
  }