Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

communicator/ssh: Add support SSH over HTTP Proxy #30274

Merged
merged 2 commits into from Apr 27, 2022

Conversation

htamakos
Copy link
Contributor

Description

These commits support SSH over HTTP Proxy in the SSH provisioner without significantly changing the existing Pure Go SSH implementation.
I found that in #4523 #1709, the lack of support for SSH on HTTP Proxy has inconvenienced many people. I myself have to switch networks whenever I use terraform in a company network.
Therefore, I proposed this implementation.

Changes

  • add proxy_* fields to connection which add configuration for a proxy host
    • proxy_host: Setting this enables the SSH over HTTP connection. This host
      will be connected to first, and then the host or bastion_host connection will be made from there.
    • proxy_port - The port to use connect to the proxy host.
    • proxy_scheme - http or https
    • proxy_user_name - The username to use connect to the private proxy host.
    • proxy_user_password - The password to use connect to the private proxy host.

Others

You can create a test environment that connects to the test node via SSH through HTTP PROXY in the following repository.

https://github.com/htamakos/terraform-communicator-ssh-test-env

Result Example

$ ~/ghq/github.com/htamakos/terraform/terraform apply -auto-approve
null_resource.remote_exec_via_ssh_over_http_proxy_with_auth_through_bastion: Refreshing state... [id=8719430125056995160]
null_resource.remote_exec_via_ssh: Refreshing state... [id=1156678337337142727]
null_resource.remote_exec_via_ssh_over_http_proxy: Refreshing state... [id=2456805027942864311]
null_resource.remote_exec_via_ssh_over_http_proxy_through_bastion: Refreshing state... [id=2488039607822794741]
null_resource.remote_exec_via_ssh_over_http_proxy_with_auth: Refreshing state... [id=4092500202928979050]

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
-/+ destroy and then create replacement

Terraform will perform the following actions:

  # null_resource.remote_exec_via_ssh must be replaced
-/+ resource "null_resource" "remote_exec_via_ssh" {
      ~ id       = "1156678337337142727" -> (known after apply)
      ~ triggers = {
          - "build_number" = "2021-12-30T03:16:55Z"
        } -> (known after apply) # forces replacement
    }

  # null_resource.remote_exec_via_ssh_over_http_proxy must be replaced
-/+ resource "null_resource" "remote_exec_via_ssh_over_http_proxy" {
      ~ id       = "2456805027942864311" -> (known after apply)
      ~ triggers = {
          - "build_number" = "2021-12-30T03:16:56Z"
        } -> (known after apply) # forces replacement
    }

  # null_resource.remote_exec_via_ssh_over_http_proxy_through_bastion must be replaced
-/+ resource "null_resource" "remote_exec_via_ssh_over_http_proxy_through_bastion" {
      ~ id       = "2488039607822794741" -> (known after apply)
      ~ triggers = {
          - "build_number" = "2021-12-30T03:16:56Z"
        } -> (known after apply) # forces replacement
    }

  # null_resource.remote_exec_via_ssh_over_http_proxy_with_auth must be replaced
-/+ resource "null_resource" "remote_exec_via_ssh_over_http_proxy_with_auth" {
      ~ id       = "4092500202928979050" -> (known after apply)
      ~ triggers = {
          - "build_number" = "2021-12-30T03:16:56Z"
        } -> (known after apply) # forces replacement
    }

  # null_resource.remote_exec_via_ssh_over_http_proxy_with_auth_through_bastion must be replaced
-/+ resource "null_resource" "remote_exec_via_ssh_over_http_proxy_with_auth_through_bastion" {
      ~ id       = "8719430125056995160" -> (known after apply)
      ~ triggers = {
          - "build_number" = "2021-12-30T03:16:56Z"
        } -> (known after apply) # forces replacement
    }
