Why can't terraform SSH in to EC2 Instance using supplied example?
Asked Answered
A

7

10

I'm using the AWS Two-tier example and I've direct copy-n-pasted the whole thing. terraform apply works right up to where it tries to SSH into the created EC2 instance. It loops several times giving this output before finally failing.

aws_instance.web (remote-exec): Connecting to remote host via SSH...
aws_instance.web (remote-exec):   Host: 54.174.8.144
aws_instance.web (remote-exec):   User: ubuntu
aws_instance.web (remote-exec):   Password: false
aws_instance.web (remote-exec):   Private key: false
aws_instance.web (remote-exec):   SSH Agent: true

Ultimately, it fails w/:

Error applying plan:

1 error(s) occurred:

* ssh: handshake failed: ssh: unable to authenticate, attempted methods [none publickey], no supported methods remain

Terraform does not automatically rollback in the face of errors.
Instead, your Terraform state file has been partially updated with
any resources that successfully completed. Please address the error
above and apply again to incrementally change your infrastructure.

I've searched around and seen some older posts/issues saying flip agent=false and I've tried that also w/ no changes or success. I'm skeptical that this example is broky out of the box yet I've done no tailoring or modifications that could have broken it. I'm using terraform 0.6.11 installed via homebrew on OS X 10.10.5.

Additional detail:

resource "aws_instance" "web" {
  # The connection block tells our provisioner how to
  # communicate with the resource (instance)
  connection {
    # The default username for our AMI
    user = "ubuntu"

    # The connection will use the local SSH agent for authentication.
    agent = false
  }

  instance_type = "t1.micro"

  # Lookup the correct AMI based on the region
  # we specified
  ami = "${lookup(var.aws_amis, var.aws_region)}"

  # The name of our SSH keypair we created above.
  key_name = "${aws_key_pair.auth.id}"

  # Our Security group to allow HTTP and SSH access
  vpc_security_group_ids = ["${aws_security_group.default.id}"]

  # We're going to launch into the same subnet as our ELB. In a production
  # environment it's more common to have a separate private subnet for
  # backend instances.
  subnet_id = "${aws_subnet.default.id}"

  # We run a remote provisioner on the instance after creating it.
  # In this case, we just install nginx and start it. By default,
  # this should be on port 80
  provisioner "remote-exec" {
    inline = [
      "sudo apt-get -y update",
      "sudo apt-get -y install nginx",
      "sudo service nginx start"
    ]
  }
}

And from the variables tf file:

variable "key_name" {
  description = "Desired name of AWS key pair"
  default = "test-keypair"
}

variable "key_path" {
  description = "key location"
  default = "/Users/n8/dev/play/.ssh/terraform.pub"
}

but i can ssh in with this command:

ssh -i ../.ssh/terraform [email protected]
Autograph answered 13/2, 2016 at 14:42 Comment(4)
can you connect with normal ssh? Do you have the keys in your agent?Margaretamargarete
i was able to ssh in manually. i'm not sure I understand your second question so the answer is probably 'no'. Can you please explain?Autograph
Please update the question with information how can you ssh from command-line and how do you authenticate.Margaretamargarete
added some information. thanks!Autograph
M
26

You have two possibilities:

  1. Add your key to your ssh-agent:

    ssh-add ../.ssh/terraform
    

    and use agent = true in your configuration. The case should work for you

  2. Modify your configuration to use the key directly with

    secret_key = "../.ssh/terraform"
    

    or so. Please consult the documentation for more specific syntax.

Margaretamargarete answered 13/2, 2016 at 17:22 Comment(5)
@NathanHinchey feel free to use the votes for the answers that worked for you and helped you.Margaretamargarete
@Margaretamargarete I commented because this answer is over 2 years old, so I wanted to confirm that this solution was still relevant for current/near future readersCutanddried
If you have ssh-agent already setup you may just need to do ssh-addHyperparathyroidism
@PaulOdeon ssh-add adds only the keys in default location (id_(rsa|dsa|ecdsa|ed25519)), which the OP's one obviously is not.Margaretamargarete
@Margaretamargarete you're right, although that didn't apply to me and google brought me here :)Hyperparathyroidism
A
4

I had the same issue and I did following configurations

connection {
    type = "ssh"
    user = "ec2-user"
    private_key = "${file("*.pem")}"
    timeout = "2m"
    agent = false
}
Alkyne answered 2/6, 2016 at 21:17 Comment(1)
agent = false done the trick for meInquiline
C
3

