canonical / rockcraft

Tool to create OCI Images using the language from Snapcraft and Charmcraft.
GNU General Public License v3.0
32 stars 41 forks source link

File capabilities (xattrs) are not preserved in final ROCK image layers. #683

Open aznashwan opened 2 weeks ago

aznashwan commented 2 weeks ago

Bug Description

File capabilities set via xattrs on files during ROCK build time are not preserved in the final ROCK image.

There are numerous examples of OCI images which are run as a non-root user but require root-like capabilities like binding port numbers under 1024 with cap_net_bind_service (e.g: the Nginx Ingress Controller image which runs as www-data).

To Reproduce

Build the below-listed rockcraft.yaml sample and check the caps in the final file as follows:

cd /path/to/rockfile/dir

# Build and upload the rock:
rockcraft --verbose --debug pack
rockcraft.skopeo --insecure-policy copy oci-archive:caps-test-rock_v1.0.0_amd64.rock docker-daemon:caps-test-rock:v1.0.0

# NOTE: `-v` makes `setcap` check the given caps are present on the file:
docker run --entrypoint setcap caps-test-rock:v1.0.0 -v cap_net_bind_service=+ep /example.sh
# /example.sh differs in [pe]
# $? = 1

Environment

Host: Ubuntu 22.04 on x86_64 VM on VMWare Rockcraft: 1.5.3 installed via snap Docker: 24.0.7-0ubuntu2~22.04.1 amd64 installed via apt

rockcraft.yaml

name: caps-test-rock
summary: Test image to showcase snap caps preservation issues.
description: Test image to showcase snap caps preservation issues.

version: v1.0.0
license: Apache-2.0

base: ubuntu@22.04
build-base: ubuntu@22.04
platforms:
  amd64:
  # arm64:

services:
  sleep:
    command: sleep inf
    override: replace
    startup: enabled

parts:
  setup:
    plugin: nil

    build-packages:
      - libcap2-bin

    stage-packages:
      - libcap2-bin
      - coreutils

    override-build: |
      set -eux

      echo -e "#!/bin/bash\necho Hello!" > $CRAFT_PART_INSTALL/example.sh

      setcap    cap_net_bind_service=+ep $CRAFT_PART_INSTALL/example.sh
      # NOTE: `-v` makes `setcap` check the given caps are present on the file
      # and will exit non-zero if it doesn't, so the caps are set during build:
      setcap -v cap_net_bind_service=+ep $CRAFT_PART_INSTALL/example.sh

Relevant log output

No relevant logs to share...
aznashwan commented 2 weeks ago

There are numerous examples of OCI images which are run as a non-root [...] (e.g: the Nginx Ingress Controller image which runs as www-data).

Also wanted to confirm the caps are present in non-ROCK images:

docker run -u root --rm -it --entrypoint bash registry.k8s.io/ingress-nginx/controller:v1.11.0 -c "apk update && apk add libcap && setcap -v cap_net_bind_service=+ep /nginx-ingress-controller"
# /nginx-ingress-controller: OK
cjdcordeiro commented 2 weeks ago

Thanks for raising this @aznashwan

For future reference, here's the original discussion.