From b6ccafafeb0aeff492da432973d5b4593a0e8143 Mon Sep 17 00:00:00 2001 From: Tomas Kopecek Date: Tue, 31 Aug 2021 14:17:12 +0200 Subject: [PATCH] proxyauthtype for web users --- koji/auth.py | 12 ++++++++++++ www/conf/web.conf | 4 +--- www/kojiweb/index.py | 36 ++++++----------------------------- www/kojiweb/wsgi_publisher.py | 16 +++++++++++++++- 4 files changed, 34 insertions(+), 34 deletions(-) diff --git a/koji/auth.py b/koji/auth.py index a43a3102..f6345b0b 100644 --- a/koji/auth.py +++ b/koji/auth.py @@ -316,6 +316,15 @@ class Session(object): return (local_ip, local_port, remote_ip, remote_port) def sslLogin(self, proxyuser=None, proxyauthtype=None): + + """Login into brew via SSL. proxyuser name can be specified and if it is + allowed in the configuration file then connection is allowed to login as + that user. By default we assume that proxyuser is coming via same + authentication mechanism but proxyauthtype can be set to koji.AUTHTYPE_* + value for different handling. Typical case is proxying kerberos user via + web ui which itself is authenticated via SSL certificate. (See kojiweb + for usage). + """ if self.logged_in: raise koji.AuthError("Already logged in") @@ -364,6 +373,9 @@ class Session(object): # in this point we can continue with proxied user in same way as if it is not proxied if proxyauthtype is not None: + if proxyauthtype not in (koji.AUTHTYPE_GSSAPI, koji.AUTHTYPE_SSL): + raise koji.AuthError( + "Proxied authtype %s is not valid for sslLogin" % proxyauthtype) authtype = proxyauthtype if authtype == koji.AUTHTYPE_GSSAPI and '@' in username: diff --git a/www/conf/web.conf b/www/conf/web.conf index a0cde346..9f2922e1 100644 --- a/www/conf/web.conf +++ b/www/conf/web.conf @@ -25,9 +25,7 @@ KojiFilesURL = http://server.example.com/kojifiles # way Kojiweb authenticates to the hub. This can be used # to have users authenticate to kojiweb via kerberos while # still using an SSL certificate to authenticate to the hub. -# If doing that, consider also setting "LoginCreatesUser = Off" -# in the hub config. -# WebAuth = kerberos +# WebAuthType = kerberos LoginTimeout = 72 diff --git a/www/kojiweb/index.py b/www/kojiweb/index.py index 102ff9e1..4805a1b1 100644 --- a/www/kojiweb/index.py +++ b/www/kojiweb/index.py @@ -151,17 +151,18 @@ def _gssapiLogin(environ, session, principal): wprinc = options['WebPrincipal'] keytab = options['WebKeytab'] ccache = options['WebCCache'] + authtype = options['WebAuthType'] return session.gssapi_login(principal=wprinc, keytab=keytab, - ccache=ccache, proxyuser=principal) + ccache=ccache, proxyuser=principal, proxyauthtype=authtype) def _sslLogin(environ, session, username): options = environ['koji.options'] client_cert = options['WebCert'] server_ca = options['KojiHubCA'] - + authtype = options['WebAuthType'] return session.ssl_login(client_cert, None, server_ca, - proxyuser=username) + proxyuser=username, proxyauthtype=authtype) def _assertLogin(environ): @@ -272,22 +273,7 @@ def login(environ, page=None): session = _getServer(environ) options = environ['koji.options'] - # If 'WebAuth' is not set, then default it to - # match the method of authenticating to the hub. - # This matches the original behaviour - webauth = options['WebAuth'] - if not webauth: - if options['WebPrincipal']: - webauth = 'kerberos' - if options['WebCert']: - webauth = 'ssl' - - if not webauth: - raise koji.AuthError( - 'KojiWeb is incorrectly configured for authentication, contact the system ' - 'administrator') - - if webauth == 'ssl': + if options['WebAuthType'] == koji.AUTHTYPE_SSL: ## Clients authenticate to KojiWeb by SSL, so extract ## the username via the (verified) client certificate if environ['wsgi.url_scheme'] != 'https': @@ -304,8 +290,7 @@ def login(environ, page=None): username = environ.get('SSL_CLIENT_S_DN_CN') if not username: raise koji.AuthError('unable to get user information from client certificate') - - elif webauth == 'kerberos': + elif options['WebAuthType'] == koji.AUTHTYPE_GSSAPI: ## Clients authenticate to KojiWeb by Kerberos, so extract ## the username via the REMOTE_USER which will be the ## Kerberos principal @@ -316,18 +301,9 @@ def login(environ, page=None): 'presenting this page') username = principal - else: - ## It is still possible to get here if someone explicitly - ## set WebAuth to an incorrect value in the configuration file - raise koji.AuthError( - 'KojiWeb is incorrectly configured for authentication, contact the system ' - 'administrator') ## This now is how we proxy the user to the hub if options['WebCert']: - ## The username might be a principal user@REALM. Remove - ## any @REALM part here. - username = username.split('@', 1)[0] if not _sslLogin(environ, session, username): raise koji.AuthError('could not login %s using SSL certificates' % username) diff --git a/www/kojiweb/wsgi_publisher.py b/www/kojiweb/wsgi_publisher.py index e96ee48c..f703f1e2 100644 --- a/www/kojiweb/wsgi_publisher.py +++ b/www/kojiweb/wsgi_publisher.py @@ -78,7 +78,7 @@ class Dispatcher(object): ['KrbCanonHost', 'boolean', False], ['KrbServerRealm', 'string', None], - ['WebAuth', 'string', None], + ['WebAuthType', 'string', None], ['WebCert', 'string', None], ['KojiHubCA', 'string', '/etc/kojiweb/kojihubca.crt'], @@ -150,6 +150,20 @@ class Dispatcher(object): else: opts[name] = default opts['Secret'] = koji.util.HiddenValue(opts['Secret']) + + if opts['WebAuthType'] not in (None, 'gssapi', 'ssl'): + raise koji.ConfigurationError(f"Invalid value {opts['WebAuthType']} for " + "WebAuthType (ssl/gssapi)") + if opts['WebAuthType'] == 'gssapi': + opts['WebAuthType'] = koji.AUTHTYPE_GSSAPI + elif opts['WebAuthType'] == 'ssl': + opts['WebAuthType'] = koji.AUTHTYPE_SSL + # if there is no explicit request, use same authtype as web has + elif opts['WebPrincipal']: + opts['WebAuthType'] = koji.AUTHTYPE_GSSAPI + elif opts['WebCert']: + opts['WebAuthType'] = koji.AUTHTYPE_SSL + self.options = opts return opts