Add support for --security-opt mask and unmask
Fixes: https://github.com/containers/buildah/issues/5881 Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
This commit is contained in:
parent
996c49d8ec
commit
adf54cde0e
|
@ -62,6 +62,8 @@ type CommonBuildOptions struct {
|
||||||
// LabelOpts is a slice of the fields of an SELinux context, given in "field:pair" format, or "disable".
|
// LabelOpts is a slice of the fields of an SELinux context, given in "field:pair" format, or "disable".
|
||||||
// Recognized field names are "role", "type", and "level".
|
// Recognized field names are "role", "type", and "level".
|
||||||
LabelOpts []string
|
LabelOpts []string
|
||||||
|
// Paths to mask
|
||||||
|
Masks []string
|
||||||
// MemorySwap limits the amount of memory and swap together.
|
// MemorySwap limits the amount of memory and swap together.
|
||||||
MemorySwap int64
|
MemorySwap int64
|
||||||
// NoHostname tells the builder not to create /etc/hostname content when running
|
// NoHostname tells the builder not to create /etc/hostname content when running
|
||||||
|
@ -109,6 +111,8 @@ type CommonBuildOptions struct {
|
||||||
SSHSources []string
|
SSHSources []string
|
||||||
// OCIHooksDir is the location of OCI hooks for the build containers
|
// OCIHooksDir is the location of OCI hooks for the build containers
|
||||||
OCIHooksDir []string
|
OCIHooksDir []string
|
||||||
|
// Paths to unmask
|
||||||
|
Unmasks []string
|
||||||
}
|
}
|
||||||
|
|
||||||
// BuildOptions can be used to alter how an image is built.
|
// BuildOptions can be used to alter how an image is built.
|
||||||
|
|
|
@ -935,11 +935,17 @@ Security Options
|
||||||
"label=type:TYPE" : Set the label type for the container
|
"label=type:TYPE" : Set the label type for the container
|
||||||
"label=level:LEVEL" : Set the label level for the container
|
"label=level:LEVEL" : Set the label level for the container
|
||||||
"label=disable" : Turn off label confinement for the container
|
"label=disable" : Turn off label confinement for the container
|
||||||
|
|
||||||
|
"mask=_/path/1:/path/2_": The paths to mask separated by a colon. A masked path cannot be accessed inside the container.
|
||||||
|
|
||||||
"no-new-privileges" : Disable container processes from gaining additional privileges
|
"no-new-privileges" : Disable container processes from gaining additional privileges
|
||||||
|
|
||||||
"seccomp=unconfined" : Turn off seccomp confinement for the container
|
"seccomp=unconfined" : Turn off seccomp confinement for the container
|
||||||
"seccomp=profile.json : JSON configuration for a seccomp filter
|
"seccomp=profile.json : JSON configuration for a seccomp filter
|
||||||
|
|
||||||
|
"unmask=_ALL_ or _/path/1:/path/2_, or shell expanded paths (/proc/*): Paths to unmask separated by a colon. If set to **ALL**, it unmasks all the paths that are masked or made read-only by default.
|
||||||
|
The default masked paths are **/proc/acpi, /proc/kcore, /proc/keys, /proc/latency_stats, /proc/sched_debug, /proc/scsi, /proc/timer_list, /proc/timer_stats, /sys/firmware, and /sys/fs/selinux**, **/sys/devices/virtual/powercap**. The default paths that are read-only are **/proc/asound**, **/proc/bus**, **/proc/fs**, **/proc/irq**, **/proc/sys**, **/proc/sysrq-trigger**, **/sys/fs/cgroup**.
|
||||||
|
|
||||||
**--shm-size**=""
|
**--shm-size**=""
|
||||||
|
|
||||||
Size of `/dev/shm`. The format is `<number><unit>`. `number` must be greater than `0`.
|
Size of `/dev/shm`. The format is `<number><unit>`. `number` must be greater than `0`.
|
||||||
|
|
Binary file not shown.
|
@ -249,6 +249,18 @@ func parseSecurityOpts(securityOpts []string, commonOpts *define.CommonBuildOpti
|
||||||
commonOpts.ApparmorProfile = con[1]
|
commonOpts.ApparmorProfile = con[1]
|
||||||
case "seccomp":
|
case "seccomp":
|
||||||
commonOpts.SeccompProfilePath = con[1]
|
commonOpts.SeccompProfilePath = con[1]
|
||||||
|
case "mask":
|
||||||
|
commonOpts.Masks = append(commonOpts.Masks, strings.Split(con[1], ":")...)
|
||||||
|
case "unmask":
|
||||||
|
unmasks := strings.Split(con[1], ":")
|
||||||
|
for _, unmask := range unmasks {
|
||||||
|
matches, _ := filepath.Glob(unmask)
|
||||||
|
if len(matches) > 0 {
|
||||||
|
commonOpts.Unmasks = append(commonOpts.Unmasks, matches...)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
commonOpts.Unmasks = append(commonOpts.Unmasks, unmask)
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("invalid --security-opt 2: %q", opt)
|
return fmt.Errorf("invalid --security-opt 2: %q", opt)
|
||||||
}
|
}
|
||||||
|
|
12
run_linux.go
12
run_linux.go
|
@ -328,7 +328,7 @@ func (b *Builder) Run(command []string, options RunOptions) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setupMaskedPaths(g)
|
setupMaskedPaths(g, b.CommonBuildOpts)
|
||||||
setupReadOnlyPaths(g)
|
setupReadOnlyPaths(g)
|
||||||
|
|
||||||
setupTerminal(g, options.Terminal, options.TerminalSize)
|
setupTerminal(g, options.Terminal, options.TerminalSize)
|
||||||
|
@ -1199,8 +1199,14 @@ func (b *Builder) runSetupVolumeMounts(mountLabel string, volumeMounts []string,
|
||||||
return mounts, nil
|
return mounts, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func setupMaskedPaths(g *generate.Generator) {
|
func setupMaskedPaths(g *generate.Generator, opts *define.CommonBuildOptions) {
|
||||||
for _, mp := range config.DefaultMaskedPaths {
|
if slices.Contains(opts.Unmasks, "all") {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, mp := range append(config.DefaultMaskedPaths, opts.Masks...) {
|
||||||
|
if slices.Contains(opts.Unmasks, mp) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
g.AddLinuxMaskedPaths(mp)
|
g.AddLinuxMaskedPaths(mp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7125,3 +7125,16 @@ EOF
|
||||||
echo RUN --mount=type=tmpfs,target=tmpfssubdir test '`stat -f -c %i .`' '!=' '`stat -f -c %i tmpfssubdir`' >> ${TEST_SCRATCH_DIR}/Containerfile
|
echo RUN --mount=type=tmpfs,target=tmpfssubdir test '`stat -f -c %i .`' '!=' '`stat -f -c %i tmpfssubdir`' >> ${TEST_SCRATCH_DIR}/Containerfile
|
||||||
run_buildah build --security-opt label=disable ${TEST_SCRATCH_DIR}
|
run_buildah build --security-opt label=disable ${TEST_SCRATCH_DIR}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@test "build-security-opt-mask" {
|
||||||
|
base=busybox
|
||||||
|
_prefetch $base
|
||||||
|
run_buildah build bud/masks
|
||||||
|
expect_output --substring "masked" "Everything should be masked"
|
||||||
|
run_buildah build --security-opt unmask=all bud/masks
|
||||||
|
expect_output --substring "unmasked" "Everything should be masked"
|
||||||
|
run_buildah build --security-opt unmask=/proc/* bud/masks
|
||||||
|
expect_output --substring "unmasked" "Everything should be masked"
|
||||||
|
run_buildah build --security-opt unmask=/proc/acpi bud/masks
|
||||||
|
expect_output --substring "unmasked" "Everything should be masked"
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
FROM alpine
|
||||||
|
COPY --chmod=700 test.sh /
|
||||||
|
RUN /test.sh
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
# !/bin/sh
|
||||||
|
|
||||||
|
function output {
|
||||||
|
for mask in /proc/acpi /proc/kcore /proc/keys /proc/latency_stats /proc/sched_debug /proc/scsi /proc/timer_list /proc/timer_stats /sys/dev/block /sys/devices/virtual/powercap /sys/firmware /sys/fs/selinux; do
|
||||||
|
test -e $mask || continue
|
||||||
|
test -f $mask && cat $mask 2> /dev/null
|
||||||
|
test -d $mask && ls $mask
|
||||||
|
done
|
||||||
|
}
|
||||||
|
output=$(output | wc -c )
|
||||||
|
if [ $output == 0 ]; then
|
||||||
|
echo "masked"
|
||||||
|
else
|
||||||
|
echo "unmasked"
|
||||||
|
fi
|
Loading…
Reference in New Issue