Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test namespace flags of 'bud' subcommand #3173

Merged
merged 2 commits into from
Apr 27, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions tests/bud/namespaces/Containerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
FROM alpine
RUN echo "ReadlinkResult" && readlink /proc/self/ns/user
RUN echo "UidMapResult" && cat /proc/self/uid_map
RUN echo "GidMapResult" && cat /proc/self/gid_map
COPY --chown=1:1 somefile /
RUN echo "StatSomefileResult" && stat -c '%u:%g' /somefile
COPY somedir /somedir
RUN echo "StatSomedirResult" && stat -c '%u:%g' /somedir
RUN echo "StatSomeotherfileResult" && stat -c '%u:%g %a' /somedir/someotherfile
160 changes: 116 additions & 44 deletions tests/namespaces.bats
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,51 @@ load helpers
fi
}

idmapping_check_namespace() {
local _uidmapargs=$1
local _gidmapargs=$2
local _mynamespace=$3
local _output=$4

[ "$_output" != "" ]
if [ -z "${_uidmapargs}${_gidmapargs}" ]; then
if test "$BUILDAH_ISOLATION" != "chroot" -a "$BUILDAH_ISOLATION" != "rootless" ; then
expect_output --from="$_output" "$_mynamespace"
fi
else
[ "$_output" != "$_mynamespace" ]
fi
}

idmapping_check_map() {
local _output_uidmap=$1
local _output_gidmap=$2
local _expect_uidmap=$3
local _expect_gidmap=$4

[ -n "$_output_uidmap" ]
local uidmap=$(sed -E -e 's, +, ,g' -e 's,^ +,,g' <<< "${_output_uidmap}")
[ -n "$_output_gidmap" ]
local gidmap=$(sed -E -e 's, +, ,g' -e 's,^ +,,g' <<< "${_output_gidmap}")
echo expected UID map "${_expect_uidmap}", got UID map "${uidmap}", expected GID map "${_expect_gid_map}", got GID map "${gidmap}".
expect_output --from="$uidmap" "${_expect_uidmap}"
expect_output --from="$gidmap" "${_expect_gidmap}"
# these vars are global
rootuid=$(sed -E -e 's,^([^ ]*) (.*) ([^ ]*),\2,' <<< "$uidmap")
rootgid=$(sed -E -e 's,^([^ ]*) (.*) ([^ ]*),\2,' <<< "$gidmap")
}

idmapping_check_permission() {
local _output_file_stat=$1
local _output_dir_stat=$2
local _output_otherfile_stat=$3
local _expect_otherfile_stat=$4

expect_output --from="${_output_file_stat}" "1:1" "Check if a copied file gets the right permissions"
expect_output --from="${_output_dir_stat}" "0:0" "Check if a copied directory gets the right permissions"
expect_output --from="${_output_otherfile_stat}" "${_expect_otherfile_stat}" "Check if another copied file gets the right permissions"
}

@test "idmapping" {
mkdir -p $TESTDIR/no-cni-configs
RUNOPTS="--cni-config-dir=${TESTDIR}/no-cni-configs ${RUNC_BINARY:+--runtime $RUNC_BINARY}"
Expand Down Expand Up @@ -163,55 +208,65 @@ load helpers

# If we specified mappings, expect to be in a different namespace by default.
run_buildah run $RUNOPTS "$ctr" readlink /proc/self/ns/user
[ "$output" != "" ]
case x"${uidmapargs[$i]}""${gidmapargs[$i]}" in
x)
if test "$BUILDAH_ISOLATION" != "chroot" -a "$BUILDAH_ISOLATION" != "rootless" ; then
expect_output "$mynamespace"
fi
;;
*)
[ "$output" != "$mynamespace" ]
;;
esac
idmapping_check_namespace "${uidmapargs[$i]}" "${gidmapargs[$i]}" "$mynamespace" "$output"
# Check that we got the mappings that we expected.
run_buildah run $RUNOPTS "$ctr" cat /proc/self/uid_map
[ "$output" != "" ]
uidmap=$(sed -E -e 's, +, ,g' -e 's,^ +,,g' <<< "$output")
output_uidmap="$output"
run_buildah run $RUNOPTS "$ctr" cat /proc/self/gid_map
[ "$output" != "" ]
gidmap=$(sed -E -e 's, +, ,g' -e 's,^ +,,g' <<< "$output")
echo With settings "$map", expected UID map "${uidmaps[$i]}", got UID map "${uidmap}", expected GID map "${gidmaps[$i]}", got GID map "${gidmap}".
expect_output --from="$uidmap" "${uidmaps[$i]}"
expect_output --from="$gidmap" "${gidmaps[$i]}"
rootuid=$(sed -E -e 's,^([^ ]*) (.*) ([^ ]*),\2,' <<< "$uidmap")
rootgid=$(sed -E -e 's,^([^ ]*) (.*) ([^ ]*),\2,' <<< "$gidmap")
output_gidmap="$output"
idmapping_check_map "$output_uidmap" "$output_gidmap" "${uidmaps[$i]}" "${gidmaps[$i]}"

# Check that if we copy a file into the container, it gets the right permissions.
run_buildah copy --chown 1:1 "$ctr" ${TESTDIR}/somefile /
run_buildah run $RUNOPTS "$ctr" stat -c '%u:%g' /somefile
expect_output "1:1"

