Home

Awesome

FOSSA Status FOSSA Status

FGA Operator Documentation

This documentation helps you deploy an OpenFGA authorization model and ensures your deployments stay in sync with the latest authorization model from OpenFGA. The FGA operator automates the synchronization between your deployments and the authorization models.

Steps

1. Create an Authorization Model

Make an authorization request:

apiVersion: extensions.fga-operator/v1
kind: AuthorizationModelRequest
metadata:
  name: documents
spec:
  instances:
    - version:
        major: 1
        minor: 1
        patch: 1
      authorizationModel: |
        model
          schema 1.1
          
        type user
          
        type document
          relations
            define reader: [user]
            define writer: [user]
            define owner: [user]

This request will:

apiVersion: extensions.fga-operator/v1
kind: Store
metadata:
  labels:
    authorization-model: documents
  name: documents
  namespace: default
  ownerReferences:
  - apiVersion: extensions.fga-operator/v1
    blockOwnerDeletion: true
    controller: true
    kind: AuthorizationModelRequest
    name: documents
    uid: <SOME_ID>
spec:
  id: 01J1N8HCY7MQP4QP3GVDWTM9ZG

apiVersion: extensions.fga-operator/v1
kind: AuthorizationModel
metadata:
  labels:
    authorization-model: documents
  name: documents
  namespace: default
  ownerReferences:
  - apiVersion: extensions.fga-operator/v1
    blockOwnerDeletion: true
    controller: true
    kind: AuthorizationModelRequest
    name: documents
    uid: <SOME_ID>
spec:
  instances:
  - authorizationModel: |
      model
        schema 1.1

      type user

      type document
        relations
          define reader: [user]
          define writer: [user]
          define owner: [user]  
    createdAt: "2024-07-06T06:44:24Z"
    id: 01J23CJTA8X4K87X62ECX1Y58Z
    version:
      major: 1
      minor: 1
      patch: 1

2. Deployment with Label

Given a deployment with the label openfga-store set to the name of the authorization request:

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    openfga-store: documents
    app: annotated-curl
  name: annotated-curl
spec:
  replicas: 1
  selector:
    matchLabels:
      app: annotated-curl
  template:
    metadata:
      labels:
        app: annotated-curl
    spec:
      containers:
      - name: main
        image: curlimages/curl:8.7.1
        command: ["sleep", "9999999"]

The environment variable OPENFGA_AUTH_MODEL_ID will be set to the latest created authorization model ID from OpenFGA.

apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    openfga-auth-id-updated-at: "2024-07-06T06:44:24Z"
    openfga-auth-model-version: 1.1.1
    openfga-store-id-updated-at: "2024-07-06T06:44:24Z"
  labels:
    app: annotated-curl
    openfga-store: documents
  name: annotated-curl
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: annotated-curl
  template:
    metadata:
      labels:
        app: annotated-curl
    spec:
      containers:
      - command:
        - sleep
        - "9999999"
        env:
        - name: OPENFGA_STORE_ID
          value: 01J1N8HCY7MQP4QP3GVDWTM9ZG
        - name: OPENFGA_AUTH_MODEL_ID
          value: 01J23CJTA8X4K87X62ECX1Y58Z
        image: curlimages/curl:8.7.1
        imagePullPolicy: IfNotPresent
        name: main

3. Update the Authorization Model

To update the authorization model, make a request like below. The important part is setting a new version since this is what the controller compares.

apiVersion: extensions.fga-operator/v1
kind: AuthorizationModelRequest
metadata:
  name: documents
spec:
  instances:
    - version:
        major: 1
        minor: 1
        patch: 2
      authorizationModel: |
        model
          schema 1.1
        
        type user
        
        type document
          relations
            define foo: [user]
            define reader: [user]
            define writer: [user]
            define owner: [user]
    - version:
        major: 1
        minor: 1
        patch: 1
      authorizationModel: |
        model
          schema 1.1
          
        type user
          
        type document
          relations
            define reader: [user]
            define writer: [user]
            define owner: [user]

The controller will call OpenFGA and create the new authorization model. The controller will update the AuthorizationModel with the new reference.

apiVersion: extensions.fga-operator/v1
kind: AuthorizationModel
metadata:
  creationTimestamp: "2024-07-06T06:44:25Z"
  generation: 2
  labels:
    authorization-model: documents
  name: documents
  namespace: default
  ownerReferences:
  - apiVersion: extensions.fga-operator/v1
    blockOwnerDeletion: true
    controller: true
    kind: AuthorizationModelRequest
    name: documents
    uid: e507bff2-09b2-44d7-9f2e-b6f238dda3b3
  resourceVersion: "734046"
  uid: 6c0ab77c-765b-40d1-8372-77a5cefb325e
spec:
  instances:
  - authorizationModel: |
      model
        schema 1.1

      type user

      type document
        relations
          define reader: [user]
          define writer: [user]
          define owner: [user]
    createdAt: "2024-07-06T06:44:24Z"
    id: 01J23CJTA8X4K87X62ECX1Y58Z
    version:
      major: 1
      minor: 1
      patch: 1
  - authorizationModel: |
      model
        schema 1.1

      type user

      type document
        relations
          define foo: [user]
          define reader: [user]
          define writer: [user]
          define owner: [user]
    createdAt: "2024-07-06T06:50:37Z"
    id: 01J23CY66445FA3Z6TQEC9WBZK
    version:
      major: 1
      minor: 1
      patch: 2

