remove deprecated krbV support

Fixes: https://pagure.io/koji/issue/1991
This commit is contained in:
Tomas Kopecek 2020-05-13 16:36:32 +02:00 committed by Mike McLean
parent ee93da4177
commit f8419e3626
25 changed files with 30 additions and 552 deletions

View file

@ -69,12 +69,6 @@ from koji.tasks import (
)
from koji.util import dslice, dslice_ex, isSuccess, parseStatus, to_list
try:
import krbV
Krb5Error = krbV.Krb5Error
except ImportError: # pragma: no cover
krbV = None
try:
import requests_kerberos
Krb5Error = requests_kerberos.exceptions.RequestException
@ -6454,10 +6448,6 @@ def get_options():
'host_principal_format': 'compile/%s@EXAMPLE.COM',
'keytab': '/etc/kojid/kojid.keytab',
'ccache': '/var/tmp/kojid.ccache',
'krbservice': 'host',
'krb_rdns': True,
'krb_canon_host': False,
'krb_server_realm': None,
'server': None,
'user': None,
'password': None,
@ -6501,8 +6491,7 @@ def get_options():
quit("value for %s option must be a valid integer" % name)
elif name in ['offline_retry', 'use_createrepo_c', 'createrepo_skip_stat',
'createrepo_update', 'use_fast_upload', 'support_rpm_source_layout',
'krb_rdns', 'krb_canon_host', 'build_arch_can_fail', 'no_ssl_verify',
'log_timestamps']:
'build_arch_can_fail', 'no_ssl_verify', 'log_timestamps']:
defaults[name] = config.getboolean('kojid', name)
elif name in ['plugin', 'plugins']:
defaults['plugin'] = value.split()
@ -6608,14 +6597,14 @@ if __name__ == "__main__":
quit("Error: Unable to log in. Bad credentials?")
except requests.exceptions.ConnectionError:
quit("Error: Unable to connect to server %s" % (options.server))
elif krbV or requests_kerberos:
elif requests_kerberos:
krb_principal = options.krb_principal
if krb_principal is None:
krb_principal = options.host_principal_format % socket.getfqdn()
try:
session.krb_login(principal=krb_principal,
keytab=options.keytab,
ccache=options.ccache)
session.gssapi_login(principal=krb_principal,
keytab=options.keytab,
ccache=options.ccache)
except Krb5Error as e:
quit("Kerberos authentication failed: %s" % e.args)
except socket.error as e:

View file

@ -102,9 +102,6 @@ from_addr=Koji Build System <buildsys@example.com>
;location of the keytab
;keytab = /etc/kojid/kojid.keytab
;the service name of the principal being used by the hub
;krbservice = host
;configuration for SSL authentication
;client certificate

View file

@ -119,7 +119,6 @@ def get_options():
help=_("specify a configuration profile"))
parser.add_option("--keytab", help=_("specify a Kerberos keytab to use"), metavar="FILE")
parser.add_option("--principal", help=_("specify a Kerberos principal to use"))
parser.add_option("--krbservice", help=_("specify the Kerberos service name for the hub"))
parser.add_option("--cert", help=_("specify a SSL cert to use"), metavar="FILE")
parser.add_option("--ca", help=SUPPRESS_HELP, metavar="FILE") # FIXME: remove in 1.24
parser.add_option("--runas", help=_("run as the specified user (requires special privileges)"))

View file

@ -16,21 +16,12 @@
;configuration for Kerberos authentication
;the service name of the principal being used by the hub
;krbservice = host
;the principal to auth as for automated clients
;principal = client@EXAMPLE.COM
;the keytab to auth as for automated clients
;keytab = /etc/krb5.keytab
;enable to lookup dns canonical hostname for krb auth
;krb_canon_host = no
;The realm of server principal. Using client's realm if not set
;krb_server_realm = EXAMPLE.COM
;configuration for SSL authentication

View file

