#2550 Allow kojiweb to proxy users obtained via different mechanisms
Closed 3 years ago by tkopecek. Opened 4 years ago by electronghost.
electronghost/koji kojiweb_mixed_auth  into  master

file modified
+8
@@ -19,6 +19,14 @@ 

  # WebCert = /etc/kojiweb/kojiweb.crt

  # KojiHubCA = /etc/kojiweb/kojihubca.crt

  

+ # How the users authenticate to kojiweb, if different from the

+ # 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

+ 

  LoginTimeout = 72

  

  # This must be CHANGED to random value and uncommented before deployment

file modified
+42 -11
@@ -271,8 +271,24 @@ 

      session = _getServer(environ)

      options = environ['koji.options']

  

-     # try SSL first, fall back to Kerberos

-     if options['WebCert']:

+     # 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':

+         ## Clients authenticate to KojiWeb by SSL, so extract

+         ## the username via the (verified) client certificate

          if environ['wsgi.url_scheme'] != 'https':

              dest = 'login'

              if page:
@@ -288,22 +304,37 @@ 

          if not username:

              raise koji.AuthError('unable to get user information from client certificate')

  

-         if not _sslLogin(environ, session, username):

-             raise koji.AuthError('could not login %s using SSL certificates' % username)

- 

-         authlogger.info('Successful SSL authentication by %s', username)

- 

-     elif options['WebPrincipal']:

+     elif webauth == 'kerberos':

+         ## Clients authenticate to KojiWeb by Kerberos, so extract

+         ## the username via the REMOTE_USER which will be the

+         ## Kerberos principal

          principal = environ.get('REMOTE_USER')

          if not principal:

              raise koji.AuthError(

                  'configuration error: mod_auth_gssapi should have performed authentication before '

                  'presenting this page')

  

-         if not _gssapiLogin(environ, session, principal):

-             raise koji.AuthError('could not login using principal: %s' % principal)

- 

          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)

+ 

+         authlogger.info('Successful SSL authentication by %s', username)

+     elif options['WebPrincipal']:

+         if not _gssapiLogin(environ, session, username):

+             raise koji.AuthError('could not login using principal: %s' % username)

