Access nmcli command from network-manager via interface

I’m developing a snap that requires access to the network-manager snap’s nmcli command. How can I go about requesting an additional interface slot for the network-manager snap to accomplish this?

To get going very quickly without waiting for us to improve snapd and release an update, I suggest simply bundling the command in your snap. You can simply take the binary and use it.

In the future, we want to enable snaps to make available a set of binaries together with the main interface, so that you’d not have to do anything else in your snap other than simply connecting the network-manager interface itself.

Gotcha, I was contemplating that as an option before, but I thought there may be risk of conflicts between the network-manager snap and my snap both trying to save connection configurations within their respective snap data directories.

I was recently told (through another canonical support channel) that the recommended way to do this is to use DBus directly to talk to network-manager as that is how the nmcli tool itself communicates with network-manager. I don’t know how to get started with this method though and it seems way more complex than it should need to be to accomplish what I want to.

Hi Ryan,

You and I spoke earlier this week in Seattle about your snap needs. I believe the interface plug you need is network-manager, which combined with the nmcli tool might give you the access you need. You can try it with your snap installing it locally and manually connecting it with snap connect. If that’s not correct, @niemeyer can hopefully find out what is.

Hi Michael!

I have tried connecting my snap to the :network-manager interface, but with no luck access the nmcli tool after manually connecting the interfaces to my snap. Still gives error:

bash: nmcli: command not found

when trying to run nmcli from snap run --shell [my_snap] console.

I’ve also tried this with every listed network related interface plug without any luck.

You would still need to bundle the nmcli tool in your snap, but that interface should give it access to talk to the actual network-manager over dbus

Ah I see. I’ll go ahead and bundle-in nmcli and do some testing using that method first before resorting to the dbus comm method.

Ah I see. I’ll go ahead and bundle-in nmcli and do some testing using that method first before resorting to the dbus comm method.

You can safely bundle the nmcli binary coming from the Ubuntu archive (16.04). We currently ship the same NetworkManager version (1.2.2) as a snap which is part of 16.04.

If you have any further questions about how to use the network-manager interface or the snap, please have a look at https://docs.ubuntu.com/core/en/stacks/network/network-manager/docs/index

Bundling in the nmcli does work as expected in my local development environment, but I get an AppArmor error when installing/running the snap on my Ubuntu Core device.

Error:

(process:6665): nmcli-CRITICAL **: Error: Could not create NMClient object: An AppArmor policy prevents this sender from sending this message to this recipient; type="method_call", sender=":1.36" (uid=1000 pid=6665 comm="/snap/machineshop-edge/x15/bin/nmcli c show ") interface="org.freedesktop.DBus.Properties" member="GetAll" error name="(unset)" requested_reply="0" destination=":1.7" (uid=0 pid=1578 comm="/snap/network-manager/115/usr/sbin/NetworkManager ").

Local machine:

  • snap 2.23.6
  • snapd 2.23.6
  • series 16
  • ubuntu 16.04
  • kernel 4.8.0-48-generic

Ubuntu Core machine:

  • snap 2.23.1
  • snapd 2.23.1
  • series 16
  • kernel 4.4.0-1003-caracalla

All of the same interfaces are connected in the same way as in my local environment. Any ideas?

Are you using the network-manager interface for you app? How does the relevant part of your snapcraft.yaml look like?

It needs to be something like

apps:
  my-app:
     command: path/to/nmcli
     plugs: [network-manager]

The other thing I can see in your error message is that you’re calling nmcli not as root (sender=":1.36" (uid=1000 ...)). Non-root users don’t have the permissions to call everything on the service side. If you use root via sudo /snap/bin/my-app then things should work.

I do not need to expose my bundled-in nmcli to the user as a command. I need to use nmcli command from within my service. The wifi-ap snap accomplishes what I need to do, so I used it as an example.

My snapcraft.yaml:

...
apps:
    service:
        command: start.sh
        daemon: simple
        plugs:
        - network-bind
        - network
        - network-control
        - network-manager
        - network-setup-observe
parts:
    ...
    nmcli:
        plugin: nil
        stage-packages:
            - network-manager
        organize:
            usr/bin/nmcli: bin/nmcli

I do have the network-manager interfaces connected to my snap’s network-manager interface, but I do see a difference in the interfaces names from my local version to my ubuntu core version:

Local (Snap v2.23.6):

:network                  machineshop-edge,wifi-ap
:network-bind             core,machineshop-edge,wifi-ap
:network-control          wifi-ap
:network-manager          machineshop-edge,wifi-ap
:network-observe          -
:network-setup-control    -
:network-setup-observe    network-manager

Ubuntu Core (Snap v2.23.1):

:network                      machineshop-edge,snapweb,tpm2,uefi-fw-tools,wifi-ap
:network-bind                 machineshop-edge,snapweb,tpm2,wifi-ap
:network-control              machineshop-edge,wifi-ap
:network-observe              -
:network-setup-control        -
:network-setup-observe        network-manager
network-manager:service       locationd:network-manager,machineshop-edge:network-manager,network-manager:nmcli,wifi-ap:network-manager

Do you think it may be due to the difference in versions since it works as expected in my local environment?

on your classic install (desktop) the network-manager interface backend is provided through the installed network-manager deb … while ubuntu core requires you to install the network-manager snap … that is what causes the name difference (not sure but there might also be a functional difference here)

@jdstrand Any helpful hints you might provide here, or anything we’d want to fix?

It looks like there is a security denial. Please do this at the time of the error:

$ grep audit /var/log/syslog

and paste them here.

