Loading capif_backend/backoffice_service/utils/vault.py +26 −8 Changes for capif_backend/backoffice_service/utils/vault.py: 26 added lines, 8 removed lines. Original line number Diff line number Diff line Loading @@ -138,10 +138,20 @@ def read_provider(user_uuid, prov_dom_id): except (ValueError, KeyError, TypeError) as e: raise VaultError(f"Unexpected Vault response shape for provider {prov_dom_id}") from e def list_invokers(user_uuid): """Return the apiInvokerIds stored for a user.""" _ENTITY_KINDS = ("invokers", "providers") def _list_entities(user_uuid, kind): """Return the ids stored under the user's `kind` folder (possibly an empty list). `kind` must be one of the hardcoded _ENTITY_KINDS, never a value from the request: it becomes part of the Vault path and is not checked by _ENTITY_ID_RE. The uuid comes from the JWT. Raises VaultError on any failure other than "nothing there". KV v2 only lists under `metadata` (not `data`); Vault's LIST verb is sent as GET ?list=true. """ if kind not in _ENTITY_KINDS: raise ValueError(f"Unknown entity kind: {kind}") path = f"secret/metadata/backoffice/users/{user_uuid}/invokers" path = f"secret/metadata/backoffice/users/{user_uuid}/{kind}" try: response = requests.get( f"{vault_addr()}/v1/{path}", Loading @@ -151,18 +161,26 @@ def list_invokers(user_uuid): timeout=10, ) except requests.exceptions.RequestException as e: raise VaultError(f"Vault list of invokers failed: {e}") from e raise VaultError(f"Vault list of {kind} failed: {e}") from e # Vault returns 404 when the path has no keys: this user has no invokers yet. # Vault answers 404 when the path has no keys: this user has none yet. if response.status_code == 404: return [] if not response.ok: raise VaultError(f"Vault list of invokers failed: {response.status_code}") raise VaultError(f"Vault list of {kind} failed: {response.status_code}") try: keys = response.json()["data"]["keys"] except (ValueError, KeyError, TypeError) as e: raise VaultError("Unexpected Vault list response shape") from e raise VaultError(f"Unexpected Vault list response shape for {kind}") from e # Keys ending in "/" would be sub-folders, not invokers # Keys ending in "/" would be sub-folders, not entities; we never create them, but skip them defensively. return [key for key in keys if not key.endswith("/")] def list_invokers(user_uuid): """Return the apiInvokerIds stored for a user (possibly an empty list).""" return _list_entities(user_uuid, "invokers") def list_providers(user_uuid): """Return the apiProvDomIds stored for a user (possibly an empty list).""" return _list_entities(user_uuid, "providers") Loading
capif_backend/backoffice_service/utils/vault.py +26 −8 Changes for capif_backend/backoffice_service/utils/vault.py: 26 added lines, 8 removed lines. Original line number Diff line number Diff line Loading @@ -138,10 +138,20 @@ def read_provider(user_uuid, prov_dom_id): except (ValueError, KeyError, TypeError) as e: raise VaultError(f"Unexpected Vault response shape for provider {prov_dom_id}") from e def list_invokers(user_uuid): """Return the apiInvokerIds stored for a user.""" _ENTITY_KINDS = ("invokers", "providers") def _list_entities(user_uuid, kind): """Return the ids stored under the user's `kind` folder (possibly an empty list). `kind` must be one of the hardcoded _ENTITY_KINDS, never a value from the request: it becomes part of the Vault path and is not checked by _ENTITY_ID_RE. The uuid comes from the JWT. Raises VaultError on any failure other than "nothing there". KV v2 only lists under `metadata` (not `data`); Vault's LIST verb is sent as GET ?list=true. """ if kind not in _ENTITY_KINDS: raise ValueError(f"Unknown entity kind: {kind}") path = f"secret/metadata/backoffice/users/{user_uuid}/invokers" path = f"secret/metadata/backoffice/users/{user_uuid}/{kind}" try: response = requests.get( f"{vault_addr()}/v1/{path}", Loading @@ -151,18 +161,26 @@ def list_invokers(user_uuid): timeout=10, ) except requests.exceptions.RequestException as e: raise VaultError(f"Vault list of invokers failed: {e}") from e raise VaultError(f"Vault list of {kind} failed: {e}") from e # Vault returns 404 when the path has no keys: this user has no invokers yet. # Vault answers 404 when the path has no keys: this user has none yet. if response.status_code == 404: return [] if not response.ok: raise VaultError(f"Vault list of invokers failed: {response.status_code}") raise VaultError(f"Vault list of {kind} failed: {response.status_code}") try: keys = response.json()["data"]["keys"] except (ValueError, KeyError, TypeError) as e: raise VaultError("Unexpected Vault list response shape") from e raise VaultError(f"Unexpected Vault list response shape for {kind}") from e # Keys ending in "/" would be sub-folders, not invokers # Keys ending in "/" would be sub-folders, not entities; we never create them, but skip them defensively. return [key for key in keys if not key.endswith("/")] def list_invokers(user_uuid): """Return the apiInvokerIds stored for a user (possibly an empty list).""" return _list_entities(user_uuid, "invokers") def list_providers(user_uuid): """Return the apiProvDomIds stored for a user (possibly an empty list).""" return _list_entities(user_uuid, "providers")