From deb9c69efe89a0f74582402f8a383ef8d4591186 Mon Sep 17 00:00:00 2001 From: Daniel J Walsh Date: Mon, 7 Mar 2022 15:44:14 -0500 Subject: [PATCH] Add --no-hosts flag to eliminate use of /etc/hosts within containers Users want to turn off addition of /etc/hosts file while building container images, this would allow them to customize the /etc/hosts file within the image. Fixes: https://github.com/containers/buildah/issues/3808 Signed-off-by: Daniel J Walsh --- cmd/buildah/run.go | 3 +++ define/build.go | 7 +++++-- docs/buildah-build.1.md | 9 ++++++++- docs/buildah-run.1.md | 7 +++++++ imagebuildah/executor.go | 2 ++ imagebuildah/stage_executor.go | 1 + pkg/cli/common.go | 2 ++ pkg/parse/parse.go | 6 ++++++ run.go | 2 ++ run_linux.go | 2 +- tests/bud.bats | 9 +++++++++ tests/run.bats | 6 ++++-- 12 files changed, 50 insertions(+), 6 deletions(-) diff --git a/cmd/buildah/run.go b/cmd/buildah/run.go index 908726b52e..7f81966410 100644 --- a/cmd/buildah/run.go +++ b/cmd/buildah/run.go @@ -24,6 +24,7 @@ type runInputOptions struct { mounts []string runtime string runtimeFlag []string + noHosts bool noPivot bool terminal bool volumes []string @@ -66,6 +67,7 @@ func init() { // Do not set a default runtime here, we'll do that later in the processing. flags.StringVar(&opts.runtime, "runtime", util.Runtime(), "`path` to an alternate OCI runtime") flags.StringSliceVar(&opts.runtimeFlag, "runtime-flag", []string{}, "add global flags for the container runtime") + flags.BoolVar(&opts.noHosts, "no-hosts", false, "do not override the /etc/hosts file within the container") flags.BoolVar(&opts.noPivot, "no-pivot", false, "do not use pivot root to jail process inside rootfs") flags.BoolVarP(&opts.terminal, "terminal", "t", false, "allocate a pseudo-TTY in the container") flags.StringArrayVarP(&opts.volumes, "volume", "v", []string{}, "bind mount a host location into the container while running the command") @@ -127,6 +129,7 @@ func runCmd(c *cobra.Command, args []string, iopts runInputOptions) error { Hostname: iopts.hostname, Runtime: iopts.runtime, Args: runtimeFlags, + NoHosts: iopts.noHosts, NoPivot: noPivot, User: c.Flag("user").Value.String(), Isolation: isolation, diff --git a/define/build.go b/define/build.go index 23c0ba0a2e..6484915317 100644 --- a/define/build.go +++ b/define/build.go @@ -37,11 +37,14 @@ type CommonBuildOptions struct { DNSServers []string // DNSOptions is the list of DNS DNSOptions []string - // MemorySwap limits the amount of memory and swap together. - MemorySwap int64 // LabelOpts is the a slice of fields of an SELinux context, given in "field:pair" format, or "disable". // Recognized field names are "role", "type", and "level". LabelOpts []string + // MemorySwap limits the amount of memory and swap together. + MemorySwap int64 + // NoHosts tells the builder not to create /etc/hosts content when running + // containers. + NoHosts bool // OmitTimestamp forces epoch 0 as created timestamp to allow for // deterministic, content-addressable builds. OmitTimestamp bool diff --git a/docs/buildah-build.1.md b/docs/buildah-build.1.md index 6ea425875d..c2b60a9ddf 100644 --- a/docs/buildah-build.1.md +++ b/docs/buildah-build.1.md @@ -32,7 +32,7 @@ When a Git repository is set as the URL, the repository is cloned locally and th Add a custom host-to-IP mapping (host:ip) -Add a line to /etc/hosts. The format is hostname:ip. The **--add-host** option can be set multiple times. +Add a line to /etc/hosts. The format is hostname:ip. The **--add-host** option can be set multiple times. Conflicts with the --no-hosts option. **--all-platforms** @@ -396,6 +396,13 @@ Valid _mode_ values are: Do not use existing cached images for the container build. Build from the start with a new set of cached layers. +**--no-hosts** + +Do not create _/etc/hosts_ for the container. + +By default, Buildah manages _/etc/hosts_, adding the container's own IP address. +**--no-hosts** disables this, and the image's _/etc/hosts_ will be preserved unmodified. Conflicts with the --add-host option. + **--os**="OS" Set the OS of the image to be built, and that of the base image to be pulled, if the build uses one, instead of using the current operating system of the host. diff --git a/docs/buildah-run.1.md b/docs/buildah-run.1.md index 30068121ff..1ad6a4299a 100644 --- a/docs/buildah-run.1.md +++ b/docs/buildah-run.1.md @@ -182,6 +182,13 @@ consult the manpages of the selected container runtime. Note: Do not pass the leading `--` to the flag. To pass the runc flag `--log-format json` to buildah run, the option given would be `--runtime-flag log-format=json`. +**--no-hosts** + +Do not create _/etc/hosts_ for the container. + +By default, Buildah manages _/etc/hosts_, adding the container's own IP address. +**--no-hosts** disables this, and the image's _/etc/hosts_ will be preserved unmodified. + **--no-pivot** Do not use pivot root to jail process inside rootfs. This should be used diff --git a/imagebuildah/executor.go b/imagebuildah/executor.go index 5183456d0d..bbc1def0c4 100644 --- a/imagebuildah/executor.go +++ b/imagebuildah/executor.go @@ -96,6 +96,7 @@ type Executor struct { labels []string annotations []string layers bool + noHosts bool useCache bool removeIntermediateCtrs bool forceRmIntermediateCtrs bool @@ -245,6 +246,7 @@ func newExecutor(logger *logrus.Logger, logPrefix string, store storage.Store, o labels: append([]string{}, options.Labels...), annotations: append([]string{}, options.Annotations...), layers: options.Layers, + noHosts: options.CommonBuildOpts.NoHosts, useCache: !options.NoCache, removeIntermediateCtrs: options.RemoveIntermediateCtrs, forceRmIntermediateCtrs: options.ForceRmIntermediateCtrs, diff --git a/imagebuildah/stage_executor.go b/imagebuildah/stage_executor.go index 9567d62797..d2b635b487 100644 --- a/imagebuildah/stage_executor.go +++ b/imagebuildah/stage_executor.go @@ -495,6 +495,7 @@ func (s *StageExecutor) Run(run imagebuilder.Run, config docker.Config) error { Hostname: config.Hostname, Runtime: s.executor.runtime, Args: s.executor.runtimeArgs, + NoHosts: s.executor.noHosts, NoPivot: os.Getenv("BUILDAH_NOPIVOT") != "", Mounts: append([]Mount{}, s.executor.transientMounts...), Env: config.Env, diff --git a/pkg/cli/common.go b/pkg/cli/common.go index d05fbde7c2..bce497f290 100644 --- a/pkg/cli/common.go +++ b/pkg/cli/common.go @@ -67,6 +67,7 @@ type BudResults struct { Label []string Logfile string Manifest string + NoHosts bool NoCache bool Timestamp int64 Pull string @@ -212,6 +213,7 @@ func GetBudFlags(flags *BudResults) pflag.FlagSet { panic(fmt.Sprintf("error marking the rusage-logfile flag as hidden: %v", err)) } fs.StringVar(&flags.Manifest, "manifest", "", "add the image to the specified manifest list. Creates manifest list if it does not exist") + fs.BoolVar(&flags.NoHosts, "no-hosts", false, "Do not create the new containers /etc/hosts file, use the one from the current image.") fs.BoolVar(&flags.NoCache, "no-cache", false, "Do not use existing cached images for the container build. Build from the start with a new set of cached layers.") fs.String("os", runtime.GOOS, "set the OS to the provided value instead of the current operating system of the host") fs.StringVar(&flags.Pull, "pull", "true", "pull the image from the registry if newer or not present in store, if false, only pull the image if not present, if always, pull the image even if the named image is present in store, if never, only use the image present in store if available") diff --git a/pkg/parse/parse.go b/pkg/parse/parse.go index b57b36a625..9951c8815a 100644 --- a/pkg/parse/parse.go +++ b/pkg/parse/parse.go @@ -86,8 +86,13 @@ func CommonBuildOptionsFromFlagSet(flags *pflag.FlagSet, findFlagFunc func(name } } + noHosts, _ := flags.GetBool("no-hosts") + addHost, _ := flags.GetStringSlice("add-host") if len(addHost) > 0 { + if noHosts { + return nil, errors.Errorf("--no-hosts and --add-host conflict, can not be used together") + } for _, host := range addHost { if err := validateExtraHost(host); err != nil { return nil, errors.Wrapf(err, "invalid value for add-host") @@ -159,6 +164,7 @@ func CommonBuildOptionsFromFlagSet(flags *pflag.FlagSet, findFlagFunc func(name HTTPProxy: httpProxy, Memory: memoryLimit, MemorySwap: memorySwap, + NoHosts: noHosts, ShmSize: findFlagFunc("shm-size").Value.String(), Ulimit: ulimit, Volumes: volumes, diff --git a/run.go b/run.go index ae39072780..64d4e0979d 100644 --- a/run.go +++ b/run.go @@ -85,6 +85,8 @@ type RunOptions struct { Runtime string // Args adds global arguments for the runtime. Args []string + // NoHosts use the images /etc/hosts file + NoHosts bool // NoPivot adds the --no-pivot runtime flag. NoPivot bool // Mounts are additional mount points which we want to provide. diff --git a/run_linux.go b/run_linux.go index 794636bf4c..d69f5431b0 100644 --- a/run_linux.go +++ b/run_linux.go @@ -210,7 +210,7 @@ func (b *Builder) Run(command []string, options RunOptions) error { namespaceOptions := append(b.NamespaceOptions, options.NamespaceOptions...) volumes := b.Volumes() - if !contains(volumes, "/etc/hosts") { + if !options.NoHosts && !contains(volumes, "/etc/hosts") { hostFile, err := b.generateHosts(path, spec.Hostname, b.CommonBuildOpts.AddHost, rootIDPair) if err != nil { return err diff --git a/tests/bud.bats b/tests/bud.bats index ac98a007e7..d7d2a0cc9f 100644 --- a/tests/bud.bats +++ b/tests/bud.bats @@ -3174,6 +3174,15 @@ _EOF run_buildah build --add-host=myhostname:$ip -t testbud \ --signature-policy ${TESTSDIR}/policy.json --file ${mytmpdir} . expect_output --from="${lines[2]}" --substring "^$ip\s+myhostname" + + run_buildah 125 build --no-cache --add-host=myhostname:$ip \ + --no-hosts \ + --signature-policy ${TESTSDIR}/policy.json --file ${mytmpdir} . + expect_output --substring "\-\-no-hosts and \-\-add-host conflict, can not be used together" + + run_buildah 1 build --no-cache --no-hosts \ + --signature-policy ${TESTSDIR}/policy.json --file ${mytmpdir} . + expect_output --substring 'error building at STEP "RUN grep "myhostname" /etc/hosts' } @test "bud with --cgroup-parent" { diff --git a/tests/run.bats b/tests/run.bats index c5ef7e4af7..ffb593d1e7 100644 --- a/tests/run.bats +++ b/tests/run.bats @@ -594,8 +594,7 @@ function configure_and_check_user() { run_buildah from --quiet --pull=false --signature-policy ${TESTSDIR}/policy.json debian cid=$output run_buildah 125 run --network=bogus $cid cat /etc/hosts - expect_output --substring "unable to find network with name or ID bogus: network not found" - + expect_output --substring "unable to find network with name or ID bogus: network not found" run_buildah run $cid cat /etc/hosts expect_output --substring "127.0.0.1.*$cid" expect_output --substring "::1.*$cid" @@ -613,11 +612,14 @@ function configure_and_check_user() { run_buildah from --quiet --pull=false --signature-policy ${TESTSDIR}/policy.json debian cid=$output run_buildah run --network=host $cid cat /etc/hosts + hostOutput=$output expect_output --substring "# Generated by Buildah" m=$(buildah mount $cid) run cat $m/etc/hosts [ "$status" -eq 0 ] expect_output --substring "" + run_buildah run --network=host --no-hosts $cid cat /etc/hosts + [ "$output" != "$hostOutput" ] run_buildah rm -a run_buildah from --quiet --pull=false --signature-policy ${TESTSDIR}/policy.json debian