GET on authenticated endpoints fail despite X-Allow-Interaction

The API documentation says

GET /v2/snaps/{name}/conf

Description: configuration details for an installed snap
Access: authenticated
Operation: sync
Return: jSON map of configuration keys and values

name can be the reserved name system to get system options.

and about authentication,

If available, Polkit can also be used for authentication. The client may choose to allow user interaction for authentication, e.g. showing a graphical dialogue. This is done by setting an HTTP header (defaults to false):

X-Allow-Interaction: true

However:

% curl -sS -X GET -H 'X-Allow-Interaction: true' \
  --unix-socket /run/snapd.socket http://localhost/v2/snaps/snapd/conf
{"type":"error","status-code":401,"status":"Unauthorized","result":{"message":"access denied","kind":"login-required"}}

I can reproduce this for all other authenticated GETs endpoints I tried.

Authenticated POSTs, on the other hand, do work fine. For instance,

% curl -sS -X POST -H 'X-Allow-Interaction: true' -d '{"action":"okay","timestamp":"2"}' \
  --unix-socket /run/snapd.socket http://localhost/v2/warnings

triggers the authentication dialogue window.

Reading the snapd source shows that this endpoint doesn’t have an associated Polkit action.

The conf endpoint requires authentication which is provided by snap login:

	snapConfCmd = &Command{
		Path:        "/v2/snaps/{name}/conf",
		GET:         getSnapConf,
		PUT:         setSnapConf,
		ReadAccess:  authenticatedAccess{},
		WriteAccess: authenticatedAccess{},
	}

Compare with the apps endpoint that can be authenticated with snap login or the “io.snapcraft.snapd.manage” Polkit action:

	appsCmd = &Command{
		Path:        "/v2/apps",
		GET:         getAppsInfo,
		POST:        postApps,
		ReadAccess:  openAccess{},
		WriteAccess: authenticatedAccess{Polkit: polkitActionManage},
	}

If you need to access config and use Polkit you will need to change snapd to support this.

Discussed with @jamesh if this is an appropriate patch to add to snapd. It probably depends on what you are configuring:

  • If it’s an config option on an app snap, then this is probably suitable for a general polkit action.
  • If it’s a system config option, then this might be better done by adding a new endpoint with appropriate polkit support there.

It’s a system option, the actual endpoint I want to access is /v2/snaps/system/conf, to enable, disable or query experimental.apparmor-prompting (so analogous to snap {get,set} system experimental.apparmor-prompting).

I tried with snap login first this time but still fails with “unathorized”.

% curl -sS -X GET -H 'X-Allow-Interaction:true' --unix-socket /run/snapd.socket http://localhost/v2/snaps/system/conf
{"type":"error","status-code":401,"status":"Unauthorized","result":{"message":"access denied","kind":"login-required"}}

But I made a mistake in the description of the problem, as actually POST also doesn’t work:

% curl -sS -X PUT -d '{"experimental-apparmor-prompting":true}' -H 'X-Allow-Interaction:true' --unix-socket /run/snapd.socket http://localhost/v2/snaps/system/conf
{"type":"error","status-code":401,"status":"Unauthorized","result":{"message":"access denied","kind":"login-required"}}

@oac, as you pointed me to /v2/snaps/system/conf to get/set apparmor-prompting, do you agree with their assessment?

this might be better done by adding a new endpoint with appropriate polkit support there.

I think I agree that a dedicated endpoint would be clearer, and allow us to construct a more purpose-built authentication and configuration mechanism. Previously, I was steered towards using the existing endpoints for simplicity, but this shows that that’s not quite sufficient in this case.

Additionally, to discuss @robert.ancell 's question about the scope of configuration, we would set the config option system-wide, not on a single app/snap (as far as I know). It’s possible we might want to enable prompting for particular interfaces, but that would be a future extension.

Another important point is that even if experimental.apparmor-prompting=true is set in the system snap configuration, the host kernel might not support prompting, or the prompt subsystem could be in an error state or otherwise disabled, so querying that experimental option isn’t really sufficient to know if prompting is enabled/supported/running. A dedicated endpoint would solve this problem too.

There’s a prompting sync tomorrow, I’ll bring up this topic again there.

Rather than creating a new endpoint for querying the status of and enabling/disabling prompting, we’ll do the following:

  • Enable polkit authentication on the /v2/snaps/{snap}/conf endpoint, so clients can trigger a pop-up via X-Allow-Interaction: true — this is already in the works: https://github.com/snapcore/snapd/pull/13653
  • Expose information about apparmor prompting on the /v2/system-info endpoint, which will indicate whether prompting is unsupported by the kernel, supported but disabled, or supported and enabled.

@nteodosio does this approach sound alright with you?

Excellently, thank you for pushing this forward, @oac!

This (polkit authentication on /v2/snaps/{snap}/conf) has been merged into snapd master, and will be included in the 2.62 release of snapd: https://github.com/snapcore/snapd/pull/13653

Related, the PR to expose supported/enabled features via /v2/system-info should land in master for 2.62 as well: https://github.com/snapcore/snapd/pull/13681

This will also include the “apparmor-prompting” experimental feature, which was merged (as a no-op stub for now) into snapd master: https://github.com/snapcore/snapd/pull/13693

I will rebase the prompting branch on snapd master after 2.62 is cut.

1 Like