mirror of
https://github.com/valitydev/salt.git
synced 2024-11-07 17:09:03 +00:00
Separates key_dir from cache_dir, The key files (i.e. '.root_key', '.sudo_...') must not be shared with other masters.
This commit is contained in:
parent
19a5383c59
commit
20bf4eed1d
@ -147,6 +147,7 @@ class Master(salt.utils.parsers.MasterOptionParser, DaemonsMixin): # pylint: di
|
||||
os.path.join(self.config['cachedir'], 'jobs'),
|
||||
os.path.join(self.config['cachedir'], 'proc'),
|
||||
self.config['sock_dir'],
|
||||
self.config['key_dir'],
|
||||
self.config['token_dir'],
|
||||
self.config['syndic_dir'],
|
||||
self.config['sqlite_queue_dir'],
|
||||
@ -160,7 +161,7 @@ class Master(salt.utils.parsers.MasterOptionParser, DaemonsMixin): # pylint: di
|
||||
v_dirs,
|
||||
self.config['user'],
|
||||
permissive=self.config['permissive_pki_access'],
|
||||
pki_dir=self.config['pki_dir'],
|
||||
sensitive_dirs=[self.config['pki_dir'], self.config['key_dir']],
|
||||
)
|
||||
# Clear out syndics from cachedir
|
||||
for syndic_file in os.listdir(self.config['syndic_dir']):
|
||||
@ -280,7 +281,7 @@ class Minion(salt.utils.parsers.MinionOptionParser, DaemonsMixin): # pylint: di
|
||||
v_dirs,
|
||||
self.config['user'],
|
||||
permissive=self.config['permissive_pki_access'],
|
||||
pki_dir=self.config['pki_dir'],
|
||||
sensitive_dirs=[self.config['pki_dir']],
|
||||
)
|
||||
except OSError as error:
|
||||
self.environment_failure(error)
|
||||
@ -467,7 +468,7 @@ class ProxyMinion(salt.utils.parsers.ProxyMinionOptionParser, DaemonsMixin): #
|
||||
v_dirs,
|
||||
self.config['user'],
|
||||
permissive=self.config['permissive_pki_access'],
|
||||
pki_dir=self.config['pki_dir'],
|
||||
sensitive_dirs=[self.config['pki_dir']],
|
||||
)
|
||||
except OSError as error:
|
||||
self.environment_failure(error)
|
||||
@ -575,7 +576,7 @@ class Syndic(salt.utils.parsers.SyndicOptionParser, DaemonsMixin): # pylint: di
|
||||
],
|
||||
self.config['user'],
|
||||
permissive=self.config['permissive_pki_access'],
|
||||
pki_dir=self.config['pki_dir'],
|
||||
sensitive_dirs=[self.config['pki_dir']],
|
||||
)
|
||||
except OSError as error:
|
||||
self.environment_failure(error)
|
||||
|
@ -78,7 +78,7 @@ class SaltCMD(salt.utils.parsers.SaltCMDOptionParser):
|
||||
if 'token' in self.config:
|
||||
import salt.utils.files
|
||||
try:
|
||||
with salt.utils.files.fopen(os.path.join(self.config['cachedir'], '.root_key'), 'r') as fp_:
|
||||
with salt.utils.files.fopen(os.path.join(self.config['key_dir'], '.root_key'), 'r') as fp_:
|
||||
kwargs['key'] = fp_.readline()
|
||||
except IOError:
|
||||
kwargs['token'] = self.config['token']
|
||||
|
@ -188,11 +188,11 @@ class LocalClient(object):
|
||||
# The username may contain '\' if it is in Windows
|
||||
# 'DOMAIN\username' format. Fix this for the keyfile path.
|
||||
key_user = key_user.replace(u'\\', u'_')
|
||||
keyfile = os.path.join(self.opts[u'cachedir'],
|
||||
keyfile = os.path.join(self.opts[u'key_dir'],
|
||||
u'.{0}_key'.format(key_user))
|
||||
try:
|
||||
# Make sure all key parent directories are accessible
|
||||
salt.utils.verify.check_path_traversal(self.opts[u'cachedir'],
|
||||
salt.utils.verify.check_path_traversal(self.opts[u'key_dir'],
|
||||
key_user,
|
||||
self.skip_perm_errors)
|
||||
with salt.utils.files.fopen(keyfile, u'r') as key:
|
||||
|
@ -186,6 +186,9 @@ VALID_OPTS = {
|
||||
# The directory used to store public key data
|
||||
'pki_dir': str,
|
||||
|
||||
# The directory to store authentication keys of a master's local environment.
|
||||
'key_dir': str,
|
||||
|
||||
# A unique identifier for this daemon
|
||||
'id': str,
|
||||
|
||||
@ -1420,6 +1423,7 @@ DEFAULT_MASTER_OPTS = {
|
||||
'archive_jobs': False,
|
||||
'root_dir': salt.syspaths.ROOT_DIR,
|
||||
'pki_dir': os.path.join(salt.syspaths.CONFIG_DIR, 'pki', 'master'),
|
||||
'key_dir': os.path.join(salt.syspaths.CONFIG_DIR, 'key'),
|
||||
'key_cache': '',
|
||||
'cachedir': os.path.join(salt.syspaths.CACHE_DIR, 'master'),
|
||||
'file_roots': {
|
||||
@ -2399,7 +2403,7 @@ def syndic_config(master_config_path,
|
||||
opts.update(syndic_opts)
|
||||
# Prepend root_dir to other paths
|
||||
prepend_root_dirs = [
|
||||
'pki_dir', 'cachedir', 'pidfile', 'sock_dir', 'extension_modules',
|
||||
'pki_dir', 'key_dir', 'cachedir', 'pidfile', 'sock_dir', 'extension_modules',
|
||||
'autosign_file', 'autoreject_file', 'token_dir'
|
||||
]
|
||||
for config_key in ('log_file', 'key_logfile', 'syndic_log_file'):
|
||||
@ -3770,7 +3774,7 @@ def apply_master_config(overrides=None, defaults=None):
|
||||
|
||||
# Prepend root_dir to other paths
|
||||
prepend_root_dirs = [
|
||||
'pki_dir', 'cachedir', 'pidfile', 'sock_dir', 'extension_modules',
|
||||
'pki_dir', 'key_dir', 'cachedir', 'pidfile', 'sock_dir', 'extension_modules',
|
||||
'autosign_file', 'autoreject_file', 'token_dir', 'syndic_dir',
|
||||
'sqlite_queue_dir'
|
||||
]
|
||||
|
@ -183,11 +183,11 @@ def mk_key(opts, user):
|
||||
# The username may contain '\' if it is in Windows
|
||||
# 'DOMAIN\username' format. Fix this for the keyfile path.
|
||||
keyfile = os.path.join(
|
||||
opts['cachedir'], '.{0}_key'.format(user.replace('\\', '_'))
|
||||
opts['key_dir'], '.{0}_key'.format(user.replace('\\', '_'))
|
||||
)
|
||||
else:
|
||||
keyfile = os.path.join(
|
||||
opts['cachedir'], '.{0}_key'.format(user)
|
||||
opts['key_dir'], '.{0}_key'.format(user)
|
||||
)
|
||||
|
||||
if os.path.exists(keyfile):
|
||||
|
@ -124,7 +124,7 @@ class KeyCLI(object):
|
||||
if self.opts[u'eauth']:
|
||||
if u'token' in self.opts:
|
||||
try:
|
||||
with salt.utils.files.fopen(os.path.join(self.opts[u'cachedir'], u'.root_key'), u'r') as fp_:
|
||||
with salt.utils.files.fopen(os.path.join(self.opts[u'key_dir'], u'.root_key'), u'r') as fp_:
|
||||
low[u'key'] = fp_.readline()
|
||||
except IOError:
|
||||
low[u'token'] = self.opts[u'token']
|
||||
|
@ -205,7 +205,7 @@ class Runner(RunnerClient):
|
||||
if self.opts.get(u'eauth'):
|
||||
if u'token' in self.opts:
|
||||
try:
|
||||
with salt.utils.files.fopen(os.path.join(self.opts[u'cachedir'], u'.root_key'), u'r') as fp_:
|
||||
with salt.utils.files.fopen(os.path.join(self.opts[u'key_dir'], u'.root_key'), u'r') as fp_:
|
||||
low[u'key'] = fp_.readline()
|
||||
except IOError:
|
||||
low[u'token'] = self.opts[u'token']
|
||||
|
@ -194,13 +194,13 @@ def verify_files(files, user):
|
||||
return True
|
||||
|
||||
|
||||
def verify_env(dirs, user, permissive=False, pki_dir='', skip_extra=False):
|
||||
def verify_env(dirs, user, permissive=False, sensitive_dirs=None, skip_extra=False):
|
||||
'''
|
||||
Verify that the named directories are in place and that the environment
|
||||
can shake the salt
|
||||
'''
|
||||
if salt.utils.platform.is_windows():
|
||||
return win_verify_env(dirs, permissive, pki_dir, skip_extra)
|
||||
return win_verify_env(dirs, permissive, sensitive_dirs, skip_extra)
|
||||
import pwd # after confirming not running Windows
|
||||
try:
|
||||
pwnam = pwd.getpwnam(user)
|
||||
@ -275,10 +275,11 @@ def verify_env(dirs, user, permissive=False, pki_dir='', skip_extra=False):
|
||||
# to read in what it needs to integrate.
|
||||
#
|
||||
# If the permissions aren't correct, default to the more secure 700.
|
||||
# If acls are enabled, the pki_dir needs to remain readable, this
|
||||
# is still secure because the private keys are still only readable
|
||||
# by the user running the master
|
||||
if dir_ == pki_dir:
|
||||
# If acls are enabled, the sensitive_dirs (i.e. pki_dir, key_dir) needs to
|
||||
# remain readable, this is still secure because the private keys are still
|
||||
# only readable by the user running the master
|
||||
sensitive_dirs = sensitive_dirs or []
|
||||
if dir_ in sensitive_dirs:
|
||||
smode = stat.S_IMODE(mode.st_mode)
|
||||
if smode != 448 and smode != 488:
|
||||
if os.access(dir_, os.W_OK):
|
||||
@ -525,7 +526,7 @@ def verify_log(opts):
|
||||
log.warning('Insecure logging configuration detected! Sensitive data may be logged.')
|
||||
|
||||
|
||||
def win_verify_env(dirs, permissive=False, pki_dir='', skip_extra=False):
|
||||
def win_verify_env(dirs, permissive=False, sensitive_dirs=None, skip_extra=False):
|
||||
'''
|
||||
Verify that the named directories are in place and that the environment
|
||||
can shake the salt
|
||||
@ -596,8 +597,9 @@ def win_verify_env(dirs, permissive=False, pki_dir='', skip_extra=False):
|
||||
sys.stderr.write(msg.format(dir_, err))
|
||||
sys.exit(err.errno)
|
||||
|
||||
# The PKI dir gets its own permissions
|
||||
if dir_ == pki_dir:
|
||||
# The senitive_dirs (i.e. pki_dir, key_dir) gets its own permissions
|
||||
sensitive_dirs = sensitive_dirs or []
|
||||
if dir_ in sensitive_dirs:
|
||||
try:
|
||||
# Make Administrators group the owner
|
||||
salt.utils.win_dacl.set_owner(path, 'S-1-5-32-544')
|
||||
|
@ -111,13 +111,21 @@ class TestVerify(TestCase):
|
||||
def test_verify_env(self):
|
||||
root_dir = tempfile.mkdtemp(dir=TMP)
|
||||
var_dir = os.path.join(root_dir, 'var', 'log', 'salt')
|
||||
verify_env([var_dir], getpass.getuser())
|
||||
key_dir = os.path.join(root_dir, 'key_dir')
|
||||
verify_env([var_dir, key_dir], getpass.getuser(), sensitive_dirs=[key_dir])
|
||||
self.assertTrue(os.path.exists(var_dir))
|
||||
dir_stat = os.stat(var_dir)
|
||||
self.assertEqual(dir_stat.st_uid, os.getuid())
|
||||
self.assertEqual(dir_stat.st_mode & stat.S_IRWXU, stat.S_IRWXU)
|
||||
self.assertEqual(dir_stat.st_mode & stat.S_IRWXG, 40)
|
||||
self.assertEqual(dir_stat.st_mode & stat.S_IRWXO, 5)
|
||||
self.assertTrue(os.path.exists(key_dir))
|
||||
|
||||
var_dir_stat = os.stat(var_dir)
|
||||
self.assertEqual(var_dir_stat.st_uid, os.getuid())
|
||||
self.assertEqual(var_dir_stat.st_mode & stat.S_IRWXU, stat.S_IRWXU)
|
||||
self.assertEqual(var_dir_stat.st_mode & stat.S_IRWXG, 40)
|
||||
self.assertEqual(var_dir_stat.st_mode & stat.S_IRWXO, 5)
|
||||
|
||||
key_dir_stat = os.stat(key_dir)
|
||||
self.assertEqual(key_dir_stat.st_mode & stat.S_IRWXU, stat.S_IRWXU)
|
||||
self.assertEqual(key_dir_stat.st_mode & stat.S_IRWXG, 0)
|
||||
self.assertEqual(key_dir_stat.st_mode & stat.S_IRWXO, 0)
|
||||
|
||||
@requires_network(only_local_network=True)
|
||||
def test_verify_socket(self):
|
||||
|
Loading…
Reference in New Issue
Block a user