Skip to content

Latest commit

 

History

History
222 lines (173 loc) · 7.67 KB

testing-models.mdx

File metadata and controls

222 lines (173 loc) · 7.67 KB
sidebar_position slug description
6
/modeling/testing
Testing Models

import { DocumentationNotice, ProductName, ProductNameFormat, RelatedSection, } from '@components/Docs';

Testing Models

Every model should be tested before deployment to ensure your authorization model is correctly designed.

The .fga.yaml contains tests for authorization models. If you are using Visual Studio Code as your IDE, install the OpenFGA extension to enable syntax coloring and validation.

Define the model and tuples

.fga.yaml files have the following top level items:

Object Description
name (optional) A descriptive name for the test file
model or model_file An model or a reference to an external model file in fga or json format
tuples or tuple_file (optional) A set of tuples or a reference to an external tuple file in json, yaml or csv format. These are considered for all tests.
tests A set of tests that verify the return values of API calls

The example below defines a model and tuples:

name: Model Tests # optional

# model_file: ./model.fga # you can specify an external .fga file, or include it inline
model: |
  model
    schema 1.1

  type user

  type organization
     relations:
       define member : [user]
       define admin : [user with non_expired_grant]

   condition non_expired_grant(current_time: timestamp, grant_time: timestamp, grant_duration: duration) {
     current_time < grant_time + grant_duration
  }

# tuple_file: ./tuples.yaml # you can specify an external file, or include it inline
tuples: 

   # Anne is a member of the Acme organization
  - user: user:anne
    relation: member
    object: organization:acme

  # Peter has the admin role from February 2nd 2024 0AM to 1AM
  - user: user:peter
    relation: admin
    object: organization:acme
    condition: 
      name: non_expired_grant
      context: 
        grant_time : "2024-02-01T00:00:00Z"
        grant_duration : 1h

Write tests

Always write tests to verify that the calls your application will make return the results you expect. A good test covers scenarios that verify every relation.

Tests have the following structure:

Object Description
name (optional) A descriptive name for the test, like “Organization Membership”
tuples A set of tuples that are only considered for the test
check A set of tests for Check calls, each with a user/object and a set of assertions
list_objects A set of tests for ListObjects calls, each one with a user/type and a set of assertions for any number of relations

Write Check tests

Check tests verify the results of the check API calls to validate access requirements for a user. Each check verification has the following structure:

Object Description
user The user type and user id you are checking for access
object The object type and object id related to the user
context A set of tests for contextual parameters used to evaluate conditions
assertions A list of relation:expected-result pairs
<relation>: <true or false> The name of the relation you want to verify and the expected result

The following example adds multiple check verifications in every test:

tests:
  - name: Test
    check:
      - user: user:anne
        object: organization:acme
        assertions:
          member: true
          admin: false

      - user: user:peter
        object: organization:acme
        context: 
          current_time : "2024-02-01T00:10:00Z"
        assertions:
          member: false
          admin: true

Write List Objects tests

A good test covers scenarios that specify every relation for every object type that your application will need to call the list-objects API for.

The following verifies the expected results using the list_objects option in tests:

    list_objects:
      - user: user:anne
        type: organization
        assertions:
            member: 
                - organization:acme
            admin: []
              
      - user: user:peter
        type: organization
        context: 
          current_time : "2024-02-01T00:10:00Z"

        assertions:
            member: []
            admin: 
                - organization:acme

The example above checks that user:anne has access to the organization:acme as a member and is not an admin of any organization. It also checks that user:peter, given the current time is February 1st 2024, 0:10 AM, is not related to any organization as a member, but is related to organization:acme as an admin.

Running tests

Tests are run using the model test CLI command. For instructions on installing the OpenFGA CLI, visit the OpenFGA CLI Github repository.

fga model test --tests <filename>.fga.yaml

When all tests pass, a summary with the number of tests passed is displayed. When a test fails, a line for every test is displayed.

$ fga model test --tests docs.fga.yaml
(PASSING) Test: Checks (4/4 passing) | ListObjects (4/4 passing)

$ fga model test --tests docs.fga.yaml
(FAILING) Test: Checks (4/4 passing) | ListObjects (3/4 passing)
✓ ListObjects(user=user:anne,relation=member,type=organization, context=<nil>)
✓ ListObjects(user=user:anne,relation=admin,type=organization, context=<nil>)
✓ ListObjects(user=user:peter,relation=member,type=organization, context=&map[current_time:2024-02-01T00:10:00Z])
ⅹ ListObjects(user=user:peter,relation=admin,type=organization, context=&map[current_time:2024-02-01T00:10:00Z]): expected=[organization:acm], got=[organization:acme], error=<nil>

Running tests using GitHub Actions

Use the OpenFGA Model Testing Action to run tests from CI/CD flows in GitHub.

Set the path to the .fga.yaml file as the store-file-path parameter when configuring the action:

name: Test Action

on:
  workflow_dispatch:
  pull_request:
    branches:
      - main

jobs:
  test:
    name: Run test
    runs-on: ubuntu-latest
    steps:
      - uses: openfga/[email protected]
        with:
          store-file-path: ./example/model.fga.yaml

Related Sections

<RelatedSection description="Check the following sections for more on how to learn how to write tests." relatedLinks={[ { title: 'Use the FGA CLI ', description: 'Learn how to use the FGA CLI.', link: '../getting-started/cli', id: '../getting-started/cli.mdx', }, { title: 'Super Admin Example ', description: 'Define a model and tests for modeling a super-admin role.', link: 'https://github.com/openfga/sample-stores/blob/main/stores/superadmin/store.fga.yaml' }, { title: 'Banking Example ', description: 'Define a model and tests for banking application.', link: 'https://github.com/openfga/sample-stores/blob/main/stores/banking/store.fga.yaml' }, { title: 'Entitlements Example ', description: 'Define a model and tests for B2B application entitlements.', link: 'https://github.com/openfga/sample-stores/blob/main/stores/advanced-entitlements/store.fga.yaml' } ]} />