From d84f291cd271774129ccd7f5b8ade157f58d3282 Mon Sep 17 00:00:00 2001 From: David Zeuthen Date: Fri, 25 May 2012 17:12:17 -0400 Subject: [PATCH] Rewrite the "Writing polkit applications" chapter Signed-off-by: David Zeuthen --- docs/polkit/overview.xml | 180 ++++++++++++++++++++++++++++++--------- 1 file changed, 142 insertions(+), 38 deletions(-) diff --git a/docs/polkit/overview.xml b/docs/polkit/overview.xml index 9f5a1a9..19834d2 100644 --- a/docs/polkit/overview.xml +++ b/docs/polkit/overview.xml @@ -20,45 +20,149 @@ Writing polkit applications - polkit applications are privileged mechanisms using the - polkit authority as a decider component. To do this, a - mechanism use either - the GObject API, - the D-Bus API or - the pkcheck command to - communicate with the polkit Authority. + polkit applications are privileged mechanisms (typically) using + the polkit authority as a decider component. They do this by + installing a .policy file + into the + /usr/share/polkit-1/actions + directory and communicating with the polkit authority at runtime + (either via the + D-Bus API or indirectly + via the + libpolkit-gobject-1 library or the + pkcheck command). - - Note that clients normally doesn't use the - polkit API directly – it is intended for privileged - mechanisms. If a client needs to disable, - modify or remove UI elements to e.g. convey to the user that a - certain action cannot be carried out (because e.g. the user is - not authorized) or authentication is needed (by e.g. displaying - a padlock icon in the UI), it is usually better to have the - mechanism provide an API for this. - - - If a polkit application wants to handle the case where no - authentication agent exists (for example if the app is launched - via a - ssh1 - login), it is trivial for the application to use the PolkitAgentTextListener - class to spawn its own authentication agent as - needed. Alternatively, the - helper can be used to do this. - - - As an example of code using the GObject API, see . - For an example using the D-Bus API, see . - - Querying the Authority - FIXME: MISSING XINCLUDE CONTENT - - Accessing the Authority via D-Bus - FIXME: MISSING XINCLUDE CONTENT - + + + Best practices + + + + DO use polkit if you are writing a mechanism that is intended to be used by unprivileged programs. + + + + DO carefully consider what actions to define. In many cases there is not a 1:1 mapping between operations and polkit actions (often a polkit action has more to do with the object the operation is acting on than the operation itself). It is important to strike the right balance between too fine-grained and too coarse-grained. + + + + DO try to pick actions and implicit authorizations so applications using your mechanism will work out-of-the box for users logged in at the console (e.g. without interrupting the user with authentication dialogs). + + + + DO pass polkit variables along with + CheckAuthorization() +requests so it's possible to write authorization rules matching on these. Also document these variables in your documentation (for example, see the +udisks2 actions and variables). + + + + DO pass a customized authentication message (using the polkit.message and polkit.gettext_domain variables) that includes more detailed information about the request than whatever is declared in the .policy file's message element. For example, it's better to show Authentication is needed to format INTEL SSDSA2MH080G1GC (/dev/sda) than just Authentication is needed to format the device. + + + + + DON'T use polkit if your program isn't intended to be used by unprivileged programs. For example, if you are writing developer tools or low-level core OS command it's fine to just require the user to be root. Users can always run your tool through e.g. +sudo8, +pkexec1 +or write a simple polkit-using mechanism that allows access to a (safe) subset of your tool. + + + + DON'T use polkit unless you actually have to. In other words, not every single privileged program providing a service to an unprivileged programs has to use polkit. For example, if you have a small well-written setuid helper to help deal with some implementation-detail of the OS (such as elevating the priority of the sound server process to real-time for sessions on local seats) it's not really helpful to define a polkit action for this since no-one is going to choose to not grant the privilige (in the example, no-one is going run the sound server process without real-time priority). + + + + DON'T call + CheckAuthorization() + for all your actions every time the authority emits the + Changed signal. Not only is this a waste of resources, the result may also be inaccurate as authorization rules can return whatever they want, whenever they want. + + + + DON'T block the main thread in your mechanism (e.g. the one used to service IPC requests from unprivileged programs) while waiting for the authority to reply - calls to + CheckAuthorization() + may take a very long time (seconds, even minutes) to complete as user interaction may be involved. + Instead, use either the asynchronous API or + a dedicated thread with the synchronous API. + + + + + + + Usage in unprivileged programs + + + Unprivileged programs consuming privileged mechanisms normally + does use polkit directly - they simply call into the mechanism + and the mechanism either renders service (or refuses the + request) after checking with polkit (which may include + presenting an authentication dialog). In either case, the + unprivileged program in question is oblivious to the fact that + polkit is being used - it simply just waits for the privileged + mechanism to carry out the request (which, if authentication + dialogs are involved may take many seconds). + + + Note that unprivileged programs often need to disable, modify + or remove UI elements to e.g. convey to the user that a certain + action cannot be carried out (because e.g. the user is not + authorized) or authentication is needed (by e.g. displaying a + padlock icon in the UI). + In this case, the best approach is + usually to have the unprivileged program get this information + from the privileged mechanism - especially because there often + is no reliable way that the unprivileged program can know what + polkit action is going to be used. In general, there is no + guarantee that operations (such as D-Bus methods) map 1:1: to + polkit action - for example, a disk manager service's + Format() method may check for the action + net.company.diskmanager.format-removable if + the disk is removable and + net.company.diskmanager.format-fixed + otherwise. + + + However, in certain cases, for example when using the + org.freedesktop.policykit.imply annotation + (see the + polkit8 man page), + it does make sense for an unprivileged program to query the + polkit authority (to e.g. update UI elements) and it is + in fact allowed to do so as long as the unprivileged program doesn't pass any variables along with the + CheckAuthorization() + call (otherwise it would be easy to spoof authentication dialogs and bypass authorization rules). + In fact, since this use-case is so common, + libpolkit-gobject-1 provides the + PolkitPermission type (which is derived from + GPermission) + that can be used together with + GtkLockButton + (often used to implement an + instant apply + paradigm). + Note that for GtkLockButton to work well, the + polkit action backing it should use auth_self_keep or + auth_admin_keep for its implicit authorizations. + + + + + No authentication agent + + If a polkit application wants to handle the case where no + authentication agent exists (for example if the app is launched + via a + ssh1 + login), the application can use the PolkitAgentTextListener + type to spawn its own authentication agent as + needed. Alternatively, the + helper can be used to do this. + + + -- 2.34.1