├── .cirrus.yml ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── custom.md │ └── feature_request.md ├── renovate.json5 └── workflows │ └── checks.yml ├── .gitignore ├── CODE-OF-CONDUCT.md ├── Dockerfile ├── LICENSE ├── Makefile ├── README.md ├── SECURITY.md ├── contrib └── cirrus │ ├── build.sh │ ├── lib.sh │ ├── setup.sh │ ├── test.sh │ └── timestamp.awk ├── hack └── get_ci_vm.sh ├── logo ├── logo-udica-notext.png ├── logo-udica-notext.svg ├── logo-udica.png └── logo-udica.svg ├── setup.py ├── tests ├── append_avc_file ├── selinux.py ├── semanage.py ├── test_append_avc.podman.cil ├── test_basic.ansible.podman.yml ├── test_basic.cri.cil ├── test_basic.cri.json ├── test_basic.docker.cil ├── test_basic.docker.json ├── test_basic.oci.cil ├── test_basic.oci.json ├── test_basic.podman.cil ├── test_basic.podman.json ├── test_confined_abcdgilmns.cil ├── test_confined_cla.cil ├── test_confined_lb.cil ├── test_confined_lsid.cil ├── test_default.ansible.podman.yml ├── test_default.docker.cil ├── test_default.docker.json ├── test_default.oci.json ├── test_default.podman.cil ├── test_default.podman.json ├── test_device_access.podman.json ├── test_devices.podman.cil ├── test_devices.podman.json ├── test_fullnetworkaccess.podman.cil ├── test_integration.py ├── test_main.py ├── test_nocontext.podman.cil ├── test_nocontext.podman.json ├── test_ports.docker.cil ├── test_ports.docker.json ├── test_ports.podman.cil ├── test_ports.podman.json ├── test_stream_connect.podman.cil ├── test_ttyaccess.podman.cil ├── test_unit.py ├── test_virtaccess.podman.cil └── test_xaccess.podman.cil └── udica ├── __init__.py ├── __main__.py ├── ansible └── deploy-module.yml ├── confined_user.py ├── macros └── confined_user_macros.cil ├── man └── man8 │ └── udica.8 ├── parse.py ├── perms.py ├── policy.py └── version.py /.cirrus.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | # Default timeout for each task 4 | timeout_in: 30m 5 | 6 | # Main collection of env. vars to set for all tasks and scripts. 7 | env: 8 | #### 9 | #### Global variables used for all tasks 10 | #### 11 | CIRRUS_SHELL: "/bin/bash" 12 | # Save a little typing (path relative to $CIRRUS_WORKING_DIR) 13 | SCRIPT_BASE: "./contrib/cirrus" 14 | CIRRUS_CLONE_DEPTH: 50 15 | 16 | #### 17 | #### Cache-image names to test with 18 | #### 19 | # Google-cloud VM Images 20 | IMAGE_SUFFIX: "c20250422t130822z-f42f41d13" 21 | FEDORA_CACHE_IMAGE_NAME: "fedora-${IMAGE_SUFFIX}" 22 | 23 | #### 24 | #### Command variables to help avoid duplication 25 | #### 26 | # Command to prefix every output line with a timestamp 27 | # (can't do inline awk script, Cirrus-CI or YAML mangles quoting) 28 | _TIMESTAMP: 'awk --file ${CIRRUS_WORKING_DIR}/${SCRIPT_BASE}/timestamp.awk' 29 | _DFCMD: 'df -lhTx tmpfs' 30 | _AUDITCMD: 'cat /var/log/audit/audit.log' 31 | _JOURNALCMD: 'journalctl -b' 32 | 33 | gcp_credentials: ENCRYPTED[00f012db520bc341804da84ba135d10db0540571e08a0cd00f05636dcd0824240d9277509514f0075c0533b889c4fe35] 34 | 35 | # Default timeout for each task 36 | timeout_in: 120m 37 | 38 | 39 | # Default VM to use unless set or modified by task 40 | gce_instance: 41 | image_project: "libpod-218412" 42 | zone: "us-central1-c" # Required by Cirrus for the time being 43 | cpu: 2 44 | memory: "4Gb" 45 | disk: 200 # Gigabytes, do not set less than 200 per obscure GCE docs re: I/O performance 46 | image_name: "${FEDORA_CACHE_IMAGE_NAME}" 47 | 48 | 49 | # Each 'task' runs in parallel, '_task' suffix required on name. 50 | test_upstream_podman_task: 51 | name: "Test podman on Fedora" 52 | alias: test_upstream_podman 53 | 54 | gce_instance: 55 | image_name: "${FEDORA_CACHE_IMAGE_NAME}" 56 | 57 | env: 58 | # Which branch, tag, or sha of podman repository to test against 59 | PODMAN_FROM: 'main' # see build script below 60 | 61 | # Each 'script' runs in sequence, '_script' suffix required on name. 62 | setup_script: '${SCRIPT_BASE}/setup.sh |& ${_TIMESTAMP}' 63 | build_script: '${SCRIPT_BASE}/build.sh |& ${_TIMESTAMP}' 64 | test_script: '${SCRIPT_BASE}/test.sh |& ${_TIMESTAMP}' 65 | 66 | always: 67 | df_script: '$_DFCMD' 68 | audit_log_script: '$_AUDITCMD' 69 | journal_script: '$_JOURNALCMD' 70 | 71 | 72 | # Update metadata on VM images to record last-used-on timestamps 73 | meta_task: 74 | 75 | container: 76 | image: "quay.io/libpod/imgts:latest" 77 | cpu: 1 78 | memory: 1 79 | 80 | env: 81 | # Space-separated list of ALL images used by automation in this repository 82 | IMGNAMES: |- 83 | ${FEDORA_CACHE_IMAGE_NAME} 84 | BUILDID: "${CIRRUS_BUILD_ID}" 85 | REPOREF: "${CIRRUS_REPO_NAME}" 86 | GCPJSON: ENCRYPTED[5279a6043ee3852dabbf477cda0565183d3f0d887dde63a19ebe19eb00f9b279a8a5f4d2d7395672cb7d7046b9da11d2] 87 | GCPNAME: ENCRYPTED[67d54cd5b7f3cf1915707b13f4af9f127336c3866794e1f9ee53b0c723d0024e4d1eb2fd98ce3df5ef28babd5335cacc] 88 | GCPPROJECT: libpod-218412 89 | CIRRUS_CLONE_DEPTH: 1 # source not used 90 | 91 | script: '/usr/local/bin/entrypoint.sh |& ${_TIMESTAMP}' 92 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | 5 | --- 6 | 7 | **Describe the bug** 8 | A clear and concise description of what the bug is. 9 | 10 | **To Reproduce** 11 | Steps to reproduce the behavior: 12 | 1. ... 13 | 2. ... 14 | 3. ... 15 | 16 | **Expected behavior** 17 | A clear and concise description of what you expected to happen. 18 | 19 | **Additional context** 20 | Add any other context about the problem here. 21 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/custom.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Custom issue template 3 | about: Describe this issue template's purpose here. 4 | 5 | --- 6 | 7 | 8 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | 5 | --- 6 | 7 | **Is your feature request related to a problem? Please describe.** 8 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 9 | 10 | **Describe the solution you'd like** 11 | A clear and concise description of what you want to happen. 12 | 13 | **Describe alternatives you've considered** 14 | A clear and concise description of any alternative solutions or features you've considered. 15 | 16 | **Additional context** 17 | Add any other context or screenshots about the feature request here. 18 | -------------------------------------------------------------------------------- /.github/renovate.json5: -------------------------------------------------------------------------------- 1 | /* 2 | Renovate is a service similar to GitHub Dependabot, but with 3 | (fantastically) more configuration options. So many options 4 | in fact, if you're new I recommend glossing over this cheat-sheet 5 | prior to the official documentation: 6 | 7 | https://www.augmentedmind.de/2021/07/25/renovate-bot-cheat-sheet 8 | 9 | Configuration Update/Change Procedure: 10 | 1. Make changes 11 | 2. Manually validate changes (from repo-root): 12 | 13 | podman run -it \ 14 | -v ./.github/renovate.json5:/usr/src/app/renovate.json5:z \ 15 | docker.io/renovate/renovate:latest \ 16 | renovate-config-validator 17 | 3. Commit. 18 | 19 | Configuration Reference: 20 | https://docs.renovatebot.com/configuration-options/ 21 | 22 | Monitoring Dashboard: 23 | https://app.renovatebot.com/dashboard#github/containers 24 | 25 | Note: The Renovate bot will create/manage it's business on 26 | branches named 'renovate/*'. Otherwise, and by 27 | default, the only the copy of this file that matters 28 | is the one on the `main` branch. No other branches 29 | will be monitored or touched in any way. 30 | */ 31 | 32 | { 33 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 34 | 35 | /************************************************* 36 | ****** Global/general configuration options ***** 37 | *************************************************/ 38 | 39 | // Re-use predefined sets of configuration options to DRY 40 | "extends": [ 41 | // https://github.com/containers/automation/blob/main/renovate/defaults.json5 42 | "github>containers/automation//renovate/defaults.json5" 43 | ], 44 | 45 | // Permit automatic rebasing when base-branch changes by more than 46 | // one commit. 47 | "rebaseWhen": "behind-base-branch", 48 | 49 | /************************************************* 50 | *** Repository-specific configuration options *** 51 | *************************************************/ 52 | 53 | // https://docs.renovatebot.com/modules/manager/#supported-managers 54 | "enabledManagers": [ 55 | "pip-compile", "pip_requirements", "pip_setup", "pipenv", "poetry", "pyenv", "setup-cfg", 56 | "github-actions", "regex" 57 | ] 58 | } 59 | -------------------------------------------------------------------------------- /.github/workflows/checks.yml: -------------------------------------------------------------------------------- 1 | name: checks 2 | on: [push, pull_request] 3 | jobs: 4 | lint: 5 | runs-on: ubuntu-latest 6 | steps: 7 | - uses: actions/checkout@v4 8 | - run: sudo apt-get update -y 9 | - run: sudo apt-get install -y python3-pip python3-setuptools 10 | - run: sudo pip3 install black pyflakes 11 | - run: make format-check 12 | - run: make lint 13 | tests: 14 | runs-on: ubuntu-latest 15 | strategy: 16 | fail-fast: false 17 | matrix: 18 | image: 19 | # test on Fedora Rawhide 20 | - quay.io/fedora/fedora:rawhide 21 | # test on the latest stable release of Fedora 22 | - quay.io/fedora/fedora:latest 23 | # test on the latest stable release of Centos stream 24 | - quay.io/centos/centos:stream9 25 | container: 26 | image: ${{ matrix.image }} 27 | steps: 28 | - uses: actions/checkout@v4 29 | - run: rpm -q python3 || dnf install --nogpgcheck -y python3 30 | - run: rpm -q git || dnf install --nogpgcheck -y git 31 | - run: python3 -m unittest -v tests/test_unit.py 32 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | udica.egg-info/ 2 | build/ 3 | dist/ 4 | __pycache__/ 5 | *.py[cod] 6 | -------------------------------------------------------------------------------- /CODE-OF-CONDUCT.md: -------------------------------------------------------------------------------- 1 | ## The udica Project Community Code of Conduct 2 | 3 | The udica project follows the [Containers Community Code of Conduct](https://github.com/containers/common/blob/main/CODE-OF-CONDUCT.md). 4 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM fedora:30 2 | 3 | USER root 4 | 5 | # Update image 6 | RUN dnf update --disableplugin=subscription-manager -y && \ 7 | rm -rf /var/cache/yum 8 | 9 | # Install dependencies 10 | RUN dnf install --disableplugin=subscription-manager -y \ 11 | container-selinux \ 12 | python3 \ 13 | python3-setools \ 14 | systemd-devel \ 15 | policycoreutils \ 16 | policycoreutils-python-utils \ 17 | && rm -rf /var/cache/yum 18 | 19 | # build udica 20 | WORKDIR /tmp 21 | COPY udica/ udica/udica/ 22 | COPY LICENSE udica/ 23 | COPY README.md udica/ 24 | COPY setup.py udica/ 25 | WORKDIR /tmp/udica 26 | RUN python3 setup.py install 27 | WORKDIR / 28 | 29 | # Clean up 30 | RUN rm -rf /tmp/udica/ 31 | 32 | ENTRYPOINT ["/usr/bin/udica"] 33 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | TAG ?= latest 2 | IMAGE_NAME ?= udica 3 | CONTAINER_CMD ?= podman 4 | 5 | .PHONY: install 6 | install: 7 | python3 setup.py install 8 | 9 | .PHONY: 10 | lint: 11 | pyflakes udica 12 | 13 | .PHONY: 14 | format: 15 | black *.py udica/*.py tests/*.py 16 | 17 | .PHONY: 18 | format-check: 19 | black --check --diff *.py udica/*.py tests/*.py 20 | 21 | .PHONY: test 22 | test: lint format-check 23 | python3 -m unittest -v tests/test_unit.py 24 | 25 | .PHONY: image 26 | image: 27 | $(CONTAINER_CMD) build -f Dockerfile -t $(IMAGE_NAME):$(TAG) 28 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | ## Security and Disclosure Information Policy for the udica Project 2 | 3 | The udica Project follows the [Security and Disclosure Information Policy](https://github.com/containers/common/blob/main/SECURITY.md) for the Containers Projects. 4 | -------------------------------------------------------------------------------- /contrib/cirrus/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -eo pipefail 4 | 5 | source $(dirname $0)/lib.sh 6 | 7 | req_env_vars GOPATH SCRIPT_BASE CIRRUS_WORKING_DIR PODMAN_FROM OS_RELEASE_ID 8 | 9 | [[ "$PODMAN_FROM" == 'main' ]] || \ 10 | die 1 "Unsupported \$PODMAN_FROM value: $PODMAN_FROM" 11 | 12 | remove_packaged_podman_files 13 | 14 | echo "Building & installing libpod from '$PODMAN_FROM' source" 15 | GOSRC=$GOPATH/src/github.com/containers/libpod 16 | mkdir -p "$GOSRC" 17 | showrun git clone -b "$PODMAN_FROM" https://github.com/containers/libpod.git "$GOSRC" 18 | cd "$GOSRC" 19 | showrun make 20 | showrun make install PREFIX=/usr ETCDIR=/etc 21 | 22 | echo "Configuring podman for execution w/in a container" 23 | sed -e 's|^#mount_program|mount_program|g' \ 24 | -e 's|^mountopt[[:space:]]*=.*$|mountopt = "nodev,fsync=0"|g' \ 25 | /usr/share/containers/storage.conf \ 26 | > /etc/containers/storage.conf 27 | setsebool container_manage_cgroup true # systemd in container 28 | 29 | echo "Installing Udica from source" 30 | cd "$CIRRUS_WORKING_DIR" 31 | showrun python3 ./setup.py install 32 | -------------------------------------------------------------------------------- /contrib/cirrus/lib.sh: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Library of common, shared utility functions. This file is intended 4 | # to be sourced by other scripts, not called directly. 5 | 6 | # BEGIN Global export of all variables 7 | set -a 8 | 9 | # Due to differences across platforms and runtime execution environments, 10 | # handling of the (otherwise) default shell setup is non-uniform. Rather 11 | # than attempt to workaround differences, simply force-load/set required 12 | # items every time this library is utilized. 13 | USER="$(whoami)" 14 | HOME="$(getent passwd $USER | cut -d : -f 6)" 15 | # Some platforms set and make this read-only 16 | [[ -n "$UID" ]] || \ 17 | UID=$(getent passwd $USER | cut -d : -f 3) 18 | 19 | # Automation library installed at image-build time, 20 | # defining $AUTOMATION_LIB_PATH in this file. 21 | if [[ -r "/etc/automation_environment" ]]; then 22 | source /etc/automation_environment 23 | fi 24 | # shellcheck disable=SC2154 25 | if [[ -n "$AUTOMATION_LIB_PATH" ]]; then 26 | # shellcheck source=/usr/share/automation/lib/common_lib.sh 27 | source $AUTOMATION_LIB_PATH/common_lib.sh 28 | else 29 | ( 30 | echo "WARNING: It does not appear that containers/automation was installed." 31 | echo " Functionality of most of this library will be negatively impacted" 32 | echo " This ${BASH_SOURCE[0]} was loaded by ${BASH_SOURCE[1]}" 33 | ) > /dev/stderr 34 | fi 35 | 36 | # Managed by setup.sh; holds task-specific definitions. 37 | if [[ -r "/etc/ci_environment" ]]; then source /etc/ci_environment; fi 38 | 39 | OS_RELEASE_ID="$(source /etc/os-release; echo $ID)" 40 | # GCE image-name compatible string representation of distribution _major_ version 41 | OS_RELEASE_VER="$(source /etc/os-release; echo $VERSION_ID | tr -d '.')" 42 | # Combined to ease soe usage 43 | OS_REL_VER="${OS_RELEASE_ID}-${OS_RELEASE_VER}" 44 | 45 | # Essential default paths, many are overriden when executing under Cirrus-CI 46 | # others are duplicated here, to assist in debugging. 47 | GOPATH="${GOPATH:-/var/tmp/go}" 48 | if type -P go &> /dev/null 49 | then 50 | # required for go 1.12+ 51 | export GOCACHE="${GOCACHE:-$HOME/.cache/go-build}" 52 | eval "$(go env)" 53 | # required by make and other tools 54 | export $(go env | cut -d '=' -f 1) 55 | # Ensure compiled tooling is reachable 56 | export PATH="$PATH:$GOPATH/bin" 57 | fi 58 | PATH="$HOME/bin:$GOPATH/bin:/usr/local/bin:$PATH" 59 | CIRRUS_WORKING_DIR=${CIRRUS_WORKING_DIR:-/tmp/udica} 60 | SCRIPT_BASE=${CIRRUS_WORKING_DIR}/.cirrus 61 | 62 | CI="${CI:-false}" 63 | CIRRUS_CI="${CIRRUS_CI:-false}" 64 | CONTINUOUS_INTEGRATION="${CONTINUOUS_INTEGRATION:-false}" 65 | CIRRUS_REPO_NAME=${CIRRUS_REPO_NAME:-udica} 66 | 67 | # Unsafe env. vars for display 68 | SECRET_ENV_RE='(IRCID)|(ACCOUNT)|(^GC[EP]..+)|(SSH)' 69 | 70 | # END Global export of all variables 71 | set +a 72 | 73 | # Remove all files (except conmon, and the cni-config) provided by the distro version. 74 | remove_packaged_podman_files() { 75 | echo "Removing packaged podman files to prevent conflicts with source build and testing." 76 | req_env_vars OS_RELEASE_ID 77 | if [[ "$OS_RELEASE_ID" =~ "ubuntu" ]] 78 | then 79 | LISTING_CMD="sudo -E dpkg-query -L podman" 80 | else 81 | LISTING_CMD='sudo rpm -ql podman' 82 | fi 83 | 84 | # yum/dnf/dpkg may list system directories, only remove files 85 | $LISTING_CMD | while read fullpath 86 | do 87 | # TODO: This can go away when conmon gets it's own package 88 | if [[ -d "$fullpath" ]] || [[ $(basename "$fullpath") == "conmon" ]] || \ 89 | [[ $(dirname "$fullpath") == "/etc/cni/net.d" ]]; then continue; fi 90 | ooe.sh sudo rm -vf "$fullpath" 91 | done 92 | } 93 | -------------------------------------------------------------------------------- /contrib/cirrus/setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -eo pipefail 4 | 5 | source "$(dirname $0)/lib.sh" 6 | 7 | show_env_vars 8 | 9 | case "${OS_RELEASE_ID}" in 10 | fedora) 11 | msg "Installing necessary additional packages" 12 | ooe.sh dnf install -y \ 13 | setools-console \ 14 | systemd-devel \ 15 | fuse-overlayfs 16 | ;; 17 | *) bad_os_id_ver ;; 18 | esac 19 | 20 | echo "Configuring git for access to podman pull-requests" 21 | NEWREF='+refs/pull/*/head:refs/remotes/upstream/pr/*' 22 | git config --global --replace-all remote.origin.fetch "$NEWREF" 23 | -------------------------------------------------------------------------------- /contrib/cirrus/test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -eo pipefail 4 | 5 | source $(dirname $0)/lib.sh 6 | 7 | req_env_vars GOPATH SCRIPT_BASE CIRRUS_WORKING_DIR PODMAN_FROM 8 | 9 | showrun python3 -m udica --help 10 | 11 | showrun podman run -d -v /home:/home:ro -v /var/spool:/var/spool:rw -p 21:21 fedora sleep 1h 12 | 13 | echo "Running podman inspect -l" 14 | podman inspect -l > /tmp/container.json 15 | 16 | showrun udica -j /tmp/container.json my_container 17 | -------------------------------------------------------------------------------- /contrib/cirrus/timestamp.awk: -------------------------------------------------------------------------------- 1 | 2 | 3 | # This script is intended to be piped into by automation, in order to 4 | # mark output lines with timing information. For example: 5 | # /path/to/command |& awk --file timestamp.awk 6 | 7 | BEGIN { 8 | STARTTIME=systime() 9 | printf "[%s] START", strftime("%T") 10 | printf " - All [+xxxx] lines that follow are relative to right now.\n" 11 | } 12 | 13 | { 14 | printf "[%+05ds] %s\n", systime()-STARTTIME, $0 15 | } 16 | 17 | END { 18 | printf "[%s] END", strftime("%T") 19 | printf " - [%+05ds] total duration since START\n", systime()-STARTTIME 20 | } 21 | -------------------------------------------------------------------------------- /hack/get_ci_vm.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # 4 | # For help and usage information, simply execute the script w/o any arguments. 5 | # 6 | # This script is intended to be run by Red Hat udica developers who need 7 | # to debug problems specifically related to Cirrus-CI automated testing. 8 | # It requires that you have been granted prior access to create VMs in 9 | # google-cloud. For non-Red Hat contributors, VMs are available as-needed, 10 | # with supervision upon request. 11 | 12 | set -e 13 | 14 | SCRIPT_FILEPATH=$(realpath "${BASH_SOURCE[0]}") 15 | SCRIPT_DIRPATH=$(dirname "$SCRIPT_FILEPATH") 16 | REPO_DIRPATH=$(realpath "$SCRIPT_DIRPATH/../") 17 | 18 | # Help detect if we were called by get_ci_vm container 19 | GET_CI_VM="${GET_CI_VM:-0}" 20 | in_get_ci_vm() { 21 | if ((GET_CI_VM==0)); then 22 | echo "Error: $1 is not intended for use in this context" 23 | exit 2 24 | fi 25 | } 26 | 27 | # get_ci_vm APIv1 container entrypoint calls into this script 28 | # to obtain required repo. specific configuration options. 29 | if [[ "$1" == "--config" ]]; then 30 | in_get_ci_vm "$1" 31 | cat < /dev/stderr 48 | source ./contrib/cirrus/lib.sh 49 | echo "+ Running environment setup" > /dev/stderr 50 | ./contrib/cirrus/setup.sh 51 | else 52 | # Create and access VM for specified Cirrus-CI task 53 | mkdir -p $HOME/.config/gcloud/ssh 54 | podman run -it --rm \ 55 | --tz=local \ 56 | -e NAME="$USER" \ 57 | -e SRCDIR=/src \ 58 | -e GCLOUD_ZONE="$GCLOUD_ZONE" \ 59 | -e DEBUG="${DEBUG:-0}" \ 60 | -v $REPO_DIRPATH:/src:O \ 61 | -v $HOME/.config/gcloud:/root/.config/gcloud:z \ 62 | -v $HOME/.config/gcloud/ssh:/root/.ssh:z \ 63 | quay.io/libpod/get_ci_vm:latest "$@" 64 | fi 65 | -------------------------------------------------------------------------------- /logo/logo-udica-notext.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/containers/udica/54fa8f58f1a024fc064acef350cc3e2b276f68b7/logo/logo-udica-notext.png -------------------------------------------------------------------------------- /logo/logo-udica-notext.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | logo-udica-notext 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /logo/logo-udica.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/containers/udica/54fa8f58f1a024fc064acef350cc3e2b276f68b7/logo/logo-udica.png -------------------------------------------------------------------------------- /logo/logo-udica.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | logo-udica-3 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2018 Lukas Vrabec, 2 | # 3 | # This program is free software: you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation, either version 3 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU General Public License 14 | # along with this program. If not, see . 15 | 16 | import setuptools 17 | from setuptools.command.install import install 18 | import os 19 | 20 | from udica.version import version 21 | 22 | with open("README.md", "r") as fh: 23 | long_description = fh.read() 24 | 25 | setuptools.setup( 26 | name="udica", 27 | version=version, 28 | author="Lukas Vrabec", 29 | author_email="lvrabec@redhat.com", 30 | description="A tool for generating SELinux security policies for containers", 31 | license="GPLv3+", 32 | long_description=long_description, 33 | long_description_content_type="text/markdown", 34 | url="https://github.com/containers/udica", 35 | packages=["udica"], 36 | python_requires=">=3.4, <4", 37 | data_files=[ 38 | ("/usr/share/licenses/udica", ["LICENSE"]), 39 | ("/usr/share/udica/ansible", ["udica/ansible/deploy-module.yml"]), 40 | ("/usr/share/udica/macros", ["udica/macros/confined_user_macros.cil"]), 41 | ], 42 | # scripts=["bin/udica"], 43 | entry_points={"console_scripts": ["udica=udica.__main__:main"]}, 44 | classifiers=[ 45 | "Programming Language :: Python :: 3", 46 | "License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)", 47 | "Operating System :: OS Independent", 48 | ], 49 | ) 50 | -------------------------------------------------------------------------------- /tests/append_avc_file: -------------------------------------------------------------------------------- 1 | time->Fri Aug 9 22:29:36 2019 2 | type=AVC msg=audit(1565382576.178:800): avc: denied { open } for pid=1503 comm=container_test scontext=system_u:system_r:my_container.process:s0:c0.c1023 tcontext=system_u:object_r:etc_t:s0:c0.c1023 tclass=file permissive=0 3 | type=AVC msg=audit(1565382576.178:800): avc: denied { getattr } for pid=1503 comm=container_test scontext=system_u:system_r:my_container.process:s0:c0.c1023 tcontext=system_u:object_r:etc_t:s0:c0.c1023 tclass=file permissive=0 4 | type=AVC msg=audit(1565382576.178:800): avc: denied { write } for pid=1503 comm=container_test scontext=system_u:system_r:my_container.process:s0:c0.c1023 tcontext=system_u:object_r:tmp_t:s0:c0.c1023 tclass=file permissive=0 5 | type=AVC msg=audit(1565382576.178:800): avc: denied { add_name } for pid=1503 comm=container_test scontext=system_u:system_r:my_container.process:s0:c0.c1023 tcontext=system_u:object_r:tmp_t:s0:c0.c1023 tclass=dir permissive=0 6 | type=AVC msg=audit(1565382576.178:800): avc: denied { read } for pid=1503 comm=container_test scontext=system_u:system_r:my_container.process:s0:c0.c1023 tcontext=system_u:object_r:etc_t:s0:c0.c1023 tclass=file permissive=0 7 | type=AVC msg=audit(1565382576.178:800): avc: denied { read } for pid=1503 comm=container_test scontext=system_u:system_r:my_container.process:s0:c0.c1023 tcontext=system_u:object_r:etc_t:s0:c0.c1023 tclass=file permissive=0 8 | -------------------------------------------------------------------------------- /tests/selinux.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2019 Jan Zarsky, 2 | # 3 | # This program is free software: you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation, either version 3 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU General Public License 14 | # along with this program. If not, see . 15 | 16 | from unittest.mock import Mock 17 | 18 | SELABEL_CTX_FILE = None 19 | 20 | selabel_open = Mock() 21 | 22 | 23 | def selabel_lookup(selabel, directory, rc): 24 | if directory == "/tmp/test": 25 | return (0, None) 26 | elif directory == "/dev/fb0": 27 | return (0, "system_u:object_r:framebuf_device_t:s0") 28 | elif directory == "/etc/hosts": 29 | return (0, "system_u:object_r:net_conf_t:s0") 30 | else: 31 | return (0, "system_u:object_r:var_spool_t:s0") 32 | 33 | 34 | def getfilecon(directory): 35 | if directory == "/tmp/test": 36 | return (0, "system_u:object_r:user_tmp_t:s0") 37 | elif directory == "/etc/hosts": 38 | return (0, "system_u:object_r:net_conf_t:s0") 39 | else: 40 | return (0, "system_u:object_r:var_spool_t:s0") 41 | -------------------------------------------------------------------------------- /tests/semanage.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2019 Jan Zarsky, 2 | # 3 | # This program is free software: you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation, either version 3 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU General Public License 14 | # along with this program. If not, see . 15 | 16 | from unittest.mock import Mock 17 | 18 | semanage_handle_create = Mock() 19 | semanage_connect = Mock() 20 | semanage_context_get_type = Mock(side_effect=lambda x: x.split(":")[2]) 21 | 22 | ports = [ 23 | ("system_u:object_r:inetd_child_port_t:s0", "tcp", 1, 1), 24 | ("system_u:object_r:inetd_child_port_t:s0", "tcp", 1, 1), 25 | ("system_u:object_r:echo_port_t:s0", "tcp", 7, 7), 26 | ("system_u:object_r:echo_port_t:s0", "tcp", 7, 7), 27 | ("system_u:object_r:inetd_child_port_t:s0", "tcp", 9, 9), 28 | ("system_u:object_r:inetd_child_port_t:s0", "tcp", 9, 9), 29 | ("system_u:object_r:inetd_child_port_t:s0", "tcp", 13, 13), 30 | # default ranges 31 | ("system_u:object_r:reserved_port_t:s0", "udp", 1, 511), 32 | ("system_u:object_r:reserved_port_t:s0", "tcp", 1, 511), 33 | ("system_u:object_r:reserved_port_t:s0", "sctp", 1, 511), 34 | ("system_u:object_r:hi_reserved_port_t:s0", "udp", 512, 1023), 35 | ("system_u:object_r:hi_reserved_port_t:s0", "tcp", 512, 1023), 36 | ("system_u:object_r:hi_reserved_port_t:s0", "sctp", 512, 1023), 37 | ("system_u:object_r:unreserved_port_t:s0", "udp", 61001, 65535), 38 | ("system_u:object_r:unreserved_port_t:s0", "tcp", 61001, 65535), 39 | ("system_u:object_r:ephemeral_port_t:s0", "udp", 32768, 60999), 40 | ("system_u:object_r:ephemeral_port_t:s0", "tcp", 32768, 60999), 41 | ("system_u:object_r:unreserved_port_t:s0", "udp", 1024, 32767), 42 | ("system_u:object_r:unreserved_port_t:s0", "tcp", 1024, 32767), 43 | ("system_u:object_r:unreserved_port_t:s0", "sctp", 1024, 65535), 44 | ] 45 | ports_local = [ 46 | ("system_u:object_r:inetd_child_port_t:s0", "tcp", 13, 13), 47 | ("system_u:object_r:inetd_child_port_t:s0", "tcp", 19, 19), 48 | ("system_u:object_r:inetd_child_port_t:s0", "tcp", 19, 19), 49 | ("system_u:object_r:ftp_data_port_t:s0", "tcp", 20, 20), 50 | ("system_u:object_r:ftp_port_t:s0", "tcp", 21, 21), 51 | ("system_u:object_r:mysqld_port_t:s0", "tcp", 63132, 63164), 52 | ] 53 | semanage_port_list = Mock(return_value=(0, ports)) 54 | semanage_port_list_local = Mock(return_value=(0, ports_local)) 55 | semanage_port_get_con = Mock(side_effect=lambda x: x[0]) 56 | semanage_port_get_proto = Mock(side_effect=lambda x: x[1]) 57 | semanage_port_get_proto_str = Mock(side_effect=lambda x: x) 58 | semanage_port_get_low = Mock(side_effect=lambda x: x[2]) 59 | semanage_port_get_high = Mock(side_effect=lambda x: x[3]) 60 | 61 | fcontexts = [ 62 | ("/var/spool(/.*)?", "system_u:object_r:var_spool_t:s0"), 63 | ("/var/spool/[mg]dm(/.*)?", "system_u:object_r:xdm_spool_t:s0"), 64 | ("/var/spool/(client)?mqueue(/.*)?", "system_u:object_r:mqueue_spool_t:s0"), 65 | ("/var/spool/(.*/)?a?quota\\.(user|group)", "system_u:object_r:quota_db_t:s0"), 66 | ("/var/spool/at(/.*)?", "system_u:object_r:user_cron_spool_t:s0"), 67 | ("/var/spool/faf(/.*)?", "system_u:object_r:abrt_retrace_spool_t:s0"), 68 | ("/var/spool/fax(/.*)?", "system_u:object_r:getty_var_run_t:s0"), 69 | ("/var/spool/lpd(/.*)?", "system_u:object_r:print_spool_t:s0"), 70 | ("/var/spool/sms(/.*)?", "system_u:object_r:smsd_spool_t:s0"), 71 | ("/var/spool/abrt(/.*)?", "system_u:object_r:abrt_var_cache_t:s0"), 72 | ("/var/spool/ctdb(/.*)?", "system_u:object_r:ctdbd_spool_t:s0"), 73 | ("/var/spool/cups(/.*)?", "system_u:object_r:print_spool_t:s0"), 74 | ("/var/spool/gosa(/.*)?", "system_u:object_r:httpd_sys_rw_content_t:s0"), 75 | ("/var/spool/imap(/.*)?", "system_u:object_r:mail_spool_t:s0"), 76 | ("/var/spool/mail(/.*)?", "system_u:object_r:mail_spool_t:s0"), 77 | ("/var/spool/news(/.*)?", "system_u:object_r:news_spool_t:s0"), 78 | ("/var/spool/rwho(/.*)?", "system_u:object_r:rwho_spool_t:s0"), 79 | ("/var/spool/uucp(/.*)?", "system_u:object_r:uucpd_spool_t:s0"), 80 | ("/var/spool/exim[0-9]?(/.*)?", "system_u:object_r:exim_spool_t:s0"), 81 | ("/var/spool/audit(/.*)?", "system_u:object_r:audit_spool_t:s0"), 82 | ("/var/spool/debug(/.*)?", "system_u:object_r:abrt_var_cache_t:s0"), 83 | ("/var/spool/samba(/.*)?", "system_u:object_r:samba_spool_t:s0"), 84 | ("/var/spool/smtpd(/.*)?", "system_u:object_r:mail_spool_t:s0"), 85 | ("/var/spool/spamd(/.*)?", "system_u:object_r:spamd_spool_t:s0"), 86 | ("/var/spool/squid(/.*)?", "system_u:object_r:squid_cache_t:s0"), 87 | ("/var/spool/texmf(/.*)?", "system_u:object_r:tetex_data_t:s0"), 88 | ("/var/spool/voice(/.*)?", "system_u:object_r:getty_var_run_t:s0"), 89 | ("/var/spool/bacula.*", "system_u:object_r:bacula_spool_t:s0"), 90 | ("/var/spool/icinga(/.*)?", "system_u:object_r:nagios_spool_t:s0"), 91 | ("/var/spool/nagios(/.*)?", "system_u:object_r:nagios_spool_t:s0"), 92 | ("/var/spool/snmptt(/.*)?", "system_u:object_r:snmpd_var_lib_t:s0"), 93 | ("/var/spool/spampd(/.*)?", "system_u:object_r:spamd_spool_t:s0"), 94 | ("/var/spool/viewvc(/.*)?", "system_u:object_r:httpd_sys_rw_content_t:s0"), 95 | ("/var/spool/cron/a?quota\\.(user|group)", "system_u:object_r:quota_db_t:s0"), 96 | ("/var/spool/mailman.*", "system_u:object_r:mailman_data_t:s0"), 97 | ("/var/spool/postfix.*", "system_u:object_r:postfix_spool_t:s0"), 98 | ("/var/spool/amavisd(/.*)?", "system_u:object_r:antivirus_db_t:s0"), 99 | ("/var/spool/anacron(/.*)?", "system_u:object_r:system_cron_spool_t:s0"), 100 | ("/var/spool/courier(/.*)?", "system_u:object_r:courier_spool_t:s0"), 101 | ("/var/spool/dovecot(/.*)?", "system_u:object_r:dovecot_spool_t:s0"), 102 | ("/var/spool/prelude(/.*)?", "system_u:object_r:prelude_spool_t:s0"), 103 | ("/var/spool/pyicq-t(/.*)?", "system_u:object_r:pyicqt_var_spool_t:s0"), 104 | ("/var/spool/rsyslog(/.*)?", "system_u:object_r:var_log_t:s0"), 105 | ("/var/spool/up2date(/.*)?", "system_u:object_r:rpm_var_cache_t:s0"), 106 | ("/var/spool/asterisk(/.*)?", "system_u:object_r:asterisk_spool_t:s0"), 107 | ("/var/spool/cups-pdf(/.*)?", "system_u:object_r:print_spool_t:s0"), 108 | ("/var/spool/opendkim(/.*)?", "system_u:object_r:dkim_milter_data_t:s0"), 109 | ("/var/spool/plymouth(/.*)?", "system_u:object_r:plymouthd_spool_t:s0"), 110 | ("/var/spool/mqueue\\.in(/.*)?", "system_u:object_r:mqueue_spool_t:s0"), 111 | ("/var/spool/opendmarc(/.*)?", "system_u:object_r:dkim_milter_data_t:s0"), 112 | ("/var/spool/MIMEDefang(/.*)?", "system_u:object_r:spamd_var_run_t:s0"), 113 | ("/var/spool/authdaemon(/.*)?", "system_u:object_r:courier_spool_t:s0"), 114 | ("/var/spool/bacula/log(/.*)?", "system_u:object_r:var_log_t:s0"), 115 | ("/var/spool/callweaver(/.*)?", "system_u:object_r:callweaver_spool_t:s0"), 116 | ("/var/spool/gridengine(/.*)?", "system_u:object_r:sge_spool_t:s0"), 117 | ("/var/spool/rhsm/debug(/.*)?", "system_u:object_r:abrt_var_cache_t:s0"), 118 | ("/var/spool/turboprint(/.*)?", "system_u:object_r:lpd_var_run_t:s0"), 119 | ("/var/spool/uucppublic(/.*)?", "system_u:object_r:uucpd_spool_t:s0"), 120 | ("/var/spool/MailScanner(/.*)?", "system_u:object_r:mscan_spool_t:s0"), 121 | ("/var/spool/abrt-upload(/.*)?", "system_u:object_r:public_content_rw_t:s0"), 122 | ("/var/spool/postfix/etc(/.*)?", "system_u:object_r:etc_t:s0"), 123 | ("/var/spool/postfix/lib(/.*)?", "system_u:object_r:lib_t:s0"), 124 | ("/var/spool/postfix/usr(/.*)?", "system_u:object_r:lib_t:s0"), 125 | ("/var/spool/postfix/pid/.*", "system_u:object_r:postfix_var_run_t:s0"), 126 | ("/var/spool/abrt-retrace(/.*)?", "system_u:object_r:abrt_retrace_spool_t:s0"), 127 | ("/var/spool/milter-regex(/.*)?", "system_u:object_r:regex_milter_data_t:s0"), 128 | ("/var/spool/spamassassin(/.*)?", "system_u:object_r:spamd_spool_t:s0"), 129 | ("/var/spool/squirrelmail(/.*)?", "system_u:object_r:squirrelmail_spool_t:s0"), 130 | ("/var/spool/MD-Quarantine(/.*)?", "system_u:object_r:spamd_var_run_t:s0"), 131 | ("/var/spool/postfix/defer(/.*)?", "system_u:object_r:postfix_spool_t:s0"), 132 | ("/var/spool/postfix/flush(/.*)?", "system_u:object_r:postfix_spool_t:s0"), 133 | ("/var/spool/postfix/lib64(/.*)?", "system_u:object_r:lib_t:s0"), 134 | ("/var/spool/postfix/bounce(/.*)?", "system_u:object_r:postfix_spool_bounce_t:s0"), 135 | ("/var/spool/postfix/public(/.*)?", "system_u:object_r:postfix_public_t:s0"), 136 | ("/var/spool/retrace-server(/.*)?", "system_u:object_r:abrt_retrace_spool_t:s0"), 137 | ("/var/spool/postfix/lib/ld.*\\.so.*", "system_u:object_r:ld_so_t:s0"), 138 | ("/var/spool/postfix/private(/.*)?", "system_u:object_r:postfix_private_t:s0"), 139 | ("/var/spool/postfix/spamass(/.*)?", "system_u:object_r:spamass_milter_data_t:s0"), 140 | ("/var/spool/prelude-manager(/.*)?", "system_u:object_r:prelude_spool_t:s0"), 141 | ("/var/spool/postfix/deferred(/.*)?", "system_u:object_r:postfix_spool_t:s0"), 142 | ("/var/spool/postfix/maildrop(/.*)?", "system_u:object_r:postfix_spool_t:s0"), 143 | ("/var/spool/postfix/postgrey(/.*)?", "system_u:object_r:postgrey_spool_t:s0"), 144 | ("/var/log/boot\.log.*", "system_u:object_r:plymouthd_var_log_t:s0"), 145 | ("/var/spool/plymouth/boot\.log.*", "system_u:object_r:plymouthd_var_log_t:s0"), 146 | ("/var/spool/zoneminder-upload(/.*)?", "system_u:object_r:zoneminder_spool_t:s0"), 147 | ] 148 | fcontexts_local = [ 149 | ("/var/spool/cron", "system_u:object_r:user_cron_spool_t:s0"), 150 | ("/var/spool/fcron", "system_u:object_r:cron_spool_t:s0"), 151 | ("/var/spool/postfix/dev", "system_u:object_r:device_t:s0"), 152 | ("/var/spool/postfix/pid", "system_u:object_r:var_run_t:s0"), 153 | ("/var/spool/fcron/systab", "system_u:object_r:system_cron_spool_t:s0"), 154 | ] 155 | fcontexts_homedirs = [ 156 | ("/var/spool/cron/crontabs", "system_u:object_r:cron_spool_t:s0"), 157 | ("/var/spool/postfix/dev/log", "system_u:object_r:devlog_t:s0"), 158 | ("/var/spool/fcron/new\\.systab", "system_u:object_r:system_cron_spool_t:s0"), 159 | ("/var/spool/fcron/systab\\.orig", "system_u:object_r:system_cron_spool_t:s0"), 160 | ("/var/spool/postfix/etc/localtime", "system_u:object_r:locale_t:s0"), 161 | ("/var/spool/cron/user", "system_u:object_r:user_cron_spool_t:s0"), 162 | ("/var/spool/cron/[^/]+", "system_u:object_r:user_cron_spool_t:s0"), 163 | ] 164 | 165 | semanage_fcontext_list = Mock(return_value=(0, fcontexts)) 166 | semanage_fcontext_list_local = Mock(return_value=(0, fcontexts_local)) 167 | semanage_fcontext_list_homedirs = Mock(return_value=(0, fcontexts_homedirs)) 168 | semanage_fcontext_get_expr = Mock(side_effect=lambda x: x[0]) 169 | semanage_fcontext_get_con = Mock(side_effect=lambda x: x[1]) 170 | -------------------------------------------------------------------------------- /tests/test_append_avc.podman.cil: -------------------------------------------------------------------------------- 1 | (block my_container 2 | (blockinherit container) 3 | (allow process process ( capability ( audit_write chown dac_override fowner fsetid kill mknod net_bind_service net_raw setfcap setgid setpcap setuid sys_chroot ))) 4 | 5 | (allow process tmp_t ( file ( write ))) 6 | (allow process tmp_t ( dir ( add_name ))) 7 | (allow process etc_t ( file ( open getattr read ))) 8 | ) 9 | -------------------------------------------------------------------------------- /tests/test_basic.ansible.podman.yml: -------------------------------------------------------------------------------- 1 | archive: my_container-policy.tar.gz 2 | policy: my_container.cil base_container.cil net_container.cil home_container.cil 3 | final_policy: my_container.cil -------------------------------------------------------------------------------- /tests/test_basic.cri.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": { 3 | "id": "ffae333ef3dc2d80311090fd239055c9d045b837240e41affb9d7ae7f2b5d237", 4 | "metadata": { 5 | "attempt": 0, 6 | "name": "spoolerrorlogger" 7 | }, 8 | "state": "CONTAINER_RUNNING", 9 | "createdAt": "2019-09-23T13:52:39.968798859Z", 10 | "startedAt": "2019-09-23T13:52:40.044502422Z", 11 | "finishedAt": "1970-01-01T00:00:00Z", 12 | "exitCode": 0, 13 | "image": { 14 | "image": "registry.access.redhat.com/ubi8/ubi:latest" 15 | }, 16 | "imageRef": "registry.access.redhat.com/ubi8/ubi@sha256:8275e2ad7f458e329bdc8c0e7543cff1729998fe515a281d49638246de8e39ee", 17 | "reason": "", 18 | "message": "", 19 | "labels": { 20 | "io.kubernetes.container.name": "spoolerrorlogger", 21 | "io.kubernetes.pod.name": "spoolerrorlogger", 22 | "io.kubernetes.pod.namespace": "default", 23 | "io.kubernetes.pod.uid": "59ecb6eb-de09-11e9-8ebe-02e4204e049a" 24 | }, 25 | "annotations": { 26 | "io.kubernetes.container.hash": "113e3fda", 27 | "io.kubernetes.container.restartCount": "0", 28 | "io.kubernetes.container.terminationMessagePath": "/dev/termination-log", 29 | "io.kubernetes.container.terminationMessagePolicy": "File", 30 | "io.kubernetes.pod.terminationGracePeriod": "30" 31 | }, 32 | "mounts": [ 33 | { 34 | "containerPath": "/home", 35 | "hostPath": "/home", 36 | "propagation": "PROPAGATION_PRIVATE", 37 | "readonly": true, 38 | "selinuxRelabel": false 39 | }, 40 | { 41 | "containerPath": "/var/spool", 42 | "hostPath": "/var/spool", 43 | "propagation": "PROPAGATION_PRIVATE", 44 | "readonly": false, 45 | "selinuxRelabel": false 46 | }, 47 | { 48 | "containerPath": "/etc/hosts", 49 | "hostPath": "/etc/hosts", 50 | "propagation": "PROPAGATION_PRIVATE", 51 | "readonly": true, 52 | "selinuxRelabel": false 53 | }, 54 | { 55 | "containerPath": "/dev/termination-log", 56 | "hostPath": "/var/lib/kubelet/pods/59ecb6eb-de09-11e9-8ebe-02e4204e049a/containers/spoolerrorlogger/9e6bce3f", 57 | "propagation": "PROPAGATION_PRIVATE", 58 | "readonly": false, 59 | "selinuxRelabel": false 60 | }, 61 | { 62 | "containerPath": "/var/run/secrets/kubernetes.io/serviceaccount", 63 | "hostPath": "/var/lib/kubelet/pods/59ecb6eb-de09-11e9-8ebe-02e4204e049a/volumes/kubernetes.io~secret/default-token-rssn6", 64 | "propagation": "PROPAGATION_PRIVATE", 65 | "readonly": true, 66 | "selinuxRelabel": false 67 | } 68 | ], 69 | "logPath": "/var/log/pods/default_spoolerrorlogger_59ecb6eb-de09-11e9-8ebe-02e4204e049a/spoolerrorlogger/0.log" 70 | }, 71 | "pid": 47737, 72 | "sandboxId": "426ba7380ad7efdcf207f0df107d5c9d7389755a2a89372d24199350c70861d6" 73 | } 74 | -------------------------------------------------------------------------------- /tests/test_basic.docker.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "Id": "28ed0f82f8bca461d0c0e029067042178b3973d461584c76acfad5b877bd3b07", 4 | "Created": "2019-03-06T12:48:02.419991511Z", 5 | "Path": "bash", 6 | "Args": [], 7 | "State": { 8 | "Status": "running", 9 | "Running": true, 10 | "Paused": false, 11 | "Restarting": false, 12 | "OOMKilled": false, 13 | "Dead": false, 14 | "Pid": 17574, 15 | "ExitCode": 0, 16 | "Error": "", 17 | "StartedAt": "2019-03-06T12:48:02.984662576Z", 18 | "FinishedAt": "0001-01-01T00:00:00Z" 19 | }, 20 | "Image": "sha256:d7372e6c93c6c7b925600981b655c94829515a37cf876ff9e6d0287ff2b739d9", 21 | "ResolvConfPath": "/var/lib/docker/containers/28ed0f82f8bca461d0c0e029067042178b3973d461584c76acfad5b877bd3b07/resolv.conf", 22 | "HostnamePath": "/var/lib/docker/containers/28ed0f82f8bca461d0c0e029067042178b3973d461584c76acfad5b877bd3b07/hostname", 23 | "HostsPath": "/var/lib/docker/containers/28ed0f82f8bca461d0c0e029067042178b3973d461584c76acfad5b877bd3b07/hosts", 24 | "LogPath": "", 25 | "Name": "/compassionate_mcclintock", 26 | "RestartCount": 0, 27 | "Driver": "overlay2", 28 | "MountLabel": "system_u:object_r:container_file_t:s0:c648,c780", 29 | "ProcessLabel": "system_u:system_r:container_t:s0:c648,c780", 30 | "AppArmorProfile": "", 31 | "ExecIDs": null, 32 | "HostConfig": { 33 | "Binds": [ 34 | "/home:/home:ro", 35 | "/var/spool:/var/spool:rw" 36 | ], 37 | "ContainerIDFile": "", 38 | "LogConfig": { 39 | "Type": "journald", 40 | "Config": {} 41 | }, 42 | "NetworkMode": "default", 43 | "PortBindings": { 44 | "21/tcp": [ 45 | { 46 | "HostIp": "", 47 | "HostPort": "21" 48 | } 49 | ] 50 | }, 51 | "RestartPolicy": { 52 | "Name": "no", 53 | "MaximumRetryCount": 0 54 | }, 55 | "AutoRemove": false, 56 | "VolumeDriver": "", 57 | "VolumesFrom": null, 58 | "CapAdd": null, 59 | "CapDrop": null, 60 | "Dns": [], 61 | "DnsOptions": [], 62 | "DnsSearch": [], 63 | "ExtraHosts": null, 64 | "GroupAdd": null, 65 | "IpcMode": "", 66 | "Cgroup": "", 67 | "Links": null, 68 | "OomScoreAdj": 0, 69 | "PidMode": "", 70 | "Privileged": false, 71 | "PublishAllPorts": false, 72 | "ReadonlyRootfs": false, 73 | "SecurityOpt": null, 74 | "UTSMode": "", 75 | "UsernsMode": "", 76 | "ShmSize": 67108864, 77 | "Runtime": "oci", 78 | "ConsoleSize": [ 79 | 0, 80 | 0 81 | ], 82 | "Isolation": "", 83 | "CpuShares": 0, 84 | "Memory": 0, 85 | "NanoCpus": 0, 86 | "CgroupParent": "", 87 | "BlkioWeight": 0, 88 | "BlkioWeightDevice": null, 89 | "BlkioDeviceReadBps": null, 90 | "BlkioDeviceWriteBps": null, 91 | "BlkioDeviceReadIOps": null, 92 | "BlkioDeviceWriteIOps": null, 93 | "CpuPeriod": 0, 94 | "CpuQuota": 0, 95 | "CpuRealtimePeriod": 0, 96 | "CpuRealtimeRuntime": 0, 97 | "CpusetCpus": "", 98 | "CpusetMems": "", 99 | "Devices": [], 100 | "DiskQuota": 0, 101 | "KernelMemory": 0, 102 | "MemoryReservation": 0, 103 | "MemorySwap": 0, 104 | "MemorySwappiness": -1, 105 | "OomKillDisable": false, 106 | "PidsLimit": 0, 107 | "Ulimits": null, 108 | "CpuCount": 0, 109 | "CpuPercent": 0, 110 | "IOMaximumIOps": 0, 111 | "IOMaximumBandwidth": 0 112 | }, 113 | "GraphDriver": { 114 | "Name": "overlay2", 115 | "Data": { 116 | "LowerDir": "/var/lib/docker/overlay2/53cfa4316fa3f0daff8a2b5bf7d30a1a01f33163b9b1eddfb135188a0590114b-init/diff:/var/lib/docker/overlay2/03335b384d160af8a2d33330b4ea1440f87cbfab559a3ffd3102c031e14f3e20/diff", 117 | "MergedDir": "/var/lib/docker/overlay2/53cfa4316fa3f0daff8a2b5bf7d30a1a01f33163b9b1eddfb135188a0590114b/merged", 118 | "UpperDir": "/var/lib/docker/overlay2/53cfa4316fa3f0daff8a2b5bf7d30a1a01f33163b9b1eddfb135188a0590114b/diff", 119 | "WorkDir": "/var/lib/docker/overlay2/53cfa4316fa3f0daff8a2b5bf7d30a1a01f33163b9b1eddfb135188a0590114b/work" 120 | } 121 | }, 122 | "Mounts": [ 123 | { 124 | "Type": "bind", 125 | "Source": "/home", 126 | "Destination": "/home", 127 | "Mode": "ro", 128 | "RW": false, 129 | "Propagation": "rprivate" 130 | }, 131 | { 132 | "Type": "bind", 133 | "Source": "/var/spool", 134 | "Destination": "/var/spool", 135 | "Mode": "rw", 136 | "RW": true, 137 | "Propagation": "rprivate" 138 | } 139 | ], 140 | "Config": { 141 | "Hostname": "28ed0f82f8bc", 142 | "Domainname": "", 143 | "User": "", 144 | "AttachStdin": false, 145 | "AttachStdout": false, 146 | "AttachStderr": false, 147 | "ExposedPorts": { 148 | "21/tcp": {} 149 | }, 150 | "Tty": true, 151 | "OpenStdin": true, 152 | "StdinOnce": false, 153 | "Env": [ 154 | "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", 155 | "DISTTAG=f29container", 156 | "FGC=f29", 157 | "FBR=f29" 158 | ], 159 | "Cmd": [ 160 | "bash" 161 | ], 162 | "Image": "fedora", 163 | "Volumes": null, 164 | "WorkingDir": "", 165 | "Entrypoint": null, 166 | "OnBuild": null, 167 | "Labels": { 168 | "maintainer": "Clement Verna " 169 | } 170 | }, 171 | "NetworkSettings": { 172 | "Bridge": "", 173 | "SandboxID": "b880939c9e288f0105990445c79626778951846e27aa14a566ad8bebb84501dd", 174 | "HairpinMode": false, 175 | "LinkLocalIPv6Address": "", 176 | "LinkLocalIPv6PrefixLen": 0, 177 | "Ports": { 178 | "21/tcp": [ 179 | { 180 | "HostIp": "0.0.0.0", 181 | "HostPort": "21" 182 | } 183 | ] 184 | }, 185 | "SandboxKey": "/var/run/docker/netns/b880939c9e28", 186 | "SecondaryIPAddresses": null, 187 | "SecondaryIPv6Addresses": null, 188 | "EndpointID": "ab0f0ff865e69b01afc1734c53df4a5f14a6b64ed2bb5499539d0f8a3e067f69", 189 | "Gateway": "172.17.0.1", 190 | "GlobalIPv6Address": "", 191 | "GlobalIPv6PrefixLen": 0, 192 | "IPAddress": "172.17.0.2", 193 | "IPPrefixLen": 16, 194 | "IPv6Gateway": "", 195 | "MacAddress": "02:42:ac:11:00:02", 196 | "Networks": { 197 | "bridge": { 198 | "IPAMConfig": null, 199 | "Links": null, 200 | "Aliases": null, 201 | "NetworkID": "565ce26d5e6f78b68b4c149109ab422575f2c2842ea5f5ed46977f08fcb75b91", 202 | "EndpointID": "ab0f0ff865e69b01afc1734c53df4a5f14a6b64ed2bb5499539d0f8a3e067f69", 203 | "Gateway": "172.17.0.1", 204 | "IPAddress": "172.17.0.2", 205 | "IPPrefixLen": 16, 206 | "IPv6Gateway": "", 207 | "GlobalIPv6Address": "", 208 | "GlobalIPv6PrefixLen": 0, 209 | "MacAddress": "02:42:ac:11:00:02" 210 | } 211 | } 212 | } 213 | } 214 | ] 215 | 216 | -------------------------------------------------------------------------------- /tests/test_basic.podman.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "Id": "8569f5d102de80b9065bd0561300efe804d831d98ffbf5b423871de6ece3053e", 4 | "Created": "2020-08-03T16:37:26.089602932+02:00", 5 | "Path": "/bin/bash", 6 | "Args": [ 7 | "/bin/bash" 8 | ], 9 | "State": { 10 | "OciVersion": "1.0.2-dev", 11 | "Status": "running", 12 | "Running": true, 13 | "Paused": false, 14 | "Restarting": false, 15 | "OOMKilled": false, 16 | "Dead": false, 17 | "Pid": 528947, 18 | "ConmonPid": 528942, 19 | "ExitCode": 0, 20 | "Error": "", 21 | "StartedAt": "2020-08-03T16:37:26.575432963+02:00", 22 | "FinishedAt": "0001-01-01T00:00:00Z", 23 | "Healthcheck": { 24 | "Status": "", 25 | "FailingStreak": 0, 26 | "Log": null 27 | } 28 | }, 29 | "Image": "00ff39a8bf19f810a7e641f7eb3ddc47635913a19c4996debd91fafb6b379069", 30 | "ImageName": "registry.fedoraproject.org/fedora:latest", 31 | "Rootfs": "", 32 | "Pod": "", 33 | "ResolvConfPath": "/var/run/containers/storage/overlay-containers/8569f5d102de80b9065bd0561300efe804d831d98ffbf5b423871de6ece3053e/userdata/resolv.conf", 34 | "HostnamePath": "/var/run/containers/storage/overlay-containers/8569f5d102de80b9065bd0561300efe804d831d98ffbf5b423871de6ece3053e/userdata/hostname", 35 | "HostsPath": "/var/run/containers/storage/overlay-containers/8569f5d102de80b9065bd0561300efe804d831d98ffbf5b423871de6ece3053e/userdata/hosts", 36 | "StaticDir": "/var/lib/containers/storage/overlay-containers/8569f5d102de80b9065bd0561300efe804d831d98ffbf5b423871de6ece3053e/userdata", 37 | "OCIConfigPath": "/var/lib/containers/storage/overlay-containers/8569f5d102de80b9065bd0561300efe804d831d98ffbf5b423871de6ece3053e/userdata/config.json", 38 | "OCIRuntime": "crun", 39 | "LogPath": "/var/lib/containers/storage/overlay-containers/8569f5d102de80b9065bd0561300efe804d831d98ffbf5b423871de6ece3053e/userdata/ctr.log", 40 | "LogTag": "", 41 | "ConmonPidFile": "/var/run/containers/storage/overlay-containers/8569f5d102de80b9065bd0561300efe804d831d98ffbf5b423871de6ece3053e/userdata/conmon.pid", 42 | "Name": "strange_visvesvaraya", 43 | "RestartCount": 0, 44 | "Driver": "overlay", 45 | "MountLabel": "system_u:object_r:container_file_t:s0:c166,c565", 46 | "ProcessLabel": "system_u:system_r:container_t:s0:c166,c565", 47 | "AppArmorProfile": "", 48 | "EffectiveCaps": [ 49 | "CAP_AUDIT_WRITE", 50 | "CAP_CHOWN", 51 | "CAP_DAC_OVERRIDE", 52 | "CAP_FOWNER", 53 | "CAP_FSETID", 54 | "CAP_KILL", 55 | "CAP_MKNOD", 56 | "CAP_NET_BIND_SERVICE", 57 | "CAP_NET_RAW", 58 | "CAP_SETFCAP", 59 | "CAP_SETGID", 60 | "CAP_SETPCAP", 61 | "CAP_SETUID", 62 | "CAP_SYS_CHROOT" 63 | ], 64 | "BoundingCaps": [ 65 | "CAP_AUDIT_WRITE", 66 | "CAP_CHOWN", 67 | "CAP_DAC_OVERRIDE", 68 | "CAP_FOWNER", 69 | "CAP_FSETID", 70 | "CAP_KILL", 71 | "CAP_MKNOD", 72 | "CAP_NET_BIND_SERVICE", 73 | "CAP_NET_RAW", 74 | "CAP_SETFCAP", 75 | "CAP_SETGID", 76 | "CAP_SETPCAP", 77 | "CAP_SETUID", 78 | "CAP_SYS_CHROOT" 79 | ], 80 | "ExecIDs": [], 81 | "GraphDriver": { 82 | "Name": "overlay", 83 | "Data": { 84 | "LowerDir": "/var/lib/containers/storage/overlay/0ccfac04663bbe8813b5f24502ee0b7371ce5bf3c5adeb12e4258d191c2cf7bc/diff", 85 | "MergedDir": "/var/lib/containers/storage/overlay/26cb6707f9563ff3be5347d624db6072a461553bb1a589e4160a1ca579b83c36/merged", 86 | "UpperDir": "/var/lib/containers/storage/overlay/26cb6707f9563ff3be5347d624db6072a461553bb1a589e4160a1ca579b83c36/diff", 87 | "WorkDir": "/var/lib/containers/storage/overlay/26cb6707f9563ff3be5347d624db6072a461553bb1a589e4160a1ca579b83c36/work" 88 | } 89 | }, 90 | "Mounts": [ 91 | { 92 | "Type": "bind", 93 | "Name": "", 94 | "Source": "/home", 95 | "Destination": "/home", 96 | "Driver": "", 97 | "Mode": "", 98 | "Options": [ 99 | "rbind" 100 | ], 101 | "RW": false, 102 | "Propagation": "rprivate" 103 | }, 104 | { 105 | "Type": "bind", 106 | "Name": "", 107 | "Source": "/var/spool", 108 | "Destination": "/var/spool", 109 | "Driver": "", 110 | "Mode": "", 111 | "Options": [ 112 | "rbind" 113 | ], 114 | "RW": true, 115 | "Propagation": "rprivate" 116 | } 117 | ], 118 | "Dependencies": [], 119 | "NetworkSettings": { 120 | "EndpointID": "", 121 | "Gateway": "10.88.0.1", 122 | "IPAddress": "10.88.0.239", 123 | "IPPrefixLen": 16, 124 | "IPv6Gateway": "", 125 | "GlobalIPv6Address": "", 126 | "GlobalIPv6PrefixLen": 0, 127 | "MacAddress": "8a:e9:4b:bf:32:40", 128 | "Bridge": "", 129 | "SandboxID": "", 130 | "HairpinMode": false, 131 | "LinkLocalIPv6Address": "", 132 | "LinkLocalIPv6PrefixLen": 0, 133 | "Ports": { 134 | "21/tcp": [ 135 | { 136 | "HostIp": "", 137 | "HostPort": "21" 138 | } 139 | ] 140 | }, 141 | "SandboxKey": "/var/run/netns/cni-ef4ae8a3-3855-cd2c-a3bd-b8ee92b14ca5" 142 | }, 143 | "ExitCommand": [ 144 | "/usr/bin/podman", 145 | "--root", 146 | "/var/lib/containers/storage", 147 | "--runroot", 148 | "/var/run/containers/storage", 149 | "--log-level", 150 | "error", 151 | "--cgroup-manager", 152 | "systemd", 153 | "--tmpdir", 154 | "/var/run/libpod", 155 | "--runtime", 156 | "crun", 157 | "--storage-driver", 158 | "overlay", 159 | "--storage-opt", 160 | "overlay.mountopt=nodev,metacopy=on", 161 | "--events-backend", 162 | "file", 163 | "container", 164 | "cleanup", 165 | "8569f5d102de80b9065bd0561300efe804d831d98ffbf5b423871de6ece3053e" 166 | ], 167 | "Namespace": "", 168 | "IsInfra": false, 169 | "Config": { 170 | "Hostname": "8569f5d102de", 171 | "Domainname": "", 172 | "User": "", 173 | "AttachStdin": false, 174 | "AttachStdout": false, 175 | "AttachStderr": false, 176 | "Tty": true, 177 | "OpenStdin": true, 178 | "StdinOnce": false, 179 | "Env": [ 180 | "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", 181 | "TERM=xterm", 182 | "container=podman", 183 | "DISTTAG=f32container", 184 | "FGC=f32", 185 | "HOSTNAME=8569f5d102de", 186 | "HOME=/root" 187 | ], 188 | "Cmd": [ 189 | "/bin/bash" 190 | ], 191 | "Image": "registry.fedoraproject.org/fedora:latest", 192 | "Volumes": null, 193 | "WorkingDir": "/", 194 | "Entrypoint": "", 195 | "OnBuild": null, 196 | "Labels": { 197 | "license": "MIT", 198 | "name": "fedora", 199 | "vendor": "Fedora Project", 200 | "version": "32" 201 | }, 202 | "Annotations": { 203 | "io.container.manager": "libpod", 204 | "io.kubernetes.cri-o.Created": "2020-08-03T16:37:26.089602932+02:00", 205 | "io.kubernetes.cri-o.TTY": "true", 206 | "io.podman.annotations.autoremove": "FALSE", 207 | "io.podman.annotations.init": "FALSE", 208 | "io.podman.annotations.privileged": "FALSE", 209 | "io.podman.annotations.publish-all": "FALSE", 210 | "org.opencontainers.image.stopSignal": "15" 211 | }, 212 | "StopSignal": 15, 213 | "CreateCommand": [ 214 | "/bin/podman", 215 | "run", 216 | "-it", 217 | "-v", 218 | "/home:/home:ro", 219 | "-v", 220 | "/var/spool:/var/spool:rw", 221 | "-p", 222 | "21:21", 223 | "fedora" 224 | ] 225 | }, 226 | "HostConfig": { 227 | "Binds": [ 228 | "/home:/home:ro,rprivate,rbind", 229 | "/var/spool:/var/spool:rw,rprivate,rbind" 230 | ], 231 | "CgroupMode": "private", 232 | "ContainerIDFile": "", 233 | "LogConfig": { 234 | "Type": "k8s-file", 235 | "Config": null 236 | }, 237 | "NetworkMode": "bridge", 238 | "PortBindings": { 239 | "21/tcp": [ 240 | { 241 | "HostIp": "", 242 | "HostPort": "21" 243 | } 244 | ] 245 | }, 246 | "RestartPolicy": { 247 | "Name": "", 248 | "MaximumRetryCount": 0 249 | }, 250 | "AutoRemove": false, 251 | "VolumeDriver": "", 252 | "VolumesFrom": null, 253 | "CapAdd": [], 254 | "CapDrop": [], 255 | "Dns": [], 256 | "DnsOptions": [], 257 | "DnsSearch": [], 258 | "ExtraHosts": [], 259 | "GroupAdd": [], 260 | "IpcMode": "private", 261 | "Cgroup": "", 262 | "Cgroups": "default", 263 | "Links": null, 264 | "OomScoreAdj": 0, 265 | "PidMode": "private", 266 | "Privileged": false, 267 | "PublishAllPorts": false, 268 | "ReadonlyRootfs": false, 269 | "SecurityOpt": [], 270 | "Tmpfs": {}, 271 | "UTSMode": "private", 272 | "UsernsMode": "", 273 | "ShmSize": 65536000, 274 | "Runtime": "oci", 275 | "ConsoleSize": [ 276 | 0, 277 | 0 278 | ], 279 | "Isolation": "", 280 | "CpuShares": 0, 281 | "Memory": 0, 282 | "NanoCpus": 0, 283 | "CgroupParent": "", 284 | "BlkioWeight": 0, 285 | "BlkioWeightDevice": null, 286 | "BlkioDeviceReadBps": null, 287 | "BlkioDeviceWriteBps": null, 288 | "BlkioDeviceReadIOps": null, 289 | "BlkioDeviceWriteIOps": null, 290 | "CpuPeriod": 0, 291 | "CpuQuota": 0, 292 | "CpuRealtimePeriod": 0, 293 | "CpuRealtimeRuntime": 0, 294 | "CpusetCpus": "", 295 | "CpusetMems": "", 296 | "Devices": [], 297 | "DiskQuota": 0, 298 | "KernelMemory": 0, 299 | "MemoryReservation": 0, 300 | "MemorySwap": 0, 301 | "MemorySwappiness": 0, 302 | "OomKillDisable": false, 303 | "PidsLimit": 2048, 304 | "Ulimits": [ 305 | { 306 | "Name": "RLIMIT_NOFILE", 307 | "Soft": 1048576, 308 | "Hard": 1048576 309 | }, 310 | { 311 | "Name": "RLIMIT_NPROC", 312 | "Soft": 4194304, 313 | "Hard": 4194304 314 | } 315 | ], 316 | "CpuCount": 0, 317 | "CpuPercent": 0, 318 | "IOMaximumIOps": 0, 319 | "IOMaximumBandwidth": 0 320 | } 321 | } 322 | ] 323 | -------------------------------------------------------------------------------- /tests/test_confined_abcdgilmns.cil: -------------------------------------------------------------------------------- 1 | (boolean my_container_exec_content true) 2 | (role my_container_r) 3 | (type my_container_dbus_t) 4 | (type my_container_gkeyringd_t) 5 | (type my_container_ssh_agent_t) 6 | (type my_container_sudo_t) 7 | (type my_container_sudo_tmp_t) 8 | (type my_container_t) 9 | (type my_container_userhelper_t) 10 | (user my_container_u) 11 | (userrole my_container_u my_container_r) 12 | (userlevel my_container_u (s0)) 13 | (userrange my_container_u ((s0 ) (s0 (c0)))) 14 | 15 | (call confinedom_admin_commands_macro (my_container_t my_container_r my_container_sudo_t)) 16 | (call confinedom_graphical_login_macro (my_container_t my_container_r my_container_dbus_t)) 17 | (call confinedom_mozilla_usage_macro (my_container_t my_container_r)) 18 | (call confinedom_networking_macro (my_container_t my_container_r)) 19 | (call confinedom_security_advanced_macro (my_container_t my_container_r my_container_sudo_t my_container_userhelper_t)) 20 | (call confinedom_security_basic_macro (my_container_t my_container_r)) 21 | (call confinedom_sudo_macro (my_container_t my_container_r my_container_sudo_t my_container_sudo_tmp_t)) 22 | (call confinedom_user_login_macro (my_container_t my_container_r my_container_gkeyringd_t my_container_dbus_t my_container_exec_content)) 23 | (call confined_ssh_connect_macro (my_container_t my_container_r my_container_ssh_agent_t)) 24 | (call confined_use_basic_commands_macro (my_container_t my_container_r)) -------------------------------------------------------------------------------- /tests/test_confined_cla.cil: -------------------------------------------------------------------------------- 1 | (boolean my_container_exec_content true) 2 | (role my_container_r) 3 | (type my_container_dbus_t) 4 | (type my_container_gkeyringd_t) 5 | (type my_container_ssh_agent_t) 6 | (type my_container_sudo_t) 7 | (type my_container_t) 8 | (user my_container_u) 9 | (userrole my_container_u my_container_r) 10 | (userlevel my_container_u (s0)) 11 | (userrange my_container_u ((s0 ) (s0 (c0)))) 12 | 13 | (call confinedom_admin_commands_macro (my_container_t my_container_r my_container_sudo_t)) 14 | (call confinedom_user_login_macro (my_container_t my_container_r my_container_gkeyringd_t my_container_dbus_t my_container_exec_content)) 15 | (call confined_ssh_connect_macro (my_container_t my_container_r my_container_ssh_agent_t)) -------------------------------------------------------------------------------- /tests/test_confined_lb.cil: -------------------------------------------------------------------------------- 1 | (boolean my_container_exec_content true) 2 | (role my_container_r) 3 | (type my_container_dbus_t) 4 | (type my_container_gkeyringd_t) 5 | (type my_container_t) 6 | (user my_container_u) 7 | (userrole my_container_u my_container_r) 8 | (userlevel my_container_u (s0)) 9 | (userrange my_container_u ((s0 ) (s0 (c0)))) 10 | 11 | (call confinedom_user_login_macro (my_container_t my_container_r my_container_gkeyringd_t my_container_dbus_t my_container_exec_content)) 12 | (call confined_use_basic_commands_macro (my_container_t my_container_r)) -------------------------------------------------------------------------------- /tests/test_confined_lsid.cil: -------------------------------------------------------------------------------- 1 | (boolean my_container_exec_content true) 2 | (role my_container_r) 3 | (type my_container_dbus_t) 4 | (type my_container_gkeyringd_t) 5 | (type my_container_sudo_t) 6 | (type my_container_sudo_tmp_t) 7 | (type my_container_t) 8 | (type my_container_userhelper_t) 9 | (user my_container_u) 10 | (userrole my_container_u my_container_r) 11 | (userlevel my_container_u (s0)) 12 | (userrange my_container_u ((s0 ) (s0 (c0)))) 13 | 14 | (call confinedom_security_advanced_macro (my_container_t my_container_r my_container_sudo_t my_container_userhelper_t)) 15 | (call confinedom_security_basic_macro (my_container_t my_container_r)) 16 | (call confinedom_sudo_macro (my_container_t my_container_r my_container_sudo_t my_container_sudo_tmp_t)) 17 | (call confinedom_user_login_macro (my_container_t my_container_r my_container_gkeyringd_t my_container_dbus_t my_container_exec_content)) -------------------------------------------------------------------------------- /tests/test_default.ansible.podman.yml: -------------------------------------------------------------------------------- 1 | archive: my_container-policy.tar.gz 2 | policy: my_container.cil base_container.cil 3 | final_policy: my_container.cil 4 | -------------------------------------------------------------------------------- /tests/test_default.docker.cil: -------------------------------------------------------------------------------- 1 | (block my_container 2 | (blockinherit container) 3 | ) -------------------------------------------------------------------------------- /tests/test_default.docker.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "Id": "f35680f1c518032516e38688654c226d09582bc8e780cf062063f91612ffff17", 4 | "Created": "2019-03-06T13:43:14.838743431Z", 5 | "Path": "/bin/bash", 6 | "Args": [], 7 | "State": { 8 | "Status": "running", 9 | "Running": true, 10 | "Paused": false, 11 | "Restarting": false, 12 | "OOMKilled": false, 13 | "Dead": false, 14 | "Pid": 2866, 15 | "ExitCode": 0, 16 | "Error": "", 17 | "StartedAt": "2019-03-06T13:43:15.262353177Z", 18 | "FinishedAt": "0001-01-01T00:00:00Z" 19 | }, 20 | "Image": "sha256:d7372e6c93c6c7b925600981b655c94829515a37cf876ff9e6d0287ff2b739d9", 21 | "ResolvConfPath": "/var/lib/docker/containers/f35680f1c518032516e38688654c226d09582bc8e780cf062063f91612ffff17/resolv.conf", 22 | "HostnamePath": "/var/lib/docker/containers/f35680f1c518032516e38688654c226d09582bc8e780cf062063f91612ffff17/hostname", 23 | "HostsPath": "/var/lib/docker/containers/f35680f1c518032516e38688654c226d09582bc8e780cf062063f91612ffff17/hosts", 24 | "LogPath": "", 25 | "Name": "/agitated_keller", 26 | "RestartCount": 0, 27 | "Driver": "overlay2", 28 | "MountLabel": "system_u:object_r:container_file_t:s0:c374,c775", 29 | "ProcessLabel": "system_u:system_r:container_t:s0:c374,c775", 30 | "AppArmorProfile": "", 31 | "ExecIDs": null, 32 | "HostConfig": { 33 | "Binds": null, 34 | "ContainerIDFile": "", 35 | "LogConfig": { 36 | "Type": "journald", 37 | "Config": {} 38 | }, 39 | "NetworkMode": "default", 40 | "PortBindings": {}, 41 | "RestartPolicy": { 42 | "Name": "no", 43 | "MaximumRetryCount": 0 44 | }, 45 | "AutoRemove": false, 46 | "VolumeDriver": "", 47 | "VolumesFrom": null, 48 | "CapAdd": null, 49 | "CapDrop": null, 50 | "Dns": [], 51 | "DnsOptions": [], 52 | "DnsSearch": [], 53 | "ExtraHosts": null, 54 | "GroupAdd": null, 55 | "IpcMode": "", 56 | "Cgroup": "", 57 | "Links": null, 58 | "OomScoreAdj": 0, 59 | "PidMode": "", 60 | "Privileged": false, 61 | "PublishAllPorts": false, 62 | "ReadonlyRootfs": false, 63 | "SecurityOpt": null, 64 | "UTSMode": "", 65 | "UsernsMode": "", 66 | "ShmSize": 67108864, 67 | "Runtime": "oci", 68 | "ConsoleSize": [ 69 | 0, 70 | 0 71 | ], 72 | "Isolation": "", 73 | "CpuShares": 0, 74 | "Memory": 0, 75 | "NanoCpus": 0, 76 | "CgroupParent": "", 77 | "BlkioWeight": 0, 78 | "BlkioWeightDevice": null, 79 | "BlkioDeviceReadBps": null, 80 | "BlkioDeviceWriteBps": null, 81 | "BlkioDeviceReadIOps": null, 82 | "BlkioDeviceWriteIOps": null, 83 | "CpuPeriod": 0, 84 | "CpuQuota": 0, 85 | "CpuRealtimePeriod": 0, 86 | "CpuRealtimeRuntime": 0, 87 | "CpusetCpus": "", 88 | "CpusetMems": "", 89 | "Devices": [], 90 | "DiskQuota": 0, 91 | "KernelMemory": 0, 92 | "MemoryReservation": 0, 93 | "MemorySwap": 0, 94 | "MemorySwappiness": -1, 95 | "OomKillDisable": false, 96 | "PidsLimit": 0, 97 | "Ulimits": null, 98 | "CpuCount": 0, 99 | "CpuPercent": 0, 100 | "IOMaximumIOps": 0, 101 | "IOMaximumBandwidth": 0 102 | }, 103 | "GraphDriver": { 104 | "Name": "overlay2", 105 | "Data": { 106 | "LowerDir": "/var/lib/docker/overlay2/0b383cce0b2a34ece910e582fb43b9a0fb737ca63a497315c7918f481c55836e-init/diff:/var/lib/docker/overlay2/e6634b68fb3e2ab903f94af0418aa43834c987b41c5b0c2faec92c98a6c6cbed/diff", 107 | "MergedDir": "/var/lib/docker/overlay2/0b383cce0b2a34ece910e582fb43b9a0fb737ca63a497315c7918f481c55836e/merged", 108 | "UpperDir": "/var/lib/docker/overlay2/0b383cce0b2a34ece910e582fb43b9a0fb737ca63a497315c7918f481c55836e/diff", 109 | "WorkDir": "/var/lib/docker/overlay2/0b383cce0b2a34ece910e582fb43b9a0fb737ca63a497315c7918f481c55836e/work" 110 | } 111 | }, 112 | "Mounts": [], 113 | "Config": { 114 | "Hostname": "f35680f1c518", 115 | "Domainname": "", 116 | "User": "", 117 | "AttachStdin": false, 118 | "AttachStdout": false, 119 | "AttachStderr": false, 120 | "Tty": true, 121 | "OpenStdin": true, 122 | "StdinOnce": false, 123 | "Env": [ 124 | "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", 125 | "DISTTAG=f29container", 126 | "FGC=f29", 127 | "FBR=f29" 128 | ], 129 | "Cmd": [ 130 | "/bin/bash" 131 | ], 132 | "ArgsEscaped": true, 133 | "Image": "fedora", 134 | "Volumes": null, 135 | "WorkingDir": "", 136 | "Entrypoint": null, 137 | "OnBuild": null, 138 | "Labels": { 139 | "maintainer": "Clement Verna " 140 | } 141 | }, 142 | "NetworkSettings": { 143 | "Bridge": "", 144 | "SandboxID": "4ea8182a58cfa68b384f26ca50cd6137d9ed9a7832f882244e9e822d1af29095", 145 | "HairpinMode": false, 146 | "LinkLocalIPv6Address": "", 147 | "LinkLocalIPv6PrefixLen": 0, 148 | "Ports": {}, 149 | "SandboxKey": "/var/run/docker/netns/4ea8182a58cf", 150 | "SecondaryIPAddresses": null, 151 | "SecondaryIPv6Addresses": null, 152 | "EndpointID": "7efdef721e4aecde64e4279a20240d7cf33c15d3cb008b6f9e414ab6d77b9c4e", 153 | "Gateway": "172.17.0.1", 154 | "GlobalIPv6Address": "", 155 | "GlobalIPv6PrefixLen": 0, 156 | "IPAddress": "172.17.0.2", 157 | "IPPrefixLen": 16, 158 | "IPv6Gateway": "", 159 | "MacAddress": "02:42:ac:11:00:02", 160 | "Networks": { 161 | "bridge": { 162 | "IPAMConfig": null, 163 | "Links": null, 164 | "Aliases": null, 165 | "NetworkID": "7bb2c1062ca330fd53fc336340bc2def615d85bb73f7cae1aba8303286ed8e03", 166 | "EndpointID": "7efdef721e4aecde64e4279a20240d7cf33c15d3cb008b6f9e414ab6d77b9c4e", 167 | "Gateway": "172.17.0.1", 168 | "IPAddress": "172.17.0.2", 169 | "IPPrefixLen": 16, 170 | "IPv6Gateway": "", 171 | "GlobalIPv6Address": "", 172 | "GlobalIPv6PrefixLen": 0, 173 | "MacAddress": "02:42:ac:11:00:02" 174 | } 175 | } 176 | } 177 | } 178 | ] 179 | 180 | -------------------------------------------------------------------------------- /tests/test_default.oci.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "Id": "2d497441ae0102ac214c6a0c241ceae67858ff40bc35e46b7d95c7cbf1c9cf27", 4 | "Created": "2020-08-03T16:49:26.218811778+02:00", 5 | "Path": "/bin/bash", 6 | "Args": [ 7 | "/bin/bash" 8 | ], 9 | "State": { 10 | "OciVersion": "1.0.2-dev", 11 | "Status": "running", 12 | "Running": true, 13 | "Paused": false, 14 | "Restarting": false, 15 | "OOMKilled": false, 16 | "Dead": false, 17 | "Pid": 532447, 18 | "ConmonPid": 532442, 19 | "ExitCode": 0, 20 | "Error": "", 21 | "StartedAt": "2020-08-03T16:49:26.836249581+02:00", 22 | "FinishedAt": "0001-01-01T00:00:00Z", 23 | "Healthcheck": { 24 | "Status": "", 25 | "FailingStreak": 0, 26 | "Log": null 27 | } 28 | }, 29 | "Image": "a1f8c969978652a6d1b2dfb265ae0c6c346da69000160cd3ecd5f619e26fa9f3", 30 | "ImageName": "registry.access.redhat.com/ubi8:latest", 31 | "Rootfs": "", 32 | "Pod": "", 33 | "ResolvConfPath": "/var/run/containers/storage/overlay-containers/2d497441ae0102ac214c6a0c241ceae67858ff40bc35e46b7d95c7cbf1c9cf27/userdata/resolv.conf", 34 | "HostnamePath": "/var/run/containers/storage/overlay-containers/2d497441ae0102ac214c6a0c241ceae67858ff40bc35e46b7d95c7cbf1c9cf27/userdata/hostname", 35 | "HostsPath": "/var/run/containers/storage/overlay-containers/2d497441ae0102ac214c6a0c241ceae67858ff40bc35e46b7d95c7cbf1c9cf27/userdata/hosts", 36 | "StaticDir": "/var/lib/containers/storage/overlay-containers/2d497441ae0102ac214c6a0c241ceae67858ff40bc35e46b7d95c7cbf1c9cf27/userdata", 37 | "OCIConfigPath": "/var/lib/containers/storage/overlay-containers/2d497441ae0102ac214c6a0c241ceae67858ff40bc35e46b7d95c7cbf1c9cf27/userdata/config.json", 38 | "OCIRuntime": "crun", 39 | "LogPath": "/var/lib/containers/storage/overlay-containers/2d497441ae0102ac214c6a0c241ceae67858ff40bc35e46b7d95c7cbf1c9cf27/userdata/ctr.log", 40 | "LogTag": "", 41 | "ConmonPidFile": "/var/run/containers/storage/overlay-containers/2d497441ae0102ac214c6a0c241ceae67858ff40bc35e46b7d95c7cbf1c9cf27/userdata/conmon.pid", 42 | "Name": "hardcore_kapitsa", 43 | "RestartCount": 0, 44 | "Driver": "overlay", 45 | "MountLabel": "system_u:object_r:container_file_t:s0:c267,c502", 46 | "ProcessLabel": "system_u:system_r:container_t:s0:c267,c502", 47 | "AppArmorProfile": "", 48 | "EffectiveCaps": [ 49 | "CAP_AUDIT_WRITE", 50 | "CAP_CHOWN", 51 | "CAP_DAC_OVERRIDE", 52 | "CAP_FOWNER", 53 | "CAP_FSETID", 54 | "CAP_KILL", 55 | "CAP_MKNOD", 56 | "CAP_NET_BIND_SERVICE", 57 | "CAP_NET_RAW", 58 | "CAP_SETFCAP", 59 | "CAP_SETGID", 60 | "CAP_SETPCAP", 61 | "CAP_SETUID", 62 | "CAP_SYS_CHROOT" 63 | ], 64 | "BoundingCaps": [ 65 | "CAP_AUDIT_WRITE", 66 | "CAP_CHOWN", 67 | "CAP_DAC_OVERRIDE", 68 | "CAP_FOWNER", 69 | "CAP_FSETID", 70 | "CAP_KILL", 71 | "CAP_MKNOD", 72 | "CAP_NET_BIND_SERVICE", 73 | "CAP_NET_RAW", 74 | "CAP_SETFCAP", 75 | "CAP_SETGID", 76 | "CAP_SETPCAP", 77 | "CAP_SETUID", 78 | "CAP_SYS_CHROOT" 79 | ], 80 | "ExecIDs": [], 81 | "GraphDriver": { 82 | "Name": "overlay", 83 | "Data": { 84 | "LowerDir": "/var/lib/containers/storage/overlay/1da86dd5dbd9e4d52991b5846320796527b223a8bc5c770caa644281a94fd828/diff:/var/lib/containers/storage/overlay/226bfaae015f1d5712cfced3b5b628206618eaacf72f4a44d0e4084071996319/diff", 85 | "MergedDir": "/var/lib/containers/storage/overlay/638f0a8f089ed30d41c9d248343de779d72428d982f567ef46d7354d0d80a869/merged", 86 | "UpperDir": "/var/lib/containers/storage/overlay/638f0a8f089ed30d41c9d248343de779d72428d982f567ef46d7354d0d80a869/diff", 87 | "WorkDir": "/var/lib/containers/storage/overlay/638f0a8f089ed30d41c9d248343de779d72428d982f567ef46d7354d0d80a869/work" 88 | } 89 | }, 90 | "Mounts": [], 91 | "Dependencies": [], 92 | "NetworkSettings": { 93 | "EndpointID": "", 94 | "Gateway": "10.88.0.1", 95 | "IPAddress": "10.88.0.244", 96 | "IPPrefixLen": 16, 97 | "IPv6Gateway": "", 98 | "GlobalIPv6Address": "", 99 | "GlobalIPv6PrefixLen": 0, 100 | "MacAddress": "3e:70:fa:dd:cd:8e", 101 | "Bridge": "", 102 | "SandboxID": "", 103 | "HairpinMode": false, 104 | "LinkLocalIPv6Address": "", 105 | "LinkLocalIPv6PrefixLen": 0, 106 | "Ports": {}, 107 | "SandboxKey": "/var/run/netns/cni-407ae218-ba05-7f9a-ed9b-70a4d10f8ac8" 108 | }, 109 | "ExitCommand": [ 110 | "/usr/bin/podman", 111 | "--root", 112 | "/var/lib/containers/storage", 113 | "--runroot", 114 | "/var/run/containers/storage", 115 | "--log-level", 116 | "error", 117 | "--cgroup-manager", 118 | "systemd", 119 | "--tmpdir", 120 | "/var/run/libpod", 121 | "--runtime", 122 | "crun", 123 | "--storage-driver", 124 | "overlay", 125 | "--storage-opt", 126 | "overlay.mountopt=nodev,metacopy=on", 127 | "--events-backend", 128 | "file", 129 | "container", 130 | "cleanup", 131 | "2d497441ae0102ac214c6a0c241ceae67858ff40bc35e46b7d95c7cbf1c9cf27" 132 | ], 133 | "Namespace": "", 134 | "IsInfra": false, 135 | "Config": { 136 | "Hostname": "2d497441ae01", 137 | "Domainname": "", 138 | "User": "", 139 | "AttachStdin": false, 140 | "AttachStdout": false, 141 | "AttachStderr": false, 142 | "Tty": true, 143 | "OpenStdin": true, 144 | "StdinOnce": false, 145 | "Env": [ 146 | "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", 147 | "TERM=xterm", 148 | "container=podman", 149 | "HOSTNAME=2d497441ae01", 150 | "HOME=/root" 151 | ], 152 | "Cmd": [ 153 | "/bin/bash" 154 | ], 155 | "Image": "registry.access.redhat.com/ubi8:latest", 156 | "Volumes": null, 157 | "WorkingDir": "/", 158 | "Entrypoint": "", 159 | "OnBuild": null, 160 | "Labels": { 161 | "architecture": "x86_64", 162 | "build-date": "2020-07-22T12:11:33.547097", 163 | "com.redhat.build-host": "cpt-1007.osbs.prod.upshift.rdu2.redhat.com", 164 | "com.redhat.component": "ubi8-container", 165 | "com.redhat.license_terms": "https://www.redhat.com/en/about/red-hat-end-user-license-agreements#UBI", 166 | "description": "The Universal Base Image is designed and engineered to be the base layer for all of your containerized applications, middleware and utilities. This base image is freely redistributable, but Red Hat only supports Red Hat technologies through subscriptions for Red Hat products. This image is maintained by Red Hat and updated regularly.", 167 | "distribution-scope": "public", 168 | "io.k8s.description": "The Universal Base Image is designed and engineered to be the base layer for all of your containerized applications, middleware and utilities. This base image is freely redistributable, but Red Hat only supports Red Hat technologies through subscriptions for Red Hat products. This image is maintained by Red Hat and updated regularly.", 169 | "io.k8s.display-name": "Red Hat Universal Base Image 8", 170 | "io.openshift.expose-services": "", 171 | "io.openshift.tags": "base rhel8", 172 | "maintainer": "Red Hat, Inc.", 173 | "name": "ubi8", 174 | "release": "343", 175 | "summary": "Provides the latest release of Red Hat Universal Base Image 8.", 176 | "url": "https://access.redhat.com/containers/#/registry.access.redhat.com/ubi8/images/8.2-343", 177 | "vcs-ref": "0fede9a6ae85a36962206913c66bfe9965c49940", 178 | "vcs-type": "git", 179 | "vendor": "Red Hat, Inc.", 180 | "version": "8.2" 181 | }, 182 | "Annotations": { 183 | "io.container.manager": "libpod", 184 | "io.kubernetes.cri-o.Created": "2020-08-03T16:49:26.218811778+02:00", 185 | "io.kubernetes.cri-o.TTY": "true", 186 | "io.podman.annotations.autoremove": "FALSE", 187 | "io.podman.annotations.init": "FALSE", 188 | "io.podman.annotations.privileged": "FALSE", 189 | "io.podman.annotations.publish-all": "FALSE", 190 | "org.opencontainers.image.stopSignal": "15" 191 | }, 192 | "StopSignal": 15, 193 | "CreateCommand": [ 194 | "/bin/podman", 195 | "run", 196 | "-it", 197 | "ubi8" 198 | ] 199 | }, 200 | "HostConfig": { 201 | "Binds": [], 202 | "CgroupMode": "private", 203 | "ContainerIDFile": "", 204 | "LogConfig": { 205 | "Type": "k8s-file", 206 | "Config": null 207 | }, 208 | "NetworkMode": "bridge", 209 | "PortBindings": {}, 210 | "RestartPolicy": { 211 | "Name": "", 212 | "MaximumRetryCount": 0 213 | }, 214 | "AutoRemove": false, 215 | "VolumeDriver": "", 216 | "VolumesFrom": null, 217 | "CapAdd": [], 218 | "CapDrop": [], 219 | "Dns": [], 220 | "DnsOptions": [], 221 | "DnsSearch": [], 222 | "ExtraHosts": [], 223 | "GroupAdd": [], 224 | "IpcMode": "private", 225 | "Cgroup": "", 226 | "Cgroups": "default", 227 | "Links": null, 228 | "OomScoreAdj": 0, 229 | "PidMode": "private", 230 | "Privileged": false, 231 | "PublishAllPorts": false, 232 | "ReadonlyRootfs": false, 233 | "SecurityOpt": [], 234 | "Tmpfs": {}, 235 | "UTSMode": "private", 236 | "UsernsMode": "", 237 | "ShmSize": 65536000, 238 | "Runtime": "oci", 239 | "ConsoleSize": [ 240 | 0, 241 | 0 242 | ], 243 | "Isolation": "", 244 | "CpuShares": 0, 245 | "Memory": 0, 246 | "NanoCpus": 0, 247 | "CgroupParent": "", 248 | "BlkioWeight": 0, 249 | "BlkioWeightDevice": null, 250 | "BlkioDeviceReadBps": null, 251 | "BlkioDeviceWriteBps": null, 252 | "BlkioDeviceReadIOps": null, 253 | "BlkioDeviceWriteIOps": null, 254 | "CpuPeriod": 0, 255 | "CpuQuota": 0, 256 | "CpuRealtimePeriod": 0, 257 | "CpuRealtimeRuntime": 0, 258 | "CpusetCpus": "", 259 | "CpusetMems": "", 260 | "Devices": [], 261 | "DiskQuota": 0, 262 | "KernelMemory": 0, 263 | "MemoryReservation": 0, 264 | "MemorySwap": 0, 265 | "MemorySwappiness": 0, 266 | "OomKillDisable": false, 267 | "PidsLimit": 2048, 268 | "Ulimits": [ 269 | { 270 | "Name": "RLIMIT_NOFILE", 271 | "Soft": 1048576, 272 | "Hard": 1048576 273 | }, 274 | { 275 | "Name": "RLIMIT_NPROC", 276 | "Soft": 4194304, 277 | "Hard": 4194304 278 | } 279 | ], 280 | "CpuCount": 0, 281 | "CpuPercent": 0, 282 | "IOMaximumIOps": 0, 283 | "IOMaximumBandwidth": 0 284 | } 285 | } 286 | ] 287 | -------------------------------------------------------------------------------- /tests/test_default.podman.cil: -------------------------------------------------------------------------------- 1 | (block my_container 2 | (blockinherit container) 3 | (allow process process ( capability ( audit_write chown dac_override fowner fsetid kill mknod net_bind_service net_raw setfcap setgid setpcap setuid sys_chroot ))) 4 | 5 | ) -------------------------------------------------------------------------------- /tests/test_default.podman.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "Id": "1cc89485106bea4d54b03ccc4d46934134408acf31be045d1f9adf5007950f37", 4 | "Created": "2020-08-03T16:41:57.17883811+02:00", 5 | "Path": "/bin/bash", 6 | "Args": [ 7 | "/bin/bash" 8 | ], 9 | "State": { 10 | "OciVersion": "1.0.2-dev", 11 | "Status": "running", 12 | "Running": true, 13 | "Paused": false, 14 | "Restarting": false, 15 | "OOMKilled": false, 16 | "Dead": false, 17 | "Pid": 529799, 18 | "ConmonPid": 529794, 19 | "ExitCode": 0, 20 | "Error": "", 21 | "StartedAt": "2020-08-03T16:41:57.576550099+02:00", 22 | "FinishedAt": "0001-01-01T00:00:00Z", 23 | "Healthcheck": { 24 | "Status": "", 25 | "FailingStreak": 0, 26 | "Log": null 27 | } 28 | }, 29 | "Image": "00ff39a8bf19f810a7e641f7eb3ddc47635913a19c4996debd91fafb6b379069", 30 | "ImageName": "registry.fedoraproject.org/fedora:latest", 31 | "Rootfs": "", 32 | "Pod": "", 33 | "ResolvConfPath": "/var/run/containers/storage/overlay-containers/1cc89485106bea4d54b03ccc4d46934134408acf31be045d1f9adf5007950f37/userdata/resolv.conf", 34 | "HostnamePath": "/var/run/containers/storage/overlay-containers/1cc89485106bea4d54b03ccc4d46934134408acf31be045d1f9adf5007950f37/userdata/hostname", 35 | "HostsPath": "/var/run/containers/storage/overlay-containers/1cc89485106bea4d54b03ccc4d46934134408acf31be045d1f9adf5007950f37/userdata/hosts", 36 | "StaticDir": "/var/lib/containers/storage/overlay-containers/1cc89485106bea4d54b03ccc4d46934134408acf31be045d1f9adf5007950f37/userdata", 37 | "OCIConfigPath": "/var/lib/containers/storage/overlay-containers/1cc89485106bea4d54b03ccc4d46934134408acf31be045d1f9adf5007950f37/userdata/config.json", 38 | "OCIRuntime": "crun", 39 | "LogPath": "/var/lib/containers/storage/overlay-containers/1cc89485106bea4d54b03ccc4d46934134408acf31be045d1f9adf5007950f37/userdata/ctr.log", 40 | "LogTag": "", 41 | "ConmonPidFile": "/var/run/containers/storage/overlay-containers/1cc89485106bea4d54b03ccc4d46934134408acf31be045d1f9adf5007950f37/userdata/conmon.pid", 42 | "Name": "nostalgic_poitras", 43 | "RestartCount": 0, 44 | "Driver": "overlay", 45 | "MountLabel": "system_u:object_r:container_file_t:s0:c795,c984", 46 | "ProcessLabel": "system_u:system_r:container_t:s0:c795,c984", 47 | "AppArmorProfile": "", 48 | "EffectiveCaps": [ 49 | "CAP_AUDIT_WRITE", 50 | "CAP_CHOWN", 51 | "CAP_DAC_OVERRIDE", 52 | "CAP_FOWNER", 53 | "CAP_FSETID", 54 | "CAP_KILL", 55 | "CAP_MKNOD", 56 | "CAP_NET_BIND_SERVICE", 57 | "CAP_NET_RAW", 58 | "CAP_SETFCAP", 59 | "CAP_SETGID", 60 | "CAP_SETPCAP", 61 | "CAP_SETUID", 62 | "CAP_SYS_CHROOT" 63 | ], 64 | "BoundingCaps": [ 65 | "CAP_AUDIT_WRITE", 66 | "CAP_CHOWN", 67 | "CAP_DAC_OVERRIDE", 68 | "CAP_FOWNER", 69 | "CAP_FSETID", 70 | "CAP_KILL", 71 | "CAP_MKNOD", 72 | "CAP_NET_BIND_SERVICE", 73 | "CAP_NET_RAW", 74 | "CAP_SETFCAP", 75 | "CAP_SETGID", 76 | "CAP_SETPCAP", 77 | "CAP_SETUID", 78 | "CAP_SYS_CHROOT" 79 | ], 80 | "ExecIDs": [], 81 | "GraphDriver": { 82 | "Name": "overlay", 83 | "Data": { 84 | "LowerDir": "/var/lib/containers/storage/overlay/0ccfac04663bbe8813b5f24502ee0b7371ce5bf3c5adeb12e4258d191c2cf7bc/diff", 85 | "MergedDir": "/var/lib/containers/storage/overlay/d04481881d1ea1a63f584cea73386b25b67a9c8753e3a17a6327bc3af966aeb9/merged", 86 | "UpperDir": "/var/lib/containers/storage/overlay/d04481881d1ea1a63f584cea73386b25b67a9c8753e3a17a6327bc3af966aeb9/diff", 87 | "WorkDir": "/var/lib/containers/storage/overlay/d04481881d1ea1a63f584cea73386b25b67a9c8753e3a17a6327bc3af966aeb9/work" 88 | } 89 | }, 90 | "Mounts": [], 91 | "Dependencies": [], 92 | "NetworkSettings": { 93 | "EndpointID": "", 94 | "Gateway": "10.88.0.1", 95 | "IPAddress": "10.88.0.240", 96 | "IPPrefixLen": 16, 97 | "IPv6Gateway": "", 98 | "GlobalIPv6Address": "", 99 | "GlobalIPv6PrefixLen": 0, 100 | "MacAddress": "62:c5:f9:d2:b6:a7", 101 | "Bridge": "", 102 | "SandboxID": "", 103 | "HairpinMode": false, 104 | "LinkLocalIPv6Address": "", 105 | "LinkLocalIPv6PrefixLen": 0, 106 | "Ports": {}, 107 | "SandboxKey": "/var/run/netns/cni-4bb27c63-28c8-c568-c404-2271d5359821" 108 | }, 109 | "ExitCommand": [ 110 | "/usr/bin/podman", 111 | "--root", 112 | "/var/lib/containers/storage", 113 | "--runroot", 114 | "/var/run/containers/storage", 115 | "--log-level", 116 | "error", 117 | "--cgroup-manager", 118 | "systemd", 119 | "--tmpdir", 120 | "/var/run/libpod", 121 | "--runtime", 122 | "crun", 123 | "--storage-driver", 124 | "overlay", 125 | "--storage-opt", 126 | "overlay.mountopt=nodev,metacopy=on", 127 | "--events-backend", 128 | "file", 129 | "container", 130 | "cleanup", 131 | "1cc89485106bea4d54b03ccc4d46934134408acf31be045d1f9adf5007950f37" 132 | ], 133 | "Namespace": "", 134 | "IsInfra": false, 135 | "Config": { 136 | "Hostname": "1cc89485106b", 137 | "Domainname": "", 138 | "User": "", 139 | "AttachStdin": false, 140 | "AttachStdout": false, 141 | "AttachStderr": false, 142 | "Tty": true, 143 | "OpenStdin": true, 144 | "StdinOnce": false, 145 | "Env": [ 146 | "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", 147 | "TERM=xterm", 148 | "container=podman", 149 | "DISTTAG=f32container", 150 | "FGC=f32", 151 | "HOSTNAME=1cc89485106b", 152 | "HOME=/root" 153 | ], 154 | "Cmd": [ 155 | "/bin/bash" 156 | ], 157 | "Image": "registry.fedoraproject.org/fedora:latest", 158 | "Volumes": null, 159 | "WorkingDir": "/", 160 | "Entrypoint": "", 161 | "OnBuild": null, 162 | "Labels": { 163 | "license": "MIT", 164 | "name": "fedora", 165 | "vendor": "Fedora Project", 166 | "version": "32" 167 | }, 168 | "Annotations": { 169 | "io.container.manager": "libpod", 170 | "io.kubernetes.cri-o.Created": "2020-08-03T16:41:57.17883811+02:00", 171 | "io.kubernetes.cri-o.TTY": "true", 172 | "io.podman.annotations.autoremove": "FALSE", 173 | "io.podman.annotations.init": "FALSE", 174 | "io.podman.annotations.privileged": "FALSE", 175 | "io.podman.annotations.publish-all": "FALSE", 176 | "org.opencontainers.image.stopSignal": "15" 177 | }, 178 | "StopSignal": 15, 179 | "CreateCommand": [ 180 | "/bin/podman", 181 | "run", 182 | "-it", 183 | "fedora" 184 | ] 185 | }, 186 | "HostConfig": { 187 | "Binds": [], 188 | "CgroupMode": "private", 189 | "ContainerIDFile": "", 190 | "LogConfig": { 191 | "Type": "k8s-file", 192 | "Config": null 193 | }, 194 | "NetworkMode": "bridge", 195 | "PortBindings": {}, 196 | "RestartPolicy": { 197 | "Name": "", 198 | "MaximumRetryCount": 0 199 | }, 200 | "AutoRemove": false, 201 | "VolumeDriver": "", 202 | "VolumesFrom": null, 203 | "CapAdd": [], 204 | "CapDrop": [], 205 | "Dns": [], 206 | "DnsOptions": [], 207 | "DnsSearch": [], 208 | "ExtraHosts": [], 209 | "GroupAdd": [], 210 | "IpcMode": "private", 211 | "Cgroup": "", 212 | "Cgroups": "default", 213 | "Links": null, 214 | "OomScoreAdj": 0, 215 | "PidMode": "private", 216 | "Privileged": false, 217 | "PublishAllPorts": false, 218 | "ReadonlyRootfs": false, 219 | "SecurityOpt": [], 220 | "Tmpfs": {}, 221 | "UTSMode": "private", 222 | "UsernsMode": "", 223 | "ShmSize": 65536000, 224 | "Runtime": "oci", 225 | "ConsoleSize": [ 226 | 0, 227 | 0 228 | ], 229 | "Isolation": "", 230 | "CpuShares": 0, 231 | "Memory": 0, 232 | "NanoCpus": 0, 233 | "CgroupParent": "", 234 | "BlkioWeight": 0, 235 | "BlkioWeightDevice": null, 236 | "BlkioDeviceReadBps": null, 237 | "BlkioDeviceWriteBps": null, 238 | "BlkioDeviceReadIOps": null, 239 | "BlkioDeviceWriteIOps": null, 240 | "CpuPeriod": 0, 241 | "CpuQuota": 0, 242 | "CpuRealtimePeriod": 0, 243 | "CpuRealtimeRuntime": 0, 244 | "CpusetCpus": "", 245 | "CpusetMems": "", 246 | "Devices": [], 247 | "DiskQuota": 0, 248 | "KernelMemory": 0, 249 | "MemoryReservation": 0, 250 | "MemorySwap": 0, 251 | "MemorySwappiness": 0, 252 | "OomKillDisable": false, 253 | "PidsLimit": 2048, 254 | "Ulimits": [ 255 | { 256 | "Name": "RLIMIT_NOFILE", 257 | "Soft": 1048576, 258 | "Hard": 1048576 259 | }, 260 | { 261 | "Name": "RLIMIT_NPROC", 262 | "Soft": 4194304, 263 | "Hard": 4194304 264 | } 265 | ], 266 | "CpuCount": 0, 267 | "CpuPercent": 0, 268 | "IOMaximumIOps": 0, 269 | "IOMaximumBandwidth": 0 270 | } 271 | } 272 | ] 273 | -------------------------------------------------------------------------------- /tests/test_device_access.podman.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "Id": "68485406c4bbfd2b379beac7d80834a4ca94d7e74ada5019c7499afed62e1744", 4 | "Created": "2022-08-11T20:54:51.026287311+02:00", 5 | "Path": "/bin/bash", 6 | "Args": [ 7 | "/bin/bash" 8 | ], 9 | "State": { 10 | "OciVersion": "1.0.2-dev", 11 | "Status": "exited", 12 | "Running": false, 13 | "Paused": false, 14 | "Restarting": false, 15 | "OOMKilled": false, 16 | "Dead": false, 17 | "Pid": 0, 18 | "ExitCode": 0, 19 | "Error": "", 20 | "StartedAt": "2022-08-11T20:54:51.116938836+02:00", 21 | "FinishedAt": "2022-08-11T20:54:51.1327839+02:00", 22 | "Health": { 23 | "Status": "", 24 | "FailingStreak": 0, 25 | "Log": null 26 | }, 27 | "CheckpointedAt": "0001-01-01T00:00:00Z", 28 | "RestoredAt": "0001-01-01T00:00:00Z" 29 | }, 30 | "Image": "2ecb6df959942dd2fdeb65606ca2e42a54f8c06af10eeb594fdfc3e2656c53d1", 31 | "ImageName": "registry.fedoraproject.org/fedora:latest", 32 | "Rootfs": "", 33 | "Pod": "", 34 | "ResolvConfPath": "/run/user/1000/overlay-containers/68485406c4bbfd2b379beac7d80834a4ca94d7e74ada5019c7499afed62e1744/userdata/resolv.conf", 35 | "HostnamePath": "/run/user/1000/overlay-containers/68485406c4bbfd2b379beac7d80834a4ca94d7e74ada5019c7499afed62e1744/userdata/hostname", 36 | "HostsPath": "/run/user/1000/overlay-containers/68485406c4bbfd2b379beac7d80834a4ca94d7e74ada5019c7499afed62e1744/userdata/hosts", 37 | "StaticDir": "/home/martin/.local/share/containers/storage/overlay-containers/68485406c4bbfd2b379beac7d80834a4ca94d7e74ada5019c7499afed62e1744/userdata", 38 | "OCIConfigPath": "/home/martin/.local/share/containers/storage/overlay-containers/68485406c4bbfd2b379beac7d80834a4ca94d7e74ada5019c7499afed62e1744/userdata/config.json", 39 | "OCIRuntime": "crun", 40 | "ConmonPidFile": "/run/user/1000/overlay-containers/68485406c4bbfd2b379beac7d80834a4ca94d7e74ada5019c7499afed62e1744/userdata/conmon.pid", 41 | "PidFile": "/run/user/1000/overlay-containers/68485406c4bbfd2b379beac7d80834a4ca94d7e74ada5019c7499afed62e1744/userdata/pidfile", 42 | "Name": "charming_khorana", 43 | "RestartCount": 0, 44 | "Driver": "overlay", 45 | "MountLabel": "system_u:object_r:container_file_t:s0:c8,c574", 46 | "ProcessLabel": "system_u:system_r:container_t:s0:c8,c574", 47 | "AppArmorProfile": "", 48 | "EffectiveCaps": [ 49 | "CAP_CHOWN", 50 | "CAP_DAC_OVERRIDE", 51 | "CAP_FOWNER", 52 | "CAP_FSETID", 53 | "CAP_KILL", 54 | "CAP_NET_BIND_SERVICE", 55 | "CAP_SETFCAP", 56 | "CAP_SETGID", 57 | "CAP_SETPCAP", 58 | "CAP_SETUID", 59 | "CAP_SYS_CHROOT" 60 | ], 61 | "BoundingCaps": [ 62 | "CAP_CHOWN", 63 | "CAP_DAC_OVERRIDE", 64 | "CAP_FOWNER", 65 | "CAP_FSETID", 66 | "CAP_KILL", 67 | "CAP_NET_BIND_SERVICE", 68 | "CAP_SETFCAP", 69 | "CAP_SETGID", 70 | "CAP_SETPCAP", 71 | "CAP_SETUID", 72 | "CAP_SYS_CHROOT" 73 | ], 74 | "ExecIDs": [], 75 | "GraphDriver": { 76 | "Name": "overlay", 77 | "Data": { 78 | "LowerDir": "/home/martin/.local/share/containers/storage/overlay/1da06ca5080c2ce2499e2f9802259209c7dd85c92d64852c3165425cdc18c443/diff", 79 | "UpperDir": "/home/martin/.local/share/containers/storage/overlay/98294044df8fadc428b8a41befc0c83d574601b56076c62ce7fa93df6c48f8dc/diff", 80 | "WorkDir": "/home/martin/.local/share/containers/storage/overlay/98294044df8fadc428b8a41befc0c83d574601b56076c62ce7fa93df6c48f8dc/work" 81 | } 82 | }, 83 | "Mounts": [], 84 | "Dependencies": [], 85 | "NetworkSettings": { 86 | "EndpointID": "", 87 | "Gateway": "", 88 | "IPAddress": "", 89 | "IPPrefixLen": 0, 90 | "IPv6Gateway": "", 91 | "GlobalIPv6Address": "", 92 | "GlobalIPv6PrefixLen": 0, 93 | "MacAddress": "", 94 | "Bridge": "", 95 | "SandboxID": "", 96 | "HairpinMode": false, 97 | "LinkLocalIPv6Address": "", 98 | "LinkLocalIPv6PrefixLen": 0, 99 | "Ports": {}, 100 | "SandboxKey": "" 101 | }, 102 | "Namespace": "", 103 | "IsInfra": false, 104 | "Config": { 105 | "Hostname": "68485406c4bb", 106 | "Domainname": "", 107 | "User": "", 108 | "AttachStdin": false, 109 | "AttachStdout": false, 110 | "AttachStderr": false, 111 | "Tty": false, 112 | "OpenStdin": false, 113 | "StdinOnce": false, 114 | "Env": [ 115 | "FGC=f36", 116 | "DISTTAG=f36container", 117 | "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", 118 | "TERM=xterm", 119 | "container=oci", 120 | "HOME=/root", 121 | "HOSTNAME=68485406c4bb" 122 | ], 123 | "Cmd": [ 124 | "/bin/bash" 125 | ], 126 | "Image": "registry.fedoraproject.org/fedora:latest", 127 | "Volumes": null, 128 | "WorkingDir": "/", 129 | "Entrypoint": "", 130 | "OnBuild": null, 131 | "Labels": { 132 | "license": "MIT", 133 | "name": "fedora", 134 | "vendor": "Fedora Project", 135 | "version": "36" 136 | }, 137 | "Annotations": { 138 | "io.container.manager": "libpod", 139 | "io.kubernetes.cri-o.Created": "2022-08-11T20:54:51.026287311+02:00", 140 | "io.kubernetes.cri-o.TTY": "false", 141 | "io.podman.annotations.autoremove": "FALSE", 142 | "io.podman.annotations.init": "FALSE", 143 | "io.podman.annotations.privileged": "FALSE", 144 | "io.podman.annotations.publish-all": "FALSE", 145 | "org.opencontainers.image.stopSignal": "15" 146 | }, 147 | "StopSignal": 15, 148 | "CreateCommand": [ 149 | "podman", 150 | "run", 151 | "--device", 152 | "/dev/fb0", 153 | "fedora" 154 | ], 155 | "Umask": "0022", 156 | "Timeout": 0, 157 | "StopTimeout": 10, 158 | "Passwd": true 159 | }, 160 | "HostConfig": { 161 | "Binds": [], 162 | "CgroupManager": "systemd", 163 | "CgroupMode": "private", 164 | "ContainerIDFile": "", 165 | "LogConfig": { 166 | "Type": "journald", 167 | "Config": null, 168 | "Path": "", 169 | "Tag": "", 170 | "Size": "0B" 171 | }, 172 | "NetworkMode": "slirp4netns", 173 | "PortBindings": {}, 174 | "RestartPolicy": { 175 | "Name": "", 176 | "MaximumRetryCount": 0 177 | }, 178 | "AutoRemove": false, 179 | "VolumeDriver": "", 180 | "VolumesFrom": null, 181 | "CapAdd": [], 182 | "CapDrop": [ 183 | "CAP_AUDIT_WRITE", 184 | "CAP_MKNOD", 185 | "CAP_NET_RAW" 186 | ], 187 | "Dns": [], 188 | "DnsOptions": [], 189 | "DnsSearch": [], 190 | "ExtraHosts": [], 191 | "GroupAdd": [], 192 | "IpcMode": "shareable", 193 | "Cgroup": "", 194 | "Cgroups": "default", 195 | "Links": null, 196 | "OomScoreAdj": 0, 197 | "PidMode": "private", 198 | "Privileged": false, 199 | "PublishAllPorts": false, 200 | "ReadonlyRootfs": false, 201 | "SecurityOpt": [], 202 | "Tmpfs": {}, 203 | "UTSMode": "private", 204 | "UsernsMode": "", 205 | "ShmSize": 65536000, 206 | "Runtime": "oci", 207 | "ConsoleSize": [ 208 | 0, 209 | 0 210 | ], 211 | "Isolation": "", 212 | "CpuShares": 0, 213 | "Memory": 0, 214 | "NanoCpus": 0, 215 | "CgroupParent": "user.slice", 216 | "BlkioWeight": 0, 217 | "BlkioWeightDevice": null, 218 | "BlkioDeviceReadBps": null, 219 | "BlkioDeviceWriteBps": null, 220 | "BlkioDeviceReadIOps": null, 221 | "BlkioDeviceWriteIOps": null, 222 | "CpuPeriod": 0, 223 | "CpuQuota": 0, 224 | "CpuRealtimePeriod": 0, 225 | "CpuRealtimeRuntime": 0, 226 | "CpusetCpus": "", 227 | "CpusetMems": "", 228 | "Devices": [], 229 | "DiskQuota": 0, 230 | "KernelMemory": 0, 231 | "MemoryReservation": 0, 232 | "MemorySwap": 0, 233 | "MemorySwappiness": 0, 234 | "OomKillDisable": false, 235 | "PidsLimit": 2048, 236 | "Ulimits": [], 237 | "CpuCount": 0, 238 | "CpuPercent": 0, 239 | "IOMaximumIOps": 0, 240 | "IOMaximumBandwidth": 0, 241 | "CgroupConf": null 242 | } 243 | } 244 | ] 245 | -------------------------------------------------------------------------------- /tests/test_devices.podman.cil: -------------------------------------------------------------------------------- 1 | (block my_container 2 | (blockinherit container) 3 | (allow process process ( capability ( audit_write chown dac_override fowner fsetid kill mknod net_bind_service net_raw setfcap setgid setpcap setuid sys_chroot ))) 4 | 5 | (allow process framebuf_device_t ( blk_file ( getattr read write append ioctl lock open ))) 6 | (allow process framebuf_device_t ( chr_file ( getattr read write append ioctl lock open ))) 7 | (allow process var_spool_t ( blk_file ( getattr read write append ioctl lock open ))) 8 | (allow process var_spool_t ( chr_file ( getattr read write append ioctl lock open ))) 9 | ) -------------------------------------------------------------------------------- /tests/test_devices.podman.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "Id": "6335b78454e65cecc2c3c78c402e16d1a0691cf416468822c7f996594e991f2b", 4 | "Created": "2020-11-24T20:06:25.852770272+01:00", 5 | "Path": "/bin/bash", 6 | "Args": [ 7 | "/bin/bash" 8 | ], 9 | "State": { 10 | "OciVersion": "1.0.2-dev", 11 | "Status": "running", 12 | "Running": true, 13 | "Paused": false, 14 | "Restarting": false, 15 | "OOMKilled": false, 16 | "Dead": false, 17 | "Pid": 240290, 18 | "ConmonPid": 240287, 19 | "ExitCode": 0, 20 | "Error": "", 21 | "StartedAt": "2020-11-24T20:06:25.990467073+01:00", 22 | "FinishedAt": "0001-01-01T00:00:00Z", 23 | "Healthcheck": { 24 | "Status": "", 25 | "FailingStreak": 0, 26 | "Log": null 27 | } 28 | }, 29 | "Image": "79fd58dc76113dac76a120f22cadecc3b2d1794b414f90ea368cf66096700053", 30 | "ImageName": "registry.fedoraproject.org/fedora:latest", 31 | "Rootfs": "", 32 | "Pod": "", 33 | "ResolvConfPath": "/var/run/containers/storage/overlay-containers/6335b78454e65cecc2c3c78c402e16d1a0691cf416468822c7f996594e991f2b/userdata/resolv.conf", 34 | "HostnamePath": "/var/run/containers/storage/overlay-containers/6335b78454e65cecc2c3c78c402e16d1a0691cf416468822c7f996594e991f2b/userdata/hostname", 35 | "HostsPath": "/var/run/containers/storage/overlay-containers/6335b78454e65cecc2c3c78c402e16d1a0691cf416468822c7f996594e991f2b/userdata/hosts", 36 | "StaticDir": "/var/lib/containers/storage/overlay-containers/6335b78454e65cecc2c3c78c402e16d1a0691cf416468822c7f996594e991f2b/userdata", 37 | "OCIConfigPath": "/var/lib/containers/storage/overlay-containers/6335b78454e65cecc2c3c78c402e16d1a0691cf416468822c7f996594e991f2b/userdata/config.json", 38 | "OCIRuntime": "crun", 39 | "LogPath": "/var/lib/containers/storage/overlay-containers/6335b78454e65cecc2c3c78c402e16d1a0691cf416468822c7f996594e991f2b/userdata/ctr.log", 40 | "LogTag": "", 41 | "ConmonPidFile": "/var/run/containers/storage/overlay-containers/6335b78454e65cecc2c3c78c402e16d1a0691cf416468822c7f996594e991f2b/userdata/conmon.pid", 42 | "Name": "upbeat_ellis", 43 | "RestartCount": 0, 44 | "Driver": "overlay", 45 | "MountLabel": "system_u:object_r:container_file_t:s0:c543,c755", 46 | "ProcessLabel": "system_u:system_r:container_t:s0:c543,c755", 47 | "AppArmorProfile": "", 48 | "EffectiveCaps": [ 49 | "CAP_AUDIT_WRITE", 50 | "CAP_CHOWN", 51 | "CAP_DAC_OVERRIDE", 52 | "CAP_FOWNER", 53 | "CAP_FSETID", 54 | "CAP_KILL", 55 | "CAP_MKNOD", 56 | "CAP_NET_BIND_SERVICE", 57 | "CAP_NET_RAW", 58 | "CAP_SETFCAP", 59 | "CAP_SETGID", 60 | "CAP_SETPCAP", 61 | "CAP_SETUID", 62 | "CAP_SYS_CHROOT" 63 | ], 64 | "BoundingCaps": [ 65 | "CAP_AUDIT_WRITE", 66 | "CAP_CHOWN", 67 | "CAP_DAC_OVERRIDE", 68 | "CAP_FOWNER", 69 | "CAP_FSETID", 70 | "CAP_KILL", 71 | "CAP_MKNOD", 72 | "CAP_NET_BIND_SERVICE", 73 | "CAP_NET_RAW", 74 | "CAP_SETFCAP", 75 | "CAP_SETGID", 76 | "CAP_SETPCAP", 77 | "CAP_SETUID", 78 | "CAP_SYS_CHROOT" 79 | ], 80 | "ExecIDs": [], 81 | "GraphDriver": { 82 | "Name": "overlay", 83 | "Data": { 84 | "LowerDir": "/var/lib/containers/storage/overlay/b4fa6ff1346dec95ce4454464201fdadfd816e10eb7322048829c551ce032d08/diff", 85 | "MergedDir": "/var/lib/containers/storage/overlay/6dea692afd62add0259ae00d5c343806467c305de241df5dee32b500db315249/merged", 86 | "UpperDir": "/var/lib/containers/storage/overlay/6dea692afd62add0259ae00d5c343806467c305de241df5dee32b500db315249/diff", 87 | "WorkDir": "/var/lib/containers/storage/overlay/6dea692afd62add0259ae00d5c343806467c305de241df5dee32b500db315249/work" 88 | } 89 | }, 90 | "Mounts": [], 91 | "Dependencies": [], 92 | "NetworkSettings": { 93 | "EndpointID": "", 94 | "Gateway": "10.88.0.1", 95 | "IPAddress": "10.88.0.19", 96 | "IPPrefixLen": 16, 97 | "IPv6Gateway": "", 98 | "GlobalIPv6Address": "", 99 | "GlobalIPv6PrefixLen": 0, 100 | "MacAddress": "06:d8:84:ef:b9:d0", 101 | "Bridge": "", 102 | "SandboxID": "", 103 | "HairpinMode": false, 104 | "LinkLocalIPv6Address": "", 105 | "LinkLocalIPv6PrefixLen": 0, 106 | "Ports": {}, 107 | "SandboxKey": "/var/run/netns/cni-d1e80ea0-dca3-ade7-34b9-34ad49135471" 108 | }, 109 | "ExitCommand": [ 110 | "/usr/bin/podman", 111 | "--root", 112 | "/var/lib/containers/storage", 113 | "--runroot", 114 | "/var/run/containers/storage", 115 | "--log-level", 116 | "error", 117 | "--cgroup-manager", 118 | "systemd", 119 | "--tmpdir", 120 | "/var/run/libpod", 121 | "--runtime", 122 | "crun", 123 | "--storage-driver", 124 | "overlay", 125 | "--storage-opt", 126 | "overlay.mountopt=nodev,metacopy=on", 127 | "--events-backend", 128 | "journald", 129 | "container", 130 | "cleanup", 131 | "6335b78454e65cecc2c3c78c402e16d1a0691cf416468822c7f996594e991f2b" 132 | ], 133 | "Namespace": "", 134 | "IsInfra": false, 135 | "Config": { 136 | "Hostname": "6335b78454e6", 137 | "Domainname": "", 138 | "User": "", 139 | "AttachStdin": false, 140 | "AttachStdout": false, 141 | "AttachStderr": false, 142 | "Tty": true, 143 | "OpenStdin": true, 144 | "StdinOnce": false, 145 | "Env": [ 146 | "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", 147 | "TERM=xterm", 148 | "container=oci", 149 | "containers=podman", 150 | "DISTTAG=f33container", 151 | "FGC=f33", 152 | "HOSTNAME=6335b78454e6", 153 | "HOME=/root" 154 | ], 155 | "Cmd": [ 156 | "/bin/bash" 157 | ], 158 | "Image": "registry.fedoraproject.org/fedora:latest", 159 | "Volumes": null, 160 | "WorkingDir": "/", 161 | "Entrypoint": "", 162 | "OnBuild": null, 163 | "Labels": { 164 | "license": "MIT", 165 | "name": "fedora", 166 | "vendor": "Fedora Project", 167 | "version": "33" 168 | }, 169 | "Annotations": { 170 | "io.container.manager": "libpod", 171 | "io.kubernetes.cri-o.Created": "2020-11-24T20:06:25.852770272+01:00", 172 | "io.kubernetes.cri-o.TTY": "true", 173 | "io.podman.annotations.autoremove": "FALSE", 174 | "io.podman.annotations.init": "FALSE", 175 | "io.podman.annotations.privileged": "FALSE", 176 | "io.podman.annotations.publish-all": "FALSE", 177 | "org.opencontainers.image.stopSignal": "15" 178 | }, 179 | "StopSignal": 15, 180 | "CreateCommand": [ 181 | "/usr/bin/podman", 182 | "run", 183 | "--device", 184 | "/dev/fb0", 185 | "-it", 186 | "fedora", 187 | "/bin/bash" 188 | ], 189 | "Umask": "0022" 190 | }, 191 | "HostConfig": { 192 | "Binds": [], 193 | "CgroupMode": "private", 194 | "ContainerIDFile": "", 195 | "LogConfig": { 196 | "Type": "k8s-file", 197 | "Config": null 198 | }, 199 | "NetworkMode": "bridge", 200 | "PortBindings": {}, 201 | "RestartPolicy": { 202 | "Name": "", 203 | "MaximumRetryCount": 0 204 | }, 205 | "AutoRemove": false, 206 | "VolumeDriver": "", 207 | "VolumesFrom": null, 208 | "CapAdd": [], 209 | "CapDrop": [], 210 | "Dns": [], 211 | "DnsOptions": [], 212 | "DnsSearch": [], 213 | "ExtraHosts": [], 214 | "GroupAdd": [], 215 | "IpcMode": "private", 216 | "Cgroup": "", 217 | "Cgroups": "default", 218 | "Links": null, 219 | "OomScoreAdj": 0, 220 | "PidMode": "private", 221 | "Privileged": false, 222 | "PublishAllPorts": false, 223 | "ReadonlyRootfs": false, 224 | "SecurityOpt": [], 225 | "Tmpfs": {}, 226 | "UTSMode": "private", 227 | "UsernsMode": "", 228 | "ShmSize": 65536000, 229 | "Runtime": "oci", 230 | "ConsoleSize": [ 231 | 0, 232 | 0 233 | ], 234 | "Isolation": "", 235 | "CpuShares": 0, 236 | "Memory": 0, 237 | "NanoCpus": 0, 238 | "CgroupParent": "", 239 | "BlkioWeight": 0, 240 | "BlkioWeightDevice": null, 241 | "BlkioDeviceReadBps": null, 242 | "BlkioDeviceWriteBps": null, 243 | "BlkioDeviceReadIOps": null, 244 | "BlkioDeviceWriteIOps": null, 245 | "CpuPeriod": 0, 246 | "CpuQuota": 0, 247 | "CpuRealtimePeriod": 0, 248 | "CpuRealtimeRuntime": 0, 249 | "CpusetCpus": "", 250 | "CpusetMems": "", 251 | "Devices": [ 252 | { 253 | "PathOnHost": "/dev/fb0", 254 | "PathInContainer": "/dev/fb0", 255 | "CgroupPermissions": "" 256 | } 257 | ], 258 | "DiskQuota": 0, 259 | "KernelMemory": 0, 260 | "MemoryReservation": 0, 261 | "MemorySwap": 0, 262 | "MemorySwappiness": 0, 263 | "OomKillDisable": false, 264 | "PidsLimit": 2048, 265 | "Ulimits": [ 266 | { 267 | "Name": "RLIMIT_NOFILE", 268 | "Soft": 1048576, 269 | "Hard": 1048576 270 | }, 271 | { 272 | "Name": "RLIMIT_NPROC", 273 | "Soft": 4194304, 274 | "Hard": 4194304 275 | } 276 | ], 277 | "CpuCount": 0, 278 | "CpuPercent": 0, 279 | "IOMaximumIOps": 0, 280 | "IOMaximumBandwidth": 0, 281 | "CgroupConf": null 282 | } 283 | } 284 | ] 285 | -------------------------------------------------------------------------------- /tests/test_fullnetworkaccess.podman.cil: -------------------------------------------------------------------------------- 1 | (block my_container 2 | (blockinherit container) 3 | (blockinherit net_container) 4 | (allow process process ( capability ( audit_write chown dac_override fowner fsetid kill mknod net_bind_service net_raw setfcap setgid setpcap setuid sys_chroot ))) 5 | 6 | ) -------------------------------------------------------------------------------- /tests/test_integration.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2019 Jan Zarsky, 2 | # 3 | # This program is free software: you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation, either version 3 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU General Public License 14 | # along with this program. If not, see . 15 | 16 | import unittest 17 | import os 18 | import sys 19 | 20 | import test_main 21 | 22 | 23 | class TestIntegration(test_main.TestBase): 24 | """Test basic functionality of udica""" 25 | 26 | 27 | if __name__ == "__main__": 28 | # Very similar to our basic tests, but we don't overwrite the SELinux 29 | # modules 30 | unittest.main() 31 | -------------------------------------------------------------------------------- /tests/test_nocontext.podman.cil: -------------------------------------------------------------------------------- 1 | (block my_container 2 | (blockinherit container) 3 | (allow process process ( capability ( audit_write chown dac_override fowner fsetid kill mknod net_bind_service net_raw setfcap setgid setpcap setuid sys_chroot ))) 4 | 5 | (allow process user_tmp_t ( dir ( add_name create getattr ioctl lock open read remove_name rmdir search setattr write ))) 6 | (allow process user_tmp_t ( file ( append create getattr ioctl lock map open read rename setattr unlink write ))) 7 | (allow process user_tmp_t ( fifo_file ( getattr read write append ioctl lock open ))) 8 | (allow process user_tmp_t ( sock_file ( append getattr open read write ))) 9 | ) -------------------------------------------------------------------------------- /tests/test_nocontext.podman.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "Id": "7eaeb5b56620f22255708b711c63f7d5998ccad0145649d6621731c7155b18d6", 4 | "Created": "2020-08-03T16:44:04.327395828+02:00", 5 | "Path": "/bin/bash", 6 | "Args": [ 7 | "/bin/bash" 8 | ], 9 | "State": { 10 | "OciVersion": "1.0.2-dev", 11 | "Status": "running", 12 | "Running": true, 13 | "Paused": false, 14 | "Restarting": false, 15 | "OOMKilled": false, 16 | "Dead": false, 17 | "Pid": 530733, 18 | "ConmonPid": 530728, 19 | "ExitCode": 0, 20 | "Error": "", 21 | "StartedAt": "2020-08-03T16:44:04.747514452+02:00", 22 | "FinishedAt": "0001-01-01T00:00:00Z", 23 | "Healthcheck": { 24 | "Status": "", 25 | "FailingStreak": 0, 26 | "Log": null 27 | } 28 | }, 29 | "Image": "00ff39a8bf19f810a7e641f7eb3ddc47635913a19c4996debd91fafb6b379069", 30 | "ImageName": "registry.fedoraproject.org/fedora:latest", 31 | "Rootfs": "", 32 | "Pod": "", 33 | "ResolvConfPath": "/var/run/containers/storage/overlay-containers/7eaeb5b56620f22255708b711c63f7d5998ccad0145649d6621731c7155b18d6/userdata/resolv.conf", 34 | "HostnamePath": "/var/run/containers/storage/overlay-containers/7eaeb5b56620f22255708b711c63f7d5998ccad0145649d6621731c7155b18d6/userdata/hostname", 35 | "HostsPath": "/var/run/containers/storage/overlay-containers/7eaeb5b56620f22255708b711c63f7d5998ccad0145649d6621731c7155b18d6/userdata/hosts", 36 | "StaticDir": "/var/lib/containers/storage/overlay-containers/7eaeb5b56620f22255708b711c63f7d5998ccad0145649d6621731c7155b18d6/userdata", 37 | "OCIConfigPath": "/var/lib/containers/storage/overlay-containers/7eaeb5b56620f22255708b711c63f7d5998ccad0145649d6621731c7155b18d6/userdata/config.json", 38 | "OCIRuntime": "crun", 39 | "LogPath": "/var/lib/containers/storage/overlay-containers/7eaeb5b56620f22255708b711c63f7d5998ccad0145649d6621731c7155b18d6/userdata/ctr.log", 40 | "LogTag": "", 41 | "ConmonPidFile": "/var/run/containers/storage/overlay-containers/7eaeb5b56620f22255708b711c63f7d5998ccad0145649d6621731c7155b18d6/userdata/conmon.pid", 42 | "Name": "intelligent_brahmagupta", 43 | "RestartCount": 0, 44 | "Driver": "overlay", 45 | "MountLabel": "system_u:object_r:container_file_t:s0:c251,c393", 46 | "ProcessLabel": "system_u:system_r:container_t:s0:c251,c393", 47 | "AppArmorProfile": "", 48 | "EffectiveCaps": [ 49 | "CAP_AUDIT_WRITE", 50 | "CAP_CHOWN", 51 | "CAP_DAC_OVERRIDE", 52 | "CAP_FOWNER", 53 | "CAP_FSETID", 54 | "CAP_KILL", 55 | "CAP_MKNOD", 56 | "CAP_NET_BIND_SERVICE", 57 | "CAP_NET_RAW", 58 | "CAP_SETFCAP", 59 | "CAP_SETGID", 60 | "CAP_SETPCAP", 61 | "CAP_SETUID", 62 | "CAP_SYS_CHROOT" 63 | ], 64 | "BoundingCaps": [ 65 | "CAP_AUDIT_WRITE", 66 | "CAP_CHOWN", 67 | "CAP_DAC_OVERRIDE", 68 | "CAP_FOWNER", 69 | "CAP_FSETID", 70 | "CAP_KILL", 71 | "CAP_MKNOD", 72 | "CAP_NET_BIND_SERVICE", 73 | "CAP_NET_RAW", 74 | "CAP_SETFCAP", 75 | "CAP_SETGID", 76 | "CAP_SETPCAP", 77 | "CAP_SETUID", 78 | "CAP_SYS_CHROOT" 79 | ], 80 | "ExecIDs": [], 81 | "GraphDriver": { 82 | "Name": "overlay", 83 | "Data": { 84 | "LowerDir": "/var/lib/containers/storage/overlay/0ccfac04663bbe8813b5f24502ee0b7371ce5bf3c5adeb12e4258d191c2cf7bc/diff", 85 | "MergedDir": "/var/lib/containers/storage/overlay/1c9c24b66656886446ea03b9f66492eb830ec6e4c7a07418b48d2fb987551011/merged", 86 | "UpperDir": "/var/lib/containers/storage/overlay/1c9c24b66656886446ea03b9f66492eb830ec6e4c7a07418b48d2fb987551011/diff", 87 | "WorkDir": "/var/lib/containers/storage/overlay/1c9c24b66656886446ea03b9f66492eb830ec6e4c7a07418b48d2fb987551011/work" 88 | } 89 | }, 90 | "Mounts": [ 91 | { 92 | "Type": "bind", 93 | "Name": "", 94 | "Source": "/tmp/test", 95 | "Destination": "/tmp/test", 96 | "Driver": "", 97 | "Mode": "", 98 | "Options": [ 99 | "nosuid", 100 | "nodev", 101 | "rbind" 102 | ], 103 | "RW": true, 104 | "Propagation": "rprivate" 105 | } 106 | ], 107 | "Dependencies": [], 108 | "NetworkSettings": { 109 | "EndpointID": "", 110 | "Gateway": "10.88.0.1", 111 | "IPAddress": "10.88.0.242", 112 | "IPPrefixLen": 16, 113 | "IPv6Gateway": "", 114 | "GlobalIPv6Address": "", 115 | "GlobalIPv6PrefixLen": 0, 116 | "MacAddress": "52:fc:dd:21:82:6e", 117 | "Bridge": "", 118 | "SandboxID": "", 119 | "HairpinMode": false, 120 | "LinkLocalIPv6Address": "", 121 | "LinkLocalIPv6PrefixLen": 0, 122 | "Ports": {}, 123 | "SandboxKey": "/var/run/netns/cni-003a871b-bbb9-aeec-3e80-7b831a8d7837" 124 | }, 125 | "ExitCommand": [ 126 | "/usr/bin/podman", 127 | "--root", 128 | "/var/lib/containers/storage", 129 | "--runroot", 130 | "/var/run/containers/storage", 131 | "--log-level", 132 | "error", 133 | "--cgroup-manager", 134 | "systemd", 135 | "--tmpdir", 136 | "/var/run/libpod", 137 | "--runtime", 138 | "crun", 139 | "--storage-driver", 140 | "overlay", 141 | "--storage-opt", 142 | "overlay.mountopt=nodev,metacopy=on", 143 | "--events-backend", 144 | "file", 145 | "container", 146 | "cleanup", 147 | "7eaeb5b56620f22255708b711c63f7d5998ccad0145649d6621731c7155b18d6" 148 | ], 149 | "Namespace": "", 150 | "IsInfra": false, 151 | "Config": { 152 | "Hostname": "7eaeb5b56620", 153 | "Domainname": "", 154 | "User": "", 155 | "AttachStdin": false, 156 | "AttachStdout": false, 157 | "AttachStderr": false, 158 | "Tty": true, 159 | "OpenStdin": true, 160 | "StdinOnce": false, 161 | "Env": [ 162 | "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", 163 | "TERM=xterm", 164 | "container=podman", 165 | "DISTTAG=f32container", 166 | "FGC=f32", 167 | "HOSTNAME=7eaeb5b56620", 168 | "HOME=/root" 169 | ], 170 | "Cmd": [ 171 | "/bin/bash" 172 | ], 173 | "Image": "registry.fedoraproject.org/fedora:latest", 174 | "Volumes": null, 175 | "WorkingDir": "/", 176 | "Entrypoint": "", 177 | "OnBuild": null, 178 | "Labels": { 179 | "license": "MIT", 180 | "name": "fedora", 181 | "vendor": "Fedora Project", 182 | "version": "32" 183 | }, 184 | "Annotations": { 185 | "io.container.manager": "libpod", 186 | "io.kubernetes.cri-o.Created": "2020-08-03T16:44:04.327395828+02:00", 187 | "io.kubernetes.cri-o.TTY": "true", 188 | "io.podman.annotations.autoremove": "FALSE", 189 | "io.podman.annotations.init": "FALSE", 190 | "io.podman.annotations.privileged": "FALSE", 191 | "io.podman.annotations.publish-all": "FALSE", 192 | "org.opencontainers.image.stopSignal": "15" 193 | }, 194 | "StopSignal": 15, 195 | "CreateCommand": [ 196 | "/bin/podman", 197 | "run", 198 | "-it", 199 | "-v", 200 | "/tmp/test:/tmp/test:rw", 201 | "fedora" 202 | ] 203 | }, 204 | "HostConfig": { 205 | "Binds": [ 206 | "/tmp/test:/tmp/test:rw,rprivate,nosuid,nodev,rbind" 207 | ], 208 | "CgroupMode": "private", 209 | "ContainerIDFile": "", 210 | "LogConfig": { 211 | "Type": "k8s-file", 212 | "Config": null 213 | }, 214 | "NetworkMode": "bridge", 215 | "PortBindings": {}, 216 | "RestartPolicy": { 217 | "Name": "", 218 | "MaximumRetryCount": 0 219 | }, 220 | "AutoRemove": false, 221 | "VolumeDriver": "", 222 | "VolumesFrom": null, 223 | "CapAdd": [], 224 | "CapDrop": [], 225 | "Dns": [], 226 | "DnsOptions": [], 227 | "DnsSearch": [], 228 | "ExtraHosts": [], 229 | "GroupAdd": [], 230 | "IpcMode": "private", 231 | "Cgroup": "", 232 | "Cgroups": "default", 233 | "Links": null, 234 | "OomScoreAdj": 0, 235 | "PidMode": "private", 236 | "Privileged": false, 237 | "PublishAllPorts": false, 238 | "ReadonlyRootfs": false, 239 | "SecurityOpt": [], 240 | "Tmpfs": {}, 241 | "UTSMode": "private", 242 | "UsernsMode": "", 243 | "ShmSize": 65536000, 244 | "Runtime": "oci", 245 | "ConsoleSize": [ 246 | 0, 247 | 0 248 | ], 249 | "Isolation": "", 250 | "CpuShares": 0, 251 | "Memory": 0, 252 | "NanoCpus": 0, 253 | "CgroupParent": "", 254 | "BlkioWeight": 0, 255 | "BlkioWeightDevice": null, 256 | "BlkioDeviceReadBps": null, 257 | "BlkioDeviceWriteBps": null, 258 | "BlkioDeviceReadIOps": null, 259 | "BlkioDeviceWriteIOps": null, 260 | "CpuPeriod": 0, 261 | "CpuQuota": 0, 262 | "CpuRealtimePeriod": 0, 263 | "CpuRealtimeRuntime": 0, 264 | "CpusetCpus": "", 265 | "CpusetMems": "", 266 | "Devices": [], 267 | "DiskQuota": 0, 268 | "KernelMemory": 0, 269 | "MemoryReservation": 0, 270 | "MemorySwap": 0, 271 | "MemorySwappiness": 0, 272 | "OomKillDisable": false, 273 | "PidsLimit": 2048, 274 | "Ulimits": [ 275 | { 276 | "Name": "RLIMIT_NOFILE", 277 | "Soft": 1048576, 278 | "Hard": 1048576 279 | }, 280 | { 281 | "Name": "RLIMIT_NPROC", 282 | "Soft": 4194304, 283 | "Hard": 4194304 284 | } 285 | ], 286 | "CpuCount": 0, 287 | "CpuPercent": 0, 288 | "IOMaximumIOps": 0, 289 | "IOMaximumBandwidth": 0 290 | } 291 | } 292 | ] 293 | -------------------------------------------------------------------------------- /tests/test_ports.docker.cil: -------------------------------------------------------------------------------- 1 | (block my_container 2 | (blockinherit container) 3 | (blockinherit restricted_net_container) 4 | (allow process mysqld_port_t ( tcp_socket ( name_bind ))) 5 | ) -------------------------------------------------------------------------------- /tests/test_ports.docker.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "Id": "5c834846f8f0463510f94c756c3b2b531927cee8a5a5b5014fef7db52d9bd74e", 4 | "Created": "2019-04-08T10:35:01.385636313Z", 5 | "Path": "sleep", 6 | "Args": [ 7 | "60" 8 | ], 9 | "State": { 10 | "Status": "running", 11 | "Running": true, 12 | "Paused": false, 13 | "Restarting": false, 14 | "OOMKilled": false, 15 | "Dead": false, 16 | "Pid": 12813, 17 | "ExitCode": 0, 18 | "Error": "", 19 | "StartedAt": "2019-04-08T10:35:01.778796776Z", 20 | "FinishedAt": "0001-01-01T00:00:00Z" 21 | }, 22 | "Image": "sha256:d09302f77cfcc3e867829d80ff47f9e7738ffef69730d54ec44341a9fb1d359b", 23 | "ResolvConfPath": "/var/lib/docker/containers/5c834846f8f0463510f94c756c3b2b531927cee8a5a5b5014fef7db52d9bd74e/resolv.conf", 24 | "HostnamePath": "/var/lib/docker/containers/5c834846f8f0463510f94c756c3b2b531927cee8a5a5b5014fef7db52d9bd74e/hostname", 25 | "HostsPath": "/var/lib/docker/containers/5c834846f8f0463510f94c756c3b2b531927cee8a5a5b5014fef7db52d9bd74e/hosts", 26 | "LogPath": "", 27 | "Name": "/loving_ardinghelli", 28 | "RestartCount": 0, 29 | "Driver": "overlay2", 30 | "MountLabel": "system_u:object_r:container_file_t:s0:c794,c841", 31 | "ProcessLabel": "system_u:system_r:container_t:s0:c794,c841", 32 | "AppArmorProfile": "", 33 | "ExecIDs": null, 34 | "HostConfig": { 35 | "Binds": null, 36 | "ContainerIDFile": "", 37 | "LogConfig": { 38 | "Type": "journald", 39 | "Config": {} 40 | }, 41 | "NetworkMode": "default", 42 | "PortBindings": { 43 | "63140/tcp": [ 44 | { 45 | "HostIp": "", 46 | "HostPort": "63140" 47 | } 48 | ] 49 | }, 50 | "RestartPolicy": { 51 | "Name": "no", 52 | "MaximumRetryCount": 0 53 | }, 54 | "AutoRemove": false, 55 | "VolumeDriver": "", 56 | "VolumesFrom": null, 57 | "CapAdd": null, 58 | "CapDrop": null, 59 | "Dns": [], 60 | "DnsOptions": [], 61 | "DnsSearch": [], 62 | "ExtraHosts": null, 63 | "GroupAdd": null, 64 | "IpcMode": "", 65 | "Cgroup": "", 66 | "Links": null, 67 | "OomScoreAdj": 0, 68 | "PidMode": "", 69 | "Privileged": false, 70 | "PublishAllPorts": false, 71 | "ReadonlyRootfs": false, 72 | "SecurityOpt": null, 73 | "UTSMode": "", 74 | "UsernsMode": "", 75 | "ShmSize": 67108864, 76 | "Runtime": "oci", 77 | "ConsoleSize": [ 78 | 0, 79 | 0 80 | ], 81 | "Isolation": "", 82 | "CpuShares": 0, 83 | "Memory": 0, 84 | "NanoCpus": 0, 85 | "CgroupParent": "", 86 | "BlkioWeight": 0, 87 | "BlkioWeightDevice": null, 88 | "BlkioDeviceReadBps": null, 89 | "BlkioDeviceWriteBps": null, 90 | "BlkioDeviceReadIOps": null, 91 | "BlkioDeviceWriteIOps": null, 92 | "CpuPeriod": 0, 93 | "CpuQuota": 0, 94 | "CpuRealtimePeriod": 0, 95 | "CpuRealtimeRuntime": 0, 96 | "CpusetCpus": "", 97 | "CpusetMems": "", 98 | "Devices": [], 99 | "DiskQuota": 0, 100 | "KernelMemory": 0, 101 | "MemoryReservation": 0, 102 | "MemorySwap": 0, 103 | "MemorySwappiness": -1, 104 | "OomKillDisable": false, 105 | "PidsLimit": 0, 106 | "Ulimits": null, 107 | "CpuCount": 0, 108 | "CpuPercent": 0, 109 | "IOMaximumIOps": 0, 110 | "IOMaximumBandwidth": 0 111 | }, 112 | "GraphDriver": { 113 | "Name": "overlay2", 114 | "Data": { 115 | "LowerDir": "/var/lib/docker/overlay2/e2d4cfbe0628382678058cae029059856e45c25b09d52ce3d8c0cf917e7209d4-init/diff:/var/lib/docker/overlay2/e44913bf3f35a9468af11e2f3ede0d5c5ebeff7afd9c61e7871a55c97279db2d/diff", 116 | "MergedDir": "/var/lib/docker/overlay2/e2d4cfbe0628382678058cae029059856e45c25b09d52ce3d8c0cf917e7209d4/merged", 117 | "UpperDir": "/var/lib/docker/overlay2/e2d4cfbe0628382678058cae029059856e45c25b09d52ce3d8c0cf917e7209d4/diff", 118 | "WorkDir": "/var/lib/docker/overlay2/e2d4cfbe0628382678058cae029059856e45c25b09d52ce3d8c0cf917e7209d4/work" 119 | } 120 | }, 121 | "Mounts": [], 122 | "Config": { 123 | "Hostname": "5c834846f8f0", 124 | "Domainname": "", 125 | "User": "", 126 | "AttachStdin": false, 127 | "AttachStdout": true, 128 | "AttachStderr": true, 129 | "ExposedPorts": { 130 | "63140/tcp": {} 131 | }, 132 | "Tty": false, 133 | "OpenStdin": false, 134 | "StdinOnce": false, 135 | "Env": [ 136 | "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", 137 | "DISTTAG=fcontainer", 138 | "FGC=f", 139 | "FBR=f" 140 | ], 141 | "Cmd": [ 142 | "sleep", 143 | "60" 144 | ], 145 | "Image": "fedora", 146 | "Volumes": null, 147 | "WorkingDir": "", 148 | "Entrypoint": null, 149 | "OnBuild": null, 150 | "Labels": { 151 | "maintainer": "Clement Verna " 152 | } 153 | }, 154 | "NetworkSettings": { 155 | "Bridge": "", 156 | "SandboxID": "3bd3f5b5f1e3828363152f115da555e14404e5ef3cbf01d2d406e991e3e5d13f", 157 | "HairpinMode": false, 158 | "LinkLocalIPv6Address": "", 159 | "LinkLocalIPv6PrefixLen": 0, 160 | "Ports": { 161 | "63140/tcp": [ 162 | { 163 | "HostIp": "0.0.0.0", 164 | "HostPort": "63140" 165 | } 166 | ] 167 | }, 168 | "SandboxKey": "/var/run/docker/netns/3bd3f5b5f1e3", 169 | "SecondaryIPAddresses": null, 170 | "SecondaryIPv6Addresses": null, 171 | "EndpointID": "dcaa10d5654663aec8f17068ab0c622fe096355285ce2706cf85a94cf62b9bba", 172 | "Gateway": "172.17.0.1", 173 | "GlobalIPv6Address": "", 174 | "GlobalIPv6PrefixLen": 0, 175 | "IPAddress": "172.17.0.2", 176 | "IPPrefixLen": 16, 177 | "IPv6Gateway": "", 178 | "MacAddress": "02:42:ac:11:00:02", 179 | "Networks": { 180 | "bridge": { 181 | "IPAMConfig": null, 182 | "Links": null, 183 | "Aliases": null, 184 | "NetworkID": "12b0261683c277c28c352971d1f5d16b57881dbf81d03765a3d9cefac2fb91a3", 185 | "EndpointID": "dcaa10d5654663aec8f17068ab0c622fe096355285ce2706cf85a94cf62b9bba", 186 | "Gateway": "172.17.0.1", 187 | "IPAddress": "172.17.0.2", 188 | "IPPrefixLen": 16, 189 | "IPv6Gateway": "", 190 | "GlobalIPv6Address": "", 191 | "GlobalIPv6PrefixLen": 0, 192 | "MacAddress": "02:42:ac:11:00:02" 193 | } 194 | } 195 | } 196 | } 197 | ] 198 | -------------------------------------------------------------------------------- /tests/test_ports.podman.cil: -------------------------------------------------------------------------------- 1 | (block my_container 2 | (blockinherit container) 3 | (blockinherit restricted_net_container) 4 | (allow process process ( capability ( audit_write chown dac_override fowner fsetid kill mknod net_bind_service net_raw setfcap setgid setpcap setuid sys_chroot ))) 5 | 6 | (allow process mysqld_port_t ( tcp_socket ( name_bind ))) 7 | ) -------------------------------------------------------------------------------- /tests/test_ports.podman.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "Id": "b8fcfaac37de0d13494d5e165903b26f98896a30b73c52f1b47f3a20432d741b", 4 | "Created": "2020-08-03T16:42:57.544562109+02:00", 5 | "Path": "/bin/bash", 6 | "Args": [ 7 | "/bin/bash" 8 | ], 9 | "State": { 10 | "OciVersion": "1.0.2-dev", 11 | "Status": "running", 12 | "Running": true, 13 | "Paused": false, 14 | "Restarting": false, 15 | "OOMKilled": false, 16 | "Dead": false, 17 | "Pid": 530277, 18 | "ConmonPid": 530272, 19 | "ExitCode": 0, 20 | "Error": "", 21 | "StartedAt": "2020-08-03T16:42:58.009875371+02:00", 22 | "FinishedAt": "0001-01-01T00:00:00Z", 23 | "Healthcheck": { 24 | "Status": "", 25 | "FailingStreak": 0, 26 | "Log": null 27 | } 28 | }, 29 | "Image": "00ff39a8bf19f810a7e641f7eb3ddc47635913a19c4996debd91fafb6b379069", 30 | "ImageName": "registry.fedoraproject.org/fedora:latest", 31 | "Rootfs": "", 32 | "Pod": "", 33 | "ResolvConfPath": "/var/run/containers/storage/overlay-containers/b8fcfaac37de0d13494d5e165903b26f98896a30b73c52f1b47f3a20432d741b/userdata/resolv.conf", 34 | "HostnamePath": "/var/run/containers/storage/overlay-containers/b8fcfaac37de0d13494d5e165903b26f98896a30b73c52f1b47f3a20432d741b/userdata/hostname", 35 | "HostsPath": "/var/run/containers/storage/overlay-containers/b8fcfaac37de0d13494d5e165903b26f98896a30b73c52f1b47f3a20432d741b/userdata/hosts", 36 | "StaticDir": "/var/lib/containers/storage/overlay-containers/b8fcfaac37de0d13494d5e165903b26f98896a30b73c52f1b47f3a20432d741b/userdata", 37 | "OCIConfigPath": "/var/lib/containers/storage/overlay-containers/b8fcfaac37de0d13494d5e165903b26f98896a30b73c52f1b47f3a20432d741b/userdata/config.json", 38 | "OCIRuntime": "crun", 39 | "LogPath": "/var/lib/containers/storage/overlay-containers/b8fcfaac37de0d13494d5e165903b26f98896a30b73c52f1b47f3a20432d741b/userdata/ctr.log", 40 | "LogTag": "", 41 | "ConmonPidFile": "/var/run/containers/storage/overlay-containers/b8fcfaac37de0d13494d5e165903b26f98896a30b73c52f1b47f3a20432d741b/userdata/conmon.pid", 42 | "Name": "eloquent_booth", 43 | "RestartCount": 0, 44 | "Driver": "overlay", 45 | "MountLabel": "system_u:object_r:container_file_t:s0:c241,c976", 46 | "ProcessLabel": "system_u:system_r:container_t:s0:c241,c976", 47 | "AppArmorProfile": "", 48 | "EffectiveCaps": [ 49 | "CAP_AUDIT_WRITE", 50 | "CAP_CHOWN", 51 | "CAP_DAC_OVERRIDE", 52 | "CAP_FOWNER", 53 | "CAP_FSETID", 54 | "CAP_KILL", 55 | "CAP_MKNOD", 56 | "CAP_NET_BIND_SERVICE", 57 | "CAP_NET_RAW", 58 | "CAP_SETFCAP", 59 | "CAP_SETGID", 60 | "CAP_SETPCAP", 61 | "CAP_SETUID", 62 | "CAP_SYS_CHROOT" 63 | ], 64 | "BoundingCaps": [ 65 | "CAP_AUDIT_WRITE", 66 | "CAP_CHOWN", 67 | "CAP_DAC_OVERRIDE", 68 | "CAP_FOWNER", 69 | "CAP_FSETID", 70 | "CAP_KILL", 71 | "CAP_MKNOD", 72 | "CAP_NET_BIND_SERVICE", 73 | "CAP_NET_RAW", 74 | "CAP_SETFCAP", 75 | "CAP_SETGID", 76 | "CAP_SETPCAP", 77 | "CAP_SETUID", 78 | "CAP_SYS_CHROOT" 79 | ], 80 | "ExecIDs": [], 81 | "GraphDriver": { 82 | "Name": "overlay", 83 | "Data": { 84 | "LowerDir": "/var/lib/containers/storage/overlay/0ccfac04663bbe8813b5f24502ee0b7371ce5bf3c5adeb12e4258d191c2cf7bc/diff", 85 | "MergedDir": "/var/lib/containers/storage/overlay/707cb47b828a17213b22d7e533ced21976a752a613687f31072aff3fb33e9e63/merged", 86 | "UpperDir": "/var/lib/containers/storage/overlay/707cb47b828a17213b22d7e533ced21976a752a613687f31072aff3fb33e9e63/diff", 87 | "WorkDir": "/var/lib/containers/storage/overlay/707cb47b828a17213b22d7e533ced21976a752a613687f31072aff3fb33e9e63/work" 88 | } 89 | }, 90 | "Mounts": [], 91 | "Dependencies": [], 92 | "NetworkSettings": { 93 | "EndpointID": "", 94 | "Gateway": "10.88.0.1", 95 | "IPAddress": "10.88.0.241", 96 | "IPPrefixLen": 16, 97 | "IPv6Gateway": "", 98 | "GlobalIPv6Address": "", 99 | "GlobalIPv6PrefixLen": 0, 100 | "MacAddress": "fa:11:eb:b8:66:47", 101 | "Bridge": "", 102 | "SandboxID": "", 103 | "HairpinMode": false, 104 | "LinkLocalIPv6Address": "", 105 | "LinkLocalIPv6PrefixLen": 0, 106 | "Ports": { 107 | "63140/tcp": [ 108 | { 109 | "HostIp": "", 110 | "HostPort": "63140" 111 | } 112 | ] 113 | }, 114 | "SandboxKey": "/var/run/netns/cni-7eb38b61-500c-127d-8724-e1394fbb89b4" 115 | }, 116 | "ExitCommand": [ 117 | "/usr/bin/podman", 118 | "--root", 119 | "/var/lib/containers/storage", 120 | "--runroot", 121 | "/var/run/containers/storage", 122 | "--log-level", 123 | "error", 124 | "--cgroup-manager", 125 | "systemd", 126 | "--tmpdir", 127 | "/var/run/libpod", 128 | "--runtime", 129 | "crun", 130 | "--storage-driver", 131 | "overlay", 132 | "--storage-opt", 133 | "overlay.mountopt=nodev,metacopy=on", 134 | "--events-backend", 135 | "file", 136 | "container", 137 | "cleanup", 138 | "b8fcfaac37de0d13494d5e165903b26f98896a30b73c52f1b47f3a20432d741b" 139 | ], 140 | "Namespace": "", 141 | "IsInfra": false, 142 | "Config": { 143 | "Hostname": "b8fcfaac37de", 144 | "Domainname": "", 145 | "User": "", 146 | "AttachStdin": false, 147 | "AttachStdout": false, 148 | "AttachStderr": false, 149 | "Tty": true, 150 | "OpenStdin": true, 151 | "StdinOnce": false, 152 | "Env": [ 153 | "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", 154 | "TERM=xterm", 155 | "container=podman", 156 | "DISTTAG=f32container", 157 | "FGC=f32", 158 | "HOSTNAME=b8fcfaac37de", 159 | "HOME=/root" 160 | ], 161 | "Cmd": [ 162 | "/bin/bash" 163 | ], 164 | "Image": "registry.fedoraproject.org/fedora:latest", 165 | "Volumes": null, 166 | "WorkingDir": "/", 167 | "Entrypoint": "", 168 | "OnBuild": null, 169 | "Labels": { 170 | "license": "MIT", 171 | "name": "fedora", 172 | "vendor": "Fedora Project", 173 | "version": "32" 174 | }, 175 | "Annotations": { 176 | "io.container.manager": "libpod", 177 | "io.kubernetes.cri-o.Created": "2020-08-03T16:42:57.544562109+02:00", 178 | "io.kubernetes.cri-o.TTY": "true", 179 | "io.podman.annotations.autoremove": "FALSE", 180 | "io.podman.annotations.init": "FALSE", 181 | "io.podman.annotations.privileged": "FALSE", 182 | "io.podman.annotations.publish-all": "FALSE", 183 | "org.opencontainers.image.stopSignal": "15" 184 | }, 185 | "StopSignal": 15, 186 | "CreateCommand": [ 187 | "/bin/podman", 188 | "run", 189 | "-it", 190 | "-p", 191 | "63140:63140", 192 | "fedora" 193 | ] 194 | }, 195 | "HostConfig": { 196 | "Binds": [], 197 | "CgroupMode": "private", 198 | "ContainerIDFile": "", 199 | "LogConfig": { 200 | "Type": "k8s-file", 201 | "Config": null 202 | }, 203 | "NetworkMode": "bridge", 204 | "PortBindings": { 205 | "63140/tcp": [ 206 | { 207 | "HostIp": "", 208 | "HostPort": "63140" 209 | } 210 | ] 211 | }, 212 | "RestartPolicy": { 213 | "Name": "", 214 | "MaximumRetryCount": 0 215 | }, 216 | "AutoRemove": false, 217 | "VolumeDriver": "", 218 | "VolumesFrom": null, 219 | "CapAdd": [], 220 | "CapDrop": [], 221 | "Dns": [], 222 | "DnsOptions": [], 223 | "DnsSearch": [], 224 | "ExtraHosts": [], 225 | "GroupAdd": [], 226 | "IpcMode": "private", 227 | "Cgroup": "", 228 | "Cgroups": "default", 229 | "Links": null, 230 | "OomScoreAdj": 0, 231 | "PidMode": "private", 232 | "Privileged": false, 233 | "PublishAllPorts": false, 234 | "ReadonlyRootfs": false, 235 | "SecurityOpt": [], 236 | "Tmpfs": {}, 237 | "UTSMode": "private", 238 | "UsernsMode": "", 239 | "ShmSize": 65536000, 240 | "Runtime": "oci", 241 | "ConsoleSize": [ 242 | 0, 243 | 0 244 | ], 245 | "Isolation": "", 246 | "CpuShares": 0, 247 | "Memory": 0, 248 | "NanoCpus": 0, 249 | "CgroupParent": "", 250 | "BlkioWeight": 0, 251 | "BlkioWeightDevice": null, 252 | "BlkioDeviceReadBps": null, 253 | "BlkioDeviceWriteBps": null, 254 | "BlkioDeviceReadIOps": null, 255 | "BlkioDeviceWriteIOps": null, 256 | "CpuPeriod": 0, 257 | "CpuQuota": 0, 258 | "CpuRealtimePeriod": 0, 259 | "CpuRealtimeRuntime": 0, 260 | "CpusetCpus": "", 261 | "CpusetMems": "", 262 | "Devices": [], 263 | "DiskQuota": 0, 264 | "KernelMemory": 0, 265 | "MemoryReservation": 0, 266 | "MemorySwap": 0, 267 | "MemorySwappiness": 0, 268 | "OomKillDisable": false, 269 | "PidsLimit": 2048, 270 | "Ulimits": [ 271 | { 272 | "Name": "RLIMIT_NOFILE", 273 | "Soft": 1048576, 274 | "Hard": 1048576 275 | }, 276 | { 277 | "Name": "RLIMIT_NPROC", 278 | "Soft": 4194304, 279 | "Hard": 4194304 280 | } 281 | ], 282 | "CpuCount": 0, 283 | "CpuPercent": 0, 284 | "IOMaximumIOps": 0, 285 | "IOMaximumBandwidth": 0 286 | } 287 | } 288 | ] 289 | -------------------------------------------------------------------------------- /tests/test_stream_connect.podman.cil: -------------------------------------------------------------------------------- 1 | (block my_container 2 | (blockinherit container) 3 | (allow process network_container.process ( unix_stream_socket ( connectto ))) 4 | (allow process network_container.socket ( sock_file ( getattr write open append ))) 5 | (allow process process ( capability ( audit_write chown dac_override fowner fsetid kill mknod net_bind_service net_raw setfcap setgid setpcap setuid sys_chroot ))) 6 | 7 | ) -------------------------------------------------------------------------------- /tests/test_ttyaccess.podman.cil: -------------------------------------------------------------------------------- 1 | (block my_container 2 | (blockinherit container) 3 | (blockinherit tty_container) 4 | (allow process process ( capability ( audit_write chown dac_override fowner fsetid kill mknod net_bind_service net_raw setfcap setgid setpcap setuid sys_chroot ))) 5 | 6 | ) -------------------------------------------------------------------------------- /tests/test_unit.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2019 Jan Zarsky, 2 | # 3 | # This program is free software: you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation, either version 3 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU General Public License 14 | # along with this program. If not, see . 15 | 16 | import os 17 | from unittest.mock import patch 18 | 19 | import tests.test_main 20 | import tests.selinux as mocked_selinux 21 | import tests.semanage as mocked_semanage 22 | 23 | 24 | class TestUnit(tests.test_main.TestBase): 25 | """Test basic functionality of udica""" 26 | 27 | def setUp(self): 28 | self.selinux_patch = patch.dict("sys.modules", selinux=mocked_selinux) 29 | self.selinux_patch.start() 30 | 31 | self.semanage_patch = patch.dict("sys.modules", semanage=mocked_semanage) 32 | self.semanage_patch.start() 33 | 34 | super().setUp() 35 | 36 | def tearDown(self): 37 | self.selinux_patch.stop() 38 | self.semanage_patch.stop() 39 | super().tearDown() 40 | -------------------------------------------------------------------------------- /tests/test_virtaccess.podman.cil: -------------------------------------------------------------------------------- 1 | (block my_container 2 | (blockinherit container) 3 | (blockinherit virt_container) 4 | (allow process process ( capability ( audit_write chown dac_override fowner fsetid kill mknod net_bind_service net_raw setfcap setgid setpcap setuid sys_chroot ))) 5 | 6 | ) -------------------------------------------------------------------------------- /tests/test_xaccess.podman.cil: -------------------------------------------------------------------------------- 1 | (block my_container 2 | (blockinherit container) 3 | (blockinherit x_container) 4 | (allow process process ( capability ( audit_write chown dac_override fowner fsetid kill mknod net_bind_service net_raw setfcap setgid setpcap setuid sys_chroot ))) 5 | 6 | ) -------------------------------------------------------------------------------- /udica/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/containers/udica/54fa8f58f1a024fc064acef350cc3e2b276f68b7/udica/__init__.py -------------------------------------------------------------------------------- /udica/__main__.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2018 Lukas Vrabec, 2 | # 3 | # This program is free software: you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation, either version 3 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU General Public License 14 | # along with this program. If not, see . 15 | 16 | import argparse 17 | import subprocess 18 | import sys 19 | 20 | # import udica 21 | from udica.parse import parse_avc_file 22 | from udica.parse import ENGINE_ALL, ENGINE_PODMAN, ENGINE_DOCKER 23 | from udica.version import version 24 | from udica import parse 25 | from udica.policy import create_policy, load_policy, generate_playbook 26 | 27 | 28 | def get_args(): 29 | if "confined_user" in sys.argv: 30 | # set up confined_user parser (do not show normal "udica" options) 31 | parser = argparse.ArgumentParser( 32 | description="SELinux confined user policy generator" 33 | ) 34 | parser.add_argument("confined_user") 35 | parser.add_argument( 36 | "-a", 37 | "--admin_commands", 38 | action="store_true", 39 | default=False, 40 | dest="admin_commands", 41 | help="Use administrative commands (vipw, passwd, ...)", 42 | ) 43 | parser.add_argument( 44 | "-g", 45 | "--graphical_login", 46 | action="store_true", 47 | default=False, 48 | dest="graphical_login", 49 | help="Use graphical login environment", 50 | ) 51 | parser.add_argument( 52 | "-m", 53 | "--mozilla_usage", 54 | action="store_true", 55 | default=False, 56 | dest="mozilla_usage", 57 | help="Use mozilla firefox", 58 | ) 59 | parser.add_argument( 60 | "-n", 61 | "--networking", 62 | action="store_true", 63 | default=False, 64 | dest="networking", 65 | help="Manage basic networking (ip, ifconfig, traceroute, tcpdump, ...)", 66 | ) 67 | parser.add_argument( 68 | "-d", 69 | "--security_advanced", 70 | action="store_true", 71 | default=False, 72 | dest="security_advanced", 73 | help="Manage SELinux settings (semanage, semodule, sepolicy, ...)", 74 | ) 75 | parser.add_argument( 76 | "-i", 77 | "--security_basic", 78 | action="store_true", 79 | default=False, 80 | dest="security_basic", 81 | help="Use read-only security-related tools (seinfo, getsebool, sesearch, ...)", 82 | ) 83 | parser.add_argument( 84 | "-s", 85 | "--sudo", 86 | action="store_true", 87 | default=False, 88 | dest="sudo", 89 | help="Run commands as root using sudo", 90 | ) 91 | parser.add_argument( 92 | "-l", 93 | "--user_login", 94 | action="store_true", 95 | default=True, 96 | dest="user_login", 97 | help="Basic rules common to all users (tty, pty, ...)", 98 | ) 99 | parser.add_argument( 100 | "-c", 101 | "--ssh_connect", 102 | action="store_true", 103 | default=False, 104 | dest="ssh_connect", 105 | help="Connect over SSH", 106 | ) 107 | parser.add_argument( 108 | "-b", 109 | "--basic_commands", 110 | action="store_true", 111 | default=False, 112 | dest="basic_commands", 113 | help="Use basic commands (date, ls, ps, man, systemctl -user, journalctl -user, passwd, ...)", 114 | ) 115 | parser.add_argument( 116 | "--level", 117 | nargs="?", 118 | default="s0", 119 | dest="level", 120 | help='MLS/MCS level, defaults to "s0"', 121 | ) 122 | parser.add_argument( 123 | "--range", 124 | nargs="?", 125 | default="s0-s0:c0.c1023", 126 | dest="range", 127 | help='MLS/MCS range, defaults to "s0-s0:c0.c1023"', 128 | ) 129 | parser.add_argument("uname") 130 | else: 131 | # set up normal udica parser 132 | parser = argparse.ArgumentParser( 133 | description="Script generates SELinux policy for running container.", 134 | prog="udica [confined_user]", 135 | formatter_class=argparse.RawDescriptionHelpFormatter, 136 | epilog="""Additional options: 137 | confined_user Generate policy for a new confined user instead of a container policy""", 138 | ) 139 | parser.add_argument("-V", "--version", action="version", version=version) 140 | parser.add_argument( 141 | type=str, help="Name for SELinux policy module", dest="ContainerName" 142 | ) 143 | parser.add_argument( 144 | "-i", 145 | "--container-id", 146 | type=str, 147 | help="Running container ID", 148 | dest="ContainerID", 149 | default=None, 150 | ) 151 | parser.add_argument( 152 | "-j", 153 | "--json", 154 | help='Load json from this file, use "-j -" for stdin', 155 | required=False, 156 | dest="JsonFile", 157 | default=None, 158 | ) 159 | parser.add_argument( 160 | "--full-network-access", 161 | help="Allow container full Network access ", 162 | required=False, 163 | dest="FullNetworkAccess", 164 | action="store_true", 165 | ) 166 | parser.add_argument( 167 | "--tty-access", 168 | help="Allow container to read and write the controlling terminal ", 169 | required=False, 170 | dest="TtyAccess", 171 | action="store_true", 172 | ) 173 | parser.add_argument( 174 | "--X-access", 175 | help="Allow container to communicate with Xserver ", 176 | required=False, 177 | dest="XAccess", 178 | action="store_true", 179 | ) 180 | parser.add_argument( 181 | "--virt-access", 182 | help="Allow container to communicate with libvirt ", 183 | required=False, 184 | dest="VirtAccess", 185 | action="store_true", 186 | ) 187 | parser.add_argument( 188 | "-s", 189 | "--stream-connect", 190 | help="Allow container to stream connect with given SELinux domain ", 191 | required=False, 192 | dest="StreamConnect", 193 | ) 194 | parser.add_argument( 195 | "-l", 196 | "--load-modules", 197 | help="Load templates and module created by this tool ", 198 | required=False, 199 | dest="LoadModules", 200 | action="store_true", 201 | ) 202 | parser.add_argument( 203 | "-c", 204 | "--caps", 205 | help='List of capabilities, e.g "-c AUDIT_WRITE,CHOWN,DAC_OVERRIDE,FOWNER,FSETID,KILL,MKNOD,NET_BIND_SERVICE,NET_RAW,SETFCAP,SETGID,SETPCAP,SETUID,SYS_CHROOT"', 206 | required=False, 207 | dest="Caps", 208 | default=None, 209 | ) 210 | parser.add_argument( 211 | "--devices", 212 | type=str, 213 | help='List of devices the container should have access to, e.g "--devices /dev/dri/card0,/dev/dri/renderD128"', 214 | dest="Devices", 215 | required=False, 216 | default=None, 217 | ) 218 | parser.add_argument( 219 | "-d", 220 | "--ansible", 221 | help="Generate ansible playbook to deploy SELinux policy for containers ", 222 | required=False, 223 | dest="Ansible", 224 | action="store_true", 225 | ) 226 | parser.add_argument( 227 | "-a", 228 | "--append-rules", 229 | type=str, 230 | help="Append more SELinux allow rules from file", 231 | dest="FileAVCS", 232 | required=False, 233 | default=None, 234 | ) 235 | parser.add_argument( 236 | "-e", 237 | "--container-engine", 238 | type=str, 239 | help="Specify which container engine is used for the inspected container (supports: {})".format( 240 | ", ".join(ENGINE_ALL) 241 | ), 242 | dest="ContainerEngine", 243 | required=False, 244 | default="-", 245 | ) 246 | 247 | args = parser.parse_args() 248 | return vars(args) 249 | 250 | 251 | def main(): 252 | opts = get_args() 253 | 254 | # generate confined user policy 255 | if "confined_user" in opts.keys(): 256 | from udica.confined_user import create_confined_user_policy 257 | 258 | create_confined_user_policy(opts) 259 | return 260 | 261 | if opts["ContainerID"]: 262 | container_inspect_raw = None 263 | for backend in [ENGINE_PODMAN, ENGINE_DOCKER]: 264 | try: 265 | run_inspect = subprocess.Popen( 266 | [backend, "inspect", opts["ContainerID"]], 267 | stdout=subprocess.PIPE, 268 | stderr=subprocess.DEVNULL, 269 | ) 270 | inspect_data = run_inspect.communicate()[0] 271 | if run_inspect.returncode != 0: 272 | inspect_data = None 273 | except FileNotFoundError: 274 | inspect_data = None 275 | 276 | if inspect_data: 277 | container_inspect_raw = inspect_data 278 | break 279 | 280 | if not container_inspect_raw: 281 | print("Container with specified ID does not exits!") 282 | exit(3) 283 | 284 | if opts["JsonFile"]: 285 | if opts["JsonFile"] == "-": 286 | container_inspect_raw = sys.stdin.read() 287 | else: 288 | import os.path 289 | 290 | if os.path.isfile(opts["JsonFile"]): 291 | with open(opts["JsonFile"], "r") as f: 292 | container_inspect_raw = f.read() 293 | else: 294 | print("Json file does not exists!") 295 | exit(3) 296 | 297 | if (not opts["JsonFile"]) and (not opts["ContainerID"]): 298 | try: 299 | container_inspect_raw = sys.stdin.read() 300 | except Exception as e: 301 | print("Couldn't parse inspect data from stdin:", e) 302 | exit(3) 303 | 304 | try: 305 | engine_helper = parse.get_engine_helper( 306 | container_inspect_raw, opts["ContainerEngine"] 307 | ) 308 | except Exception as e: 309 | print("Couldn't parse inspect data:", e) 310 | exit(3) 311 | container_inspect = engine_helper.parse_inspect(container_inspect_raw) 312 | container_devices = engine_helper.get_devices(container_inspect) 313 | container_mounts = engine_helper.get_mounts(container_inspect) 314 | container_ports = engine_helper.get_ports(container_inspect) 315 | 316 | # Append allow rules if AVCs log is provided 317 | append_rules = None 318 | if opts["FileAVCS"]: 319 | import os.path 320 | 321 | if os.path.isfile(opts["FileAVCS"]): 322 | with open(opts["FileAVCS"], "r") as f: 323 | try: 324 | append_rules = parse_avc_file(f.read()) 325 | except Exception as e: 326 | print("Couldn't parse AVC file:", e) 327 | exit(3) 328 | f.close() 329 | else: 330 | print("AVC file does not exists!") 331 | exit(3) 332 | 333 | container_caps = [] 334 | 335 | container_caps = sorted(engine_helper.get_caps(container_inspect, opts)) 336 | 337 | try: 338 | create_policy( 339 | opts, 340 | container_caps, 341 | container_devices, 342 | container_mounts, 343 | container_ports, 344 | append_rules, 345 | engine_helper.container_engine, 346 | ) 347 | except Exception as e: 348 | print("Couldn't create policy:", e) 349 | exit(4) 350 | 351 | print("\nPolicy " + opts["ContainerName"] + " created!") 352 | 353 | if opts["Ansible"]: 354 | generate_playbook(opts) 355 | else: 356 | load_policy(opts) 357 | 358 | print( 359 | '\nRestart the container with: "--security-opt label=type:' 360 | + opts["ContainerName"] 361 | + '.process" parameter' 362 | ) 363 | 364 | 365 | if __name__ == "__main__": 366 | main() 367 | -------------------------------------------------------------------------------- /udica/ansible/deploy-module.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: all 3 | tasks: 4 | - name: Include variables from generated file 5 | include_vars: 6 | file: variables-deploy-module.yml 7 | 8 | - name: Ensure that all SELinux packages are installed 9 | package: 10 | name: "{{ item }}" 11 | state: present 12 | with_items: 13 | - container-selinux 14 | - policycoreutils 15 | - libselinux-utils 16 | 17 | - name: Copy SELinux policy generated by the udica 18 | copy: 19 | src: "{{ archive }}" 20 | dest: /var/lib/udica/policy/ 21 | 22 | - name: Extract SELinux policy templates on nodes 23 | unarchive: 24 | src: "{{ archive }}" 25 | dest: /var/lib/udica/policy/ 26 | 27 | - name: Load SELinux policy templates 28 | when: ansible_selinux['status'] == "enabled" 29 | shell: semodule -i {{ policy }} 30 | args: 31 | chdir: /var/lib/udica/policy/ 32 | 33 | - name: Verify that SELinux policy generated by the udica is loaded 34 | when: ansible_selinux['status'] == "enabled" 35 | shell: semodule -lfull | grep "{{ final_policy }}" 36 | register: diff_cmd 37 | failed_when: diff_cmd.rc == "1" 38 | changed_when: false 39 | -------------------------------------------------------------------------------- /udica/confined_user.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2023 Vit Mojzis, 2 | # 3 | # This program is free software; you can redistribute it and/or 4 | # modify it under the terms of the GNU General Public License as 5 | # published by the Free Software Foundation; either version 2 of 6 | # the License, or (at your option) any later version. 7 | # 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU General Public License 14 | # along with this program. If not, see . 15 | 16 | MACRO_CALLS = { 17 | "admin_commands": ( 18 | "(call confinedom_admin_commands_macro ({}))", 19 | ("_t", "_r", "_sudo_t"), 20 | ), 21 | "graphical_login": ( 22 | "(call confinedom_graphical_login_macro ({}))", 23 | ("_t", "_r", "_dbus_t"), 24 | ), 25 | "mozilla_usage": ("(call confinedom_mozilla_usage_macro ({}))", ("_t", "_r")), 26 | "networking": ("(call confinedom_networking_macro ({}))", ("_t", "_r")), 27 | "security_advanced": ( 28 | "(call confinedom_security_advanced_macro ({}))", 29 | ("_t", "_r", "_sudo_t", "_userhelper_t"), 30 | ), 31 | "security_basic": ("(call confinedom_security_basic_macro ({}))", ("_t", "_r")), 32 | "sudo": ( 33 | "(call confinedom_sudo_macro ({}))", 34 | ("_t", "_r", "_sudo_t", "_sudo_tmp_t"), 35 | ), 36 | "user_login": ( 37 | "(call confinedom_user_login_macro ({}))", 38 | ("_t", "_r", "_gkeyringd_t", "_dbus_t", "_exec_content"), 39 | ), 40 | "ssh_connect": ( 41 | "(call confined_ssh_connect_macro ({}))", 42 | ("_t", "_r", "_ssh_agent_t"), 43 | ), 44 | "basic_commands": ("(call confined_use_basic_commands_macro ({}))", ("_t", "_r")), 45 | } 46 | 47 | TYPE_DEFS = { 48 | "_t": "(type {}_t)", 49 | "_r": "(role {}_r)", 50 | "_dbus_t": "(type {}_dbus_t)", 51 | "_gkeyringd_t": "(type {}_gkeyringd_t)", 52 | "_ssh_agent_t": "(type {}_ssh_agent_t)", 53 | "_sudo_t": "(type {}_sudo_t)", 54 | "_sudo_tmp_t": "(type {}_sudo_tmp_t)", 55 | "_userhelper_t": "(type {}_userhelper_t)", 56 | "_exec_content": "(boolean {}_exec_content true)", 57 | } 58 | 59 | 60 | def create_confined_user_policy(opts): 61 | # MCS/MLS range handling - needs to be separated into up-to 4 parts 62 | # s0-s15:c0.c1023 -> (userrange {uname}_u ((s0 ) (s15 (range c0 c1023)))) 63 | # s0:c0 -> (userrange {uname}_u ((s0 ) (s0 (c0)))) 64 | mls_range = opts["range"] 65 | mcs_range = "" 66 | # separate MCS portion 67 | if ":" in opts["range"]: 68 | # s0:c0.c1023 69 | (mls_range, mcs_range) = opts["range"].split(":") 70 | if "-" in mls_range: 71 | # s0-s15 72 | (range_l, range_h) = mls_range.split("-") 73 | else: 74 | # s0 75 | range_l = mls_range 76 | range_h = range_l 77 | if mcs_range != "": 78 | if "." in mcs_range: 79 | # s0:c0.c1023 -> (userrange {uname}_u ((s0 ) (s0 (range c0 c1023)))) 80 | (mcs_range_l, mcs_range_h) = mcs_range.split(".") 81 | mcs_range = "(range {} {})".format(mcs_range_l, mcs_range_h) 82 | else: 83 | # s0:c0 -> (userrange {uname}_u ((s0 ) (s0 (c0)))) 84 | mcs_range = "({})".format(mcs_range) 85 | 86 | range = "({} ) ({} {})".format(range_l, range_h, mcs_range) 87 | 88 | defs = set() 89 | 90 | policy = """ 91 | (user {uname}_u) 92 | (userrole {uname}_u {uname}_r) 93 | (userlevel {uname}_u ({level})) 94 | (userrange {uname}_u ({range})) 95 | """.format( 96 | uname=opts["uname"], level=opts["level"], range=range 97 | ) 98 | 99 | # process arguments determining which macros are to be used 100 | for arg, value in opts.items(): 101 | if not value or arg not in MACRO_CALLS.keys(): 102 | continue 103 | for param in MACRO_CALLS[arg][1]: 104 | defs.add(TYPE_DEFS[param].format(opts["uname"])) 105 | policy += "\n" + ( 106 | MACRO_CALLS[arg][0].format( 107 | " ".join([opts["uname"] + s for s in MACRO_CALLS[arg][1]]) 108 | ) 109 | ) 110 | # print("{}: {}".format(arg, value)) 111 | 112 | policy = "\n".join(sorted(defs)) + policy 113 | 114 | with open("{}.cil".format(opts["uname"]), "w") as f: 115 | f.write(policy) 116 | 117 | print("Created {}.cil".format(opts["uname"])) 118 | print("Run the following commands to apply the new policy:") 119 | print("Install the new policy module") 120 | print( 121 | "# semodule -i {}.cil /usr/share/udica/macros/confined_user_macros.cil".format( 122 | opts["uname"] 123 | ) 124 | ) 125 | print("Create a default context file for the new user") 126 | print( 127 | "# sed -e ’s|user|{}|g’ /etc/selinux/targeted/contexts/users/user_u > /etc/selinux/targeted/contexts/users/{}_u".format( 128 | opts["uname"], opts["uname"] 129 | ) 130 | ) 131 | print("Map the new selinux user to an existing user account") 132 | print("# semanage login -a -s {}_u {}".format(opts["uname"], opts["uname"])) 133 | print("Fix labels in the user's home directory") 134 | print("# restorecon -RvF /home/{}".format(opts["uname"])) 135 | -------------------------------------------------------------------------------- /udica/man/man8/udica.8: -------------------------------------------------------------------------------- 1 | .\" Copyright (C) 2018 Lukas Vrabec, 2 | .\" 3 | .\" This program is free software: you can redistribute it and/or modify 4 | .\" it under the terms of the GNU General Public License as published by 5 | .\" the Free Software Foundation, either version 3 of the License, or 6 | .\" (at your option) any later version. 7 | .\" 8 | .\" This program is distributed in the hope that it will be useful, 9 | .\" but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | .\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | .\" GNU General Public License for more details. 12 | .\" 13 | .\" You should have received a copy of the GNU General Public License 14 | .\" along with this program. If not, see . 15 | 16 | .\" A man page for udica. 17 | .\" Contact lvrabec@redhat.com to report errors or typos. 18 | .TH man 8 "17 February 2019" "1.1" "udica man page" 19 | 20 | .SH NAME 21 | udica \- a tool for generating SELinux security profiles for containers. 22 | 23 | .SH SYNOPSIS 24 | udica [options] container_name 25 | 26 | .SH DESCRIPTION 27 | A tool for generating SELinux security profiles for containers. The whole concept is based on the "block inheritance" feature inside the CIL intermediate language supported by the SELinux user space. The tool creates a policy which combines rules inherited from specified CIL blocks (templates) and rules discovered by inspection of the container JSON file with mount points and port definitions. 28 | 29 | .SH SUPPORTED CONTAINER ENGINES 30 | CRI-O v1.14.10+ 31 | docker v1.13+ 32 | podman v2.0+, 33 | 34 | .SH OPTIONS 35 | .TP 36 | .I \-h, \-\-help 37 | Show this help message and exit 38 | 39 | .TP 40 | .I \-i, \-\-container\-id ID 41 | An ID of the running container for which should be an SELinux policy created 42 | 43 | .TP 44 | .I \-j, \-\-json JSONFILE 45 | Load JSON content of the inspected container from this file 46 | 47 | .TP 48 | .I \-l, \-\-load\-modules 49 | Load templates and module created by this tool 50 | 51 | .TP 52 | .I \-c, \-\-caps CAPS 53 | List of capabilities, for example: "\-c AUDIT\_WRITE,CHOWN,DAC\_OVERRIDE,FOWNER,FSETID,KILL" 54 | (mandatory to use for Docker Engine, see the BUGS section) 55 | 56 | .TP 57 | .I \-\-devices DEVS 58 | List of devices the container should have access to, e.g "\-\-devices /dev/dri/card0,/dev/dri/renderD128" 59 | (overrides devices specified in the conatiner JSON) 60 | 61 | .TP 62 | .I \-a, \-\-append-rules FILE 63 | Append more SELinux allow rules generated from SELinux denials in audit daemon. 64 | 65 | .TP 66 | .I \-s, \-\-stream-connect DOMAIN 67 | Allow container to stream connect with given SELinux domain. 68 | 69 | .TP 70 | .I \-e, \-\-container-engine ENGINE 71 | Specify which container engine is used for the inspected container (supports: CRI-O, docker, podman) 72 | 73 | .TP 74 | .I \-\-full\-network\-access 75 | Allow a container full network access 76 | 77 | .TP 78 | .I \-\-tty\-access 79 | Allow a container to read and write the controlling terminal 80 | 81 | .TP 82 | .I \-\-X\-access 83 | Allow a container to communicate with the X server 84 | 85 | .TP 86 | .I \-\-virt\-access 87 | Allow a container to communicate with libvirt 88 | 89 | .SH EXIT STATUS 90 | .TP 91 | .B 0 92 | no errors encountered. 93 | .TP 94 | .B 1 95 | other errors. 96 | .TP 97 | .B 2 98 | error while parsing options. 99 | .TP 100 | .B 3 101 | error while getting container info. 102 | .TP 103 | .B 4 104 | error while creating an SELinux policy. 105 | 106 | .SH EXAMPLES 107 | .nf 108 | # cat my_con.json | udica \-\-x\-access \-\-full\-network\-access my_container 109 | Creates a new SELinux policy with name my_container based on inspecting container and adding access to the X server and full network access. 110 | 111 | .SH SEE ALSO 112 | .BR selinux(8), 113 | .BR podman(1) 114 | 115 | .SH BUGS 116 | Since it is not possible to detect capabilities used by a container in Docker Engine, you have to use '-c' to specify capabilities for docker container manually. 117 | 118 | It is not possible to generate a custom local policy using the "audit2allow -M" command from AVCs where source context was generated by udica. For this purpose please use '--append-rules' option. 119 | 120 | In some situations udica fails to identify which container engine is used, therefore "--container-engine" parameter has to be used to inform udica how JSON inspection file should be parsed. 121 | 122 | .SH REPORTING BUGS 123 | Report bugs to 124 | 125 | .SH AUTHOR 126 | Written by Lukas Vrabec (lvrabec@redhat.com) 127 | -------------------------------------------------------------------------------- /udica/parse.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2018 Lukas Vrabec, 2 | # 3 | # This program is free software: you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation, either version 3 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU General Public License 14 | # along with this program. If not, see . 15 | 16 | import abc 17 | import json 18 | 19 | #: Constant for the podman engine 20 | ENGINE_PODMAN = "podman" 21 | 22 | #: Constant for the cri-o engine 23 | ENGINE_CRIO = "CRI-O" 24 | 25 | #: Constant for the docker engine 26 | ENGINE_DOCKER = "docker" 27 | 28 | #: Constant for the containerd engine 29 | ENGINE_CONTAINERD = "containerd" 30 | 31 | #: All supported engines 32 | ENGINE_ALL = [ENGINE_PODMAN, ENGINE_CRIO, ENGINE_DOCKER, ENGINE_CONTAINERD] 33 | 34 | 35 | # Decorator for verifying that getting value from "data" won't 36 | # result in Key error or Type error 37 | # e.g. in data[0]["HostConfig"]["Devices"] 38 | # missing "HostConfig" key in data[0] produces KeyError and 39 | # data[0]["HostConfig"] == none produces TypeError 40 | def getter_decorator(function): 41 | # Verify that each element in path exists and return the corresponding value, 42 | # otherwise return [] -- can be safely processed by iterators 43 | def wrapper(self, data, *args): 44 | try: 45 | value = function(self, data, *args) 46 | return value if value else [] 47 | except (KeyError, TypeError): 48 | return [] 49 | 50 | return wrapper 51 | 52 | 53 | def json_is_list(json_rep): 54 | """Check if the inspected file is in a format from docker or podman. 55 | 56 | We know this because the type in the inspect command will be a list 57 | """ 58 | return isinstance(json_rep, list) 59 | 60 | 61 | def json_is_containerd_format(json_rep): 62 | """Check if the inspected file is in a format from containerd.""" 63 | return ( 64 | isinstance(json_rep, list) 65 | and isinstance(json_rep[0], dict) 66 | and ("containerd" in json_rep[0].get("Runtime", {}).get("Name", "")) 67 | ) 68 | 69 | 70 | def json_is_podman_format(json_rep): 71 | """Check if the inspected file is in a format from podman.""" 72 | return isinstance(json_rep, list) and ( 73 | "container=oci" in json_rep[0]["Config"]["Env"] 74 | or "container=podman" in json_rep[0]["Config"]["Env"] 75 | ) 76 | 77 | 78 | def get_engine_helper(data, ContainerEngine): 79 | engine = validate_container_engine(ContainerEngine) 80 | if engine == "-": 81 | json_rep = json.loads(data) 82 | if json_is_list(json_rep): 83 | if json_is_containerd_format(json_rep): 84 | return ContainerdHelper() 85 | elif json_is_podman_format(json_rep): 86 | return PodmanHelper() 87 | return DockerHelper() 88 | else: 89 | return CrioHelper() 90 | else: 91 | if engine == ENGINE_DOCKER: 92 | return DockerHelper() 93 | elif engine == ENGINE_PODMAN: 94 | return PodmanHelper() 95 | elif engine == ENGINE_CRIO: 96 | return CrioHelper() 97 | elif engine == ENGINE_CONTAINERD: 98 | return ContainerdHelper() 99 | raise RuntimeError("Unkown engine") 100 | 101 | 102 | class EngineHelper(abc.ABC): 103 | def __init__(self, container_engine): 104 | self.container_engine = container_engine 105 | 106 | def parse_inspect(self, data): 107 | return json.loads(data) 108 | 109 | @abc.abstractmethod 110 | def get_devices(self, data): 111 | raise NotImplementedError( 112 | "Error getting devices from unknown format %s" % self.container_engine 113 | ) 114 | 115 | @abc.abstractmethod 116 | def get_mounts(self, data): 117 | raise NotImplementedError( 118 | "Error getting mounts from unknown format %s" % self.container_engine 119 | ) 120 | 121 | @abc.abstractmethod 122 | def get_ports(self, data): 123 | raise NotImplementedError( 124 | "Error getting ports from unknown format %s" % self.container_engine 125 | ) 126 | 127 | def get_caps(self, data, opts): 128 | if opts["Caps"]: 129 | if opts["Caps"] in ["None", "none"]: 130 | return [] 131 | return opts["Caps"].split(",") 132 | return [] 133 | 134 | 135 | class PodmanDockerHelper(EngineHelper): 136 | @getter_decorator 137 | def get_devices(self, data): 138 | return data[0]["HostConfig"]["Devices"] 139 | 140 | @getter_decorator 141 | def get_mounts(self, data): 142 | return data[0]["Mounts"] 143 | 144 | @getter_decorator 145 | def get_ports(self, data): 146 | ports = [] 147 | for key, value in data[0]["NetworkSettings"]["Ports"].items(): 148 | container_port = str(key).split("/") 149 | new_port = { 150 | "portNumber": int(container_port[0]), 151 | "protocol": container_port[1], 152 | } 153 | ports.append(new_port) 154 | return ports 155 | 156 | 157 | class PodmanHelper(PodmanDockerHelper): 158 | def __init__(self): 159 | super().__init__(ENGINE_PODMAN) 160 | 161 | @getter_decorator 162 | def get_caps(self, data, opts): 163 | if opts["Caps"]: 164 | return ( 165 | opts["Caps"].split(",") if opts["Caps"] not in ["None", "none"] else [] 166 | ) 167 | else: 168 | return data[0]["EffectiveCaps"] 169 | return [] 170 | 171 | 172 | class DockerHelper(PodmanDockerHelper): 173 | def __init__(self): 174 | super().__init__(ENGINE_DOCKER) 175 | 176 | def parse_inspect(self, data): 177 | json_rep = super().parse_inspect(data) 178 | self.adjust_json_from_docker(json_rep) 179 | return json_rep 180 | 181 | def adjust_json_from_docker(self, json_rep): 182 | """If the json comes from a docker call, we need to adjust it to make use 183 | of it.""" 184 | try: 185 | if not isinstance(json_rep[0]["NetworkSettings"]["Ports"], dict): 186 | raise Exception( 187 | "Error parsing docker engine inspection JSON structure, try to specify container engine using '--container-engine' parameter" 188 | ) 189 | except (KeyError, TypeError): 190 | # "Ports" not specified in given json file 191 | pass 192 | 193 | try: 194 | for item in json_rep[0]["Mounts"]: 195 | item["source"] = item["Source"] 196 | if item["Mode"] == "rw": 197 | item["options"] = "rw" 198 | if item["Mode"] == "ro": 199 | item["options"] = "ro" 200 | except (KeyError, TypeError): 201 | # "Mounts" not specified in given json file 202 | pass 203 | 204 | 205 | class CrioHelper(EngineHelper): 206 | def __init__(self): 207 | super().__init__(ENGINE_CRIO) 208 | 209 | def get_devices(self, data): 210 | # Not applicable in the CRI-O case, since this is handled by the 211 | # bind mounting device on the container 212 | return [] 213 | 214 | @getter_decorator 215 | def get_mounts(self, data): 216 | return data["status"]["mounts"] 217 | 218 | def get_ports(self, data): 219 | # Not applicable in the CRI-O case, since this is handled by the 220 | # kube-proxy/CNI. 221 | return [] 222 | 223 | 224 | class ContainerdHelper(EngineHelper): 225 | def __init__(self): 226 | super().__init__(ENGINE_CONTAINERD) 227 | 228 | @getter_decorator 229 | def get_devices(self, data): 230 | # Copy "path" attribute to "PathOnHost" 231 | # since that is what other container engines are using 232 | devices = [] 233 | for device in data[0]["Spec"]["linux"]["devices"]: 234 | path = device.get("path", None) 235 | if path: 236 | device["PathOnHost"] = path 237 | devices.append(device) 238 | 239 | return devices 240 | 241 | @getter_decorator 242 | def get_mounts(self, data): 243 | return data[0]["Spec"]["mounts"] 244 | 245 | @getter_decorator 246 | def get_ports(self, data): 247 | ports = [] 248 | # nerdctl/ports is a json string which needs to be parsed 249 | for port in json.loads(data[0]["Labels"]["nerdctl/ports"]): 250 | new_ports = {"portNumber": port["HostPort"], "protocol": port["Protocol"]} 251 | ports.append(new_ports) 252 | return ports 253 | 254 | @getter_decorator 255 | def get_caps(self, data, opts): 256 | if opts["Caps"]: 257 | if opts["Caps"] in ["None", "none"]: 258 | return [] 259 | return opts["Caps"].split(",") 260 | return data[0]["Spec"]["process"]["capabilities"]["effective"] 261 | 262 | 263 | def parse_cap(data): 264 | return data.decode().split("\n")[1].split(",") 265 | 266 | 267 | def context_to_type(context): 268 | return context.split("=")[1].split(":")[2] 269 | 270 | 271 | def remove_dupe_perms(string): 272 | perms = string.split() 273 | return " ".join(sorted(set(perms), key=perms.index)) 274 | 275 | 276 | def parse_avc_file(data): 277 | append_rules = [] 278 | 279 | for avc in data.splitlines(): 280 | new_rule = [] 281 | items = avc.split(" ") 282 | 283 | if "type=AVC" not in items[0]: 284 | continue 285 | 286 | for item in items: 287 | if "scontext" in item: 288 | new_rule.append(context_to_type(item)) 289 | if "tcontext" in item: 290 | new_rule.append(context_to_type(item)) 291 | if "tclass" in item: 292 | new_rule.append(item.split("=")[1]) 293 | 294 | open_bracket = items.index("{") 295 | perm = open_bracket + 1 296 | new_rule.append(items[perm]) 297 | 298 | for rule in append_rules: 299 | if ( 300 | rule[0] == new_rule[0] 301 | and rule[1] == new_rule[1] 302 | and rule[2] == new_rule[2] 303 | ): 304 | new_rule[3] = rule[3] + " " + new_rule[3] 305 | append_rules.remove(rule) 306 | new_rule[3] = remove_dupe_perms(new_rule[3]) 307 | append_rules.append(new_rule) 308 | 309 | return append_rules 310 | 311 | 312 | def validate_container_engine(ContainerEngine): 313 | if ContainerEngine in ENGINE_ALL + ["CRIO", "-"]: 314 | # Fix CRIO reference to use ENGINE_CRIO 315 | if ContainerEngine == "CRIO": 316 | return ENGINE_CRIO 317 | return ContainerEngine 318 | else: 319 | raise Exception("Container Engine %s is not supported." % ContainerEngine) 320 | -------------------------------------------------------------------------------- /udica/perms.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2018 Lukas Vrabec, 2 | # 3 | # This program is free software: you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation, either version 3 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU General Public License 14 | # along with this program. If not, see . 15 | 16 | perm = { 17 | "device_rw": "getattr read write append ioctl lock open", 18 | "dir_rw": "add_name create getattr ioctl lock open read remove_name rmdir search setattr write", 19 | "dir_ro": "getattr ioctl lock open read search", 20 | "file_rw": "append create getattr ioctl lock map open read rename setattr unlink write", 21 | "file_ro": "getattr ioctl lock open read", 22 | "fifo_rw": "getattr read write append ioctl lock open", 23 | "fifo_ro": "getattr open read lock ioctl", 24 | "socket_rw": "append getattr open read write", 25 | "socket_ro": "getattr open read", 26 | } 27 | 28 | socket = {"tcp": "tcp_socket", "udp": "udp_socket", "sctp": "sctp_socket"} 29 | -------------------------------------------------------------------------------- /udica/version.py: -------------------------------------------------------------------------------- 1 | version = "0.2.8" 2 | --------------------------------------------------------------------------------