Skip to content

Commit

Permalink
Document more buildah build --secret options
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
nalind committed Oct 17, 2024
1 parent 5518774 commit 6c85740
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 14 deletions.
14 changes: 11 additions & 3 deletions docs/buildah-build.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -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**=[]

Expand Down
8 changes: 6 additions & 2 deletions pkg/parse/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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, ",")
Expand All @@ -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
Expand All @@ -1288,6 +1291,7 @@ func Secrets(secrets []string) (map[string]define.Secret, error) {
src = fullPath
}
newSecret := define.Secret{
ID: id,
Source: src,
SourceType: typ,
}
Expand Down
13 changes: 7 additions & 6 deletions run_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -1735,15 +1736,15 @@ 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
}

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
}
Expand All @@ -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
}
Expand All @@ -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")
}
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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)
}
Expand Down
10 changes: 7 additions & 3 deletions tests/bud.bats
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}

Expand Down Expand Up @@ -6037,11 +6037,11 @@ _EOF
_prefetch alpine

run_buildah 125 build $WITH_POLICY_JSON -t secretreq -f $BUDFILES/run-mounts/Dockerfile.secret-required $BUDFILES/run-mounts
expect_output --substring "secret required but no secret with id mysecret found"
expect_output --substring 'secret required but no secret with id "mysecret" found'

# Also test secret required without value
run_buildah 125 build $WITH_POLICY_JSON -t secretreq -f $BUDFILES/run-mounts/Dockerfile.secret-required-wo-value $BUDFILES/run-mounts
expect_output --substring "secret required but no secret with id mysecret found"
expect_output --substring 'secret required but no secret with id "mysecret" found'
}

@test "bud with containerfile env secret" {
Expand All @@ -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
}

Expand Down

0 comments on commit 6c85740

Please sign in to comment.