From af1fe4e14568b7cca9fe19a3abd0c052eb99076d Mon Sep 17 00:00:00 2001 From: Nalin Dahyabhai Date: Wed, 16 Oct 2024 17:09:41 -0400 Subject: [PATCH] Document more buildah build --secret options Describe the "env" and "type" options in the buildah-build(1) man page. When parsing the "--secret=" flag for the CLI, instead of ignoring an option that we don't recognize, return an error. Even though the set of meaningful "id" values for secrets is passed in via the command line, don't directly use it to construct a file path. Change the default mode for SSH agent sockets that we create from 0o620 to 0o600. Signed-off-by: Nalin Dahyabhai --- docs/buildah-build.1.md | 14 +++++++++++--- pkg/parse/parse.go | 8 ++++++-- run_common.go | 13 +++++++------ tests/bud.bats | 6 +++++- 4 files changed, 29 insertions(+), 12 deletions(-) diff --git a/docs/buildah-build.1.md b/docs/buildah-build.1.md index 6820a2e9d39..15b89b439e8 100644 --- a/docs/buildah-build.1.md +++ b/docs/buildah-build.1.md @@ -903,17 +903,25 @@ specified. These text substitutions are performed: Generate SBOMs using the specified scanner image. -**--secret**=**id=id,src=path** +**--secret**=**id=id[,src=*envOrFile*][,env=ENV][,type=file|env]** Pass secret information to be used in the Containerfile for building images in a safe way that will not end up stored in the final image, or be seen in other stages. -The secret will be mounted in the container at the default location of `/run/secrets/id`. +The value of the secret will be read from an environment variable or file named +by the "id" option, or named by the "src" option if it is specified, or from an +environment variable specifed by the "env" option. +The secret will be mounted in the container at `/run/secrets/*id*` by default. To later use the secret, use the --mount flag in a `RUN` instruction within a `Containerfile`: `RUN --mount=type=secret,id=mysecret cat /run/secrets/mysecret` -Note: Changing the contents of secret files will not trigger a rebuild of layers that use said secrets. +The location of the secret in the container can be overridden using the +"target", "dst", or "destination" option of the `RUN --mount` flag. + +`RUN --mount=type=secret,id=mysecret,target=/run/secrets/myothersecret cat /run/secrets/myothersecret` + +Note: changing the contents of secret files will not trigger a rebuild of layers that use said secrets. **--security-opt**=[] diff --git a/pkg/parse/parse.go b/pkg/parse/parse.go index c55133c5525..695b9c334d1 100644 --- a/pkg/parse/parse.go +++ b/pkg/parse/parse.go @@ -57,6 +57,8 @@ const ( BuildahCacheDir = "buildah-cache" ) +var errInvalidSecretSyntax = errors.New("incorrect secret flag format: should be --secret id=foo,src=bar[,env=ENV][,type=file|env]") + // RepoNamesToNamedReferences parse the raw string to Named reference func RepoNamesToNamedReferences(destList []string) ([]reference.Named, error) { var result []reference.Named @@ -1240,7 +1242,6 @@ func GetTempDir() string { // Secrets parses the --secret flag func Secrets(secrets []string) (map[string]define.Secret, error) { - invalidSyntax := fmt.Errorf("incorrect secret flag format: should be --secret id=foo,src=bar[,env=ENV,type=file|env]") parsed := make(map[string]define.Secret) for _, secret := range secrets { tokens := strings.Split(secret, ",") @@ -1260,10 +1261,12 @@ func Secrets(secrets []string) (map[string]define.Secret, error) { return nil, errors.New("invalid secret type, must be file or env") } typ = kv[1] + default: + return nil, errInvalidSecretSyntax } } if id == "" { - return nil, invalidSyntax + return nil, errInvalidSecretSyntax } if src == "" { src = id @@ -1288,6 +1291,7 @@ func Secrets(secrets []string) (map[string]define.Secret, error) { src = fullPath } newSecret := define.Secret{ + ID: id, Source: src, SourceType: typ, } diff --git a/run_common.go b/run_common.go index dca6dfb5b32..8aa07e547d9 100644 --- a/run_common.go +++ b/run_common.go @@ -26,6 +26,7 @@ import ( "github.com/containers/buildah/copier" "github.com/containers/buildah/define" "github.com/containers/buildah/internal" + "github.com/containers/buildah/internal/tmpdir" internalUtil "github.com/containers/buildah/internal/util" "github.com/containers/buildah/internal/volumes" "github.com/containers/buildah/pkg/overlay" @@ -1735,7 +1736,7 @@ func (b *Builder) getSecretMount(tokens []string, secrets map[string]define.Secr if id == "" { return nil, "", errInvalidSyntax } - // Default location for secretis is /run/secrets/id + // Default location for secrets is /run/secrets/id if target == "" { target = "/run/secrets/" + id } @@ -1743,7 +1744,7 @@ func (b *Builder) getSecretMount(tokens []string, secrets map[string]define.Secr secr, ok := secrets[id] if !ok { if required { - return nil, "", fmt.Errorf("secret required but no secret with id %s found", id) + return nil, "", fmt.Errorf("secret required but no secret with id %q found", id) } return nil, "", nil } @@ -1754,7 +1755,7 @@ func (b *Builder) getSecretMount(tokens []string, secrets map[string]define.Secr switch secr.SourceType { case "env": data = []byte(os.Getenv(secr.Source)) - tmpFile, err := os.CreateTemp(define.TempDir, "buildah*") + tmpFile, err := os.CreateTemp(tmpdir.GetTempDir(), "buildah*") if err != nil { return nil, "", err } @@ -1774,7 +1775,7 @@ func (b *Builder) getSecretMount(tokens []string, secrets map[string]define.Secr if err != nil { return nil, "", err } - ctrFileOnHost = filepath.Join(containerWorkingDir, "secrets", id) + ctrFileOnHost = filepath.Join(containerWorkingDir, "secrets", digest.FromString(id).Encoded()[:16]) default: return nil, "", errors.New("invalid source secret type") } @@ -1818,7 +1819,7 @@ func (b *Builder) getSSHMount(tokens []string, count int, sshsources map[string] var id, target string var required bool var uid, gid uint32 - var mode uint32 = 400 + var mode uint32 = 0o600 for _, val := range tokens { kv := strings.SplitN(val, "=", 2) if len(kv) < 2 { @@ -1863,7 +1864,7 @@ func (b *Builder) getSSHMount(tokens []string, count int, sshsources map[string] if id == "" { id = "default" } - // Default location for secretis is /run/buildkit/ssh_agent.{i} + // Default location for secrets is /run/buildkit/ssh_agent.{i} if target == "" { target = fmt.Sprintf("/run/buildkit/ssh_agent.%d", count) } diff --git a/tests/bud.bats b/tests/bud.bats index 02c394a19cd..e825e7e2e91 100644 --- a/tests/bud.bats +++ b/tests/bud.bats @@ -6006,7 +6006,7 @@ _EOF SOMESECRETDATA _EOF - run_buildah bud --secret=id=mysecret,src=${mytmpdir}/mysecret $WITH_POLICY_JSON -t secretmode -f $BUDFILES/run-mounts/Dockerfile.secret-mode $BUDFILES/run-mounts + run_buildah bud --secret=id=mysecret,src=${mytmpdir}/mysecret,type=file $WITH_POLICY_JSON -t secretmode -f $BUDFILES/run-mounts/Dockerfile.secret-mode $BUDFILES/run-mounts expect_output --substring "400" } @@ -6061,6 +6061,10 @@ _EOF run_buildah from secretimg run_buildah 1 run secretimg-working-container cat /run/secrets/mysecret expect_output --substring "cat: can't open '/run/secrets/mysecret': No such file or directory" + + run_buildah 125 build --secret=id=mysecret2,env=MYSECRET,true=false $WITH_POLICY_JSON -f $BUDFILES/run-mounts/Dockerfile.secret $BUDFILES/run-mounts + expect_output --substring "incorrect secret flag format" + run_buildah rm -a }