Skip to content

Users & Access

Local accounts, roles and paid admin seats, two-factor authentication, API keys, and cleaning up people who have left — including the recovery paths for when the thing you need to fix is the thing that is locked.

Tier: Free


What it does

Everyone who uses KubeManta signs in as themselves. Accounts come from one of three places: the local account you set at install, accounts an admin creates here, or accounts provisioned automatically the first time someone signs in through your identity provider.

There are two roles. A viewer can see everything the product observes and change nothing. An admin can act — restart, scale, apply, run a terminal session. Viewers are free and unlimited at every tier; admin seats are what you pay for, so the seat count only ever blocks assigning admin. Running out of seats can never log anyone out, revoke an existing admin, or interrupt an incident — it stops the promotion, and says so.

Two-factor authentication

A user with a local account can add a TOTP second factor: Two-factor auth in the account menu (top right), scan the QR code with an authenticator app, then enter one code to confirm.

If you sign in through SAML or OIDC, your identity provider handles this. Okta, Entra, Google and the rest authenticate you and enforce MFA there, so KubeManta does not ask for a second code on top — that is the point of federating identity. Turn MFA on at the provider, not here. The setup is hidden for those accounts rather than offered and ignored.

LDAP is the exception, and it is off by default. A directory sign-in checks the password against LDAP and nothing else — a simple bind does no MFA — so unless you enable it, those accounts are password-only. An admin switches it on in Admin → Auth → Allow directory users to add two-factor, and each user then chooses whether to enrol; nobody is forced, so enabling it cannot lock anyone out.

Switching it back off hides the setup from people who have not enrolled. Anyone who already confirmed a code keeps being asked for it — their authenticator still holds it, and quietly ignoring it would leave them believing they are protected when they are not. Removing one person's second factor is a deliberate action on their account, never a side effect of a switch. The enrolment is not active until that confirmation succeeds, so a mis-scanned code cannot lock you out of your own account.

TOTP is the only second factor and that is deliberate. Email, SMS and push each depend on something outside the cluster, and they fail precisely during the outage that a second factor on a break-glass login exists for.

Two behaviours are worth knowing because they occasionally surprise people. A code is single-use — a replay of the same code is refused even while it is still inside its time window, which is what makes a shoulder-surfed or phished code worthless seconds later. And the clock tolerance is one step either side (±30 seconds), so a phone whose clock has drifted by minutes will produce codes KubeManta rejects; fix the phone's time sync rather than retrying.

If someone loses their authenticator, an operator with cluster access clears it from the pod:

kubectl exec -n kubemanta-system deploy/kubemanta-agent -- \
  python3 -m app.reset_mfa --list
kubectl exec -n kubemanta-system deploy/kubemanta-agent -- \
  python3 -m app.reset_mfa --principal user:3

That is intentionally a pod-side command rather than a button: anyone who can kubectl exec into the agent already holds the database and the session signing key, so it grants nothing new — while a browser button would let a stolen admin session strip a second factor.

Recovering somebody else's account

Admin → Users → Account recovery on a local account. Two separate actions, because they are two different decisions:

Set a one-time password. You choose it and pass it on; the user must choose their own at their next sign-in, so what you typed stops working the moment they use it. Their current sessions are signed out, and the reset is recorded against you, not them.

That one-time property is the point. Setting somebody's password hands you a working credential for their account, and anything done with it would be attributed to them. Expiring it on first use bounds that window and makes it visible: either they sign in and change it, or the credential you hold stops working. The same applies to accounts you create — the password you choose is one-time.

Remove their second factor, for the lost-phone case. Removing your own requires a current code — correctly, so a stolen session cannot strip it — which makes the self-service control useless in exactly the situation that needs it. This hands over no credential, only removes a factor, and is recorded as its own event.

An account that signs in through an identity provider has no password here to reset, and says so rather than appearing to work.

If nobody can sign in at all, recovery is pod-side — see Locked out of everything below.

Changing your own password

Change password in the account menu (top right). It asks for your current password first: without that, anyone who got hold of your open session could change the credential and lock you out of your own account — the same reason removing a second factor requires a live code.

