Complete service-account credential administration

This commit is contained in:
2026-08-04 01:04:39 +02:00
parent 1409dbf94d
commit 998d47ae94
15 changed files with 1672 additions and 17 deletions
+48 -1
View File
@@ -364,6 +364,8 @@ ACCESS_DOCUMENTATION: tuple[DocumentationTopic, ...] = (
DocumentationLink(label="Groups API", href="/api/v1/admin/groups", kind="api"),
DocumentationLink(label="Roles API", href="/api/v1/admin/roles", kind="api"),
DocumentationLink(label="API keys API", href="/api/v1/admin/api-keys", kind="api"),
DocumentationLink(label="Service accounts", href="/admin?section=tenant-service-accounts", kind="runtime"),
DocumentationLink(label="Service accounts API", href="/api/v1/admin/service-accounts", kind="api"),
),
configuration_keys=("access_governance",),
metadata={
@@ -375,6 +377,7 @@ ACCESS_DOCUMENTATION: tuple[DocumentationTopic, ...] = (
"access.admin.tenant-groups",
"access.admin.tenant-roles",
"access.admin.api-keys",
"access.admin.service-accounts",
"access.credentials",
],
"route": "/admin",
@@ -443,6 +446,49 @@ ACCESS_DOCUMENTATION: tuple[DocumentationTopic, ...] = (
],
},
),
DocumentationTopic(
id="access.workflow.manage-service-account-credentials",
title="Manage service accounts and credentials",
summary="Create non-login automation principals, set a current scope ceiling, and rotate their one-time credentials without granting human login access.",
body=(
"Service accounts are tenant-owned automation principals. The account itself has no password or interactive session. Administrators first define its scope ceiling, then create one or more independently revocable credentials. "
"A credential secret is disclosed once and only its hash and prefix remain in GovOPlaN. Runtime authorization is always the intersection of the credential scopes and the service account's current ceiling, so lowering the ceiling or deactivating the account takes effect immediately. "
"Rotation creates the replacement and revokes the previous credential in one transaction. Retirement disables the backing principal and revokes every active credential. Every credential mutation requires the current service-account revision; a stale browser must reload instead of overwriting a concurrent change."
),
layer="configured",
documentation_types=("admin", "user"),
audience=("tenant_admin", "access_admin", "operator"),
order=32,
conditions=(
DocumentationCondition(
required_modules=("access",),
any_scopes=(
"access:service_account:read",
"access:service_account:write",
),
),
),
links=(
DocumentationLink(label="Service accounts", href="/admin?section=tenant-service-accounts", kind="runtime"),
DocumentationLink(label="Service accounts API", href="/api/v1/admin/service-accounts", kind="api"),
DocumentationLink(label="Credential lifecycle API", href="/api/v1/admin/service-accounts/{service_account_id}/credentials", kind="api"),
),
metadata={
"kind": "workflow",
"help_contexts": ["access.admin.service-accounts"],
"prerequisites": [
"The tenant permits API credentials.",
"You have service-account write permission and may delegate every selected scope.",
],
"steps": [
"Create a service account and define the narrowest useful scope ceiling.",
"Open the account and create a credential with an equal or narrower scope grant.",
"Record the one-time secret in an external secret manager.",
"Rotate credentials before expiry and revoke credentials that are no longer used.",
],
"verification": "The administration table shows the expected active credential count, last-use timestamp, revision, and audit events without exposing secret material.",
},
),
DocumentationTopic(
id="access.reference.external-function-role-mappings",
title="Organization function facts and access roles",
@@ -457,7 +503,7 @@ ACCESS_DOCUMENTATION: tuple[DocumentationTopic, ...] = (
layer="configured",
documentation_types=("admin", "user"),
audience=("tenant_admin", "access_admin", "operator"),
order=32,
order=33,
conditions=(
DocumentationCondition(
required_modules=("access", "organizations"),
@@ -735,6 +781,7 @@ manifest = ModuleManifest(
ViewSurface(id="access.admin.tenant-users", module_id="access", kind="section", label="Tenant users", order=40),
ViewSurface(id="access.admin.tenant-credentials", module_id="access", kind="section", label="Tenant credentials", order=70),
ViewSurface(id="access.admin.tenant-api-keys", module_id="access", kind="section", label="Tenant API keys", order=80),
ViewSurface(id="access.admin.tenant-service-accounts", module_id="access", kind="section", label="Service accounts", order=90),
ViewSurface(id="access.admin.group-credentials", module_id="access", kind="section", label="Group credentials", order=30),
ViewSurface(id="access.admin.user-credentials", module_id="access", kind="section", label="User credentials", order=30),
ViewSurface(id="access.settings.credentials", module_id="access", kind="section", label="Personal credentials", order=30),