From 4a3dc401470e18cca90cadd2dc3796fce5c21212 Mon Sep 17 00:00:00 2001
From: Yu Ming Zhu <yzhu@redhat.com>
Date: Oct 10 2019 13:01:24 +0000
Subject: [PATCH 1/7] use GSS_NAME instead of REMOTE_USER for GSSAPI auth


jira: https://projects.engineering.redhat.com/browse/BST-475

---

diff --git a/hub/hub.conf b/hub/hub.conf
index 452d023..cc096e9 100644
--- a/hub/hub.conf
+++ b/hub/hub.conf
@@ -25,6 +25,8 @@ KojiDir = /mnt/koji
 ## Allowed Kerberos Realms separated by ','.
 ## Default value "*" indicates any Realm is allowed
 # AllowedKrbRealms = *
+## default realm to support multiple realms
+# DefaultRealm = EXAMPLE.COM
 
 ## end Kerberos auth configuration
 
diff --git a/hub/kojixmlrpc.py b/hub/kojixmlrpc.py
index 9f2dd3c..026dc99 100644
--- a/hub/kojixmlrpc.py
+++ b/hub/kojixmlrpc.py
@@ -422,6 +422,7 @@ def load_config(environ):
         ['ProxyPrincipals', 'string', ''],
         ['HostPrincipalFormat', 'string', None],
         ['AllowedKrbRealms', 'string', '*'],
+        ['DefaultRealm', 'string', None],
 
         ['DNUsernameComponent', 'string', 'CN'],
         ['ProxyDNs', 'string', ''],
diff --git a/koji/auth.py b/koji/auth.py
index d281319..4d844af 100644
--- a/koji/auth.py
+++ b/koji/auth.py
@@ -398,8 +398,21 @@ class Session(object):
         if self.logged_in:
             raise koji.AuthError("Already logged in")
 
-        if context.environ.get('REMOTE_USER'):
-            username = context.environ.get('REMOTE_USER')
+        # we use GSS_NAME(krb_principal) to identify user
+        if context.environ.get('GSS_NAME'):
+            # it is kerberos principal rather than user's name.
+            username = context.environ.get('GSS_NAME')
+            # to support multipal realms, replace realm part with the default one.
+            atidx = username.find('@')
+            if atidx == -1:
+                raise koji.AuthError(
+                    'invalid Kerberos principal: %s' % username)
+            default_realm = context.opts.get('DefaultRealm')
+            if not default_realm:
+                raise koji.ConfigurationError(
+                    'DefaultRealm is not specified. Please contact the'
+                    ' administrator.')
+            username = username[:atidx] + '@' + default_realm
             client_dn = username
             authtype = koji.AUTHTYPE_GSSAPI
         else:
@@ -414,17 +427,29 @@ class Session(object):
             authtype = koji.AUTHTYPE_SSL
 
         if proxyuser:
-            proxy_dns = [dn.strip() for dn in context.opts.get('ProxyDNs', '').split('|')]
+            if authtype == koji.AUTHTYPE_GSSAPI:
+                delimiter = ','
+                proxy_opt = 'ProxyPrincipals'
+            else:
+                delimiter = '|'
+                proxy_opt = 'ProxyDNs'
+            proxy_dns = [dn.strip() for dn in context.opts.get(proxy_opt, '').split(delimiter)]
             if client_dn in proxy_dns:
-                # the SSL-authenticated user authorized to login other users
+                # the user authorized to login other users
                 username = proxyuser
             else:
                 raise koji.AuthError('%s is not authorized to login other users' % client_dn)
 
-        user_id = self.getUserId(username)
+        if authtype == koji.AUTHTYPE_GSSAPI:
+            user_id = self.getUserIdFromKerberos(username)
+        else:
+            user_id = self.getUserId(username)
         if not user_id:
             if context.opts.get('LoginCreatesUser'):
-                user_id = self.createUser(username)
+                if authtype == koji.AUTHTYPE_GSSAPI:
+                    user_id = self.createUserFromKerberos(username)
+                else:
+                    user_id = self.createUser(username)
             else:
                 raise koji.AuthError('Unknown user: %s' % username)
 

