mirror of
https://github.com/hashicorp/terraform.git
synced 2026-02-18 18:29:44 -05:00
ssh-based provisioner: Re-enable support for PowerShell (#37794)
Some checks failed
build / Determine intended Terraform version (push) Has been cancelled
build / Determine Go toolchain version (push) Has been cancelled
Quick Checks / Unit Tests (push) Has been cancelled
Quick Checks / Race Tests (push) Has been cancelled
Quick Checks / End-to-end Tests (push) Has been cancelled
Quick Checks / Code Consistency Checks (push) Has been cancelled
build / Generate release metadata (push) Has been cancelled
build / Build for freebsd_386 (push) Has been cancelled
build / Build for linux_386 (push) Has been cancelled
build / Build for openbsd_386 (push) Has been cancelled
build / Build for windows_386 (push) Has been cancelled
build / Build for darwin_amd64 (push) Has been cancelled
build / Build for freebsd_amd64 (push) Has been cancelled
build / Build for linux_amd64 (push) Has been cancelled
build / Build for openbsd_amd64 (push) Has been cancelled
build / Build for solaris_amd64 (push) Has been cancelled
build / Build for windows_amd64 (push) Has been cancelled
build / Build for freebsd_arm (push) Has been cancelled
build / Build for linux_arm (push) Has been cancelled
build / Build for darwin_arm64 (push) Has been cancelled
build / Build for linux_arm64 (push) Has been cancelled
build / Build for windows_arm64 (push) Has been cancelled
build / Build Docker image for linux_386 (push) Has been cancelled
build / Build Docker image for linux_amd64 (push) Has been cancelled
build / Build Docker image for linux_arm (push) Has been cancelled
build / Build Docker image for linux_arm64 (push) Has been cancelled
build / Build e2etest for linux_386 (push) Has been cancelled
build / Build e2etest for windows_386 (push) Has been cancelled
build / Build e2etest for darwin_amd64 (push) Has been cancelled
build / Build e2etest for linux_amd64 (push) Has been cancelled
build / Build e2etest for windows_amd64 (push) Has been cancelled
build / Build e2etest for linux_arm (push) Has been cancelled
build / Build e2etest for darwin_arm64 (push) Has been cancelled
build / Build e2etest for linux_arm64 (push) Has been cancelled
build / Run e2e test for linux_386 (push) Has been cancelled
build / Run e2e test for windows_386 (push) Has been cancelled
build / Run e2e test for darwin_amd64 (push) Has been cancelled
build / Run e2e test for linux_amd64 (push) Has been cancelled
build / Run e2e test for windows_amd64 (push) Has been cancelled
build / Run e2e test for linux_arm (push) Has been cancelled
build / Run e2e test for linux_arm64 (push) Has been cancelled
build / Run terraform-exec test for linux amd64 (push) Has been cancelled
Some checks failed
build / Determine intended Terraform version (push) Has been cancelled
build / Determine Go toolchain version (push) Has been cancelled
Quick Checks / Unit Tests (push) Has been cancelled
Quick Checks / Race Tests (push) Has been cancelled
Quick Checks / End-to-end Tests (push) Has been cancelled
Quick Checks / Code Consistency Checks (push) Has been cancelled
build / Generate release metadata (push) Has been cancelled
build / Build for freebsd_386 (push) Has been cancelled
build / Build for linux_386 (push) Has been cancelled
build / Build for openbsd_386 (push) Has been cancelled
build / Build for windows_386 (push) Has been cancelled
build / Build for darwin_amd64 (push) Has been cancelled
build / Build for freebsd_amd64 (push) Has been cancelled
build / Build for linux_amd64 (push) Has been cancelled
build / Build for openbsd_amd64 (push) Has been cancelled
build / Build for solaris_amd64 (push) Has been cancelled
build / Build for windows_amd64 (push) Has been cancelled
build / Build for freebsd_arm (push) Has been cancelled
build / Build for linux_arm (push) Has been cancelled
build / Build for darwin_arm64 (push) Has been cancelled
build / Build for linux_arm64 (push) Has been cancelled
build / Build for windows_arm64 (push) Has been cancelled
build / Build Docker image for linux_386 (push) Has been cancelled
build / Build Docker image for linux_amd64 (push) Has been cancelled
build / Build Docker image for linux_arm (push) Has been cancelled
build / Build Docker image for linux_arm64 (push) Has been cancelled
build / Build e2etest for linux_386 (push) Has been cancelled
build / Build e2etest for windows_386 (push) Has been cancelled
build / Build e2etest for darwin_amd64 (push) Has been cancelled
build / Build e2etest for linux_amd64 (push) Has been cancelled
build / Build e2etest for windows_amd64 (push) Has been cancelled
build / Build e2etest for linux_arm (push) Has been cancelled
build / Build e2etest for darwin_arm64 (push) Has been cancelled
build / Build e2etest for linux_arm64 (push) Has been cancelled
build / Run e2e test for linux_386 (push) Has been cancelled
build / Run e2e test for windows_386 (push) Has been cancelled
build / Run e2e test for darwin_amd64 (push) Has been cancelled
build / Run e2e test for linux_amd64 (push) Has been cancelled
build / Run e2e test for windows_amd64 (push) Has been cancelled
build / Run e2e test for linux_arm (push) Has been cancelled
build / Run e2e test for linux_arm64 (push) Has been cancelled
build / Run terraform-exec test for linux amd64 (push) Has been cancelled
* ssh-based provisioner: Re-enable support for PowerShell * add changelog entry
This commit is contained in:
parent
9595517730
commit
40482337a7
3 changed files with 153 additions and 6 deletions
5
.changes/v1.15/ENHANCEMENTS-20251022-162909.yaml
Normal file
5
.changes/v1.15/ENHANCEMENTS-20251022-162909.yaml
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
kind: ENHANCEMENTS
|
||||
body: 'ssh-based provisioner (file + remote-exec): Re-enable support for PowerShell'
|
||||
time: 2025-10-22T16:29:09.342697+01:00
|
||||
custom:
|
||||
Issue: "37794"
|
||||
|
|
@ -436,7 +436,7 @@ func (c *Communicator) Upload(path string, input io.Reader) error {
|
|||
return scpUploadFile(targetFile, input, w, stdoutR, size)
|
||||
}
|
||||
|
||||
cmd, err := quoteShell([]string{"scp", "-vt", targetDir}, c.connInfo.TargetPlatform)
|
||||
cmd, err := quoteScpCommand([]string{"scp", "-vt", targetDir}, c.connInfo.TargetPlatform)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -509,7 +509,7 @@ func (c *Communicator) UploadDir(dst string, src string) error {
|
|||
return uploadEntries()
|
||||
}
|
||||
|
||||
cmd, err := quoteShell([]string{"scp", "-rvt", dst}, c.connInfo.TargetPlatform)
|
||||
cmd, err := quoteScpCommand([]string{"scp", "-rvt", dst}, c.connInfo.TargetPlatform)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -886,14 +886,15 @@ func (c *bastionConn) Close() error {
|
|||
return c.Bastion.Close()
|
||||
}
|
||||
|
||||
func quoteShell(args []string, targetPlatform string) (string, error) {
|
||||
func quoteScpCommand(args []string, targetPlatform string) (string, error) {
|
||||
if targetPlatform == TargetPlatformUnix {
|
||||
return shquot.POSIXShell(args), nil
|
||||
}
|
||||
if targetPlatform == TargetPlatformWindows {
|
||||
return shquot.WindowsArgv(args), nil
|
||||
cmd, args := shquot.WindowsArgvSplit(args)
|
||||
return fmt.Sprintf("%s %s", cmd, args), nil
|
||||
}
|
||||
|
||||
return "", fmt.Errorf("Cannot quote shell command, target platform unknown: %s", targetPlatform)
|
||||
return "", fmt.Errorf("Cannot quote scp command, target platform unknown: %s", targetPlatform)
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/hashicorp/terraform/internal/communicator/remote"
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
"golang.org/x/crypto/ssh"
|
||||
|
|
@ -660,7 +661,7 @@ func TestAccHugeUploadFile(t *testing.T) {
|
|||
return scpUploadFile(targetFile, source, w, stdoutR, size)
|
||||
}
|
||||
|
||||
cmd, err := quoteShell([]string{"scp", "-vt", targetDir}, c.connInfo.TargetPlatform)
|
||||
cmd, err := quoteScpCommand([]string{"scp", "-vt", targetDir}, c.connInfo.TargetPlatform)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
@ -680,6 +681,146 @@ func TestAccHugeUploadFile(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestQuoteScpCommand(t *testing.T) {
|
||||
testCases := []struct {
|
||||
inputArgs []string
|
||||
platform string
|
||||
expectedCmd string
|
||||
}{
|
||||
// valid Unix command
|
||||
{
|
||||
[]string{"scp", "-vt", "/var/path"},
|
||||
TargetPlatformUnix,
|
||||
"'scp' -vt /var/path",
|
||||
},
|
||||
|
||||
// command injection attempt in Unix
|
||||
{
|
||||
[]string{"scp", "-vt", "/var/path;rm"},
|
||||
TargetPlatformUnix,
|
||||
"'scp' -vt /var/path\\;rm",
|
||||
},
|
||||
{
|
||||
[]string{"scp", "-vt", "/var/path&&rm"},
|
||||
TargetPlatformUnix,
|
||||
"'scp' -vt /var/path\\&\\&rm",
|
||||
},
|
||||
{
|
||||
[]string{"scp", "-vt", "/var/path|rm"},
|
||||
TargetPlatformUnix,
|
||||
"'scp' -vt /var/path\\|rm",
|
||||
},
|
||||
{
|
||||
[]string{"scp", "-vt", "/var/path||rm"},
|
||||
TargetPlatformUnix,
|
||||
"'scp' -vt /var/path\\|\\|rm",
|
||||
},
|
||||
{
|
||||
[]string{"scp", "-vt", "/var/path; rm"},
|
||||
TargetPlatformUnix,
|
||||
"'scp' -vt '/var/path; rm'",
|
||||
},
|
||||
{
|
||||
[]string{"scp", "-vt", "/var/path`rm`"},
|
||||
TargetPlatformUnix,
|
||||
"'scp' -vt /var/path\\`rm\\`",
|
||||
},
|
||||
{
|
||||
[]string{"scp", "-vt", "/var/path$(rm)"},
|
||||
TargetPlatformUnix,
|
||||
"'scp' -vt /var/path\\$\\(rm\\)",
|
||||
},
|
||||
|
||||
// valid Windows commands
|
||||
{
|
||||
[]string{"scp", "-vt", "C:\\Windows\\Temp"},
|
||||
TargetPlatformWindows,
|
||||
"scp -vt C:\\Windows\\Temp",
|
||||
},
|
||||
{
|
||||
[]string{"scp", "-vt", "C:\\Windows\\Temp With Space"},
|
||||
TargetPlatformWindows,
|
||||
"scp -vt \"C:\\Windows\\Temp With Space\"",
|
||||
},
|
||||
|
||||
// command injection attempt in Windows
|
||||
{
|
||||
[]string{"scp", "-vt", "C:\\Windows\\Temp ;rmdir"},
|
||||
TargetPlatformWindows,
|
||||
"scp -vt \"C:\\Windows\\Temp ;rmdir\"",
|
||||
},
|
||||
{
|
||||
[]string{"scp", "-vt", "C:\\Windows\\Temp\";rmdir"},
|
||||
TargetPlatformWindows,
|
||||
"scp -vt \"C:\\Windows\\Temp\\\";rmdir\"",
|
||||
},
|
||||
{
|
||||
[]string{"scp", "-vt", "C:\\Windows\\Temp\nrmdir"},
|
||||
TargetPlatformWindows,
|
||||
"scp -vt \"C:\\Windows\\Temp\nrmdir\"",
|
||||
},
|
||||
{
|
||||
[]string{"scp", "-vt", "C:\\Windows\\Temp\trmdir"},
|
||||
TargetPlatformWindows,
|
||||
"scp -vt \"C:\\Windows\\Temp\trmdir\"",
|
||||
},
|
||||
{
|
||||
[]string{"scp", "-vt", "C:\\Windows\\Temp\vrmdir"},
|
||||
TargetPlatformWindows,
|
||||
"scp -vt \"C:\\Windows\\Temp\vrmdir\"",
|
||||
},
|
||||
{
|
||||
[]string{"scp", "-vt", "C:\\Windows\\Temp\u0020rmdir"},
|
||||
TargetPlatformWindows,
|
||||
"scp -vt \"C:\\Windows\\Temp rmdir\"",
|
||||
},
|
||||
|
||||
// There is no special handling of the injection attempts below
|
||||
// but we include them anyway to demonstrate this
|
||||
// and to avoid any regressions due to upstream changes.
|
||||
{
|
||||
[]string{"scp", "-vt", "C:\\Windows\\Temp;rmdir"},
|
||||
TargetPlatformWindows,
|
||||
"scp -vt C:\\Windows\\Temp;rmdir",
|
||||
},
|
||||
{
|
||||
[]string{"scp", "-vt", "C:\\Windows\\Temp&rmdir"},
|
||||
TargetPlatformWindows,
|
||||
"scp -vt C:\\Windows\\Temp&rmdir",
|
||||
},
|
||||
{
|
||||
[]string{"scp", "-vt", "C:\\Windows\\Temp&&rmdir"},
|
||||
TargetPlatformWindows,
|
||||
"scp -vt C:\\Windows\\Temp&&rmdir",
|
||||
},
|
||||
{
|
||||
[]string{"scp", "-vt", "C:\\Windows\\Temp|rmdir"},
|
||||
TargetPlatformWindows,
|
||||
"scp -vt C:\\Windows\\Temp|rmdir",
|
||||
},
|
||||
{
|
||||
[]string{"scp", "-vt", "C:\\Windows\\Temp||rmdir"},
|
||||
TargetPlatformWindows,
|
||||
"scp -vt C:\\Windows\\Temp||rmdir",
|
||||
},
|
||||
{
|
||||
[]string{"scp", "-vt", "C:\\Windows\\Temp$(rmdir)"},
|
||||
TargetPlatformWindows,
|
||||
"scp -vt C:\\Windows\\Temp$(rmdir)",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
cmd, err := quoteScpCommand(tc.inputArgs, tc.platform)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if diff := cmp.Diff(tc.expectedCmd, cmd); diff != "" {
|
||||
t.Fatalf("unexpected command for %q: %s", tc.inputArgs, diff)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestScriptPath(t *testing.T) {
|
||||
cases := []struct {
|
||||
Input string
|
||||
|
|
|
|||
Loading…
Reference in a new issue