+ 

          authlogger.info('Successful Kerberos authentication by %s', username)

      else:

          raise koji.AuthError(

@@ -78,6 +78,8 @@ 

          ['KrbCanonHost', 'boolean', False],

          ['KrbServerRealm', 'string', None],

  

+         ['WebAuth', 'string', None],

+ 

          ['WebCert', 'string', None],

          ['KojiHubCA', 'string', '/etc/kojiweb/kojihubca.crt'],

  

This allows for users authenticated to the Koji Web interface via
Kerberos to be proxied to the HUB using an SSL certificate and
(in theory) vice versa though it's not clear why you'd want that.

This is useful in environments where the owners of the Kerberos
realm are not willing to create service accounts and export
keytabs for them.

Set WebAuth = kerberos to indicate that users are authenticated
to the web via Kerberos. The existing config controls how kojiweb
authenticates to the HUB.

If using this, it is recommended to set

LoginCreatesUser = Off

in hub.conf, to avoid accidental creation of Koji accounts for
users of the wider Kerberos realm.

I have working mixed authentication to the hub if anyone's interested in the config fragment.

My use-case involves Kerberos authentication for humans (Active Directory) but SSL certificates for all koji "service" users because the owners of the A/D domain do not like service accounts.

rebased onto 85aa5357223d4be68f3efd14d82b767281f78f78

4 years ago

rebased onto 6618be8c37b1b4624eae7a821794e614db0e576b

4 years ago

Reading through this, it's too bad we have to add another configuration option here. It would be great if Kojiweb could simply do the "right thing" based on whatever WSGI env vars are set for the HTTP request.

...I don't mean to block the inclusion of this feature here. Thanks for submitting this!

I'm not sure the right information is available. There have always been 2 authentications happening here; the user authenticates to Kojiweb, and the Kojiweb authenticates to the hub as a special user who is allowed to pretend to be other users.

The existing behaviour assumes looks at how the user auth'd to Kojiweb and assumes that the same mechanism will be used to auth to the hub (with a different user), so I'm trying to preserve that unless otherwise specified.

Given that it's authentication, I'd be nervous of too much implicit behaviour; I'd rather the admin specified exactly what they want to happen.

(Though to be fair, I'm struggling to think of a situation where you'd want to use client certificates to Kojiweb and Kerberos to the hub...)

The desired behavior here is reasonable.

I'm wondering about the possibility of subtle security impacts.

This is mostly just deferring the calls to _sslLogin or _gssapiLogin until a little later and of course allowing the possibility of mismatched auth methods. The stripping of the realm in the WebCert case is new.

I'm not sure how well this stripping is going to interact with the user_krb_principals table. In the krb auth case, the hub looks up the user from the user_krb_principals table.

You point out that this should be used with LoginCreatesUser = Off, and this is particularly true in the case where users authenticate with kerberos and the web ui authenticates with ssl. Users will be created without their principal set

I'm not sure how well this stripping is going to interact with the user_krb_principals table. In the krb auth case, the hub looks up the user from the user_krb_principals table

The stripping is only done in the case where we are using _sslLogin() to proxy the user to the hub, because in that case the user is looked up using fred instead of fred@KERBEROS.REALM.

When developing this I initially did not have the stripping of the realm, and also neglected to set LoginCreatesUser = Off and ended up with a bunch of auto-created users called <user>@KERBEROS.REALM. Which was annoying...

The path where kojiweb proxies the users to the hub by means of its own keytab'd principal should remain unaffected.

rebased onto b1d29de

4 years ago

Metadata Update from @tkopecek:
- Pull-request tagged with: testing-ready

4 years ago

As my understanding, this PR will

  1. strip the @REALM part when WebCert is defined
  2. add a new option WebAuth to determine where to get username/principal from env (it actually doesn't determine the call sslLogin, or gssapiLogin)

I think only the 1. part helps on the original issue?

This allows for users authenticated to the Koji Web interface via
Kerberos to be proxied to the HUB using an SSL certificate

On Thursday, 15 April 2021 14:33:55 BST Yuming Zhu wrote:

julian8628 commented on the pull-request: Allow kojiweb to proxy users obtained via different mechanisms that you are following: ``
As my understanding, this PR will

  1. strip the @REALM part when WebCert is defined
  2. add a new option WebAuth to determine where to get username/principal
    from env (it actually doesn't determine the call sslLogin, or
    gssapiLogin)

I think only the 1. part helps on the original issue?

We already know how Kojiweb will authenticate to the hub. What we need is a
way to declare how the users authenticate to Kojiweb, preferably explicitly
rather than inferring it. This configuration lets us know where we should be
looking for the username, as looking in the wrong place could open an attack
vector, should someone find a way of filling in the first place it looks when the
site setup was expecting the second.

Without modification, kojiweb will attempt to detect which method was used to
authenticate to the web interface by seeing which variables are set, and then
use the same method to authenticate to the hub. With this modification, it uses
the configured hub authentication method to determine how to authenticate to
the hub, and WebAuth to determine how to find the username. It then strips the
realm when using sslLogin because sslLogin does not handle the presence of
@REALM whereas gssapiLogin does.

The code does in fact work - I have been running it for some while.

If you want to use Kerberos to authenticate to the web interface at present,
you need a Kerberos principal to proxy the username+realm to koji. This
requires that a "special" Kerberos principal exist for the special user, with
a keytab extracted to the system running kojiweb. In sites where Kerberos is
handled by Active Directory, those managing the realm often flat-out refuse to
issue a keytab for what they call a service account, meaning you either have
to manage issuing certificates for all your users or give up on authentication
to the web interface, which is a bit of a shame.

--
Tim Smith tim@electronghost.co.uk
All rumours on this list are true, except this one.

Thanks for the explanation

We already know how Kojiweb will authenticate to the hub. What we need is a
way to declare how the users authenticate to Kojiweb, preferably explicitly
rather than inferring it. This configuration lets us know where we should be
looking for the username, as looking in the wrong place could open an attack
vector, should someone find a way of filling in the first place it looks when the
site setup was expecting the second.

Not sure if it is possible, but it makes sense.

This part will lead webauth == 'kerberos', when WebAuth is not set, and WebCert and WebPrincipal are both configured. After that, web will call _sslLogin.

The old code doesn't behave like that. Could you change the order?

Anyway, it is a really rare case :-)

On Thursday, 15 April 2021 22:37:31 BST Yuming Zhu wrote:

julian8628 commented on the pull-request: Allow kojiweb to proxy users obtained via different mechanisms that you are following: ` This part will leadwebauth == 'kerberos', whenWebAuthis not set, andWebCertandWebPrincipalare both configured. After that, web will call_sslLogin`.

The old code doesn't behave like that. Could you change the order?
``

Sure. I hope nobody sets both as that'd be kind of confusing. I must admit I
haven't chased through the hub code to discover if both ProxyDNs and
ProxyPrincipals can work on the same hub.

--
Tim Smith tim@electronghost.co.uk
Rebel Security foils unauthorised cloning attempt on General Madine. 'I'm
beside myself,' says General.

1 new commit added

  • Reverse check order between WebCert and WebPrincipal in case both are set
4 years ago

Metadata Update from @tkopecek:
- Pull-request untagged with: testing-ready
- Pull-request tagged with: no_qe

4 years ago

I still have issues with simple stripping the realm in the web code. We need to be sure that the hub is going to do the right thing here. Simply telling people to disable LoginCreatesUser is not really enough when the result of not doing so could be incorrect user entries that need to be manually fixed.

The hub auth code has logic for dealing with krb usernames. I think we need to find a way for that code to be used in the case where a proxy user with ssl authtype is authenticating a user with kerberos credentials.

My initial inclination is to extend the sslLogin code in auth.py a little to allow the proxy to indicate the original authtype. The code could then follow the correct logic for processing the user value. However, that my make things complicated when the web is logging in based on a user cookie (in _assertLogin).

An alternate approach is to simply alter sslLogin to treat any username containing '@' as a kerberos principal.

An alternate approach is to simply alter sslLogin to treat any username containing '@' as a kerberos principal.

My pedantic side is slightly concerned about this because hypothetically the actual username could contain an @. I'd say it's foolish set up such a user, but we don't explicitly enforce it.

Also, after looking through this again it strikes me that the new web option should be named more specifically, e.g. WebAuthtype (WebAuthType?).

Metadata Update from @tkopecek:
- Pull-request untagged with: no_qe

3 years ago

I've extended it a bit in #3008 for further discussion.

Pull-Request has been closed by tkopecek

3 years ago