From d662fb837d8f4391336f96b8c0d27695c570306e Mon Sep 17 00:00:00 2001
From: Yuming Zhu <yzhu@redhat.com>
Date: Oct 10 2019 13:02:55 +0000
Subject: [PATCH 2/7] keep on using REMOTE_USER


and handover realm translation to auth_to_local rules in /etc/krb5.conf

---

diff --git a/hub/hub.conf b/hub/hub.conf
index cc096e9..452d023 100644
--- a/hub/hub.conf
+++ b/hub/hub.conf
@@ -25,8 +25,6 @@ KojiDir = /mnt/koji
 ## Allowed Kerberos Realms separated by ','.
 ## Default value "*" indicates any Realm is allowed
 # AllowedKrbRealms = *
-## default realm to support multiple realms
-# DefaultRealm = EXAMPLE.COM
 
 ## end Kerberos auth configuration
 
diff --git a/hub/kojixmlrpc.py b/hub/kojixmlrpc.py
index 026dc99..9f2dd3c 100644
--- a/hub/kojixmlrpc.py
+++ b/hub/kojixmlrpc.py
@@ -422,7 +422,6 @@ def load_config(environ):
         ['ProxyPrincipals', 'string', ''],
         ['HostPrincipalFormat', 'string', None],
         ['AllowedKrbRealms', 'string', '*'],
-        ['DefaultRealm', 'string', None],
 
         ['DNUsernameComponent', 'string', 'CN'],
         ['ProxyDNs', 'string', ''],
diff --git a/koji/auth.py b/koji/auth.py
index 4d844af..c1cfa22 100644
--- a/koji/auth.py
+++ b/koji/auth.py
@@ -399,20 +399,9 @@ class Session(object):
             raise koji.AuthError("Already logged in")
 
         # we use GSS_NAME(krb_principal) to identify user
-        if context.environ.get('GSS_NAME'):
+        if context.environ.get('REMOTE_USER'):
             # it is kerberos principal rather than user's name.
-            username = context.environ.get('GSS_NAME')
-            # to support multipal realms, replace realm part with the default one.
-            atidx = username.find('@')
-            if atidx == -1:
-                raise koji.AuthError(
-                    'invalid Kerberos principal: %s' % username)
-            default_realm = context.opts.get('DefaultRealm')
-            if not default_realm:
-                raise koji.ConfigurationError(
-                    'DefaultRealm is not specified. Please contact the'
-                    ' administrator.')
-            username = username[:atidx] + '@' + default_realm
+            username = context.environ.get('REMOTE_USER')
             client_dn = username
             authtype = koji.AUTHTYPE_GSSAPI
         else:

From 2408e86ff69bcf51f66f49b237b136c9604e808a Mon Sep 17 00:00:00 2001
From: Yuming Zhu <yzhu@redhat.com>
Date: Oct 10 2019 13:02:55 +0000
Subject: [PATCH 3/7] in proxyuser case, do use username rather than principal


---

diff --git a/koji/auth.py b/koji/auth.py
index c1cfa22..4596a89 100644
--- a/koji/auth.py
+++ b/koji/auth.py
@@ -429,13 +429,13 @@ class Session(object):
             else:
                 raise koji.AuthError('%s is not authorized to login other users' % client_dn)
 
-        if authtype == koji.AUTHTYPE_GSSAPI:
+        if authtype == koji.AUTHTYPE_GSSAPI and '@' in username:
             user_id = self.getUserIdFromKerberos(username)
         else:
             user_id = self.getUserId(username)
         if not user_id:
             if context.opts.get('LoginCreatesUser'):
-                if authtype == koji.AUTHTYPE_GSSAPI:
+                if authtype == koji.AUTHTYPE_GSSAPI and '@' in username:
                     user_id = self.createUserFromKerberos(username)
                 else:
                     user_id = self.createUser(username)

From 3b4673879bb4ea09de0dd25aa3754a4a6df493be Mon Sep 17 00:00:00 2001
From: Yu Ming Zhu <yzhu@redhat.com>
Date: Oct 10 2019 13:02:55 +0000
Subject: [PATCH 4/7] fix typo


---

