From 4e3dd47967d280c2fdda3e9b720e61180034e293 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 fa220d9b16..92745e0590 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 1040fc5400..36a8585c43 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()