Replace direct use of os.umask with use of existing context manager

In cases where os.umask was being used simply to get the umask, a new
helper function has been added to keep improper direct usage of os.umask
from permanenly modifying the umask.
This commit is contained in:
Erik Johnson 2018-02-26 21:03:43 -06:00
parent 82ce546e18
commit 31b1d98fcb
No known key found for this signature in database
GPG Key ID: 5E5583C437808F3F
22 changed files with 333 additions and 353 deletions

View File

@ -9,11 +9,11 @@
# Import Python libs
from __future__ import absolute_import, print_function
import os
import logging
# Import Salt libs
import salt.client.netapi
import salt.utils.files
import salt.utils.parsers as parsers
from salt.utils.verify import check_user, verify_files, verify_log
@ -42,9 +42,8 @@ class SaltAPI(parsers.SaltAPIParser):
'udp://',
'file://')):
# Logfile is not using Syslog, verify
current_umask = os.umask(0o027)
verify_files([logfile], self.config['user'])
os.umask(current_umask)
with salt.utils.files.set_umask(0o027):
verify_files([logfile], self.config['user'])
except OSError as err:
log.exception('Failed to prepare salt environment')
self.shutdown(err.errno)

View File

@ -15,6 +15,7 @@ import logging
import salt.client.ssh.shell
import salt.client.ssh.state
import salt.utils
import salt.utils.files
import salt.utils.thin
import salt.roster
import salt.state
@ -496,17 +497,16 @@ def request(mods=None,
'kwargs': kwargs
}
})
cumask = os.umask(0o77)
try:
if salt.utils.is_windows():
# Make sure cache file isn't read-only
__salt__['cmd.run']('attrib -R "{0}"'.format(notify_path))
with salt.utils.fopen(notify_path, 'w+b') as fp_:
serial.dump(req, fp_)
except (IOError, OSError):
msg = 'Unable to write state request file {0}. Check permission.'
log.error(msg.format(notify_path))
os.umask(cumask)
with salt.utils.files.set_umask(0o077):
try:
if salt.utils.is_windows():
# Make sure cache file isn't read-only
__salt__['cmd.run']('attrib -R "{0}"'.format(notify_path))
with salt.utils.fopen(notify_path, 'w+b') as fp_:
serial.dump(req, fp_)
except (IOError, OSError):
msg = 'Unable to write state request file {0}. Check permission.'
log.error(msg.format(notify_path))
return ret
@ -560,17 +560,16 @@ def clear_request(name=None):
req.pop(name)
else:
return False
cumask = os.umask(0o77)
try:
if salt.utils.is_windows():
# Make sure cache file isn't read-only
__salt__['cmd.run']('attrib -R "{0}"'.format(notify_path))
with salt.utils.fopen(notify_path, 'w+b') as fp_:
serial.dump(req, fp_)
except (IOError, OSError):
msg = 'Unable to write state request file {0}. Check permission.'
log.error(msg.format(notify_path))
os.umask(cumask)
with salt.utils.files.set_umask(0o077):
try:
if salt.utils.is_windows():
# Make sure cache file isn't read-only
__salt__['cmd.run']('attrib -R "{0}"'.format(notify_path))
with salt.utils.fopen(notify_path, 'w+b') as fp_:
serial.dump(req, fp_)
except (IOError, OSError):
msg = 'Unable to write state request file {0}. Check permission.'
log.error(msg.format(notify_path))
return True

View File

