Use of nmcli from inside a snap

From the command line I have experimented with the use of nmcli .
Now I want to my java application (running as a .snap) to be able to use the nmcli commands too.
However it seems that nmcli is not visible within my .snap.

I see there was a similar question about this before. How do I actually include the nmcli in my .snap ?
If I include the full path e.g. /snap/bin/nmcli would that work.

I am running in devmode for now.

Basically you can’t access any binary in /snap/bin from within your snap. If you want to call the nmcli binary you have to ship it within your own snap and use the network-manager interface to allow access to NetworkManager over DBus.

I am not sure if there are any good dbus bindings for Java but if you can I would recommend not using nmcli but calling the DBus API from NetworkManager directly. See https://docs.ubuntu.com/core/en/stacks/network/network-manager/docs/reference/dbus-api for a link to the API documentation.

If you don’t want to call any of these dbus API endpoints directly, you still can go and take the nmcli binary from the Ubuntu Archive or build one with your snap and use it. We do something similar for the wifi-ap snap. See https://git.launchpad.net/~snappy-hwe-team/snappy-hwe-snaps/+git/wifi-ap/tree/snapcraft.yaml#n144 for details on this.

Thanks for the reply. I think it is becoming clearer now.
Where exactly can I find the latest nmcli binary to download and include in my snap?

As far as I understand in the example from the wifi-ap snap you are also not building it but using the binary.
If I do the same then I could invoke it using my-snap-name.nmcli ?

You can simply get it from the Ubuntu archive by adding the network-manager package to the stage-packages part in your snapcraft.yaml. For example:

  nmcli:
    plugin: nil
    stage-packages:
      - network-manager
    organize:
      usr/bin/nmcli: bin/nmcli

If I do the same then I could invoke it using my-snap-name.nmcli ?

From outside of your snap, yes, if you export nmcli as app. Otherwise you can just call it as normal from somewhere inside your snap.

Just to understand something. Could I call network-manager.nmcli from inside my snap and connect the correct slots/plugs instead?

I am not sure if I understand what you want to ask. But let me try to answer what I understand. You can’t call /snap/bin/network-manager.nmcli as this is owned by the network-manager snap. No interface will allow you to use something out of /snap/bin. The a plug of the network-manager interface will only allow you to talk to the NetworkManager service coming from the network-manager snap over dbus, nothing else.

So if you ship nmcli as binary in your own snap to have to assign a network-manager plug to any application/service inside the snap which will use it. See https://git.launchpad.net/~snappy-hwe-team/snappy-hwe-snaps/+git/wifi-ap/tree/snapcraft.yaml#n144 for a good example (already linked above).

Ok I think I get it. nmcli is not supported as part of the network-manager interface.

So now I have the nmcli binary in my snap.
I also have manually connected my-app:network-manager to network-manager:service.

It seems like nmcli is executing but failing.
I find the following DENIALS in syslog: (snap.gateway.main is my app)

May 31 09:56:08 caracalla kernel: [ 4888.000600] audit: type=1400 audit(1496224568.303:282): apparmor=“DENIED” operation=“ptrace” profile=“snap.network-manager.networkmanager” pid=1516 comm=“NetworkManager” requested_mask=“trace” denied_mask=“trace” peer=“snap.gateway.main”
May 31 09:56:08 caracalla kernel: [ 4888.060435] audit: type=1400 audit(1496224568.363:283): apparmor=“DENIED” operation=“ptrace” profile=“snap.network-manager.networkmanager” pid=1516 comm=“NetworkManager” requested_mask=“trace” denied_mask=“trace” peer=“snap.gateway.main”
May 31 09:56:08 caracalla kernel: [ 4888.140704] audit: type=1400 audit(1496224568.443:284): apparmor=“DENIED” operation=“ptrace” profile=“snap.network-manager.networkmanager” pid=1516 comm=“NetworkManager” requested_mask=“trace” denied_mask=“trace” peer=“snap.gateway.main”
May 31 09:56:08 caracalla kernel: [ 4888.355956] audit: type=1400 audit(1496224568.659:285): apparmor=“DENIED” operation=“ptrace” profile=“snap.network-manager.networkmanager” pid=1516 comm=“NetworkManager” requested_mask=“trace” denied_mask=“trace” peer=“snap.gateway.main”
May 31 09:56:08 caracalla kernel: [ 4888.410982] audit: type=1400 audit(1496224568.711:286): apparmor=“DENIED” operation=“ptrace” profile=“snap.network-manager.networkmanager” pid=1516 comm=“NetworkManager” requested_mask=“trace” denied_mask=“trace” peer=“snap.gateway.main”
May 31 09:56:08 caracalla kernel: [ 4888.487292] audit: type=1400 audit(1496224568.787:287): apparmor=“DENIED” operation=“ptrace” profile=“snap.network-manager.networkmanager” pid=1516 comm=“NetworkManager” requested_mask=“trace” denied_mask=“trace” peer=“snap.gateway.main”

Do I need some thing else?

there is another similar thread at Access nmcli command from network-manager via interface perhaps there is something helpful in it for you ?

Yes I have been reading the other thread. I seem to have a very similar setup now with regard to slots plugs etc.

In the file /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.gateway.main”),

Should I still be getting Denials in syslog?

Those ptrace denials can be ignored.If there are no other denials everything should work fine.

i wonder if we could quieten them somehow if they are non-fatal … since writing them causes unneeded I/O and log spam

We really should, yes. I am not if allowing ptrace is an option. Otherwise we have to fix the NetworkManager code itself.

If they are truly harmless, we could add to interfaces/builtin/network_manager.go in networkManagerConnectedSlotAppArmor:

deny ptrace (trace) peer=###PLUG_SECURITY_TAGS###,

Normally we don’t want to use explicit deny rules because deny rules are always evaluated after allow rules (ie, another allow rule can’t undo it), but in this case the rule is very specific-- the network-manager slot is not allowed to ptrace trace connected plugs.

Thanks @jdstrand! I will propose a PR for this rule later today.

Just to check , lines with apparmor=STATUS or apparmor=ALLOWED in syslog are also nothing to worry about?

You can safely ignore apparmor=STATUS messages.

apparmor=ALLOWED indicates that your devmode snap is doing something that is a violation of sandbox policy, but because you are in devmode it is only logged, not DENIED. Most of the time this will indicate a problem when you put your snap in strict mode (I say most of the time because software may exercise different code paths when under confinement depending on how it handles denials, etc).

Maybe I should start a new thread but previously I had been debugging denials using

/snap/bin/snappy-debug.security scanlog.

Will everything show up here that also shows up in syslog?

Unfortunately no-- dbus denials do not show up. This is a missing feature in the tool that is on the roadmap but not yet implemented.

ok got it.

I am using sockets in my snap.
I was getting denials in snappy-debug.security before I connected my snap to the network-control interface.

However I still get something in syslog:

Jun 1 10:44:05 caracalla kernel: [ 5737.055861] audit: type=1400 audit(1496313845.917:457): apparmor=“ALLOWED” operation=“getsockname” profile=“snap.gateway.main//null-/bin/systemctl” pid=3398 comm=“shutdown” family=“unix” sock_type=“stream” protocol=0 requested_mask=“getattr” denied_mask=“getattr” addr=none

This indicates you are calling systemctl and this is not supported by any interface (because of systemd’s current design it is unconfineable. Ie, the policy quickly spins out to you can interfere with the system or other snaps). Why are you using systemctl? Perhaps there is another way to achive your goal.