Plan: 5 to add, 0 to change, 5 to destroy.
null_resource.remote_exec_via_ssh_over_http_proxy_with_auth: Destroying... [id=4834391650718277819]
null_resource.remote_exec_via_ssh: Destroying... [id=4727489635703643485]
null_resource.remote_exec_via_ssh_over_http_proxy_through_bastion: Destroying... [id=154493005404606358]
null_resource.remote_exec_via_ssh_over_http_proxy_with_auth_through_bastion: Destroying... [id=5750345333101675414]
null_resource.remote_exec_via_ssh_over_http_proxy: Destroying... [id=2912693274146434159]
null_resource.remote_exec_via_ssh: Destruction complete after 0s
null_resource.remote_exec_via_ssh_over_http_proxy_with_auth: Destruction complete after 0s
null_resource.remote_exec_via_ssh_over_http_proxy_with_auth_through_bastion: Destruction complete after 0s
null_resource.remote_exec_via_ssh_over_http_proxy_through_bastion: Destruction complete after 0s
null_resource.remote_exec_via_ssh_over_http_proxy: Destruction complete after 0s
null_resource.remote_exec_via_ssh: Creating...
null_resource.remote_exec_via_ssh_over_http_proxy_with_auth: Creating...
null_resource.remote_exec_via_ssh_over_http_proxy_with_auth_through_bastion: Creating...
null_resource.remote_exec_via_ssh: Provisioning with 'remote-exec'...
null_resource.remote_exec_via_ssh_over_http_proxy_with_auth: Provisioning with 'remote-exec'...
null_resource.remote_exec_via_ssh_over_http_proxy_with_auth (remote-exec): Connecting to remote host via SSH...
null_resource.remote_exec_via_ssh_over_http_proxy_with_auth (remote-exec):   Host: bas
null_resource.remote_exec_via_ssh_over_http_proxy_with_auth (remote-exec):   User: root
null_resource.remote_exec_via_ssh_over_http_proxy_with_auth (remote-exec):   Password: true
null_resource.remote_exec_via_ssh_over_http_proxy_with_auth (remote-exec):   Private key: false
null_resource.remote_exec_via_ssh_over_http_proxy_with_auth (remote-exec):   Certificate: false
null_resource.remote_exec_via_ssh_over_http_proxy_with_auth (remote-exec):   SSH Agent: false
null_resource.remote_exec_via_ssh_over_http_proxy_with_auth (remote-exec):   Checking Host Key: false
null_resource.remote_exec_via_ssh_over_http_proxy_with_auth (remote-exec):   Target Platform: unix
null_resource.remote_exec_via_ssh_over_http_proxy_with_auth (remote-exec): Using configured proxy host...
null_resource.remote_exec_via_ssh_over_http_proxy_with_auth (remote-exec):   ProxyHost: localhost
null_resource.remote_exec_via_ssh_over_http_proxy_with_auth (remote-exec):   ProxyPort: 23129
null_resource.remote_exec_via_ssh_over_http_proxy_with_auth (remote-exec):   ProxyUserName: root
null_resource.remote_exec_via_ssh_over_http_proxy_with_auth (remote-exec):   ProxyUserPassword: true
null_resource.remote_exec_via_ssh (remote-exec): Connecting to remote host via SSH...
null_resource.remote_exec_via_ssh (remote-exec):   Host: 0.0.0.0
null_resource.remote_exec_via_ssh (remote-exec):   User: root
null_resource.remote_exec_via_ssh (remote-exec):   Password: true
null_resource.remote_exec_via_ssh (remote-exec):   Private key: false
null_resource.remote_exec_via_ssh (remote-exec):   Certificate: false
null_resource.remote_exec_via_ssh (remote-exec):   SSH Agent: false
null_resource.remote_exec_via_ssh (remote-exec):   Checking Host Key: false
null_resource.remote_exec_via_ssh (remote-exec):   Target Platform: unix
null_resource.remote_exec_via_ssh_over_http_proxy: Creating...
null_resource.remote_exec_via_ssh_over_http_proxy_through_bastion: Creating...
null_resource.remote_exec_via_ssh_over_http_proxy_with_auth_through_bastion: Provisioning with 'remote-exec'...
null_resource.remote_exec_via_ssh_over_http_proxy_with_auth_through_bastion (remote-exec): Connecting to remote host via SSH...
null_resource.remote_exec_via_ssh_over_http_proxy_with_auth_through_bastion (remote-exec):   Host: app
null_resource.remote_exec_via_ssh_over_http_proxy_with_auth_through_bastion (remote-exec):   User: root
null_resource.remote_exec_via_ssh_over_http_proxy_with_auth_through_bastion (remote-exec):   Password: true
null_resource.remote_exec_via_ssh_over_http_proxy_with_auth_through_bastion (remote-exec):   Private key: false
null_resource.remote_exec_via_ssh_over_http_proxy_with_auth_through_bastion (remote-exec):   Certificate: false
null_resource.remote_exec_via_ssh_over_http_proxy_with_auth_through_bastion (remote-exec):   SSH Agent: false
null_resource.remote_exec_via_ssh_over_http_proxy_with_auth_through_bastion (remote-exec):   Checking Host Key: false
null_resource.remote_exec_via_ssh_over_http_proxy_with_auth_through_bastion (remote-exec):   Target Platform: unix
null_resource.remote_exec_via_ssh_over_http_proxy_with_auth_through_bastion (remote-exec): Using configured bastion host...
null_resource.remote_exec_via_ssh_over_http_proxy_with_auth_through_bastion (remote-exec):   Host: bas
null_resource.remote_exec_via_ssh_over_http_proxy_with_auth_through_bastion (remote-exec):   User: root
null_resource.remote_exec_via_ssh_over_http_proxy_with_auth_through_bastion (remote-exec):   Password: true
null_resource.remote_exec_via_ssh_over_http_proxy_with_auth_through_bastion (remote-exec):   Private key: false
null_resource.remote_exec_via_ssh_over_http_proxy_with_auth_through_bastion (remote-exec):   Certificate: false
null_resource.remote_exec_via_ssh_over_http_proxy_with_auth_through_bastion (remote-exec):   SSH Agent: false
null_resource.remote_exec_via_ssh_over_http_proxy_with_auth_through_bastion (remote-exec):   Checking Host Key: false
null_resource.remote_exec_via_ssh_over_http_proxy_with_auth_through_bastion (remote-exec): Using configured proxy host...
null_resource.remote_exec_via_ssh_over_http_proxy_with_auth_through_bastion (remote-exec):   ProxyHost: localhost
null_resource.remote_exec_via_ssh_over_http_proxy_with_auth_through_bastion (remote-exec):   ProxyPort: 23129
null_resource.remote_exec_via_ssh_over_http_proxy_with_auth_through_bastion (remote-exec):   ProxyUserName: root
null_resource.remote_exec_via_ssh_over_http_proxy_with_auth_through_bastion (remote-exec):   ProxyUserPassword: true
null_resource.remote_exec_via_ssh_over_http_proxy: Provisioning with 'remote-exec'...
null_resource.remote_exec_via_ssh_over_http_proxy_through_bastion: Provisioning with 'remote-exec'...
null_resource.remote_exec_via_ssh_over_http_proxy (remote-exec): Connecting to remote host via SSH...
null_resource.remote_exec_via_ssh_over_http_proxy (remote-exec):   Host: bas
null_resource.remote_exec_via_ssh_over_http_proxy (remote-exec):   User: root
null_resource.remote_exec_via_ssh_over_http_proxy (remote-exec):   Password: true
null_resource.remote_exec_via_ssh_over_http_proxy (remote-exec):   Private key: false
null_resource.remote_exec_via_ssh_over_http_proxy (remote-exec):   Certificate: false
null_resource.remote_exec_via_ssh_over_http_proxy (remote-exec):   SSH Agent: false
null_resource.remote_exec_via_ssh_over_http_proxy (remote-exec):   Checking Host Key: false
null_resource.remote_exec_via_ssh_over_http_proxy (remote-exec):   Target Platform: unix
null_resource.remote_exec_via_ssh_over_http_proxy_through_bastion (remote-exec): Connecting to remote host via SSH...
null_resource.remote_exec_via_ssh_over_http_proxy_through_bastion (remote-exec):   Host: app
null_resource.remote_exec_via_ssh_over_http_proxy_through_bastion (remote-exec):   User: root
null_resource.remote_exec_via_ssh_over_http_proxy_through_bastion (remote-exec):   Password: true
null_resource.remote_exec_via_ssh_over_http_proxy_through_bastion (remote-exec):   Private key: false
null_resource.remote_exec_via_ssh_over_http_proxy_through_bastion (remote-exec):   Certificate: false
null_resource.remote_exec_via_ssh_over_http_proxy_through_bastion (remote-exec):   SSH Agent: false
null_resource.remote_exec_via_ssh_over_http_proxy_through_bastion (remote-exec):   Checking Host Key: false
null_resource.remote_exec_via_ssh_over_http_proxy_through_bastion (remote-exec):   Target Platform: unix
null_resource.remote_exec_via_ssh_over_http_proxy (remote-exec): Using configured proxy host...
null_resource.remote_exec_via_ssh_over_http_proxy (remote-exec):   ProxyHost: localhost
null_resource.remote_exec_via_ssh_over_http_proxy (remote-exec):   ProxyPort: 23128
null_resource.remote_exec_via_ssh_over_http_proxy (remote-exec):   ProxyUserName:
null_resource.remote_exec_via_ssh_over_http_proxy (remote-exec):   ProxyUserPassword: false
null_resource.remote_exec_via_ssh_over_http_proxy_through_bastion (remote-exec): Using configured bastion host...
null_resource.remote_exec_via_ssh_over_http_proxy_through_bastion (remote-exec):   Host: bas
null_resource.remote_exec_via_ssh_over_http_proxy_through_bastion (remote-exec):   User: root
null_resource.remote_exec_via_ssh_over_http_proxy_through_bastion (remote-exec):   Password: true
null_resource.remote_exec_via_ssh_over_http_proxy_through_bastion (remote-exec):   Private key: false
null_resource.remote_exec_via_ssh_over_http_proxy_through_bastion (remote-exec):   Certificate: false
null_resource.remote_exec_via_ssh_over_http_proxy_through_bastion (remote-exec):   SSH Agent: false
null_resource.remote_exec_via_ssh_over_http_proxy_through_bastion (remote-exec):   Checking Host Key: false
null_resource.remote_exec_via_ssh_over_http_proxy_through_bastion (remote-exec): Using configured proxy host...
null_resource.remote_exec_via_ssh_over_http_proxy_through_bastion (remote-exec):   ProxyHost: localhost
null_resource.remote_exec_via_ssh_over_http_proxy_through_bastion (remote-exec):   ProxyPort: 23128
null_resource.remote_exec_via_ssh_over_http_proxy_through_bastion (remote-exec):   ProxyUserName:
null_resource.remote_exec_via_ssh_over_http_proxy_through_bastion (remote-exec):   ProxyUserPassword: false
null_resource.remote_exec_via_ssh (remote-exec): Connected!
null_resource.remote_exec_via_ssh_over_http_proxy (remote-exec): Connected!
null_resource.remote_exec_via_ssh_over_http_proxy_with_auth (remote-exec): Connected!
null_resource.remote_exec_via_ssh_over_http_proxy_through_bastion (remote-exec): Connected!
null_resource.remote_exec_via_ssh_over_http_proxy_with_auth_through_bastion (remote-exec): Connected!
null_resource.remote_exec_via_ssh (remote-exec): Success: remote_exec_via_ssh
null_resource.remote_exec_via_ssh_over_http_proxy_with_auth (remote-exec): Success: remote_exec_via_ssh_over_http_proxy_with_auth
null_resource.remote_exec_via_ssh_over_http_proxy (remote-exec): Success: remote_exec_via_ssh_over_http_proxy
null_resource.remote_exec_via_ssh_over_http_proxy_through_bastion (remote-exec): Success: remote_exec_via_ssh_over_http_proxy_through_bastio
n
null_resource.remote_exec_via_ssh: Creation complete after 0s [id=1156678337337142727]
null_resource.remote_exec_via_ssh_over_http_proxy_with_auth_through_bastion (remote-exec): Success: remote_exec_via_ssh_over_http_proxy_with
_auth_through_bastion
null_resource.remote_exec_via_ssh_over_http_proxy_with_auth: Creation complete after 0s [id=4092500202928979050]
null_resource.remote_exec_via_ssh_over_http_proxy_through_bastion: Creation complete after 0s [id=2488039607822794741]
null_resource.remote_exec_via_ssh_over_http_proxy: Creation complete after 0s [id=2456805027942864311]
null_resource.remote_exec_via_ssh_over_http_proxy_with_auth_through_bastion: Creation complete after 0s [id=8719430125056995160]