diff --git a/koji/auth.py b/koji/auth.py
index 4596a89..8ffa329 100644
--- a/koji/auth.py
+++ b/koji/auth.py
@@ -398,7 +398,7 @@ class Session(object):
         if self.logged_in:
             raise koji.AuthError("Already logged in")
 
-        # we use GSS_NAME(krb_principal) to identify user
+        # we use REMOTE_USER to identify user
         if context.environ.get('REMOTE_USER'):
             # it is kerberos principal rather than user's name.
             username = context.environ.get('REMOTE_USER')

From 0c4d57d958f974262851326acc198509d9821152 Mon Sep 17 00:00:00 2001
From: Yuming Zhu <yzhu@redhat.com>
Date: Oct 10 2019 13:02:55 +0000
Subject: [PATCH 5/7] adding some notes in documents


---

diff --git a/docs/source/server_howto.rst b/docs/source/server_howto.rst
index b070b94..a897959 100644
--- a/docs/source/server_howto.rst
+++ b/docs/source/server_howto.rst
@@ -588,6 +588,7 @@ Configuration Files
 * ``/etc/httpd/conf/httpd.conf``
 * ``/etc/httpd/conf.d/kojihub.conf``
 * ``/etc/httpd/conf.d/ssl.conf`` (when using ssl auth)
+* ``/etc/krb5.conf`` (when using GSSAPI auth)
 
 Install koji-hub
 ----------------
@@ -652,6 +653,24 @@ options should point to where the certificates are located on the hub.
     #  https://bugs.python.org/issue34670
     SSLProtocol TLSv1.2
 
+/etc/krb5.conf
+^^^^^^^^^^^^^^
+
+If Apache's mod_auth_gssapi is enabled on hub, ``auth_to_local`` rules should
+be configured as below.
+
+::
+
+    [realms]
+      EXAMPLE.COM = {
+        ...
+        auth_to_local = RULE:[1:$1@$0](.*@OTHER\.COM)s/@.*/@EXAMPLE.COM/
+        auth_to_local = RULE:[1:$1@$0](.*@EXAMPLE\.COM)
+        auth_to_local = RULE:[2:$1/$2@$0](.*@OTHER\.COM)s/@.*/@EXAMPLE.COM/
+        auth_to_local = RULE:[2:$1/$2@$0](.*@EXAMPLE\.COM)
+        ...
+      }
+
 /etc/koji-hub/hub.conf
 ^^^^^^^^^^^^^^^^^^^^^^
 
diff --git a/hub/httpd.conf b/hub/httpd.conf
index 8a741d7..9df9dd4 100644
--- a/hub/httpd.conf
+++ b/hub/httpd.conf
@@ -55,3 +55,13 @@ Alias /kojifiles "/mnt/koji/"
 # In this case, you will need to enable these options globally (in ssl.conf):
 # SSLVerifyClient require
 # SSLVerifyDepth  10
+
+# uncomment this to enable authentication via GSSAPI
+# <Location /kojihub/ssllogin>
+#         AuthType GSSAPI
+#         GssapiSSLonly Off
+#         GssapiLocalName On
+#         AuthName "GSSAPI Single Sign On Login"
+#         GssapiCredStore keytab:/etc/koji.keytab
+#         Require valid-user
+# </Location>

From 7b60e0e7eb7e378759398afe1b5e1e7a2c86e227 Mon Sep 17 00:00:00 2001
From: Yuming Zhu <yzhu@redhat.com>
Date: Oct 10 2019 13:04:06 +0000
Subject: [PATCH 6/7] backwards compatibility for ProxyDNs change


---

diff --git a/hub/hub.conf b/hub/hub.conf
index 452d023..ba365ed 100644
--- a/hub/hub.conf
+++ b/hub/hub.conf
@@ -25,6 +25,8 @@ KojiDir = /mnt/koji
 ## Allowed Kerberos Realms separated by ','.
 ## Default value "*" indicates any Realm is allowed
 # AllowedKrbRealms = *
+## TODO: this option should be removed in future release
+# DisableGSSAPIProxyDNFallback = False
 
 ## end Kerberos auth configuration
 