@ -51,6 +51,7 @@ import salt.utils.decorators
import salt.payload
import salt.transport.client
import salt.transport.frame
import salt.utils.files
import salt.utils.rsax931
import salt.utils.verify
import salt.version
@ -69,8 +70,7 @@ def dropfile(cachedir, user=None):
'''
dfn = os.path.join(cachedir, '.dfn')
# set a mask (to avoid a race condition on file creation) and store original.
mask = os.umask(191)
try:
with salt.utils.files.set_umask(0o277):
log.info('Rotating AES key')
if os.path.isfile(dfn):
log.info('AES key rotation already requested')
@ -88,8 +88,6 @@ def dropfile(cachedir, user=None):
os.chown(dfn, uid, -1)
except (KeyError, ImportError, OSError, IOError):
pass
finally:
os.umask(mask) # restore original umask
def gen_keys(keydir, keyname, keysize, user=None):
@ -119,10 +117,9 @@ def gen_keys(keydir, keyname, keysize, user=None):
if not os.access(keydir, os.W_OK):
raise IOError('Write access denied to "{0}" for user "{1}".'.format(os.path.abspath(keydir), getpass.getuser()))
cumask = os.umask(191)
with salt.utils.fopen(priv, 'wb+') as f:
f.write(gen.exportKey('PEM'))
os.umask(cumask)
with salt.utils.files.set_umask(0o277):
with salt.utils.fopen(priv, 'wb+') as f:
f.write(gen.exportKey('PEM'))
with salt.utils.fopen(pub, 'wb+') as f:
f.write(gen.publickey().exportKey('PEM'))
os.chmod(priv, 256)

View File

@ -32,6 +32,7 @@ import salt.fileserver
import salt.utils.args
import salt.utils.atomicfile
import salt.utils.event
import salt.utils.files
import salt.utils.verify
import salt.utils.minions
import salt.utils.gzip_util
@ -231,10 +232,9 @@ def mk_key(opts, user):
os.unlink(keyfile)
key = salt.crypt.Crypticle.generate_key_string()
cumask = os.umask(191)
with salt.utils.fopen(keyfile, 'w+') as fp_:
fp_.write(key)
os.umask(cumask)
with salt.utils.files.set_umask(0o277):
with salt.utils.fopen(keyfile, 'w+') as fp_:
fp_.write(key)
# 600 octal: Read and write access to the owner only.
# Write access is necessary since on subsequent runs, if the file
# exists, it needs to be written to again. Windows enforces this.

View File

@ -138,22 +138,20 @@ class Client(object):
saltenv,
path)
destdir = os.path.dirname(dest)
cumask = os.umask(63)
with salt.utils.files.set_umask(0o077):
# remove destdir if it is a regular file to avoid an OSError when
# running os.makedirs below
if os.path.isfile(destdir):
os.remove(destdir)
# remove destdir if it is a regular file to avoid an OSError when
# running os.makedirs below
if os.path.isfile(destdir):
os.remove(destdir)
# ensure destdir exists
try:
os.makedirs(destdir)
except OSError as exc:
if exc.errno != errno.EEXIST: # ignore if it was there already
raise
# ensure destdir exists
try:
os.makedirs(destdir)
except OSError as exc:
if exc.errno != errno.EEXIST: # ignore if it was there already
raise
yield dest
os.umask(cumask)
yield dest
def get_cachedir(self, cachedir=None):
if cachedir is None:

View File

@ -24,6 +24,7 @@ import salt.exceptions
import salt.minion
import salt.utils
import salt.utils.event
import salt.utils.files
import salt.utils.kinds
# pylint: disable=import-error,no-name-in-module,redefined-builtin
@ -1017,7 +1018,7 @@ class RaetKey(Key):
'''
Use libnacl to generate and safely save a private key
'''
import libnacl.dual # pylint: disable=3rd-party-module-not-gated
import libnacl.dual # pylint: disable=import-error,3rd-party-module-not-gated
d_key = libnacl.dual.DualSecret()
keydir, keyname, _, _ = self._get_key_attrs(keydir, keyname,
keysize, user)
@ -1411,14 +1412,13 @@ class RaetKey(Key):
keydata = {'priv': priv,
'sign': sign}
path = os.path.join(self.opts['pki_dir'], 'local.key')
c_umask = os.umask(191)
if os.path.exists(path):
#mode = os.stat(path).st_mode
os.chmod(path, stat.S_IWUSR | stat.S_IRUSR)
with salt.utils.fopen(path, 'w+') as fp_:
fp_.write(self.serial.dumps(keydata))
os.chmod(path, stat.S_IRUSR)
os.umask(c_umask)
with salt.utils.files.set_umask(0o277):
if os.path.exists(path):
#mode = os.stat(path).st_mode
os.chmod(path, stat.S_IWUSR | stat.S_IRUSR)
with salt.utils.fopen(path, 'w+') as fp_:
fp_.write(self.serial.dumps(keydata))
os.chmod(path, stat.S_IRUSR)
def delete_local(self):
'''

View File

