Terraform: Why is null_resource's remote-exec not connecting to aws_instance via SSH?



  • I've been going through answers to similar questions on this StackExchange and on StackOverflow and reading through documentations all day ...

    Here's the .tf file I'm executing:

    # defines the AWS provider
    provider "aws" {
      # credentials path: ~/.aws/credentials
      profile = var.aws_profile
    }
    resource "aws_key_pair" "key_pair" {
      # variable's default value: "id_rsa"
      key_name   = var.aws_key_pair_name
      # variable's default value: public key of "id_rsa"
      public_key = var.aws_key_pair_public
    }
    resource "aws_security_group" "security_group" {
      ingress {
        from_port = 22
        to_port = 22
        protocol = "tcp"
        cidr_blocks = ["0.0.0.0/0"]
      }
      egress {
        from_port = 0
        to_port = 0
        protocol = "-1"
        cidr_blocks = ["0.0.0.0/0"]
      }
      tags = {
        # variable's default value: "security-group-1"
        Name = var.aws_security_group_tags_name
      }
    }
    resource "aws_instance" "instance" {
      # variable's default value: ID of the Ubuntu AMI
      ami = var.aws_instance_ami
      # variable's default value: "t2.micro"
      instance_type = var.aws_instance_type
      associate_public_ip_address  = true
      key_name = aws_key_pair.key_pair.key_name
      vpc_security_group_ids = [aws_security_group.security_group.id]
      tags = {
        # variable's default value: "ec2-instance-1"
        Name = var.aws_instance_tags_name
      }
    }
    resource "null_resource" "instance" {
      provisioner "remote-exec" {
        connection  {
          type = "ssh"
          host = aws_instance.instance.public_ip
          # variable's default value: "ubuntu", Ubuntu AMI's default system user account
          user = var.aws_instance_user_name
          # variable's default value: "~/.ssh/id_rsa"
          # the path to the public key provided to aws_key_pair.key_pair
          private_key = file(var.aws_key_pair_private_path)
          timeout = "20s"
        }
        inline = ["echo 'remote-exec message'"]
      }
      provisioner "local-exec" {
        command = "echo 'local-exec message'"
      }
    }
    

    I tried executing it with the permissions of the private key's file set to 400 and 600. It's returning the following error in both cases:

    aws_instance.instance (remote-exec): Connecting to remote host via SSH...
    aws_instance.instance (remote-exec):   Host: 54.82.23.158
    aws_instance.instance (remote-exec):   User: ubuntu
    aws_instance.instance (remote-exec):   Password: false
    aws_instance.instance (remote-exec):   Private key: true
    aws_instance.instance (remote-exec):   Certificate: false
    aws_instance.instance (remote-exec):   SSH Agent: true
    aws_instance.instance (remote-exec):   Checking Host Key: false
    aws_instance.instance (remote-exec):   Target Platform: unix
    aws_instance.instance: Still creating... [1m0s elapsed]
    ╷
    │ Error: remote-exec provisioner error
    │ 
    │   with aws_instance.instance,
    │   on main.tf line 63, in resource "aws_instance" "instance":
    │   63:   provisioner "remote-exec" {
    │ 
    │ timeout - last error: SSH authentication failed (ubuntu@54.82.23.158:22): ssh: handshake failed: ssh: unable to
    │ authenticate, attempted methods [none publickey], no supported methods remain
    

    This is despite of the fact that the following command connects to the EC2 instance successfully:

    ubuntu:~/projects/course-1/project-1$ ssh -i "id_rsa" ubuntu@ec2-54-163-199-195.compute-1.amazonaws.com
    

    What am I missing? Is there a better apprach?



  • You need to change remote-exec syntax a bit. First, establish a connection to the remote server then execute with the provisioner as:

        resource "null_resource" "instance" {
          connection  {
            type = "ssh"
            host = aws_instance.instance.public_ip
            # variable's default value: "ubuntu", Ubuntu AMI's default system user account
            user = var.aws_instance_user_name
            # variable's default value: "~/.ssh/id_rsa"
            # the path to the public key provided to aws_key_pair.key_pair
            private_key = file(var.aws_key_pair_private_path)
            timeout = "20s"
          }
          provisioner "remote-exec" {
            inline = ["echo 'remote-exec message'"]
          }
          provisioner "local-exec" {
            command = "echo 'local-exec message'"
          }
        }
    

    This should fix your problem. Thank you!




Suggested Topics

  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2