Changing it signs out your other sessions and leaves the one you are using alone. Rotating a password usually means "somebody else may have had it", so sessions minted with the old one should not outlive it; being signed out of the screen you are standing on, as a reward for improving your security, would just teach people not to bother.

An account that signs in through an identity provider has no password here to change, and is told so rather than being shown a form that would do nothing.

When you find yourself back at the login screen

Sessions end for several different reasons, and the login screen names which one. The distinction matters: a session that timed out overnight is not the same as one an administrator revoked, and without the reason the last thing you clicked looks like the cause.

You will see one of:

  • Signed out after N hours of inactivity. The ordinary one. Idle sessions end after SESSION_IDLE_TIMEOUT (8 hours by default), and the message names the actual window rather than a guess. Signing back in is all it needs.
  • Your session reached its maximum age. The absolute lifetime, separate from idleness — nothing you could have done would have kept it, which is why it is worded differently from a timeout.
  • Ended by an administrator, or because the account password changed. Somebody did this deliberately. If it was not you, ask who.
  • This account is no longer active. Signing in will not help; it needs an administrator to re-enable it.

Two of these are worth knowing apart. An idle timeout is not a security event — nobody did anything to you. A revoked session means somebody did. Reading the first as the second sends people hunting for a setting to change when the answer is a conversation, and reading the second as the first hides a change somebody made to your account.

A session belonging to a different account is never affected by what happens to yours. Resetting a local account's password ends that account's sessions and nothing else — including when the same person also signs in through an identity provider, which is a separate account with a separate credential.

Signing in with a one-time password

If your password was set by somebody else — an admin created or recovered your account — the first thing you see after signing in is the change-password form, with no way past it. Until you choose your own, every other part of KubeManta answers "your password was set for you and must be changed", including the API: the limit is enforced by the server, not by hiding buttons, because a one-time password that still works from a script is not one-time.

Signing out always works. So does the form itself — those are the only two things that do.

API keys

Everyone creates their own, under Account → API keys in the account menu (top right). An admin cannot mint a key for somebody else: a key acts as its owner, so one issued on your behalf would do things as you while the audit trail named you. An admin can see any key's name, prefix and last use — never its secret — and can revoke it at any time.

The secret is shown once, when the key is created. KubeManta stores only a hash, so there is no way to display it again; copy it then, or create a new key.

It appears in a dialog of its own that has to be dismissed deliberately — neither Escape nor a click outside it will close it — because dismissing by reflex would discard the only readable copy of a credential nobody can reissue.

You choose what each key can do. At mint you pick its scopes — named permissions like workloads:read, alerts:write or helm:write. Nothing is pre-selected: grant only what the integration needs, because a leaked key can do exactly that much and no more. A CI job that restarts a pod needs workloads:write and nothing else.

Two limits apply together, and both can only narrow:

  • Scopes decide which surfaces the key may reach.
  • The owner's role, re-read on every request. Demote someone and their key immediately acts as a viewer whatever its scopes say; deactivate them and it stops working. A key can never do more than the person who holds it.

Each key's scopes are listed beside it in Account → API keys, so "what could this key do if it leaked?" is answerable at a glance.

Some surfaces no key can reach, at any scope. Identity and credentials (users, groups, SSO, other API keys, your password, your second factor), the licence, expert mode, the audit feed, and the terminal. There is no scope that opens them — a key can never mint another key, disable a safety control, widen its own reach, or read the shell history of everyone who used the terminal. Those need an interactive login.

Mint one for yourself from the account menu → API keys. The secret is shown once. If you are upgrading from a release before scoped keys, your existing keys were revoked on upgrade and need re-minting with the scopes they actually need — there was no safe way to guess what an old key was meant to do.

What to do with it: everything the dashboard reads, a script can read. The API reference documents the X-API-Key header, the endpoints behind each screen — namespaces and pods, incidents, CPU/memory/network history, application sizing, API-server latency, security posture and findings — with worked request examples and the scope each endpoint requires. Your own cluster can also serve its OpenAPI schema at /api/agent/openapi.json, so you can generate a typed client rather than hand-writing one — that endpoint is off by default, and is exposed (along with /docs and /redoc) by setting KUBEMANTA_ENABLE_API_DOCS=true on the agent.

