From Tom's reply:
I think that how we use su currently is good, but I also think that it would make sense to add the ability to create a sustained shell. That way the su switch only needs to happen once and the shell can be kept in __context__.
> That addition would allow for a user shell to be created on a per session basis and then re-used, which should satisfy both ends of the argument here.
Original post:
Using su to implement runas can waste quite a lot of time as a full user session is initialised, and every command for every state is run independently. I'm noticing this particularly when using the postgres states.
Is it feasible to (perhaps configurably) prefer sudo (without -i) or even a fork-and-setuid instead, for a lightweight solution.
People want PAM process e.g. ulimits set. Which su does.
For flavor, have a look at #51005 and maybe some of the referenced code. Faster/lighter is obviously better than slower/heavier all other things equal, but the semantic of "run this command as this user" can be tricky to get right in a platform independent way without resorting to su. There's a significant different between "run this command with some specific UID" and "run this command as this user." The latter implies things sourcing shell initialization files to create the right environment, getting the right resource limits, etc.
I am of the opinion that if the state is relying on how the minion happens to initialise the shell login environment for a particular user then that's incorrect. Anything like that should be explictly specified in salt, or you lose the repeatablility/minion independence. And if everything is specified you don't need to perform unnecessary tasks (like starting a load of systemd --user services).
A different approach could be to (somehow) keep the su session open and reuse it for every command using the same runas, though that sounds more complicated.
People want to run commands and have the users path, and limits and application settings. And that fair for them to want things this way.
In the case of cmd.run for example, I think it's important to note we're not providing a list of arguments to exec -- we're providing a literal string to be evaluated by the shell. For that reason, the least surprising behavior is for the command to be run in exactly the same was as when run by the appropriate user from a login shell. The opportunities for optimization which stand out for me are to (1) provide a state that is a thinner wrapper around exec and (2) keep a login shell around in a sub-process for potentially running more than one command.
@saltstack/team-core Thoughts?
For cmd.run it鈥檚 fair, though some more options in that regard could be nice. I meant the internal calls, in particular looking at postgres, where you need a lot of states for every db, role, grant and every single query is run separately with su psql.
Setting loginctl enable-linger has helped a little, but it鈥檚 still a large proportion of the time computing a highstate.
I don't have in-depth knowledge here, yet, but my impression is that su is typically the right way to do things.
It also seems like we want to have an alternative approach that tools like postgres can use to avoid all that extra overhead. So maybe this issue should be something like "Create alternative to su" or "Create long-lived su" or something?
I think that how we use su currently is good, but I also think that it would make sense to add the ability to create a sustained shell. That way the su switch only needs to happen once and the shell can be kept in __context__.
That addition would allow for a user shell to be created on a per session basis and then re-used, which should satisfy both ends of the argument here.
I would totally merge that PR :)
Perhaps this should become a separate discussion, but I've been looking at the psql case again.
You can, using pg_ident.conf, map the user that salt runs as (probably root) to any postgres user you want. If this is configured then there's no need to involve su or sudo or anything. However, as far as I can see, there's no way to avoid the code setting runas (and then setting user to the same thing) for local connections.
It's not obvious to me how things should be rearranged to make this possible, otherwise I'd make a PR.
runas could support values like su:username, proc:username, sudo:username The : is an invalid character in a username for Unix/Linux/Windows. And default to su where it currently does.
Lot of people complain that limits.conf was not being applied which su fixed..e.g. increased file limits
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
If this issue is closed prematurely, please leave a comment and we will gladly reopen the issue.
@saltstack/team-core is there a decision on whether there should be any additions/changes here?
Thank you for updating this issue. It is no longer marked as stale.
@OrangeDog I've updated the title to bring it in line with Tom's suggestion. That seems like enough information to get someone started.
Presumably a persistent login shell is only a thing when Salt is being used in a master/minion configuration. I use salt exclusively via salt-call, so this doesn't apply to me, but I'm concerned that the persistent shell idea is going to create trouble. Let's assume a "command" is a string that the shell evaluates as direct input (i.e. as if it were typed.) What if that string is "source hose-my-environment.sh'? What if the shell is used to run a script that messes with ulimits?
I'm still partial to dividing use cases into an exec wrapper that requires complete and explicit configuration in a state and an su wrapper that starts from scratch.