From 48cc3541e12676a2005a8bd5660757e025402e39 Mon Sep 17 00:00:00 2001 From: Russ Allbery Date: Fri, 14 Oct 2022 10:07:15 -0700 Subject: [PATCH] Only pass groups with GIDs to moneypenny moneypenny doesn't support groups without GIDs in its model, so it was failing with the new support for groups from OIDC claims that have no GIDs (such as at IN2P3-CC). Only pass groups with GIDs to moneypenny since it doesn't do anything with the ones without GIDs anyway. This will be fixed properly by the new lab controller. Note that the provisioning flow also doesn't support the user's GID properly and instead assumes that their primary GID matches their UID. This is not fixed in this commit since it should be addressed by the lab controller, which is hopefully coming soon enough that it doesn't need to be fixed here (which would require changes to the moneypenny model and its provisioning Docker image). --- src/nublado2/provisioner.py | 7 ++++++- tests/provisioner_test.py | 23 +++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/nublado2/provisioner.py b/src/nublado2/provisioner.py index 9f769f4..3398a8a 100644 --- a/src/nublado2/provisioner.py +++ b/src/nublado2/provisioner.py @@ -34,11 +34,16 @@ async def provision_homedir(self, spawner: Spawner) -> None: base_url = self.nublado_config.base_url token = self.nublado_config.gafaelfawr_token + # Only include groups with GIDs. Provisioning can't do anything with + # the ones that don't have GIDs, and currently the model doesn't allow + # them. + groups = [g for g in auth_state["groups"] if "id" in g] + # Start the provisioning request. dossier = { "username": spawner.user.name, "uid": int(auth_state["uid"]), - "groups": auth_state["groups"], + "groups": groups, } provision_url = urljoin(base_url, "moneypenny/users") session = await get_session() diff --git a/tests/provisioner_test.py b/tests/provisioner_test.py index d1997c5..a8f544e 100644 --- a/tests/provisioner_test.py +++ b/tests/provisioner_test.py @@ -85,3 +85,26 @@ async def test_provision() -> None: m.get(status_url, callback=handler, repeat=True) m.get(wait_url, callback=handler) await resource_manager.provisioner.provision_homedir(spawner) + + +@pytest.mark.asyncio +async def test_no_gids() -> None: + resource_manager = ResourceManager() + spawner = Mock(spec=Spawner) + spawner.user = Mock(spec=User) + spawner.user.name = "someuser" + auth_state = { + "uid": 1234, + "groups": [{"name": "foo"}], + } + spawner.user.get_auth_state.return_value = auth_state + + commission_url = "https://data.example.com/moneypenny/users" + status_url = "https://data.example.com/moneypenny/users/someuser" + wait_url = "https://data.example.com/moneypenny/users/someuser/wait" + with aioresponses() as m: + handler = build_handler("someuser", 1234, []) + m.post(commission_url, callback=handler) + m.get(status_url, callback=handler, repeat=True) + m.get(wait_url, callback=handler) + await resource_manager.provisioner.provision_homedir(spawner)