github.com/opensuse/umoci@v0.4.2/test/unpack.bats (about)

     1  #!/usr/bin/env bats -t
     2  # umoci: Umoci Modifies Open Containers' Images
     3  # Copyright (C) 2016, 2017, 2018 SUSE LLC.
     4  #
     5  # Licensed under the Apache License, Version 2.0 (the "License");
     6  # you may not use this file except in compliance with the License.
     7  # You may obtain a copy of the License at
     8  #
     9  #   http://www.apache.org/licenses/LICENSE-2.0
    10  #
    11  # Unless required by applicable law or agreed to in writing, software
    12  # distributed under the License is distributed on an "AS IS" BASIS,
    13  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14  # See the License for the specific language governing permissions and
    15  # limitations under the License.
    16  
    17  load helpers
    18  
    19  function setup() {
    20  	setup_image
    21  }
    22  
    23  function teardown() {
    24  	teardown_tmpdirs
    25  	teardown_image
    26  }
    27  
    28  @test "umoci unpack" {
    29  	# Unpack the image.
    30  	new_bundle_rootfs
    31  	umoci unpack --image "${IMAGE}:${TAG}" "$BUNDLE"
    32  	[ "$status" -eq 0 ]
    33  	bundle-verify "$BUNDLE"
    34  
    35  	# We need to make sure these files properly exist.
    36  	[ -f "$BUNDLE/config.json" ]
    37  	[ -d "$ROOTFS" ]
    38  
    39  	# Check that the image appears about right.
    40  	# NOTE: Since we could be using different images, this will be fairly
    41  	#	   generic.
    42  	[ -e "$ROOTFS/bin/sh" ]
    43  	[ -e "$ROOTFS/etc/passwd" ]
    44  	[ -e "$ROOTFS/etc/group" ]
    45  
    46  	# Ensure that gomtree suceeds on the unpacked bundle.
    47  	gomtree -p "$ROOTFS" -f "$BUNDLE"/sha256_*.mtree
    48  	[ "$status" -eq 0 ]
    49  	[ -z "$output" ]
    50  
    51  	# Make sure that unpack fails without a bundle path.
    52  	umoci unpack --image "${IMAGE}:${TAG}"
    53  	[ "$status" -ne 0 ]
    54  	# ... or with too many
    55  	umoci unpack --image "${IMAGE}:${TAG}" too many arguments
    56  	[ "$status" -ne 0 ]
    57  	! [ -d too ]
    58  	! [ -d many ]
    59  	! [ -d arguments ]
    60  
    61  	image-verify "${IMAGE}"
    62  }
    63  
    64  @test "umoci unpack [missing args]" {
    65  	umoci unpack --image="${IMAGE}:${TAG}"
    66  	[ "$status" -ne 0 ]
    67  
    68  	new_bundle_rootfs
    69  	umoci unpack "$BUNDLE"
    70  	[ "$status" -ne 0 ]
    71  }
    72  
    73  @test "umoci unpack [config.json contains mount namespace]" {
    74  	# Unpack the image.
    75  	new_bundle_rootfs
    76  	umoci unpack --image "${IMAGE}:${TAG}" "$BUNDLE"
    77  	[ "$status" -eq 0 ]
    78  	bundle-verify "$BUNDLE"
    79  
    80  	# Ensure that we have a mount namespace enabled.
    81  	sane_run jq -SM 'any(.linux.namespaces[] | .type; . == "mount")' "$BUNDLE/config.json"
    82  	[ "$status" -eq 0 ]
    83  	[[ "$output" == "true" ]]
    84  
    85  	image-verify "${IMAGE}"
    86  }
    87  
    88  @test "umoci unpack [consistent results]" {
    89  	# Unpack the image.
    90  	new_bundle_rootfs && BUNDLE_A="$BUNDLE" ROOTFS_A="$ROOTFS"
    91  	umoci unpack --image "${IMAGE}:${TAG}" "$BUNDLE"
    92  	[ "$status" -eq 0 ]
    93  	bundle-verify "$BUNDLE"
    94  
    95  	# Wait a beat.
    96  	sleep 5s
    97  
    98  	# Unpack it again.
    99  	new_bundle_rootfs && BUNDLE_B="$BUNDLE" ROOTFS_B="$ROOTFS"
   100  	umoci unpack --image "${IMAGE}:${TAG}" "$BUNDLE"
   101  	[ "$status" -eq 0 ]
   102  	bundle-verify "$BUNDLE"
   103  
   104  	# Ensure that gomtree cross-succeeds.
   105  	gomtree -p "$ROOTFS_A" -f "$BUNDLE_B"/sha256_*.mtree
   106  	[ "$status" -eq 0 ]
   107  	[ -z "$output" ]
   108  	gomtree -p "$ROOTFS_B" -f "$BUNDLE_A"/sha256_*.mtree
   109  	[ "$status" -eq 0 ]
   110  	[ -z "$output" ]
   111  
   112  	image-verify "${IMAGE}"
   113  }
   114  
   115  @test "umoci unpack [setuid]" {
   116  	# Unpack the image.
   117  	new_bundle_rootfs
   118  	umoci unpack --image "${IMAGE}:${TAG}" "$BUNDLE"
   119  	[ "$status" -eq 0 ]
   120  	bundle-verify "$BUNDLE"
   121  
   122  	# Make some files setuid and setgid.
   123  	touch "$ROOTFS/setuid"  && chmod u+xs  "$ROOTFS/setuid"
   124  	touch "$ROOTFS/setgid"  && chmod g+xs  "$ROOTFS/setgid"
   125  	touch "$ROOTFS/setugid" && chmod ug+xs "$ROOTFS/setugid"
   126  
   127  	# Repack the image.
   128  	umoci repack --image "${IMAGE}:${TAG}" "$BUNDLE"
   129  	[ "$status" -eq 0 ]
   130  	image-verify "${IMAGE}"
   131  
   132  	# Unpack the image.
   133  	new_bundle_rootfs
   134  	umoci unpack --image "${IMAGE}:${TAG}" "$BUNDLE"
   135  	[ "$status" -eq 0 ]
   136  	bundle-verify "$BUNDLE"
   137  
   138  	# Check that the set{uid,gid} bits were preserved.
   139  	[ -u "$ROOTFS/setuid" ]
   140  	[ -g "$ROOTFS/setgid" ]
   141  	[ -u "$ROOTFS/setugid" ] && [ -g "$ROOTFS/setugid" ]
   142  
   143  	image-verify "${IMAGE}"
   144  }
   145  
   146  @test "umoci unpack [setcap]" {
   147  	# We need to setcap which requires root on quite a few kernels -- and we
   148  	# don't support v3 capabilities yet (which allow us as an unprivileged user
   149  	# to write capabilities).
   150  	requires root
   151  
   152  	# Unpack the image.
   153  	new_bundle_rootfs
   154  	umoci unpack --image "${IMAGE}:${TAG}" "$BUNDLE"
   155  	[ "$status" -eq 0 ]
   156  	bundle-verify "$BUNDLE"
   157  
   158  	# Make some files setuid and setgid.
   159  	touch "$ROOTFS/setcap1" && setcap "cap_net_raw+eip" "$ROOTFS/setcap1"
   160  	touch "$ROOTFS/setcap2" && setcap "cap_sys_admin,cap_setfcap+eip" "$ROOTFS/setcap2"
   161  
   162  	# Repack the image.
   163  	umoci repack --image "${IMAGE}:${TAG}" "$BUNDLE"
   164  	[ "$status" -eq 0 ]
   165  	image-verify "${IMAGE}"
   166  
   167  	# Unpack the image (as root).
   168  	new_bundle_rootfs
   169  	umoci unpack --image "${IMAGE}:${TAG}" "$BUNDLE"
   170  	[ "$status" -eq 0 ]
   171  	bundle-verify "$BUNDLE"
   172  
   173  	# Ensure that the capability bits were preserved.
   174  	sane_run getcap "$ROOTFS/setcap1"
   175  	[ "$status" -eq 0 ]
   176  	[[ "$output" == *" = cap_net_raw+eip"* ]]
   177  	sane_run getcap "$ROOTFS/setcap2"
   178  	[ "$status" -eq 0 ]
   179  	[[ "$output" == *" = cap_sys_admin,cap_setfcap"* ]]
   180  
   181  	# Unpack the image (as rootless).
   182  	new_bundle_rootfs
   183  	umoci unpack --rootless --image "${IMAGE}:${TAG}" "$BUNDLE"
   184  	[ "$status" -eq 0 ]
   185  	bundle-verify "$BUNDLE"
   186  
   187  	# TODO: Actually set capabilities as an unprivileged user and then test
   188  	#	   that the correct v3 capabilities were set.
   189  
   190  	image-verify "${IMAGE}"
   191  }
   192  
   193  @test "umoci unpack [mknod]" {
   194  	# We need to mknod which requires root on most kernels. Since Linux 4.18 it's
   195  	# been possible for unprivileged users to mknod(2) but we can't use that here
   196  	# (it requires owning the filesystem's superblock).
   197  	requires root
   198  
   199  	# Unpack the image.
   200  	new_bundle_rootfs
   201  	umoci unpack --image "${IMAGE}:${TAG}" "$BUNDLE"
   202  	[ "$status" -eq 0 ]
   203  	bundle-verify "$BUNDLE"
   204  
   205  	# Make some mknod.
   206  	mknod "$ROOTFS/block1" b 128 42  # 80:2a 61a4
   207  	mknod "$ROOTFS/block2" b 255 128 # ff:80 61a4
   208  	mknod "$ROOTFS/char1"  c 133 37  # 85:25 21a4
   209  	mknod "$ROOTFS/char2"  c 253 97  # fd:61 21a4
   210  	mkfifo "$ROOTFS/fifo"
   211  
   212  	# Repack the image.
   213  	umoci repack --image "${IMAGE}:${TAG}" "$BUNDLE"
   214  	[ "$status" -eq 0 ]
   215  	image-verify "${IMAGE}"
   216  
   217  	# Unpack the image (as root).
   218  	new_bundle_rootfs
   219  	umoci unpack --image "${IMAGE}:${TAG}" "$BUNDLE"
   220  	[ "$status" -eq 0 ]
   221  	bundle-verify "$BUNDLE"
   222  
   223  	# Check that all of the bits were preserved.
   224  	[ -b "$ROOTFS/block1" ]
   225  	[[ "$(stat -c '%t:%T' "$ROOTFS/block1")" == *"80:2a"* ]]
   226  	[ -b "$ROOTFS/block2" ]
   227  	[[ "$(stat -c '%t:%T' "$ROOTFS/block2")" == *"ff:80"* ]]
   228  	[ -c "$ROOTFS/char1" ]
   229  	[[ "$(stat -c '%t:%T' "$ROOTFS/char1")" == *"85:25"* ]]
   230  	[ -c "$ROOTFS/char2" ]
   231  	[[ "$(stat -c '%t:%T' "$ROOTFS/char2")" == *"fd:61"* ]]
   232  	[ -p "$ROOTFS/fifo" ]
   233  
   234  	# Unpack the image (as rootless).
   235  	new_bundle_rootfs
   236  	umoci unpack --rootless --image "${IMAGE}:${TAG}" "$BUNDLE"
   237  	[ "$status" -eq 0 ]
   238  	bundle-verify "$BUNDLE"
   239  
   240  	# At the least, check that the files exist.
   241  	[ -e "$ROOTFS/block1" ]
   242  	[ -e "$ROOTFS/block2" ]
   243  	[ -e "$ROOTFS/char1" ]
   244  	[ -e "$ROOTFS/char2" ]
   245  	# But the FIFOs should be preserved.
   246  	[ -p "$ROOTFS/fifo" ]
   247  
   248  	image-verify "${IMAGE}"
   249  }
   250  
   251  @test "umoci unpack --keep-dirlinks" {
   252  	# Unpack the image.
   253  	new_bundle_rootfs
   254  	umoci unpack --image "${IMAGE}:${TAG}" "$BUNDLE"
   255  	[ "$status" -eq 0 ]
   256  	bundle-verify "$BUNDLE"
   257  
   258  	# Create some links for us to play with in the next layer.
   259  	mkdir "$ROOTFS/dir"
   260  	touch "$ROOTFS/dir/a"
   261  	ln -s dir "$ROOTFS/link"
   262  	ln -s link "$ROOTFS/link2"
   263  	ln -s loop2 "$ROOTFS/loop1"
   264  	ln -s loop3 "$ROOTFS/loop2"
   265  	ln -s link2/loop4 "$ROOTFS/loop3"
   266  	ln -s ../loop1 "$ROOTFS/dir/loop4"
   267  	chmod 000 "$ROOTFS/dir"
   268  
   269  	# Repack the image.
   270  	umoci repack --refresh-bundle --image "${IMAGE}:${TAG}" "$BUNDLE"
   271  	[ "$status" -eq 0 ]
   272  	image-verify "$IMAGE"
   273  
   274  	# Create a fake rootfs which contains entries inside symlinks.
   275  	ROOTFS="$(setup_tmpdir)"
   276  	mkdir "$ROOTFS/link"  # == /dir
   277  	touch "$ROOTFS/link/b"
   278  	mkdir "$ROOTFS/link2"  # == /link == /dir
   279  	touch "$ROOTFS/link2/c"
   280  	mkdir "$ROOTFS/loop1" # == /loop{1..4} ... (symlink loop)
   281  	touch "$ROOTFS/loop1/broken"
   282  	sane_run tar cvfC "$BATS_TMPDIR/layer1.tar" "$ROOTFS" .
   283  	[ "$status" -eq 0 ]
   284  
   285  	# Insert our fake layer manually.
   286  	umoci raw add-layer --image "${IMAGE}:${TAG}" "$BATS_TMPDIR/layer1.tar"
   287  	[ "$status" -eq 0 ]
   288  	image-verify "${IMAGE}"
   289  
   290  	# Unpack our weird image.
   291  	new_bundle_rootfs
   292  	umoci unpack --keep-dirlinks --image "${IMAGE}:${TAG}" "$BUNDLE"
   293  	[ "$status" -eq 0 ]
   294  	bundle-verify "$BUNDLE"
   295  
   296  	# Resolution of links without destroying the links themselves.
   297  	chmod 755 "$ROOTFS/dir"
   298  	[ -f "$ROOTFS/dir/a" ]
   299  	[ -f "$ROOTFS/dir/b" ]
   300  	[ -f "$ROOTFS/dir/c" ]
   301  	[ -L "$ROOTFS/link" ]
   302  	[ -L "$ROOTFS/link2" ]
   303  	[ "$(readlink "$ROOTFS/link")" = "dir" ]
   304  	[ "$(readlink "$ROOTFS/link2")" = "link" ]
   305  	# ... but symlink loops have to be broken.
   306  	[ -d "$ROOTFS/loop1" ]
   307  	[ -f "$ROOTFS/loop1/broken" ]
   308  	[ -L "$ROOTFS/loop2" ]
   309  	[ -L "$ROOTFS/loop3" ]
   310  	[ -L "$ROOTFS/dir/loop4" ]
   311  	[ "$(readlink "$ROOTFS/loop2")" = "loop3" ]
   312  	[ "$(readlink "$ROOTFS/loop3")" = "link2/loop4" ]
   313  	[ "$(readlink "$ROOTFS/dir/loop4")" = "../loop1" ]
   314  }