mirror of
https://github.com/valitydev/salt.git
synced 2024-11-07 17:09:03 +00:00
External auth support in salt-key.
This commit is contained in:
parent
0cf7b3fbb9
commit
0589ba8dce
@ -1191,6 +1191,7 @@ class LocalFuncs(object):
|
||||
'''
|
||||
# All wheel ops pass through eauth
|
||||
if 'token' in load:
|
||||
atype = 'token'
|
||||
try:
|
||||
token = self.loadauth.get_tok(load['token'])
|
||||
except Exception as exc:
|
||||
@ -1209,122 +1210,106 @@ class LocalFuncs(object):
|
||||
log.warning(msg)
|
||||
return dict(error=dict(name='TokenAuthenticationError',
|
||||
message=msg))
|
||||
good = self.ckminions.wheel_check(
|
||||
self.opts['external_auth'][token['eauth']][token['name']]
|
||||
if token['name'] in self.opts['external_auth'][token['eauth']]
|
||||
else self.opts['external_auth'][token['eauth']]['*'],
|
||||
load['fun'])
|
||||
if not good:
|
||||
msg = ('Authentication failure of type "token" occurred for '
|
||||
'user {0}.').format(token['name'])
|
||||
log.warning(msg)
|
||||
return dict(error=dict(name='TokenAuthenticationError',
|
||||
message=msg))
|
||||
|
||||
jid = salt.utils.jid.gen_jid()
|
||||
fun = load.pop('fun')
|
||||
tag = tagify(jid, prefix='wheel')
|
||||
data = {'fun': "wheel.{0}".format(fun),
|
||||
'jid': jid,
|
||||
'tag': tag,
|
||||
'user': token['name']}
|
||||
username = token['name']
|
||||
elif 'eauth' in load:
|
||||
atype = 'eauth'
|
||||
try:
|
||||
self.event.fire_event(data, tagify([jid, 'new'], 'wheel'))
|
||||
ret = self.wheel_.call_func(fun, **load)
|
||||
data['return'] = ret
|
||||
data['success'] = True
|
||||
self.event.fire_event(data, tagify([jid, 'ret'], 'wheel'))
|
||||
return {'tag': tag,
|
||||
'data': data}
|
||||
if load['eauth'] not in self.opts['external_auth']:
|
||||
# The eauth system is not enabled, fail
|
||||
msg = ('Authentication failure of type "eauth" occurred for '
|
||||
'user {0}.').format(load.get('username', 'UNKNOWN'))
|
||||
log.warning(msg)
|
||||
return dict(error=dict(name='EauthAuthenticationError',
|
||||
message=msg))
|
||||
|
||||
username = self.loadauth.load_name(load)
|
||||
if not ((username in self.opts['external_auth'][load['eauth']]) |
|
||||
('*' in self.opts['external_auth'][load['eauth']])):
|
||||
msg = ('Authentication failure of type "eauth" occurred for '
|
||||
'user {0}.').format(load.get('username', 'UNKNOWN'))
|
||||
log.warning(msg)
|
||||
return dict(error=dict(name='EauthAuthenticationError',
|
||||
message=msg))
|
||||
if not self.loadauth.time_auth(load):
|
||||
msg = ('Authentication failure of type "eauth" occurred for '
|
||||
'user {0}.').format(load.get('username', 'UNKNOWN'))
|
||||
log.warning(msg)
|
||||
return dict(error=dict(name='EauthAuthenticationError',
|
||||
message=msg))
|
||||
except Exception as exc:
|
||||
log.error(exc)
|
||||
log.error('Exception occurred while '
|
||||
'introspecting {0}: {1}'.format(fun, exc))
|
||||
data['return'] = 'Exception occurred in wheel {0}: {1}: {2}'.format(
|
||||
fun,
|
||||
exc.__class__.__name__,
|
||||
exc,
|
||||
)
|
||||
data['success'] = False
|
||||
self.event.fire_event(data, tagify([jid, 'ret'], 'wheel'))
|
||||
return {'tag': tag,
|
||||
'data': data}
|
||||
|
||||
if 'eauth' not in load:
|
||||
msg = ('Authentication failure of type "eauth" occurred for '
|
||||
'user {0}.').format(load.get('username', 'UNKNOWN'))
|
||||
log.warning(msg)
|
||||
return dict(error=dict(name='EauthAuthenticationError',
|
||||
log.error(
|
||||
'Exception occurred in the wheel system: {0}'.format(exc)
|
||||
)
|
||||
return dict(error=dict(name=exc.__class__.__name__,
|
||||
args=exc.args,
|
||||
message=str(exc)))
|
||||
else:
|
||||
atype = 'user'
|
||||
if 'key' not in load:
|
||||
msg = 'Authentication failure of type "user" occurred'
|
||||
log.warning(msg)
|
||||
return dict(error=dict(name='UserAuthenticationError',
|
||||
message=msg))
|
||||
if load['eauth'] not in self.opts['external_auth']:
|
||||
# The eauth system is not enabled, fail
|
||||
msg = ('Authentication failure of type "eauth" occurred for '
|
||||
'user {0}.').format(load.get('username', 'UNKNOWN'))
|
||||
log.warning(msg)
|
||||
return dict(error=dict(name='EauthAuthenticationError',
|
||||
key = load.pop('key')
|
||||
|
||||
if 'user' in load:
|
||||
username = load['user']
|
||||
auth_user = salt.auth.AuthUser(username)
|
||||
if auth_user.is_sudo:
|
||||
username = self.opts.get('user', 'root')
|
||||
else:
|
||||
username = salt.utils.get_user()
|
||||
|
||||
if username not in self.key and \
|
||||
key != self.key[username] and \
|
||||
key != self.key['root']:
|
||||
msg = 'Authentication failure of type "user" occurred for user {0}'.format(username)
|
||||
log.warning(msg)
|
||||
return dict(error=dict(name='UserAuthenticationError',
|
||||
message=msg))
|
||||
|
||||
if not atype == 'user':
|
||||
auth_list = []
|
||||
if '*' in self.opts['external_auth'][load['eauth']]:
|
||||
auth_list.extend(self.opts['external_auth'][load['eauth']]['*'])
|
||||
if username in self.opts['external_auth'][load['eauth']]:
|
||||
auth_list = self.opts['external_auth'][load['eauth']][username]
|
||||
good = self.ckminions.wheel_check(auth_list, load['fun'])
|
||||
if not good:
|
||||
msg = ('Authentication failure of type "{0}" occurred for '
|
||||
'user {1}.').format(atype, load.get('username', 'UNKNOWN'))
|
||||
log.warning(msg)
|
||||
return dict(error=dict(name='EauthAuthenticationError',
|
||||
message=msg))
|
||||
|
||||
# Authenticated. Do the job.
|
||||
jid = salt.utils.jid.gen_jid()
|
||||
fun = load.pop('fun')
|
||||
tag = tagify(jid, prefix='wheel')
|
||||
data = {'fun': "wheel.{0}".format(fun),
|
||||
'jid': jid,
|
||||
'tag': tag,
|
||||
'user': username}
|
||||
try:
|
||||
name = self.loadauth.load_name(load)
|
||||
if not ((name in self.opts['external_auth'][load['eauth']]) |
|
||||
('*' in self.opts['external_auth'][load['eauth']])):
|
||||
msg = ('Authentication failure of type "eauth" occurred for '
|
||||
'user {0}.').format(load.get('username', 'UNKNOWN'))
|
||||
log.warning(msg)
|
||||
return dict(error=dict(name='EauthAuthenticationError',
|
||||
message=msg))
|
||||
if not self.loadauth.time_auth(load):
|
||||
msg = ('Authentication failure of type "eauth" occurred for '
|
||||
'user {0}.').format(load.get('username', 'UNKNOWN'))
|
||||
log.warning(msg)
|
||||
return dict(error=dict(name='EauthAuthenticationError',
|
||||
message=msg))
|
||||
good = self.ckminions.wheel_check(
|
||||
self.opts['external_auth'][load['eauth']][name]
|
||||
if name in self.opts['external_auth'][load['eauth']]
|
||||
else self.opts['external_auth'][token['eauth']]['*'],
|
||||
load['fun'])
|
||||
if not good:
|
||||
msg = ('Authentication failure of type "eauth" occurred for '
|
||||
'user {0}.').format(load.get('username', 'UNKNOWN'))
|
||||
log.warning(msg)
|
||||
return dict(error=dict(name='EauthAuthenticationError',
|
||||
message=msg))
|
||||
|
||||
jid = salt.utils.jid.gen_jid()
|
||||
fun = load.pop('fun')
|
||||
tag = tagify(jid, prefix='wheel')
|
||||
data = {'fun': "wheel.{0}".format(fun),
|
||||
'jid': jid,
|
||||
'tag': tag,
|
||||
'user': load.get('username', 'UNKNOWN')}
|
||||
try:
|
||||
self.event.fire_event(data, tagify([jid, 'new'], 'wheel'))
|
||||
ret = self.wheel_.call_func(fun, **load)
|
||||
data['return'] = ret
|
||||
data['success'] = True
|
||||
self.event.fire_event(data, tagify([jid, 'ret'], 'wheel'))
|
||||
return {'tag': tag,
|
||||
'data': data}
|
||||
except Exception as exc:
|
||||
log.error('Exception occurred while '
|
||||
'introspecting {0}: {1}'.format(fun, exc))
|
||||
data['return'] = 'Exception occurred in wheel {0}: {1}: {2}'.format(
|
||||
fun,
|
||||
exc.__class__.__name__,
|
||||
exc,
|
||||
)
|
||||
self.event.fire_event(data, tagify([jid, 'ret'], 'wheel'))
|
||||
return {'tag': tag,
|
||||
'data': data}
|
||||
|
||||
self.event.fire_event(data, tagify([jid, 'new'], 'wheel'))
|
||||
ret = self.wheel_.call_func(fun, **load)
|
||||
data['return'] = ret
|
||||
data['success'] = True
|
||||
self.event.fire_event(data, tagify([jid, 'ret'], 'wheel'))
|
||||
return {'tag': tag,
|
||||
'data': data}
|
||||
except Exception as exc:
|
||||
log.error(
|
||||
'Exception occurred in the wheel system: {0}'.format(exc)
|
||||
)
|
||||
return dict(error=dict(name=exc.__class__.__name__,
|
||||
args=exc.args,
|
||||
message=str(exc)))
|
||||
log.error('Exception occurred while '
|
||||
'introspecting {0}: {1}'.format(fun, exc))
|
||||
data['return'] = 'Exception occurred in wheel {0}: {1}: {2}'.format(
|
||||
fun,
|
||||
exc.__class__.__name__,
|
||||
exc,
|
||||
)
|
||||
data['success'] = False
|
||||
self.event.fire_event(data, tagify([jid, 'ret'], 'wheel'))
|
||||
return {'tag': tag,
|
||||
'data': data}
|
||||
|
||||
def mk_token(self, load):
|
||||
'''
|
||||
|
571
salt/key.py
571
salt/key.py
@ -16,10 +16,11 @@ import hashlib
|
||||
import logging
|
||||
|
||||
# Import salt libs
|
||||
import salt.crypt
|
||||
import salt.client
|
||||
import salt.exceptions
|
||||
import salt.crypt
|
||||
import salt.daemons.masterapi
|
||||
import salt.exceptions
|
||||
import salt.minion
|
||||
import salt.utils
|
||||
import salt.utils.event
|
||||
import salt.utils.kinds
|
||||
@ -51,412 +52,193 @@ class KeyCLI(object):
|
||||
'''
|
||||
def __init__(self, opts):
|
||||
self.opts = opts
|
||||
self.client = salt.wheel.WheelClient(opts)
|
||||
if self.opts['transport'] in ('zeromq', 'tcp'):
|
||||
self.key = Key(opts)
|
||||
self.key = Key
|
||||
else:
|
||||
self.key = RaetKey(opts)
|
||||
self.key = RaetKey
|
||||
self.auth = None
|
||||
|
||||
def list_status(self, status):
|
||||
'''
|
||||
Print out the keys under a named status
|
||||
def _update_opts(self):
|
||||
# get the key command
|
||||
for cmd in ('gen_keys',
|
||||
'gen_signature',
|
||||
'list',
|
||||
'list_all',
|
||||
'print',
|
||||
'print_all',
|
||||
'accept',
|
||||
'accept_all',
|
||||
'reject',
|
||||
'reject_all',
|
||||
'delete',
|
||||
'delete_all',
|
||||
'finger',
|
||||
'finger_all',
|
||||
'list_all'): # last is default
|
||||
if self.opts[cmd]:
|
||||
break
|
||||
# set match if needed
|
||||
if not cmd.startswith('gen_'):
|
||||
if cmd == 'list_all':
|
||||
self.opts['match'] = 'all'
|
||||
elif cmd.endswith('_all'):
|
||||
self.opts['match'] = '*'
|
||||
else:
|
||||
self.opts['match'] = self.opts[cmd]
|
||||
if cmd.startswith('accept'):
|
||||
self.opts['include_rejected'] = self.opts['include_all'] or self.opts['include_rejected']
|
||||
self.opts['include_accepted'] = False
|
||||
elif cmd.startswith('reject'):
|
||||
self.opts['include_accepted'] = self.opts['include_all'] or self.opts['include_accepted']
|
||||
self.opts['include_rejected'] = False
|
||||
elif cmd == 'gen_keys':
|
||||
self.opts['keydir'] = self.opts['gen_keys_dir']
|
||||
self.opts['keyname'] = self.opts['gen_keys']
|
||||
# match is set to opts, now we can forget about *_all commands
|
||||
self.opts['fun'] = cmd.replace('_all', '')
|
||||
|
||||
:param str status: A string indicating which set of keys to return
|
||||
'''
|
||||
keys = self.key.list_keys()
|
||||
if status.startswith('acc'):
|
||||
salt.output.display_output(
|
||||
{self.key.ACC: keys[self.key.ACC]},
|
||||
'key',
|
||||
self.opts
|
||||
)
|
||||
elif status.startswith(('pre', 'un')):
|
||||
salt.output.display_output(
|
||||
{self.key.PEND: keys[self.key.PEND]},
|
||||
'key',
|
||||
self.opts
|
||||
)
|
||||
elif status.startswith('rej'):
|
||||
salt.output.display_output(
|
||||
{self.key.REJ: keys[self.key.REJ]},
|
||||
'key',
|
||||
self.opts
|
||||
)
|
||||
elif status.startswith('den'):
|
||||
if self.key.DEN:
|
||||
salt.output.display_output(
|
||||
{self.key.DEN: keys[self.key.DEN]},
|
||||
'key',
|
||||
self.opts
|
||||
)
|
||||
elif status.startswith('all'):
|
||||
self.list_all()
|
||||
|
||||
def list_all(self):
|
||||
'''
|
||||
Print out all keys
|
||||
'''
|
||||
salt.output.display_output(
|
||||
self.key.list_keys(),
|
||||
'key',
|
||||
self.opts)
|
||||
|
||||
def accept(self, match, include_rejected=False, include_denied=False):
|
||||
'''
|
||||
Accept the keys matched
|
||||
|
||||
:param str match: A string to match against. i.e. 'web*'
|
||||
:param bool include_rejected: Whether or not to accept a matched key that was formerly rejected
|
||||
:param bool include_denied: Whether or not to accept a matched key that was formerly denied
|
||||
'''
|
||||
def _print_accepted(matches, after_match):
|
||||
if self.key.ACC in after_match:
|
||||
accepted = sorted(
|
||||
set(after_match[self.key.ACC]).difference(
|
||||
set(matches.get(self.key.ACC, []))
|
||||
)
|
||||
)
|
||||
for key in accepted:
|
||||
print('Key for minion {0} accepted.'.format(key))
|
||||
|
||||
matches = self.key.name_match(match)
|
||||
keys = {}
|
||||
if self.key.PEND in matches:
|
||||
keys[self.key.PEND] = matches[self.key.PEND]
|
||||
if include_rejected and bool(matches.get(self.key.REJ)):
|
||||
keys[self.key.REJ] = matches[self.key.REJ]
|
||||
if include_denied and bool(matches.get(self.key.DEN)):
|
||||
keys[self.key.DEN] = matches[self.key.DEN]
|
||||
if not keys:
|
||||
msg = (
|
||||
'The key glob \'{0}\' does not match any unaccepted{1} keys.'
|
||||
.format(match, (('', ' or denied'),
|
||||
(' or rejected', ', rejected or denied')
|
||||
)[include_rejected][include_denied])
|
||||
)
|
||||
print(msg)
|
||||
raise salt.exceptions.SaltSystemExit(code=1)
|
||||
if not self.opts.get('yes', False):
|
||||
print('The following keys are going to be accepted:')
|
||||
salt.output.display_output(
|
||||
keys,
|
||||
'key',
|
||||
self.opts)
|
||||
try:
|
||||
veri = input('Proceed? [n/Y] ')
|
||||
except KeyboardInterrupt:
|
||||
raise SystemExit("\nExiting on CTRL-c")
|
||||
if not veri or veri.lower().startswith('y'):
|
||||
_print_accepted(
|
||||
matches,
|
||||
self.key.accept(
|
||||
match_dict=keys,
|
||||
include_rejected=include_rejected,
|
||||
include_denied=include_denied
|
||||
)
|
||||
)
|
||||
else:
|
||||
print('The following keys are going to be accepted:')
|
||||
salt.output.display_output(
|
||||
keys,
|
||||
'key',
|
||||
self.opts)
|
||||
_print_accepted(
|
||||
matches,
|
||||
self.key.accept(
|
||||
match_dict=keys,
|
||||
include_rejected=include_rejected,
|
||||
include_denied=include_denied
|
||||
)
|
||||
)
|
||||
|
||||
def accept_all(self, include_rejected=False, include_denied=False):
|
||||
'''
|
||||
Accept all keys
|
||||
|
||||
:param bool include_rejected: Whether or not to accept a matched key that was formerly rejected
|
||||
:param bool include_denied: Whether or not to accept a matched key that was formerly denied
|
||||
'''
|
||||
self.accept('*', include_rejected=include_rejected, include_denied=include_denied)
|
||||
|
||||
def delete(self, match):
|
||||
'''
|
||||
Delete the matched keys
|
||||
|
||||
:param str match: A string to match against. i.e. 'web*'
|
||||
'''
|
||||
def _print_deleted(matches, after_match):
|
||||
deleted = []
|
||||
for keydir in (self.key.ACC, self.key.PEND, self.key.REJ):
|
||||
deleted.extend(list(
|
||||
set(matches.get(keydir, [])).difference(
|
||||
set(after_match.get(keydir, []))
|
||||
)
|
||||
))
|
||||
for key in sorted(deleted):
|
||||
print('Key for minion {0} deleted.'.format(key))
|
||||
|
||||
matches = self.key.name_match(match)
|
||||
if not matches:
|
||||
print(
|
||||
'The key glob \'{0}\' does not match any accepted, unaccepted '
|
||||
'or rejected keys.'.format(match)
|
||||
)
|
||||
raise salt.exceptions.SaltSystemExit(code=1)
|
||||
if not self.opts.get('yes', False):
|
||||
print('The following keys are going to be deleted:')
|
||||
salt.output.display_output(
|
||||
matches,
|
||||
'key',
|
||||
self.opts)
|
||||
try:
|
||||
veri = input('Proceed? [N/y] ')
|
||||
except KeyboardInterrupt:
|
||||
raise SystemExit("\nExiting on CTRL-c")
|
||||
if veri.lower().startswith('y'):
|
||||
_print_deleted(
|
||||
matches,
|
||||
self.key.delete_key(match_dict=matches, revoke_auth=True)
|
||||
)
|
||||
else:
|
||||
print('Deleting the following keys:')
|
||||
salt.output.display_output(
|
||||
matches,
|
||||
'key',
|
||||
self.opts)
|
||||
_print_deleted(
|
||||
matches,
|
||||
self.key.delete_key(match_dict=matches)
|
||||
)
|
||||
|
||||
def delete_all(self):
|
||||
'''
|
||||
Delete all keys
|
||||
'''
|
||||
self.delete('*')
|
||||
|
||||
def reject(self, match, include_accepted=False, include_denied=False):
|
||||
'''
|
||||
Reject the matched keys
|
||||
|
||||
:param str match: A string to match against. i.e. 'web*'
|
||||
:param bool include_accepted: Whether or not to reject a matched key
|
||||
that was formerly accepted
|
||||
:param bool include_denied: Whether or not to reject a matched key
|
||||
that was formerly denied
|
||||
'''
|
||||
def _print_rejected(matches, after_match):
|
||||
if self.key.REJ in after_match:
|
||||
rejected = sorted(
|
||||
set(after_match[self.key.REJ]).difference(
|
||||
set(matches.get(self.key.REJ, []))
|
||||
)
|
||||
)
|
||||
for key in rejected:
|
||||
print('Key for minion {0} rejected.'.format(key))
|
||||
|
||||
matches = self.key.name_match(match)
|
||||
keys = {}
|
||||
if self.key.PEND in matches:
|
||||
keys[self.key.PEND] = matches[self.key.PEND]
|
||||
if include_accepted and bool(matches.get(self.key.ACC)):
|
||||
keys[self.key.ACC] = matches[self.key.ACC]
|
||||
if include_denied and bool(matches.get(self.key.DEN)):
|
||||
keys[self.key.DEN] = matches[self.key.DEN]
|
||||
if not keys:
|
||||
msg = 'The key glob \'{0}\' does not match any {1} keys.'.format(
|
||||
match,
|
||||
(('unaccepted', 'unaccepted or denied'),
|
||||
('accepted or unaccepted', 'accepted, unaccepted or denied')
|
||||
)[include_accepted][include_denied]
|
||||
)
|
||||
print(msg)
|
||||
def _init_auth(self):
|
||||
if self.auth:
|
||||
return
|
||||
if not self.opts.get('yes', False):
|
||||
print('The following keys are going to be rejected:')
|
||||
salt.output.display_output(
|
||||
keys,
|
||||
'key',
|
||||
self.opts)
|
||||
veri = input('Proceed? [n/Y] ')
|
||||
if veri.lower().startswith('n'):
|
||||
return
|
||||
_print_rejected(
|
||||
matches,
|
||||
self.key.reject(
|
||||
match_dict=matches,
|
||||
include_accepted=include_accepted,
|
||||
include_denied=include_denied
|
||||
)
|
||||
|
||||
low = {}
|
||||
skip_perm_errors = self.opts['eauth'] != ''
|
||||
|
||||
if self.opts['eauth']:
|
||||
if 'token' in self.opts:
|
||||
try:
|
||||
with salt.utils.fopen(os.path.join(self.opts['cachedir'], '.root_key'), 'r') as fp_:
|
||||
low['key'] = fp_.readline()
|
||||
except IOError:
|
||||
low['token'] = self.opts['token']
|
||||
#
|
||||
# If using eauth and a token hasn't already been loaded into
|
||||
# low, prompt the user to enter auth credentials
|
||||
if 'token' not in low and 'key' not in low and self.opts['eauth']:
|
||||
# This is expensive. Don't do it unless we need to.
|
||||
resolver = salt.auth.Resolver(self.opts)
|
||||
res = resolver.cli(self.opts['eauth'])
|
||||
if self.opts['mktoken'] and res:
|
||||
tok = resolver.token_cli(
|
||||
self.opts['eauth'],
|
||||
res
|
||||
)
|
||||
if tok:
|
||||
low['token'] = tok.get('token', '')
|
||||
if not res:
|
||||
log.error('Authentication failed')
|
||||
return {}
|
||||
low.update(res)
|
||||
low['eauth'] = self.opts['eauth']
|
||||
else:
|
||||
low['user'] = salt.utils.get_specific_user()
|
||||
low['key'] = salt.utils.get_master_key(low['user'], self.opts, skip_perm_errors)
|
||||
|
||||
self.auth = low
|
||||
|
||||
def _run_cmd(self, cmd, args=None):
|
||||
fun_name = 'key.{0}'.format(cmd)
|
||||
fun = self.client.functions[fun_name]
|
||||
if args is None:
|
||||
argspec = salt.utils.args.get_function_argspec(fun)
|
||||
args = []
|
||||
if argspec.args:
|
||||
for arg in argspec.args:
|
||||
args.append(self.opts[arg])
|
||||
args, kwargs = salt.minion.load_args_and_kwargs(
|
||||
fun,
|
||||
args,
|
||||
self.opts,
|
||||
)
|
||||
|
||||
def reject_all(self, include_accepted=False, include_denied=False):
|
||||
'''
|
||||
Reject all keys
|
||||
low = {
|
||||
'fun': fun_name,
|
||||
'arg': args,
|
||||
'kwarg': kwargs,
|
||||
}
|
||||
|
||||
:param bool include_accepted: Whether or not to reject a matched key that was formerly accepted
|
||||
:param bool include_denied: Whether or not to reject a matched key that was formerly denied
|
||||
'''
|
||||
self.reject('*', include_accepted=include_accepted, include_denied=include_denied)
|
||||
self._init_auth()
|
||||
low.update(self.auth)
|
||||
|
||||
def print_key(self, match):
|
||||
'''
|
||||
Print out a single key
|
||||
# Execute the key request!
|
||||
ret = self.client.cmd_sync(low)
|
||||
|
||||
:param str match: A string to match against. i.e. 'web*'
|
||||
'''
|
||||
matches = self.key.key_str(match)
|
||||
salt.output.display_output(
|
||||
matches,
|
||||
'key',
|
||||
self.opts)
|
||||
ret = ret['data']['return']
|
||||
if isinstance(ret, dict) and 'local' in ret:
|
||||
ret.pop('local', None)
|
||||
|
||||
def print_all(self):
|
||||
'''
|
||||
Print out all managed keys
|
||||
'''
|
||||
self.print_key('*')
|
||||
return ret
|
||||
|
||||
def finger(self, match):
|
||||
'''
|
||||
Print out the fingerprints for the matched keys
|
||||
def _filter_ret(self, cmd, ret):
|
||||
if cmd.startswith('delete'):
|
||||
return ret
|
||||
|
||||
:param str match: A string to match against. i.e. 'web*'
|
||||
'''
|
||||
matches = self.key.finger(match)
|
||||
salt.output.display_output(
|
||||
matches,
|
||||
'key',
|
||||
self.opts)
|
||||
keys = {}
|
||||
if self.key.PEND in ret:
|
||||
keys[self.key.PEND] = ret[self.key.PEND]
|
||||
if self.opts['include_accepted'] and bool(ret.get(self.key.ACC)):
|
||||
keys[self.key.ACC] = ret[self.key.ACC]
|
||||
if self.opts['include_rejected'] and bool(ret.get(self.key.REJ)):
|
||||
keys[self.key.REJ] = ret[self.key.REJ]
|
||||
if self.opts['include_denied'] and bool(ret.get(self.key.DEN)):
|
||||
keys[self.key.DEN] = ret[self.key.DEN]
|
||||
return keys
|
||||
|
||||
def finger_all(self):
|
||||
'''
|
||||
Print out all fingerprints
|
||||
'''
|
||||
matches = self.key.finger('*')
|
||||
salt.output.display_output(
|
||||
matches,
|
||||
'key',
|
||||
self.opts)
|
||||
|
||||
def prep_signature(self):
|
||||
'''
|
||||
Searches for usable keys to create the
|
||||
master public-key signature
|
||||
'''
|
||||
self.privkey = None
|
||||
self.pubkey = None
|
||||
|
||||
# check given pub-key
|
||||
if self.opts['pub']:
|
||||
if not os.path.isfile(self.opts['pub']):
|
||||
print('Public-key {0} does not exist'.format(self.opts['pub']))
|
||||
return
|
||||
self.pubkey = self.opts['pub']
|
||||
|
||||
# default to master.pub
|
||||
def _print_no_match(self, cmd, match):
|
||||
statuses = ['unaccepted']
|
||||
if self.opts['include_accepted']:
|
||||
statuses.append('accepted')
|
||||
if self.opts['include_rejected']:
|
||||
statuses.append('rejected')
|
||||
if self.opts['include_denied']:
|
||||
statuses.append('denied')
|
||||
if len(statuses) == 1:
|
||||
stat_str = statuses[0]
|
||||
else:
|
||||
mpub = self.opts['pki_dir'] + '/' + 'master.pub'
|
||||
if os.path.isfile(mpub):
|
||||
self.pubkey = mpub
|
||||
|
||||
# check given priv-key
|
||||
if self.opts['priv']:
|
||||
if not os.path.isfile(self.opts['priv']):
|
||||
print('Private-key {0} does not exist'.format(self.opts['priv']))
|
||||
return
|
||||
self.privkey = self.opts['priv']
|
||||
|
||||
# default to master_sign.pem
|
||||
else:
|
||||
mpriv = self.opts['pki_dir'] + '/' + 'master_sign.pem'
|
||||
if os.path.isfile(mpriv):
|
||||
self.privkey = mpriv
|
||||
|
||||
if not self.privkey:
|
||||
if self.opts['auto_create']:
|
||||
print('Generating new signing key-pair {0}.* in {1}'
|
||||
''.format(self.opts['master_sign_key_name'],
|
||||
self.opts['pki_dir']))
|
||||
salt.crypt.gen_keys(self.opts['pki_dir'],
|
||||
self.opts['master_sign_key_name'],
|
||||
self.opts['keysize'],
|
||||
self.opts.get('user'))
|
||||
|
||||
self.privkey = self.opts['pki_dir'] + '/' + self.opts['master_sign_key_name'] + '.pem'
|
||||
else:
|
||||
print('No usable private-key found')
|
||||
return
|
||||
|
||||
if not self.pubkey:
|
||||
print('No usable public-key found')
|
||||
return
|
||||
|
||||
print('Using public-key {0}'.format(self.pubkey))
|
||||
print('Using private-key {0}'.format(self.privkey))
|
||||
|
||||
if self.opts['signature_path']:
|
||||
if not os.path.isdir(self.opts['signature_path']):
|
||||
print('target directory {0} does not exist'
|
||||
''.format(self.opts['signature_path']))
|
||||
else:
|
||||
self.opts['signature_path'] = self.opts['pki_dir']
|
||||
|
||||
sign_path = self.opts['signature_path'] + '/' + self.opts['master_pubkey_signature']
|
||||
|
||||
self.key.gen_signature(self.privkey,
|
||||
self.pubkey,
|
||||
sign_path)
|
||||
stat_str = '{0} or {1}'.format(', '.join(statuses[:-1]), statuses[-1])
|
||||
msg = 'The key glob \'{0}\' does not match any {1} keys.'.format(match, stat_str)
|
||||
print(msg)
|
||||
|
||||
def run(self):
|
||||
'''
|
||||
Run the logic for saltkey
|
||||
'''
|
||||
if self.opts['gen_keys']:
|
||||
self.key.gen_keys()
|
||||
return
|
||||
elif self.opts['gen_signature']:
|
||||
self.prep_signature()
|
||||
return
|
||||
if self.opts['list']:
|
||||
self.list_status(self.opts['list'])
|
||||
elif self.opts['list_all']:
|
||||
self.list_all()
|
||||
elif self.opts['print']:
|
||||
self.print_key(self.opts['print'])
|
||||
elif self.opts['print_all']:
|
||||
self.print_all()
|
||||
elif self.opts['accept']:
|
||||
self.accept(
|
||||
self.opts['accept'],
|
||||
include_rejected=self.opts['include_all'] or self.opts['include_rejected'],
|
||||
include_denied=self.opts['include_denied']
|
||||
)
|
||||
elif self.opts['accept_all']:
|
||||
self.accept_all(
|
||||
include_rejected=self.opts['include_all'] or self.opts['include_rejected'],
|
||||
include_denied=self.opts['include_denied']
|
||||
)
|
||||
elif self.opts['reject']:
|
||||
self.reject(
|
||||
self.opts['reject'],
|
||||
include_accepted=self.opts['include_all'] or self.opts['include_accepted'],
|
||||
include_denied=self.opts['include_denied']
|
||||
)
|
||||
elif self.opts['reject_all']:
|
||||
self.reject_all(
|
||||
include_accepted=self.opts['include_all'] or self.opts['include_accepted'],
|
||||
include_denied=self.opts['include_denied']
|
||||
)
|
||||
elif self.opts['delete']:
|
||||
self.delete(self.opts['delete'])
|
||||
elif self.opts['delete_all']:
|
||||
self.delete_all()
|
||||
elif self.opts['finger']:
|
||||
self.finger(self.opts['finger'])
|
||||
elif self.opts['finger_all']:
|
||||
self.finger_all()
|
||||
else:
|
||||
self.list_all()
|
||||
self._update_opts()
|
||||
cmd = self.opts['fun']
|
||||
|
||||
veri = None
|
||||
if cmd in ('accept', 'reject', 'delete'):
|
||||
ret = self._run_cmd('list_match')
|
||||
if not isinstance(ret, dict):
|
||||
salt.output.display_output(ret, 'key', opts=self.opts)
|
||||
return ret
|
||||
ret = self._filter_ret(cmd, ret)
|
||||
if not ret:
|
||||
self._print_no_match(cmd, self.opts['match'])
|
||||
return
|
||||
print('The following keys are going to be {0}ed:'.format(cmd))
|
||||
salt.output.display_output(ret, 'key', opts=self.opts)
|
||||
|
||||
if not self.opts.get('yes', False):
|
||||
try:
|
||||
if cmd.startswith('delete'):
|
||||
veri = input('Proceed? [N/y] ')
|
||||
if not veri:
|
||||
veri = 'n'
|
||||
else:
|
||||
veri = input('Proceed? [n/Y] ')
|
||||
if not veri:
|
||||
veri = 'y'
|
||||
except KeyboardInterrupt:
|
||||
raise SystemExit("\nExiting on CTRL-c")
|
||||
|
||||
if veri is None or veri.lower().startswith('y'):
|
||||
ret = self._run_cmd(cmd)
|
||||
if isinstance(ret, dict):
|
||||
salt.output.display_output(ret, 'key', opts=self.opts)
|
||||
else:
|
||||
salt.output.display_output({'return': ret}, 'key', opts=self.opts)
|
||||
|
||||
|
||||
class MultiKeyCLI(KeyCLI):
|
||||
@ -692,14 +474,13 @@ class Key(object):
|
||||
# We have to differentiate between RaetKey._check_minions_directories
|
||||
# and Zeromq-Keys. Raet-Keys only have three states while ZeroMQ-keys
|
||||
# havd an additional 'denied' state.
|
||||
if self.opts['transport'] in ('zeromq', 'tcp'):
|
||||
key_dirs = self._check_minions_directories()
|
||||
else:
|
||||
key_dirs = self._check_minions_directories()
|
||||
key_dirs = self._check_minions_directories()
|
||||
|
||||
ret = {}
|
||||
|
||||
for dir_ in key_dirs:
|
||||
if dir_ is None:
|
||||
continue
|
||||
ret[os.path.basename(dir_)] = []
|
||||
try:
|
||||
for fn_ in salt.utils.isorted(os.listdir(dir_)):
|
||||
@ -743,7 +524,7 @@ class Key(object):
|
||||
if not fn_.startswith('.'):
|
||||
if os.path.isfile(os.path.join(rej, fn_)):
|
||||
ret[os.path.basename(rej)].append(fn_)
|
||||
elif match.startswith('den'):
|
||||
elif match.startswith('den') and den is not None:
|
||||
ret[os.path.basename(den)] = []
|
||||
for fn_ in salt.utils.isorted(os.listdir(den)):
|
||||
if not fn_.startswith('.'):
|
||||
@ -1064,7 +845,7 @@ class RaetKey(Key):
|
||||
accepted = os.path.join(self.opts['pki_dir'], self.ACC)
|
||||
pre = os.path.join(self.opts['pki_dir'], self.PEND)
|
||||
rejected = os.path.join(self.opts['pki_dir'], self.REJ)
|
||||
return accepted, pre, rejected
|
||||
return accepted, pre, rejected, None
|
||||
|
||||
def check_minion_cache(self, preserve_minions=False):
|
||||
'''
|
||||
@ -1151,7 +932,7 @@ class RaetKey(Key):
|
||||
If the key has been accepted return "accepted"
|
||||
if the key should be rejected, return "rejected"
|
||||
'''
|
||||
acc, pre, rej = self._check_minions_directories() # pylint: disable=W0632
|
||||
acc, pre, rej, _ = self._check_minions_directories() # pylint: disable=W0632
|
||||
acc_path = os.path.join(acc, minion_id)
|
||||
pre_path = os.path.join(pre, minion_id)
|
||||
rej_path = os.path.join(rej, minion_id)
|
||||
|
129
salt/master.py
129
salt/master.py
@ -1790,6 +1790,7 @@ class ClearFuncs(object):
|
||||
Send a master control function back to the wheel system
|
||||
'''
|
||||
# All wheel ops pass through eauth
|
||||
username = None
|
||||
if 'token' in clear_load:
|
||||
auth_error = self.process_token(clear_load['token'],
|
||||
clear_load['fun'],
|
||||
@ -1798,77 +1799,77 @@ class ClearFuncs(object):
|
||||
return auth_error
|
||||
else:
|
||||
token = self.loadauth.get_tok(clear_load.pop('token'))
|
||||
|
||||
jid = salt.utils.jid.gen_jid()
|
||||
fun = clear_load.pop('fun')
|
||||
tag = tagify(jid, prefix='wheel')
|
||||
data = {'fun': "wheel.{0}".format(fun),
|
||||
'jid': jid,
|
||||
'tag': tag,
|
||||
'user': token['name']}
|
||||
username = token['name']
|
||||
elif 'eauth' in clear_load:
|
||||
try:
|
||||
self.event.fire_event(data, tagify([jid, 'new'], 'wheel'))
|
||||
ret = self.wheel_.call_func(fun, **clear_load)
|
||||
data['return'] = ret
|
||||
data['success'] = True
|
||||
self.event.fire_event(data, tagify([jid, 'ret'], 'wheel'))
|
||||
return {'tag': tag,
|
||||
'data': data}
|
||||
except Exception as exc:
|
||||
log.error(exc)
|
||||
log.error('Exception occurred while '
|
||||
'introspecting {0}: {1}'.format(fun, exc))
|
||||
data['return'] = 'Exception occurred in wheel {0}: {1}: {2}'.format(
|
||||
fun,
|
||||
exc.__class__.__name__,
|
||||
exc,
|
||||
)
|
||||
data['success'] = False
|
||||
self.event.fire_event(data, tagify([jid, 'ret'], 'wheel'))
|
||||
return {'tag': tag,
|
||||
'data': data}
|
||||
try:
|
||||
eauth_error = self.process_eauth(clear_load, 'wheel')
|
||||
if eauth_error:
|
||||
return eauth_error
|
||||
eauth_error = self.process_eauth(clear_load, 'wheel')
|
||||
if eauth_error:
|
||||
return eauth_error
|
||||
|
||||
# No error occurred, consume the password from the clear_load if
|
||||
# passed
|
||||
clear_load.pop('password', None)
|
||||
jid = salt.utils.jid.gen_jid()
|
||||
fun = clear_load.pop('fun')
|
||||
tag = tagify(jid, prefix='wheel')
|
||||
data = {'fun': "wheel.{0}".format(fun),
|
||||
'jid': jid,
|
||||
'tag': tag,
|
||||
'user': clear_load.pop('username', 'UNKNOWN')}
|
||||
try:
|
||||
self.event.fire_event(data, tagify([jid, 'new'], 'wheel'))
|
||||
ret = self.wheel_.call_func(fun, **clear_load)
|
||||
data['return'] = ret
|
||||
data['success'] = True
|
||||
self.event.fire_event(data, tagify([jid, 'ret'], 'wheel'))
|
||||
return {'tag': tag,
|
||||
'data': data}
|
||||
# No error occurred, consume the password from the clear_load if
|
||||
# passed
|
||||
clear_load.pop('password', None)
|
||||
username = clear_load.pop('username', 'UNKNOWN')
|
||||
except Exception as exc:
|
||||
log.error('Exception occurred while '
|
||||
'introspecting {0}: {1}'.format(fun, exc))
|
||||
data['return'] = 'Exception occurred in wheel {0}: {1}: {2}'.format(
|
||||
fun,
|
||||
exc.__class__.__name__,
|
||||
exc,
|
||||
log.error(
|
||||
'Exception occurred in the wheel system: {0}'.format(exc)
|
||||
)
|
||||
self.event.fire_event(data, tagify([jid, 'ret'], 'wheel'))
|
||||
return {'tag': tag,
|
||||
'data': data}
|
||||
return dict(error=dict(name=exc.__class__.__name__,
|
||||
args=exc.args,
|
||||
message=str(exc)))
|
||||
else:
|
||||
if 'key' not in clear_load:
|
||||
msg = 'Authentication failure of type "user" occurred'
|
||||
log.warning(msg)
|
||||
return dict(error=dict(name='UserAuthenticationError',
|
||||
message=msg))
|
||||
key = clear_load.pop('key')
|
||||
|
||||
if 'user' in clear_load:
|
||||
username = clear_load['user']
|
||||
auth_user = salt.auth.AuthUser(username)
|
||||
if auth_user.is_sudo:
|
||||
username = self.opts.get('user', 'root')
|
||||
else:
|
||||
username = salt.utils.get_user()
|
||||
|
||||
if username not in self.key and \
|
||||
key != self.key[username] and \
|
||||
key != self.key['root']:
|
||||
msg = 'Authentication failure of type "user" occurred for user {0}'.format(username)
|
||||
log.warning(msg)
|
||||
return dict(error=dict(name='UserAuthenticationError',
|
||||
message=msg))
|
||||
|
||||
# Authorized. Do the job!
|
||||
try:
|
||||
jid = salt.utils.jid.gen_jid()
|
||||
fun = clear_load.pop('fun')
|
||||
tag = tagify(jid, prefix='wheel')
|
||||
data = {'fun': "wheel.{0}".format(fun),
|
||||
'jid': jid,
|
||||
'tag': tag,
|
||||
'user': username}
|
||||
|
||||
self.event.fire_event(data, tagify([jid, 'new'], 'wheel'))
|
||||
ret = self.wheel_.call_func(fun, **clear_load)
|
||||
data['return'] = ret
|
||||
data['success'] = True
|
||||
self.event.fire_event(data, tagify([jid, 'ret'], 'wheel'))
|
||||
return {'tag': tag,
|
||||
'data': data}
|
||||
except Exception as exc:
|
||||
log.error(
|
||||
'Exception occurred in the wheel system: {0}'.format(exc)
|
||||
log.error('Exception occurred while '
|
||||
'introspecting {0}: {1}'.format(fun, exc))
|
||||
data['return'] = 'Exception occurred in wheel {0}: {1}: {2}'.format(
|
||||
fun,
|
||||
exc.__class__.__name__,
|
||||
exc,
|
||||
)
|
||||
return dict(error=dict(name=exc.__class__.__name__,
|
||||
args=exc.args,
|
||||
message=str(exc)))
|
||||
data['success'] = False
|
||||
self.event.fire_event(data, tagify([jid, 'ret'], 'wheel'))
|
||||
return {'tag': tag,
|
||||
'data': data}
|
||||
|
||||
def mk_token(self, clear_load):
|
||||
'''
|
||||
|
@ -2165,7 +2165,8 @@ class SaltKeyOptionParser(six.with_metaclass(OptionParserMeta,
|
||||
OutputOptionsMixIn,
|
||||
RunUserMixin,
|
||||
HardCrashMixin,
|
||||
SaltfileMixIn)):
|
||||
SaltfileMixIn,
|
||||
EAuthMixIn)):
|
||||
|
||||
description = 'Salt key is used to manage Salt authentication keys'
|
||||
|
||||
@ -2181,6 +2182,7 @@ class SaltKeyOptionParser(six.with_metaclass(OptionParserMeta,
|
||||
|
||||
def _mixin_setup(self):
|
||||
actions_group = optparse.OptionGroup(self, 'Actions')
|
||||
actions_group.set_conflict_handler('resolve')
|
||||
actions_group.add_option(
|
||||
'-l', '--list',
|
||||
default='',
|
||||
@ -2206,7 +2208,7 @@ class SaltKeyOptionParser(six.with_metaclass(OptionParserMeta,
|
||||
default='',
|
||||
help='Accept the specified public key (use --include-rejected and '
|
||||
'--include-denied to match rejected and denied keys in '
|
||||
'addition to pending keys). Globs are supported.'
|
||||
'addition to pending keys). Globs are supported.',
|
||||
)
|
||||
|
||||
actions_group.add_option(
|
||||
|
@ -64,7 +64,8 @@ class WheelClient(salt.client.mixins.SyncClientMixin,
|
||||
':' + str(self.opts['ret_port'])
|
||||
channel = salt.transport.Channel.factory(self.opts,
|
||||
crypt='clear',
|
||||
master_uri=master_uri)
|
||||
master_uri=master_uri,
|
||||
usage='master_call')
|
||||
ret = channel.send(load)
|
||||
if isinstance(ret, collections.Mapping):
|
||||
if 'error' in ret:
|
||||
|
@ -7,22 +7,26 @@ Wheel system wrapper for key system
|
||||
from __future__ import absolute_import
|
||||
import os
|
||||
import hashlib
|
||||
import logging
|
||||
|
||||
# Import salt libs
|
||||
import salt.key
|
||||
from salt.key import get_key
|
||||
import salt.crypt
|
||||
import salt.utils
|
||||
|
||||
__func_alias__ = {
|
||||
'list_': 'list'
|
||||
'list_': 'list',
|
||||
'key_str': 'print',
|
||||
}
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def list_(match):
|
||||
'''
|
||||
List all the keys under a named status
|
||||
'''
|
||||
skey = salt.key.Key(__opts__)
|
||||
skey = get_key(__opts__)
|
||||
return skey.list_status(match)
|
||||
|
||||
|
||||
@ -30,15 +34,23 @@ def list_all():
|
||||
'''
|
||||
List all the keys
|
||||
'''
|
||||
skey = salt.key.Key(__opts__)
|
||||
skey = get_key(__opts__)
|
||||
return skey.all_keys()
|
||||
|
||||
|
||||
def list_match(match):
|
||||
'''
|
||||
List all the keys based on a glob match
|
||||
'''
|
||||
skey = get_key(__opts__)
|
||||
return skey.name_match(match)
|
||||
|
||||
|
||||
def accept(match, include_rejected=False, include_denied=False):
|
||||
'''
|
||||
Accept keys based on a glob match
|
||||
'''
|
||||
skey = salt.key.Key(__opts__)
|
||||
skey = get_key(__opts__)
|
||||
return skey.accept(match, include_rejected=include_rejected, include_denied=include_denied)
|
||||
|
||||
|
||||
@ -59,7 +71,7 @@ def accept_dict(match):
|
||||
],
|
||||
}
|
||||
'''
|
||||
skey = salt.key.Key(__opts__)
|
||||
skey = get_key(__opts__)
|
||||
return skey.accept(match_dict=match)
|
||||
|
||||
|
||||
@ -67,7 +79,7 @@ def delete(match):
|
||||
'''
|
||||
Delete keys based on a glob match
|
||||
'''
|
||||
skey = salt.key.Key(__opts__)
|
||||
skey = get_key(__opts__)
|
||||
return skey.delete_key(match)
|
||||
|
||||
|
||||
@ -75,7 +87,7 @@ def delete_dict(match):
|
||||
'''
|
||||
Delete keys based on a dict of keys
|
||||
'''
|
||||
skey = salt.key.Key(__opts__)
|
||||
skey = get_key(__opts__)
|
||||
return skey.delete_key(match_dict=match)
|
||||
|
||||
|
||||
@ -83,7 +95,7 @@ def reject(match, include_accepted=False, include_denied=False):
|
||||
'''
|
||||
Reject keys based on a glob match
|
||||
'''
|
||||
skey = salt.key.Key(__opts__)
|
||||
skey = get_key(__opts__)
|
||||
return skey.reject(match, include_accepted=include_accepted, include_denied=include_denied)
|
||||
|
||||
|
||||
@ -91,7 +103,7 @@ def reject_dict(match):
|
||||
'''
|
||||
Reject keys based on a dict of keys
|
||||
'''
|
||||
skey = salt.key.Key(__opts__)
|
||||
skey = get_key(__opts__)
|
||||
return skey.reject(match_dict=match)
|
||||
|
||||
|
||||
@ -99,7 +111,7 @@ def key_str(match):
|
||||
'''
|
||||
Return the key strings
|
||||
'''
|
||||
skey = salt.key.Key(__opts__)
|
||||
skey = get_key(__opts__)
|
||||
return skey.key_str(match)
|
||||
|
||||
|
||||
@ -107,7 +119,7 @@ def finger(match):
|
||||
'''
|
||||
Return the matching key fingerprints
|
||||
'''
|
||||
skey = salt.key.Key(__opts__)
|
||||
skey = get_key(__opts__)
|
||||
return skey.finger(match)
|
||||
|
||||
|
||||
@ -143,3 +155,68 @@ def gen_accept(id_, keysize=2048, force=False):
|
||||
with salt.utils.fopen(acc_path, 'w+') as fp_:
|
||||
fp_.write(ret['pub'])
|
||||
return ret
|
||||
|
||||
|
||||
def gen_keys(keydir=None, keyname=None, keysize=None, user=None):
|
||||
'''
|
||||
Generate minion RSA public keypair
|
||||
'''
|
||||
skey = get_key(__opts__)
|
||||
return skey.gen_keys(keydir, keyname, keysize, user)
|
||||
|
||||
|
||||
def gen_signature(priv, pub, signature_path, auto_create=False, keysize=None):
|
||||
'''
|
||||
Generate master public-key-signature
|
||||
'''
|
||||
# check given pub-key
|
||||
if pub:
|
||||
if not os.path.isfile(pub):
|
||||
return 'Public-key {0} does not exist'.format(pub)
|
||||
# default to master.pub
|
||||
else:
|
||||
mpub = __opts__['pki_dir'] + '/' + 'master.pub'
|
||||
if os.path.isfile(mpub):
|
||||
pub = mpub
|
||||
|
||||
# check given priv-key
|
||||
if priv:
|
||||
if not os.path.isfile(priv):
|
||||
return 'Private-key {0} does not exist'.format(priv)
|
||||
# default to master_sign.pem
|
||||
else:
|
||||
mpriv = __opts__['pki_dir'] + '/' + 'master_sign.pem'
|
||||
if os.path.isfile(mpriv):
|
||||
priv = mpriv
|
||||
|
||||
if not priv:
|
||||
if auto_create:
|
||||
log.debug('Generating new signing key-pair {0}.* in {1}'
|
||||
''.format(__opts__['master_sign_key_name'],
|
||||
__opts__['pki_dir']))
|
||||
salt.crypt.gen_keys(__opts__['pki_dir'],
|
||||
__opts__['master_sign_key_name'],
|
||||
keysize or __opts__['keysize'],
|
||||
__opts__.get('user'))
|
||||
|
||||
priv = __opts__['pki_dir'] + '/' + __opts__['master_sign_key_name'] + '.pem'
|
||||
else:
|
||||
return 'No usable private-key found'
|
||||
|
||||
if not pub:
|
||||
return 'No usable public-key found'
|
||||
|
||||
log.debug('Using public-key {0}'.format(pub))
|
||||
log.debug('Using private-key {0}'.format(priv))
|
||||
|
||||
if signature_path:
|
||||
if not os.path.isdir(signature_path):
|
||||
log.debug('target directory {0} does not exist'
|
||||
''.format(signature_path))
|
||||
else:
|
||||
signature_path = __opts__['pki_dir']
|
||||
|
||||
sign_path = signature_path + '/' + __opts__['master_pubkey_signature']
|
||||
|
||||
skey = get_key(__opts__)
|
||||
return skey.gen_signature(priv, pub, sign_path)
|
||||
|
Loading…
Reference in New Issue
Block a user