polkit

出自 ArchWiki

出自 polkit homepage

polkit 是一个应用程序级别的工具包,用于定义和处理策略,该策略允许非特权进程与特权进程对话:它是一个框架,用于集中决策过程,以授予非特权应用程序访问特权操作的权限。

Polkit 用于控制系统范围内的权限。它为非特权进程与特权进程通信提供了一种有组织的方式。与 sudo 等系统相比,它不会将 root 权限授予整个进程,而是允许对集中式系统策略进行更精细的控制。

Polkit 的工作原理是划定不同的动作,例如运行 GParted,并通过组或名称划定用户,例如 wheel 组的成员。然后,它定义了如何(如果允许)允许这些用户执行这些动作,例如通过输入密码来验证其作为组成员的身份。

安装

安装 polkit 软件包。

认证代理

身份验证代理用于让会话用户证明他们确实是该用户(通过作为用户进行身份验证)或管理用户(通过作为管理员进行身份验证)。polkit 软件包包含 pkttyagent,这是一个文本身份验证代理,用作通用后备。

如果您正在使用图形环境,请确保已安装图形身份验证代理并在登录时自动启动(例如,通过 xinitrc)。

CinnamonDeepinHyprlandGNOMEGNOME FlashbackKDELXDELXQtMATEXfce 已经有一个身份验证代理。在其他桌面环境中,您必须选择以下实现之一


提示: 在继续之前,通过查看进程列表检查您的自动启动配置。例如,使用 pgrep -af polkit-gnome

配置

警告: 不要修改软件包的默认权限文件,因为这些文件可能会在软件包升级时被覆盖。

Polkit 定义可以分为两种

  • 动作 在 XML .policy 文件中定义,这些文件位于 /usr/share/polkit-1/actions 中。每个动作都附带一组默认权限(例如,您需要验证为管理员身份才能使用 GParted 动作)。默认值可以被覆盖,但编辑动作文件不是正确的方法。
  • 授权规则 在 JavaScript .rules 文件中定义。它们位于两个位置
    • 第三方软件包可以使用 /usr/share/polkit-1/rules.d
    • /etc/polkit-1/rules.d 用于本地配置。

Polkit 在 Linux 中现有的权限系统(组成员身份、管理员状态)之上运行,它不会替换它们。.rules 文件指定用户子集,引用动作文件中指定的一个(或多个)动作,并确定这些用户可以在哪些限制下执行这些动作。例如,一个规则文件可以覆盖所有用户在使用 GParted 时需要验证为管理员身份的默认要求,从而确定某些特定用户不需要这样做。另一个示例:完全不允许某个用户使用 GParted。

注意: 这并不排除通过不遵守 polkit 的方式(例如命令行)运行 GParted。因此,polkit 应该用于为非特权用户扩展对特权服务的访问权限,而不是试图限制(半)特权用户的权利。出于安全目的,sudoers 仍然是首选方法。

动作

提示: 要在图形界面中显示 Policykit 动作,请安装 polkit-explorer-gitAUR 软件包。

您可以通过 polkit 使用的动作将取决于您安装的软件包。有些在多个桌面环境中使用(org.freedesktop.*),有些是 DE 特定的(org.gnome.*),有些是特定于单个程序的(org.gnome.gparted.policy)。命令 pkaction 列出 /usr/share/polkit-1/actions 中定义的所有动作,以供快速参考。

为了了解 polkit 可以做什么,以下是一些常用的动作组

  • systemd-logind (org.freedesktop.login1.policy) 由 polkit 监管的动作包括关闭电源、重启、挂起和休眠系统,包括当其他用户可能仍在登录时。
  • udisks (org.freedesktop.udisks2.policy) 由 polkit 监管的动作包括挂载文件系统和解锁加密设备。
  • NetworkManager (org.freedesktop.NetworkManager.policy) 由 polkit 监管的动作包括打开和关闭网络、Wi-Fi 或移动宽带。

每个动作都在 .policy 文件中的 <action> 标签中定义。org.gnome.gparted.policy 包含一个动作,如下所示

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE policyconfig PUBLIC
 "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
 "http://www.freedesktop.org/software/polkit/policyconfig-1.dtd">