Apr 18 21:32:57 caracalla kernel: [1658598.417295] audit: type=1400 audit(1492551177.653:1522): apparmor="STATUS" operation="profile_replace" profile="unconfined" name="snap.core.hook.configure" pid=1121 comm="apparmor_parser"
Apr 18 21:32:57 caracalla kernel: [1658598.486594] audit: type=1400 audit(1492551177.721:1523): apparmor="STATUS" operation="profile_replace" profile="unconfined" name="snap.network-manager.hook.configure" pid=1123 comm="apparmor_parser"
Apr 18 21:32:58 caracalla kernel: [1658599.096993] audit: type=1400 audit(1492551178.333:1524): apparmor="STATUS" operation="profile_replace" profile="unconfined" name="snap.network-manager.networkmanager" pid=1125 comm="apparmor_parser"
Apr 18 21:32:58 caracalla kernel: [1658599.145652] audit: type=1400 audit(1492551178.381:1525): apparmor="STATUS" operation="profile_replace" profile="unconfined" name="snap.network-manager.nmcli" pid=1127 comm="apparmor_parser"
Apr 18 21:33:05 caracalla kernel: [1658606.208469] audit: type=1400 audit(1492551185.437:1526): apparmor="STATUS" operation="profile_replace" profile="unconfined" name="snap.machineshop-edge.nmcli" pid=1138 comm="apparmor_parser"
Apr 18 21:33:06 caracalla kernel: [1658606.790070] audit: type=1400 audit(1492551186.017:1527): apparmor="STATUS" operation="profile_replace" profile="unconfined" name="snap.machineshop-edge.service" pid=1140 comm="apparmor_parser"
Apr 18 21:33:10 caracalla kernel: [1658611.634222] audit: type=1107 audit(1492551190.857:1528): pid=1376 uid=100 auid=4294967295 ses=4294967295 msg='apparmor="DENIED" operation="dbus_method_call"  bus="system" path="/org/freedesktop/NetworkManager" interface="org.freedesktop.DBus.Properties" member="GetAll" name=":1.45" mask="receive" pid=1578 label="snap.network-manager.networkmanager" peer_pid=1200 peer_label="snap.machineshop-edge.service"
Apr 18 21:33:38 caracalla kernel: [1658638.829121] audit: type=1400 audit(1492551218.028:1529): apparmor="DENIED" operation="capable" profile="snap.machineshop-edge.service" pid=1214 comm="ifconfig" capability=16  capname="sys_module"

This is the denial that is causing trouble. This access is currently allowed in networkManagerConnectedSlotAppArmor via this rule:

# Allow traffic to/from our DBus path
dbus (receive, send)
    bus=system
    path=/org/freedesktop/NetworkManager{,/**}
    peer=(label=###PLUG_SECURITY_TAGS###),

Can you look to see if this rule is in /var/lib/snapd/apparmor/profiles/snap.network-manager.networkmanager:

# Allow traffic to/from our DBus path
dbus (receive, send)
    bus=system
    path=/org/freedesktop/NetworkManager{,/**}
    peer=(label="snap.machineshop-edge.service"),

I suspect that at the time of access the security policy doesn’t contain this rule. This could be a result of nmcli running before you have manually connected the interfaces. Can you verify that the interfaces are connected with ‘snap interfaces’ and then run nmcli (and report any security policy denials).

If the interfaces show they are connected but the above rule isn’t in your policy, then that would indicate there is a bug in the interface connection code.

It’s working as expected now. The required network-manager interface was connected to my snap’s network-manager interface (see previous post), but I tried disconnecting from the network-manager:service slot then re-connecting it, and now it’s working.

On another note, is there any way to auto-connect this interface instead of having the user who installs my snap have to do so? Or are there plans for a permissions/interfaces request prompt when a user installs a snap (similar to Android) so they can be auto-connected at that time?

Hmm, if it was connected but not allowed and disconnecting/connecting fixed it, that still might indicate a bug. If you can find a reliable reproducer where snap interfaces shows it is connected but the access is still denied, please report it.

For some ‘plugs’, the base declaration deliberately makes it so these interfaces require a manual connection, usually because the interface grants privileged access to the system. https://github.com/snapcore/snapd/wiki/Interfaces gives some high-level details for each interface and whether auto-connection happens or not and why. Keep in mind, interfaces are manually connected for a reason and the user installing the snap should have a say on whether the interface should be connected. This keeps the ecosystem secure and maintains the public store’s reputation.

The snap declaration mechanism exists to override the base declaration and allow auto-connection and store reviewers may issue a snap declaration through the store. Issuing a snap declaration in this manner requires trust in the snap’s publisher because it removes the user’s choice during the install process and essentially having the brand (ie, public store or private brand store) vouch for the snap publisher. If your snap is in a brand store, then the brand owner can issue snap declarations for your brand (since vouching for your own software makes a lot of sense :).

As for prompting on install to honor the user’s input and making it easier, I believe that this is planned, though IMO we want to be careful about introducing click-through security prompts like those that plagued Android over the years (indeed, they are trying to move away from them).

1 Like

Will do. I’ll definitely report the bug if I can re-produce the issue reliably.

Ah OK, that may be an option for our situation. I will ask our HW partners if they plan on hosting a private brand store.

Thank you all for your help!

@rmn87 Hi, I have been following a path similar to yours.
(Use of nmcli from inside a snap)

I am trying to use nmcli from inside my snap (which basically is a java application).
I have successfully the nmcli binary into my snap and also made the network-manager connection.

I am still getting an error returned from nmcli con show from inside the snap. The guys on the forum have confirmed that I have no security issues so it should be all fine.

Did you also run nmcli as root as someone suggested or can you recall anything else that had to be fixed?

Thanks.