PolicyKit: Branch 'wip/js-rule-files'

David Zeuthen david at kemper.freedesktop.org
Fri May 25 14:12:33 PDT 2012


 docs/polkit/overview.xml |  180 +++++++++++++++++++++++++++++++++++++----------
 1 file changed, 142 insertions(+), 38 deletions(-)

New commits:
commit d84f291cd271774129ccd7f5b8ade157f58d3282
Author: David Zeuthen <davidz at redhat.com>
Date:   Fri May 25 17:12:17 2012 -0400

    Rewrite the "Writing polkit applications" chapter
    
    Signed-off-by: David Zeuthen <davidz at redhat.com>

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 @@
   <chapter id="polkit-apps">
     <title>Writing polkit applications</title>
     <para>
-      polkit applications are privileged mechanisms using the
-      polkit authority as a decider component. To do this, a
-      <emphasis>mechanism</emphasis> use either
-      the <link linkend="ref-api">GObject API</link>,
-      the <link linkend="ref-dbus-api">D-Bus API</link> or
-      the <link linkend="pkcheck.1">pkcheck</link> 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 <filename class='extension'>.policy</filename> file
+      into the
+      <filename class='directory'>/usr/share/polkit-1/actions</filename>
+      directory and communicating with the polkit authority at runtime
+      (either via the
+      <link linkend="ref-dbus-api">D-Bus API</link> or indirectly
+      via the
+      <link linkend="ref-api">libpolkit-gobject-1</link> library or the
+      <link linkend="pkcheck.1">pkcheck</link> command).
     </para>