<policyconfig>

  <action id="org.gnome.gparted">
    <message>Authentication is required to run the GParted Partition Editor</message>
    <icon_name>gparted</icon_name>
    <defaults>
      <allow_any>auth_admin</allow_any>
      <allow_inactive>auth_admin</allow_inactive>
      <allow_active>auth_admin</allow_active>
    </defaults>
    <annotate key="org.freedesktop.policykit.exec.path">/usr/bin/gparted</annotate>
    <annotate key="org.freedesktop.policykit.exec.allow_gui">true</annotate>
  </action>

</policyconfig>

属性 id 是发送到 D-Bus 的实际命令,message 标签是在需要身份验证时向用户显示的解释,icon_name 顾名思义。

defaults 标签是权限或缺少权限的位置。它包含三个设置:allow_anyallow_inactiveallow_active。这里的 inactive 和 active 都指的是本地控制台或显示器上的本地会话,而 allow_any 设置用于所有其他会话,包括远程会话(SSH、VNC 等)。

对于每个设置,以下选项可用

  • no:用户未被授权执行该动作。因此,不需要身份验证。
  • yes:用户被授权执行该动作,无需任何身份验证。
  • auth_self:需要身份验证,但用户不需要是管理用户。
  • auth_admin:需要以管理用户身份进行身份验证。
  • auth_self_keep:与 auth_self 相同,但与 sudo 类似,授权持续几分钟。
  • auth_admin_keep:与 auth_admin 相同,但与 sudo 类似,授权持续几分钟。

这些是默认设置,除非在以后的配置中被覆盖,否则对所有用户都有效。

有关详细说明,请参阅 polkit(8) man 页面。

从 GParted 动作可以看出,无论会话是活动的还是非活动的,用户都需要验证为管理员身份才能使用 GParted。

授权规则

覆盖默认设置的授权规则布置在如上所述的一组目录中。对于与单个系统的个人配置相关的所有目的,应仅使用 /etc/polkit-1/rules.d

addRule() 方法用于添加一个函数,该函数可以在每次执行动作和主体的授权检查时调用。函数按照添加的顺序调用,直到其中一个函数返回值。因此,要添加一个在其他规则之前处理的授权规则,请将其放在 /etc/polkit-1/rules.d 中的文件中,文件名在其他规则文件之前排序,例如 00-early-checks.rules

.rules 文件的布局非常不言自明

/* Allow users in admin group to run GParted without authentication */
polkit.addRule(function(action, subject) {
    if (action.id == "org.gnome.gparted" &&
        subject.isInGroup("admin")) {
        return polkit.Result.YES;
    }
});

在函数内部,我们检查指定的动作 ID (org.gnome.gparted) 和用户的组 (admin),然后返回值 "yes"。

管理员身份

addAdminRule() 方法用于添加一个函数,该函数可以在需要管理员身份验证时调用。该函数用于指定哪些身份可以用于动作和主体标识的授权检查的管理员身份验证。添加的函数按照添加的顺序调用,直到其中一个函数返回值。

管理员身份的默认配置包含在文件 /usr/share/polkit-1/rules.d/50-default.rules 中,因此对该配置的任何更改都应通过将该文件复制到 /etc/polkit-1/rules.d 目录并编辑该文件来进行

/etc/polkit-1/rules.d/50-default.rules
polkit.addAdminRule(function(action, subject) {
    return ["unix-group:wheel"];
});

唯一要编辑的部分(复制后)是函数的返回数组:当被要求以管理员身份验证时,用户应该以谁的身份进行验证?如果他们是指定为管理员的组的成员,他们只需要输入自己的密码。如果只有其他用户(例如 root)是管理员身份,他们将需要输入 root 密码。用户身份识别的格式与指定权限的格式相同。

Arch 默认设置是将 wheel 组的所有成员设为管理员。如下所示的规则将使 polkit 请求 root 密码而不是用户密码进行管理员身份验证。

/etc/polkit-1/rules.d/49-rootpw_global.rules
/* Always authenticate Admins by prompting for the root
 * password, similar to the rootpw option in sudo
 */
polkit.addAdminRule(function(action, subject) {
    return ["unix-user:root"];
});

示例

允许用户使用 org.freedesktop.timedate1.set-timezone 动作

要允许名为 archie 的用户在无需身份验证的情况下使用 org.freedesktop.timedate1.set-timezone 动作,请以 root 身份创建以下 polkit 规则文件

/etc/polkit-1/rules.d/49-allow-archie-set-timezone.rules
polkit.addRule(function(action, subject) {
    if (action.id == "org.freedesktop.timedate1.set-timezone" &&
        subject.user == "archie") {
        return polkit.Result.YES;
    }
});