@hashicorp-cla
Copy link

hashicorp-cla commented Mar 12, 2022

CLA assistant check
All committers have signed the CLA.

@crw
Copy link
Collaborator

crw commented Mar 14, 2022

Thanks for this contribution!

@htamakos
Copy link
Contributor Author

@crw
Thank you for your comment! What should I do to get this PR merged?

@gesnaud
Copy link

gesnaud commented Apr 13, 2022

Hi there!

Also very interested about proxy support in SSH connection!
Seems that the PR have one fail in the CI: website-link-check

image

I can help, but error message is little bit dry :)

Copy link
Member

@alisdair alisdair left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for working on this, and especially for the test docker-compose environment! I was able to verify it locally.

I have some comments inline on the implementation which I'd like to be addressed before merge. Please let me know if you have any questions on those.

Optional: true,
},
"proxy_port": {
Type: cty.String,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be a cty.Number, not a string.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fix it.

)

// Dialer implements for SSH over HTTP Proxy.
type Dialer struct {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this type (and the new functions in this file) should be exported from this package. I'd also suggest including "proxy" in the name of this type, e.g. proxyDialer, to clarify that it's not a generic SSH dialer.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

base = base + p.username + ":" + p.password + "@"
}

return url.Parse(base + p.host)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like a fragile way to construct a url.URL—what if some of the arguments require URL quoting?