The controller will update annotated deployments so that the example deployment will have its OPENFGA_AUTH_MODEL_ID environment variable updated.

apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    openfga-auth-id-updated-at: "2024-07-06T06:50:37Z"
    openfga-auth-model-version: 1.1.2
    openfga-store-id-updated-at: "2024-07-06T06:44:24Z"
  labels:
    app: annotated-curl
    openfga-store: documents
  name: annotated-curl
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: annotated-curl
  template:
    metadata:
      labels:
        app: annotated-curl
    spec:
      containers:
      - command:
        - sleep
        - "9999999"
        env:
        - name: OPENFGA_STORE_ID
          value: 01J1N8HCY7MQP4QP3GVDWTM9ZG
        - name: OPENFGA_AUTH_MODEL_ID
          value: 01J23CY66445FA3Z6TQEC9WBZK
        image: curlimages/curl:8.7.1
        imagePullPolicy: IfNotPresent
        name: main

4. Set a Specific Version on Deployment

To lock the OPENFGA_AUTH_MODEL_ID to a specific user-provided version, add the label openfga-auth-model-version and set it to the desired version.

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    openfga-store: documents
    openfga-auth-model-version: "1.1.1"
    app: annotated-curl
  name: annotated-curl
spec:
  replicas: 1
  selector:
    matchLabels:
      app: annotated-curl
  template:
    metadata:
      labels:
        app: annotated-curl
    spec:
      containers:
      - name: main
        image: curlimages/curl:8.7.1
        command: ["sleep", "9999999"]

By applying the above, the OPENFGA_AUTH_MODEL_ID will be set to the authorization model ID with version label 1.1.1.

apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    openfga-auth-id-updated-at: "2024-07-06T07:01:40Z"
    openfga-auth-model-version: 1.1.1
    openfga-store-id-updated-at: "2024-07-06T06:44:24Z"
  labels:
    app: annotated-curl
    openfga-auth-model-version: 1.1.1
    openfga-store: documents
  name: annotated-curl
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: annotated-curl
  template:
    metadata:
      labels:
        app: annotated-curl
    spec:
      containers:
      - command:
        - sleep
        - "9999999"
        env:
        - name: OPENFGA_STORE_ID
          value: 01J1N8HCY7MQP4QP3GVDWTM9ZG
        - name: OPENFGA_AUTH_MODEL_ID
          value: 01J23CJTA8X4K87X62ECX1Y58Z
        image: curlimages/curl:8.7.1
        imagePullPolicy: IfNotPresent
        name: main

Migration Guide for Using Operator with Existing Models

If you have existing stores and authorization models and wish to migrate to use the operator without deploying a new authorization model or store, you can retain the existing ones. Creating new models would require reconciling all existing relationship tuples, which might not be desirable.

To address this, the AuthorizationModelRequest resource provides the properties existingStoreId and existingAuthorizationModelId, allowing you to reuse your current setup.

Example configuration:

apiVersion: extensions.fga-operator/v1
kind: AuthorizationModelRequest
metadata:
  name: documents
spec:
  existingStoreId: 01J1N8HCY7MQP4QP3GVDWTM9ZG
  instances:
    - version:
        major: 1
        minor: 1
        patch: 1
      existingAuthorizationModelId: 01J23CJTA8X4K87X62ECX1Y58Z
      authorizationModel: |
        model
          schema 1.1
          
        type user
          
        type document
          relations
            define reader: [user]
            define writer: [user]
            define owner: [user]

In this configuration, the operator will not create a store and authorization model in OpenFGA. It will only handle the creation of Custom Resource Definitions (CRDs), such as AuthorizationModel and Store, and perform the necessary deployment updates.

Installation using Helm

To install the Helm chart for fga-operator, follow the steps below:

Add Helm Repository:

helm repo add fga-operator https://3schwartz.github.io/fga-operator/
helm repo update

Search for the chart

helm search repo fga --devel

Install the Chart:

helm install fga-operator fga-operator/fga-operator --version <CHOOSE_VERSION>

Verify Installation:

helm list

The helm chart can be added as a chart dependency in Chart.yaml:

...
dependencies:
- name: fga-operator
  version: "<CHOOSE_VERSION>"
  repository: https://3schwartz.github.io/fga-operator/

Configurations

Configurations can be set using either command-line flags or environment variables.

Command line flags

All command line flags has defaults and hence none of them are mandatory.

NameDescriptionDefault ImageDefault Helm Chart
metrics-bind-addressThe address the metric endpoint binds to. Setting it to "0" will disable the endpoint.":8080"0
health-probe-bind-addressThe address the probe endpoint binds to.":8081"8081
leader-electEnable leader election for controller manager. Enabling this will ensure there is only one active controller manager.falsetrue
metrics-secureIf set the metrics endpoint is served securely.falsefalse
enable-http2If set, HTTP/2 will be enabled for the metrics and webhook serversfalsefalse
zap-develconfigures the logger to use a Zap development config (stacktraces on warnings, no sampling), otherwise a Zap production config will be used (stacktraces on errors, sampling).truefalse