Below is a complete and stand-alone resource "null_resource" with remote-exec provisioner w/ SSH connection including the necessary arguments supported by the ssh connection type:

  • private_key - The contents of an SSH key to use for the connection. These can be loaded from a file on disk using the file function. This takes preference over the password if provided.

  • type - The connection type that should be used. Valid types are ssh and winrm Defaults to ssh.

  • user - The user that we should use for the connection. Defaults to root when using type ssh and defaults to Administrator when using type winrm.

  • host - The address of the resource to connect to. This is usually specified by the provider.

  • port - The port to connect to. Defaults to 22 when using type ssh and defaults to 5985 when using type winrm.

  • timeout - The timeout to wait for the connection to become available. This defaults to 5 minutes. Should be provided as a string like 30s or 5m.

  • agent - Set to false to disable using ssh-agent to authenticate. On Windows the only supported SSH authentication agent is Pageant.

resource null_resource w/ remote-exec example code below:

resource "null_resource" "ec2-ssh-connection" {
  provisioner "remote-exec" {
    inline = [
      "sudo apt-get update",
      "sudo apt-get install -y python2.7 python-dev python-pip python-setuptools python-virtualenv libssl-dev vim zip"
    ]

    connection {
      host        = "100.20.30.5"  
      type        = "ssh"
      port        = 22
      user        = "ubuntu"
      private_key = "${file(/path/to/your/id_rsa_private_key)}"
      timeout     = "1m"
      agent       = false
    }
  }
}
Clerc answered 21/3, 2019 at 20:28 Comment(0)
L
1

The solution provided in https://mcmap.net/q/1040291/-why-can-39-t-terraform-ssh-in-to-ec2-instance-using-supplied-example was not working for me so I tried more ways and found the issue was with the keypair type I am using.

I was using the RSA keypair type and because of that I was getting an error

  • ssh: handshake failed: ssh: unable to authenticate, attempted methods [none publickey], no supported methods remain

I created a new key pair with the ED25519 type and it works perfectly fine with me. https://aws.amazon.com/about-aws/whats-new/2021/08/amazon-ec2-customers-ed25519-keys-authentication/

Connection block which I used

connection {
  //Use the public IP of the instance to connect to it.
  host        = self.public_ip
  type        = "ssh"
  user        = "ubuntu"
  private_key = file("pemfile-location.pem")
  timeout     = "1m"
  agent       = true
}
Luu answered 21/7, 2022 at 3:58 Comment(1)
ED25519 format works for me. Thank you!Callan
S
0
  1. Check user name that exists in the base image. For example, it can be ubuntu for Ubuntu OS, or ec2-user for AWS images.
    Alternatively, most cloud providers allow Terraform to create a new user on the first instance start with help of cloud-init config (check your provider documentation):

    metadata = {
        user-data = "${file("./user-meta-data.txt")}"
    }
    

    user-meta-data.txt:

    #cloud-config
    users:
      - name: <NEW-USER-NAME>
        groups: sudo
        shell: /bin/bash
        sudo: ['ALL=(ALL) NOPASSWD:ALL']
        ssh-authorized-keys:
        - ssh-rsa <SSH-PUBLIC-KEY>
    
  2. Increase connection timeout settings, sometimes it takes 1-2 minutes to start instance cloud network with ssh.

    connection {
       type = "ssh"
       user = "<USER_NAME>"
       private_key = "${file("pathto/id_rsa")}"
       timeout = "3m"
    }
    

If it does not work, try to connect manually via ssh with -v for verbose

ssh -v -i <path_to_private_key/id_rsa> <USER_NAME>@<INSTANCE_IP>
Simply answered 3/4, 2021 at 17:15 Comment(0)
B
0
the top answer  it does not work for me. 
the answer that use ed25519 does work for me. but not necessary to use PEM fortmat. 

here is working sample for me
  connection {
    host = "${aws_instance.example.public_ip}"
    type = "ssh"
    port = "22"
    user = "ubuntu"
    timeout = "120s"
    private_key = "${file("${var.key_location}")}"
    agent= false
  }
}

key_location="~/.ssh/id_ed25519"
Battlement answered 14/2, 2023 at 2:53 Comment(0)
S
0

i was also facing same issue, THe Issue is may be because of you are using your office system. so its unable handshake. SO create one ec2 and install terraform and run your code.

Susurrate answered 16/6 at 0:48 Comment(1)
The answer is unclear and lacks detail. Please provide more specific troubleshooting steps or clarify the solution. Also, check for grammatical errors.Ostensory

© 2022 - 2024 — McMap. All rights reserved.