From 4b6c92045fc9b0bc80f92f85b2c9304d4d18ef2f Mon Sep 17 00:00:00 2001 From: mprahl Date: Dec 13 2018 17:49:38 +0000 Subject: [PATCH 1/2] Add a `ctx` kwarg to ClientSession.krb_login Before this change, `koji.ClientSession.krb_login` always used the default context. This can be an issue when a multi-threaded application shares this context and the Kerberos cache is stored in the thread keyring. In this scenario, the first thread to run `krb_login` will succeed while all others will get a "Permission denied" error. By adding the `ctx` kwarg, a thread can establish a context and tell `krb_login` to use it instead of the default context. --- diff --git a/koji/__init__.py b/koji/__init__.py index aba10ec..1bc9212 100644 --- a/koji/__init__.py +++ b/koji/__init__.py @@ -2107,7 +2107,7 @@ class ClientSession(object): sinfo = self.callMethod('subsession') return type(self)(self.baseurl, self.opts, sinfo) - def krb_login(self, principal=None, keytab=None, ccache=None, proxyuser=None): + def krb_login(self, principal=None, keytab=None, ccache=None, proxyuser=None, ctx=None): """Log in using Kerberos. If principal is not None and keytab is not None, then get credentials for the given principal from the given keytab. If both are None, authenticate using existing local credentials (as obtained @@ -2115,7 +2115,8 @@ class ClientSession(object): not specified, the default ccache will be used. If proxyuser is specified, log in the given user instead of the user associated with the Kerberos principal. The principal must be in the "ProxyPrincipals" list on - the server side.""" + the server side. ctx is the Kerberos context to use, and should be unique + per thread. If ctx is not specified, the default context is used.""" try: # Silently try GSSAPI first @@ -2134,7 +2135,8 @@ class ClientSession(object): "Please install python-krbV to use kerberos." ) - ctx = krbV.default_context() + if not ctx: + ctx = krbV.default_context() if ccache != None: ccache = krbV.CCache(name='FILE:' + ccache, context=ctx) From 5687f7bcef6225161288307cd7d0009e6641c863 Mon Sep 17 00:00:00 2001 From: mprahl Date: Dec 13 2018 17:57:45 +0000 Subject: [PATCH 2/2] Don't force the Kerberos cache to be stored as a file when using the ccache kwarg on krb_login A multi-threaded application may choose to store the Kerberos cache in the thread keyring [1] to avoid Kerberos cache corruption. Since `krb_login` prepends the passed in `ccache` with `FILE:`, the application must resort to setting the `KRB_CCACHE` environment variable. This is annoying and unnecessary because ccache defaults to `FILE` anyways if no Kerberos cache type is specified in the value for `ccache` [2]. 1 - http://man7.org/linux/man-pages/man7/thread-keyring.7.html 2 - https://web.mit.edu/kerberos/krb5-1.12/doc/basic/ccache_def.html#ccache-types --- diff --git a/koji/__init__.py b/koji/__init__.py index 1bc9212..f2d7d44 100644 --- a/koji/__init__.py +++ b/koji/__init__.py @@ -2139,7 +2139,7 @@ class ClientSession(object): ctx = krbV.default_context() if ccache != None: - ccache = krbV.CCache(name='FILE:' + ccache, context=ctx) + ccache = krbV.CCache(name=ccache, context=ctx) else: ccache = ctx.default_ccache()