diff --git a/docs/source/index.rst b/docs/source/index.rst index 965ab83b..5ce4df47 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -25,6 +25,7 @@ Contents access_controls permissions defining_hub_policies + kerberos_gssapi_debug external_repo_server_bootstrap image_build winbuild diff --git a/docs/source/kerberos_gssapi_debug.rst b/docs/source/kerberos_gssapi_debug.rst new file mode 100644 index 00000000..67117e6b --- /dev/null +++ b/docs/source/kerberos_gssapi_debug.rst @@ -0,0 +1,21 @@ +============================== +Koji Kerberos/GSSAPI debugging +============================== + +Run basic command Koji with debug option isn't help to debug Kerberos/GSSAPI issue. + +:: + + koji -d hello + +Run following KRB5_TRACE command for debug Kerberos/GSSAPI auth issues: + +:: + + KRB5_TRACE=/dev/stdout python koji -d hello + +Kerberos/GSSAPI debug results: + +#. TGS request result: Server krbtgt/SERVER.COM not found in Kerberos database + + Used Kerberos which is not related to current Kerberos database. diff --git a/koji/__init__.py b/koji/__init__.py index 41706064..0b4cd9db 100644 --- a/koji/__init__.py +++ b/koji/__init__.py @@ -416,6 +416,11 @@ class LiveMediaError(GenericError): faultCode = 1022 +class GSSAPIAuthError(AuthError): + """Raised when GSSAPI issue in authentication""" + faultCode = 1023 + + class MultiCallInProgress(object): """ Placeholder class to be returned by method calls when in the process of @@ -2492,9 +2497,11 @@ class ClientSession(object): # will fail with a handshake failure, which is retried by default. sinfo = self._callMethod('sslLogin', [proxyuser], retry=False) except Exception as e: - e_str = ''.join(traceback.format_exception_only(type(e), e)) - e_str = 'gssapi auth failed: %s' % e_str - self.logger.debug(e_str) + e_str = ''.join(traceback.format_exception_only(type(e), e)).strip('\n') + e_str = '(gssapi auth failed: %s)\n' % e_str + e_str += 'Use following documentation to debug kerberos/gssapi auth issues. ' \ + 'https://docs.pagure.org/koji/kerberos_gssapi_debug/' + self.logger.error(e_str) # Auth with https didn't work. Restore for the next attempt. self.baseurl = old_baseurl finally: @@ -2507,8 +2514,8 @@ class ClientSession(object): if not sinfo: err = 'unable to obtain a session' if e_str: - err += ' (%s)' % e_str - raise AuthError(err) + err += ' %s' % e_str + raise GSSAPIAuthError(err) self.setSession(sinfo) diff --git a/tests/test_lib/test_gssapi.py b/tests/test_lib/test_gssapi.py index f796f8f7..afbc8978 100644 --- a/tests/test_lib/test_gssapi.py +++ b/tests/test_lib/test_gssapi.py @@ -82,7 +82,7 @@ class TestGSSAPI(unittest.TestCase): def test_gssapi_login_error(self): old_environ = dict(**os.environ) self.session._callMethod.side_effect = Exception('login failed') - with self.assertRaises(koji.AuthError): + with self.assertRaises(koji.GSSAPIAuthError): self.session.gssapi_login() self.session._callMethod.assert_called_once_with('sslLogin', [None], retry=False) @@ -101,7 +101,7 @@ class TestGSSAPI(unittest.TestCase): # failed gssapi auth should leave the url alone self.session.baseurl = url1 self.session._callMethod.side_effect = Exception('login failed') - with self.assertRaises(koji.AuthError): + with self.assertRaises(koji.GSSAPIAuthError): self.session.gssapi_login() self.assertEqual(self.session.baseurl, url1) self.assertEqual(old_environ, dict(**os.environ))