I think instead we likely want to instantiate the URL struct directly, using a url.Userinfo to add the username and password if specified.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

p.auth = true
p.username = username
p.password = password
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it required that both username and password are set? I believe it's valid to specify just username and no password, or a blank username with a password.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

c.Close()
return nil, err
}
reqUrl.Scheme = ""
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again I'm surprised by using url.Parse here, especially since we erase the schema. Could we build a url.URL value directly in this case, setting only the host?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed


if connInfo.ProxyHost != "" {
p = newProxyInfo(
connInfo.ProxyHost+":"+strconv.FormatUint(uint64(connInfo.ProxyPort), 10),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think fmt.Sprintf might be clearer here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

password string
// Whether the HTTP Proxy requires authentication
auth bool
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Upon further reading, I think we could omit this new type, and use a *url.URL representing the proxy connection instead. While I haven't tried it, so I might be missing something, I think this would be simpler.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

// If http proxy requires authentication, configure settings for basic authentication.
if p.proxy.auth {
req.SetBasicAuth(p.proxy.username, p.proxy.password)
req.Header.Add("Proxy-Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(p.proxy.username+":"+p.proxy.password)))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of building this value ourselves, could we reuse the authorization header value?

Suggested change
req.Header.Add("Proxy-Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(p.proxy.username+":"+p.proxy.password)))
req.Header.Add("Proxy-Authorization", req.Header.Get("Authorization"))

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

Optional: true,
},
"proxy_port": {
Type: cty.String,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same note as above—I think this should be a cty.Number.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed


* `proxy_user_name` - The username to use connect to the private proxy host.

* `proxy_user_password` - The password to use connect to the private proxy host.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should clarify which of these fields are optional for the HTTP proxy to be used.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

@alisdair
Copy link
Member

One other note: before pushing any changes, please rebase against the latest main branch to ensure you pick up the latest CI configuration. Thanks!

Terraform's remote-exec provision hangs out when it execs on HTTP Proxy bacause it dosen't support SSH over HTTP Proxy.
This commits enables Terraform's remote-exec to support SSH over HTTP Proxy.

* adds `proxy_*` fields to `connection` which add configuration for a proxy host
* if `proxy_host` set, connect to that proxy host via CONNECT method, then make the SSH connection to `host` or `bastion_host`
@htamakos
Copy link
Contributor Author

@alisdair
Thank you for your very kind and thoughtful review!
I fully agree with your points. I have fixed it in the way you suggested. Please check again.

Copy link
Member

@alisdair alisdair left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks great! Thanks again for working on this 🙌

@alisdair alisdair merged commit 4cfb6bc into hashicorp:main Apr 27, 2022
@github-actions
Copy link

Reminder for the merging maintainer: if this is a user-visible change, please update the changelog on the appropriate release branch.

alisdair pushed a commit that referenced this pull request Apr 28, 2022
Terraform's remote-exec provision hangs out when it execs on HTTP Proxy bacause it dosen't support SSH over HTTP Proxy. This commits enables Terraform's remote-exec to support SSH over HTTP Proxy.

* adds `proxy_*` fields to `connection` which add configuration for a proxy host
* if `proxy_host` set, connect to that proxy host via CONNECT method, then make the SSH connection to `host` or `bastion_host`
@alisdair
Copy link
Member

This change is targeted for the upcoming 1.2 release.

@s0rtega
Copy link

s0rtega commented May 3, 2022

Thanks for working on this feature. I was doing some testing last days and I found some issues during the provisioning of files. I was not sure if opening a new bug or continuing with the conversation here, so let me know if I need to move to a new one.

Terraform version

  • Terraform v1.3.0-dev on windows_amd64.
  • Terraform v1.3.0-dev on linux_amd64.

Debug Output

aws_instance.test: Provisioning with 'file'...
2022-05-03T08:59:29.827+0800 [INFO]  using private key for authentication
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xc0000005 code=0x0 addr=0x18 pc=0x1f545d8]

goroutine 167 [running]:
github.com/hashicorp/terraform/internal/communicator/ssh.(*Communicator).Connect(0xc002ff7240, {0x0, 0x0})
        C:/Users/test/Desktop/terraform/internal/communicator/ssh/communicator.go:176 +0x658
github.com/hashicorp/terraform/internal/builtin/provisioners/file.copyFiles.func1()
        C:/Users/test/Desktop/terraform/internal/builtin/provisioners/file/resource_provisioner.go:159 +0x26
github.com/hashicorp/terraform/internal/communicator.Retry.func1()
        C:/Users/test/Desktop/terraform/internal/communicator/communicator.go:112 +0x1d8
created by github.com/hashicorp/terraform/internal/communicator.Retry
        C:/Users/test/Desktop/terraform/internal/communicator/communicator.go:95 +0x10f

Expected Behavior

The file provisioner should copy the file to the remote system during the deployment.

Actual Behavior

If the proxy is configured on the connection level, the provisioning of the file is crashing the terraform binary.
This behavior is happening both in Windows and Linux with the terraform binary compiled from clean sources (git clone && go build).

If the proxy configuration is removed from the connection block the file is copied successfully to the remote system. If the provisioner block is removed the execution finish without crashing using the proxy as intended.

Steps to Reproduce

  1. Create a basic deployment tf file for AWS:
provider "aws" {
  region = "eu-central-1"
}

resource "aws_instance" "test" {
    instance_type                       = "t2.micro"
    ami                                       = "ami-0006ba1ba3732dd33"
    key_name                             = "test"
    vpc_security_group_ids        = ["allowSSH-sg"]
    associate_public_ip_address = "true"
    availability_zone                   = "eu-central-1a"    
	
	connection {
	  host = self.public_ip
	  type = "ssh"
	  user = "ec2-user"
	  private_key = file("test")
	  timeout = "5m"
	  proxy_scheme = "http"
	  proxy_host   = "myproxy.com"
	  proxy_port   = 8000	  
	}

	# Copies the file
	provisioner "file" {
		source      = "files/test.sh"
		destination = "/tmp/test.sh"
	}
	
	provisioner "remote-exec" {
		inline = [
		  "echo finished"
		]
	}
}
  1. run terraform apply and the execution should crash during the provisioning of the file.

@alisdair
Copy link
Member

alisdair commented May 3, 2022

Thanks for the report, @s0rtega! I filed an issue at #30982 and will try to reproduce soon.

@github-actions
Copy link

github-actions bot commented Jun 2, 2022

I'm going to lock this pull request because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active contributions.
If you have found a problem that seems related to this change, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jun 2, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants