Skip to content

Commit

Permalink
podman-remote: copy secret to contextdir is absolute path on host
Browse files Browse the repository at this point in the history
Podman remote must treat build secrets as part of context directory. If
secret path is absolute path on host copy it to tar file and pass it to
remote server.

Signed-off-by: Aditya Rajan <[email protected]>
  • Loading branch information
flouthoc committed Nov 30, 2021
1 parent bfcaf53 commit e720417
Show file tree
Hide file tree
Showing 7 changed files with 106 additions and 8 deletions.
23 changes: 22 additions & 1 deletion pkg/api/handlers/compat/images_build.go
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,28 @@ func BuildImage(w http.ResponseWriter, r *http.Request) {
utils.BadRequest(w, "secrets", query.Secrets, err)
return
}
secrets = m

// for podman-remote all secrets must be picked from context director
// hence modify src so contextdir is added as prefix

for _, secret := range m {
secretOpt := strings.Split(secret, ",")
if len(secretOpt) > 0 {
modifiedOpt := []string{}
for _, token := range secretOpt {
arr := strings.SplitN(token, "=", 2)
if len(arr) > 1 {
if arr[0] == "src" {
modifiedSrc := fmt.Sprintf("src=%s", filepath.Join(contextDirectory, arr[1]))
modifiedOpt = append(modifiedOpt, modifiedSrc)
} else {
modifiedOpt = append(modifiedOpt, token)
}
}
}
secrets = append(secrets, strings.Join(modifiedOpt[:], ","))
}
}
}

var output string
Expand Down
61 changes: 54 additions & 7 deletions pkg/bindings/images/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"compress/gzip"
"context"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net/http"
Expand Down Expand Up @@ -116,13 +117,6 @@ func Build(ctx context.Context, containerFiles []string, options entities.BuildO
}
params.Add("dnsservers", c)
}
if secrets := options.CommonBuildOpts.Secrets; len(secrets) > 0 {
c, err := jsoniter.MarshalToString(secrets)
if err != nil {
return nil, err
}
params.Add("secrets", c)
}
if dnsoptions := options.CommonBuildOpts.DNSOptions; len(dnsoptions) > 0 {
c, err := jsoniter.MarshalToString(dnsoptions)
if err != nil {
Expand Down Expand Up @@ -384,6 +378,59 @@ func Build(ctx context.Context, containerFiles []string, options entities.BuildO
}
params.Set("dockerfile", string(cFileJSON))
}

// build secrets are usually absolute host path or relative to context dir on host
// in any case move secret to current context and ship the tar.
if secrets := options.CommonBuildOpts.Secrets; len(secrets) > 0 {
secretsForRemote := []string{}

for _, secret := range secrets {
secretOpt := strings.Split(secret, ",")
if len(secretOpt) > 0 {
modifiedOpt := []string{}
for _, token := range secretOpt {
arr := strings.SplitN(token, "=", 2)
if len(arr) > 1 {
if arr[0] == "src" {
// read specified secret into a tmp file
// move tmp file to tar and change secret source to relative tmp file
tmpSecretFile, err := ioutil.TempFile(options.ContextDirectory, "podman-build-secret")
if err != nil {
return nil, err
}
defer os.Remove(tmpSecretFile.Name()) // clean up
defer tmpSecretFile.Close()
srcSecretFile, err := os.Open(arr[1])
if err != nil {
return nil, err
}
defer srcSecretFile.Close()
_, err = io.Copy(tmpSecretFile, srcSecretFile)
if err != nil {
return nil, err
}

//add tmp file to context dir
tarContent = append(tarContent, tmpSecretFile.Name())

modifiedSrc := fmt.Sprintf("src=%s", filepath.Base(tmpSecretFile.Name()))
modifiedOpt = append(modifiedOpt, modifiedSrc)
} else {
modifiedOpt = append(modifiedOpt, token)
}
}
}
secretsForRemote = append(secretsForRemote, strings.Join(modifiedOpt[:], ","))
}
}

c, err := jsoniter.MarshalToString(secretsForRemote)
if err != nil {
return nil, err
}
params.Add("secrets", c)
}

tarfile, err := nTar(append(excludes, dontexcludes...), tarContent...)
if err != nil {
logrus.Errorf("Cannot tar container entries %v error: %v", tarContent, err)
Expand Down
3 changes: 3 additions & 0 deletions test/e2e/build/Dockerfile.with-multiple-secret
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
FROM alpine
RUN --mount=type=secret,id=mysecret cat /run/secrets/mysecret
RUN --mount=type=secret,id=mysecret2 cat /run/secrets/mysecret2
2 changes: 2 additions & 0 deletions test/e2e/build/Dockerfile.with-secret
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
FROM alpine
RUN --mount=type=secret,id=mysecret cat /run/secrets/mysecret
1 change: 1 addition & 0 deletions test/e2e/build/anothersecret.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
anothersecret
1 change: 1 addition & 0 deletions test/e2e/build/secret.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
somesecret
23 changes: 23 additions & 0 deletions test/e2e/build_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,29 @@ var _ = Describe("Podman build", func() {
Expect(session).Should(Exit(0))
})

It("podman build with a secret from file", func() {
session := podmanTest.Podman([]string{"build", "-f", "build/Dockerfile.with-secret", "-t", "secret-test", "--secret", "id=mysecret,src=build/secret.txt", "build/"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
Expect(session.OutputToString()).To(ContainSubstring("somesecret"))

session = podmanTest.Podman([]string{"rmi", "secret-test"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
})

It("podman build with multiple secrets from files", func() {
session := podmanTest.Podman([]string{"build", "-f", "build/Dockerfile.with-multiple-secret", "-t", "multiple-secret-test", "--secret", "id=mysecret,src=build/secret.txt", "--secret", "id=mysecret2,src=build/anothersecret.txt", "build/"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
Expect(session.OutputToString()).To(ContainSubstring("somesecret"))
Expect(session.OutputToString()).To(ContainSubstring("anothersecret"))

session = podmanTest.Podman([]string{"rmi", "multiple-secret-test"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
})

It("podman build with logfile", func() {
logfile := filepath.Join(podmanTest.TempDir, "logfile")
session := podmanTest.Podman([]string{"build", "--pull-never", "--tag", "test", "--logfile", logfile, "build/basicalpine"})
Expand Down

0 comments on commit e720417

Please sign in to comment.