PolicyKit Authentication Framework: Creating Your Own Rules


Last week I was explaining the important distinction between authentication and authorization, and how Linux  handles them in PAM and polkit, respectively.

The PolicyKit Authentication Framework or polkit controls how subjects or unprivileged programs (such as a user’s shell) can be allowed to run mechanisms or privileged programs (such as normally root-only programs like mount or reboot) after authenticating simply as the current user or as a user who knows the root password.

What Can You Do With Polkit?

Use the pkaction command to list the set of possible polkit actions. There’s a lot of output, let’s see those possibly related to rebooting and shutting down as configured by Red Hat on RHEL 7. The ones we’re really interested in are highlighted here:

# pkaction | egrep 'power|shutdown|reboot|halt'

Pre-Defined Policies

Mechanisms define the set of possible actions in XML files named /usr/share/polkit-1/actions/*.policy. Based on the above output, we want to change to the /usr/share/polkit-1/actions directory and examine the contents of the file org.freedsktop.login1.policy.

Within that file we will look for blocks such as:
<action id="org.freedesktop.login1.reboot">
Notice that three defaults have been defined:

This means that any client can do this if they can provide the root password. If they have done this recently (e.g., 5 minutes but this of course is also configurable), authentication doesn’t have to be re-done.

This means the same thing for a client in an inactive session on a local console.

This means that a client in an active session on a local console can simply do this without any authentication. This is the line that allows random users to reboot.

We mustn’t edit any of these policy files, because future updates to the polkit packages would overwrite our changes. We must change the behavior with rules.

Pre-Defined Rules

Rules applying to those policies about actions and the authentication methods are written in Java and are stored in /usr/share/polkit-1/rules.d/*.rules and /etc/polkit-1/rules.d/*.rules. The polkitd daemon watches both directories so it should notice your changes. Packages may put rule files into either location.

Make your changes by adding new files named /etc/polkit-1/rules.d/*.rules.

Rules are sorted into lexical order by the file names, with files in /etc before those in /usr if you have two files with the same name in both areas. Start your file names with 2-digit numbers as that’s the environment already in place. As the polkit(8) manual page explains, the following order would be used for these four files:

  1. /etc/polkit-1/rules.d/10-auth.rules
  2. /usr/share/polkit-1/rules.d/10-auth.rules
  3. /etc/polkit-1/rules.d/15-auth.rules
  4. /usr/share/polkit-1/rules.d/20-auth.rules

Creating New Rules

Let’s try this! Let’s make the following policy change:

In order to shut down or reboot, even if an application has asked for those actions to be delayed until it is finished, and even if there are others logged in, you must enter the root password.

Create /etc/polkit-1/rules.d/10-shutdown.rules with this content:

polkit.addRule(function(action, subject) {
    if (action.id == "org.freedesktop.login1.reboot" ||
        action.id == "org.freedesktop.login1.reboot-ignore-inhibit" ||
        action.id == "org.freedesktop.login1.reboot-multiple-sessions" ||
        action.id == "org.freedesktop.login1.power-off" ||
        action.id == "org.freedesktop.login1.power-off-ignore-inhibit" ||
        action.id == "org.freedesktop.login1.power-off-multiple-sessions") {
                return polkit.Result.AUTH_ADMIN;

Or maybe you would prefer to allow all members of group wheel to do this without further authentication, while everyone else will be asked for the root password. Use this:

polkit.addRule(function(action, subject) {
    if (action.id == "org.freedesktop.login1.reboot" ||
        action.id == "org.freedesktop.login1.reboot-ignore-inhibit" ||
        action.id == "org.freedesktop.login1.reboot-multiple-sessions" ||
        action.id == "org.freedesktop.login1.power-off" ||
        action.id == "org.freedesktop.login1.power-off-ignore-inhibit" ||
        action.id == "org.freedesktop.login1.power-off-multiple-sessions") {
                if (subject.isInGroup("wheel")) {
                        return polkit.Result.YES;
                } else {
                        return polkit.Result.AUTH_ADMIN;

You have to get the Java syntax correct, and it may not be obvious that you have an extra or missing parenthesis or curly bracket. If you wonder why your new rule isn’t doing what you expect, try the following and look for syntax error messages:

# grep polkit /var/log/messages | tail

Experiment With Polkit In A Safe Environment

Not everyone is ready to start experimenting with polkit. One of the exercises in Learning Tree’s Linux server administration course has a bonus section that leads more advanced attendees through this. Come to the course and experiment with this on a non-critical system.

Type to search blog.learningtree.com

Do you mean "" ?

Sorry, no results were found for your query.

Please check your spelling and try your search again.