Organization
Docs version v1 (main)Nauthera is pre-1.0, in a design-partner programUpdated
An Organization declares one organization: a tenant with its
own issuer, signing keys, users, sessions and audit log. The
operator creates it on the server through the gRPC
AdminService, or adopts the organization that already holds its slug, and keeps the
settings that may change in step with the resource.
| Property | Value |
|---|---|
| API group / version | nauthera.io/v1alpha1 |
| Kind | Organization |
| Plural / short name | organizations / org |
| Scope | Cluster |
| Definition | deploy/ in nauthera-server |
The resource is cluster-scoped because creating a tenant is not a decision one namespace may make for the whole deployment: only someone allowed to create cluster-scoped resources can apply one.
Example
apiVersion: nauthera.io/v1alpha1
kind: Organization
metadata:
name: acme
spec:
slug: acme
displayName: Acme Inc.
namespaces: [acme, grafana] # the namespaces that may configure acme
emailDomains: [acme.example] # routed to acme by a broker, once verified
emailVerificationRequired: true
deletionPolicy: Retain
secondFactor:
methods: [totp, passkey]
required: true
rules:
- name: passkey-off-site
outsideZones: [office]
methods: [passkey]
networkZones:
- name: office
addressRanges:
- 203.0.113.0/24
- 2001:db8:1::/48
branding:
productName: Acme
logoUrl: https://acme.example/logo.svg
theme:
color:
accent: "#7B61FF"kubectl get organizations shows the slug, the issuer, the phase and the Ready
condition's status and reason; -o wide adds the message.
Before you apply one
The server decides whether the operator may manage an organization. The operator's
identity needs the organizations operation and the organization's slug (or *) in its
server. entry; in the Helm chart that is
certManager.. The chart's
default entry leaves out
organizations and acts in the main organization only, so add organizations and the
slug before applying a resource. Without them every call is
refused, and the resource reports Refused with OPERATION_NOT_GRANTED or
OUTSIDE_GRANT.
The main organization cannot be declared this way. A resource cannot name the slug
default, and the server refuses to create, change or delete the main organization over
the control plane whatever the grant says. Configure it with the deployment instead,
under orgs.main (see Organizations).
What the operator does
- Creates or adopts. A resource whose slug no organization holds creates one. One
whose slug is taken adopts that organization and writes every setting that differs:
displayName(the slug when unset),fapiMode,emailVerificationRequired,branding,secondFactorandnetworkZones. - Sends only what changed. On every generation the server does not hold yet, the operator reads the organization and sends only the settings that differ. An unchanged resource produces no write.
- Fixed at creation.
slug,fipsModeanddeletionPolicycannot be edited. An adopted organization whose FIPS mode differs fromspec.fipsModeis reported asFixedAtCreation, and nothing is written until they agree. - Held to the level above.
secondFactornarrows the deployment'smfapolicy and can never loosen it. A policy that states more than the deployment allows (a method it does not offer, passwordless sign-in it keeps closed, a longerrememberForSeconds, a zone it does not spare in) or a rule naming a zone the organization cannot see is refused, and the resource reportsRefusednaming the field and the bound. See Multi-Factor Authentication. - Admits its namespaces.
namespaceslists the namespaces whose OIDCClient, IdentityProvider, LDAPDirectory, Branding and BrokerMembership resources may configure the organization. A resource anywhere else is refused before anything reaches the server; see Which organization a resource configures. Adding or removing a namespace re-evaluates the resources in it. - Claims email domains. Each of
emailDomainsis claimed on the server, andstatus.emailDomainsshows the TXT record to publish under it. The operator looks a pending domain up every five minutes and a settled one every hour, so a record that disappears is noticed. A domain another organization verified is reportedRefused; dropping one from the list releases its claim. A broker routes an address at a verified domain to this organization. - Network zones are named address ranges that the organization's rules, and its
clients' rules, may name beside the deployment's
security.network_zones. A zone may not take a deployment zone's name, and only deployment zones can spare a challenge (spareZones). - Default branding.
brandingis what every sign-in page under the organization wears, with a client's own Branding laid over it field by field. The organization's admin dashboard wears its color, typography and radius tokens, fonts and logo. Removingbrandingfrom the resource clears the default.
The operator writes the declared settings when the resource changes. A setting changed
afterwards through the admin API or nauthera-cli update org is not compared against
the resource, and is written over only when the resource's next generation differs from
what the server holds.
Deleting a resource
spec.deletionPolicy decides, and defaults to Retain:
Retainleaves the organization serving, with its users, keys and audit log.Deleteremoves the organization from the server. It must be chosen when the resource is created, so a later edit cannot arm a deletion. Only the organization this resource created or adopted is removed: one it never reached, or one recreated under the slug since, is left alone.
A finalizer (nauthera.io/organization) holds the resource until that is done. A removal
the server does not take keeps the resource in phase Deleting with reason
OrganizationNotRemoved, and is retried. Each outcome is recorded as a Removed or
Retained event.
The definition's description below says Delete removes the organization "with everything
it holds". The server deletes the organization's own record and stops serving it, but its
users, clients and sessions stay in the database. See Deleting an org.
Spec
spec.branding
Type: object | Optional
The organization's default branding: what every sign-in page under it wears, with a client's own Branding laid over it field by field; what its admin dashboard wears, reduced to its color, typography and radius tokens, fonts and logo; and what its email wears, its logo and accent color. The same document a Branding carries. Removing it clears the default.
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
appName | string | No | — | App name, shown as "Continue to {appName}". |
companyName | string | No | — | Copyright holder shown in the footer. |
faviconUrl | string | No | — | Icon shown in the browser tab and bookmarks: an https URL or an inline data:image/ URI. |
fonts | []string | No | — | Font stylesheet URLs to load, on fonts.googleapis.com or fonts.gstatic.com only: a stylesheet can restyle the password field, so the font CDN is the one host trusted with it. |
hero | object | No | — | Hero pane content for the split layout. |
layout | string | No | — | Page layout — centered (default) or split. One of: centered, split. |
logoUrl | string | No | — | Logo image rendered in the header: an https URL or an inline data:image/ URI. The /ui CSP img-src blocks http images (mixed content). The admin dashboard shows an inline logo of up to 64 KiB, or one on its own origin, and nothing else. The organization's email shows its logo too; Gmail and Outlook show no SVG, so a PNG suits both. |
mode | string | No | — | Default color mode. One of: system, light, dark. |
privacyUrl | string | No | — | |
productName | string | No | — | Tenant/product name shown in the auth header. |
supportUrl | string | No | — | |
termsUrl | string | No | — | |
theme | object | No | — | The design system's theme, as its defineTheme takes it. A field the design system does not know is refused; the values of its token and component maps are stored as written and checked by the server. |
spec.deletionPolicy
Type: string | Optional
What deleting this resource does to the organization. Retain leaves it serving, with its users, keys and audit log. Delete removes the organization's record and its own settings, such as its zones and email domains, and stops serving it; its users, clients, sessions and audit log stay in the database. Immutable, so a later edit cannot arm a deletion.
Defaults to "Retain".
One of: Retain, Delete.
spec.displayName
Type: string | Optional
Human-readable name shown in the hosted UI. Defaults to the slug.
spec.emailDomains
Type: []string | Optional
The email domains whose addresses a broker routes to this organization, lower case, an internationalized name in its xn-- form. Each is claimed on the server and verified once the TXT record status.emailDomains names is published under it; a domain another organization verified is refused. Removing one releases its claim.
spec. emailVerificationRequired
Type: boolean | Optional
Keeps an account whose address is not verified from signing in until it follows an emailed link. An organization with no email relay can send no link, so its unverified accounts stay out.
Defaults to false.
spec.fapiMode
Type: boolean | Optional
Holds the organization's clients to the FAPI 2.0 Security Profile: pushed authorization requests are mandatory and PKCE is S256 only. It can only tighten what the deployment requires of every organization, never relax it.
Defaults to false.
spec.fipsMode
Type: boolean | Optional
Restricts the organization to the FIPS 140-3 approved algorithm set, such as PBKDF2 instead of argon2id for passwords. A server not running the validated module refuses to serve such an organization rather than serve it other algorithms. Immutable.
Defaults to false.
spec.namespaces
Type: []string | Optional
The namespaces whose OIDCClient, IdentityProvider, LDAPDirectory, Branding and BrokerMembership resources may configure this organization. A resource in a namespace no organization lists is refused, and one in a namespace several list names its organization in spec.organization. Empty admits none.
spec.networkZones
Type: []object | Optional
The organization's own network zones, beside the deployment's: its rules and its clients' rules may name either. A zone may not take a deployment zone's name, and only deployment zones spare a challenge.
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
addressRanges | []string | Yes | — | CIDR ranges, IPv4 or IPv6; one covering every address of its family is refused. |
name | string | Yes | — | A lowercase label of up to 63 letters, digits and hyphens. |
spec.secondFactor
Type: object | Optional
The organization's second-factor policy, narrowing the deployment's: which methods its users may use, whether holding one is a condition of a session, whether a passkey alone signs a user in, when a user who holds one is spared the challenge, and the rules that narrow it further for some sign-ins. Absent is the empty policy. The organization's admin dashboard runs under it as it is, but is never spared; its other clients narrow it. A policy stating more than the deployment allows is refused, and the resource reports the refusal naming the bound.
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
alwaysChallenge | boolean | No | — | Spares no sign-in, on a remembered browser or in a zone. |
methods | []string | No | — | The methods a user may enroll and answer with. Empty inherits the level above. |
passwordless | boolean | No | — | Opens sign-in with a discoverable passkey and no password. It is open only where the deployment, the organization and the client all open it. |
rememberForSeconds | integer | No | — | Spares a user who holds a permitted factor the challenge on a browser that passed a second factor for them within this many seconds, while their password and factors are the ones it passed under. Zero inherits the level above's window. |
required | boolean | No | — | Sends a user who holds no permitted factor through enrollment before a session is issued. |
rules | []object | No | — | Narrow this level's policy for the sign-ins that meet them. A rule only ever narrows its own level. |
spareZones | []string | No | — | Spares such a user the challenge from these of the deployment's network zones. Empty inherits the level above's. |
spec.slug
Type: string | Required
The slug the organization is addressed at (/orgs/{slug}/) and known by on the server: lowercase letters, digits and hyphens, not starting with a hyphen. Immutable.
Status
The operator writes status from the server's answer. id, issuer and
observedGeneration come from the server; lastReconciledTime moves on every reconcile.
status.issuer is the issuer the OIDCClient,
IdentityProvider, LDAPDirectory,
Branding and
BrokerMembership resources in the namespaces it
admits are sent under. status.emailDomains reports each of spec.emailDomains: its
state (Pending, Verified or Refused) and the TXT record that proves it.
phase is one of Pending, Ready, Error or Deleting. Beside the connection
reasons every resource shares (Refused, Unreachable, Unsupported,
CredentialUnavailable, TrustAnchorUnavailable; see the
OIDCClient reference), the Ready condition's reason is
one of:
| Reason | Phase | Meaning |
|---|---|---|
Created | Ready | The server created the organization from this resource. |
Adopted | Ready | An organization already held the slug. This resource now manages it, and any setting that differed was written. |
Synced | Ready | The server holds the current generation of the settings. |
FixedAtCreation | Error | The organization's FIPS mode differs from spec.fipsMode. Nothing is written. |
OrganizationNotRemoved | Deleting | Under deletionPolicy: Delete, the server has not removed the organization yet. |
A refusal is retried every five minutes, and a server that does not answer about once a minute.
| Field | Type | Description |
|---|---|---|
conditions | []object | Standard Kubernetes conditions (Ready, Synced, ...). |
emailDomains | []object | Each domain of spec.emailDomains as the server holds its claim. |
id | string | The server-assigned organization ID, stable for the organization's life. |
issuer | string | The organization's OIDC issuer: the iss its tokens carry, and the issuer the resources in the namespaces it admits are sent under. |
lastReconciledTime | string | When the operator last reconciled the resource, whatever the outcome. A stale value means the operator is not running, not the leader, or cannot see the resource. |
observedGeneration | integer | .metadata.generation last reconciled by the server. |
phase | string | High-level lifecycle phase. |
Related
- Organizations: what an organization is and how else to manage one
- Operator: installing the operator and granting it
organizations - Multi-Factor Authentication: the second-factor policy each level narrows
- Branding: a client's own branding, laid over the default