-    <para>
-      Note that <emphasis>clients</emphasis> normally doesn't use the
-      polkit API directly – it is intended for privileged
-      <emphasis>mechanisms</emphasis>. 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.
-    </para>
-    <para>
-      If a polkit application wants to handle the case where no
-      authentication agent exists (for example if the app is launched
-      via a
-      <citerefentry><refentrytitle>ssh</refentrytitle><manvolnum>1</manvolnum></citerefentry>
-      login), it is trivial for the application to use the <link
-      linkend="PolkitAgentTextListener">PolkitAgentTextListener</link>
-      class to spawn its own authentication agent as
-      needed. Alternatively, the <xref linkend="pkttyagent.1"/>
-      helper can be used to do this.
-    </para>
-    <para>
-      As an example of code using the GObject API, see <xref linkend="cancel-example"/>.
-      For an example using the D-Bus API, see <xref linkend="polkit-raw-dbus-py"/>.
-    </para>
-    <example id="cancel-example"><title>Querying the Authority</title>
-      <programlisting><xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" href="../../src/examples/cancel.c"><xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
-    </example>
-    <example id="polkit-raw-dbus-py"><title>Accessing the Authority via D-Bus</title>
-      <programlisting><xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" href="../../src/examples/polkit-raw-dbus.py"><xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
-    </example>
+
+    <simplesect id="polkit-apps-best-practices">
+      <title>Best practices</title>
+      <itemizedlist mark='opencircle' spacing='compact'>
+
+        <listitem><para>
+          <emphasis role='bold'>DO</emphasis> use polkit if you are writing a mechanism that is intended to be used by unprivileged programs.
+        </para></listitem>
+
+        <listitem><para>
+          <emphasis role='bold'>DO</emphasis> 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.
+        </para></listitem>
+
+        <listitem><para>
+          <emphasis role='bold'>DO</emphasis> 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).
+        </para></listitem>
+
+        <listitem><para>
+          <emphasis role='bold'>DO</emphasis> pass polkit variables along with
+        <link linkend="eggdbus-method-org.freedesktop.PolicyKit1.Authority.CheckAuthorization">CheckAuthorization()</link>
+requests so it's possible to write <emphasis>authorization rules</emphasis> matching on these. Also document these variables in your documentation (for example, see the
+<ulink url="http://udisks.freedesktop.org/docs/latest/udisks-polkit-actions.html">udisks2 actions and variables</ulink>).
+        </para></listitem>
+
+        <listitem><para>
+          <emphasis role='bold'>DO</emphasis> pass a customized authentication message (using the <literal>polkit.message</literal> and <literal>polkit.gettext_domain</literal> variables) that includes more detailed information about the request than whatever is declared in the <filename class='extension'>.policy</filename> file's <literal>message</literal> element. For example, it's better to show <quote>Authentication is needed to format INTEL SSDSA2MH080G1GC (/dev/sda)</quote> than just <quote>Authentication is needed to format the device</quote>.
+        </para></listitem>
+
+
+        <listitem><para>
+          <emphasis role='bold'>DON'T</emphasis> 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.
+<citerefentry><refentrytitle>sudo</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<link linkend="pkexec.1"><citerefentry><refentrytitle>pkexec</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>
+or write a simple polkit-using mechanism that allows access to a (safe) subset of your tool.
+        </para></listitem>
+
+        <listitem><para>
+          <emphasis role='bold'>DON'T</emphasis> 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 <ulink url="http://en.wikipedia.org/wiki/Setuid">setuid</ulink> 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).
+        </para></listitem>
+
+        <listitem><para>
+          <emphasis role='bold'>DON'T</emphasis> call
+        <link linkend="eggdbus-method-org.freedesktop.PolicyKit1.Authority.CheckAuthorization">CheckAuthorization()</link>
+        for all your actions every time the authority emits the
+        <link linkend="eggdbus-signal-org.freedesktop.PolicyKit1.Authority::Changed">Changed</link> 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.
+        </para></listitem>
+
+        <listitem><para>
+          <emphasis role='bold'>DON'T</emphasis> 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
+        <link linkend="eggdbus-method-org.freedesktop.PolicyKit1.Authority.CheckAuthorization">CheckAuthorization()</link>
+        may take a very long time (seconds, even minutes) to complete as user interaction may be involved.
+        Instead, use either the <link linkend="polkit-authority-check-authorization">asynchronous API</link> or
+        a dedicated thread with the <link linkend="polkit-authority-check-authorization-sync">synchronous API</link>.
+        </para></listitem>
+
+      </itemizedlist>
+    </simplesect>
+
+    <simplesect id="polkit-apps-unprivileged">
+      <title>Usage in unprivileged programs</title>
+
+      <para>
+        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).
+      </para>
+      <para>
+        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
+        <literal>Format()</literal> method may check for the action
+        <literal>net.company.diskmanager.format-removable</literal> if
+        the disk is removable and
+        <literal>net.company.diskmanager.format-fixed</literal>
+        otherwise.
+      </para>
+      <para>
+        However, in certain cases, for example when using the
+        <emphasis>org.freedesktop.policykit.imply</emphasis> annotation
+        (see the
+        <link linkend="polkit.8"><citerefentry><refentrytitle>polkit</refentrytitle><manvolnum>8</manvolnum></citerefentry></link> 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
+        <link linkend="eggdbus-method-org.freedesktop.PolicyKit1.Authority.CheckAuthorization">CheckAuthorization()</link>
+        call (otherwise it would be easy to spoof authentication dialogs and bypass authorization rules).
+        In fact, since this use-case is so common,
+        <link linkend="ref-api">libpolkit-gobject-1</link> provides the
+        <link linkend="PolkitPermission"><type>PolkitPermission</type></link> type (which is derived from
+        <ulink url="http://developer.gnome.org/gio/unstable/GPermission.html"><type>GPermission</type></ulink>)
+        that can be used together with
+        <ulink url="http://developer.gnome.org/gtk3/unstable/GtkLockButton.html"><type>GtkLockButton</type></ulink>
+        (often used to implement an
+        <ulink url="http://developer.gnome.org/hig-book/3.2/hig-book.html#windows-instant-apply">instant apply</ulink>
+        paradigm).
+        Note that for <type>GtkLockButton</type> to work well, the
+        polkit action backing it should use <literal>auth_self_keep</literal> or
+        <literal>auth_admin_keep</literal> for its implicit authorizations.
+      </para>
+    </simplesect>
+
+    <simplesect id="polkit-apps-no-auth-agent">
+      <title>No authentication agent</title>
+      <para>
+        If a polkit application wants to handle the case where no
+        authentication agent exists (for example if the app is launched
+        via a
+        <citerefentry><refentrytitle>ssh</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+        login), the application can use the <link
+        linkend="PolkitAgentTextListener">PolkitAgentTextListener</link>
+        type to spawn its own authentication agent as
+        needed. Alternatively, the <xref linkend="pkttyagent.1"/>
+        helper can be used to do this.
+      </para>
+    </simplesect>
+
   </chapter>
 
   <chapter id="polkit-agents">


More information about the hal-commit mailing list