@ -20,11 +20,6 @@ import koji
from koji import parse_arches
from koji.util import md5_constructor, to_list
try:
import krbV
except ImportError: # pragma: no cover
krbV = None
# for compatibility with plugins based on older version of lib
# Use optparse imports directly in new code.
@ -663,18 +658,6 @@ def warn(msg):
sys.stderr.flush()
def has_krb_creds():
if krbV is None:
return False
try:
ctx = krbV.default_context()
ccache = ctx.default_ccache()
ccache.principal()
return True
except krbV.Krb5Error:
return False
def activate_session(session, options):
"""Test and login the session is applicable"""
if isinstance(options, dict):
@ -692,7 +675,7 @@ def activate_session(session, options):
and options.authtype is None:
# authenticate using user/password
session.login()
elif options.authtype == "kerberos" or has_krb_creds() and options.authtype is None:
elif options.authtype == "kerberos" or options.authtype is None:
try:
if getattr(options, 'keytab', None) and getattr(options, 'principal', None):
session.gssapi_login(principal=options.principal, keytab=options.keytab,

View file

@ -242,27 +242,6 @@ Kerberos Authentication
keytab=/etc/kojid/kojid.keytab
Location of the keytab.
krb_canon_host=False
Kerberos authentication requires correct hostnames. If this option is
specified, dns is used to get the correct hostname for the
server (i.e. resolve any CNAMEs). Note, this option will not function
unless ``python-dns`` is installed.
The ``krb_rdns`` option takes a different approach.
krb_principal=None
Explicit principal used for login. If it is not specified, it is
created via ``host_principal_format``.
krb_rdns=True
Kerberos authentication needs correct hostname. If this option is
specified, ``socket.getfqdn(host)`` is used to determine reverse DNS
records. Otherwise, ``host`` is used directly. Playing with this option
can help you in some firewalled setups. ``krb_canon_host`` takes
precedence over this option and takes a different approach.
krbservice=host
The service name of the principal being used by the hub.
SSL Authentication
^^^^^^^^^^^^^^^^^^

View file

@ -883,11 +883,6 @@ For a simple test, all we need is the ``server`` and authentication sections.
;path to the koji top directory
topdir = /mnt/koji
; configuration for Kerberos authentication
;the service name of the principal being used by the hub
;krbservice = host
; configuration for SSL athentication
;client certificate
@ -1351,12 +1346,6 @@ Authentication Configuration
;location of the keytab
;keytab = /etc/kojira/kojira.keytab
;the service name of the principal being used by the hub
;krbservice = host
;The realm of server principal. Using client's realm if not set
;krb_server_realm = EXAMPLE.COM
``/etc/sysconfig/kojira``
The local user kojira runs as needs to be able to read and write to
``/mnt/koji/repos/``. If the volume that directory resides on is

View file

@ -125,11 +125,7 @@ Requires: rpm-python
%endif
Requires: pyOpenSSL
Requires: python-requests
%if 0%{?fedora} || 0%{?rhel} >= 7
Requires: python-requests-kerberos
%else
Requires: python-krbV >= 1.0.13
%endif
Requires: python-dateutil
Requires: python-six

View file

@ -62,16 +62,6 @@ from six.moves import range, zip
from koji.xmlrpcplus import Fault, dumps, getparser, loads, xmlrpc_client
from . import util
krbV = None
try:
import krbV
except ImportError: # pragma: no cover
pass
dns_resolver = None
try:
import dns.resolver as dns_resolver
except ImportError: # pragma: no cover
pass
SSL_Error = None
try:
from OpenSSL.SSL import Error as SSL_Error
@ -1899,10 +1889,6 @@ def read_config(profile_name, user_config=None):
'use_fast_upload': False,
'upload_blocksize': 1048576,
'poll_interval': 6,
'krbservice': 'host',
'krb_rdns': True,
'krb_canon_host': False,
'krb_server_realm': None,
'principal': None,
'keytab': None,
'cert': None,
@ -1949,9 +1935,8 @@ def read_config(profile_name, user_config=None):
# options *can* be set via the config file. Such options should
# not have a default value set in the option parser.
if name in result:
if name in ('anon_retry', 'offline_retry',
'use_fast_upload', 'krb_rdns', 'debug',
'debug_xmlrpc', 'krb_canon_host'):
if name in ('anon_retry', 'offline_retry', 'use_fast_upload',
'debug', 'debug_xmlrpc'):
result[name] = config.getboolean(profile_name, name)
elif name in ('max_retries', 'retry_interval',
'offline_retry_interval', 'poll_interval',
@ -2371,7 +2356,6 @@ def grab_session_options(options):
s_opts = (
'user',
'password',
'krbservice',
'debug_xmlrpc',
'debug',
'max_retries',
@ -2383,9 +2367,6 @@ def grab_session_options(options):
'auth_timeout',
'use_fast_upload',
'upload_blocksize',
'krb_rdns',
'krb_canon_host',
'krb_server_realm',
'no_ssl_verify',
'serverca',
)
@ -2473,121 +2454,6 @@ 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, 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
from kinit). ccache is the absolute path to use for the credential cache. If
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. ctx is the Kerberos context to use, and should be unique
per thread. If ctx is not specified, the default context is used."""
util.deprecated("Please use gssapi_login instead, krb_login will be removed in koji 1.22")
try:
# Silently try GSSAPI first
if self.gssapi_login(principal, keytab, ccache, proxyuser=proxyuser):
return True
except Exception as e:
if krbV:
e_str = ''.join(traceback.format_exception_only(type(e), e))
self.logger.debug('gssapi auth failed: %s', e_str)
pass
else:
raise
if not krbV:
raise PythonImportError(
"Please install python-krbV to use kerberos."
)
if not ctx:
ctx = krbV.default_context()
if ccache is not None:
ccache = krbV.CCache(name=ccache, context=ctx)
else:
ccache = ctx.default_ccache()
if principal is not None:
if keytab is not None:
cprinc = krbV.Principal(name=principal, context=ctx)
keytab = krbV.Keytab(name=keytab, context=ctx)
ccache.init(cprinc)
ccache.init_creds_keytab(principal=cprinc, keytab=keytab)
else:
raise AuthError('cannot specify a principal without a keytab')
else:
# We're trying to log ourself in. Connect using existing credentials.
cprinc = ccache.principal()
self.logger.debug('Authenticating as: %s', cprinc.name)
sprinc = krbV.Principal(name=self._serverPrincipal(cprinc), context=ctx)
ac = krbV.AuthContext(context=ctx)
ac.flags = krbV.KRB5_AUTH_CONTEXT_DO_SEQUENCE | krbV.KRB5_AUTH_CONTEXT_DO_TIME
ac.rcache = ctx.default_rcache()
# create and encode the authentication request
(ac, req) = ctx.mk_req(server=sprinc, client=cprinc,
auth_context=ac, ccache=ccache,
options=krbV.AP_OPTS_MUTUAL_REQUIRED)
req_enc = base64.encodestring(req)
# ask the server to authenticate us
(rep_enc, sinfo_enc, addrinfo) = self.callMethod('krbLogin', req_enc, proxyuser)
# Set the addrinfo we received from the server
# (necessary before calling rd_priv())
# addrinfo is in (serveraddr, serverport, clientaddr, clientport)
# format, so swap the pairs because clientaddr is now the local addr
ac.addrs = tuple((addrinfo[2], addrinfo[3], addrinfo[0], addrinfo[1]))
# decode and read the reply from the server
rep = base64.b64decode(rep_enc)
ctx.rd_rep(rep, auth_context=ac)
# decode and decrypt the login info
sinfo_priv = base64.b64decode(sinfo_enc)
sinfo_str = ac.rd_priv(sinfo_priv)
sinfo = dict(zip(['session-id', 'session-key'], sinfo_str.split()))
if not sinfo:
self.logger.warning('No session info received')
return False
self.setSession(sinfo)
self.krb_principal = cprinc.name
self.authtype = AUTHTYPE_KERB
return True
def _serverPrincipal(self, cprinc):
"""Get the Kerberos principal of the server we're connecting
to, based on baseurl."""
host = six.moves.urllib.parse.urlparse(self.baseurl).hostname
servername = self._fix_krb_host(host)
realm = self.opts.get('krb_server_realm')
if not realm:
realm = cprinc.realm
service = self.opts.get('krbservice', 'host')
ret = '%s/%s@%s' % (service, servername, realm)
self.logger.debug('Using server principal: %s', ret)
return ret
def _fix_krb_host(self, host):
if self.opts.get('krb_canon_host', False):
if dns_resolver is None:
self.logger.warning('python-dns missing -- cannot resolve hostname')
else:
answer = dns_resolver.query(host, 'A')
return answer.canonical_name.to_text(omit_final_dot=True)
if self.opts.get('krb_rdns', True):
return socket.getfqdn(host)
# else
return host
def gssapi_login(self, principal=None, keytab=None, ccache=None, proxyuser=None):
if not requests_kerberos:
raise PythonImportError(

View file

@ -21,7 +21,6 @@
from __future__ import absolute_import
import base64
import random
import re
import socket
@ -34,11 +33,6 @@ import koji
from .context import context
from .util import to_list
try:
import krbV
except ImportError:
krbV = None
# 1 - load session if provided
# - check uri for session id
# - load session info from db
@ -300,82 +294,6 @@ class Session(object):
context.cnx.commit()
return sinfo
def krbLogin(self, krb_req, proxyuser=None):
"""Authenticate the user using the base64-encoded
AP_REQ message in krb_req. If proxyuser is not None,
log in that user instead of the user associated with the
Kerberos principal. The principal must be an authorized
"proxy_principal" in the server config."""
if self.logged_in:
raise koji.AuthError("Already logged in")
if krbV is None:
# python3 is not supported
raise koji.AuthError("krbV module not installed")
if not (context.opts.get('AuthPrincipal') and context.opts.get('AuthKeytab')):
raise koji.AuthError('not configured for Kerberos authentication')
ctx = krbV.default_context()
srvprinc = krbV.Principal(name=context.opts.get('AuthPrincipal'), context=ctx)
srvkt = krbV.Keytab(name=context.opts.get('AuthKeytab'), context=ctx)
ac = krbV.AuthContext(context=ctx)
ac.flags = krbV.KRB5_AUTH_CONTEXT_DO_SEQUENCE | krbV.KRB5_AUTH_CONTEXT_DO_TIME
conninfo = self.getConnInfo()
ac.addrs = conninfo
# decode and read the authentication request
req = base64.b64decode(krb_req)
ac, opts, sprinc, ccreds = ctx.rd_req(req, server=srvprinc, keytab=srvkt,
auth_context=ac,
options=krbV.AP_OPTS_MUTUAL_REQUIRED)
cprinc = ccreds[2]
# Successfully authenticated via Kerberos, now log in
if proxyuser:
proxyprincs = [princ.strip()
for princ in context.opts.get('ProxyPrincipals', '').split(',')]
if cprinc.name in proxyprincs:
login_principal = proxyuser
else:
raise koji.AuthError(
'Kerberos principal %s is not authorized to log in other users' % cprinc.name)
else:
login_principal = cprinc.name
if '@' in login_principal:
user_id = self.getUserIdFromKerberos(login_principal)
else:
# backward compatible
# it's only possible when proxyuser is username, but we shouldn't
# allow this.
user_id = self.getUserId(login_principal)
if not user_id:
# Only do autocreate if we also couldn't find by username AND the proxyuser
# looks like a krb5 principal
if context.opts.get('LoginCreatesUser') and '@' in login_principal:
user_id = self.createUserFromKerberos(login_principal)
else:
raise koji.AuthError('Unknown Kerberos principal: %s' % login_principal)
self.checkLoginAllowed(user_id)
hostip = self.get_remote_ip()
sinfo = self.createSession(user_id, hostip, koji.AUTHTYPE_KERB)
# encode the reply
rep = ctx.mk_rep(auth_context=ac)
rep_enc = base64.encodestring(rep)
# encrypt and encode the login info
sinfo_priv = ac.mk_priv('%(session-id)s %(session-key)s' % sinfo)
sinfo_enc = base64.encodestring(sinfo_priv)
return (rep_enc, sinfo_enc, conninfo)
def getConnInfo(self):
"""Return a tuple containing connection information
in the following format:

View file

@ -20,10 +20,6 @@ def get_install_requires():
# 'rpm-py-installer', # it is optional feature
# 'rpm',
]
if sys.version_info[0] < 3:
# optional auth library for older hubs
# hubs >= 1.12 are using requests' default GSSAPI
requires.append('python-krbV')
# since pyOpenSSL-18.0.0, py26 support is dropped
# see https://pagure.io/koji/issue/1060
if sys.version_info[0] == 2 and sys.version_info[1] < 7:

