A cross-platform CLI to interact with an OpenFGA server
- About OpenFGA
- Resources
- Installation
- Building from Source
- Usage
- Contributing
- License
OpenFGA is an open source Fine-Grained Authorization solution inspired by Google's Zanzibar paper. It was created by the FGA team at Auth0 based on Auth0 Fine-Grained Authorization (FGA), available under a permissive license (Apache-2) and welcomes community contributions.
OpenFGA is designed to make it easy for application builders to model their permission layer, and to add and integrate fine-grained authorization into their applications. OpenFGA’s design is optimized for reliability and low latency at a high scale.
- OpenFGA Documentation
- OpenFGA API Documentation
- OpenFGA Discord Community
- Zanzibar Academy
- Google's Zanzibar Paper (2019)
brew install openfga/tap/fga
Download the .deb, .rpm or .apk packages from the releases page.
Debian:
sudo apt install ./fga_<version>_linux_<arch>.deb
Fedora:
sudo dnf install ./fga_<version>_linux_<arch>.rpm
Alpine Linux:
sudo apk add --allow-untrusted ./fga_<version>_linux_<arch>.apk
docker pull openfga/cli; docker run -it openfga/cli
note that the command will be named
cli
go install github.com/openfga/cli@latest
Download the pre-compiled binaries from the releases page.
Make sure you have Go 1.20 or later installed. See the Go downloads page.
-
Clone the repo to a local directory, and navigate to that directory:
git clone https://github.com/openfga/cli.git && cd cli
-
Then use the build command:
go build -o ./dist/fga main.go
or if you have
make
installed, just run:make build
-
Run the OpenFGA CLI with:
./dist/fga
For any command that interacts with an OpenFGA server, these configuration values can be passed (where applicable)
Name | Flag | CLI |
---|---|---|
Server Url | --server-url |
FGA_SERVER_URL |
Shared Secret | --api-token |
FGA_API_TOKEN |
Client ID | --client-id |
FGA_CLIENT_ID |
Client Secret | --client-secret |
FGA_CLIENT_SECRET |
Token Issuer | --api-token-issuer |
FGA_API_TOKEN_ISSUER |
Token Audience | --api-audience |
FGA_API_AUDIENCE |
Store ID | --store-id |
FGA_STORE_ID |
Authorization Model ID | --model-id |
FGA_MODEL_ID |
Description | command | parameters | example |
---|---|---|---|
Create a Store | create |
--name |
fga store create --name="FGA Demo Store" |
List Stores | list |
fga store list |
|
Get a Store | get |
--store-id |
fga store get --store-id=01H0H015178Y2V4CX10C2KGHF4 |
Delete a Store | delete |
--store-id |
fga store delete --store-id=01H0H015178Y2V4CX10C2KGHF4 |
fga store create
--name
: Specifies the name of the store to be created
fga store create --name "FGA Demo Store"
{
"id": "01H0H015178Y2V4CX10C2KGHF4",
"name": "FGA Demo Store",
"created_at": "2023-05-19T16:10:07.637585677Z",
"updated_at": "2023-05-19T16:10:07.637585677Z"
}
fga store list
--max-pages
: Max number of pages to retrieve (default: 20)
fga store list
{
"stores": [{
"id": "..",
"name": "..",
"created_at": "",
"updated_at": "",
"deleted_at": ""
}, { .. }]
}
fga store get
--store-id
: Specifies the store id to get
fga store get --store-id=01H0H015178Y2V4CX10C2KGHF4
{
"id": "01H0H015178Y2V4CX10C2KGHF4",
"name": "FGA Demo Store",
"created_at": "2023-05-19T16:10:07.637585677Z",
"updated_at": "2023-05-19T16:10:07.637585677Z"
}
fga store delete
--store-id
: Specifies the store id to delete
fga store delete --store-id=01H0H015178Y2V4CX10C2KGHF4
{}
model
Description | command | parameters | example |
---|---|---|---|
Read Authorization Models | list |
--store-id |
fga model list --store-id=01H0H015178Y2V4CX10C2KGHF4 |
Write Authorization Model | write |
--store-id , --file |
fga model write --store-id=01H0H015178Y2V4CX10C2KGHF4 --file=model.json |
Read a Single Authorization Model | get |
--store-id , --model-id |
fga model get --store-id=01H0H015178Y2V4CX10C2KGHF4 --model-id=01GXSA8YR785C4FYS3C0RTG7B1 |
fga model list
--store-id
: Specifies the store id--max-pages
: Max number of pages to retrieve (default: 20)
fga model list --store-id=01H0H015178Y2V4CX10C2KGHF4
[{
"schema_version": "1.1",
"id": "01GXSA8YR785C4FYS3C0RTG7B1",
"type_definitions": [
{"type": "user"},
// { ... }
],
},
// { ... }
]
fga model write
--store-id
: Specifies the store id--file
: Specifies the file containing the model in JSON format
fga model write --store-id=01H0H015178Y2V4CX10C2KGHF4 --file=model.json
fga model write --store-id=01H0H015178Y2V4CX10C2KGHF4 '{"type_definitions": [ { "type": "user" }, { "type": "document", "relations": { "can_view": { "this": {} } }, "metadata": { "relations": { "can_view": { "directly_related_user_types": [ { "type": "user" } ] }}}} ], "schema_version": "1.1"}'
{
"authorization_model_id":"01GXSA8YR785C4FYS3C0RTG7B1"
}
fga model get
--store-id
: Specifies the store id--model-id
: Specifies the model id
fga model get --store-id=01H0H015178Y2V4CX10C2KGHF4 --model-id=01GXSA8YR785C4FYS3C0RTG7B1
{
"schema_version": "1.1",
"id": "01GXSA8YR785C4FYS3C0RTG7B1",
"type_definitions": [
{"type": "user"},
// { ... }
],
}
If model-id
is not specified when using the get
command, the latest authorization model will be returned.
fga model get
--store-id
: Specifies the store id
fga model get --store-id=01H0H015178Y2V4CX10C2KGHF4
{
"schema_version": "1.1",
"id": "01GXSA8YR785C4FYS3C0RTG7B1",
"type_definitions": [
{"type": "user"},
// { ... }
],
}
fga model validate
fga model validate '{"schema_version":"1.1,"type_definitions":[{"type":"user"}]}'
- Valid model with an ID
{"id":"01GPGWB8R33HWXS3KK6YG4ETGH","created_at":"2023-01-11T16:59:22Z","is_valid":true}
- Valid model without an ID
{"is_valid":true}
- Invalid model with an ID
{"id":"01GPGTVEH5NYTQ19RYFQKE0Q4Z","created_at":"2023-01-11T16:33:15Z","is_valid":false,"error":"invalid schema version"}
- Invalid model without an ID
{"is_valid":false,"error":"the relation type 'employee' on 'member' in object type 'group' is not valid"}
tuple
Description | command | parameters | example |
---|---|---|---|
Write Relationship Tuples | write |
--store-id , --model-id |
fga tuple write --store-id=01H0H015178Y2V4CX10C2KGHF4 '{"schema_version":"1.1","type_definitions":[...]}' |
Delete Relationship Tuples | delete |
--store-id , --model-id |
fga tuple delete --store-id=01H0H015178Y2V4CX10C2KGHF4 |
Read Relationship Tuples | read |
--store-id , --model-id |
fga tuple read --store-id=01H0H015178Y2V4CX10C2KGHF4 --model-id=01GXSA8YR785C4FYS3C0RTG7B1 |
Read Relationship Tuple Changes (Watch) | changes |
--store-id , --model-id |
fga tuple changes --store-id=01H0H015178Y2V4CX10C2KGHF4 --model-id=01GXSA8YR785C4FYS3C0RTG7B1 |
Import Relationship Tuples | import |
--store-id , --model-id , --file |
fga tuple import --store-id=01H0H015178Y2V4CX10C2KGHF4 --model-id=01GXSA8YR785C4FYS3C0RTG7B1 --file=tuples.json |
fga tuple write --store-id=
<user>
: User<relation>
: Relation<object>
: Object--store-id
: Specifies the store id--model-id
: Specifies the model id to target (optional)
fga tuple write --store-id=01H0H015178Y2V4CX10C2KGHF4 user:anne can_view document:roadmap
{}
fga tuple delete --store-id=
<user>
: User<relation>
: Relation<object>
: Object--store-id
: Specifies the store id
fga tuple delete --store-id=01H0H015178Y2V4CX10C2KGHF4 user:anne can_view document:roadmap
{}
fga tuple read [--user=] [--relation=] [--object=] --store-id=
--store-id
: Specifies the store id--user
: User--relation
: Relation--object
: Object
fga tuple read --store-id=01H0H015178Y2V4CX10C2KGHF4 --user user:anne --relation can_view --object document:roadmap
{
"tuples": [
{
"key": {
"object": "document:roadmap",
"relation": "can_view",
"user": "user:anne"
},
"timestamp": "2023-07-06T15:12:55.080666875Z"
}
]
}
fga tuple changes --type --store-id=
--store-id
: Specifies the store id--type
: restrict to a specific type (optional)--max-pages
: Max number of pages to retrieve (default: 20)
fga tuple changes --store-id=01H0H015178Y2V4CX10C2KGHF4 --type document
{
"changes": [
{
"operation": "TUPLE_OPERATION_WRITE",
"timestamp": "2023-07-06T15:12:40.294950382Z",
"tuple_key": {
"object": "document:roadmap",
"relation": "can_view",
"user": "user:anne"
}
}
]
}
fga tuple import --store-id= [--model-id=] --file= [--max-tuples-per-write=] [--max-parallel-requests=]
--store-id
: Specifies the store id--model-id
: Specifies the model id to target (optional)--file
: Specifies the file name,yaml
andjson
files are supported--max-tuples-per-write
: Max tuples to send in a single write (optional, default=20)--max-parallel-requests
: Max requests to send in parallel (optional, default=4)
File format should be: In YAML:
- user: user:anne
relation: can_view
object: document:roadmap
- user: user:beth
relation: can_view
object: document:roadmap
In JSON:
[{
"user": "user:anne",
"relation": "can_view",
"object": "document:roadmap"
}, {
"user": "user:beth",
"relation": "can_view",
"object": "document:roadmap"
}]
fga tuple import --store-id=01H0H015178Y2V4CX10C2KGHF4 --file tuples.json
{
"successful": [
{
"object":"document:roadmap",
"relation":"writer",
"user":"user:annie"
}
],
"failed": [
{
"tuple_key": {
"object":"document:roadmap",
"relation":"writer",
"user":"carl"
},
"reason":"Write validation error ..."
}
]
}
query
Description | command | parameters | example |
---|---|---|---|
Check | check |
--store-id , --model-id |
fga query check --store-id=01H0H015178Y2V4CX10C2KGHF4 user:anne can_view document:roadmap |
List Objects | list-objects |
--store-id , --model-id |
fga query list-objects --store-id=01H0H015178Y2V4CX10C2KGHF4 user:anne can_view document |
List Relations | list-relations |
--store-id , --model-id |
fga query list-relations --store-id=01H0H015178Y2V4CX10C2KGHF4 user:anne document |
Expand | expand |
--store-id , --model-id |
fga query expand --store-id=01H0H015178Y2V4CX10C2KGHF4 can_view document:roadmap |
fga query check [--contextual-tuple " "]* --store-id= [--model-id=]
--store-id
: Specifies the store id--model-id
: Specifies the model id to target (optional)--contextual-tuple
: Contextual tuples
fga query check --store-id=01H0H015178Y2V4CX10C2KGHF4 user:anne can_view document:roadmap --contextual-tuple "user:anne can_view folder:product" --contextual-tuple "folder:product parent document:roadmap"
{
"allowed": true,
}
fga query list-objects <object_type> [--contextual-tuple " "]* --store-id= [--model-id=]
--store-id
: Specifies the store id--model-id
: Specifies the model id to target (optional)--contextual-tuple
: Contextual tuples (optional) (can be multiple)
fga query list-objects --store-id=01H0H015178Y2V4CX10C2KGHF4 user:anne can_view document --contextual-tuple "user:anne can_view folder:product" --contextual-tuple "folder:product parent document:roadmap"
{
"objects": [
"document:roadmap",
"document:budget"
],
}
fga query list-objects [--relation ]* [--contextual-tuple " "]* --store-id= [--model-id=]
--store-id
: Specifies the store id--model-id
: Specifies the model id to target (optional)--contextual-tuple
: Contextual tuples (optional) (can be multiple)
fga query list-relations --store-id=01H0H015178Y2V4CX10C2KGHF4 user:anne document:roadmap --relation can_view
{
"relations": [
"can_view"
],
}
fga query expand --store-id= [--model-id=]
--store-id
: Specifies the store id--model-id
: Specifies the model id to target (optional)
fga query expand --store-id=01H0H015178Y2V4CX10C2KGHF4 can_view document:roadmap
{
"tree": {
"root": {
"name": "repo:openfga/openfga#reader",
"union": {
"nodes": [{
"leaf": {
"users": {
"users": ["user:anne"]
}
},
"name": "repo:openfga/openfga#reader"
}]
}
}
}
}
See CONTRIBUTING.
This project is licensed under the Apache-2.0 license. See the LICENSE file for more info.