There has been some interest in using polkit on Ubuntu Core devices, and since we got this working for the Ubuntu Core Desktop prototype builds I thought I’d go over what I think would be needed to get it working in regular Ubuntu Core. This is probably of interest to @valentind and @mvo.
polkit interface available on Core.
polkit interface described here is already merged to snapd, but the implicit slot is currently only provided on classic systems.
For UCD, we patched snapd to make it implicit on core too. This wouldn’t be appropriate to merge upstream as is, since we don’t want to provide the slot on Ubuntu Core systems that don’t ship with polkit. So I suggest we modify the interface to set:
This is sufficient for Core 22. If we wanted to add polkit support to Core 20 or 18, we should also check for the existence of
Add polkitd to core22 base snap
The hook scripts used to build the core22 base snap should be updated to install the polkitd package.
In addition, we need to allow snaps to install their polkit actions. This can be done by editing
static/etc/system-image/writable-paths to add:
/usr/share/polkit-1 auto persistent transition none
That should be enough to allow installation of snapped system daemons that want to talk to polkitd. That’s not the whole story though, since we also need to let polkitd make authorisation decisions.
This is done via configuration in
/etc/polkit-1/localauthority (as documented in the pklocalauthority(8) man page), falling back to defaults provided by the daemon in the
.policy file it installed to
/usr/share/polkit-1/actions. I’m not sure how interesting local configuration will be, but if we want it we’d need to add
/etc/polkit-1/localauthority as a writable path.
In addition to blanket allow or deny policies, authorisation might depend on:
- Is the user an administrator?
- Can the user authenticate as themselves? (i.e. the familiar password prompts you’d see on the desktop).
Both of these require additional work to enable on Ubuntu Core systems.
Make polkit recognise administrative users.
Polkit needs to be taught about which users on a system are admin users. In addition to
root, Ubuntu configures members of the
admin groups as administrators via
Unfortunately, users created on Ubuntu Core devices are members of neither of these groups. This is because those groups are defined in
/etc/group, which is read-only on Core. Snapd manages to get sudo working by dropping sudo configuration fragments in
/etc/sudoers.d, but that’s not going to help with polkitd.
While adding similar polkit config fragments could work here, for Ubuntu Core Desktop we instead worked out how to add users to these system groups despite them being read-only. This was done as so:
- we patched
libnss-extrausersto remove the restriction on creating groups with
gid < 500in
- we modified
/etc/nsswitch.confso the group database was configured as:
group: files [SUCCESS=merge] extrausers
- we modified the initial version of
/var/lib/extrausers/groupto include the line
sudogroup with the same group ID and an empty user list).
With these changes, rather than taking the first matching group record glibc will consult both databases and merge the membership lists. So we can now add new members to the group without compromising the ability for future core22 releases to add new system groups to the system.
With this in place, snapd would need to learn how to add administrative users to the sudo group. We are using gnome-initial-setup to create user accounts so haven’t tackled this on Core Desktop. It ends up using the shadow utils to manipulate accounts though, and all the
--extrausers patches we needed are already in Ubuntu Core 22.04. So it shouldn’t be too difficult for snapd to use too.
Password prompting via a polkit agent
Polkit handles authentication prompts via a polkit agent. A polkit agent registers itself as being responsible for one or more processes, and will be contacted by polkitd if those processes require an action with a
For Ubuntu Core Desktop, we wanted gnome-shell to be able to act as an agent for all processes in the session, so I created a
polkit-agent interface to let the shell do this. It hasn’t yet been merged to master though as the AppArmor policy needs tightening up:
Even with a tighter policy, this is interface must be treated as super privileged. A polkit agent needs to be able to call the setuid
/usr/libexec/polkit-agent-helper-1 process, which in turn uses PAM to authenticate the user. With password auth, the agent will be handling the user’s password.
Password prompting on the command line
You’ve probably seen how some systemd utilities can prompt you for a password when run as a regular user. It does this by spawning
pkttyagent as a fallback if no other agent is registered for the utility. The code for that is in
Running this from within a snap sandbox would require the
polkit-agent interface as described above. But another possibility would be to have
snap run spawn the fallback agent outside of the sandbox on behalf of the sandboxed app. If we want to go this route, it could be enabled via another attribute on the app in the
One thing to keep in mind is that pkttyagent has its own security problems. Since the snapped process is already running by the time it triggers a authorisation check, it can race the agent to read from the tty and possibly capture the user’s password.