View file

@ -17,8 +17,6 @@ class TestActivateSession(unittest.TestCase):
self.warn = mock.patch('koji_cli.lib.warn').start()
self.error = mock.patch('koji_cli.lib.error').start()
# self.ensure_connection = mock.patch('koji_cli.lib.warn.ensure_connection').start()
self.has_krb_creds = mock.patch('koji_cli.lib.has_krb_creds').start()
self.has_krb_creds.return_value = False
def tearDown(self):
mock.patch.stopall()
@ -33,7 +31,6 @@ class TestActivateSession(unittest.TestCase):
activate_session(session, options)
session.login.assert_not_called()
session.ssl_login.assert_not_called()
session.krb_login.assert_not_called()
session.gssapi_login.assert_not_called()
def test_activate_session_ssl(self):
@ -48,7 +45,6 @@ class TestActivateSession(unittest.TestCase):
session.ssl_login.assert_called_once_with(certfile, None, 'SERVERCA',
proxyuser=None)
session.login.assert_not_called()
session.krb_login.assert_not_called()
session.gssapi_login.assert_not_called()
def test_activate_session_ssl_implicit(self):
@ -64,7 +60,6 @@ class TestActivateSession(unittest.TestCase):
session.ssl_login.assert_called_once_with(certfile, None, 'SERVERCA',
proxyuser=None)
session.login.assert_not_called()
session.krb_login.assert_not_called()
session.gssapi_login.assert_not_called()
def test_activate_session_pw(self):
@ -74,7 +69,6 @@ class TestActivateSession(unittest.TestCase):
activate_session(session, options)
session.login.assert_called_once_with()
session.ssl_login.assert_not_called()
session.krb_login.assert_not_called()
session.gssapi_login.assert_not_called()
def test_activate_session_pw_implicit(self):
@ -85,7 +79,6 @@ class TestActivateSession(unittest.TestCase):
activate_session(session, options)
session.login.assert_called_once_with()
session.ssl_login.assert_not_called()
session.krb_login.assert_not_called()
session.gssapi_login.assert_not_called()
def test_activate_session_krb(self):
@ -96,7 +89,6 @@ class TestActivateSession(unittest.TestCase):
activate_session(session, options)
session.login.assert_not_called()
session.ssl_login.assert_not_called()
session.krb_login.assert_not_called()
session.gssapi_login.assert_called_once_with(proxyuser=None)
def test_activate_session_krb_implicit(self):
@ -104,11 +96,9 @@ class TestActivateSession(unittest.TestCase):
session.logged_in = True
options = {'authtype': None, 'debug': False, 'cert': '',
'keytab': None, 'principal': None}
self.has_krb_creds.return_value = True
activate_session(session, options)
session.login.assert_not_called()
session.ssl_login.assert_not_called()
session.krb_login.assert_not_called()
session.gssapi_login.assert_called_once_with(proxyuser=None)
def test_activate_session_krb_keytab(self):
@ -119,7 +109,6 @@ class TestActivateSession(unittest.TestCase):
activate_session(session, options)
session.login.assert_not_called()
session.ssl_login.assert_not_called()
session.krb_login.assert_not_called()
session.gssapi_login.assert_called_once_with(principal='PRINCIPAL',
keytab='KEYTAB', proxyuser=None)
@ -127,10 +116,8 @@ class TestActivateSession(unittest.TestCase):
session = mock.MagicMock()
session.logged_in = False
options = {'authtype': None, 'debug': False, 'cert': ''}
self.has_krb_creds.return_value = False
activate_session(session, options)
session.login.assert_not_called()
session.ssl_login.assert_not_called()
session.krb_login.assert_not_called()
session.gssapi_login.assert_not_called()
session.gssapi_login.assert_called_once()
self.error.assert_called_once()