@ -22,6 +22,7 @@ from zipimport import zipimporter
import salt.config
import salt.syspaths
import salt.utils.context
import salt.utils.files
import salt.utils.lazy
import salt.utils.event
import salt.utils.odict
@ -781,24 +782,23 @@ def grains(opts, force_refresh=False, proxy=None):
grains_data.update(opts['grains'])
# Write cache if enabled
if opts.get('grains_cache', False):
cumask = os.umask(0o77)
try:
if salt.utils.is_windows():
# Late import
import salt.modules.cmdmod
# Make sure cache file isn't read-only
salt.modules.cmdmod._run_quiet('attrib -R "{0}"'.format(cfn))
with salt.utils.fopen(cfn, 'w+b') as fp_:
try:
serial = salt.payload.Serial(opts)
serial.dump(grains_data, fp_)
except TypeError:
# Can't serialize pydsl
pass
except (IOError, OSError):
msg = 'Unable to write to grains cache file {0}'
log.error(msg.format(cfn))
os.umask(cumask)
with salt.utils.files.set_umask(0o077):
try:
if salt.utils.is_windows():
# Late import
import salt.modules.cmdmod
# Make sure cache file isn't read-only
salt.modules.cmdmod._run_quiet('attrib -R "{0}"'.format(cfn))
with salt.utils.fopen(cfn, 'w+b') as fp_:
try:
serial = salt.payload.Serial(opts)
serial.dump(grains_data, fp_)
except TypeError:
# Can't serialize pydsl
pass
except (IOError, OSError):
msg = 'Unable to write to grains cache file {0}'
log.error(msg.format(cfn))
if grains_deep_merge:
salt.utils.dictupdate.update(grains_data, opts['grains'])

View File

@ -67,6 +67,7 @@ import salt.log.setup
import salt.utils.args
import salt.utils.atomicfile
import salt.utils.event
import salt.utils.files
import salt.utils.job
import salt.utils.verify
import salt.utils.minions
@ -481,9 +482,8 @@ class Master(SMaster):
# Check to see if we need to create a pillar cache dir
if self.opts['pillar_cache'] and not os.path.isdir(os.path.join(self.opts['cachedir'], 'pillar_cache')):
try:
prev_umask = os.umask(0o077)
os.mkdir(os.path.join(self.opts['cachedir'], 'pillar_cache'))
os.umask(prev_umask)
with salt.utils.files.set_umask(0o077):
os.mkdir(os.path.join(self.opts['cachedir'], 'pillar_cache'))
except OSError:
pass

View File

