# apparmor.d - Full set of apparmor profiles
# Copyright (C) 2022 Jeroen Rijken
# SPDX-License-Identifier: GPL-2.0-only

abi <abi/4.0>,

include <tunables/global>

@{exec_path} = /{usr/,}{local/,}bin/k3s
@{att} = /att/k3s/
profile k3s /{usr/,}{local/,}bin/k3s  flags=(attach_disconnected,attach_disconnected.path=@{att},complain) {
  include <abstractions/attached/base>
  include <abstractions/disks-read>
  include <abstractions/nameservice-strict>
  include <abstractions/ssl_certs>

  capability chown,
  capability kill,
  capability dac_override,
  capability dac_read_search,
  capability fsetid,
  capability fowner,
  capability net_admin,
  capability syslog,
  capability sys_admin,
  capability sys_ptrace,
  capability sys_resource,

  ptrace peer=@{profile_name},
  ptrace (read) peer={cni-calico-node,cri-containerd.apparmor.d,cni-xtables-nft,ip,kmod,kubernetes-pause,mount,unconfined},

  # k3s requires ptrace to all AppArmor profiles loaded in Kubernetes.
  # For simplification, let's assume for now all AppArmor profiles start with a predefined prefix.
  ptrace (read) peer=container-*,
  ptrace (read) peer=docker-*,
  ptrace (read) peer=k3s-*,
  ptrace (read) peer=kubernetes-*,
  # When using ZFS as storage provider instead of the default overlay2.
  ptrace (read) peer=zfs,
  ptrace (read) peer=zpool,

  network inet dgram,
  network inet6 dgram,
  network inet stream,
  network inet6 stream,
  network netlink raw,

  mount -> /var/lib/kubelet/pods/@{uuid}/volumes/kubernetes.io~*/{,**/},
  mount -> /var/lib/kubelet/pods/@{uuid}/volume-subpaths/{,**},

  umount /var/lib/kubelet/pods/@{uuid}/volumes/kubernetes.io~*/{,**/},
  umount /var/lib/kubelet/pods/@{uuid}/volume-subpaths/{,**},

  signal (send, receive) set=term,
  signal (send) set=kill peer=unconfined,

  unix (bind,listen) type=stream addr=@xtables,

  @{exec_path} mr,

  @{bin}/kmod rpx,
  @{bin}/mount rpx,
  @{bin}/systemd-run rix,
  @{bin}/{nano,emacs,ed} rpux,
  @{bin}/vim{,.basic} rpux,
  @{sbin}/xtables-nft-multi rpx -> cni-xtables-nft,

  @{lib}/kubernetes/kubelet-plugins/volume/exec/nodeagent~uds/uds rix,
  /var/lib/rancher/k3s/data/@{hex}/bin/* rix,

  @{lib}/kubernetes/kubelet-plugins/volume/exec/{,**} r,

  /etc/machine-id r,
  /etc/rancher/{,**} rw,

  /var/lib/kubelet/{,**} rw,
  /var/lib/rancher/{,**} rw,
  /var/lib/rancher/k3s/data/.lock rwk,
  /var/lib/rancher/k3s/server/db/{,**} rwk,

  /var/log/containers/ r,
  /var/log/containers/** rw,
  /var/log/rancher/{,**} r,
  /var/log/kubelet/{,**} r,
  /var/log/kubernetes/{,**} r,
  /var/log/kubernetes/audit/** rw,
  /var/log/pods/{,**} r,
  /var/log/pods/{,**/} rw,
  /var/log/pods/**/@{int}.log{,*} rw,

  owner @{HOME}/.kube/** rw,

  @{run}/containerd/containerd.sock rw,
  @{run}/systemd/notify w,
  @{run}/systemd/private rw,
  @{run}/systemd/resolve/resolv.conf r,
  @{run}/nodeagent/ rw,
  @{run}/xtables.lock rwk,

  owner /var/tmp/** rwkl,
  owner @{tmp}/** rwkl,

  owner @{PROC}/@{pids}/cgroup r,
  owner @{PROC}/@{pids}/cpuset r,
        @{PROC}/@{pids}/fd/ r,
        @{PROC}/@{pids}/limits r,
  owner @{PROC}/@{pids}/mounts r,
  owner @{PROC}/@{pids}/mountinfo r,
        @{PROC}/@{pids}/net/dev r,
        @{PROC}/@{pids}/net/ip_tables_names r,
  owner @{PROC}/@{pids}/net/ipv6_route r,
  owner @{PROC}/@{pids}/net/route r,
  owner @{PROC}/@{pids}/oom_score_adj rw,
  owner @{PROC}/@{pids}/stat r,
  owner @{PROC}/@{pids}/uid_map r,

        @{PROC}/diskstats r,
        @{PROC}/loadavg r,
        @{PROC}/modules r,
        @{PROC}/sys/fs/pipe-max-size r,
        @{PROC}/sys/kernel/keys/* r,
        @{PROC}/sys/kernel/panic rw,
        @{PROC}/sys/kernel/panic_on_oom rw,
        @{PROC}/sys/kernel/panic_on_oops rw,
        @{PROC}/sys/kernel/pid_max r,
        @{PROC}/sys/kernel/osrelease r,
        @{PROC}/sys/kernel/threads-max r,
        @{PROC}/sys/net/core/somaxconn r,
        @{PROC}/sys/net/ipv{4,6}/conf/all/* rw,
        @{PROC}/sys/net/ipv{4,6}/conf/default/* rw,
        @{PROC}/sys/net/bridge/bridge-nf-call-iptables r,
        @{PROC}/sys/net/netfilter/* rw,
        @{PROC}/sys/vm/panic_on_oom r,

  @{sys}/class/net/ r,

  @{sys}/devices/@{pci}/net/*/{address,mtu,speed} r,
  @{sys}/devices/system/edac/mc/ r,
  @{sys}/devices/system/cpu/cpu@{int}/cache/{,**} r,
  @{sys}/devices/system/cpu/cpu@{int}/topology/{,**} r,
  @{sys}/devices/system/cpu/cpufreq/policy@{int}/cpuinfo_max_freq r,
  @{sys}/devices/system/cpu/present{,/} r,
  @{sys}/devices/system/node/ r,
  @{sys}/devices/system/node/node@{int}/ r,
  @{sys}/devices/system/node/node@{int}/{cpumap,distance,meminfo} r,
  @{sys}/devices/system/node/node@{int}/hugepages/{,**} r,

  @{sys}/devices/virtual/block/*/** r,
  @{sys}/devices/virtual/dmi/id/* r,
  @{sys}/devices/virtual/net/cali@{hex}/{address,mtu,speed} r,
  @{sys}/devices/virtual/net/vxlan.calico/{address,mtu,speed} r,

  @{sys}/fs/cgroup/{,*,*/} r,
  @{sys}/fs/cgroup/cgroup.subtree_control rw,
  @{sys}/fs/cgroup/kubepods/{,**} rw,
  @{sys}/fs/cgroup/system.slice/{,**/} r,
  @{sys}/fs/cgroup/system.slice/k3s.service/* r,
  @{sys}/fs/cgroup/user.slice/ r,
  @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/ r,
  @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user-runtime-dir@@{uid}.service/ r,
  @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/{,**/} r,
  @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/session-@{word}.scope/{,**/} r,

  @{sys}/kernel/mm/hugepages/ r,
  @{sys}/kernel/mm/hugepages/hugepages-*/nr_hugepages r,
  @{sys}/kernel/security/apparmor/profiles r,

  @{sys}/module/apparmor/parameters/enabled r,

  /dev/kmsg r,
  /dev/pts/@{int} rw,

  include if exists <local/k3s>
}

# vim:syntax=apparmor