View file

@ -170,79 +170,6 @@ class TestAuthSession(unittest.TestCase):
with self.assertRaises(koji.AuthError):
s.login('user', 'password')
@mock.patch('koji.auth.context')
@mock.patch('koji.auth.socket')
@mock.patch('koji.auth.base64')
def test_krbLogin(self, base64, socket, context):
# TODO
s, cntext, cursor = self.get_session()
context.cnx = cntext.cnx
with self.assertRaises(koji.AuthError) as cm:
s.krbLogin('krb_req', 'proxyuser')
self.assertEqual(cm.exception.args[0], 'Already logged in')
s.logged_in = False
if six.PY3:
with self.assertRaises(koji.AuthError) as cm:
s.krbLogin('krb_req', 'proxyuser')
self.assertEqual(cm.exception.args[0], 'krbV module not installed')
else:
with mock.patch('koji.auth.krbV', create=True) as krbV:
princ = mock.MagicMock()
princ.name = 'princ_name'
krbV.default_context.return_value \
.rd_req.return_value = (mock.MagicMock(), 2, 3,
[1, 2, princ])
with self.assertRaises(koji.AuthError) as cm:
s.krbLogin('krb_req', 'proxyuser')
self.assertEqual(cm.exception.args[0],
'Kerberos principal princ_name is'
' not authorized to log in other users')
context.opts = {'ProxyPrincipals': 'anyothers,' + princ.name,
'AuthPrincipal': 'authprinc',
'AuthKeytab': 'authkeytab',
'LoginCreatesUser': False,
'CheckClientIP': False}
with self.assertRaises(koji.AuthError) as cm:
s.krbLogin('krb_req', 'proxyuser@realm.com')
self.assertEqual(cm.exception.args[0],
'Unknown Kerberos principal:'
' proxyuser@realm.com')
# case: create user by kerberos
context.opts['LoginCreatesUser'] = True
context.cnx.cursor.return_value. \
fetchone.side_effect = [None,
(1,),
('name', 'type',
koji.USER_STATUS['NORMAL']),
('session-id',)]
context.cnx.cursor.return_value.fetchall.return_value = None
s.krbLogin('krb_req', 'proxyuser@realm.com')
self.assertEqual(context.cnx.cursor.return_value.execute.
call_count, 14)
# case: create user by username, proxyuser is username
context.cnx.cursor.return_value. \
fetchone.side_effect = [None]
context.cnx.cursor.return_value.fetchall.return_value = None
with self.assertRaises(koji.AuthError) as cm:
s.krbLogin('krb_req', 'proxyuser')
self.assertEqual(cm.exception.args[0],
'Unknown Kerberos principal: proxyuser')
# case: create user by kerberos - set krb princ
context.opts['LoginCreatesUser'] = True
context.cnx.cursor.return_value. \
fetchone.side_effect = [None,
(1,),
('name', 'type',
koji.USER_STATUS['NORMAL']),
('session-id',)]
context.cnx.cursor.return_value.fetchall. \
return_value = [('proxyuser', 'proxyuser@otherrealm.com')]
s.krbLogin('krb_req', 'proxyuser@realm.com')
self.assertEqual(context.cnx.cursor.return_value.execute.
call_count, 22)
@mock.patch('koji.auth.context')
def test_checkKrbPrincipal(self, context):
s, cntext, cursor = self.get_session()

