Skip to content

The v1 docs follow nauthera-server's main branch and its 0.x releases on the way to 1.0, so fields and APIs can still change.

v1

BrokerMembership

Docs version v1 (main)Nauthera is pre-1.0, in a design-partner programUpdated

A BrokerMembership declares one side of an identity broker membership, from a namespace of that side's organization. The broker's side names the member it invites; the member's side names the broker it accepts. The membership is active while both sides exist, and deleting either one ends it.

PropertyValue
API group / versionnauthera.io/v1alpha1
KindBrokerMembership
Plural / short namebrokermemberships / bm
ScopeNamespaced
Definitiondeploy/crds/brokermembership-crd.yaml in nauthera-server

Example

The main organization (default) brokers acme, and admits it to one of its clients:

# The broker's side, in a namespace the main organization admits.
apiVersion: nauthera.io/v1alpha1
kind: BrokerMembership
metadata:
  name: acme
  namespace: nauthera
spec:
  member: acme
  clients: [grafana]          # optional; omitted admits every client of the broker
---
# The member's side, in a namespace acme admits.
apiVersion: nauthera.io/v1alpha1
kind: BrokerMembership
metadata:
  name: nauthera
  namespace: acme
spec:
  broker: default

kubectl get bm -A shows both sides with the membership's state:

NAMESPACE   NAME       MEMBER   BROKER    STATE    PHASE   READY   REASON       AGE
acme        nauthera            default   active   Ready   True    Registered   3m
nauthera    acme       acme               active   Ready   True    Registered   4m

Behavior

  • One side per resource. Exactly one of spec.member and spec.broker is set: member makes the resource the broker's invitation, broker makes it the member's acceptance. Both, and the organization the side is declared for, are fixed after creation.
  • Each side from its own organization. Which organization a side is declared for follows from its namespace, as for every namespaced resource (see Which organization a resource configures). The server also holds each side to the operator's grant for that organization, so a team that cannot write in the other organization's namespaces cannot consent for it.
  • Either order. A member's side applied first waits as AwaitingBroker and is sent again every minute. The broker's side is Ready with AwaitingMember until the member accepts; it has done its part. A side created or deleted in the same cluster has every other side sent again at once; one in another cluster notices within ten minutes.
  • The broker's clients. spec.clients lists the client_ids of the broker's clients the membership admits, and only those route to the member. Editing it changes them at once. A client the membership does not admit never offers the member: a broker can admit its members to Grafana and keep its Argo CD for its own users.
  • Accepting provisions a client at the member. It is the reserved client {broker}-broker the broker signs the member's users in through. Ending the membership removes it.
  • Managed here. What a resource declares cannot be changed or ended from the admin dashboard or the admin API, which answer 409 with the audit cause operator_managed. Change the resource instead.

Deleting a resource

Deleting either side ends the membership. A finalizer (nauthera.io/brokermembership) holds the resource until the server has withdrawn its side; one the server did not take keeps the resource in phase Deleting with reason MembershipNotEnded, and is retried. If the other side still exists, the broker's side invites again, and the membership is pending until the member accepts once more.

Spec

spec.broker

Type: string | Optional

The slug of the broker accepted, when this resource is the member's side. Immutable.

spec.clients

Type: []string | Optional

The client_ids of the broker's clients the membership admits, with spec.member only. Empty admits every client of the broker.

spec.member

Type: string | Optional

The slug of the organization invited, when this resource is the broker's side. Immutable.

spec.organization

Type: string | Optional

The slug of the organization this side belongs to. Needed only where more than one organization admits the namespace in its spec.namespaces; otherwise the one that does is taken. The main organization is "default". Immutable.

Status

status.state is the membership's state on the server, pending or active, and empty while the server holds none. 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) and the namespace reasons (NamespaceNotCovered, NamespaceNotAdmitted, OrganizationAmbiguous, OrganizationNotReady, OrganizationChanged), the Ready condition's reason is one of:

ReasonPhaseMeaning
RegisteredReadyThe membership is active.
AwaitingMemberReadyThe broker's invitation is recorded and the member has not accepted it.
AwaitingBrokerPendingThe member's acceptance names a broker that has not invited it. Sent again every minute.
MembershipNotEndedDeletingThe resource is being deleted and the server has not ended the membership.

Each failure reason has a runbook.

FieldTypeDescription
acceptedAtstringWhen the member accepted.
conditions[]objectStandard Kubernetes conditions (Ready, ...).
lastReconciledTimestringWhen 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.
observedGenerationinteger.metadata.generation last reconciled by the server.
organizationstringThe slug of the organization this side was declared for. Once set, a namespace that comes to configure another organization is refused rather than moving the side.
phasestringHigh-level lifecycle phase.
statestringThe membership's state on the server: pending until the member accepts, then active. Empty while the server holds none.