From 777490bd19ea3bcd3d495336d9a39b75704448ff Mon Sep 17 00:00:00 2001 From: Chenxiong Qi Date: Dec 19 2016 14:23:16 +0000 Subject: Better message when fail to authenticate via Kerberos Fixes: #180 Both lookaside and Koji require Kerberos authentication now. This patch prints more meaningful message to notify user why specific operation cannot be performed. Signed-off-by: Chenxiong Qi --- diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 9ba0fd0..807d41c 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -4,6 +4,7 @@ ChangeLog v1.47 (2016-12-15) ------------------ +- Better message when fail to authenticate via Kerberos - #180 (cqi) - Refactor Commands._srpmdetails - Add missing import koji.ssl.SSLCommon - BZ#1404102 (cqi) - Fix upload with old PyCURL - BZ#1241059 (lsedlar) diff --git a/pyrpkg/__init__.py b/pyrpkg/__init__.py index 91e376e..61907a2 100644 --- a/pyrpkg/__init__.py +++ b/pyrpkg/__init__.py @@ -346,7 +346,19 @@ class Commands(object): # Or try kerberos elif authtype == 'kerberos' or self._has_krb_creds() and authtype is None: - session.krb_login(proxyuser=self.runas) + self.log.debug('Logging into {0} with Kerberos authentication.'.format( + koji_config['server'])) + + if self._load_krb_user(): + try: + session.krb_login(proxyuser=self.runas) + except koji.krbV.Krb5Error as e: + self.log.error('Kerberos authentication fails: %s', e.args[1]) + else: + self.log.warning('Kerberos authentication is used, but you do not have a ' + 'valid credential.') + self.log.warning('Please use kinit to get credential with a principal that has ' + 'realm {0}'.format(', '.join(list(self.realms)))) if not session.logged_in: raise rpkgError('Could not login to %s' % koji_config['server']) @@ -803,7 +815,8 @@ class Commands(object): """This property ensures the user attribute""" if not self._user: - if not self._load_krb_user(): + self._user = self._load_krb_user() + if not self._user: self.load_user() return self._user @@ -811,7 +824,7 @@ class Commands(object): """This attempts to get the username from active tickets""" if not self.realms: - return False + return None if not isinstance(self.realms, list): self.realms = [self.realms] @@ -819,10 +832,9 @@ class Commands(object): for realm in self.realms: username = cccolutils.get_user_for_realm(realm) if username: - self._user = username - return True + return username # We could not find a username for any of the realms, let's fall back - return False + return None def load_user(self): """This sets the user attribute""" diff --git a/pyrpkg/errors.py b/pyrpkg/errors.py index 5ea5f08..62924a9 100644 --- a/pyrpkg/errors.py +++ b/pyrpkg/errors.py @@ -50,4 +50,13 @@ class DownloadError(rpkgError): class UploadError(rpkgError): """Raised when something went wrong during an upload""" - pass + + def __init__(self, message, http_status=None): + self.message = message + self.http_status = http_status + + def __str__(self): + return str(self.message) + + def __unicode__(self): + return unicode(self.message) diff --git a/pyrpkg/lookaside.py b/pyrpkg/lookaside.py index de97b91..18823b7 100644 --- a/pyrpkg/lookaside.py +++ b/pyrpkg/lookaside.py @@ -24,6 +24,7 @@ import pycurl import six from .errors import DownloadError, InvalidHashType, UploadError +from six.moves import http_client class CGILookasideCache(object): @@ -122,6 +123,15 @@ class CGILookasideCache(object): sum = self.hash_file(filename, hashtype) return sum == hash + def raise_upload_error(self, http_status): + messages = { + http_client.UNAUTHORIZED: 'Request is unauthorized.', + http_client.INTERNAL_SERVER_ERROR: 'Error occurs inside the server.', + } + default = 'Fail to upload files. Server returns status {0}'.format(http_status) + message = messages.get(http_status, default) + raise UploadError(message, http_status=http_status) + def download(self, name, filename, hash, outfile, hashtype=None, **kwargs): """Download a source file @@ -235,7 +245,7 @@ class CGILookasideCache(object): output = buf.getvalue().strip() if status != 200: - raise UploadError(output) + self.raise_upload_error(status) # Lookaside CGI script returns these strings depending on whether # or not the file exists: @@ -316,7 +326,7 @@ class CGILookasideCache(object): sys.stdout.flush() if status != 200: - raise UploadError(output) + self.raise_upload_error(status) if output: self.log.debug(output)