View file

@ -12,31 +12,6 @@ from koji.xmlrpcplus import Fault
class TestClientSession(unittest.TestCase):
@mock.patch('socket.getfqdn')
def test_server_principal_rdns(self, getfqdn):
opts = {'krb_rdns': True}
session = koji.ClientSession('http://koji.example.com:30/kojihub', opts)
cprinc = mock.MagicMock()
cprinc.realm = "REALM"
getfqdn.return_value = 'koji02.example.com'
princ = session._serverPrincipal(cprinc)
self.assertEqual(princ, 'host/koji02.example.com@REALM')
getfqdn.assert_called_with('koji.example.com')
@mock.patch('socket.getfqdn')
def test_server_principal_no_rdns(self, getfqdn):
opts = {'krb_rdns': False}
session = koji.ClientSession('http://koji.example.com/kojihub', opts)
cprinc = mock.MagicMock()
cprinc.realm = "REALM"
getfqdn.return_value = 'koji02.example.com'
princ = session._serverPrincipal(cprinc)
self.assertEqual(princ, 'host/koji.example.com@REALM')
getfqdn.assert_not_called()
@mock.patch('requests.Session')
def test_new_session(self, rsession):
koji.ClientSession('http://koji.example.com/kojihub')

View file

@ -9,7 +9,6 @@ import koji
NORMAL_VAL = {'user': 'jdoe',
'password': 'fakepwd',
'krbservice': 'fakekrbservice',
'debug_xmlrpc': True,
'debug': False,
'max_retries': 3,
@ -20,8 +19,6 @@ NORMAL_VAL = {'user': 'jdoe',
'timeout': 30000,
'use_fast_upload': False,
'upload_blocksize': 1024,
'krb_rdns': 'fakerdns',
'krb_canon_host': 'fakehost',
'no_ssl_verify': True,
'serverca': '/fake/serverca.cert',
}
@ -30,7 +27,6 @@ EMPTY_VAL = {}
NONE_VAL = {'user': None,
'password': None,
'krbservice': None,
'debug_xmlrpc': None,
'debug': None,
'max_retries': None,
@ -41,8 +37,6 @@ NONE_VAL = {'user': None,
'timeout': None,
'use_fast_upload': None,
'upload_blocksize': None,
'krb_rdns': None,
'krb_canon_host': None,
'no_ssl_verify': None,
'serverca': None,
}
@ -53,13 +47,11 @@ MIXED_VAL = {'user': None,
'password': None,
'anon_retry': 3,
'timeout': 100,
'krb_rdns': 'fakerdns',
'meaningless': 'wow',
'nonval': None}
MIXED_REL = {'anon_retry': 3,
'timeout': 100,
'krb_rdns': 'fakerdns',
}

View file

@ -1,41 +0,0 @@
from __future__ import absolute_import
import base64
# This is python-mock, not the rpm mock tool we know and love
import mock
import six
try:
import unittest2 as unittest
except ImportError:
import unittest
import koji
class KrbVTestCase(unittest.TestCase):
@mock.patch('koji.krbV', new=None)
@mock.patch('koji.requests_kerberos', new=None)
def test_krbv_disabled(self):
"""Test that when krbV and gssapi are absent, we behave rationally"""
self.assertEquals(koji.krbV, None)
session = koji.ClientSession('whatever')
with self.assertRaises(ImportError):
session.krb_login()
# this case should work on python3, but skipped still
@unittest.skipIf(six.PY3, "skipped on python3 since missing of python-krbV")
@mock.patch('koji.krbV', create=True)
@mock.patch('requests_kerberos.__version__', new='0.7.0')
@mock.patch('koji.ClientSession._serverPrincipal')
def test_krbv_old_requests_kerberos(self, _serverPrincipal_mock, krbV_mock):
self.assertIsNotNone(koji.krbV)
ctx = koji.krbV.default_context.return_value
ctx.mk_req = mock.MagicMock()
ac = mock.MagicMock()
ctx.mk_req.return_value = (ac, six.b('req'))
ac.rd_priv = mock.MagicMock(return_value='session-id session-key')
session = koji.ClientSession('whatever')
session._callMethod = mock.MagicMock(
return_value=(base64.encodestring(six.b('a')), base64.encodestring(six.b('b')), [0, 1, 2, 3]))
rv = session.krb_login(principal='any@SOMEWHERE.COM', keytab='/path/to/keytab')
self.assertTrue(rv)

View file

@ -16,12 +16,6 @@ unprotected_keys =
server = https://koji.fedoraproject.org/kojihub
weburl = https://koji.fedoraproject.org/koji
# The service name of the principal being used by the hub
#krbservice = host
## The realm of server principal. Using client's realm if not set
# krb_server_realm = EXAMPLE.COM
# The domain name that will be appended to Koji usernames
# when creating email notifications
#email_domain = fedoraproject.org

View file

@ -44,11 +44,6 @@ from six.moves import range
import koji
from koji.util import to_list
try:
import krbV
except ImportError: # pragma: no cover
krbV = None
# koji.fp.o keeps stalling, probably network errors...
# better to time out than to stall
socket.setdefaulttimeout(180) # XXX - too short?
@ -82,8 +77,6 @@ def get_options():
help=_("use alternate configuration file"))
parser.add_option("--keytab", help=_("specify a Kerberos keytab to use"))
parser.add_option("--principal", help=_("specify a Kerberos principal to use"))
parser.add_option("--krbservice", help=_("the service name of the"
" principal being used by the hub"))
parser.add_option("--runas", metavar="USER",
help=_("run as the specified user (requires special privileges)"))
parser.add_option("--user", help=_("specify user"))
@ -305,17 +298,12 @@ def activate_session(session):
elif options.user:
# authenticate using user/password
session.login()
elif krbV:
try:
if options.keytab and options.principal:
session.krb_login(principal=options.principal, keytab=options.keytab,
proxyuser=options.runas)
else:
session.krb_login(proxyuser=options.runas)
except krbV.Krb5Error as e:
error(_("Kerberos authentication failed: '%s' (%s)") % (e.args[1], e.args[0]))
except socket.error as e:
warn(_("Could not connect to Kerberos authentication service: '%s'") % e.args[1])
else:
if options.keytab and options.principal:
session.gssapi_login(principal=options.principal, keytab=options.keytab,
proxyuser=options.runas)
else:
session.gssapi_login(proxyuser=options.runas)
if not options.noauth and not session.logged_in:
error(_("Error: unable to log in"))
ensure_connection(session)

View file

@ -3,8 +3,4 @@
[main]
server=http://localhost/kojihub/
krbservice=host
remote=https://koji.fedoraproject.org/kojihub
## The realm of server principal. Using client's realm if not set
# krb_server_realm = EXAMPLE.COM

View file

@ -33,8 +33,6 @@ def get_options():
parser.add_option("-s", "--server", help=_("url of koji XMLRPC server"))
parser.add_option("--keytab", help=_("specify a Kerberos keytab to use"))
parser.add_option("--principal", help=_("specify a Kerberos principal to use"))
parser.add_option("--krbservice", default="host",
help=_("the service name of the principal being used by the hub"))
parser.add_option("--krb-rdns", action="store_true", default=False,
help=_("get reverse dns FQDN for krb target"))
parser.add_option("--krb-canon-host", action="store_true", default=False,
@ -88,9 +86,6 @@ def get_options():
# name, alias, type
['keytab', None, 'string'],
['principal', None, 'string'],
['krbservice', None, 'string'],
['krb_rdns', None, 'boolean'],
['krb_canon_host', None, 'boolean'],
['runas', None, 'string'],
['user', None, 'string'],
['password', None, 'string'],

View file

@ -1082,10 +1082,6 @@ def get_options():
'principal': None,
'keytab': '/etc/kojira/kojira.keytab',
'ccache': '/var/tmp/kojira.ccache',
'krbservice': 'host',
'krb_rdns': True,
'krb_canon_host': False,
'krb_server_realm': None,
'retry_interval': 60,
'max_retries': 120,
'offline_retry': True,
@ -1114,10 +1110,10 @@ def get_options():
'delete_batch_size', 'dist_repo_lifetime', 'sleeptime',
'recent_tasks_lifetime')
str_opts = ('topdir', 'server', 'user', 'password', 'logfile', 'principal', 'keytab',
'krbservice', 'cert', 'ca', 'serverca', 'debuginfo_tags', 'queue_file',
'cert', 'ca', 'serverca', 'debuginfo_tags', 'queue_file',
'source_tags', 'separate_source_tags', 'ignore_tags') # FIXME: remove ca here
bool_opts = ('verbose', 'debug', 'ignore_stray_repos', 'offline_retry',
'krb_rdns', 'krb_canon_host', 'no_ssl_verify', 'check_external_repos')
'no_ssl_verify', 'check_external_repos')
legacy_opts = ('with_src')
for name in config.options(section):
if name in int_opts:
@ -1195,8 +1191,8 @@ if __name__ == "__main__":
elif options.user:
# authenticate using user/password
session.login()
elif (koji.krbV or koji.requests_kerberos) and options.principal and options.keytab:
session.krb_login(options.principal, options.keytab, options.ccache)
elif koji.requests_kerberos and options.principal and options.keytab:
session.gssapi_login(options.principal, options.keytab, options.ccache)
else:
quit("No username/password/certificate supplied and Kerberos missing or not configured")
# get an exclusive session

