communicator/ssh: Fix crash with SSH bastion port

The connection block schema defines the bastion_port argument as a
number, but we were incorrectly trying to convert it from a string. This
commit fixes that by attempting to convert the cty.Number to the int
result type, returning the error on failure.

An alternative approach would be to change the bastion_port argument in
the schema to be a string, matching the port argument. I'm less sure
about the secondary effects of that change, though.
This commit is contained in:
Alisdair McDiarmid 2021-05-10 11:46:07 -04:00
parent 87c9e78666
commit 0cbe4d8efb
2 changed files with 27 additions and 4 deletions

View File

@ -17,6 +17,7 @@ import (
"github.com/hashicorp/terraform/communicator/shared" "github.com/hashicorp/terraform/communicator/shared"
sshagent "github.com/xanzy/ssh-agent" sshagent "github.com/xanzy/ssh-agent"
"github.com/zclconf/go-cty/cty" "github.com/zclconf/go-cty/cty"
"github.com/zclconf/go-cty/cty/gocty"
"golang.org/x/crypto/ssh" "golang.org/x/crypto/ssh"
"golang.org/x/crypto/ssh/agent" "golang.org/x/crypto/ssh/agent"
"golang.org/x/crypto/ssh/knownhosts" "golang.org/x/crypto/ssh/knownhosts"
@ -127,11 +128,9 @@ func decodeConnInfo(v cty.Value) (*connectionInfo, error) {
case "bastion_host_key": case "bastion_host_key":
connInfo.BastionHostKey = v.AsString() connInfo.BastionHostKey = v.AsString()
case "bastion_port": case "bastion_port":
p, err := strconv.Atoi(v.AsString()) if err := gocty.FromCtyValue(v, &connInfo.BastionPort); err != nil {
if err != nil {
return nil, err return nil, err
} }
connInfo.BastionPort = p
case "agent_identity": case "agent_identity":
connInfo.AgentIdentity = v.AsString() connInfo.AgentIdentity = v.AsString()
} }

View File

@ -17,6 +17,7 @@ func TestProvisioner_connInfo(t *testing.T) {
"port": cty.StringVal("22"), "port": cty.StringVal("22"),
"timeout": cty.StringVal("30s"), "timeout": cty.StringVal("30s"),
"bastion_host": cty.StringVal("127.0.1.1"), "bastion_host": cty.StringVal("127.0.1.1"),
"bastion_port": cty.NumberIntVal(20022),
}) })
conf, err := parseConnectionInfo(v) conf, err := parseConnectionInfo(v)
@ -54,7 +55,7 @@ func TestProvisioner_connInfo(t *testing.T) {
if conf.BastionHost != "127.0.1.1" { if conf.BastionHost != "127.0.1.1" {
t.Fatalf("bad: %v", conf) t.Fatalf("bad: %v", conf)
} }
if conf.BastionPort != 22 { if conf.BastionPort != 20022 {
t.Fatalf("bad: %v", conf) t.Fatalf("bad: %v", conf)
} }
if conf.BastionUser != "root" { if conf.BastionUser != "root" {
@ -135,3 +136,26 @@ func TestProvisioner_connInfoEmptyHostname(t *testing.T) {
t.Fatalf("bad: should not allow empty host") t.Fatalf("bad: should not allow empty host")
} }
} }
func TestProvisioner_stringBastionPort(t *testing.T) {
v := cty.ObjectVal(map[string]cty.Value{
"type": cty.StringVal("ssh"),
"user": cty.StringVal("root"),
"password": cty.StringVal("supersecret"),
"private_key": cty.StringVal("someprivatekeycontents"),
"host": cty.StringVal("example.com"),
"port": cty.StringVal("22"),
"timeout": cty.StringVal("30s"),
"bastion_host": cty.StringVal("example.com"),
"bastion_port": cty.StringVal("12345"),
})
conf, err := parseConnectionInfo(v)
if err != nil {
t.Fatalf("err: %v", err)
}
if conf.BastionPort != 12345 {
t.Fatalf("bad %v", conf)
}
}