There are 2 fundamental differences between /etc/security/pam_env.conf
and /etc/environment
.
The order in which PAM processes them.
/etc/environment
is parsed first, but anything defined here is overridden by definitions for those same variables if they also exist in pam_env.conf
.
However, it's possible to subsume + extend the variables from /etc/environment
in /etc/security/pam_env.conf
, e.g.:
/etc/security/pam_env.conf
PATH DEFAULT=${PATH}:/usr/sbin
Variable expansion
a. /etc/environment
is not a script, but a set of assignment expressions, i.e. ${PATH}
is not expanded, but used literally.
b. /etc/security/pam_env.conf
is a different animal altogether. It's not a script per se; it's still just a set of KEY=VALUE assignments, but PAM can expand existing variables (ex: ${PATH}
, ${DISPLAY}
) and other PAM_ITEMs (ex: @{PAM_SERVICE}
, @{PAM_USER}
, etc.). Take special note of $
vs @
here.
PAM also handles the special variables @{HOME}
and @{SHELL}
, which expand to whatever is defined in /etc/passwd
. *Note: in most PAM applications, the traditional variables ${HOME}
and ${SHELL}
(compare @
vs $
) are not available this early in PAM's flow.
Using the example given in the comments of /etc/security/pam_env.conf
, this replacing/expanding behavior can be used to modify the DISPLAY
variable for remote login sessions.
/etc/security/pam_env.conf
REMOTE_HOST DEFAULT=localhost OVERRIDE=@{PAM_RHOST}
DISPLAY DEFAULT=${REMOTE_HOST}:0.0 OVERRIDE=${DISPLAY}
To the specific problem you described here, the values you configured in /etc/environment
weren't available in the sudo
temporary environment because the session
facility given by the PAM application definition for /etc/pam.d/sudo
never calls pam_env.so
for sessions.
In /etc/pam.d/sudo
, sessions only import the rules from /etc/pam.d/system-auth
. Following the trail, in /etc/pam.d/system-auth
, the session stack doesn't have an entry for pam_env.so
.
There are a few ways to customize the variables available in a sudo
environment.
If you need some custom set of environment variables that only exist in sudo-land, it's fairly straightforward.
Create a file to contain your exclusive-to-sudo environment variables.
/etc/security/sudo_custom_vars.conf
GREET DEFAULT="hello from sudo land"
VAR1 DEFAULT="${GREET}"
_VAR2 DEFAULT="VAR2 not passed to sudo, ...but"
VAR2 DEFAULT="${_VAR2} ${GREET}" OVERRIDE=${VAR2}
VAR3 DEFAULT="Nope. Unknown users cannot sudo." OVERRIDE=@{PAM_RUSER}
...
Make a copy of /etc/pam.d/system-auth
, rename it along the lines of /etc/pam.d/sudo-environment
, and add a directive to the bottom of the session
stack:
session required pam_unix.so
session optional pam_permit.so
# Add a line for using pam_env.so
session optional pam_env.so conffile=/etc/security/sudo_custom_vars.conf
If you want pass variables from the non-sudo environment, include the user_readenv=1
flag
session optional pam_env.so conffile=/etc/security/sudo_custom_vars.conf user_readenv=1
In the PAM application definition /etc/pam.d/sudo
, make the replacement:
- session include system-auth
+ session include sudo-environment
Open a new terminal to test
$ su <your username> # Testing PAM without logging out
$ export VAR1=""
$ export VAR2="hello from down here" # Set var in non-sudo environment
$ echo $VAR1
<nothing>
$ sudo sh -c 'echo $VAR1' # Test sudo's DEFAULT value
hello from sudo land
$ echo $VAR2
hello from down here
$ sudo sh -c 'echo $VAR2' # VAR2 not passed to sudo
VAR2 not passed to sudo, ...but hello from sudo land
$ sudo -E su -c 'echo $VAR2' # VAR2 (and everything else) passed to sudo
hello from down here
$ sudo env VAR2="inline override" su -c 'echo $VAR2'
inline override
$ sudo sh -c 'echo $VAR3' # Testing we can read a PAM_ITEM
aaron
An alternative to tinkering around with the PAM modules is to edit /etc/sudoers
with # visudo
, as you did. I realize this is an old question and way-back-when, commenting Default env_reset
was the the thing to do.
Moving forward, the accepted best practice when using sudoers
to pull in variable definitions from the environment is to append the variables to env_keep
. (...that is, unless you need a unique set of variables as shown above)
/etc/sudoers
Defaults env_keep += "var1 var2, etc..."