View file

@ -20,12 +20,6 @@ logfile=/var/log/kojira.log
;location of the keytab
;keytab = /etc/kojira/kojira.keytab
;the service name of the principal being used by the hub
;krbservice = host
;The realm of server principal. Using client's realm if not set
;krb_server_realm = EXAMPLE.COM
;configuration for SSL authentication
;client certificate

View file

@ -57,11 +57,6 @@ from koji.tasks import ( # noqa: F401
ServerRestart
)
try:
import krbV
except ImportError: # pragma: no cover
krbV = None
# Register libvirt handler
def libvirt_callback(ignore, err):
@ -135,10 +130,6 @@ def get_options():
'host_principal_format': 'compile/%s@EXAMPLE.COM',
'keytab': '/etc/kojivmd/kojivmd.keytab',
'ccache': '/var/tmp/kojivmd.ccache',
'krbservice': 'host',
'krb_rdns': True,
'krb_canon_host': False,
'krb_server_realm': None,
'server': None,
'user': None,
'password': None,
@ -160,8 +151,7 @@ def get_options():
defaults[name] = int(value)
except ValueError:
quit("value for %s option must be a valid integer" % name)
elif name in ['offline_retry', 'krb_rdns', 'krb_canon_host',
'no_ssl_verify']:
elif name in ['offline_retry', 'no_ssl_verify']:
defaults[name] = config.getboolean('kojivmd', name)
elif name in ['plugin', 'plugins']:
defaults['plugin'] = value.split()
@ -1156,20 +1146,13 @@ if __name__ == "__main__":
quit("Error: Unable to log in. Bad credentials?")
except requests.exceptions.ConnectionError:
quit("Error: Unable to connect to server %s" % (options.server))
elif krbV:
else:
krb_principal = options.krb_principal
if krb_principal is None:
krb_principal = options.host_principal_format % socket.getfqdn()
try:
session.krb_login(principal=krb_principal,
keytab=options.keytab,
ccache=options.ccache)
except krbV.Krb5Error as e:
quit("Kerberos authentication failed: '%s' (%s)" % (e.args[1], e.args[0]))
except socket.error as e:
quit("Could not connect to Kerberos authentication service: '%s'" % e.args[1])
else:
quit("No username/password supplied and Kerberos missing or not configured")
session.gssapi_login(principal=krb_principal,
keytab=options.keytab,
ccache=options.ccache)
# make session exclusive
try:
session.exclusiveSession(force=options.force_lock)

