feat(iam): provision the LLM inference roles and assert project roles
The api-gw gates /v1/* on a capability named in the access token. ZITADEL had no such role, so every inference call was 403 once the token came from ZITADEL instead of Authentik. - add llm:inference (Authentik spelling, keeps consumer manifests unchanged) and llm-inference (dash alias) to the project roles - enable projectRoleAssertion on the project, which is what puts urn:zitadel:iam:org:project:roles into the access token; without it the role list never reaches the resource server
This commit is contained in:
@@ -80,6 +80,10 @@ ROLES = {
|
||||
"sqs-writers": "SQS/Temporal queue read/write access",
|
||||
"s3-users": "S3 read access",
|
||||
"s3-writers": "S3 read/write access",
|
||||
# LLM gate for the api-gw. The colon form matches the Authentik-era
|
||||
# permission string, so consumer manifests did not change.
|
||||
"llm:inference": "LLM inference access (api-gw)",
|
||||
"llm-inference": "LLM inference access (dash alias)",
|
||||
}
|
||||
|
||||
_WEB = {"app_type_id": "OIDC_APP_TYPE_WEB", "auth_method_id": "OIDC_AUTH_METHOD_TYPE_BASIC"}
|
||||
@@ -266,13 +270,26 @@ def _api(method: str, path: str, token: str, body: dict | None = None,
|
||||
|
||||
def _ensure_project(token: str, name: str) -> str:
|
||||
code, d = _api("POST", "/management/v1/projects/_search", token, {})
|
||||
project_id = ""
|
||||
for row in d.get("result") or []:
|
||||
if row.get("name") == name:
|
||||
return row["id"]
|
||||
code, d = _api("POST", "/management/v1/projects", token, {"name": name})
|
||||
if code not in (200, 201) or not d.get("id"):
|
||||
die(f"create project {name} failed: {code} {d}")
|
||||
return d["id"]
|
||||
project_id = row["id"]
|
||||
break
|
||||
if not project_id:
|
||||
code, d = _api("POST", "/management/v1/projects", token, {"name": name})
|
||||
if code not in (200, 201) or not d.get("id"):
|
||||
die(f"create project {name} failed: {code} {d}")
|
||||
project_id = d["id"]
|
||||
|
||||
# projectRoleAssertion puts the project roles into the ACCESS token as
|
||||
# `urn:zitadel:iam:org:project:roles`. Without it the api-gw sees no
|
||||
# llm:inference role and answers 403 for every inference call, even when
|
||||
# the caller is correctly authorised in ZITADEL.
|
||||
code, d = _api("PUT", f"/management/v1/projects/{project_id}",
|
||||
token, {"name": name, "projectRoleAssertion": True})
|
||||
if code not in (200, 201):
|
||||
die(f"enable projectRoleAssertion on {name} failed: {code} {d}")
|
||||
return project_id
|
||||
|
||||
|
||||
def _ensure_roles(token: str, project_id: str, roles: dict[str, str]) -> None:
|
||||
|
||||
Reference in New Issue
Block a user