How to use REST API for 'snap get core watchdog'

I use below in one of my snap (device monitor).

system (“snap connections”);
system(“snap get core watchdog”);
system (“getent group”);

Snap works in devmode but not in strict mode.
I learnt that I need to use snap-control interface along with REST API with curl to talk to snapd. I have added the sanpd-control plug but I know nothing about REST API.

Although I went through https://docs.ubuntu.com/core/en/reference/rest#post-v2create-user I think I do not know where to start.

Appreciate if someone could give some inputs / examples.

If you have the snapd-control interface connected, then those snap subcommands should work within confinement. It uses the same REST API as anything else would. If you are interested in the details of the REST API though, the following is a good place to start:

One thing to add though: it is unlikely that you will be able to publish a snap using snapd-control to the main Snap Store. A snap with this interface can install and remove arbitrary snaps, connect interfaces that would be disconnected by default, change confinement options, etc. Connecting snapd-control punches a huge hole in the strict confinement sandbox, so it’s use is strictly controlled.

Perhaps it would be best to start by describing what you want to do at a high level?

Ok. Is my understanding correct that I will have to do REST API coding in my snap instead of simply doing system("snap ") right?

This is for a brand store. I hope no issues then, right?

I have multiples items for which I (BELIEVE I) need REST API:

In one of the snaps (with strict confinement)

  1. I have an app called launch which runs a script (content below)

    #!/bin/sh

    echo “adding”
    groupadd --extrausers --system xyz_group
    useradd --extrausers --system -g xyz_group xyz_user

    echo “verifying”
    getent group | cut -d: -f1 | grep xyz
    getent passwd | grep xyz

  2. I am doing as below from a .c file:

    printf("\nWatchdog:\n");
    system(“snap get core watchdog”);

    printf("\nUser and Group:\n");
    system (“getent group | cut -d: -f1 | grep xyz”);

    printf("\nSnap Plugs and Slots:\n");
    system (“snap connections”);

    printf(“Storage Status:\n”);
    system (“df -kh ./”);

    printf("\nMemory Status:\n");
    system (“free -th”);

You should be fine with a brand store.

It looks like the AppArmor policies block access to the /usr/bin/snap binary, but if you shipped a copy of it in your snap, it would likely work when snapd-control is connected.

As you’re using C, another option would be to use the snapd-glib library, which will probably be simpler than working from scratch.

Just for being sure again, are you suggesting that I can achieve same things with sanpd-glib as compared to REST API / curl combination (if I need snapd access only in .c files)?

If yes, then:
Q1. I will have to create a content interface to make use of the API’s exported by snapd-glib in .h file. Right?
Q2. Do you know of any existing snap project making use of snapd-glib. I searched in github but couldn’t find one.

Finally, what about the script that I mentioned above? Just having snapd-control interface in plugs of app in the snap is enough?

You would need to include a copy of the snapd-glib library within your snap. You could achieve this by adding libsnapd-glib1 to stage-packages in your project (and probably put libsnapd-glib-dev in build-packages to get its headers).

The library itself doesn’t grant you any extra permissions: it simply makes it easier for you to use the REST API from a C program. It is the snapd-control interface that grants you permission to communicate with snapd.

Ok. Got it. Will try this out and update thread in case I have any doubts.

@jamesh just wanted to confirm that using snapd-glib I can solve below issue.

Following are details that I got by using snappy-debug / journalctl for the failures:

Q. What does it mean by
* adjust snap to ship ‘snap’
* adjust snap to ship ‘groupadd’
* adjust snap to ship ‘useradd’

  1. Snap name : hw-wtdog
    confinement : strict
    app : runner (invokes a script)
    deamon : simple
    command : snap set core watchdog.runtime-timeout=3m
    snap set core watchdog.shutdown-timeout=8m
    = AppArmor =
    Time: Apr 17 05:06:10
    Log: apparmor=“DENIED” operation=“exec” profile=“snap.hw-wtdog.runner” name="/snap/snapd/7264/usr/bin/snap" pid=2606 comm=“sh” requested_mask=“x” denied_mask=“x” fsuid=0 ouid=0
    File: /snap/snapd/7264/usr/bin/snap (exec)
    Suggestions:

    • adjust snap to ship ‘snap’
    • adjust program to use relative paths if the snap already ships ‘snap’
  2. Snap name : hw-wtdog
    confinement : strict
    app : launch (invokes a script)
    deamon : simple
    command : groupadd --extrausers --system xyz_group
    useradd --extrausers --system -g xyz_group xyz_user
    = AppArmor =
    Time: Apr 17 05:46:45
    Log: apparmor=“DENIED” operation=“exec” profile=“snap.app-mgr.launch” name="/usr/sbin/groupadd" pid=3400 comm=“sh” requested_mask=“x” denied_mask=“x” fsuid=1001 ouid=0
    File: /usr/sbin/groupadd (exec)
    Suggestions:

    • adjust snap to ship ‘groupadd’
    • adjust program to use relative paths if the snap already ships ‘groupadd’

    = AppArmor =
    Time: Apr 17 05:46:45
    Log: apparmor=“DENIED” operation=“exec” profile=“snap.app-mgr.launch” name="/usr/sbin/useradd" pid=3401 comm=“sh” requested_mask=“x” denied_mask=“x” fsuid=1001 ouid=0
    File: /usr/sbin/useradd (exec)
    Suggestions:

    • adjust snap to ship ‘useradd’
    • adjust program to use relative paths if the snap already ships ‘useradd’

The confusingly worded “adjust snap to ship ‘snap’” message is suggesting you include a copy of the /usr/bin/snap binary within your snap and call your copy of binary instead.

If you replace the /usr/bin/snap calls with snapd-glib API calls, this denial should go away without doing that.

For the useradd/groupadd denials, I doubt you’ll be able to get those tools running from within the snap sandbox. There are other options though:

  1. use snapd’s create-user API.
  2. add an appropriately signed system-user assertion to the system (also possible via the API).

I do wonder if some of this system configuration would be better handled through the gadget snap for your device though.

You mean even REST API or snapd-glib can’t solve this issue?

I do have system-user assertion:

   `xyz@localhost:~$ snap known system-user
    type: system-user
    authority-id: <<REMOVED>>
    revision: 1
    brand-id: <<REMOVED>>
    email: <<REMOVED>>
    models:
      - <<REMOVED>>
    name: <<REMOVED>>
    password: <<REMOVED>>
    series:
      - 16
    since: <<REMOVED>>
    until: <<REMOVED>>
    username: <<REMOVED>>
    sign-key-sha3-384: <<REMOVED>>
    xyz@localhost:~$`