@ -1061,8 +1061,7 @@ def unzip(zip_file,
if extract_perms:
perm = zfile.getinfo(target).external_attr >> 16
if perm == 0:
umask_ = os.umask(0)
os.umask(umask_)
umask_ = salt.utils.files.get_umask()
if target.endswith('/'):
perm = 0o777 & ~umask_
else:

View File

@ -5032,30 +5032,25 @@ def manage_file(name,
# Create the file, user rw-only if mode will be set to prevent
# a small security race problem before the permissions are set
if mode:
current_umask = os.umask(0o77)
# Create a new file when test is False and source is None
if contents is None:
if not __opts__['test']:
if touch(name):
ret['changes']['new'] = 'file {0} created'.format(name)
ret['comment'] = 'Empty file'
else:
return _error(
ret, 'Empty file {0} not created'.format(name)
)
else:
if not __opts__['test']:
if touch(name):
ret['changes']['diff'] = 'New file'
else:
return _error(
ret, 'File {0} not created'.format(name)
)
if mode:
os.umask(current_umask)
with salt.utils.files.set_umask(0o077 if mode else None):
# Create a new file when test is False and source is None
if contents is None:
if not __opts__['test']:
if touch(name):
ret['changes']['new'] = 'file {0} created'.format(name)
ret['comment'] = 'Empty file'
else:
return _error(
ret, 'Empty file {0} not created'.format(name)
)
else:
if not __opts__['test']:
if touch(name):
ret['changes']['diff'] = 'New file'
else:
return _error(
ret, 'File {0} not created'.format(name)
)
if contents is not None:
# Write the static contents to a temporary file
@ -5089,8 +5084,7 @@ def manage_file(name,
# out what mode to use for the new file.
if mode is None and not salt.utils.is_windows():
# Get current umask
mask = os.umask(0)
os.umask(mask)
mask = salt.utils.files.get_umask()
# Calculate the mode value that results from the umask
mode = oct((0o777 ^ mask) & 0o666)

View File

@ -29,6 +29,7 @@ import salt.config
import salt.payload
import salt.state
import salt.utils
import salt.utils.files
import salt.utils.jid
import salt.utils.url
from salt.exceptions import CommandExecutionError, SaltInvocationError
@ -632,17 +633,16 @@ def request(mods=None,
'kwargs': kwargs
}
})
cumask = os.umask(0o77)
try:
if salt.utils.is_windows():
# Make sure cache file isn't read-only
__salt__['cmd.run']('attrib -R "{0}"'.format(notify_path))
with salt.utils.fopen(notify_path, 'w+b') as fp_:
serial.dump(req, fp_)
except (IOError, OSError):
msg = 'Unable to write state request file {0}. Check permission.'
log.error(msg.format(notify_path))
os.umask(cumask)
with salt.utils.files.set_umask(0o077):
try:
if salt.utils.is_windows():
# Make sure cache file isn't read-only
__salt__['cmd.run']('attrib -R "{0}"'.format(notify_path))
with salt.utils.fopen(notify_path, 'w+b') as fp_:
serial.dump(req, fp_)
except (IOError, OSError):
msg = 'Unable to write state request file {0}. Check permission.'
log.error(msg.format(notify_path))
return ret
@ -696,17 +696,16 @@ def clear_request(name=None):
req.pop(name)
else:
return False
cumask = os.umask(0o77)
try:
if salt.utils.is_windows():
# Make sure cache file isn't read-only
__salt__['cmd.run']('attrib -R "{0}"'.format(notify_path))
with salt.utils.fopen(notify_path, 'w+b') as fp_:
serial.dump(req, fp_)
except (IOError, OSError):
msg = 'Unable to write state request file {0}. Check permission.'
log.error(msg.format(notify_path))
os.umask(cumask)
with salt.utils.files.set_umask(0o077):
try:
if salt.utils.is_windows():
# Make sure cache file isn't read-only
__salt__['cmd.run']('attrib -R "{0}"'.format(notify_path))
with salt.utils.fopen(notify_path, 'w+b') as fp_:
serial.dump(req, fp_)
except (IOError, OSError):
msg = 'Unable to write state request file {0}. Check permission.'
log.error(msg.format(notify_path))
return True
@ -1111,13 +1110,12 @@ def sls(mods, test=None, exclude=None, queue=False, **kwargs):
return ['Pillar failed to render with the following messages:'] + errors
orchestration_jid = kwargs.get('orchestration_jid')
umask = os.umask(0o77)
if kwargs.get('cache'):
if os.path.isfile(cfn):
with salt.utils.fopen(cfn, 'rb') as fp_:
high_ = serial.load(fp_)
return st_.state.call_high(high_, orchestration_jid)
os.umask(umask)
with salt.utils.files.set_umask(0o077):
if kwargs.get('cache'):
if os.path.isfile(cfn):
with salt.utils.fopen(cfn, 'rb') as fp_:
high_ = serial.load(fp_)
return st_.state.call_high(high_, orchestration_jid)
if isinstance(mods, six.string_types):
mods = mods.split(',')
@ -1144,32 +1142,32 @@ def sls(mods, test=None, exclude=None, queue=False, **kwargs):
if __salt__['config.option']('state_data', '') == 'terse' or kwargs.get('terse'):
ret = _filter_running(ret)
cache_file = os.path.join(__opts__['cachedir'], 'sls.p')
cumask = os.umask(0o77)
try:
if salt.utils.is_windows():
# Make sure cache file isn't read-only
__salt__['cmd.run'](['attrib', '-R', cache_file], python_shell=False)
with salt.utils.fopen(cache_file, 'w+b') as fp_:
serial.dump(ret, fp_)
except (IOError, OSError):
msg = 'Unable to write to SLS cache file {0}. Check permission.'
log.error(msg.format(cache_file))
_set_retcode(ret, high_)
# Work around Windows multiprocessing bug, set __opts__['test'] back to
# value from before this function was run.
__opts__['test'] = orig_test
with salt.utils.files.set_umask(0o077):
try:
if salt.utils.is_windows():
# Make sure cache file isn't read-only
__salt__['cmd.run'](['attrib', '-R', cache_file], python_shell=False)
with salt.utils.fopen(cache_file, 'w+b') as fp_:
serial.dump(ret, fp_)
except (IOError, OSError):
msg = 'Unable to write to SLS cache file {0}. Check permission.'
log.error(msg.format(cache_file))
_set_retcode(ret, high_)
# Work around Windows multiprocessing bug, set __opts__['test'] back to
# value from before this function was run.
__opts__['test'] = orig_test
try:
with salt.utils.fopen(cfn, 'w+b') as fp_:
try:
serial.dump(high_, fp_)
except TypeError:
# Can't serialize pydsl
pass
except (IOError, OSError):
msg = 'Unable to write to highstate cache file {0}. Do you have permissions?'
log.error(msg.format(cfn))
try:
with salt.utils.fopen(cfn, 'w+b') as fp_:
try:
serial.dump(high_, fp_)
except TypeError:
# Can't serialize pydsl
pass
except (IOError, OSError):
msg = 'Unable to write to highstate cache file {0}. Do you have permissions?'
log.error(msg.format(cfn))
os.umask(cumask)
_snapper_post(opts, kwargs.get('__pub_jid', 'called localy'), snapper_pre)
return ret

View File

@ -638,8 +638,7 @@ def init(name,
else:
log.debug('Copying {0} to {1}'.format(sfn, img_dest))
salt.utils.files.copyfile(sfn, img_dest)
mask = os.umask(0)
os.umask(mask)
mask = salt.utils.files.get_umask()
# Apply umask and remove exec bit
mode = (0o0777 ^ mask) & 0o0666
os.chmod(img_dest, mode)

View File

@ -24,6 +24,7 @@ import ast
# Import salt libs
import salt.utils
import salt.utils.files
import salt.exceptions
import salt.ext.six as six
from salt.utils.odict import OrderedDict
@ -757,28 +758,27 @@ def write_pem(text, path, overwrite=True, pem_type=None):
"-----BEGIN CERTIFICATE-----MIIGMzCCBBugA..." \\
path=/etc/pki/mycert.crt
'''
old_umask = os.umask(0o77)
text = get_pem_entry(text, pem_type=pem_type)
_dhparams = ''
_private_key = ''
if pem_type and pem_type == 'CERTIFICATE' and os.path.isfile(path) and \
not overwrite:
_filecontents = _text_or_file(path)
try:
_dhparams = get_pem_entry(_filecontents, 'DH PARAMETERS')
except salt.exceptions.SaltInvocationError:
pass
try:
_private_key = get_pem_entry(_filecontents, '(?:RSA )?PRIVATE KEY')
except salt.exceptions.SaltInvocationError:
pass
with salt.utils.fopen(path, 'w') as _fp:
if pem_type and pem_type == 'CERTIFICATE' and _private_key:
_fp.write(_private_key)
_fp.write(text)
if pem_type and pem_type == 'CERTIFICATE' and _dhparams:
_fp.write(_dhparams)
os.umask(old_umask)
with salt.utils.files.set_umask(0o077):
text = get_pem_entry(text, pem_type=pem_type)
_dhparams = ''
_private_key = ''
if pem_type and pem_type == 'CERTIFICATE' and os.path.isfile(path) and \
not overwrite:
_filecontents = _text_or_file(path)
try:
_dhparams = get_pem_entry(_filecontents, 'DH PARAMETERS')
except salt.exceptions.SaltInvocationError:
pass
try:
_private_key = get_pem_entry(_filecontents, '(?:RSA )?PRIVATE KEY')
except salt.exceptions.SaltInvocationError:
pass
with salt.utils.fopen(path, 'w') as _fp:
if pem_type and pem_type == 'CERTIFICATE' and _private_key:
_fp.write(_private_key)
_fp.write(text)
if pem_type and pem_type == 'CERTIFICATE' and _dhparams:
_fp.write(_dhparams)
return 'PEM written to {0}'.format(path)

View File

@ -3716,22 +3716,21 @@ class BaseHighState(object):
return err
if not high:
return ret
cumask = os.umask(0o77)
try:
if salt.utils.is_windows():
# Make sure cache file isn't read-only
self.state.functions['cmd.run']('attrib -R "{0}"'.format(cfn), output_loglevel='quiet')
with salt.utils.fopen(cfn, 'w+b') as fp_:
try:
self.serial.dump(high, fp_)
except TypeError:
# Can't serialize pydsl
pass
except (IOError, OSError):
msg = 'Unable to write to "state.highstate" cache file {0}'
log.error(msg.format(cfn))
with salt.utils.files.set_umask(0o077):
try:
if salt.utils.is_windows():
# Make sure cache file isn't read-only
self.state.functions['cmd.run']('attrib -R "{0}"'.format(cfn), output_loglevel='quiet')
with salt.utils.fopen(cfn, 'w+b') as fp_:
try:
self.serial.dump(high, fp_)
except TypeError:
# Can't serialize pydsl
pass
except (IOError, OSError):
msg = 'Unable to write to "state.highstate" cache file {0}'
log.error(msg.format(cfn))
os.umask(cumask)
return self.state.call_high(high, orchestration_jid)
def compile_highstate(self):

View File

@ -23,6 +23,7 @@ import salt.utils
import salt.utils.verify
import salt.utils.event
import salt.utils.async
import salt.utils.files
import salt.payload
import salt.exceptions
import salt.transport.frame
@ -1359,11 +1360,8 @@ class TCPPubServerChannel(salt.transport.server.PubServerChannel):
# Securely create socket
log.info('Starting the Salt Puller on {0}'.format(pull_uri))
old_umask = os.umask(0o177)
try:
with salt.utils.files.set_umask(0o177):
pull_sock.start()
finally:
os.umask(old_umask)
# run forever
try:

View File

@ -23,6 +23,7 @@ import salt.crypt
import salt.utils
import salt.utils.verify
import salt.utils.event
import salt.utils.files
import salt.payload
import salt.transport.client
import salt.transport.server
@ -750,11 +751,8 @@ class ZeroMQPubServerChannel(salt.transport.server.PubServerChannel):
# Securely create socket
log.info('Starting the Salt Puller on {0}'.format(pull_uri))
old_umask = os.umask(0o177)
try:
with salt.utils.files.set_umask(0o177):
pull_sock.bind(pull_uri)
finally:
os.umask(old_umask)
try:
while True:

View File

@ -76,6 +76,7 @@ import salt.utils
import salt.utils.async
import salt.utils.cache
import salt.utils.dicttrim
import salt.utils.files
import salt.utils.process
import salt.utils.zeromq
import salt.log.setup
@ -1014,12 +1015,9 @@ class AsyncEventPublisher(object):
)
log.info('Starting pull socket on {0}'.format(epull_uri))
old_umask = os.umask(0o177)
try:
with salt.utils.files.set_umask(0o177):
self.publisher.start()
self.puller.start()
finally:
os.umask(old_umask)
def handle_publish(self, package, _):
'''
@ -1102,8 +1100,7 @@ class EventPublisher(salt.utils.process.SignalHandlingMultiprocessingProcess):
)
# Start the master event publisher
old_umask = os.umask(0o177)
try:
with salt.utils.files.set_umask(0o177):
self.publisher.start()
self.puller.start()
if (self.opts['ipc_mode'] != 'tcp' and (
@ -1111,8 +1108,6 @@ class EventPublisher(salt.utils.process.SignalHandlingMultiprocessingProcess):
self.opts['external_auth'])):
os.chmod(os.path.join(
self.opts['sock_dir'], 'master_event_pub.ipc'), 0o666)
finally:
os.umask(old_umask)
# Make sure the IO loop and respective sockets are closed and
# destroyed

View File

@ -11,6 +11,7 @@ import shutil
# Import salt libs
import salt.fileclient
import salt.utils.files
import salt.utils.url
# Import 3rd-party libs
@ -63,85 +64,83 @@ def sync(opts, form, saltenv=None, extmod_whitelist=None, extmod_blacklist=None)
remote = set()
source = salt.utils.url.create('_' + form)
mod_dir = os.path.join(opts['extension_modules'], '{0}'.format(form))
cumask = os.umask(0o77)
touched = False
try:
if not os.path.isdir(mod_dir):
log.info('Creating module dir \'{0}\''.format(mod_dir))
try:
os.makedirs(mod_dir)
except (IOError, OSError):
log.error(
'Cannot create cache module directory {0}. Check '
'permissions.'.format(mod_dir)
)
fileclient = salt.fileclient.get_file_client(opts)
for sub_env in saltenv:
log.info(
'Syncing {0} for environment \'{1}\''.format(form, sub_env)
)
cache = []
log.info(
'Loading cache from {0}, for {1})'.format(source, sub_env)
)
# Grab only the desired files (.py, .pyx, .so)
cache.extend(
fileclient.cache_dir(
source, sub_env, include_empty=False,
include_pat=r'E@\.(pyx?|so|zip)$', exclude_pat=None
)
)
local_cache_dir = os.path.join(
opts['cachedir'],
'files',
sub_env,
'_{0}'.format(form)
with salt.utils.files.set_umask(0o077):
try:
if not os.path.isdir(mod_dir):
log.info('Creating module dir \'{0}\''.format(mod_dir))
try:
os.makedirs(mod_dir)
except (IOError, OSError):
log.error(
'Cannot create cache module directory {0}. Check '
'permissions.'.format(mod_dir)
)
log.debug('Local cache dir: \'{0}\''.format(local_cache_dir))
for fn_ in cache:
relpath = os.path.relpath(fn_, local_cache_dir)
relname = os.path.splitext(relpath)[0].replace(os.sep, '.')
if extmod_whitelist and form in extmod_whitelist and relname not in extmod_whitelist[form]:
continue
if extmod_blacklist and form in extmod_blacklist and relname in extmod_blacklist[form]:
continue
remote.add(relpath)
dest = os.path.join(mod_dir, relpath)
log.info('Copying \'{0}\' to \'{1}\''.format(fn_, dest))
if os.path.isfile(dest):
# The file is present, if the sum differs replace it
hash_type = opts.get('hash_type', 'md5')
src_digest = salt.utils.get_hash(fn_, hash_type)
dst_digest = salt.utils.get_hash(dest, hash_type)
if src_digest != dst_digest:
# The downloaded file differs, replace!
fileclient = salt.fileclient.get_file_client(opts)
for sub_env in saltenv:
log.info(
'Syncing {0} for environment \'{1}\''.format(form, sub_env)
)
cache = []
log.info(
'Loading cache from {0}, for {1})'.format(source, sub_env)
)
# Grab only the desired files (.py, .pyx, .so)
cache.extend(
fileclient.cache_dir(
source, sub_env, include_empty=False,
include_pat=r'E@\.(pyx?|so|zip)$', exclude_pat=None
)
)
local_cache_dir = os.path.join(
opts['cachedir'],
'files',
sub_env,
'_{0}'.format(form)
)
log.debug('Local cache dir: \'{0}\''.format(local_cache_dir))
for fn_ in cache:
relpath = os.path.relpath(fn_, local_cache_dir)
relname = os.path.splitext(relpath)[0].replace(os.sep, '.')
if extmod_whitelist and form in extmod_whitelist and relname not in extmod_whitelist[form]:
continue
if extmod_blacklist and form in extmod_blacklist and relname in extmod_blacklist[form]:
continue
remote.add(relpath)
dest = os.path.join(mod_dir, relpath)
log.info('Copying \'{0}\' to \'{1}\''.format(fn_, dest))
if os.path.isfile(dest):
# The file is present, if the sum differs replace it
hash_type = opts.get('hash_type', 'md5')
src_digest = salt.utils.get_hash(fn_, hash_type)
dst_digest = salt.utils.get_hash(dest, hash_type)
if src_digest != dst_digest:
# The downloaded file differs, replace!
shutil.copyfile(fn_, dest)
ret.append('{0}.{1}'.format(form, relname))
else:
dest_dir = os.path.dirname(dest)
if not os.path.isdir(dest_dir):
os.makedirs(dest_dir)
shutil.copyfile(fn_, dest)
ret.append('{0}.{1}'.format(form, relname))
else:
dest_dir = os.path.dirname(dest)
if not os.path.isdir(dest_dir):
os.makedirs(dest_dir)
shutil.copyfile(fn_, dest)
ret.append('{0}.{1}'.format(form, relname))
touched = bool(ret)
if opts['clean_dynamic_modules'] is True:
current = set(_listdir_recursively(mod_dir))
for fn_ in current - remote:
full = os.path.join(mod_dir, fn_)
if os.path.isfile(full):
touched = True
os.remove(full)
# Cleanup empty dirs
while True:
emptydirs = _list_emptydirs(mod_dir)
if not emptydirs:
break
for emptydir in emptydirs:
touched = True
shutil.rmtree(emptydir, ignore_errors=True)
except Exception as exc:
log.error('Failed to sync {0} module: {1}'.format(form, exc))
finally:
os.umask(cumask)
touched = bool(ret)
if opts['clean_dynamic_modules'] is True:
current = set(_listdir_recursively(mod_dir))
for fn_ in current - remote:
full = os.path.join(mod_dir, fn_)
if os.path.isfile(full):
touched = True
os.remove(full)
# Cleanup empty dirs
while True:
emptydirs = _list_emptydirs(mod_dir)
if not emptydirs:
break
for emptydir in emptydirs:
touched = True
shutil.rmtree(emptydir, ignore_errors=True)
except Exception as exc:
log.error('Failed to sync {0} module: {1}'.format(form, exc))
return ret, touched

View File

@ -274,20 +274,29 @@ def wait_lock(path, lock_fn=None, timeout=5, sleep=0.1, time_start=None):
log.trace('Write lock for %s (%s) released', path, lock_fn)
def get_umask():
'''
Returns the current umask
'''
ret = os.umask(0) # pylint: disable=blacklisted-function
os.umask(ret) # pylint: disable=blacklisted-function
return ret
@contextlib.contextmanager
def set_umask(mask):
'''
Temporarily set the umask and restore once the contextmanager exits
'''
if salt.utils.is_windows():
# Don't attempt on Windows
if mask is None or salt.utils.is_windows():
# Don't attempt on Windows, or if no mask was passed
yield
else:
try:
orig_mask = os.umask(mask)
orig_mask = os.umask(mask) # pylint: disable=blacklisted-function
yield
finally:
os.umask(orig_mask)
os.umask(orig_mask) # pylint: disable=blacklisted-function
def safe_filename_leaf(file_basename):

View File

@ -34,6 +34,7 @@ import salt.utils
import salt.utils.args
import salt.utils.xdg
import salt.utils.jid
import salt.utils.files
from salt.utils import kinds
from salt.defaults import DEFAULT_TARGET_DELIM
from salt.utils.validate.path import is_writeable
@ -718,9 +719,8 @@ class LogLevelMixIn(six.with_metaclass(MixInMeta, object)):
# verify the default
if logfile is not None and not logfile.startswith(('tcp://', 'udp://', 'file://')):
# Logfile is not using Syslog, verify
current_umask = os.umask(0o027)
verify_files([logfile], self.config['user'])
os.umask(current_umask)
with salt.utils.files.set_umask(0o027):
verify_files([logfile], self.config['user'])
if logfile is None:
# Use the default setting if the logfile wasn't explicity set

View File

@ -28,6 +28,7 @@ from salt.exceptions import SaltClientError, SaltSystemExit, \
CommandExecutionError
import salt.defaults.exitcodes
import salt.utils
import salt.utils.files
log = logging.getLogger(__name__)
@ -218,12 +219,11 @@ def verify_env(dirs, user, permissive=False, pki_dir='', skip_extra=False, root_
continue
if not os.path.isdir(dir_):
try:
cumask = os.umask(18) # 077
os.makedirs(dir_)
with salt.utils.files.set_umask(0o022):
os.makedirs(dir_)
# If starting the process as root, chown the new dirs
if os.getuid() == 0:
os.chown(dir_, uid, gid)
os.umask(cumask)
except OSError as err:
msg = 'Failed to create directory path "{0}" - {1}\n'
sys.stderr.write(msg.format(dir_, err))

View File

@ -30,6 +30,7 @@ from tests.integration.utils import testprogram
# Import salt libs
import salt.utils
import salt.utils.files
import salt.ext.six as six
log = logging.getLogger(__name__)
@ -373,58 +374,56 @@ class CallTest(ShellCase, testprogram.TestProgramCase, ShellCaseCommonTestsMixin
def test_issue_14979_output_file_permissions(self):
output_file = os.path.join(TMP, 'issue-14979')
current_umask = os.umask(0o077)
try:
# Let's create an initial output file with some data
self.run_script(
'salt-call',
'-c {0} --output-file={1} -g'.format(
self.get_config_dir(),
output_file
),
catch_stderr=True,
with_retcode=True
)
stat1 = os.stat(output_file)
with salt.utils.files.set_umask(0o077):
try:
# Let's create an initial output file with some data
self.run_script(
'salt-call',
'-c {0} --output-file={1} -g'.format(
self.get_config_dir(),
output_file
),
catch_stderr=True,
with_retcode=True
)
stat1 = os.stat(output_file)
# Let's change umask
os.umask(0o777)
# Let's change umask
os.umask(0o777) # pylint: disable=blacklisted-function
self.run_script(
'salt-call',
'-c {0} --output-file={1} --output-file-append -g'.format(
self.get_config_dir(),
output_file
),
catch_stderr=True,
with_retcode=True
)
stat2 = os.stat(output_file)
self.assertEqual(stat1.st_mode, stat2.st_mode)
# Data was appeneded to file
self.assertTrue(stat1.st_size < stat2.st_size)
self.run_script(
'salt-call',
'-c {0} --output-file={1} --output-file-append -g'.format(
self.get_config_dir(),
output_file
),
catch_stderr=True,
with_retcode=True
)
stat2 = os.stat(output_file)
self.assertEqual(stat1.st_mode, stat2.st_mode)
# Data was appeneded to file
self.assertTrue(stat1.st_size < stat2.st_size)
# Let's remove the output file
os.unlink(output_file)
# Not appending data
self.run_script(
'salt-call',
'-c {0} --output-file={1} -g'.format(
self.get_config_dir(),
output_file
),
catch_stderr=True,
with_retcode=True
)
stat3 = os.stat(output_file)
# Mode must have changed since we're creating a new log file
self.assertNotEqual(stat1.st_mode, stat3.st_mode)
finally:
if os.path.exists(output_file):
# Let's remove the output file
os.unlink(output_file)
# Restore umask
os.umask(current_umask)
# Not appending data
self.run_script(
'salt-call',
'-c {0} --output-file={1} -g'.format(
self.get_config_dir(),
output_file
),
catch_stderr=True,
with_retcode=True
)
stat3 = os.stat(output_file)
# Mode must have changed since we're creating a new log file
self.assertNotEqual(stat1.st_mode, stat3.st_mode)
finally:
if os.path.exists(output_file):
os.unlink(output_file)
@skipIf(sys.platform.startswith('win'), 'This test does not apply on Win')
def test_42116_cli_pillar_override(self):