The platform team owns nats-system: the NATS operator, the system account, every account and its limits. The payments team owns the payments namespace and wants to declare its own users and streams there, without reading anything in nats-system.

What the platform team declares #

The account, and a grant that lets users in payments attach to it. The grant sits in the namespace it opens up, so only someone who can write there can open it. It trusts payments with every user key of the account: a NatsUser there can claim any key the account’s users hold, those issued outside the auth controller included, and deleting it revokes that key. Accounts stay in nats-system alone: whichever NatsAccount records an account key first holds it, so a namespace granted NatsAccounts to the NatsOperator could take any account key no NatsAccount records yet.

01-platform.yaml

# Owned by the platform team, in nats-system: the account and its limits.
apiVersion: auth.nats.mikluko.io/v1beta1
kind: NatsAccount
metadata:
  name: payments
  namespace: nats-system
spec:
  operatorRef:
    name: demo
  limits:
    connections: 200
    jetstream:
      memoryStorage: 512Mi
      diskStorage: 100Gi
      streams: 10
      consumers: 100
---
# The platform team's consent: NatsUsers in the payments namespace may
# reference the payments account here, and nothing else in nats-system.
apiVersion: nats.mikluko.io/v1beta1
kind: NatsReferenceGrant
metadata:
  name: payments-users
  namespace: nats-system
spec:
  from:
    - group: auth.nats.mikluko.io
      kind: NatsUser
      namespace: payments
  to:
    - group: auth.nats.mikluko.io
      kind: NatsAccount
      name: payments   # omitted: every NatsAccount in nats-system
kubectl apply -f https://nats-operator.io/docs/stories/04-team-self-service/01-platform.yaml

What the payments team declares #

Users that reference the account across namespaces, and everything JetStream in its own namespace. Creds Secrets land beside the users.

01-team.yaml

# Owned by the payments team, in its own namespace. The team never reads
# nats-system: its creds Secret lands here.
apiVersion: auth.nats.mikluko.io/v1beta1
kind: NatsUser
metadata:
  name: payments-api
  namespace: payments
spec:
  accountRef:
    kind: NatsAccount
    namespace: nats-system   # admitted by the payments-users grant
    name: payments
  permissions:
    publish:
      allow: ["payments.>", "$JS.API.>"]
    subscribe:
      allow: ["payments.>", "_INBOX.>"]
  credentials:
    secretKeyRef:
      name: payments-api-creds
---
# The user the JetStream controller acts as in this account.
apiVersion: auth.nats.mikluko.io/v1beta1
kind: NatsUser
metadata:
  name: payments-jetstream
  namespace: payments
spec:
  accountRef:
    kind: NatsAccount
    namespace: nats-system
    name: payments
  permissions:
    publish:
      allow: ["$JS.API.>"]
    subscribe:
      allow: ["_INBOX.>"]
  credentials:
    secretKeyRef:
      name: payments-jetstream-creds
---
# Everything JetStream stays in the team's namespace: no grant needed.
apiVersion: nats.mikluko.io/v1beta1
kind: NatsConnection
metadata:
  name: demo
  namespace: payments
spec:
  servers: ["nats://demo.nats-system.svc:4222"]
  credentials:
    secretKeyRef:
      name: payments-jetstream-creds
---
apiVersion: jetstream.nats.mikluko.io/v1beta1
kind: NatsStream
metadata:
  name: payments
  namespace: payments
spec:
  connectionRef:
    name: demo
  name: PAYMENTS
  subjects: ["payments.>"]
  storage: File
  replicas: 3
  maxAge: 720h
kubectl apply -f https://nats-operator.io/docs/stories/04-team-self-service/01-team.yaml

Without a grant #

A user from a namespace no grant covers is refused, and deleting a grant later revokes the users it had admitted and deletes the creds Secrets they own.

01-natsuser-payments-reader.yaml

# Declared in the orders namespace, which no grant covers, against the
# payments account.
apiVersion: auth.nats.mikluko.io/v1beta1
kind: NatsUser
metadata:
  name: payments-reader
  namespace: orders
spec:
  accountRef:
    kind: NatsAccount
    namespace: nats-system
    name: payments
  preset: readonly
  credentials:
    secretKeyRef:
      name: payments-reader-creds
kubectl apply -f https://nats-operator.io/docs/stories/04-team-self-service/01-natsuser-payments-reader.yaml

01-status-natsuser-payments-reader.yaml

# payments-reader, with no grant covering it.
status:
  observedGeneration: 1
  conditions:
    - type: Ready
      status: "False"
      reason: ReferenceNotPermitted
    - type: ReferencesResolved
      status: "False"
      reason: NoGrant
      message: >-
        no NatsReferenceGrant in nats-system admits NatsUser from namespace
        orders to NatsAccount payments