@ -226,18 +226,43 @@ class ActionBase(with_metaclass(ABCMeta, object)):
return True
return True
def _ make_tmp_path( self , remote_user = None ) :
def _ get_admin_users( self ) :
'''
'''
Create and return a temporary path on a remote box .
Returns a list of admin users that are configured for the current shell
plugin
'''
'''
try :
admin_users = self . _connection . _shell . get_option ( ' admin_users ' )
except AnsibleError :
# fallback for old custom plugins w/o get_option
admin_users = [ ' root ' ]
return admin_users
if remote_user is None :
def _is_become_unprivileged ( self ) :
remote_user = self . _play_context . remote_user
'''
The user is not the same as the connection user and is not part of the
shell configured admin users
'''
# if we don't use become then we know we aren't switching to a
# different unprivileged user
if not self . _play_context . become :
return False
# if we use become and the user is not an admin (or same user) then
# we need to return become_unprivileged as True
admin_users = self . _get_admin_users ( )
try :
try :
admin_users = self . _connection . _shell . get_option ( ' admin_users ' ) + [ remote_user ]
remote_user = self . _connection . get_option ( ' remote_user ' )
except AnsibleError :
except AnsibleError :
admin_users = [ ' root ' , remote_user ] # plugin does not support admin_users
remote_user = self . _play_context . remote_user
return bool ( self . _play_context . become_user not in admin_users + [ remote_user ] )
def _make_tmp_path ( self , remote_user = None ) :
'''
Create and return a temporary path on a remote box .
'''
become_unprivileged = self . _is_become_unprivileged ( )
try :
try :
remote_tmp = self . _connection . _shell . get_option ( ' remote_tmp ' )
remote_tmp = self . _connection . _shell . get_option ( ' remote_tmp ' )
except AnsibleError :
except AnsibleError :
@ -245,7 +270,6 @@ class ActionBase(with_metaclass(ABCMeta, object)):
# deal with tmpdir creation
# deal with tmpdir creation
basefile = ' ansible-tmp- %s - %s ' % ( time . time ( ) , random . randint ( 0 , 2 * * 48 ) )
basefile = ' ansible-tmp- %s - %s ' % ( time . time ( ) , random . randint ( 0 , 2 * * 48 ) )
use_system_tmp = bool ( self . _play_context . become and self . _play_context . become_user not in admin_users )
# Network connection plugins (network_cli, netconf, etc.) execute on the controller, rather than the remote host.
# Network connection plugins (network_cli, netconf, etc.) execute on the controller, rather than the remote host.
# As such, we want to avoid using remote_user for paths as remote_user may not line up with the local user
# As such, we want to avoid using remote_user for paths as remote_user may not line up with the local user
# This is a hack and should be solved by more intelligent handling of remote_tmp in 2.7
# This is a hack and should be solved by more intelligent handling of remote_tmp in 2.7
@ -253,7 +277,7 @@ class ActionBase(with_metaclass(ABCMeta, object)):
tmpdir = C . DEFAULT_LOCAL_TMP
tmpdir = C . DEFAULT_LOCAL_TMP
else :
else :
tmpdir = self . _remote_expand_user ( remote_tmp , sudoable = False )
tmpdir = self . _remote_expand_user ( remote_tmp , sudoable = False )
cmd = self . _connection . _shell . mkdtemp ( basefile = basefile , system = use_system_tmp , tmpdir = tmpdir )
cmd = self . _connection . _shell . mkdtemp ( basefile = basefile , system = become_unprivileged , tmpdir = tmpdir )
result = self . _low_level_execute_command ( cmd , sudoable = False )
result = self . _low_level_execute_command ( cmd , sudoable = False )
# error handling on this seems a little aggressive?
# error handling on this seems a little aggressive?
@ -297,7 +321,7 @@ class ActionBase(with_metaclass(ABCMeta, object)):
self . _connection . _shell . tmpdir = rc
self . _connection . _shell . tmpdir = rc
if not use_system_tmp :
if not become_unprivileged :
self . _connection . _shell . env . update ( { ' ANSIBLE_REMOTE_TMP ' : self . _connection . _shell . tmpdir } )
self . _connection . _shell . env . update ( { ' ANSIBLE_REMOTE_TMP ' : self . _connection . _shell . tmpdir } )
return rc
return rc
@ -409,12 +433,7 @@ class ActionBase(with_metaclass(ABCMeta, object)):
# we have a need for it, at which point we'll have to do something different.
# we have a need for it, at which point we'll have to do something different.
return remote_paths
return remote_paths
try :
if self . _is_become_unprivileged ( ) :
admin_users = self . _connection . _shell . get_option ( ' admin_users ' )
except AnsibleError :
admin_users = [ ' root ' ] # plugin does not support admin users
if self . _play_context . become and self . _play_context . become_user and self . _play_context . become_user not in admin_users + [ remote_user ] :
# Unprivileged user that's different than the ssh user. Let's get
# Unprivileged user that's different than the ssh user. Let's get
# to work!
# to work!
@ -441,8 +460,8 @@ class ActionBase(with_metaclass(ABCMeta, object)):
raise AnsibleError ( ' Failed to set file mode on remote temporary files (rc: {0} , err: {1} ) ' . format ( res [ ' rc ' ] , to_native ( res [ ' stderr ' ] ) ) )
raise AnsibleError ( ' Failed to set file mode on remote temporary files (rc: {0} , err: {1} ) ' . format ( res [ ' rc ' ] , to_native ( res [ ' stderr ' ] ) ) )
res = self . _remote_chown ( remote_paths , self . _play_context . become_user )
res = self . _remote_chown ( remote_paths , self . _play_context . become_user )
if res [ ' rc ' ] != 0 and remote_user in admin_users:
if res [ ' rc ' ] != 0 and remote_user in self . _get_ admin_users( ) :
# chown failed even if remo ve_user is root
# chown failed even if remo te_user is administrator/ root
raise AnsibleError ( ' Failed to change ownership of the temporary files Ansible needs to create despite connecting as a privileged user. '
raise AnsibleError ( ' Failed to change ownership of the temporary files Ansible needs to create despite connecting as a privileged user. '
' Unprivileged become user would be unable to read the file. ' )
' Unprivileged become user would be unable to read the file. ' )
elif res [ ' rc ' ] != 0 :
elif res [ ' rc ' ] != 0 :
@ -665,6 +684,9 @@ class ActionBase(with_metaclass(ABCMeta, object)):
module_args [ ' _ansible_keep_remote_files ' ] = C . DEFAULT_KEEP_REMOTE_FILES
module_args [ ' _ansible_keep_remote_files ' ] = C . DEFAULT_KEEP_REMOTE_FILES
# make sure all commands use the designated temporary directory if created
# make sure all commands use the designated temporary directory if created
if self . _is_become_unprivileged ( ) : # force fallback on remote_tmp as user cannot normally write to dir
module_args [ ' _ansible_tmpdir ' ] = None
else :
module_args [ ' _ansible_tmpdir ' ] = self . _connection . _shell . tmpdir
module_args [ ' _ansible_tmpdir ' ] = self . _connection . _shell . tmpdir
# make sure the remote_tmp value is sent through in case modules needs to create their own
# make sure the remote_tmp value is sent through in case modules needs to create their own