PR#3010: Honour --force-auth for anonymous commands
Merges #3010 https://pagure.io/koji/pull-request/3010 Fixes: #2657 https://pagure.io/koji/issue/2657 ensure_connection doesn't honor --force-auth
This commit is contained in:
commit
f358fd7bc4
10 changed files with 37 additions and 19 deletions
2
cli/koji
2
cli/koji
|
|
@ -127,7 +127,7 @@ def get_options():
|
|||
parser.add_option("--password", help=_("specify password"))
|
||||
parser.add_option("--noauth", action="store_true", default=False,
|
||||
help=_("do not authenticate"))
|
||||
parser.add_option("--force-auth", action="store_true", default=False,
|
||||
parser.add_option("--force-auth", action="store_true", # default (False) comes from the config
|
||||
help=_("authenticate even for read-only operations"))
|
||||
parser.add_option("--authtype", help=_("force use of a type of authentication, options: "
|
||||
"noauth, ssl, password, or kerberos"))
|
||||
|
|
|
|||
|
|
@ -45,3 +45,6 @@
|
|||
|
||||
;timeout of GSSAPI/SSL authentication by seconds, default: 60
|
||||
;auth_timeout = 60
|
||||
|
||||
;enforcing CLI authentication even for anonymous calls
|
||||
;force_auth = False
|
||||
|
|
|
|||
|
|
@ -1793,6 +1793,7 @@ def handle_prune_signed_copies(goptions, session, args):
|
|||
cutoff_ts = time.time() - options.days * 24 * 3600
|
||||
if options.debug:
|
||||
print("Cutoff date: %s" % time.asctime(time.localtime(cutoff_ts)))
|
||||
activate_session(session, goptions)
|
||||
if not options.build:
|
||||
if options.verbose:
|
||||
print("Getting builds...")
|
||||
|
|
@ -2145,11 +2146,12 @@ def handle_add_volume(goptions, session, args):
|
|||
print("Added volume %(name)s with id %(id)i" % volinfo)
|
||||
|
||||
|
||||
def handle_list_volumes(options, session, args):
|
||||
def anon_handle_list_volumes(goptions, session, args):
|
||||
"[info] List storage volumes"
|
||||
usage = _("usage: %prog list-volumes")
|
||||
parser = OptionParser(usage=get_usage_str(usage))
|
||||
(options, args) = parser.parse_args(args)
|
||||
ensure_connection(session, goptions)
|
||||
for volinfo in session.listVolumes():
|
||||
print(volinfo['name'])
|
||||
|
||||
|
|
@ -7265,6 +7267,7 @@ def anon_handle_download_logs(options, session, args):
|
|||
for child_task in child_tasks:
|
||||
save_logs(child_task['id'], match, task_log_dir, recurse)
|
||||
|
||||
ensure_connection(session, options)
|
||||
for arg in args:
|
||||
if suboptions.nvr:
|
||||
suboptions.recurse = True
|
||||
|
|
@ -7413,6 +7416,7 @@ def anon_handle_wait_repo(options, session, args):
|
|||
|
||||
tag = args[0]
|
||||
|
||||
ensure_connection(session, options)
|
||||
if suboptions.target:
|
||||
target_info = session.getBuildTarget(tag)
|
||||
if not target_info:
|
||||
|
|
@ -7686,7 +7690,7 @@ _search_types = ('package', 'build', 'tag', 'target', 'user', 'host', 'rpm',
|
|||
'maven', 'win')
|
||||
|
||||
|
||||
def anon_handle_search(options, session, args):
|
||||
def anon_handle_search(goptions, session, args):
|
||||
"[search] Search the system"
|
||||
usage = _("usage: %prog search [options] <search_type> <pattern>")
|
||||
usage += _('\nAvailable search types: %s') % ', '.join(_search_types)
|
||||
|
|
@ -7707,6 +7711,7 @@ def anon_handle_search(options, session, args):
|
|||
matchType = 'regexp'
|
||||
elif options.exact:
|
||||
matchType = 'exact'
|
||||
ensure_connection(session, goptions)
|
||||
data = session.search(pattern, type, matchType)
|
||||
for row in data:
|
||||
print(row['name'])
|
||||
|
|
|
|||
|
|
@ -136,6 +136,10 @@ def get_usage_str(usage):
|
|||
|
||||
|
||||
def ensure_connection(session, options=None):
|
||||
if options and options.force_auth:
|
||||
# in such case we should act as a real activate_session
|
||||
activate_session(session, options)
|
||||
return
|
||||
try:
|
||||
ret = session.getAPIVersion()
|
||||
except requests.exceptions.ConnectionError as ex:
|
||||
|
|
@ -751,6 +755,8 @@ def activate_session(session, options):
|
|||
warn(_("Could not connect to Kerberos authentication service: %s") % e.args[1])
|
||||
if not noauth and not session.logged_in:
|
||||
error(_("Unable to log in, no authentication methods available"))
|
||||
# don't add "options" to ensure_connection it would create loop in case of --force-auth
|
||||
# when it calls activate_session
|
||||
ensure_connection(session)
|
||||
if getattr(options, 'debug', None):
|
||||
print("successfully connected to hub")
|
||||
|
|
|
|||
|
|
@ -1942,6 +1942,7 @@ def read_config(profile_name, user_config=None):
|
|||
'debug_xmlrpc': False,
|
||||
'pyver': None,
|
||||
'plugin_paths': None,
|
||||
'force_auth': False,
|
||||
}
|
||||
|
||||
result = config_defaults.copy()
|
||||
|
|
@ -1978,7 +1979,7 @@ def read_config(profile_name, user_config=None):
|
|||
# not have a default value set in the option parser.
|
||||
if name in result:
|
||||
if name in ('anon_retry', 'offline_retry', 'use_fast_upload',
|
||||
'debug', 'debug_xmlrpc'):
|
||||
'debug', 'debug_xmlrpc', 'force_auth'):
|
||||
result[name] = config.getboolean(profile_name, name)
|
||||
elif name in ('max_retries', 'retry_interval',
|
||||
'offline_retry_interval', 'poll_interval',
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ class TestDownloadLogs(utils.CliTestCase):
|
|||
'koji_cli.commands.list_task_output_all_volumes').start()
|
||||
self.ensuredir = mock.patch('koji.ensuredir').start()
|
||||
self.download_file = mock.patch('koji_cli.commands.download_file').start()
|
||||
self.activate_session = mock.patch('koji_cli.commands.activate_session').start()
|
||||
self.ensure_connection = mock.patch('koji_cli.commands.ensure_connection').start()
|
||||
self.stdout = mock.patch('sys.stdout', new_callable=six.StringIO).start()
|
||||
self.stderr = mock.patch('sys.stderr', new_callable=six.StringIO).start()
|
||||
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ class TestCliListTargets(utils.CliTestCase):
|
|||
time.tzset()
|
||||
|
||||
@mock.patch('sys.stderr', new_callable=six.StringIO)
|
||||
@mock.patch('koji_cli.commands.activate_session')
|
||||
@mock.patch('koji_cli.commands.ensure_connection')
|
||||
def test_list_targets_error_args(self, ensure_connection_mock, stderr):
|
||||
session = mock.MagicMock(getAPIVersion=lambda: koji.API_VERSION,
|
||||
getBuildTargets=lambda n: [])
|
||||
|
|
@ -47,7 +47,7 @@ class TestCliListTargets(utils.CliTestCase):
|
|||
self.assertExitCode(ex, 2)
|
||||
|
||||
@mock.patch('sys.stderr', new_callable=six.StringIO)
|
||||
@mock.patch('koji_cli.commands.activate_session')
|
||||
@mock.patch('koji_cli.commands.ensure_connection')
|
||||
def test_list_targets_error_all_not_found(self, ensure_connection_mock, stderr):
|
||||
session = mock.MagicMock(getAPIVersion=lambda: koji.API_VERSION,
|
||||
getBuildTargets=lambda n: [])
|
||||
|
|
@ -60,7 +60,7 @@ class TestCliListTargets(utils.CliTestCase):
|
|||
@mock.patch('optparse.OptionParser.parse_args',
|
||||
return_value=(Values({'quiet': False, 'name': 'f50'}), []))
|
||||
@mock.patch('sys.stderr', new_callable=six.StringIO)
|
||||
@mock.patch('koji_cli.commands.activate_session')
|
||||
@mock.patch('koji_cli.commands.ensure_connection')
|
||||
def test_list_targets_error_name_not_found(self, ensure_connection_mock, stderr, opt):
|
||||
session = mock.MagicMock(getAPIVersion=lambda: koji.API_VERSION,
|
||||
getBuildTargets=lambda n: [])
|
||||
|
|
@ -71,7 +71,7 @@ class TestCliListTargets(utils.CliTestCase):
|
|||
self.assertTrue('No such build target:' in stderr.getvalue())
|
||||
|
||||
@mock.patch('sys.stdout', new_callable=six.StringIO)
|
||||
@mock.patch('koji_cli.commands.activate_session')
|
||||
@mock.patch('koji_cli.commands.ensure_connection')
|
||||
def test_list_targets_all(self, ensure_connection_mock, stdout):
|
||||
session = mock.MagicMock(getAPIVersion=lambda: koji.API_VERSION,
|
||||
getBuildTargets=lambda n: _mock_targets)
|
||||
|
|
@ -88,7 +88,7 @@ class TestCliListTargets(utils.CliTestCase):
|
|||
@mock.patch('optparse.OptionParser.parse_args',
|
||||
return_value=(Values({'quiet': False, 'name': 'f50'}), []))
|
||||
@mock.patch('sys.stdout', new_callable=six.StringIO)
|
||||
@mock.patch('koji_cli.commands.activate_session')
|
||||
@mock.patch('koji_cli.commands.ensure_connection')
|
||||
def test_list_targets_one(self, ensure_connection_mock, stdout, opt):
|
||||
session = mock.MagicMock(getAPIVersion=lambda: koji.API_VERSION,
|
||||
getBuildTargets=lambda n: _mock_targets)
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import mock
|
|||
import six
|
||||
import unittest
|
||||
|
||||
from koji_cli.commands import handle_list_volumes
|
||||
from koji_cli.commands import anon_handle_list_volumes
|
||||
from . import utils
|
||||
|
||||
|
||||
|
|
@ -13,12 +13,12 @@ class TestListVolumes(utils.CliTestCase):
|
|||
maxDiff = None
|
||||
|
||||
@mock.patch('sys.stdout', new_callable=six.StringIO)
|
||||
@mock.patch('koji_cli.commands.activate_session')
|
||||
def test_handle_list_volumes(
|
||||
@mock.patch('koji_cli.commands.ensure_connection')
|
||||
def test_anon_handle_list_volumes(
|
||||
self,
|
||||
activate_session_mock,
|
||||
ensure_connection_mock,
|
||||
stdout):
|
||||
"""Test handle_list_volumes function"""
|
||||
"""Test anon_handle_list_volumes function"""
|
||||
session = mock.MagicMock()
|
||||
options = mock.MagicMock()
|
||||
vol_info = [
|
||||
|
|
@ -29,12 +29,12 @@ class TestListVolumes(utils.CliTestCase):
|
|||
|
||||
expected = "\n".join([v['name'] for v in vol_info]) + "\n"
|
||||
session.listVolumes.return_value = vol_info
|
||||
handle_list_volumes(options, session, [])
|
||||
anon_handle_list_volumes(options, session, [])
|
||||
self.assert_console_message(stdout, expected)
|
||||
|
||||
def test_handle_list_volumes_help(self):
|
||||
def test_anon_handle_list_volumes_help(self):
|
||||
self.assert_help(
|
||||
handle_list_volumes,
|
||||
anon_handle_list_volumes,
|
||||
"""Usage: %s list-volumes
|
||||
(Specify the --help global option for a list of other help options)
|
||||
|
||||
|
|
|
|||
|
|
@ -20,10 +20,12 @@ Available search types: package, build, tag, target, user, host, rpm, maven, win
|
|||
%s: error: {message}
|
||||
""" % (self.progname, self.progname)
|
||||
|
||||
@mock.patch('koji_cli.commands.ensure_connection')
|
||||
@mock.patch('sys.stdout', new_callable=six.StringIO)
|
||||
def test_anon_handle_search(
|
||||
self,
|
||||
stdout):
|
||||
stdout,
|
||||
ensure_connection_mock):
|
||||
"""Test anon_handle_search function"""
|
||||
session = mock.MagicMock()
|
||||
options = mock.MagicMock()
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ class TestWaitRepo(utils.CliTestCase):
|
|||
|
||||
def setUpMocks(self):
|
||||
self.activate_session = mock.patch('koji_cli.commands.activate_session').start()
|
||||
self.ensure_connection = mock.patch('koji_cli.commands.ensure_connection').start()
|
||||
self.checkForBuilds = mock.patch('koji.util.checkForBuilds').start()
|
||||
|
||||
def tearDown(self):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue