From 165236f50dd4b0f79e1bdb66c407f8464053e73b Mon Sep 17 00:00:00 2001
From: Thomas Achatz <thomas.achatz@crate.io>
Date: Wed, 2 Oct 2024 10:13:49 +0200
Subject: [PATCH] Fix JWT auth handlers for clusters without users

---
 CHANGES.rst                            |  2 ++
 crate/operator/cratedb.py              |  4 ++--
 crate/operator/operations.py           | 11 ++++++-----
 crate/operator/update_user_password.py |  5 ++---
 4 files changed, 12 insertions(+), 10 deletions(-)

diff --git a/CHANGES.rst b/CHANGES.rst
index 3f135acb..82622fde 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -9,6 +9,8 @@ Unreleased
 
 * Add ``minDomains`` to ``TopologySpreadConstraint`` to ensure that pods are spread across zones.
 
+* Fixed JWT auth handlers for clusters without users.
+
 2.41.1 (2024-08-30)
 -------------------
 
diff --git a/crate/operator/cratedb.py b/crate/operator/cratedb.py
index eef7b0ad..e7703397 100644
--- a/crate/operator/cratedb.py
+++ b/crate/operator/cratedb.py
@@ -104,8 +104,8 @@ async def create_user(
     if not user_exists:
         query = f"CREATE USER {username_ident} WITH (password = %s"
         params = [password]
-        if crate_version_supports_jwt(crate_version):
-            iss = cratedb["spec"].get("grandCentral", {}).get("jwkUrl")
+        iss = cratedb["spec"].get("grandCentral", {}).get("jwkUrl")
+        if crate_version_supports_jwt(crate_version) and iss:
             query += ', jwt = {"iss" = %s, "username" = %s, "aud" = %s}'
             params.extend([iss, username, name])
 
diff --git a/crate/operator/operations.py b/crate/operator/operations.py
index bed2ea55..b148a555 100644
--- a/crate/operator/operations.py
+++ b/crate/operator/operations.py
@@ -1200,9 +1200,8 @@ async def set_user_jwt(
     user_exists = bool(row[0])
 
     username_ident = quote_ident(username, cursor._impl)
-    if user_exists:
-        iss = cratedb["spec"].get("grandCentral", {}).get("jwkUrl")
-
+    iss = cratedb["spec"].get("grandCentral", {}).get("jwkUrl")
+    if user_exists and iss:
         query = (
             f"ALTER USER {username_ident} SET "
             f"""(jwt = {{"iss" = '{iss}', "username" = '{username}', """
@@ -1339,7 +1338,9 @@ async def handle(  # type: ignore
         """
         cratedb = await get_cratedb_resource(namespace, name)
         crate_version = cratedb["spec"]["cluster"]["version"]
-        if crate_version_supports_jwt(crate_version):
+        users = cratedb["spec"].get("users")
+        gc_config = cratedb["spec"].get("grandCentral", {})
+        if crate_version_supports_jwt(crate_version) and users and gc_config:
             async with GlobalApiClient() as api_client:
                 core = CoreV1Api(api_client)
                 host = await get_host(core, namespace, name)
@@ -1348,7 +1349,7 @@ async def handle(  # type: ignore
                     host, password, timeout=CONNECT_TIMEOUT
                 ) as conn:
                     async with conn.cursor() as cursor:
-                        for user_spec in cratedb["spec"].get("users"):
+                        for user_spec in users:
                             username = user_spec["name"]
 
                             await set_user_jwt(
diff --git a/crate/operator/update_user_password.py b/crate/operator/update_user_password.py
index 12190dcc..33bc69d8 100644
--- a/crate/operator/update_user_password.py
+++ b/crate/operator/update_user_password.py
@@ -104,11 +104,10 @@ async def pod_exec(cmd):
 
     async with WsApiClient() as ws_api_client:
         core_ws = CoreV1Api(ws_api_client)
-        if crate_version_supports_jwt(crate_version):
+        iss = cratedb["spec"].get("grandCentral", {}).get("jwkUrl")
+        if crate_version_supports_jwt(crate_version) and iss:
             # For users with `jwt` and `password` set, we need to reset
             # `jwt` config first to be able to update the password.
-            iss = cratedb["spec"].get("grandCentral", {}).get("jwkUrl")
-
             command_reset_user_jwt = get_curl_command(
                 {
                     "stmt": 'ALTER USER "{}" SET (jwt = NULL)'.format(username),