How to run cups commands inside a snap

I’m using a bash script for retrieving data about printers. I basically wrapped cups commands like lpinfo and lpstat. However, from snap logs I get this /snap/my-snap/x2/bin/printer_init.sh: line 6: /snap/bin/cups.lpinfo: Permission denied

Any clue about how to handle this?

you simply need to ship these commands via a stage-packages: entry in your snap … either the cups or cups-control interfaces (not sure which of the two) will then give you access to the cups socket of the system so the tools can communicate with cupsd …

1 Like

That’s the way! Thank you @ogra I have actually used stage-snaps: [cups] and I got all the binaries I need into my snap.

Thank you mate!

1 Like

I’m back @ogra. I’m now testing things on Ubuntu Core and I get a slightly different behavior.

From snap logs I get this

2023-06-23T11:28:21+02:00 my-utils.printer-init[15767]: lpinfo: Forbidden

So, I tried to manually connect to the cups-control interface (as I did yesterday while testing on Ubuntu 20.04) but I get this

error: snap "snapd" has no "cups-control" interface slots

I double checked using snap interface and actually on Ubuntu Core there is no cups-control interface.

A lot of useful information can be found here https://snapcraft.io/docs/cups-interface

However, still looking for a solution for automating printer setup on Ubuntu Core.

what exactly is missing ?

Cups interface allows access to the CUPS socket for printing via the cups snap but it doesn’t allow printer administration tasks.

The right interface for doing that is cups-control but it seems is not available on Ubuntu Core.

This is the output on Ubuntu Core when running snap interface

Name              Summary
alsa              allows access to raw ALSA devices
audio-playback    allows audio playback via supporting services
content           allows sharing code and data with other snaps
cups              allows access to the CUPS socket for printing
docker            allows access to Docker socket
docker-support    allows operating as the Docker daemon
firewall-control  allows control over network firewall
hardware-observe  allows reading information about system hardware
home              allows access to non-hidden files in the home directory
network           allows access to the network
network-bind      allows operating as a network service
network-control   allows configuring networking and network namespaces
opengl            allows access to OpenGL stack
personal-files    allows access to personal files or directories
pulseaudio        allows operating as or interacting with the pulseaudio service
raw-usb           allows raw access to all USB devices
shutdown          allows shutting down or rebooting the system
system-files      allows access to system files or directories
wayland           allows access to compositors supporting wayland protocol

says that cups-control has been superseded by the cups interface, so i would expect the latter to provide everything you need …

perhaps @till.kamppeter can explain how it is supposed to work on UbuntuCore when you want to have a printer administration application running there …

You are right. cups-control has been superseded but on the cups interface page they are saying

The cups-control interface will continue to be available to allow printer setup tools (and general system admin tools, like this one) to be snapped.

I hope @till.kamppeter shows me the way :muscle:

At the moment I figured it out using a systemd service that I run as a workaround on Ubuntu Core systems. It does what I need but if one day I can converge all the administrative tasks into a snap that works on Ubuntu Core as well, it would be great. Still working for finding a solution. I won’t surrender (for now).

Only to get hold on the command line tools of CUPS the CUPS Snap is really overkill. It contains the CUPS daemin, its web interface, larger packages for the rendering, especially Ghostscript and QPDF, and also cups-browsed. I also do not know what stage-snaps: [cups] exactly does, whether it simply adds the files of the staged Snap or whether it activates all functionality of it (fire up an own copy of the contained daemons). So I recommend stage-packages: [cups-client] here to stage only the Debian package with the command line tools.

2 Likes

a stage snap only adds the contents but not the startup files or anything from the apps: section of the snap you include. it is good to get the binaries you want from the snap you stage, but you have to care for i.e. starting a daemon yourself in case you want this.

1 Like

Thanks, so the CUPS Snap is still overkill here as it contains the unnecessary executables cupsd, cups-browsed, gs, CUPS filters, and other auxiliary files … The Debian package cups-client actually contains only the CLI tools of CUPS.

1 Like

