]> git.ipfire.org Git - pbs.git/commitdiff
hub: Require builders and users to authenticate using Kerberos
authorMichael Tremer <michael.tremer@ipfire.org>
Wed, 5 Oct 2022 14:37:41 +0000 (14:37 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Wed, 5 Oct 2022 14:39:01 +0000 (14:39 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/buildservice/builders.py
src/hub/__init__.py
src/hub/handlers.py
src/hub/jobs.py
src/hub/queue.py

index 852e827af62db11b90fef19bb0b3c358b34829e6..203ce1cb2453cd5d2dd5b7628ba812c170f29292 100644 (file)
@@ -53,23 +53,6 @@ class Builders(base.Object):
                # The Builder object and the passphrase are returned.
                return builder, passphrase
 
-       def auth(self, name, passphrase):
-               # If either name or passphrase is None, we don't check at all.
-               if None in (name, passphrase):
-                       return
-
-               # Search for the hostname in the database.
-               builder = self._get_builder("SELECT * FROM builders \
-                       WHERE name = %s AND deleted IS FALSE", name)
-
-               # If the builder was not found or the passphrase does not match,
-               # you have bad luck.
-               if not builder or not builder.validate_passphrase(passphrase):
-                       return
-
-               # Otherwise we return the Builder object.
-               return builder
-
        def get_by_id(self, builder_id):
                return self._get_builder("SELECT * FROM builders WHERE id = %s", builder_id)
 
index d8291d9d065cbc29b46c23adf0e857c0d532895b..7e66ee3db786ad46c12af2928e876517ce15b9fc 100644 (file)
@@ -41,6 +41,9 @@ class Application(tornado.web.Application):
                        # Queue
                        (r"/queue", queue.QueueHandler),
 
+                       # Test
+                       (r"/test", handlers.TestHandler),
+
                        # Uploads
                        (r"/uploads", uploads.CreateHandler),
                ], **settings)
index 82dceb7575a126bfb8b634b1fdb2b7857aac6280..0d3a944a5f5074307dec581d2342a27417401011 100644 (file)
@@ -1,6 +1,5 @@
 #!/usr/bin/python
 
-import base64
 import json
 import logging
 import tornado.web
@@ -9,9 +8,38 @@ from .. import builds
 from .. import builders
 from .. import users
 
+from ..web.auth import KerberosAuthMixin
+
 log = logging.getLogger("pakfire.hub")
 
-class BackendMixin(object):
+class AuthMixin(KerberosAuthMixin):
+       """
+               Requires a builder or user to authenticate
+       """
+       def get_current_user(self):
+               # Fetch the Kerberos ticket
+               principal = self.get_authenticated_user()
+
+               # Return nothing if we did not receive any credentials
+               if not principal:
+                       return
+
+               log.debug("Searching for principal %s..." % principal)
+
+               # Strip the realm
+               principal, delimiter, realm = principal.partition("@")
+
+               # Return any builders
+               if principal.startswith("host/"):
+                       hostname = principal.removeprefix("host/")
+
+                       return self.backend.builders.get_by_name(hostname)
+
+               # Return users
+               return self.backend.users.get_by_name(principal)
+
+
+class BackendMixin(AuthMixin):
        @property
        def backend(self):
                """
@@ -24,49 +52,7 @@ class BackendMixin(object):
                return self.backend.db
 
 
-class HTTPBasicAuthMixin(object):
-       def get_basic_auth_credentials(self):
-               """
-                       This handles HTTP Basic authentication.
-               """
-               auth_header = self.request.headers.get("Authorization", None)
-
-               # If no authentication information was provided, we stop here.
-               if not auth_header:
-                       return None, None
-
-               # No basic auth? We cannot handle that.
-               if not auth_header.startswith("Basic "):
-                       raise tornado.web.HTTPError(400, "Can only handle Basic auth.")
-
-               try:
-                       # Convert into bytes()
-                       auth_header = auth_header[6:].encode()
-
-                       # Decode base64
-                       auth_header = base64.b64decode(auth_header).decode()
-
-                       name, password = auth_header.split(":", 1)
-               except:
-                       raise tornado.web.HTTPError(400, "Authorization data was malformed")
-
-               return name, password
-
-
-class BaseHandler(BackendMixin, HTTPBasicAuthMixin, tornado.web.RequestHandler):
-       def get_current_user(self):
-               name, password = self.get_basic_auth_credentials()
-               if name is None:
-                       return
-
-               builder = self.backend.builders.auth(name, password)
-               if builder:
-                       return builder
-
-               user = self.backend.users.auth(name, password)
-               if user:
-                       return user
-
+class BaseHandler(BackendMixin, tornado.web.RequestHandler):
        @property
        def builder(self):
                if isinstance(self.current_user, builders.Builder):
@@ -109,6 +95,16 @@ class BaseHandler(BackendMixin, HTTPBasicAuthMixin, tornado.web.RequestHandler):
                        return self.backend.uploads.get_by_uuid(uuid)
 
 
+# Hello World
+
+class TestHandler(BaseHandler):
+       """
+               This handler is for checking whether authentication works, etc...
+       """
+       @tornado.web.authenticated
+       def get(self):
+               self.write("Hello, %s!\n" % self.current_user)
+
 # Builds
 
 class BuildsGetHandler(BaseHandler):
index dd41779d1d23655e01d795663df22ce9acc24cdb..79e4e8623e3d4ce57824a8581353cf686640b130 100644 (file)
@@ -23,11 +23,11 @@ import json
 import logging
 import tornado.websocket
 
-from .handlers import BackendMixin, HTTPBasicAuthMixin
+from .handlers import BackendMixin
 
 log = logging.getLogger("pakfire.hub.jobs")
 
-class BuilderHandler(BackendMixin, HTTPBasicAuthMixin, tornado.websocket.WebSocketHandler):
+class BuilderHandler(BackendMixin, tornado.websocket.WebSocketHandler):
        """
                Builders connect to this handler when they are running a build.
 
index dc166bb9544209647f8d5c1f80fb27a1b62d35f0..34deb7520955ee93b29e23a3a9a91430917e8bd6 100644 (file)
@@ -22,7 +22,7 @@
 import logging
 import tornado.websocket
 
-from .handlers import BackendMixin, HTTPBasicAuthMixin
+from .handlers import BackendMixin
 
 log = logging.getLogger("pakfire.hub.queue")
 
@@ -71,10 +71,10 @@ async def dispatch_jobs(backend):
                        # If there is no job for the builder, we might as well shut it down
                        await builder.stop()
 
-class QueueHandler(BackendMixin, HTTPBasicAuthMixin, tornado.websocket.WebSocketHandler):
+class QueueHandler(BackendMixin, tornado.websocket.WebSocketHandler):
        """
                Builders connect to this handler which will add them to a list of connections.
-               
+
                For all connections, we regularly check if we have any new build jobs, and if so,
                we will send them the job.
        """