---
title: Charmhub | Deploy Temporal Server using Charmhub - The Open Operator Collection
description: Deploy the latest version of Temporal Server as a Kubernetes Operator
  on any cloud.
url: https://charmhub.io/temporal-k8s/docs/h-authorization
---

# Temporal Server

[Workflows Charmers](https://charmhub.io/publisher/workflows-charmers "View all packages from Workflows Charmers")

* [Workflows Charmers](https://charmhub.io/publisher/workflows-charmers "View all packages from Workflows Charmers")

Platform:

1.23/stable 60

```
juju deploy temporal-k8s --channel 1.23/stable
```

[Learn to deploy on juju >](https://juju.is/docs/juju/manage-applications)

---

#### Relevant links

* [Homepage](https://github.com/canonical/temporal-k8s-operator)

---

#### Contacts

##### Maintainers

+ [Commercial Systems](mailto:jaas-crew@lists.canonical.com)

* [Submit a bug](https://github.com/canonical/temporal-k8s-operator/issues)

---

Share your thoughts on this charm with the community on discourse.

[Join the discussion](https://discourse.charmhub.io/)

# Authorization

Enabling authorization requires that you have an active
[Charmed Temporal K8s Operator](https://charmhub.io/temporal-k8s/docs/t-introduction)
deployed as described in the tutorial. It is recommended that you first go
through the steps of enabling authentication as outlined
[here](https://charmhub.io/temporal-k8s/docs/h-authentication).

By default the Temporal Server doesn’t offer any authorization, but it offers
the plugin mechanism to add a custom one. We have added an OAuth-based
[authentication](https://charmhub.io/temporal-k8s/docs/h-authentication)
using Google Cloud and an authorization mechanism that leverages
[Google Cloud](https://cloud.google.com) and [OpenFGA](https://openfga.dev/).
This custom build of the Temporal Server can be found
[here](https://github.com/canonical/charmed-temporal-image).

## [Deploy OpenFGA](https://charmhub.io/temporal-k8s/docs/h-authorization#p-28861-deploy-openfga)

To deploy Charmed OpenFGA K8s, you need to run the following command, which will
fetch the charm from [Charmhub](https://charmhub.io/openfga-k8s) and deploy it
to your model:

```
juju deploy openfga-k8s --channel edge
```

Wait until the application is ready - when it is ready, `juju status` will show:

```
Model           Controller           Cloud/Region        Version  SLA          Timestamp
temporal-model  temporal-controller  microk8s/localhost  3.1.5    unsupported  12:35:24+03:00

App                 Version   Status    Scale  Charm                Channel    Rev  Address         Exposed  Message
openfga-k8s                   blocked      1   openfga-k8s          edge         9  10.152.183.144  no       installing agent
postgresql-k8s      14.7      active       1   postgresql-k8s       14/stable   73  10.152.183.250  no       Primary
temporal-admin-k8s            active       1   temporal-admin-k8s   stable       4  10.152.183.21   no
temporal-k8s                  active       1   temporal-k8s         stable       9  10.152.183.191  no

Unit                   Workload   Agent  Address      Ports  Message
openfga-k8s/0*         blocked    idle   10.1.232.7          Waiting for postgresql relation
postgresql-k8s/0*      active     idle   10.1.232.66         Primary
temporal-admin-k8s/0*  active     idle   10.1.232.71
temporal-k8s/0*        active     idle   10.1.232.64
```

## [Relate OpenFGA K8s to PostgreSQL K8s](https://charmhub.io/temporal-k8s/docs/h-authorization#p-28861-relate-openfga-k8s-to-postgresql-k8s)

To relate the two charms together, run the following command:

```
juju relate openfga-k8s postgresql-k8s
```

Wait until the charm has settled - when ready, `juju status --relations` will
show:

```
Model           Controller           Cloud/Region        Version  SLA          Timestamp
temporal-model  temporal-controller  microk8s/localhost  3.1.5    unsupported  12:35:24+03:00

App                 Version   Status    Scale  Charm                Channel    Rev  Address         Exposed  Message
openfga-k8s                   active       1   openfga-k8s          edge         9  10.152.183.144  no
postgresql-k8s      14.7      active       1   postgresql-k8s       14/stable   73  10.152.183.250  no       Primary
temporal-admin-k8s            active       1   temporal-admin-k8s   stable       4  10.152.183.21   no
temporal-k8s                  active       1   temporal-k8s         stable       9  10.152.183.191  no

Unit                   Workload   Agent  Address      Ports  Message
openfga-k8s/0*         active     idle   10.1.232.7
postgresql-k8s/0*      active     idle   10.1.232.66         Primary
temporal-admin-k8s/0*  active     idle   10.1.232.71
temporal-k8s/0*        active     idle   10.1.232.64

Relation provider                 Requirer                       Interface          Type     Message
openfga-k8s:peer                  openfga-k8s:peer               openfga-peer       peer
postgresql-k8s:database           openfga-k8s:database           postgresql_client  regular
postgresql-k8s:database           temporal-k8s:db                postgresql_client  regular
postgresql-k8s:database           temporal-k8s:visibility        postgresql_client  regular
postgresql-k8s:database-peers     postgresql-k8s:database-peers  postgresql_peers   peer
postgresql-k8s:restart            postgresql-k8s:restart         rolling_op         peer
temporal-admin-k8s:admin          temporal-k8s:admin             temporal           regular
temporal-k8s:peer                 temporal-k8s:peer              temporal           peer
```

At this point, we have a functioning OpenFGA store which we can now use to store
namespace access rules.

## [Relate Temporal K8s to OpenFGA K8s](https://charmhub.io/temporal-k8s/docs/h-authorization#p-28861-relate-temporal-k8s-to-openfga-k8s)

To enable authorization, we must first configure the Temporal Server as follows:

```
juju config temporal-k8s auth-enabled=true
```

At this point, the `temporal-k8s` application should be in a `blocked` state
with a message `openfga:temporal relation not ready`. We can now relate the two
charms together by running the following command:

```
juju relate temporal-k8s openfga-k8s
```

Once the units settle, the `temporal-k8s` application should still be in a
`blocked` state, but with an updated message
`missing openfga authorization model`. We can now create an
authorization model in the OpenFGA store by
running the following command:

```
juju run temporal-k8s/0 create-authorization-model  model="$(<temporal_auth_model.json)" --string-args=true
```

Wait until the charm has settled - when ready, `juju status --relations` will
show:

```
Model           Controller           Cloud/Region        Version  SLA          Timestamp
temporal-model  temporal-controller  microk8s/localhost  3.1.5    unsupported  12:35:24+03:00

App                 Version   Status    Scale  Charm                Channel    Rev  Address         Exposed  Message
openfga-k8s                   active       1   openfga-k8s          edge         9  10.152.183.144  no
postgresql-k8s      14.7      active       1   postgresql-k8s       14/stable   73  10.152.183.250  no       Primary
temporal-admin-k8s            active       1   temporal-admin-k8s   stable       4  10.152.183.21   no
temporal-k8s                  active       1   temporal-k8s         stable       9  10.152.183.191  no

Unit                   Workload   Agent  Address      Ports  Message
openfga-k8s/0*         active     idle   10.1.232.7
postgresql-k8s/0*      active     idle   10.1.232.66         Primary
temporal-admin-k8s/0*  active     idle   10.1.232.71
temporal-k8s/0*        active     idle   10.1.232.64         auth enabled

Relation provider                 Requirer                       Interface          Type     Message
openfga-k8s:openfga               temporal-k8s:openfga           openfga            regular
openfga-k8s:peer                  openfga-k8s:peer               openfga-peer       peer
postgresql-k8s:database           openfga-k8s:database           postgresql_client  regular
postgresql-k8s:database           temporal-k8s:db                postgresql_client  regular
postgresql-k8s:database           temporal-k8s:visibility        postgresql_client  regular
postgresql-k8s:database-peers     postgresql-k8s:database-peers  postgresql_peers   peer
postgresql-k8s:restart            postgresql-k8s:restart         rolling_op         peer
temporal-admin-k8s:admin          temporal-k8s:admin             temporal           regular
temporal-k8s:peer                 temporal-k8s:peer              temporal           peer
```

At this point, our Temporal Server is active again with authorization enabled.
This means that any request made to the Temporal Server will need to be
[authenticated](https://charmhub.io/temporal-k8s/docs/h-authentication)
using Google OAuth.

## [Create OpenFGA Authorization Rules](https://charmhub.io/temporal-k8s/docs/h-authorization#p-28861-create-openfga-authorization-rules)

Once authorization is enabled, you will not be able to access any namespace in
Temporal. You must now create the necessary tuples in the OpenFGA store to
enable users read/write access to different namespaces.

The authorization model used is as follows:

```
model
  schema 1.1

type user
type group
  relations
    define member: [user]
type namespace
  relations
    define admin: [group#member]
    define reader: [group#member] or writer
    define writer: [group#member] or admin
```

The above model is a simple way of relating users to groups to namespaces. A
`user` can be related to a `group` as a `member`, and a `group` can be related
to a `namespace` as either a `reader`, `writer` or `admin`. For example, if user
`john` is a member of group `abc`, and group `abc` is related to namespace
`example` as a `writer`, then user `john` will be assigned write access on
namespace `example`.

To add authorization rules to our OpenFGA store, we can use the available
actions as follows:

```
# Add user to group:
juju run temporal-k8s/0 add-auth-rule user="<your_email>" group="test_group"

# Output:
Running operation 19 with 1 task
  - task 20 on unit-temporal-k8s-0

Waiting for task 20...
output: 'operation type "create" for user "<your_email>" on group "test_group" successful'
result: command succeeded

# Assign group 'writer' role to namespace:
juju run temporal-k8s/0 add-auth-rule group="test_group" namespace="default" role="writer"

# Output:
Running operation 19 with 1 task
  - task 20 on unit-temporal-k8s-0

Waiting for task 20...
output: 'operation type "create" for group "test_group" and role "writer" on namespace "default" successful'
result: command succeeded
```

And you’re done! If the above actions ran successfully, you should be able to
access the `default` namespace in Temporal with the authenticated user
identified by `<your_email>`, whether through web UI login or the use of a
Google Cloud service account.

The following actions may also be used for removing auth rules, checking access
rules and for auditing purposes:

```
# 1. Check auth rule
juju run temporal-k8s/0 check-auth-rule user="<your_email>" namespace="default" role="writer"

# Output:
output: "True"
result: command succeeded

# 2. List auth rules
juju run temporal-k8s/0 list-auth-rule user="<your_email>"

# Output:
output: |
  admin: '[]'
  member: '[''group:test_group'']'
  reader: '[''namespace:default'']'
  writer: '[''namespace:default'']'
result: command succeeded

# 3. Remove auth rule
juju run temporal-k8s/0 remove-auth-rule user="<your_email>" group="test_group"

# Output:
output: 'operation type "delete" for user "<your_email>" on group "test_group" successful'
result: command succeeded
```

### [Temporal System Admins](https://charmhub.io/temporal-k8s/docs/h-authorization#p-28861-temporal-system-admins)

A Temporal System Admin refers to anyone who has access to all namespaces, as
well as the ability to administer namespace creation and removal. This can be
enabled as follows:

```
# Configure admin group (can be multiple comma-separated groups) and add system admin
juju config temporal-k8s auth-admin-groups="admins"
juju run temporal-k8s/0 add-auth-rule user="<your_email>" group="admins"

# List system admins
juju run temporal-k8s/0 list-system-admins

# Output:
output:
  admins: '[''<your_email>'']'
result: command succeeded
```

Once configured, the user with `<your_email>` will be able to see all namespaces
through the Web UI as well as create new namespaces using
[tctl](https://charmhub.io/temporal-k8s/docs/h-cli).

---
