# vim: ft=apparmor
#------------------------------------------------------------------
#    Copyright (C) 2024 Canonical Ltd.
#    Copyright (C) 2026 Christian Boltz
#
#    This program is free software; you can redistribute it and/or
#    modify it under the terms of version 2 of the GNU General Public
#    License published by the Free Software Foundation.
#------------------------------------------------------------------
abi <abi/5.0>,

include <tunables/global>

profile wg-quick /usr/bin/wg-quick flags=(attach_disconnected) {
  include <abstractions/base>
  include <abstractions/consoles>

  capability dac_read_search,
  capability net_admin,

  # Network access rules
  network netlink raw,
  network unix stream,

  # use wg aa profile
  file mrpx /usr/bin/wg -> wg,

  # binaries called from within wg-quick
  file mrix /usr/bin/readlink,
  file mrix /usr/bin/stat,
  file mrix /usr/bin/cat,
  file mrix /usr/bin/rm,
  file mrix /usr/bin/mv,
  file mrix /usr/bin/sync,
  file mrix /usr/bin/sort,
  file mrix /usr/sbin/xtables-nft-multi,
  file mrix /usr/bin/resolvectl,
  file mrix /usr/sbin/resolvconf,
  file PUx /usr/bin/systemd-creds,

  # dbus access
  file rw @{run}/dbus/system_bus_socket,

  dbus (send)
      bus=system
      path=/org/freedesktop/resolve1
      interface=org.freedesktop.resolve1.Manager
      member="SetLink{DNSEx,Domains}"
      peer=(name=org.freedesktop.resolve1, label=unconfined),

  dbus (send)
      bus=system
      path=/org/freedesktop/DBus
      interface=org.freedesktop.DBus
      member="Hello"
      peer=(name=org.freedesktop.DBus, label=unconfined),

  # Sub-profile for nft tool restrictions
  file mrCx /usr/sbin/nft,
  profile nft /usr/sbin/nft {
    include <abstractions/base>

    capability net_admin,

    # Allow executable mapping and read for the binary
    file mr /usr/sbin/nft,

    # Network access rules
    network netlink raw,

    file r /usr/share/iproute2/rt_realms,
    file r /usr/share/iproute2/group,
  }

  # Sub-profile for IP tool restrictions
  file mrCx /usr/{s,}bin/ip -> ip,
  profile ip {
    include <abstractions/base>

    capability net_admin,
    capability sys_module,

    /usr/lib*/glibc-hwcaps/x86-64-v3/libz.so.*    mr,
    /usr/lib*/glibc-hwcaps/x86-64-v3/libzstd.so.* mr,

    # Allow executable mapping and read for the binary
    file mr /usr/{s,}bin/ip,

    # Network access rules
    network netlink raw,

    file r /usr/share/iproute2/group,
    file r /usr/share/iproute2/rt_tables,
    file r @{run}/netns/{,**},
  }

  # Sub-profile for sysctl tool restrictions
  file mrCx /usr/sbin/sysctl,
  profile sysctl /usr/sbin/sysctl {
    include <abstractions/base>

    # Allow executable mapping and read for the binary
    file mr /usr/sbin/sysctl,

    file w @{PROC}/sys/net/ipv4/conf/all/src_valid_mark,
  }

  # wireguard configuration and key files
  file rw @{etc_rw}/wireguard/{,**},

  # Allow executable mapping and read for the binary
  file mr @{exec_path},

  # Process-specific access
  file r @{PROC}/@{pid}/net/ip_tables_names,


  # alts (actually /usr/sbin/iptables-save)
  /usr/bin/alts Cx -> wg-quick//alts,
  profile alts {
    include <abstractions/base>

    /usr/bin/alts r,

    /usr/share/libalternatives/ r,
    /usr/share/libalternatives/ip6tables-save/ r,
    /usr/share/libalternatives/ip6tables-save/*.conf r,
    /usr/share/libalternatives/iptables-save/ r,
    /usr/share/libalternatives/iptables-save/*.conf r,

    /usr/sbin/xtables-nft-multi Px -> wg-quick//xtables-nft-multi,
  }

  profile xtables-nft-multi {
    include <abstractions/base>

    capability net_admin,

    @{PROC}/@{pid}/net/ip_tables_names r,
    @{PROC}/@{pid}/net/ip6_tables_names r,

    /usr/sbin/xtables-nft-multi r,
  }


  # DNS= option if using https://git.zx2c4.com/wireguard-tools/tree/contrib/dns-hatchet/hatchet.bash uses unshare, mount etc. to bind-mount /etc/resolv.conf
  @{PROC}/@{pid}/cgroup r,
  /usr/bin/unshare Cx -> unshare,

  profile unshare {
    include <abstractions/base>

    capability sys_admin,

    /{usr/,}bin/bash Px -> wg-quick//unshare-bash,
    /usr/bin/unshare r,
  }

  profile unshare-bash {
    include <abstractions/base>

    /{usr/,}bin/bash r,
    /{usr/,}bin/cat rix,
    /{usr/,}bin/mount Px -> wg-quick//unshare-mount,
    /{usr/,}bin/stat rix,

    /{usr/,}lib/bash/ r,

    /etc/ r,
    /etc/resolv.conf r,

    /dev/shm/resolv.conf w, # r needed?
    /dev/tty rw,

    @{PROC}/filesystems r,
  }

  profile unshare-mount {
    include <abstractions/base>

    capability sys_admin,

    /{usr/,}bin/mount r,

    / r,
    /etc/fstab r,

    @{run}/mount/utab r,

    @{PROC}/@{pid}/mountinfo r,
    @{PROC}/filesystems r,

    /dev/shm/ r,
  }


  # umount private /dev/shm/ on VPN shutdown
  /{usr/,}bin/umount Cx -> umount,
  profile umount {
    capability sys_admin,

    /{usr/,}bin/umount r,

    @{run}/mount/utab r,
    @{run}/mount/utab.act wk,
    @{run}/mount/utab.lock rwk,
    @{run}/netconfig/resolv.conf r,

    @{PROC}/@{pid}/mountinfo r,
    @{PROC}/filesystems r,
  }


  # Site-specific additions and overrides. See local/README for details.
  include if exists <local/wg-quick>
}
