It didn’t work when I tried it on version 2.28
. Unfortunately, this means that it’s still not possible to set $PATH for example, without relisting all directories or using the wrapper scripts of old.
If that doesn’t work, let’s get it fixed.
@chipaca Can you put that somewhere in your ever-growing list of paper cuts?
To add to this, we can’t use env vars (nor a lot of other potentially useful stuff, like quotes) in commands. I think it makes sense for things like daemons to not need a wrapper just to have a funky commandline; not sure about regular commands though.
We have some tricks up our sleeves in snapcraft
, this is one of the reasons we use the wrapper (among others)
btw, cool snippeting forum!
EDIT: my statement is true only for environment, not for command. Sorry for this mixup.
So a follow up question, is there a way to have the environment
entries affect command
but not be exported? This will help a lot with classic confined snaps.
Do you mean interpolating the command but not exporting as a variable? Mixing these two options seems super confusing, and the benefit is unclear. Seems simpler and more straightforward to simply use a variable name which isn’t used by the command.
The use case is to be able to do something like:
LD_LIBRARY_PATH=$SNAP/usr/lib/x86_64-gnu-linux <command>
without having LD_LIBRARY_PATH
leak into command
.
The thing that uses this environment variable is ld.so, which is the interpreter of the dynamically linked executable. Not exporting means the shell holds it just for its own use on interpolations, which means it won’t pass it over during the child fork, which means ld.so won’t find it.
Just to add one egg to to this basket, there’s a bug now that $PATH is incorrect. I suspect it has happened since we introduced better environment handling. Details are available here:
https://rocket.ubuntu.com/channel/snapcraft?msg=ahsLwYvntQT5aZSTX
One quirk I found is that variables defined in snap.yaml environment: sections are interpolated for $SNAP* variables for apps, but not in the configure hook, they are set to the un-interpolated string.
An example snap that shows this problem is here:
https://code.launchpad.net/~bloodearnest/+git/snap-env-test
The configure hook variables are left un-interpolated, but the app ones are. Additionally, a stray newline is added to the variables value!?
I note that only $SNAP* variables are interpolated, which i assume is a security feature? I would be nice if other variables defined within the same environment: block could also be interpreted?
I am working around this hardcoding /var/snap//current instead of $SNAP_DATA in my environment: block, but I need to strip my env vars in the configure hook code
@bloodearnest, @zyga-snapd I’ll look at why this isn’t working for configure hook. Thanks for reporting.
Ok, at first I thought this is a bug and has an easy explanation - we do not do osutil.SubstituteEnv(..)
for hooks in snap-exec
. But I think it is actually by design and not an oversight (one could also say it’s a limitation): hooks are executed by snapd with euid=root (but are confined of course), so doing env var expansion for hooks would be a security issue.
@bloodearnest so, we don’t interpolate the variables from “environment:” section for hooks, but you can of course use $SNAP_DATA
, $SNAP_COMMON
etc. directly in hooks (no need for intermediate values in the yaml).
Hmm, wait, this makes no sense. We run daemons as root and we do expand their environment. Is this really by design?
@zyga-snapd I don’t know the original designs and I didn’t implement the hook machinery. All I can say is right now the env expansion happens in snap-exec
and for some reason we don’t expand for hooks - fixing this is a one line change if that’s what we want.
Thanks for checking this out.
I could see how full environment expansion likely has security issues, but @zyga-snapd’s question seems valid.
If there are security issues, would it be possible to create a clean environment with the appropriate $SNAP* variables in it, and use that to do expansion in snap-exec (I think this is fairly common pattern)? Or some similar mechanism where at least $SNAP* variables can be interpolated.
2 quick arguments for this idea
-
simplicity and principle of least surprise. In general there seems to be a move to treat apps and hooks as similarly as possible (e.g. snapctl in apps, etc).
-
My use case is to define a constant set of paths, based below SNAP/SNAP_DATA/SNAP_COMMON, in one place. Then my hooks and my apps can use that as the one source of truth, keeping it DRY. I did have an env file that I manually sourced in each and every app wrapper and in the configure hook wrapper, but I would prefer to have that in the snap.yaml, where it’s more visible and less manual.
Also, the issue of the appended new line is quite annoying. I don’t know where there is coming from, but it isn’t from the yaml.
Thanks
You’re right. We discussed this further in a hangout. Indeed, it doesn’t seem sensible to treat hooks any different. I’ll look at fixing this. Will report here when I have something for review.