Skip to content

Commit

Permalink
Merge pull request #11 from le-yams/feat/configurable_external_fga_se…
Browse files Browse the repository at this point in the history
…rver

feat: configurable external fga server
  • Loading branch information
rhamzeh authored Jun 3, 2024
2 parents 21bd8b0 + 74cb4ae commit 21b4215
Show file tree
Hide file tree
Showing 6 changed files with 263 additions and 16 deletions.
75 changes: 75 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,78 @@ jobs:
uses: ./
with:
test_path: ./example/model.fga.yaml

test_conditions_support:
name: Test conditions support
runs-on: ubuntu-latest
strategy:
matrix:
test:
- openfga_tag: v1.5.3
conditions_supported: true
- openfga_tag: v1.4.3
conditions_supported: true
- openfga_tag: v1.3.7
conditions_supported: false
services:
postgres:
image: postgres:14
env:
POSTGRES_USER: openfga
POSTGRES_PASSWORD: "1234"
ports:
- 5432:5432
options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
env:
OPENFGA_DATASTORE_ENGINE: 'postgres'
OPENFGA_DATASTORE_URI: 'postgres://openfga:[email protected]:5432/openfga'
OPENFGA_LOG_LEVEL: debug
steps:
- uses: actions/checkout@v4
- name: Install OpenFGA server ${{ matrix.test.openfga_tag }}
uses: jaxxstorm/[email protected]
with:
repo: openfga/openfga
tag: ${{ matrix.test.openfga_tag }}
cache: enable
- name: Migrate OpenFGA Database
shell: bash
run: openfga migrate
- name: Start OpenFGA Server
shell: bash
run: openfga run &
- name: Install OpenFGA cli
uses: jaxxstorm/[email protected]
with:
repo: openfga/cli
cache: enable
- name: Install jq
uses: dcarbone/install-jq-action@v2
- name: Create store with model
id: 'store'
run: |
fga store create --model ./example/model_with_conditions.fga > store_response.json
cat store_response.json
store_id=$(jq -r '.store.id' store_response.json)
echo "store_id=${store_id}" >> $GITHUB_OUTPUT
- name: Run OpenFGA CLI Tests
id: 'tests'
uses: ./
continue-on-error: true
with:
test_path: ./example/model_with_conditions.fga.yaml
fga_server_url: 'http://localhost:8080'
fga_server_store_id: ${{ steps.store.outputs.store_id }}
- name: Assert expected results
run: |
if [ "${{ matrix.test.conditions_supported }}" == "true" ] && [ "${{ steps.tests.outcome }}" == "failure" ]
then
echo "${{ matrix.test.openfga_tag }} is expected to support conditions but tests failed"
exit 1
fi
if [ "${{ matrix.test.conditions_supported }}" == "false" ] && [ "${{ steps.tests.outcome }}" == "success" ]
then
echo "${{ matrix.test.openfga_tag }} is expected to not support conditions but tests passed"
exit 1
fi
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@


# IntelliJ IDEA
.idea
*.iml
74 changes: 67 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,23 @@
# OpenFGA Github Action - Test
[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fopenfga%2Faction-openfga-test.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2Fopenfga%2Faction-openfga-test?ref=badge_shield)

[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fopenfga%2Faction-openfga-test.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2Fopenfga%2Faction-openfga-test?ref=badge_shield)

This action can be used to test your authorization model using store test files.

## Parameter

| Parameter | Description | Required | Default |
|----------------------|----------------------------------------------------------------------------------|----------|--------------|
| `test_path` | The path to your store test file or folder relative to the root of your project. | No | `.` |
| `test_files_pattern` | The pattern to match test files. | No | `*.fga.yaml` |
| Parameter | Description | Required | Default |
|-----------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------|--------------|
| `test_path` | The path to your store test file or folder relative to the root of your project. | No | `.` |
| `test_files_pattern` | The pattern to match test files. | No | `*.fga.yaml` |
| `fga_server_url` | The OpenFGA server to test the Authorization Model against. If empty (which is the default value), the tests are run using the cli built-in OpenFGA instance. If specified, it is mandatory to specify the store id with the `fga_server_store_id` input, also the `model` and `model_file` entries of the tests are ignored | No | _empty_ |
| `fga_server_store_id` | The OpenFGA server store id. Must be provided if fga_server_url is configured. | No | _empty_ |
| `fga_api_token` | The api token to use for testing against an OpenFGA server. Ignored if `fga_server_url` is not provided. | No | _empty_ |

> Note: the action will fail if no test is found in the specified test path with the given pattern

## Examples


### Running tests of `*.fga.yaml` files present in the repository

```yaml
Expand Down Expand Up @@ -69,6 +70,65 @@ jobs:
test_path: example/model.fga.yaml
```

### Running tests against a given version of OpenFGA

