podman-remote: copy secret to contextdir is absolute path on host

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 <arajan@redhat.com>
This commit is contained in:
Aditya Rajan 2021-11-26 18:18:30 +05:30
parent bfcaf538bb
commit e7204178e1
No known key found for this signature in database
GPG Key ID: 8E5A8A19DF7C8673
7 changed files with 106 additions and 8 deletions

View File

@ -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

View File

@ -5,6 +5,7 @@ import (
"compress/gzip"
"context"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net/http"
@ -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 {
@ -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)

View File

@ -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

View File

@ -0,0 +1,2 @@
FROM alpine
RUN --mount=type=secret,id=mysecret cat /run/secrets/mysecret

View File

@ -0,0 +1 @@
anothersecret

View File

@ -0,0 +1 @@
somesecret

View File

@ -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"})