mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10:20 +00:00
Merge pull request #43203 from rallytime/fix-21969
Return a SaltInvocationError when passing incorrect function pattern for wheel/runner functions.
This commit is contained in:
commit
792cc0eb54
8 changed files with 645 additions and 140 deletions
|
@ -293,29 +293,31 @@ class LoadAuth(object):
|
|||
def authenticate_key(self, load, key):
|
||||
'''
|
||||
Authenticate a user by the key passed in load.
|
||||
Return the effective user id (name) if it's differ from the specified one (for sudo).
|
||||
If the effective user id is the same as passed one return True on success or False on
|
||||
Return the effective user id (name) if it's different from the specified one (for sudo).
|
||||
If the effective user id is the same as the passed one, return True on success or False on
|
||||
failure.
|
||||
'''
|
||||
auth_key = load.pop('key')
|
||||
if not auth_key:
|
||||
log.warning('Authentication failure of type "user" occurred.')
|
||||
error_msg = 'Authentication failure of type "user" occurred.'
|
||||
auth_key = load.pop('key', None)
|
||||
if auth_key is None:
|
||||
log.warning(error_msg)
|
||||
return False
|
||||
|
||||
if 'user' in load:
|
||||
auth_user = AuthUser(load['user'])
|
||||
if auth_user.is_sudo():
|
||||
# If someone sudos check to make sure there is no ACL's around their username
|
||||
if auth_key != key[self.opts.get('user', 'root')]:
|
||||
log.warning('Authentication failure of type "user" occurred.')
|
||||
log.warning(error_msg)
|
||||
return False
|
||||
return auth_user.sudo_name()
|
||||
elif load['user'] == self.opts.get('user', 'root') or load['user'] == 'root':
|
||||
if auth_key != key[self.opts.get('user', 'root')]:
|
||||
log.warning('Authentication failure of type "user" occurred.')
|
||||
log.warning(error_msg)
|
||||
return False
|
||||
elif auth_user.is_running_user():
|
||||
if auth_key != key.get(load['user']):
|
||||
log.warning('Authentication failure of type "user" occurred.')
|
||||
log.warning(error_msg)
|
||||
return False
|
||||
elif auth_key == key.get('root'):
|
||||
pass
|
||||
|
@ -323,15 +325,15 @@ class LoadAuth(object):
|
|||
if load['user'] in key:
|
||||
# User is authorised, check key and check perms
|
||||
if auth_key != key[load['user']]:
|
||||
log.warning('Authentication failure of type "user" occurred.')
|
||||
log.warning(error_msg)
|
||||
return False
|
||||
return load['user']
|
||||
else:
|
||||
log.warning('Authentication failure of type "user" occurred.')
|
||||
log.warning(error_msg)
|
||||
return False
|
||||
else:
|
||||
if auth_key != key[salt.utils.get_user()]:
|
||||
log.warning('Authentication failure of type "other" occurred.')
|
||||
log.warning(error_msg)
|
||||
return False
|
||||
return True
|
||||
|
||||
|
@ -413,6 +415,64 @@ class LoadAuth(object):
|
|||
|
||||
return auth_list
|
||||
|
||||
def check_authentication(self, load, auth_type, key=None, show_username=False):
|
||||
'''
|
||||
.. versionadded:: Oxygen
|
||||
|
||||
Go through various checks to see if the token/eauth/user can be authenticated.
|
||||
|
||||
Returns a dictionary containing the following keys:
|
||||
|
||||
- auth_list
|
||||
- username
|
||||
- error
|
||||
|
||||
If an error is encountered, return immediately with the relevant error dictionary
|
||||
as authentication has failed. Otherwise, return the username and valid auth_list.
|
||||
'''
|
||||
auth_list = []
|
||||
username = load.get('username', 'UNKNOWN')
|
||||
ret = {'auth_list': auth_list,
|
||||
'username': username,
|
||||
'error': {}}
|
||||
|
||||
# Authenticate
|
||||
if auth_type == 'token':
|
||||
token = self.authenticate_token(load)
|
||||
if not token:
|
||||
ret['error'] = {'name': 'TokenAuthenticationError',
|
||||
'message': 'Authentication failure of type "token" occurred.'}
|
||||
return ret
|
||||
|
||||
# Update username for token
|
||||
username = token['name']
|
||||
ret['username'] = username
|
||||
auth_list = self.get_auth_list(load, token=token)
|
||||
elif auth_type == 'eauth':
|
||||
if not self.authenticate_eauth(load):
|
||||
ret['error'] = {'name': 'EauthAuthenticationError',
|
||||
'message': 'Authentication failure of type "eauth" occurred for '
|
||||
'user {0}.'.format(username)}
|
||||
return ret
|
||||
|
||||
auth_list = self.get_auth_list(load)
|
||||
elif auth_type == 'user':
|
||||
if not self.authenticate_key(load, key):
|
||||
if show_username:
|
||||
msg = 'Authentication failure of type "user" occurred for user {0}.'.format(username)
|
||||
else:
|
||||
msg = 'Authentication failure of type "user" occurred'
|
||||
ret['error'] = {'name': 'UserAuthenticationError', 'message': msg}
|
||||
return ret
|
||||
else:
|
||||
ret['error'] = {'name': 'SaltInvocationError',
|
||||
'message': 'Authentication type not supported.'}
|
||||
return ret
|
||||
|
||||
# Authentication checks passed
|
||||
ret['auth_list'] = auth_list
|
||||
return ret
|
||||
|
||||
|
||||
class Authorize(object):
|
||||
'''
|
||||
|
@ -558,6 +618,15 @@ class Authorize(object):
|
|||
load.get('arg', None),
|
||||
load.get('tgt', None),
|
||||
load.get('tgt_type', 'glob'))
|
||||
|
||||
# Handle possible return of dict data structure from any_auth call to
|
||||
# avoid a stacktrace. As mentioned in PR #43181, this entire class is
|
||||
# dead code and is marked for removal in Salt Neon. But until then, we
|
||||
# should handle the dict return, which is an error and should return
|
||||
# False until this class is removed.
|
||||
if isinstance(good, dict):
|
||||
return False
|
||||
|
||||
if not good:
|
||||
# Accept find_job so the CLI will function cleanly
|
||||
if load.get('fun', '') != 'saltutil.find_job':
|
||||
|
@ -570,7 +639,7 @@ class Authorize(object):
|
|||
authorization
|
||||
|
||||
Note: this will check that the user has at least one right that will let
|
||||
him execute "load", this does not deal with conflicting rules
|
||||
the user execute "load", this does not deal with conflicting rules
|
||||
'''
|
||||
|
||||
adata = self.auth_data
|
||||
|
|
|
@ -1013,30 +1013,33 @@ class LocalFuncs(object):
|
|||
'''
|
||||
Send a master control function back to the runner system
|
||||
'''
|
||||
if 'token' in load:
|
||||
auth_type = 'token'
|
||||
err_name = 'TokenAuthenticationError'
|
||||
token = self.loadauth.authenticate_token(load)
|
||||
if not token:
|
||||
return dict(error=dict(name=err_name,
|
||||
message='Authentication failure of type "token" occurred.'))
|
||||
username = token['name']
|
||||
auth_list = self.loadauth.get_auth_list(load, token)
|
||||
else:
|
||||
auth_type = 'eauth'
|
||||
err_name = 'EauthAuthenticationError'
|
||||
username = load.get('username', 'UNKNOWN')
|
||||
if not self.loadauth.authenticate_eauth(load):
|
||||
return dict(error=dict(name=err_name,
|
||||
message=('Authentication failure of type "eauth" occurred '
|
||||
'for user {0}.').format(username)))
|
||||
auth_list = self.loadauth.get_auth_list(load)
|
||||
# All runner opts pass through eauth
|
||||
auth_type, err_name, key = self._prep_auth_info(load)
|
||||
|
||||
if not self.ckminions.runner_check(auth_list, load['fun'], load['kwarg']):
|
||||
return dict(error=dict(name=err_name,
|
||||
message=('Authentication failure of type "{0}" occurred '
|
||||
'for user {1}.').format(auth_type, username)))
|
||||
# Authenticate
|
||||
auth_check = self.loadauth.check_authentication(load, auth_type)
|
||||
error = auth_check.get('error')
|
||||
|
||||
if error:
|
||||
# Authentication error occurred: do not continue.
|
||||
return {'error': error}
|
||||
|
||||
# Authorize
|
||||
runner_check = self.ckminions.runner_check(
|
||||
auth_check.get('auth_list', []),
|
||||
load['fun'],
|
||||
load['kwarg']
|
||||
)
|
||||
username = auth_check.get('username')
|
||||
if not runner_check:
|
||||
return {'error': {'name': err_name,
|
||||
'message': 'Authentication failure of type "{0}" occurred '
|
||||
'for user {1}.'.format(auth_type, username)}}
|
||||
elif isinstance(runner_check, dict) and 'error' in runner_check:
|
||||
# A dictionary with an error name/message was handled by ckminions.runner_check
|
||||
return runner_check
|
||||
|
||||
# Authorized. Do the job!
|
||||
try:
|
||||
fun = load.pop('fun')
|
||||
runner_client = salt.runner.RunnerClient(self.opts)
|
||||
|
@ -1045,48 +1048,46 @@ class LocalFuncs(object):
|
|||
username)
|
||||
except Exception as exc:
|
||||
log.error('Exception occurred while '
|
||||
'introspecting {0}: {1}'.format(fun, exc))
|
||||
return dict(error=dict(name=exc.__class__.__name__,
|
||||
args=exc.args,
|
||||
message=str(exc)))
|
||||
'introspecting {0}: {1}'.format(fun, exc))
|
||||
return {'error': {'name': exc.__class__.__name__,
|
||||
'args': exc.args,
|
||||
'message': str(exc)}}
|
||||
|
||||
def wheel(self, load):
|
||||
'''
|
||||
Send a master control function back to the wheel system
|
||||
'''
|
||||
# All wheel ops pass through eauth
|
||||
if 'token' in load:
|
||||
auth_type = 'token'
|
||||
err_name = 'TokenAuthenticationError'
|
||||
token = self.loadauth.authenticate_token(load)
|
||||
if not token:
|
||||
return dict(error=dict(name=err_name,
|
||||
message='Authentication failure of type "token" occurred.'))
|
||||
username = token['name']
|
||||
auth_list = self.loadauth.get_auth_list(load, token)
|
||||
elif 'eauth' in load:
|
||||
auth_type = 'eauth'
|
||||
err_name = 'EauthAuthenticationError'
|
||||
username = load.get('username', 'UNKNOWN')
|
||||
if not self.loadauth.authenticate_eauth(load):
|
||||
return dict(error=dict(name=err_name,
|
||||
message=('Authentication failure of type "eauth" occurred for '
|
||||
'user {0}.').format(username)))
|
||||
auth_list = self.loadauth.get_auth_list(load)
|
||||
else:
|
||||
auth_type = 'user'
|
||||
err_name = 'UserAuthenticationError'
|
||||
username = load.get('username', 'UNKNOWN')
|
||||
if not self.loadauth.authenticate_key(load, self.key):
|
||||
return dict(error=dict(name=err_name,
|
||||
message=('Authentication failure of type "user" occurred for '
|
||||
'user {0}.').format(username)))
|
||||
auth_type, err_name, key = self._prep_auth_info(load)
|
||||
|
||||
# Authenticate
|
||||
auth_check = self.loadauth.check_authentication(
|
||||
load,
|
||||
auth_type,
|
||||
key=key,
|
||||
show_username=True
|
||||
)
|
||||
error = auth_check.get('error')
|
||||
|
||||
if error:
|
||||
# Authentication error occurred: do not continue.
|
||||
return {'error': error}
|
||||
|
||||
# Authorize
|
||||
username = auth_check.get('username')
|
||||
if auth_type != 'user':
|
||||
if not self.ckminions.wheel_check(auth_list, load['fun'], load['kwarg']):
|
||||
return dict(error=dict(name=err_name,
|
||||
message=('Authentication failure of type "{0}" occurred for '
|
||||
'user {1}.').format(auth_type, username)))
|
||||
wheel_check = self.ckminions.wheel_check(
|
||||
auth_check.get('auth_list', []),
|
||||
load['fun'],
|
||||
load['kwarg']
|
||||
)
|
||||
if not wheel_check:
|
||||
return {'error': {'name': err_name,
|
||||
'message': 'Authentication failure of type "{0}" occurred for '
|
||||
'user {1}.'.format(auth_type, username)}}
|
||||
elif isinstance(wheel_check, dict) and 'error' in wheel_check:
|
||||
# A dictionary with an error name/message was handled by ckminions.wheel_check
|
||||
return wheel_check
|
||||
|
||||
# Authenticated. Do the job.
|
||||
jid = salt.utils.jid.gen_jid(self.opts)
|
||||
|
@ -1106,7 +1107,7 @@ class LocalFuncs(object):
|
|||
'data': data}
|
||||
except Exception as exc:
|
||||
log.error('Exception occurred while '
|
||||
'introspecting {0}: {1}'.format(fun, exc))
|
||||
'introspecting {0}: {1}'.format(fun, exc))
|
||||
data['return'] = 'Exception occurred in wheel {0}: {1}: {2}'.format(
|
||||
fun,
|
||||
exc.__class__.__name__,
|
||||
|
@ -1371,3 +1372,18 @@ class LocalFuncs(object):
|
|||
},
|
||||
'pub': pub_load
|
||||
}
|
||||
|
||||
def _prep_auth_info(self, load):
|
||||
key = None
|
||||
if 'token' in load:
|
||||
auth_type = 'token'
|
||||
err_name = 'TokenAuthenticationError'
|
||||
elif 'eauth' in load:
|
||||
auth_type = 'eauth'
|
||||
err_name = 'EauthAuthenticationError'
|
||||
else:
|
||||
auth_type = 'user'
|
||||
err_name = 'UserAuthenticationError'
|
||||
key = self.key
|
||||
|
||||
return auth_type, err_name, key
|
||||
|
|
141
salt/master.py
141
salt/master.py
|
@ -1668,44 +1668,36 @@ class ClearFuncs(object):
|
|||
Send a master control function back to the runner system
|
||||
'''
|
||||
# All runner ops pass through eauth
|
||||
if u'token' in clear_load:
|
||||
# Authenticate
|
||||
token = self.loadauth.authenticate_token(clear_load)
|
||||
auth_type, err_name, key, sensitive_load_keys = self._prep_auth_info(clear_load)
|
||||
|
||||
if not token:
|
||||
return dict(error=dict(name=u'TokenAuthenticationError',
|
||||
message=u'Authentication failure of type "token" occurred.'))
|
||||
# Authenticate
|
||||
auth_check = self.loadauth.check_authentication(clear_load, auth_type, key=key)
|
||||
error = auth_check.get(u'error')
|
||||
|
||||
# Authorize
|
||||
auth_list = self.loadauth.get_auth_list(clear_load, token)
|
||||
if error:
|
||||
# Authentication error occurred: do not continue.
|
||||
return {u'error': error}
|
||||
|
||||
if not self.ckminions.runner_check(auth_list, clear_load[u'fun'], clear_load.get(u'kwarg', {})):
|
||||
return dict(error=dict(name=u'TokenAuthenticationError',
|
||||
message=(u'Authentication failure of type "token" occurred for '
|
||||
u'user {0}.').format(token[u'name'])))
|
||||
clear_load.pop(u'token')
|
||||
username = token[u'name']
|
||||
elif u'eauth' in clear_load:
|
||||
if not self.loadauth.authenticate_eauth(clear_load):
|
||||
return dict(error=dict(name=u'EauthAuthenticationError',
|
||||
message=(u'Authentication failure of type "eauth" occurred for '
|
||||
u'user {0}.').format(clear_load.get(u'username', u'UNKNOWN'))))
|
||||
# Authorize
|
||||
username = auth_check.get(u'username')
|
||||
if auth_type != u'user':
|
||||
runner_check = self.ckminions.runner_check(
|
||||
auth_check.get(u'auth_list', []),
|
||||
clear_load[u'fun'],
|
||||
clear_load.get(u'kwarg', {})
|
||||
)
|
||||
if not runner_check:
|
||||
return {u'error': {u'name': err_name,
|
||||
u'message': u'Authentication failure of type "{0}" occurred for '
|
||||
u'user {1}.'.format(auth_type, username)}}
|
||||
elif isinstance(runner_check, dict) and u'error' in runner_check:
|
||||
# A dictionary with an error name/message was handled by ckminions.runner_check
|
||||
return runner_check
|
||||
|
||||
auth_list = self.loadauth.get_auth_list(clear_load)
|
||||
if not self.ckminions.runner_check(auth_list, clear_load[u'fun'], clear_load.get(u'kwarg', {})):
|
||||
return dict(error=dict(name=u'EauthAuthenticationError',
|
||||
message=(u'Authentication failure of type "eauth" occurred for '
|
||||
u'user {0}.').format(clear_load.get(u'username', u'UNKNOWN'))))
|
||||
|
||||
# No error occurred, consume the password from the clear_load if
|
||||
# passed
|
||||
username = clear_load.pop(u'username', u'UNKNOWN')
|
||||
clear_load.pop(u'password', None)
|
||||
# No error occurred, consume sensitive settings from the clear_load if passed.
|
||||
for item in sensitive_load_keys:
|
||||
clear_load.pop(item, None)
|
||||
else:
|
||||
if not self.loadauth.authenticate_key(clear_load, self.key):
|
||||
return dict(error=dict(name=u'UserAuthenticationError',
|
||||
message=u'Authentication failure of type "user" occurred'))
|
||||
|
||||
if u'user' in clear_load:
|
||||
username = clear_load[u'user']
|
||||
if salt.auth.AuthUser(username).is_sudo():
|
||||
|
@ -1722,52 +1714,45 @@ class ClearFuncs(object):
|
|||
username)
|
||||
except Exception as exc:
|
||||
log.error(u'Exception occurred while introspecting %s: %s', fun, exc)
|
||||
return dict(error=dict(name=exc.__class__.__name__,
|
||||
args=exc.args,
|
||||
message=str(exc)))
|
||||
return {u'error': {u'name': exc.__class__.__name__,
|
||||
u'args': exc.args,
|
||||
u'message': str(exc)}}
|
||||
|
||||
def wheel(self, clear_load):
|
||||
'''
|
||||
Send a master control function back to the wheel system
|
||||
'''
|
||||
# All wheel ops pass through eauth
|
||||
username = None
|
||||
if u'token' in clear_load:
|
||||
# Authenticate
|
||||
token = self.loadauth.authenticate_token(clear_load)
|
||||
if not token:
|
||||
return dict(error=dict(name=u'TokenAuthenticationError',
|
||||
message=u'Authentication failure of type "token" occurred.'))
|
||||
auth_type, err_name, key, sensitive_load_keys = self._prep_auth_info(clear_load)
|
||||
|
||||
# Authorize
|
||||
auth_list = self.loadauth.get_auth_list(clear_load, token)
|
||||
if not self.ckminions.wheel_check(auth_list, clear_load[u'fun'], clear_load.get(u'kwarg', {})):
|
||||
return dict(error=dict(name=u'TokenAuthenticationError',
|
||||
message=(u'Authentication failure of type "token" occurred for '
|
||||
u'user {0}.').format(token[u'name'])))
|
||||
clear_load.pop(u'token')
|
||||
username = token[u'name']
|
||||
elif u'eauth' in clear_load:
|
||||
if not self.loadauth.authenticate_eauth(clear_load):
|
||||
return dict(error=dict(name=u'EauthAuthenticationError',
|
||||
message=(u'Authentication failure of type "eauth" occurred for '
|
||||
u'user {0}.').format(clear_load.get(u'username', u'UNKNOWN'))))
|
||||
# Authenticate
|
||||
auth_check = self.loadauth.check_authentication(clear_load, auth_type, key=key)
|
||||
error = auth_check.get(u'error')
|
||||
|
||||
auth_list = self.loadauth.get_auth_list(clear_load)
|
||||
if not self.ckminions.wheel_check(auth_list, clear_load[u'fun'], clear_load.get(u'kwarg', {})):
|
||||
return dict(error=dict(name=u'EauthAuthenticationError',
|
||||
message=(u'Authentication failure of type "eauth" occurred for '
|
||||
u'user {0}.').format(clear_load.get(u'username', u'UNKNOWN'))))
|
||||
if error:
|
||||
# Authentication error occurred: do not continue.
|
||||
return {u'error': error}
|
||||
|
||||
# No error occurred, consume the password from the clear_load if
|
||||
# passed
|
||||
clear_load.pop(u'password', None)
|
||||
username = clear_load.pop(u'username', u'UNKNOWN')
|
||||
# Authorize
|
||||
username = auth_check.get(u'username')
|
||||
if auth_type != u'user':
|
||||
wheel_check = self.ckminions.wheel_check(
|
||||
auth_check.get(u'auth_list', []),
|
||||
clear_load[u'fun'],
|
||||
clear_load.get(u'kwarg', {})
|
||||
)
|
||||
if not wheel_check:
|
||||
return {u'error': {u'name': err_name,
|
||||
u'message': u'Authentication failure of type "{0}" occurred for '
|
||||
u'user {1}.'.format(auth_type, username)}}
|
||||
elif isinstance(wheel_check, dict) and u'error' in wheel_check:
|
||||
# A dictionary with an error name/message was handled by ckminions.wheel_check
|
||||
return wheel_check
|
||||
|
||||
# No error occurred, consume sensitive settings from the clear_load if passed.
|
||||
for item in sensitive_load_keys:
|
||||
clear_load.pop(item, None)
|
||||
else:
|
||||
if not self.loadauth.authenticate_key(clear_load, self.key):
|
||||
return dict(error=dict(name=u'UserAuthenticationError',
|
||||
message=u'Authentication failure of type "user" occurred'))
|
||||
|
||||
if u'user' in clear_load:
|
||||
username = clear_load[u'user']
|
||||
if salt.auth.AuthUser(username).is_sudo():
|
||||
|
@ -1963,6 +1948,24 @@ class ClearFuncs(object):
|
|||
}
|
||||
}
|
||||
|
||||
def _prep_auth_info(self, clear_load):
|
||||
sensitive_load_keys = []
|
||||
key = None
|
||||
if u'token' in clear_load:
|
||||
auth_type = u'token'
|
||||
err_name = u'TokenAuthenticationError'
|
||||
sensitive_load_keys = [u'token']
|
||||
elif u'eauth' in clear_load:
|
||||
auth_type = u'eauth'
|
||||
err_name = u'EauthAuthenticationError'
|
||||
sensitive_load_keys = [u'username', u'password']
|
||||
else:
|
||||
auth_type = u'user'
|
||||
err_name = u'UserAuthenticationError'
|
||||
key = self.key
|
||||
|
||||
return auth_type, err_name, key, sensitive_load_keys
|
||||
|
||||
def _prep_jid(self, clear_load, extra):
|
||||
'''
|
||||
Return a jid for this publication
|
||||
|
|
|
@ -985,7 +985,11 @@ class CkMinions(object):
|
|||
if form != 'cloud':
|
||||
comps = fun.split('.')
|
||||
if len(comps) != 2:
|
||||
return False
|
||||
# Hint at a syntax error when command is passed improperly,
|
||||
# rather than returning an authentication error of some kind.
|
||||
# See Issue #21969 for more information.
|
||||
return {'error': {'name': 'SaltInvocationError',
|
||||
'message': 'A command invocation error occurred: Check syntax.'}}
|
||||
mod_name = comps[0]
|
||||
fun_name = comps[1]
|
||||
else:
|
||||
|
|
1
tests/unit/daemons/__init__.py
Normal file
1
tests/unit/daemons/__init__.py
Normal file
|
@ -0,0 +1 @@
|
|||
# -*- coding: utf-8 -*-
|
201
tests/unit/daemons/test_masterapi.py
Normal file
201
tests/unit/daemons/test_masterapi.py
Normal file
|
@ -0,0 +1,201 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Import Python libs
|
||||
from __future__ import absolute_import
|
||||
|
||||
# Import Salt libs
|
||||
import salt.config
|
||||
import salt.daemons.masterapi as masterapi
|
||||
|
||||
# Import Salt Testing Libs
|
||||
from tests.support.unit import TestCase
|
||||
from tests.support.mock import (
|
||||
patch,
|
||||
MagicMock,
|
||||
)
|
||||
|
||||
|
||||
class LocalFuncsTestCase(TestCase):
|
||||
'''
|
||||
TestCase for salt.daemons.masterapi.LocalFuncs class
|
||||
'''
|
||||
|
||||
def setUp(self):
|
||||
opts = salt.config.master_config(None)
|
||||
self.local_funcs = masterapi.LocalFuncs(opts, 'test-key')
|
||||
|
||||
def test_runner_token_not_authenticated(self):
|
||||
'''
|
||||
Asserts that a TokenAuthenticationError is returned when the token can't authenticate.
|
||||
'''
|
||||
mock_ret = {u'error': {u'name': u'TokenAuthenticationError',
|
||||
u'message': u'Authentication failure of type "token" occurred.'}}
|
||||
ret = self.local_funcs.runner({u'token': u'asdfasdfasdfasdf'})
|
||||
self.assertDictEqual(mock_ret, ret)
|
||||
|
||||
def test_runner_token_authorization_error(self):
|
||||
'''
|
||||
Asserts that a TokenAuthenticationError is returned when the token authenticates, but is
|
||||
not authorized.
|
||||
'''
|
||||
token = u'asdfasdfasdfasdf'
|
||||
load = {u'token': token, u'fun': u'test.arg', u'kwarg': {}}
|
||||
mock_token = {u'token': token, u'eauth': u'foo', u'name': u'test'}
|
||||
mock_ret = {u'error': {u'name': u'TokenAuthenticationError',
|
||||
u'message': u'Authentication failure of type "token" occurred '
|
||||
u'for user test.'}}
|
||||
|
||||
with patch('salt.auth.LoadAuth.authenticate_token', MagicMock(return_value=mock_token)), \
|
||||
patch('salt.auth.LoadAuth.get_auth_list', MagicMock(return_value=[])):
|
||||
ret = self.local_funcs.runner(load)
|
||||
|
||||
self.assertDictEqual(mock_ret, ret)
|
||||
|
||||
def test_runner_token_salt_invocation_error(self):
|
||||
'''
|
||||
Asserts that a SaltInvocationError is returned when the token authenticates, but the
|
||||
command is malformed.
|
||||
'''
|
||||
token = u'asdfasdfasdfasdf'
|
||||
load = {u'token': token, u'fun': u'badtestarg', u'kwarg': {}}
|
||||
mock_token = {u'token': token, u'eauth': u'foo', u'name': u'test'}
|
||||
mock_ret = {u'error': {u'name': u'SaltInvocationError',
|
||||
u'message': u'A command invocation error occurred: Check syntax.'}}
|
||||
|
||||
with patch('salt.auth.LoadAuth.authenticate_token', MagicMock(return_value=mock_token)), \
|
||||
patch('salt.auth.LoadAuth.get_auth_list', MagicMock(return_value=[])):
|
||||
ret = self.local_funcs.runner(load)
|
||||
|
||||
self.assertDictEqual(mock_ret, ret)
|
||||
|
||||
def test_runner_eauth_not_authenticated(self):
|
||||
'''
|
||||
Asserts that an EauthAuthenticationError is returned when the user can't authenticate.
|
||||
'''
|
||||
mock_ret = {u'error': {u'name': u'EauthAuthenticationError',
|
||||
u'message': u'Authentication failure of type "eauth" occurred for '
|
||||
u'user UNKNOWN.'}}
|
||||
ret = self.local_funcs.runner({u'eauth': u'foo'})
|
||||
self.assertDictEqual(mock_ret, ret)
|
||||
|
||||
def test_runner_eauth_authorization_error(self):
|
||||
'''
|
||||
Asserts that an EauthAuthenticationError is returned when the user authenticates, but is
|
||||
not authorized.
|
||||
'''
|
||||
load = {u'eauth': u'foo', u'username': u'test', u'fun': u'test.arg', u'kwarg': {}}
|
||||
mock_ret = {u'error': {u'name': u'EauthAuthenticationError',
|
||||
u'message': u'Authentication failure of type "eauth" occurred for '
|
||||
u'user test.'}}
|
||||
with patch('salt.auth.LoadAuth.authenticate_eauth', MagicMock(return_value=True)), \
|
||||
patch('salt.auth.LoadAuth.get_auth_list', MagicMock(return_value=[])):
|
||||
ret = self.local_funcs.runner(load)
|
||||
|
||||
self.assertDictEqual(mock_ret, ret)
|
||||
|
||||
def test_runner_eauth_salt_invocation_errpr(self):
|
||||
'''
|
||||
Asserts that an EauthAuthenticationError is returned when the user authenticates, but the
|
||||
command is malformed.
|
||||
'''
|
||||
load = {u'eauth': u'foo', u'username': u'test', u'fun': u'bad.test.arg.func', u'kwarg': {}}
|
||||
mock_ret = {u'error': {u'name': u'SaltInvocationError',
|
||||
u'message': u'A command invocation error occurred: Check syntax.'}}
|
||||
with patch('salt.auth.LoadAuth.authenticate_eauth', MagicMock(return_value=True)), \
|
||||
patch('salt.auth.LoadAuth.get_auth_list', MagicMock(return_value=[])):
|
||||
ret = self.local_funcs.runner(load)
|
||||
|
||||
self.assertDictEqual(mock_ret, ret)
|
||||
|
||||
def test_wheel_token_not_authenticated(self):
|
||||
'''
|
||||
Asserts that a TokenAuthenticationError is returned when the token can't authenticate.
|
||||
'''
|
||||
mock_ret = {u'error': {u'name': u'TokenAuthenticationError',
|
||||
u'message': u'Authentication failure of type "token" occurred.'}}
|
||||
ret = self.local_funcs.wheel({u'token': u'asdfasdfasdfasdf'})
|
||||
self.assertDictEqual(mock_ret, ret)
|
||||
|
||||
def test_wheel_token_authorization_error(self):
|
||||
'''
|
||||
Asserts that a TokenAuthenticationError is returned when the token authenticates, but is
|
||||
not authorized.
|
||||
'''
|
||||
token = u'asdfasdfasdfasdf'
|
||||
load = {u'token': token, u'fun': u'test.arg', u'kwarg': {}}
|
||||
mock_token = {u'token': token, u'eauth': u'foo', u'name': u'test'}
|
||||
mock_ret = {u'error': {u'name': u'TokenAuthenticationError',
|
||||
u'message': u'Authentication failure of type "token" occurred '
|
||||
u'for user test.'}}
|
||||
|
||||
with patch('salt.auth.LoadAuth.authenticate_token', MagicMock(return_value=mock_token)), \
|
||||
patch('salt.auth.LoadAuth.get_auth_list', MagicMock(return_value=[])):
|
||||
ret = self.local_funcs.wheel(load)
|
||||
|
||||
self.assertDictEqual(mock_ret, ret)
|
||||
|
||||
def test_wheel_token_salt_invocation_error(self):
|
||||
'''
|
||||
Asserts that a SaltInvocationError is returned when the token authenticates, but the
|
||||
command is malformed.
|
||||
'''
|
||||
token = u'asdfasdfasdfasdf'
|
||||
load = {u'token': token, u'fun': u'badtestarg', u'kwarg': {}}
|
||||
mock_token = {u'token': token, u'eauth': u'foo', u'name': u'test'}
|
||||
mock_ret = {u'error': {u'name': u'SaltInvocationError',
|
||||
u'message': u'A command invocation error occurred: Check syntax.'}}
|
||||
|
||||
with patch('salt.auth.LoadAuth.authenticate_token', MagicMock(return_value=mock_token)), \
|
||||
patch('salt.auth.LoadAuth.get_auth_list', MagicMock(return_value=[])):
|
||||
ret = self.local_funcs.wheel(load)
|
||||
|
||||
self.assertDictEqual(mock_ret, ret)
|
||||
|
||||
def test_wheel_eauth_not_authenticated(self):
|
||||
'''
|
||||
Asserts that an EauthAuthenticationError is returned when the user can't authenticate.
|
||||
'''
|
||||
mock_ret = {u'error': {u'name': u'EauthAuthenticationError',
|
||||
u'message': u'Authentication failure of type "eauth" occurred for '
|
||||
u'user UNKNOWN.'}}
|
||||
ret = self.local_funcs.wheel({u'eauth': u'foo'})
|
||||
self.assertDictEqual(mock_ret, ret)
|
||||
|
||||
def test_wheel_eauth_authorization_error(self):
|
||||
'''
|
||||
Asserts that an EauthAuthenticationError is returned when the user authenticates, but is
|
||||
not authorized.
|
||||
'''
|
||||
load = {u'eauth': u'foo', u'username': u'test', u'fun': u'test.arg', u'kwarg': {}}
|
||||
mock_ret = {u'error': {u'name': u'EauthAuthenticationError',
|
||||
u'message': u'Authentication failure of type "eauth" occurred for '
|
||||
u'user test.'}}
|
||||
with patch('salt.auth.LoadAuth.authenticate_eauth', MagicMock(return_value=True)), \
|
||||
patch('salt.auth.LoadAuth.get_auth_list', MagicMock(return_value=[])):
|
||||
ret = self.local_funcs.wheel(load)
|
||||
|
||||
self.assertDictEqual(mock_ret, ret)
|
||||
|
||||
def test_wheel_eauth_salt_invocation_errpr(self):
|
||||
'''
|
||||
Asserts that an EauthAuthenticationError is returned when the user authenticates, but the
|
||||
command is malformed.
|
||||
'''
|
||||
load = {u'eauth': u'foo', u'username': u'test', u'fun': u'bad.test.arg.func', u'kwarg': {}}
|
||||
mock_ret = {u'error': {u'name': u'SaltInvocationError',
|
||||
u'message': u'A command invocation error occurred: Check syntax.'}}
|
||||
with patch('salt.auth.LoadAuth.authenticate_eauth', MagicMock(return_value=True)), \
|
||||
patch('salt.auth.LoadAuth.get_auth_list', MagicMock(return_value=[])):
|
||||
ret = self.local_funcs.wheel(load)
|
||||
|
||||
self.assertDictEqual(mock_ret, ret)
|
||||
|
||||
def test_wheel_user_not_authenticated(self):
|
||||
'''
|
||||
Asserts that an UserAuthenticationError is returned when the user can't authenticate.
|
||||
'''
|
||||
mock_ret = {u'error': {u'name': u'UserAuthenticationError',
|
||||
u'message': u'Authentication failure of type "user" occurred for '
|
||||
u'user UNKNOWN.'}}
|
||||
ret = self.local_funcs.wheel({})
|
||||
self.assertDictEqual(mock_ret, ret)
|
209
tests/unit/test_master.py
Normal file
209
tests/unit/test_master.py
Normal file
|
@ -0,0 +1,209 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Import Python libs
|
||||
from __future__ import absolute_import
|
||||
|
||||
# Import Salt libs
|
||||
import salt.config
|
||||
import salt.master
|
||||
|
||||
# Import Salt Testing Libs
|
||||
from tests.support.unit import TestCase
|
||||
from tests.support.mock import (
|
||||
patch,
|
||||
MagicMock,
|
||||
)
|
||||
|
||||
|
||||
class ClearFuncsTestCase(TestCase):
|
||||
'''
|
||||
TestCase for salt.master.ClearFuncs class
|
||||
'''
|
||||
|
||||
def setUp(self):
|
||||
opts = salt.config.master_config(None)
|
||||
self.clear_funcs = salt.master.ClearFuncs(opts, {})
|
||||
|
||||
def test_runner_token_not_authenticated(self):
|
||||
'''
|
||||
Asserts that a TokenAuthenticationError is returned when the token can't authenticate.
|
||||
'''
|
||||
mock_ret = {u'error': {u'name': u'TokenAuthenticationError',
|
||||
u'message': u'Authentication failure of type "token" occurred.'}}
|
||||
ret = self.clear_funcs.runner({u'token': u'asdfasdfasdfasdf'})
|
||||
self.assertDictEqual(mock_ret, ret)
|
||||
|
||||
def test_runner_token_authorization_error(self):
|
||||
'''
|
||||
Asserts that a TokenAuthenticationError is returned when the token authenticates, but is
|
||||
not authorized.
|
||||
'''
|
||||
token = u'asdfasdfasdfasdf'
|
||||
clear_load = {u'token': token, u'fun': u'test.arg'}
|
||||
mock_token = {u'token': token, u'eauth': u'foo', u'name': u'test'}
|
||||
mock_ret = {u'error': {u'name': u'TokenAuthenticationError',
|
||||
u'message': u'Authentication failure of type "token" occurred '
|
||||
u'for user test.'}}
|
||||
|
||||
with patch('salt.auth.LoadAuth.authenticate_token', MagicMock(return_value=mock_token)), \
|
||||
patch('salt.auth.LoadAuth.get_auth_list', MagicMock(return_value=[])):
|
||||
ret = self.clear_funcs.runner(clear_load)
|
||||
|
||||
self.assertDictEqual(mock_ret, ret)
|
||||
|
||||
def test_runner_token_salt_invocation_error(self):
|
||||
'''
|
||||
Asserts that a SaltInvocationError is returned when the token authenticates, but the
|
||||
command is malformed.
|
||||
'''
|
||||
token = u'asdfasdfasdfasdf'
|
||||
clear_load = {u'token': token, u'fun': u'badtestarg'}
|
||||
mock_token = {u'token': token, u'eauth': u'foo', u'name': u'test'}
|
||||
mock_ret = {u'error': {u'name': u'SaltInvocationError',
|
||||
u'message': u'A command invocation error occurred: Check syntax.'}}
|
||||
|
||||
with patch('salt.auth.LoadAuth.authenticate_token', MagicMock(return_value=mock_token)), \
|
||||
patch('salt.auth.LoadAuth.get_auth_list', MagicMock(return_value=[])):
|
||||
ret = self.clear_funcs.runner(clear_load)
|
||||
|
||||
self.assertDictEqual(mock_ret, ret)
|
||||
|
||||
def test_runner_eauth_not_authenticated(self):
|
||||
'''
|
||||
Asserts that an EauthAuthenticationError is returned when the user can't authenticate.
|
||||
'''
|
||||
mock_ret = {u'error': {u'name': u'EauthAuthenticationError',
|
||||
u'message': u'Authentication failure of type "eauth" occurred for '
|
||||
u'user UNKNOWN.'}}
|
||||
ret = self.clear_funcs.runner({u'eauth': u'foo'})
|
||||
self.assertDictEqual(mock_ret, ret)
|
||||
|
||||
def test_runner_eauth_authorization_error(self):
|
||||
'''
|
||||
Asserts that an EauthAuthenticationError is returned when the user authenticates, but is
|
||||
not authorized.
|
||||
'''
|
||||
clear_load = {u'eauth': u'foo', u'username': u'test', u'fun': u'test.arg'}
|
||||
mock_ret = {u'error': {u'name': u'EauthAuthenticationError',
|
||||
u'message': u'Authentication failure of type "eauth" occurred for '
|
||||
u'user test.'}}
|
||||
with patch('salt.auth.LoadAuth.authenticate_eauth', MagicMock(return_value=True)), \
|
||||
patch('salt.auth.LoadAuth.get_auth_list', MagicMock(return_value=[])):
|
||||
ret = self.clear_funcs.runner(clear_load)
|
||||
|
||||
self.assertDictEqual(mock_ret, ret)
|
||||
|
||||
def test_runner_eauth_salt_invocation_errpr(self):
|
||||
'''
|
||||
Asserts that an EauthAuthenticationError is returned when the user authenticates, but the
|
||||
command is malformed.
|
||||
'''
|
||||
clear_load = {u'eauth': u'foo', u'username': u'test', u'fun': u'bad.test.arg.func'}
|
||||
mock_ret = {u'error': {u'name': u'SaltInvocationError',
|
||||
u'message': u'A command invocation error occurred: Check syntax.'}}
|
||||
with patch('salt.auth.LoadAuth.authenticate_eauth', MagicMock(return_value=True)), \
|
||||
patch('salt.auth.LoadAuth.get_auth_list', MagicMock(return_value=[])):
|
||||
ret = self.clear_funcs.runner(clear_load)
|
||||
|
||||
self.assertDictEqual(mock_ret, ret)
|
||||
|
||||
def test_runner_user_not_authenticated(self):
|
||||
'''
|
||||
Asserts that an UserAuthenticationError is returned when the user can't authenticate.
|
||||
'''
|
||||
mock_ret = {u'error': {u'name': u'UserAuthenticationError',
|
||||
u'message': u'Authentication failure of type "user" occurred'}}
|
||||
ret = self.clear_funcs.runner({})
|
||||
self.assertDictEqual(mock_ret, ret)
|
||||
|
||||
def test_wheel_token_not_authenticated(self):
|
||||
'''
|
||||
Asserts that a TokenAuthenticationError is returned when the token can't authenticate.
|
||||
'''
|
||||
mock_ret = {u'error': {u'name': u'TokenAuthenticationError',
|
||||
u'message': u'Authentication failure of type "token" occurred.'}}
|
||||
ret = self.clear_funcs.wheel({u'token': u'asdfasdfasdfasdf'})
|
||||
self.assertDictEqual(mock_ret, ret)
|
||||
|
||||
def test_wheel_token_authorization_error(self):
|
||||
'''
|
||||
Asserts that a TokenAuthenticationError is returned when the token authenticates, but is
|
||||
not authorized.
|
||||
'''
|
||||
token = u'asdfasdfasdfasdf'
|
||||
clear_load = {u'token': token, u'fun': u'test.arg'}
|
||||
mock_token = {u'token': token, u'eauth': u'foo', u'name': u'test'}
|
||||
mock_ret = {u'error': {u'name': u'TokenAuthenticationError',
|
||||
u'message': u'Authentication failure of type "token" occurred '
|
||||
u'for user test.'}}
|
||||
|
||||
with patch('salt.auth.LoadAuth.authenticate_token', MagicMock(return_value=mock_token)), \
|
||||
patch('salt.auth.LoadAuth.get_auth_list', MagicMock(return_value=[])):
|
||||
ret = self.clear_funcs.wheel(clear_load)
|
||||
|
||||
self.assertDictEqual(mock_ret, ret)
|
||||
|
||||
def test_wheel_token_salt_invocation_error(self):
|
||||
'''
|
||||
Asserts that a SaltInvocationError is returned when the token authenticates, but the
|
||||
command is malformed.
|
||||
'''
|
||||
token = u'asdfasdfasdfasdf'
|
||||
clear_load = {u'token': token, u'fun': u'badtestarg'}
|
||||
mock_token = {u'token': token, u'eauth': u'foo', u'name': u'test'}
|
||||
mock_ret = {u'error': {u'name': u'SaltInvocationError',
|
||||
u'message': u'A command invocation error occurred: Check syntax.'}}
|
||||
|
||||
with patch('salt.auth.LoadAuth.authenticate_token', MagicMock(return_value=mock_token)), \
|
||||
patch('salt.auth.LoadAuth.get_auth_list', MagicMock(return_value=[])):
|
||||
ret = self.clear_funcs.wheel(clear_load)
|
||||
|
||||
self.assertDictEqual(mock_ret, ret)
|
||||
|
||||
def test_wheel_eauth_not_authenticated(self):
|
||||
'''
|
||||
Asserts that an EauthAuthenticationError is returned when the user can't authenticate.
|
||||
'''
|
||||
mock_ret = {u'error': {u'name': u'EauthAuthenticationError',
|
||||
u'message': u'Authentication failure of type "eauth" occurred for '
|
||||
u'user UNKNOWN.'}}
|
||||
ret = self.clear_funcs.wheel({u'eauth': u'foo'})
|
||||
self.assertDictEqual(mock_ret, ret)
|
||||
|
||||
def test_wheel_eauth_authorization_error(self):
|
||||
'''
|
||||
Asserts that an EauthAuthenticationError is returned when the user authenticates, but is
|
||||
not authorized.
|
||||
'''
|
||||
clear_load = {u'eauth': u'foo', u'username': u'test', u'fun': u'test.arg'}
|
||||
mock_ret = {u'error': {u'name': u'EauthAuthenticationError',
|
||||
u'message': u'Authentication failure of type "eauth" occurred for '
|
||||
u'user test.'}}
|
||||
with patch('salt.auth.LoadAuth.authenticate_eauth', MagicMock(return_value=True)), \
|
||||
patch('salt.auth.LoadAuth.get_auth_list', MagicMock(return_value=[])):
|
||||
ret = self.clear_funcs.wheel(clear_load)
|
||||
|
||||
self.assertDictEqual(mock_ret, ret)
|
||||
|
||||
def test_wheel_eauth_salt_invocation_errpr(self):
|
||||
'''
|
||||
Asserts that an EauthAuthenticationError is returned when the user authenticates, but the
|
||||
command is malformed.
|
||||
'''
|
||||
clear_load = {u'eauth': u'foo', u'username': u'test', u'fun': u'bad.test.arg.func'}
|
||||
mock_ret = {u'error': {u'name': u'SaltInvocationError',
|
||||
u'message': u'A command invocation error occurred: Check syntax.'}}
|
||||
with patch('salt.auth.LoadAuth.authenticate_eauth', MagicMock(return_value=True)), \
|
||||
patch('salt.auth.LoadAuth.get_auth_list', MagicMock(return_value=[])):
|
||||
ret = self.clear_funcs.wheel(clear_load)
|
||||
|
||||
self.assertDictEqual(mock_ret, ret)
|
||||
|
||||
def test_wheel_user_not_authenticated(self):
|
||||
'''
|
||||
Asserts that an UserAuthenticationError is returned when the user can't authenticate.
|
||||
'''
|
||||
mock_ret = {u'error': {u'name': u'UserAuthenticationError',
|
||||
u'message': u'Authentication failure of type "user" occurred'}}
|
||||
ret = self.clear_funcs.wheel({})
|
||||
self.assertDictEqual(mock_ret, ret)
|
|
@ -57,7 +57,9 @@ class CkMinionsTestCase(TestCase):
|
|||
ret = self.ckminions.spec_check(auth_list, 'test.arg', {}, 'wheel')
|
||||
self.assertFalse(ret)
|
||||
ret = self.ckminions.spec_check(auth_list, 'testarg', {}, 'runner')
|
||||
self.assertFalse(ret)
|
||||
mock_ret = {'error': {'name': 'SaltInvocationError',
|
||||
'message': 'A command invocation error occurred: Check syntax.'}}
|
||||
self.assertDictEqual(mock_ret, ret)
|
||||
|
||||
# Test spec in plural form
|
||||
auth_list = ['@runners']
|
||||
|
|
Loading…
Add table
Reference in a new issue