diff --git a/README.md b/README.md index 8d72c86..a757d2b 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ Ruek lean on well known API design principals to provide an authorization servic integrate, quick to master and flexible enough to handle complex requirements. -## Features +## 🔥 Features * ABAC, RBAC & ReBAC * Schema-less fine-grained authorization (FGA) @@ -42,180 +42,34 @@ integrate, quick to master and flexible enough to handle complex requirements. * Built using the fastest gRPC server implementation[^5] -## Documentation +## 📜 Documentation You can find a bit more detailed documentation in [docs/](docs/README.md). -## Getting started +## 🚀 Quickstart (with `docker`) -### Prerequisites - -* [CMake](https://cmake.org) (>= 3.23) -* [Protobuf](https://protobuf.dev) (>= 3.15) -* [libpq](https://www.postgresql.org/docs/current/libpq.html) -* [PostgreSQL](https://www.postgresql.org) (or [PostgreSQL protocol](https://www.postgresql.org/docs/current/protocol.html) compatible server) - -### Compiling - -``` -❯ cmake -B .build -G Ninja \ - -DCMAKE_BUILD_TYPE=Release \ - -DPostgreSQL_ADDITIONAL_VERSIONS=16 \ - -Druek_ENABLE_COVERAGE=OFF -``` - -``` -❯ cmake --build .build --target ruek +### Create a docker network +```sh +docker network create ruek-net ``` -### Setting-up - +### Run PostgreSQL +```sh +docker run --net=ruek-net --name=pg -e POSTGRES_PASSWORD=postgres -d postgres:16-alpine ``` -❯ psql --dbname=postgres -psql (16.1) -Type "help" for help. - -postgres=# create user ruek; -CREATE ROLE -postgres=# create database ruek owner ruek; -CREATE DATABASE -``` - -``` -❯ psql --username=ruek --dbname=ruek < db/schema.sql -``` - -### Running - -``` -❯ PGDATABASE=ruek PGUSER=ruek ./.build/bin/ruek -Listening on [127.0.0.1:8080] ... -``` - - -## Usage - -### Creating a user +### Setup PostgreSQL user and database for Ruek +```sh +echo "create user ruek with password 'ruek'; create database ruek owner ruek;" | docker run --rm -i --network=ruek-net -e PGPASSWORD=postgres postgres:16-alpine psql --host=pg --username=postgres ``` -❯ grpcurl \ - -import-path proto \ - -import-path ./.build/_deps/googleapis-src \ - -proto proto/ruek/api/v1/principals.proto \ - -plaintext \ - localhost:8080 ruek.api.v1.Principals/Create - -{ - "id": "cn7qtdu56a1cqrj8kur0" -} +```sh +curl -sL https://raw.githubusercontent.com/uatuko/ruek/refs/heads/main/db/schema.sql | docker run --rm -i --network=ruek-net -e PGPASSWORD=ruek postgres:16-alpine psql --host=pg --username=ruek --dbname=ruek ``` -### Granting access - -``` -❯ grpcurl \ - -import-path proto \ - -import-path ./.build/_deps/googleapis-src \ - -proto proto/ruek/api/v1/authz.proto \ - -plaintext \ - -d '{ - "principal_id": "cn7qtdu56a1cqrj8kur0", - "entity_type": "documents", - "entity_id": "65bd28aaa076ee8c8463cff8" - }' \ - localhost:8080 ruek.api.v1.Authz/Grant - -{} -``` - -### Checking access - -``` -❯ grpcurl \ - -import-path proto \ - -import-path ./.build/_deps/googleapis-src \ - -proto proto/ruek/api/v1/authz.proto \ - -plaintext \ - -d '{ - "principal_id": "cn7qtdu56a1cqrj8kur0", - "entity_type": "documents", - "entity_id": "65bd28aaa076ee8c8463cff8" - }' \ - localhost:8080 ruek.api.v1.Authz/Check - -{ - "ok": true -} -``` - -### Listing users - -``` -❯ grpcurl \ - -import-path proto \ - -import-path ./.build/_deps/googleapis-src \ - -proto proto/ruek/api/v1/principals.proto \ - -plaintext \ - localhost:8080 ruek.api.v1.Principals/List - -{ - "principals": [ - { - "id": "cn7qtim56a1cqrj8kurg" - }, - { - "id": "cn7qtdu56a1cqrj8kur0" - } - ] -} -``` - -### Listing entities a user can access - -``` -❯ grpcurl \ - -import-path proto \ - -import-path ./.build/_deps/googleapis-src \ - -proto proto/ruek/api/v1/entities.proto \ - -plaintext \ - -d '{ - "principal_id": "cn7qtdu56a1cqrj8kur0", - "entity_type": "documents" - }' \ - localhost:8080 ruek.api.v1.Entities/List - -{ - "entities": [ - { - "id": "65bd28aaa076ee8c8463cff8", - "type": "documents" - } - ] -} -``` - -### Listing users that has access to an entity - -``` -❯ grpcurl \ - -import-path proto \ - -import-path ./.build/_deps/googleapis-src \ - -proto proto/ruek/api/v1/entities.proto \ - -plaintext \ - -d '{ - "entity_type": "documents", - "entity_id": "65bd28aaa076ee8c8463cff8" - }' \ - localhost:8080 ruek.api.v1.Entities/ListPrincipals - -{ - "principals": [ - { - "id": "cn7qtdu56a1cqrj8kur0" - } - ] -} +### Run Ruek +```sh +docker run --network=ruek-net --name=ruek -e PGHOST=pg -e PGUSER=ruek -e PGPASSWORD=ruek -p 8080:8080 -d uatuko/ruek:latest ``` diff --git a/docs/README.md b/docs/README.md index ba3c61d..84f3f4a 100644 --- a/docs/README.md +++ b/docs/README.md @@ -2,5 +2,96 @@ ## Table of contents +* [Getting started](#getting-started) * [API Documentation](api/README.md) * [ReBAC](rebac.md) + + +## Getting started + +### Prerequisites + +Ruek require [PostgreSQL](https://www.postgresql.org) (or [PostgreSQL protocol](https://www.postgresql.org/docs/current/protocol.html) compatible server) to run. + +
+Example - setting up PostgreSQL in docker + +```sh +# create a docker network to connect postgres and ruek containers +docker network create ruek-net + +# run postgres in the 'ruek-net' network +docker run --net=ruek-net --name=pg -e POSTGRES_PASSWORD=postgres -d postgres:16-alpine + +# wait until postgres starts up +while ! $(docker run --rm --network=ruek-net postgres:16-alpine pg_isready --host=pg | grep -q 'accepting connections'); do sleep 1; done + +# setup postgres user and db for ruek +echo "create user ruek with password 'ruek'; create database ruek owner ruek;" | docker run --rm -i --network=ruek-net -e PGPASSWORD=postgres postgres:16-alpine psql --host=pg --username=postgres + +# initialize ruek db +curl -sL https://raw.githubusercontent.com/uatuko/ruek/refs/heads/main/db/schema.sql | docker run --rm -i --network=ruek-net -e PGPASSWORD=ruek postgres:16-alpine psql --host=pg --username=ruek --dbname=ruek +``` +
+ +### Using pre-built containers + +The quickest way to run Ruek is by using pre-built containers. There are `linux/amd64` and `linux/arm64` containers published to [`docker.io/uatuko/ruek`](https://hub.docker.com/r/uatuko/ruek) and [`ghcr.io/uatuko/ruek`](https://github.com/uatuko/ruek/pkgs/container/ruek). + +> [!IMPORTANT] +> In the following example, Ruek is connecting to a PostgreSQL server running on host `pg` using the username `ruek` and password `ruek`. If you are running PostgreSQL in docker, you probably will need to specify the `--network` option to connect to a container network (e.g. `--network=ruek-net`) + +e.g. +```sh +docker run --name=ruek -e PGHOST=pg -e PGUSER=ruek -e PGPASSWORD=ruek -p 8080:8080 -d uatuko/ruek:latest +``` + +### Compiling from source + +#### Prerequisites + +* [CMake](https://cmake.org) (>= 3.23) +* [Protobuf](https://protobuf.dev) (>= 3.15) +* [libpq](https://www.postgresql.org/docs/current/libpq.html) + +#### Build with CMake + +> [!NOTE] +> The following should result in a Ruek executable at `.build/bin/ruek`. + +```sh +# generate build files +cmake -B .build \ + -DCMAKE_BUILD_TYPE=Release \ + -DPostgreSQL_ADDITIONAL_VERSIONS=16 \ + -DRUEK_ENABLE_COVERAGE=OFF \ + -DRUEK_BUILD_TESTING=OFF + +# compile +cmake --build .build --target ruek +``` + + +### Setting-up PostgreSQL + +``` +❯ psql --dbname=postgres +psql (16.1) +Type "help" for help. + +postgres=# create user ruek; +CREATE ROLE +postgres=# create database ruek owner ruek; +CREATE DATABASE +``` + +``` +❯ psql --username=ruek --dbname=ruek < db/schema.sql +``` + +### Running + +``` +❯ PGDATABASE=ruek PGUSER=ruek ./.build/bin/ruek +Listening on [127.0.0.1:8080] ... +``` diff --git a/docs/api/v1/relations.md b/docs/api/v1/relations.md index 890fa0f..bc39e93 100644 --- a/docs/api/v1/relations.md +++ b/docs/api/v1/relations.md @@ -186,7 +186,7 @@ rpc ListRight(RelationsListRightRequest) returns (RelationsListRightResponse) { | `right` | (oneof) | | | [ `right` ] right_entity | [`Entity`](#entity) | | | [ `right` ] right_principal_id | `string` | | -| strategy | (optional) `uint32` | Lookup strategy to use (default `2`). See [lookup strategies](#a1---lookup-strategies). | +| strategy | (optional) `uint32` | Lookup strategy to use (default `2`). See [lookup strategies](#a1-lookup-strategies). | | cost_limit | (optional) `uint32` | A value between `1` and `65535` to limit the lookup cost (default `1000`). | ### RelationsCheckResponse diff --git a/docs/rebac.md b/docs/rebac.md index 572ef7f..08c8523 100644 --- a/docs/rebac.md +++ b/docs/rebac.md @@ -61,7 +61,8 @@ To derive the relation `[]user:jane/reader/doc:notes.txt` using a BFS[^bfs] grap (which has **O(v+e)** complexity), we will need to read 10,003 tuples. This can be really slow depending on DB load and number of concurrent requests. -> 💡 This is only an illustrative example. In reality, Ruek traverse the relations graphs from right +> [!TIP] +> This is only an illustrative example. In reality, Ruek traverse the relations graphs from right > to left which will result in only 3 reads in this instance. ![Relations Graph #02](./assets/rebac-relations-graph-02.svg) @@ -71,7 +72,8 @@ strategies to suite different shapes of relations graphs. ### Direct -> 💡 Best for reads (**O(1)**), _can be_ worst for writes (**O(1+l+r)**). +> [!TIP] +> Best for reads (**O(1)**), _can be_ worst for writes (**O(1+l+r)**). _Direct_ strategy optimise for **O(1)** relations checks at the expense of computing and storing derived relations during creation. @@ -88,7 +90,8 @@ the relations graph and compute and store the derived tuple `t2-1`. This ensures ### Graph -> 💡 Best for writes (**O(1)**), _can be_ worst for reads (**O(1+v+e)**). +> [!TIP] +> Best for writes (**O(1)**), _can be_ worst for reads (**O(1+v+e)**). _Graph_ strategy does not perform any additional computations when creating relations resulting in **O(1)** writes. When checking relations, if a direct relation does not exists Ruek will use a graph traversal @@ -97,7 +100,8 @@ of the relations graph. ### Set -> 💡 A balance between reads and writes (**O(1+n+m)**), best for large datasets. +> [!TIP] +> A balance between reads and writes (**O(1+n+m)**), best for large datasets. _Set_ strategy require relations to be defined between principals (e.g. users, groups) and entities. When creating relations, Ruek will analyse the relations graph and compute and store derived relations