```yaml
name: Test Action
on:
workflow_dispatch:
jobs:
test:
name: Run test
runs-on: ubuntu-latest
services:
postgres:
image: postgres:14
env:
POSTGRES_USER: openfga
POSTGRES_PASSWORD: '1234'
ports:
- 5432:5432
options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
env:
OPENFGA_DATASTORE_ENGINE: 'postgres'
OPENFGA_DATASTORE_URI: 'postgres://openfga:[email protected]:5432/openfga'
OPENFGA_LOG_LEVEL: debug
steps:
- name: Install OpenFGA server v1.5.3
uses: jaxxstorm/[email protected]
with:
repo: openfga/openfga
tag: v1.5.3
cache: enable
- name: Migrate OpenFGA database
shell: bash
run: openfga migrate
- name: Start OpenFGA server in background
shell: bash
run: openfga run &
- name: Install OpenFGA cli
uses: jaxxstorm/[email protected]
with:
repo: openfga/cli
cache: enable
- name: Install jq
uses: dcarbone/install-jq-action@v2
- name: Create store with model
id: 'store'
run: |
fga store create --model ./example/model_with_conditions.fga > store_response.json
cat store_response.json
store_id= $(jq -r '.store.id' store_response.json)
echo "store_id=${store_id}" >> $GITHUB_OUTPUT
- name: Run tests
uses: openfga/[email protected]
with:
fga_server_url: 'http://localhost:8080'
fga_server_store_id: ${{ steps.store.outputs.store_id }}
```

## License

[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fopenfga%2Faction-openfga-test.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2Fopenfga%2Faction-openfga-test?ref=badge_large)
49 changes: 40 additions & 9 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,19 @@ inputs:
description: 'Pattern to match the test files'
required: false
default: '*.fga.yaml'
fga_server_url:
description: 'The OpenFGA server to test the Authorization Model against. If not provided, the tests will be run using the cli built-in OpenFGA instance.'
required: false
default: ''
fga_server_store_id:
description: 'The OpenFGA server store id. Must be provided if fga_server_url is configured.'
required: false
default: ''
fga_api_token:
description: 'The api token to use for testing against an OpenFGA server. Ignored if fga_server_url is not provided.'
required: false
default: ''


runs:
using: composite
Expand All @@ -22,17 +35,35 @@ runs:
with:
repo: openfga/cli
cache: enable
- uses: chrisdickinson/[email protected]
with:
yq-version: v4.25.3
- name: Run OpenFGA CLI
shell: bash
run: |
while IFS= read -r -d '' test_file
do
((test_files_count+=1))
while IFS= read -r -d '' test_file
do
((test_files_count+=1))
if [[ -z "${{ inputs.fga_server_url }}" ]]; then
echo "Running FGA test file ${test_file}"
fga model test --tests "${test_file}"
done < <(find ${{ inputs.test_path }} -name "${{ inputs.test_files_pattern }}" -print0)
if [[ ${test_files_count} -eq 0 ]]; then
echo "No FGA test file found for path '${{ inputs.test_path }}' and pattern '${{ inputs.test_files_pattern }}'"
exit 1
fi
else
echo "Running FGA test file ${test_file} against OpenFGA server ${{ inputs.fga_server_url }}"
fga_token="${{ inputs.fga_api_token }}"
test_file_without_model=mktemp
yq 'del(.model_file, .model)' ${test_file} > ${test_file_without_model}
fga model test \
${fga_server_opts} \
--api-url "${{ inputs.fga_server_url }}" \
--store-id "${{ inputs.fga_server_store_id }}" \
${fga_token:+--api-token ${fga_token}} \
--tests "${test_file_without_model}"
fi
done < <(find ${{ inputs.test_path }} -name "${{ inputs.test_files_pattern }}" -print0)
if [[ ${test_files_count} -eq 0 ]]; then
echo "No FGA test file found for path '${{ inputs.test_path }}' and pattern '${{ inputs.test_files_pattern }}'"
exit 1
fi
12 changes: 12 additions & 0 deletions example/model_with_conditions.fga
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
model
schema 1.1

type user

type document
relations
define viewer: [user, user with non_expired_grant]

condition non_expired_grant(current_time: timestamp, grant_time: timestamp, grant_duration: duration) {
current_time < grant_time + grant_duration
}
64 changes: 64 additions & 0 deletions example/model_with_conditions.fga.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
name: FolderBox with temporal accesses # store name
model_file: ./model_with_conditions.fga

tuples:
- user: user:bob
relation: viewer
object: document:1

- user: user:anne
relation: viewer
object: document:1
condition:
name: non_expired_grant
context:
grant_time : "2023-01-01T00:00:00Z"
grant_duration : 1h

- user: user:anne
relation: viewer
object: document:2
condition:
name: non_expired_grant
context:
grant_time : "2023-01-01T00:00:00Z"
grant_duration : 5s

tests:
- name: Test temporal access
check:
- user: user:anne
object: document:1
context:
current_time: "2023-01-01T00:10:00Z"
assertions:
viewer: true

- user: user:anne
object: document:1
context:
current_time: "2023-01-01T02:00:00Z"
assertions:
viewer: false

- user: user:anne
object: document:2
context:
current_time: "2023-01-01T00:00:09Z"
assertions:
viewer: false

- user: user:bob
object: document:1
assertions:
viewer: true

list_objects:
- user: user:anne
type: document
context:
current_time: "2023-01-01T00:00:01Z"
assertions:
viewer:
- document:1
- document:2

0 comments on commit 21b4215

Please sign in to comment.