To be able to do administrative tasks on CUPS (creating/modifying/removing queues, changing server settings, deleting someone else’s jobs, …) out of a Snap, independent which type of app (GUI, CLI, daemon, …) one has to plug cups-control, and NOT cups. The cups interface allows only listing printers, options, and jobs, printing jobs. and deleting one’s own jobs. Therefore cups-control is a “dangerous” interface which needs manual connection or permission of the Snap Store team for auto-connection, in contrary to cups being a “safe” interface which just auto-connects.

Note also that the command line tool lpinfo, even being totally read-only, is an administrative tool and its operations (list available devices, list available drivers) are considered administrative and therefore you need to plug cups-control to use this tool or do its operations via CUPS API or equivalent IPP requests to the CUPS daemon out of a Snap.

If you see a non-administrartive operation getting blocked or any operation from a classically installed tool or application, this is a bug, please report it.

Thank you for all this information. So I was on the right way using the cups-control interface and actually is working fine on Ubuntu 20.04. In fact, my printer-admin snap, after running the command snap connect printer-admin:cups-control gets the right access to the cups admin tools. However, when I install my snap on Ubuntu Core, I cannot connect it to the cups-control interface due to this error: error: snap "snapd" has no "cups-control" interface slots.

So, it might be that snapd behaves differently on Ubuntu Core. I believe there is no issue with cups snap itself (but I might be wrong).

Ubuntu Core is supposed to not have CUPS included in the immutable core and as it is the immutable distro Ubuntu Core, it cannot have the Debian package of CUPS installed. Therefore the snapd of Ubuntu Core having a cups-control slot does not make sense. The only way to have CUPS on Ubuntu Core is to have the CUPS Snap installed (I hope you have done so, if not, please install it).

The CUPS Snap needs a slot for administrative requests from other Snaps, this I really need to investigate and if this is missing, it is actually a bug.

To start the investigations I want you to try the following (on Ubuntu Core):

snap connect printer-admin:cups-control cups:cups-control

First, post the terminal output of this command here. If what you got is not an error message, try out whether your printer-admin is able to do administrative operations with the snapped CUPS. Please tell your results here, and also post the error messages in case of a failure. Also attach your CUPS error_log here, which is the following file:

/var/snap/cups/current/var/log/error_log

Independent whether you succeed to do administrative operations after doing the command above, run also the following command

snap connect printer-admin:cups-control cups:cups-server

and proceed as I described above. Does this also work?

Background: The slot named cups-server of the CUPS Snap I have introduced as an internal interface for the components of the CUPS Snap for a cups-control plug connecting to it. If the first or both of the above commands fail, I will need a way to get a working cups-control slot added to the CUPS Snap, assuring that there is no clash with the cups-control slot of snapd running on classic distros.

Also a Snap plugging cups-control and having gotten the auto-connect permission would need to plug snapd’s cups-control slot on a classic distro and the CUPS Snap’s cups-control slot on an all-Snap (Ubuntu Core) distro. Perhaps here also work on snapd would be needed.

Thanks mate. Yes, absolutely I have installed the cups snap on Ubuntu Core because, as you said, CUPS is not included in the immutable core of the OS.

I have investigated the things you mentioned.

On Ubuntu Core I ran:

snap connect printer-admin:cups-control cups:cups-control

and I got the same error:

error: snap "cups" has no slot named "cups-control"

Since my snap runs automatic checks using some cups admin commands, the log file /var/snap/cups/current/var/log/error_log repeatedly shows this:

D [26/Jun/2023:23:36:16 +0200] [Client 12243] POST / HTTP/1.1
D [26/Jun/2023:23:36:16 +0200] cupsdSetBusyState: newbusy="Active clients", busy="Not busy"
D [26/Jun/2023:23:36:16 +0200] [Client 12243] Read: status=200, state=6
D [26/Jun/2023:23:36:16 +0200] [Client 12243] Authorized as root using PeerCred.
D [26/Jun/2023:23:36:16 +0200] [Client 12243] 2.0 CUPS-Get-Devices 1
D [26/Jun/2023:23:36:16 +0200] CUPS-Get-Devices
D [26/Jun/2023:23:36:16 +0200] cupsdIsAuthorized: username="root"
D [26/Jun/2023:23:36:16 +0200] [Client 12243] AppArmor profile is 'snap.printer-admin.printer-init'.
E [26/Jun/2023:23:36:16 +0200] [Client 12243] Unable to check snap context: (null): error running snapctl: cannot use --apparmor-label check with cups:cups-control
E [26/Jun/2023:23:36:16 +0200] [Client 12243] Returning HTTP Forbidden for CUPS-Get-Devices (no URI) from localhost
D [26/Jun/2023:23:36:16 +0200] [Client 12243] cupsdSendHeader: code=403, type="text/html", auth_type=0
D [26/Jun/2023:23:36:16 +0200] [Client 12243] HTTP_STATE_WAITING Closing for error 32 (Broken pipe)
D [26/Jun/2023:23:36:16 +0200] [Client 12243] Closing connection.
D [26/Jun/2023:23:36:16 +0200] cupsdSetBusyState: newbusy="Not busy", busy="Active clients"

I confirm that connecting to the cups-server interface works. I ran the command:

snap connect printer-admin:cups-control cups:cups-server

and as you can see I successfully connect to the cups-server interface

Interface           Plug                              Slot                 Notes
cups                printer-admin:cups                cups:cups            -
cups-control        printer-admin:cups-control        cups:cups-server     manual

Now something seems happening but the server closes the connection with the client due to broken pipe errors:

D [27/Jun/2023:00:08:16 +0200] cupsdSetBusyState: newbusy="Active clients", busy="Not busy"
D [27/Jun/2023:00:08:16 +0200] [Client 12260] Server address is "/var/snap/cups/common/run/cups.sock".
D [27/Jun/2023:00:08:16 +0200] [Client 12260] Accepted from localhost (Domain)
D [27/Jun/2023:00:08:16 +0200] [Client 12260] Waiting for request.
D [27/Jun/2023:00:08:16 +0200] Expiring subscriptions...
D [27/Jun/2023:00:08:16 +0200] [Client 12260] POST / HTTP/1.1
D [27/Jun/2023:00:08:16 +0200] cupsdSetBusyState: newbusy="Active clients", busy="Active clients"
D [27/Jun/2023:00:08:16 +0200] [Client 12260] Read: status=200, state=6
D [27/Jun/2023:00:08:16 +0200] [Client 12260] No authentication data provided.
D [27/Jun/2023:00:08:16 +0200] [Client 12260] 2.0 CUPS-Get-Devices 1
D [27/Jun/2023:00:08:16 +0200] CUPS-Get-Devices
D [27/Jun/2023:00:08:16 +0200] cupsdIsAuthorized: username=""
D [27/Jun/2023:00:08:16 +0200] [Client 12260] Returning HTTP Unauthorized for CUPS-Get-Devices (no URI) from localhost
D [27/Jun/2023:00:08:16 +0200] [Client 12260] cupsdSendHeader: code=401, type="text/html", auth_type=0
D [27/Jun/2023:00:08:16 +0200] [Client 12260] WWW-Authenticate: Basic realm=\"CUPS\", PeerCred, Local trc=\"y\"
D [27/Jun/2023:00:08:16 +0200] [Client 12260] HTTP_STATE_WAITING Closing for error 32 (Broken pipe)
D [27/Jun/2023:00:08:16 +0200] [Client 12260] Closing connection.
D [27/Jun/2023:00:08:16 +0200] cupsdSetBusyState: newbusy="Not busy", busy="Active clients"
D [27/Jun/2023:00:08:16 +0200] cupsdSetBusyState: newbusy="Active clients", busy="Not busy"
D [27/Jun/2023:00:08:16 +0200] [Client 12261] Server address is "/var/snap/cups/common/run/cups.sock".
D [27/Jun/2023:00:08:16 +0200] [Client 12261] Accepted from localhost (Domain)
D [27/Jun/2023:00:08:16 +0200] [Client 12261] Waiting for request.
D [27/Jun/2023:00:08:16 +0200] cupsdSetBusyState: newbusy="Active clients", busy="Active clients"
D [27/Jun/2023:00:08:16 +0200] [Client 12262] Server address is "/var/snap/cups/common/run/cups.sock".
D [27/Jun/2023:00:08:16 +0200] [Client 12262] Accepted from localhost (Domain)
D [27/Jun/2023:00:08:16 +0200] [Client 12262] Waiting for request.
D [27/Jun/2023:00:08:16 +0200] [Client 12261] HTTP_STATE_WAITING Closing for error 32 (Broken pipe)
D [27/Jun/2023:00:08:16 +0200] [Client 12261] Closing connection.
D [27/Jun/2023:00:08:16 +0200] cupsdSetBusyState: newbusy="Not busy", busy="Active clients"
D [27/Jun/2023:00:08:16 +0200] cupsdSetBusyState: newbusy="Active clients", busy="Not busy"
D [27/Jun/2023:00:08:16 +0200] [Client 12263] Server address is "/var/snap/cups/common/run/cups.sock".
D [27/Jun/2023:00:08:16 +0200] [Client 12263] Accepted from localhost (Domain)
D [27/Jun/2023:00:08:16 +0200] [Client 12263] Waiting for request.
D [27/Jun/2023:00:08:16 +0200] [Client 12262] HTTP_STATE_WAITING Closing for error 32 (Broken pipe)
D [27/Jun/2023:00:08:16 +0200] [Client 12262] Closing connection.
D [27/Jun/2023:00:08:16 +0200] cupsdSetBusyState: newbusy="Not busy", busy="Active clients"
D [27/Jun/2023:00:08:16 +0200] [Client 12263] POST / HTTP/1.1
D [27/Jun/2023:00:08:16 +0200] cupsdSetBusyState: newbusy="Active clients", busy="Not busy"
D [27/Jun/2023:00:08:16 +0200] [Client 12263] Read: status=200, state=6
D [27/Jun/2023:00:08:16 +0200] [Client 12263] Authorized as root using PeerCred.
D [27/Jun/2023:00:08:16 +0200] [Client 12263] 2.0 CUPS-Get-Devices 1
D [27/Jun/2023:00:08:16 +0200] CUPS-Get-Devices
D [27/Jun/2023:00:08:16 +0200] cupsdIsAuthorized: username="root"
D [27/Jun/2023:00:08:16 +0200] [Client 12263] AppArmor profile is 'snap.printer-admin.printer-init'.
E [27/Jun/2023:00:08:16 +0200] [Client 12263] Unable to check snap context: (null): error running snapctl: cannot use --apparmor-label check with cups:cups-control
E [27/Jun/2023:00:08:16 +0200] [Client 12263] Returning HTTP Forbidden for CUPS-Get-Devices (no URI) from localhost
D [27/Jun/2023:00:08:16 +0200] [Client 12263] cupsdSendHeader: code=403, type="text/html", auth_type=0
D [27/Jun/2023:00:08:16 +0200] [Client 12263] HTTP_STATE_WAITING Closing for error 32 (Broken pipe)
D [27/Jun/2023:00:08:16 +0200] [Client 12263] Closing connection.
D [27/Jun/2023:00:08:16 +0200] cupsdSetBusyState: newbusy="Not busy", busy="Active clients"
D [27/Jun/2023:00:08:17 +0200] Expiring subscriptions...

One further idea to solve the cups-control dilemma with classic distro versus Core:

snapd which provides the cups-control slot :cups-control provides it only if (I do not which criteria here is actually used) it is running on a classic distro OR if a classic CUPS installation (DEB/RPM/source) exists. This means that snapd simply does not have a :cups-control slot on Ubuntu Core.

What it should do is in case of not finding an evidence of a classic distro/classic CUPS to check for the CUPS Snap and connect the domain socket of the CUPS Snap with the :cups-control slot

Can you tell me which version of the CUPS Snap you are using (snap list | grep cups)?

You are right. I don’t know either what snapd evaluates before making available the cups-control slot. For sure on Ubuntu 20.04, which comes with CUPS on board, snapd provides me the cups-control slot. I will conduct tests on other versions of Ubuntu and using other distros as well.

Definitely I will test this workaround too and I let you know.