output_file_stat="$output"
# Check that if we copy a directory into the container, its contents get the right permissions.
run_buildah copy "$ctr" ${TESTDIR}/somedir /somedir
run_buildah run $RUNOPTS "$ctr" stat -c '%u:%g' /somedir
expect_output "0:0"
output_dir_stat="$output"
run_buildah run $RUNOPTS "$ctr" stat -c '%u:%g %a' /somedir/someotherfile
output_otherfile_stat="$output"
idmapping_check_permission "$output_file_stat" "$output_dir_stat" "$output_otherfile_stat" "0:0 4700"

# Check that the copied file has the right permissions on host.
run_buildah mount "$ctr"
mnt="$output"
run stat -c '%u:%g %a' "$mnt"/somedir/someotherfile
[ $status -eq 0 ]
expect_output "$rootuid:$rootgid 4700"
run_buildah run $RUNOPTS "$ctr" stat -c '%u:%g %a' /somedir/someotherfile
expect_output "0:0 4700"

# Check that a container with mapped-layer can be committed.
run_buildah commit "$ctr" localhost/alpine-working:$i


# Also test bud command
Comment on lines +240 to +242
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The idmapping test was unmaintainable even before this addition; it is now even more so. I like the addition, and it is well done, but I wonder if you could take some time to find a way to refactor this, perhaps by crafting one or more smaller helper functions?

# Build an image using these mappings.
echo "Building image with ${uidmapargs[$i]} ${gidmapargs[$i]}"
run_buildah bud ${uidmapargs[$i]} ${gidmapargs[$i]} $RUNOPTS --signature-policy ${TESTSDIR}/policy.json \
-t localhost/alpine-bud:$i -f ${TESTSDIR}/bud/namespaces/Containerfile $TESTDIR
# If we specified mappings, expect to be in a different namespace by default.
output_namespace="$(grep -A1 'ReadlinkResult' <<< "$output" | tail -n1)"
idmapping_check_namespace "${uidmapargs[$i]}" "${gidmapargs[$i]}" "$mynamespace" "$output_namespace"
# Check that we got the mappings that we expected.
output_uidmap="$(grep -A1 'UidMapResult' <<< "$output" | tail -n1)"
output_gidmap="$(grep -A1 'GidMapResult' <<< "$output" | tail -n1)"
idmapping_check_map "$output_uidmap" "$output_gidmap" "${uidmaps[$i]}" "${gidmaps[$i]}"

# Check that if we copy a file into the container, it gets the right permissions.
output_file_stat="$(grep -A1 'StatSomefileResult' <<< "$output" | tail -n1)"
# Check that if we copy a directory into the container, its contents get the right permissions.
output_dir_stat="$(grep -A1 'StatSomedirResult' <<< "$output" | tail -n1)"
output_otherfile_stat="$(grep -A1 'StatSomeotherfileResult' <<< "$output" | tail -n1)"
# bud strips suid.
idmapping_check_permission "$output_file_stat" "$output_dir_stat" "$output_otherfile_stat" "0:0 700"
done
}

general_namespace() {
mkdir -p $TESTDIR/no-cni-configs
RUNOPTS="--cni-config-dir=${TESTDIR}/no-cni-configs ${RUNC_BINARY:+--runtime $RUNC_BINARY}"
mytmpdir=$TESTDIR/my-dir
mkdir -p ${mytmpdir}

# The name of the /proc/self/ns/$link.
nstype="$1"
Expand Down Expand Up @@ -254,27 +309,44 @@ general_namespace() {
;;
esac

if [ "$nsflag" = "userns" ]; then
# "run" doesn't have --userns option.
continue
# "run" doesn't have --userns option.
if [ "$nsflag" != "userns" ]; then
for different in ${types[@]} ; do
# Check that, if we override it, we get what we specify for "run".
run_buildah run $RUNOPTS --"$nsflag"=$different "$ctr" readlink /proc/self/ns/"$nstype"
[ "$output" != "" ]
case "$different" in
""|container|private)
[ "$output" != "$mynamespace" ]
;;
host)
expect_output "$mynamespace"
;;
/*)
expect_output "$(readlink $different)"
;;
esac
done
fi

for different in ${types[@]} ; do
# Check that, if we override it, we get what we specify for "run".
run_buildah run $RUNOPTS --"$nsflag"=$different "$ctr" readlink /proc/self/ns/"$nstype"
[ "$output" != "" ]
case "$different" in
""|container|private)
[ "$output" != "$mynamespace" ]
;;
host)
expect_output "$mynamespace"
;;
/*)
expect_output "$(readlink $different)"
;;
esac
done
# Also check "from" command
cat > $mytmpdir/Containerfile << _EOF
FROM alpine
RUN echo "TargetOutput" && readlink /proc/self/ns/$nstype
_EOF
run_buildah bud --"$nsflag"=$namespace $RUNOPTS --signature-policy ${TESTSDIR}/policy.json --file ${mytmpdir} .
result=$(grep -A1 "TargetOutput" <<< "$output" | tail -n1)
case "$namespace" in
""|container|private)
[ "$result" != "$mynamespace" ]
;;
host)
expect_output --from="$result" "$mynamespace"
;;
/*)
expect_output --from="$result" "$(readlink $namespace)"
;;
esac

done
}
Expand Down