From b35263062e10cd4459cbd240b0a494b1da489b48 Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Wed, 2 Aug 2023 11:43:07 +0530 Subject: [PATCH 1/5] Fix Windows FIPS Build --- command/connect/envoy/exec_windows.go | 96 ++++++++++++++++----------- 1 file changed, 59 insertions(+), 37 deletions(-) diff --git a/command/connect/envoy/exec_windows.go b/command/connect/envoy/exec_windows.go index e70108794ca0..8aeab1a50d81 100644 --- a/command/connect/envoy/exec_windows.go +++ b/command/connect/envoy/exec_windows.go @@ -6,6 +6,7 @@ package envoy import ( "errors" "fmt" + "github.com/hashicorp/consul/version" "github.com/natefinch/npipe" "os" "os/exec" @@ -14,50 +15,71 @@ import ( ) func makeBootstrapPipe(bootstrapJSON []byte) (string, error) { - pipeFile := filepath.Join(os.TempDir(), - fmt.Sprintf("envoy-%x-bootstrap.json", time.Now().UnixNano()+int64(os.Getpid()))) + if version.IsFIPS() { + tempFile := filepath.Join(os.TempDir(), + fmt.Sprintf("envoy-%x-bootstrap.json", time.Now().UnixNano()+int64(os.Getpid()))) - binary, args, err := execArgs("connect", "envoy", "pipe-bootstrap", pipeFile) - if err != nil { - return pipeFile, err - } + f, err := os.Create(tempFile) + if err != nil { + return tempFile, err + } - // Dial the named pipe - pipeConn, err := npipe.Dial(pipeFile) - if err != nil { - return pipeFile, err - } - defer pipeConn.Close() + defer f.Close() + f.Write(bootstrapJSON) + f.Sync() + // We can't wait for the process since we need to exec into Envoy before it + // will be able to complete so it will be remain as a zombie until Envoy is + // killed then will be reaped by the init process (pid 0). This is all a bit + // gross but the cleanest workaround I can think of for Envoy 1.10 not + // supporting /dev/fd/ config paths any more. So we are done and leaving + // the child to run it's course without reaping it. + return tempFile, nil + } else { + pipeFile := filepath.Join(os.TempDir(), + fmt.Sprintf("envoy-%x-bootstrap.json", time.Now().UnixNano()+int64(os.Getpid()))) + + binary, args, err := execArgs("connect", "envoy", "pipe-bootstrap", pipeFile) + if err != nil { + return pipeFile, err + } - // Start the command to connect to the named pipe - cmd := exec.Command(binary, args...) - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - cmd.Stdin = pipeConn + // Dial the named pipe + pipeConn, err := npipe.Dial(pipeFile) + if err != nil { + return pipeFile, err + } + defer pipeConn.Close() + + // Start the command to connect to the named pipe + cmd := exec.Command(binary, args...) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + cmd.Stdin = pipeConn + + // Start the command + err = cmd.Start() + if err != nil { + return pipeFile, err + } - // Start the command - err = cmd.Start() - if err != nil { - return pipeFile, err - } + // Write the config + n, err := pipeConn.Write(bootstrapJSON) + if err != nil { + return pipeFile, err + } - // Write the config - n, err := pipeConn.Write(bootstrapJSON) - if err != nil { - return pipeFile, err - } + if n < len(bootstrapJSON) { + return pipeFile, fmt.Errorf("failed writing boostrap to child STDIN: %s", err) + } - if n < len(bootstrapJSON) { - return pipeFile, fmt.Errorf("failed writing boostrap to child STDIN: %s", err) + // We can't wait for the process since we need to exec into Envoy before it + // will be able to complete so it will be remain as a zombie until Envoy is + // killed then will be reaped by the init process (pid 0). This is all a bit + // gross but the cleanest workaround I can think of for Envoy 1.10 not + // supporting /dev/fd/ config paths any more. So we are done and leaving + // the child to run it's course without reaping it. + return pipeFile, nil } - - // We can't wait for the process since we need to exec into Envoy before it - // will be able to complete so it will be remain as a zombie until Envoy is - // killed then will be reaped by the init process (pid 0). This is all a bit - // gross but the cleanest workaround I can think of for Envoy 1.10 not - // supporting /dev/fd/ config paths any more. So we are done and leaving - // the child to run it's course without reaping it. - return pipeFile, nil } func startProc(binary string, args []string) (p *os.Process, err error) { From bb80bf7aca2e3129a0d970ad0b14efc71767104d Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Wed, 2 Aug 2023 12:18:52 +0530 Subject: [PATCH 2/5] create new file for windows arm --- command/connect/envoy/exec_windows.go | 96 ++++++++------------- command/connect/envoy/exec_windows_arm64.go | 83 ++++++++++++++++++ 2 files changed, 120 insertions(+), 59 deletions(-) create mode 100644 command/connect/envoy/exec_windows_arm64.go diff --git a/command/connect/envoy/exec_windows.go b/command/connect/envoy/exec_windows.go index 8aeab1a50d81..e70108794ca0 100644 --- a/command/connect/envoy/exec_windows.go +++ b/command/connect/envoy/exec_windows.go @@ -6,7 +6,6 @@ package envoy import ( "errors" "fmt" - "github.com/hashicorp/consul/version" "github.com/natefinch/npipe" "os" "os/exec" @@ -15,71 +14,50 @@ import ( ) func makeBootstrapPipe(bootstrapJSON []byte) (string, error) { - if version.IsFIPS() { - tempFile := filepath.Join(os.TempDir(), - fmt.Sprintf("envoy-%x-bootstrap.json", time.Now().UnixNano()+int64(os.Getpid()))) + pipeFile := filepath.Join(os.TempDir(), + fmt.Sprintf("envoy-%x-bootstrap.json", time.Now().UnixNano()+int64(os.Getpid()))) - f, err := os.Create(tempFile) - if err != nil { - return tempFile, err - } + binary, args, err := execArgs("connect", "envoy", "pipe-bootstrap", pipeFile) + if err != nil { + return pipeFile, err + } - defer f.Close() - f.Write(bootstrapJSON) - f.Sync() - // We can't wait for the process since we need to exec into Envoy before it - // will be able to complete so it will be remain as a zombie until Envoy is - // killed then will be reaped by the init process (pid 0). This is all a bit - // gross but the cleanest workaround I can think of for Envoy 1.10 not - // supporting /dev/fd/ config paths any more. So we are done and leaving - // the child to run it's course without reaping it. - return tempFile, nil - } else { - pipeFile := filepath.Join(os.TempDir(), - fmt.Sprintf("envoy-%x-bootstrap.json", time.Now().UnixNano()+int64(os.Getpid()))) - - binary, args, err := execArgs("connect", "envoy", "pipe-bootstrap", pipeFile) - if err != nil { - return pipeFile, err - } + // Dial the named pipe + pipeConn, err := npipe.Dial(pipeFile) + if err != nil { + return pipeFile, err + } + defer pipeConn.Close() - // Dial the named pipe - pipeConn, err := npipe.Dial(pipeFile) - if err != nil { - return pipeFile, err - } - defer pipeConn.Close() - - // Start the command to connect to the named pipe - cmd := exec.Command(binary, args...) - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - cmd.Stdin = pipeConn - - // Start the command - err = cmd.Start() - if err != nil { - return pipeFile, err - } + // Start the command to connect to the named pipe + cmd := exec.Command(binary, args...) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + cmd.Stdin = pipeConn - // Write the config - n, err := pipeConn.Write(bootstrapJSON) - if err != nil { - return pipeFile, err - } + // Start the command + err = cmd.Start() + if err != nil { + return pipeFile, err + } - if n < len(bootstrapJSON) { - return pipeFile, fmt.Errorf("failed writing boostrap to child STDIN: %s", err) - } + // Write the config + n, err := pipeConn.Write(bootstrapJSON) + if err != nil { + return pipeFile, err + } - // We can't wait for the process since we need to exec into Envoy before it - // will be able to complete so it will be remain as a zombie until Envoy is - // killed then will be reaped by the init process (pid 0). This is all a bit - // gross but the cleanest workaround I can think of for Envoy 1.10 not - // supporting /dev/fd/ config paths any more. So we are done and leaving - // the child to run it's course without reaping it. - return pipeFile, nil + if n < len(bootstrapJSON) { + return pipeFile, fmt.Errorf("failed writing boostrap to child STDIN: %s", err) } + + // We can't wait for the process since we need to exec into Envoy before it + // will be able to complete so it will be remain as a zombie until Envoy is + // killed then will be reaped by the init process (pid 0). This is all a bit + // gross but the cleanest workaround I can think of for Envoy 1.10 not + // supporting /dev/fd/ config paths any more. So we are done and leaving + // the child to run it's course without reaping it. + return pipeFile, nil } func startProc(binary string, args []string) (p *os.Process, err error) { diff --git a/command/connect/envoy/exec_windows_arm64.go b/command/connect/envoy/exec_windows_arm64.go new file mode 100644 index 000000000000..c59e3d808ace --- /dev/null +++ b/command/connect/envoy/exec_windows_arm64.go @@ -0,0 +1,83 @@ +//go:build windows +// +build windows + +package envoy + +import ( + "errors" + "fmt" + "os" + "os/exec" + "path/filepath" + "time" +) + +func makeBootstrapPipe(bootstrapJSON []byte) (string, error) { + tempFile := filepath.Join(os.TempDir(), + fmt.Sprintf("envoy-%x-bootstrap.json", time.Now().UnixNano()+int64(os.Getpid()))) + + f, err := os.Create(tempFile) + if err != nil { + return tempFile, err + } + + defer f.Close() + f.Write(bootstrapJSON) + f.Sync() + // We can't wait for the process since we need to exec into Envoy before it + // will be able to complete so it will be remain as a zombie until Envoy is + // killed then will be reaped by the init process (pid 0). This is all a bit + // gross but the cleanest workaround I can think of for Envoy 1.10 not + // supporting /dev/fd/ config paths any more. So we are done and leaving + // the child to run it's course without reaping it. + return tempFile, nil +} + +func startProc(binary string, args []string) (p *os.Process, err error) { + if binary, err = exec.LookPath(binary); err == nil { + var procAttr os.ProcAttr + procAttr.Files = []*os.File{os.Stdin, + os.Stdout, os.Stderr} + p, err := os.StartProcess(binary, args, &procAttr) + if err == nil { + return p, nil + } + } + return nil, err +} + +func execEnvoy(binary string, prefixArgs, suffixArgs []string, bootstrapJSON []byte) error { + tempFile, err := makeBootstrapPipe(bootstrapJSON) + if err != nil { + os.RemoveAll(tempFile) + return err + } + // We don't defer a cleanup since we are about to Exec into Envoy which means + // defer will never fire. The child process cleans up for us in the happy + // path. + + // We default to disabling hot restart because it makes it easier to run + // multiple envoys locally for testing without them trying to share memory and + // unix sockets and complain about being different IDs. But if user is + // actually configuring hot-restart explicitly with the --restart-epoch option + // then don't disable it! + disableHotRestart := !hasHotRestartOption(prefixArgs, suffixArgs) + + // First argument needs to be the executable name. + envoyArgs := []string{} + envoyArgs = append(envoyArgs, prefixArgs...) + if disableHotRestart { + envoyArgs = append(envoyArgs, "--disable-hot-restart") + } + envoyArgs = append(envoyArgs, suffixArgs...) + envoyArgs = append(envoyArgs, "--config-path", tempFile) + + // Exec + if proc, err := startProc(binary, envoyArgs); err == nil { + proc.Wait() + } else if err != nil { + return errors.New("Failed to exec envoy: " + err.Error()) + } + + return nil +} From 2d888ae1a71b5698225819ab5baab12a2732b1d9 Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Wed, 2 Aug 2023 12:20:27 +0530 Subject: [PATCH 3/5] removed build tag --- command/connect/envoy/exec_windows_arm64.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/command/connect/envoy/exec_windows_arm64.go b/command/connect/envoy/exec_windows_arm64.go index c59e3d808ace..8423ba8a5af7 100644 --- a/command/connect/envoy/exec_windows_arm64.go +++ b/command/connect/envoy/exec_windows_arm64.go @@ -1,6 +1,3 @@ -//go:build windows -// +build windows - package envoy import ( From b421c954b49a2632fb1b877d3a27aa7b08ce21a4 Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Wed, 2 Aug 2023 12:29:09 +0530 Subject: [PATCH 4/5] fix buidl tags --- command/connect/envoy/exec_windows.go | 2 ++ command/connect/envoy/exec_windows_arm64.go | 3 +++ 2 files changed, 5 insertions(+) diff --git a/command/connect/envoy/exec_windows.go b/command/connect/envoy/exec_windows.go index e70108794ca0..c62ce04ae48e 100644 --- a/command/connect/envoy/exec_windows.go +++ b/command/connect/envoy/exec_windows.go @@ -1,5 +1,7 @@ //go:build windows +//go:build !fips // +build windows +// +build !fips package envoy diff --git a/command/connect/envoy/exec_windows_arm64.go b/command/connect/envoy/exec_windows_arm64.go index 8423ba8a5af7..b080d7818786 100644 --- a/command/connect/envoy/exec_windows_arm64.go +++ b/command/connect/envoy/exec_windows_arm64.go @@ -1,3 +1,6 @@ +//go:build fips +// +build fips + package envoy import ( From 85433cd6617568aa396e1b7140a1bc1fffe0bdb3 Mon Sep 17 00:00:00 2001 From: absolutelightning Date: Wed, 2 Aug 2023 13:01:55 +0530 Subject: [PATCH 5/5] fix multiple go build --- command/connect/envoy/exec_windows.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/command/connect/envoy/exec_windows.go b/command/connect/envoy/exec_windows.go index c62ce04ae48e..4b63711b4890 100644 --- a/command/connect/envoy/exec_windows.go +++ b/command/connect/envoy/exec_windows.go @@ -1,7 +1,5 @@ -//go:build windows -//go:build !fips -// +build windows -// +build !fips +//go:build windows && !fips +// +build windows,!fips package envoy