Environment Variables

NameDescriptionDefaultMandatoryExamples
OPENFGA_API_URLUrl to OpenFGA.-Yes"http://127.0.0.1:8089", "http://openfga.demo.svc.cluster.local:8080"
OPENFGA_API_TOKENPreshared key used for authentication to OpenFGA.-Yes"foobar", "some_token"
RECONCILIATION_INTERVALThe time interval between reconciliation loops, unless an AuthorizationModelRequest is created or modified."10s"No"45s", "5m", "3h"

Limitations

Events

This table outlines the events emitted by the controllers during the reconciliation process, along with their type and description.

ReasonTypeControllerDescriptionCRD
StoreFetchFailureWarningAuthorizationModelReconcilerTriggered when the store resource cannot be fetched during reconciliation.AuthorizationModel
AuthorizationModelIdUpdateFailedWarningAuthorizationModelReconcilerEmitted when finding the correct Authorization Model id on a deployment fails.AuthorizationModel<br/> Deployment
FailedListingDeploymentsWarningAuthorizationModelReconcilerRaised when there is an issue listing deployments during reconciliation.AuthorizationModel
FailedUpdatingDeploymentWarningAuthorizationModelReconcilerEmitted when a deployment update fails during reconciliation.AuthorizationModel<br/> Deployment
AuthorizationModelStatusChangeFailedWarningAuthorizationModelRequestReconcilerTriggered when the status update for an AuthorizationModelRequest fails.AuthorizationModelRequest
ClientInitializationFailedWarningAuthorizationModelRequestReconcilerEmitted when the OpenFGA client initialization fails.AuthorizationModelRequest
StoreFailedWarningAuthorizationModelRequestReconcilerRaised when there is an issue creating or fetching the store from OpenFGA.AuthorizationModelRequest
AuthorizationModelCreationFailedWarningAuthorizationModelRequestReconcilerTriggered when the creation of the AuthorizationModel in OpenFGA fails.AuthorizationModelRequest
AuthorizationModelUpdateFailedWarningAuthorizationModelRequestReconcilerEmitted when the update of an AuthorizationModel in Kubernetes fails.AuthorizationModelRequest

Status

AuthorizationModelRequest

This table describes the possible statuses for the AuthorizationModelRequest resource during its lifecycle.

StatusDescription
PendingIndicates that the request has been created but has not yet started processing.
SynchronizingIndicates that the request is actively being processed (e.g., creating or updating resources in OpenFGA or Kubernetes).
SynchronizedIndicates that the request has been successfully reconciled, and all resources are up to date.
SynchronizationFailedSet when the synchronization process fails due to errors in OpenFGA or Kubernetes operations.

Reconciliation Design

This design outlines the interaction between the client, custom resource definitions (CRDs), and the operator for managing OpenFGA Stores and Authorization Models.

sequenceDiagram
actor Client

box Custom Resource Definitions
participant AuthorizationModelRequest
participant Store
participant AuthorizationModel
participant Deployment
end

box Operator
participant AuthorizationModelRequestReconciler
participant AuthorizationModelReconciler
end

participant OpenFGA

    Client ->> AuthorizationModelRequest: Creates a request
    
    
    AuthorizationModelRequestReconciler ->> AuthorizationModelRequest: Listen to create and update
    activate AuthorizationModelRequestReconciler

    opt If Store doesn't exists in OpenFGA
        AuthorizationModelRequestReconciler ->> OpenFGA: Create Store
        AuthorizationModelRequestReconciler ->> Store: Create
    end
    
    opt Authorization Model has changed or initialized
        AuthorizationModelRequestReconciler ->> OpenFGA: Create Authorization Model
        AuthorizationModelRequestReconciler ->> AuthorizationModel: Create or Update AuthorizationModel
    end
    
    deactivate AuthorizationModelRequestReconciler

    activate AuthorizationModelReconciler
    
    AuthorizationModelReconciler ->> AuthorizationModel: Listen to create and update
    
    AuthorizationModelReconciler ->> Store: Fetch Store
    AuthorizationModelReconciler ->> AuthorizationModel: Fetch AuthorizationModel
    
    loop Check deployments every RECONCILIATION_INTERVAL
        AuthorizationModelReconciler ->> Deployment: List deployments with `openfga-store` label
        
        opt ENV `OPENFGA_AUTH_MODEL_ID` or `OPENFGA_STORE_ID` are not up to date.
            AuthorizationModelReconciler ->> Deployment: Update ENVs and annotations
        end
    end

    deactivate AuthorizationModelReconciler

Steps

Client Request

AuthorizationModelRequestReconciler Request Reconciliation:

AuthorizationModelReconciler Model Reconciliation:

This flow ensures that OpenFGA stores and authorization models are kept in sync with Kubernetes deployments.