diff --git a/hub/kojixmlrpc.py b/hub/kojixmlrpc.py
index 9f2dd3c..7b91e15 100644
--- a/hub/kojixmlrpc.py
+++ b/hub/kojixmlrpc.py
@@ -422,6 +422,8 @@ def load_config(environ):
         ['ProxyPrincipals', 'string', ''],
         ['HostPrincipalFormat', 'string', None],
         ['AllowedKrbRealms', 'string', '*'],
+        # TODO: this option should be removed in future release
+        ['DisableGSSAPIProxyDNFallback', 'boolean', False],
 
         ['DNUsernameComponent', 'string', 'CN'],
         ['ProxyDNs', 'string', ''],
diff --git a/koji/auth.py b/koji/auth.py
index 8ffa329..2399698 100644
--- a/koji/auth.py
+++ b/koji/auth.py
@@ -423,6 +423,15 @@ class Session(object):
                 delimiter = '|'
                 proxy_opt = 'ProxyDNs'
             proxy_dns = [dn.strip() for dn in context.opts.get(proxy_opt, '').split(delimiter)]
+
+            # backwards compatible for GSSAPI.
+            # in old way, proxy user whitelist is ProxyDNs.
+            # TODO: this should be removed in future release
+            if authtype == koji.AUTHTYPE_GSSAPI and not context.opts.get(
+                    'DisableGSSAPIProxyDNFallback', False):
+                proxy_dns += [dn.strip() for dn in
+                              context.opts.get('ProxyDNs', '').split('|')]
+
             if client_dn in proxy_dns:
                 # the user authorized to login other users
                 username = proxyuser

From 5629ff59a02054c87df640eccbf2539eb04faed8 Mon Sep 17 00:00:00 2001
From: Yu Ming Zhu <yzhu@redhat.com>
Date: Oct 10 2019 13:04:06 +0000
Subject: [PATCH 7/7] doc: GssapiLocalName should be off


---

diff --git a/docs/source/server_howto.rst b/docs/source/server_howto.rst
index a897959..b070b94 100644
--- a/docs/source/server_howto.rst
+++ b/docs/source/server_howto.rst
@@ -588,7 +588,6 @@ Configuration Files
 * ``/etc/httpd/conf/httpd.conf``
 * ``/etc/httpd/conf.d/kojihub.conf``
 * ``/etc/httpd/conf.d/ssl.conf`` (when using ssl auth)
-* ``/etc/krb5.conf`` (when using GSSAPI auth)
 
 Install koji-hub
 ----------------
@@ -653,24 +652,6 @@ options should point to where the certificates are located on the hub.
     #  https://bugs.python.org/issue34670
     SSLProtocol TLSv1.2
 
-/etc/krb5.conf
-^^^^^^^^^^^^^^
-
-If Apache's mod_auth_gssapi is enabled on hub, ``auth_to_local`` rules should
-be configured as below.
-
-::
-
-    [realms]
-      EXAMPLE.COM = {
-        ...
-        auth_to_local = RULE:[1:$1@$0](.*@OTHER\.COM)s/@.*/@EXAMPLE.COM/
-        auth_to_local = RULE:[1:$1@$0](.*@EXAMPLE\.COM)
-        auth_to_local = RULE:[2:$1/$2@$0](.*@OTHER\.COM)s/@.*/@EXAMPLE.COM/
-        auth_to_local = RULE:[2:$1/$2@$0](.*@EXAMPLE\.COM)
-        ...
-      }
-
 /etc/koji-hub/hub.conf
 ^^^^^^^^^^^^^^^^^^^^^^
 
diff --git a/hub/httpd.conf b/hub/httpd.conf
index 9df9dd4..208a29c 100644
--- a/hub/httpd.conf
+++ b/hub/httpd.conf
@@ -60,7 +60,7 @@ Alias /kojifiles "/mnt/koji/"
 # <Location /kojihub/ssllogin>
 #         AuthType GSSAPI
 #         GssapiSSLonly Off
-#         GssapiLocalName On
+#         GssapiLocalName Off
 #         AuthName "GSSAPI Single Sign On Login"
 #         GssapiCredStore keytab:/etc/koji.keytab
 #         Require valid-user