保存规则文件后,策略应立即生效。您可以使用 timedatectl 设置时区来测试它

[archie]$ timedatectl set-timezone America/New_York

如果操作完成时没有要求身份验证,则规则按预期工作。如果该动作似乎不允许,请确保 /etc/polkit-1/rules.d/ 中没有优先级更高的冲突规则(前缀编号较低)。

调试/日志

要启用使用 polkit.log() 函数的日志记录,请从 /usr/lib/systemd/system/polkit.service 文件中的 ExecStart 命令中删除 --no-debug 标志。

以下规则记录有关任何请求访问的详细信息

/etc/polkit-1/rules.d/00-log-access.rules
polkit.addRule(function(action, subject) {
    polkit.log("action=" + action);
    polkit.log("subject=" + subject);
});

要手动测试规则,请使用 pkcheck[1]

$ pkcheck -u -p $$ --enable-internal-agent -a action

禁用挂起和休眠

本条目或章节的事实准确性存在争议。

原因: 如果 logind 不可用,systemctl(1) 会回退到直接启动 suspend.target/hibernate.target。要实际禁用 systemd-sleep,应使用电源管理/挂起和休眠#完全禁用睡眠。(在Talk:Polkit中讨论)

以下规则禁用所有用户的挂起和休眠。

/etc/polkit-1/rules.d/10-disable-suspend.rules
polkit.addRule(function(action, subject) {
    if (action.id == "org.freedesktop.login1.suspend" ||
        action.id == "org.freedesktop.login1.suspend-multiple-sessions" ||
        action.id == "org.freedesktop.login1.hibernate" ||
        action.id == "org.freedesktop.login1.hibernate-multiple-sessions")
    {
        return polkit.Result.NO;
    }
});

绕过密码提示

要实现类似于 sudo NOPASSWD 选项的功能,并仅基于用户/组身份获得授权,您可以在 /etc/polkit-1/rules.d/ 中创建自定义规则。这允许您覆盖密码身份验证,可以仅针对特定动作全局地进行覆盖。有关示例规则集,请参见 [2]

全局地

以 root 身份创建以下文件

/etc/polkit-1/rules.d/49-nopasswd_global.rules
/* Allow members of the wheel group to execute any actions
 * without password authentication, similar to "sudo NOPASSWD:"
 */
polkit.addRule(function(action, subject) {
    if (subject.isInGroup("wheel")) {
        return polkit.Result.YES;
    }
});

wheel 替换为您首选的任何组。

这将导致对任何需要管理员权限的操作通过 Polkit 进行自动身份验证。因此,请谨慎选择要授予此类权限的组。

还有 AUTH_ADMIN_KEEP,它允许将授权保持 5 分钟。但是,授权是按进程进行的,因此,如果新进程在 5 分钟内请求授权,则新进程仍会再次要求输入密码。

针对特定动作

以 root 身份创建以下文件

/etc/polkit-1/rules.d/49-nopasswd_limited.rules
/* Allow members of the wheel group to execute the defined actions 
 * without password authentication, similar to "sudo NOPASSWD:"
 */
polkit.addRule(function(action, subject) {
    if ((action.id == "org.gnome.gparted" ||
	 action.id == "org.libvirt.unix.manage") &&
        subject.isInGroup("wheel"))
    {
        return polkit.Result.YES;
    }
});

此处选择的 action.id 只是 GParted 和 Libvirt 的(工作)示例,但是您可以将它们替换为您喜欢的任何其他动作,只要它们存在(自定义或由软件包提供),并且您也可以定义任何组而不是 wheel

|| 运算符用于分隔动作(逻辑 OR),&& 表示逻辑 AND,并且必须保留为最后一个运算符。

Udisks

文件管理器在尝试挂载存储设备时可能会要求输入密码,或者产生未授权或类似的错误。有关详细信息,请参见 Udisks#配置

允许普通用户管理单个 systemd 单元

通过检查传递给 polkit 策略检查的某些值,您可以赋予特定用户或组管理特定单元的能力。例如,您可能希望普通用户启动和停止 wpa_supplicant

/etc/polkit-1/rules.d/10-wifimanagement.rules
polkit.addRule(function(action, subject) {
    if (action.id == "org.freedesktop.systemd1.manage-units") {
        if (action.lookup("unit") == "wpa_supplicant.service") {
            var verb = action.lookup("verb");
            if (verb == "start" || verb == "stop" || verb == "restart") {
                return polkit.Result.YES;
            }
        }
    }
});

参见