2
votes

I'm creating a server in AWS using Terraform.

My remote-exec provisioner will not connect and execute, continually giving me the output:

aws_spot_instance_request.single_server_instance (remote-exec): Connecting to remote host via WinRM...
aws_spot_instance_request.single_server_instance (remote-exec):   Host: 54.219.179.241
aws_spot_instance_request.single_server_instance (remote-exec):   Port: 5985
aws_spot_instance_request.single_server_instance (remote-exec):   User: Administrator
aws_spot_instance_request.single_server_instance (remote-exec):   Password: true
aws_spot_instance_request.single_server_instance (remote-exec):   HTTPS: false
aws_spot_instance_request.single_server_instance (remote-exec):   Insecure: false
aws_spot_instance_request.single_server_instance (remote-exec):   CACert: false

Before failing with:

Error applying plan:

1 error(s) occurred:

* aws_spot_instance_request.single_server_instance: 1 error(s) occurred:

* timeout

My Resource is as follows:

resource "aws_spot_instance_request" "single_server_instance" {
  # The connection block tells our provisioner how to
  # communicate with the resource (instance)
  connection {
    type     = "winrm"
    user     = "Administrator"
    password = "${var.admin_password}"
    #insecure = true
    #port = 5985
    host = "${self.public_ip}"
    #timeout = "5m"
  }

  wait_for_fulfillment        = true
  associate_public_ip_address = true
  instance_type = "${var.aws_instance_type}"
  ami           = "${lookup(var.aws_amis, var.aws_region)}"
  spot_price    = "1.00"
  vpc_security_group_ids =  [
                              "${aws_security_group.WinRM.id}",
                              "${aws_security_group.RDP.id}"
                            ]
  key_name = "sdlweb85"

  provisioner "remote-exec" {
    inline = [
      "mkdir c:\\installs"
      #"powershell.exe Invoke-WebRequest -Uri 'https://www.dropbox.com/s/meno68gl3rfbtio/install.ps1?dl=0' -OutFile 'C:/installs/install.ps1'"
    ]
  }
  #provisioner "file" {
  #  source      = "scripts/"
  #  destination = "c:/install_scripts/"   
  #}

  user_data = <<EOF
              <powershell>
              # Configure a Windows host for remote management (this works for both Ansible and Chef)
              # You will want to copy this script to a location you own (e.g. s3 bucket) or paste it here
              Invoke-Expression ((New-Object System.Net.Webclient).DownloadString('https://raw.githubusercontent.com/ansible/ansible/devel/examples/scripts/ConfigureRemotingForAnsible.ps1'))
              # Set Administrator password
              $admin = [adsi]("WinNT://./administrator, user")
              $admin.psbase.invoke("SetPassword", "${var.admin_password}")
              Set-NetFirewallProfile -Profile Domain,Public,Private -Enabled False
              New-SelfSignedCertificate -DnsName "*.amazonaws.com" -CertStoreLocation "cert:\LocalMachine\My"
              #winrm quickconfig -quiet
              </powershell>
            EOF
}

Security Groups

resource "aws_security_group" "WinRM" {
  name        = "WinRM"

  # WinRM access from anywhere
  ingress {
    from_port   = 5985
    to_port     = 5986
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  # outbound internet access
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

resource "aws_security_group" "RDP" {
  name        = "RDP"

  # RDP access from anywhere
  ingress {
    from_port   = 3389
    to_port     = 3389
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  # outbound internet access
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

I cannot figure out the problem. From my local machine, I can connect to the remote server using

Enter-PSSession -ComputerName $ip -Credential ~\Administrator
2

2 Answers

1
votes

Winrm HTTP is disabled by default on Amazon Windows AMI. You have to run a powershell command to enable it, ansible has a nice one to do it. You can create an AMI that has winrm enabled and use that one to launch spot instances.

You can also set the provisioner in terraform to HTTPS true https://www.terraform.io/docs/provisioners/connection.html#https

1
votes

Note that terraform uses Go WinRM which doesn't support https at this time.

I had to stick with the following:

user_data = <<EOF  
<script>
  winrm quickconfig -q & winrm set winrm/config @{MaxTimeoutms="1800000"} & winrm set winrm/config/service @{AllowUnencrypted="true"} & winrm set winrm/config/service/auth @{Basic="true"}
</script>
<powershell>
  netsh advfirewall firewall add rule name="WinRM in" protocol=TCP dir=in profile=any localport=5985 remoteip=any localip=any action=allow
  # Set Administrator password
  $admin = [adsi]("WinNT://./administrator, user")
  $admin.psbase.invoke("SetPassword", "${var.admin_password}")
</powershell>
EOF