Implement GSSAPI login
Signed-off-by: Patrick Uiterwijk <puiterwijk@redhat.com>
This commit is contained in:
parent
06f8d24967
commit
480cdfb540
4 changed files with 64 additions and 13 deletions
2
cli/koji
2
cli/koji
|
|
@ -6968,6 +6968,8 @@ def handle_moshimoshi(options, session, args):
|
|||
authtype = u.get('authtype', getattr(session, 'authtype', None))
|
||||
if authtype == koji.AUTHTYPE_NORMAL:
|
||||
print "Authenticated via password"
|
||||
elif authtype == koji.AUTHTYPE_GSSAPI:
|
||||
print "Authenticated via GSSAPI"
|
||||
elif authtype == koji.AUTHTYPE_KERB:
|
||||
print "Authenticated via Kerberos principal %s" % u["krb_principal"]
|
||||
elif authtype == koji.AUTHTYPE_SSL:
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ Requires: python-krbV >= 1.0.13
|
|||
Requires: rpm-python
|
||||
Requires: pyOpenSSL
|
||||
Requires: python-requests
|
||||
Requires: python-requests-kerberos
|
||||
Requires: python-urlgrabber
|
||||
Requires: python-dateutil
|
||||
BuildRequires: python
|
||||
|
|
|
|||
|
|
@ -57,6 +57,10 @@ try:
|
|||
import requests
|
||||
except ImportError: #pragma: no cover
|
||||
requests = None
|
||||
try:
|
||||
from requests_kerberos import HTTPKerberosAuth
|
||||
except ImportError: #pragma: no cover
|
||||
HTTPKerberosAuth = None
|
||||
import rpm
|
||||
import shutil
|
||||
import signal
|
||||
|
|
@ -192,6 +196,7 @@ USER_STATUS = Enum((
|
|||
AUTHTYPE_NORMAL = 0
|
||||
AUTHTYPE_KERB = 1
|
||||
AUTHTYPE_SSL = 2
|
||||
AUTHTYPE_GSSAPI = 3
|
||||
|
||||
#dependency types
|
||||
DEP_REQUIRE = 0
|
||||
|
|
@ -2017,6 +2022,14 @@ class ClientSession(object):
|
|||
principal. The principal must be in the "ProxyPrincipals" list on
|
||||
the server side."""
|
||||
|
||||
if principal is None and keytab is None and ccache is None:
|
||||
try:
|
||||
# Silently try GSSAPI first
|
||||
if self.gssapi_login(proxyuser=proxyuser):
|
||||
return True
|
||||
except:
|
||||
pass
|
||||
|
||||
if not krbV:
|
||||
raise exceptions.ImportError(
|
||||
"Please install python-krbV to use kerberos."
|
||||
|
|
@ -2094,6 +2107,37 @@ class ClientSession(object):
|
|||
|
||||
return '%s/%s@%s' % (service, servername, realm)
|
||||
|
||||
def gssapi_login(self, proxyuser=None):
|
||||
if not HTTPKerberosAuth:
|
||||
raise exceptions.ImportError(
|
||||
"Please install python-requests-kerberos to use GSSAPI."
|
||||
)
|
||||
|
||||
# force https
|
||||
uri = urlparse.urlsplit(self.baseurl)
|
||||
if uri[0] != 'https':
|
||||
self.baseurl = 'https://%s%s' % (uri[1], uri[2])
|
||||
|
||||
# Force a new session
|
||||
self.new_session()
|
||||
|
||||
# 60 second timeout during login
|
||||
old_opts = self.opts
|
||||
self.opts = old_opts.copy()
|
||||
self.opts['timeout'] = 60
|
||||
self.opts['auth'] = HTTPKerberosAuth()
|
||||
try:
|
||||
sinfo = self.callMethod('sslLogin', proxyuser)
|
||||
finally:
|
||||
self.opts = old_opts
|
||||
if not sinfo:
|
||||
raise AuthError, 'unable to obtain a session'
|
||||
|
||||
self.setSession(sinfo)
|
||||
|
||||
self.authtype = AUTHTYPE_GSSAPI
|
||||
return True
|
||||
|
||||
def ssl_login(self, cert=None, ca=None, serverca=None, proxyuser=None):
|
||||
cert = cert or self.opts.get('cert')
|
||||
serverca = serverca or self.opts.get('serverca')
|
||||
|
|
@ -2222,6 +2266,9 @@ class ClientSession(object):
|
|||
if cert:
|
||||
# TODO: we really only need to do this for ssllogin calls
|
||||
callopts['cert'] = cert
|
||||
auth = self.opts.get('auth')
|
||||
if auth:
|
||||
callopts['auth'] = auth
|
||||
timeout = self.opts.get('timeout')
|
||||
if timeout:
|
||||
callopts['timeout'] = timeout
|
||||
|
|
|
|||
27
koji/auth.py
27
koji/auth.py
|
|
@ -374,27 +374,28 @@ class Session(object):
|
|||
if self.logged_in:
|
||||
raise koji.AuthError, "Already logged in"
|
||||
|
||||
if context.environ['wsgi.url_scheme'] != 'https':
|
||||
raise koji.AuthError, 'cannot call sslLogin() via a non-https connection: %s' % context.environ['wsgi.url_scheme']
|
||||
if context.environ.get('REMOTE_USER'):
|
||||
username = context.environ.get('REMOTE_USER')
|
||||
client_dn = username
|
||||
authtype = koji.AUTHTYPE_GSSAPI
|
||||
else:
|
||||
if context.environ.get('SSL_CLIENT_VERIFY') != 'SUCCESS':
|
||||
raise koji.AuthError, 'could not verify client: %s' % context.environ.get('SSL_CLIENT_VERIFY')
|
||||
|
||||
if context.environ.get('SSL_CLIENT_VERIFY') != 'SUCCESS':
|
||||
raise koji.AuthError, 'could not verify client: %s' % context.environ.get('SSL_CLIENT_VERIFY')
|
||||
|
||||
name_dn_component = context.opts.get('DNUsernameComponent', 'CN')
|
||||
client_name = context.environ.get('SSL_CLIENT_S_DN_%s' % name_dn_component)
|
||||
if not client_name:
|
||||
raise koji.AuthError, 'unable to get user information (%s) from client certificate' % name_dn_component
|
||||
name_dn_component = context.opts.get('DNUsernameComponent', 'CN')
|
||||
username = context.environ.get('SSL_CLIENT_S_DN_%s' % name_dn_component)
|
||||
if not username:
|
||||
raise koji.AuthError, 'unable to get user information (%s) from client certificate' % name_dn_component
|
||||
client_dn = context.environ.get('SSL_CLIENT_S_DN')
|
||||
authtype = koji.AUTHTYPE_SSL
|
||||
|
||||
if proxyuser:
|
||||
client_dn = context.environ.get('SSL_CLIENT_S_DN')
|
||||
proxy_dns = [dn.strip() for dn in context.opts.get('ProxyDNs', '').split('|')]
|
||||
if client_dn in proxy_dns:
|
||||
# the SSL-authenticated user authorized to login other users
|
||||
username = proxyuser
|
||||
else:
|
||||
raise koji.AuthError, '%s is not authorized to login other users' % client_dn
|
||||
else:
|
||||
username = client_name
|
||||
|
||||
cursor = context.cnx.cursor()
|
||||
query = """SELECT id FROM users
|
||||
|
|
@ -416,7 +417,7 @@ class Session(object):
|
|||
if hostip == '127.0.0.1':
|
||||
hostip = socket.gethostbyname(socket.gethostname())
|
||||
|
||||
sinfo = self.createSession(user_id, hostip, koji.AUTHTYPE_SSL)
|
||||
sinfo = self.createSession(user_id, hostip, authtype)
|
||||
return sinfo
|
||||
|
||||
def makeExclusive(self, force=False):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue