From fdbb696731c7ce1f160ffd4937ec8a739cc47e0a Mon Sep 17 00:00:00 2001 From: ZuhairM7 Date: Sat, 29 Nov 2025 20:43:20 -0600 Subject: [PATCH] bindings: fix handling of env secrets in remote builds Previously, using --secret=id=foo,env=BAR in remote mode would fail because the client sent the env var name to the server, which tried to resolve it locally. This patch modifies the client to resolve the environment variable locally, write it to a temp file, and send it as a file-based secret. Fixes #27494 Signed-off-by: ZuhairM7 Signed-off-by: ZuhairM7 --- pkg/bindings/images/build.go | 19 +++++++++++++++++-- test/e2e/build_test.go | 9 +++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/pkg/bindings/images/build.go b/pkg/bindings/images/build.go index ed64366d30..df6c188937 100644 --- a/pkg/bindings/images/build.go +++ b/pkg/bindings/images/build.go @@ -626,7 +626,8 @@ func prepareSecrets(secrets []string, contextDir string, tempManager *remote_bui for _, token := range secretOpt { opt, val, hasVal := strings.Cut(token, "=") if hasVal { - if opt == "src" { + switch opt { + case "src": // read specified secret into a tmp file // move tmp file to tar and change secret source to relative tmp file tmpSecretFilePath, err := tempManager.CreateTempSecret(val, contextDir) @@ -639,7 +640,21 @@ func prepareSecrets(secrets []string, contextDir string, tempManager *remote_bui modifiedSrc := fmt.Sprintf("src=%s", filepath.Base(tmpSecretFilePath)) modifiedOpt = append(modifiedOpt, modifiedSrc) - } else { + case "env": + // read specified env into a tmp file + // move tmp file to tar and change secret source to relative tmp file + secretVal := os.Getenv(val) + tmpSecretFilePath, err := tempManager.CreateTempFileFromReader(contextDir, "podman-build-secret-*", strings.NewReader(secretVal)) + if err != nil { + return nil, nil, err + } + + // add tmp file to context dir + tarContent = append(tarContent, tmpSecretFilePath) + + modifiedSrc := fmt.Sprintf("src=%s", filepath.Base(tmpSecretFilePath)) + modifiedOpt = append(modifiedOpt, modifiedSrc) + default: modifiedOpt = append(modifiedOpt, token) } } diff --git a/test/e2e/build_test.go b/test/e2e/build_test.go index d859fec005..d0208b2902 100644 --- a/test/e2e/build_test.go +++ b/test/e2e/build_test.go @@ -99,6 +99,15 @@ var _ = Describe("Podman build", func() { Expect(session).Should(ExitCleanly()) }) + It("podman build with a secret from env", func() { + os.Setenv("MYSECRET", "somesecret") + defer os.Unsetenv("MYSECRET") + session := podmanTest.PodmanExitCleanly("build", "-f", "build/Containerfile.with-secret", "-t", "secret-test", "--secret", "id=mysecret,env=MYSECRET", "build/") + Expect(session.OutputToString()).To(ContainSubstring("somesecret")) + + podmanTest.PodmanExitCleanly("rmi", "secret-test") + }) + It("podman build with multiple secrets from files", func() { session := podmanTest.Podman([]string{"build", "-f", "build/Containerfile.with-multiple-secret", "-t", "multiple-secret-test", "--secret", "id=mysecret,src=build/secret.txt", "--secret", "id=mysecret2,src=build/anothersecret.txt", "build/"}) session.WaitWithDefaultTimeout()