Removing people who have left

Deactivating an account is the normal action: the person can no longer sign in, their sessions stop working on their next request, and everything they did stays attributed in the audit trail. Bulk actions handle the common cleanup of thirty stale accounts at once.

Bulk is deliberately not all-or-nothing. Each account is attempted independently and the result tells you what happened to every one, because a batch that fails wholesale on one already-deleted id teaches you nothing about the other twenty-nine. Two guards always apply: the last active admin cannot be removed — checked per account as the batch runs, so selecting every admin at once still refuses at the final one — and you cannot remove yourself in bulk, since revoking your own session midway would leave the rest half-done and you locked out. The single-user route is still there when that is genuinely what you want.

For a legal erasure request rather than an offboarding, see the erasure plan on the user's own row: it shows exactly what will be deleted, what will be pseudonymised, and what KubeManta refuses to erase and on what grounds.

Roles that come from your identity provider

If you run SSO, roles come from groups, and the split is deliberate: your directory decides who is in a group, KubeManta decides what a group grants.

Groups are not typed in. They appear under Admin → Groups the first time somebody signs in carrying them, with a member count and when they were last seen — which is what makes an opaque identifier recognisable, because several directories send group GUIDs rather than names. A group grants viewer until you set it to admin.

Two consequences worth knowing:

  • Removing somebody from a group at your IdP demotes them at their next sign-in. Membership is re-read from the claim on every login, so your directory stays the one place you deprovision.
  • Promoting one person in Admin → Users pins them. A pinned role survives logins and is not overwritten by their groups — that is the escape hatch for the person who needs admin without the whole group having it.

If nothing appears under Groups after people have signed in, the group claim is not reaching KubeManta; check the groups attribute in the SSO settings. A directory with no groups at all can grant admin by email address instead.

Setup

Admin → Users. Create an account, set its role, and share the credentials through whatever channel you normally use — KubeManta does not email them.

If you run SSO, prefer provisioning through your IdP and use local accounts only for break-glass. Local password login can be turned off entirely once SSO works; that switch is one-way from the browser on purpose, and re-enabling it is a pod-side command:

kubectl exec -n kubemanta-system deploy/kubemanta-agent -- \
  python3 -m app.enable_local_login --admin-only

Enabling it is audited, so the recovery leaves a record rather than living only in someone's shell history.

Troubleshooting

"Seat limit reached" when promoting someone. You are at your paid admin count. Demote an admin who no longer needs it, or add seats. Nothing else is affected — the person can still sign in as a viewer, and every existing admin keeps working.

Someone deactivated can still load a page. Deactivating takes effect on that account's very next request, so there is no cache to wait out. A browser keeps rendering the page it already has; what matters is whether new requests are still being answered. If they are, the account is probably still active — check the row rather than assuming the check failed.

Locked out of everything. One pod-side command fixes every gate at once, because from the login page they are indistinguishable — a forgotten password, a lost authenticator, a deactivated account, an IP ban and disabled password login all produce the same refusal, and working out which is the hard part exactly when you have least patience for it:

printf '%s' "$NEW_PASSWORD" | kubectl exec -i -n kubemanta-system \
    deploy/kubemanta-agent -c agent -- python3 -m app.recover_admin --password-stdin

It recreates the account if it was deleted, resets the password, removes any second factor, reactivates, clears IP bans and re-enables password login. You supply the password — nothing is generated, because a generated password has to be printed and a printed credential outlives its terminal. kubectl exec is the real boundary: whoever has it already owns the database.

The narrower tools remain for when you know exactly which gate is stuck: python3 -m app.clear_bans and python3 -m app.enable_local_login.


Generated from KubeManta 1.2.0 — this page is rendered from the product's own documentation, so it cannot drift from what ships. Manifest built 2026-09-12T02:14:45Z.