build: mirror --authfile to filesystem if pointing to FD instead of file

Following PR makes sure that buildah mirrors --authfile to a temporary
file in filesystem if arg is pointing to an FD instead of actual file
as FD can be only consumed once.

Fixes: https://github.com/containers/buildah/issues/3070

Signed-off-by: Aditya Rajan <arajan@redhat.com>
This commit is contained in:
Aditya Rajan 2021-09-06 16:00:09 +05:30
parent 58a16f9768
commit 5a24cd02b7
4 changed files with 48 additions and 0 deletions

View File

@ -100,6 +100,7 @@ func getContainerfiles(files []string) []string {
func buildCmd(c *cobra.Command, inputArgs []string, iopts buildOptions) error { func buildCmd(c *cobra.Command, inputArgs []string, iopts buildOptions) error {
output := "" output := ""
cleanTmpFile := false
tags := []string{} tags := []string{}
if c.Flag("tag").Changed { if c.Flag("tag").Changed {
tags = iopts.Tag tags = iopts.Tag
@ -111,6 +112,10 @@ func buildCmd(c *cobra.Command, inputArgs []string, iopts buildOptions) error {
if err := auth.CheckAuthFile(iopts.BudResults.Authfile); err != nil { if err := auth.CheckAuthFile(iopts.BudResults.Authfile); err != nil {
return err return err
} }
iopts.BudResults.Authfile, cleanTmpFile = buildahutil.MirrorToTempFileIfPathIsDescriptor(iopts.BudResults.Authfile)
if cleanTmpFile {
defer os.Remove(iopts.BudResults.Authfile)
}
pullPolicy := define.PullIfMissing pullPolicy := define.PullIfMissing
if iopts.Pull { if iopts.Pull {

View File

@ -1,12 +1,44 @@
package util package util
import ( import (
"io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
"strings"
"github.com/pkg/errors" "github.com/pkg/errors"
) )
// Mirrors path to a tmpfile if path points to a
// file descriptor instead of actual file on filesystem
// reason: operations with file descriptors are can lead
// to edge cases where content on FD is not in a consumable
// state after first consumption.
// returns path as string and bool to confirm if temp file
// was created and needs to be cleaned up.
func MirrorToTempFileIfPathIsDescriptor(file string) (string, bool) {
// one use-case is discussed here
// https://github.com/containers/buildah/issues/3070
if !strings.HasPrefix(file, "/dev/fd") {
return file, false
}
b, err := ioutil.ReadFile(file)
if err != nil {
// if anything goes wrong return original path
return file, false
}
tmpfile, err := ioutil.TempFile(os.TempDir(), "buildah-temp-file")
if err != nil {
return file, false
}
if _, err := tmpfile.Write(b); err != nil {
// if anything goes wrong return original path
return file, false
}
return tmpfile.Name(), true
}
// DiscoverContainerfile tries to find a Containerfile or a Dockerfile within the provided `path`. // DiscoverContainerfile tries to find a Containerfile or a Dockerfile within the provided `path`.
func DiscoverContainerfile(path string) (foundCtrFile string, err error) { func DiscoverContainerfile(path string) (foundCtrFile string, err error) {
// Test for existence of the file // Test for existence of the file

View File

@ -2261,6 +2261,14 @@ _EOF
run_buildah 125 build --authfile /tmp/nonexistent --signature-policy ${TESTSDIR}/policy.json -t ${target} ${TESTSDIR}/bud/containerfile run_buildah 125 build --authfile /tmp/nonexistent --signature-policy ${TESTSDIR}/policy.json -t ${target} ${TESTSDIR}/bud/containerfile
} }
@test "bud for multi-stage Containerfile with invalid registry and --authfile as a fd, should fail with no such host" {
target=alpine-multi-stage-image
run_buildah 125 build --authfile=<(echo "{ \"auths\": { \"myrepository.example\": { \"auth\": \"$(echo 'username:password' | base64 --wrap=0)\" } } }") -t ${target} --file ${TESTSDIR}/bud/from-invalid-registry/Containerfile
# Should fail with `no such host` instead of: error reading JSON file "/dev/fd/x"
expect_output --substring "no such host"
}
@test "bud COPY with URL should fail" { @test "bud COPY with URL should fail" {
mkdir ${TESTSDIR}/bud/copy mkdir ${TESTSDIR}/bud/copy
FILE=${TESTSDIR}/bud/copy/Dockerfile.url FILE=${TESTSDIR}/bud/copy/Dockerfile.url

View File

@ -0,0 +1,3 @@
FROM alpine as build
# Invalid registry and image
FROM myrepository.example/image:tag