View file

@ -42,12 +42,6 @@ from_addr=Koji Build System <buildsys@example.com>
;location of the keytab
;keytab = /etc/kojivmd/kojivmd.keytab
;the service name of the principal being used by the hub
;krbservice = host
;The realm of server principal. Using client's realm if not set
;krb_server_realm = EXAMPLE.COM
;configuration for SSL authentication
;client certificate

View file

@ -118,13 +118,13 @@ def _getUserCookie(environ):
return user
def _krbLogin(environ, session, principal):
def _gssapiLogin(environ, session, principal):
options = environ['koji.options']
wprinc = options['WebPrincipal']
keytab = options['WebKeytab']
ccache = options['WebCCache']
return session.krb_login(principal=wprinc, keytab=keytab,
ccache=ccache, proxyuser=principal)
return session.gssapi_login(principal=wprinc, keytab=keytab,
ccache=ccache, proxyuser=principal)
def _sslLogin(environ, session, username):
@ -146,7 +146,7 @@ def _assertLogin(environ):
if not _sslLogin(environ, session, environ['koji.currentLogin']):
raise koji.AuthError('could not login %s via SSL' % environ['koji.currentLogin'])
elif options['WebPrincipal']:
if not _krbLogin(environ, environ['koji.session'], environ['koji.currentLogin']):
if not _gssapiLogin(environ, environ['koji.session'], environ['koji.currentLogin']):
raise koji.AuthError(
'could not login using principal: %s' % environ['koji.currentLogin'])
else:
@ -174,12 +174,7 @@ def _assertLogin(environ):
def _getServer(environ):
opts = environ['koji.options']
s_opts = {'krbservice': opts['KrbService'],
'krb_rdns': opts['KrbRDNS'],
'krb_canon_host': opts['KrbCanonHost'],
'krb_server_realm': opts['KrbServerRealm']
}
session = koji.ClientSession(opts['KojiHubURL'], opts=s_opts)
session = koji.ClientSession(opts['KojiHubURL'])
environ['koji.currentLogin'] = _getUserCookie(environ)
if environ['koji.currentLogin']:
@ -273,7 +268,7 @@ def login(environ, page=None):
'configuration error: mod_auth_gssapi should have performed authentication before '
'presenting this page')
if not _krbLogin(environ, session, principal):
if not _gssapiLogin(environ, session, principal):
raise koji.AuthError('could not login using principal: %s' % principal)
username = principal