diff --git a/README.md b/README.md
index 0443b87..f95a76e 100644
--- a/README.md
+++ b/README.md
@@ -43,7 +43,7 @@ Another cool feature of custom extension is its capability to discover the OpenF
2. Execute following Docker Compose command to start the deployment
```sh
- docker-compose -f docker-compose.yml -f docker-compose-apps.yml -f docker-compose-openfga.yml up
+ docker-compose -f docker-compose.yml -f docker-compose-apps.yml -f docker-compose-openfga.yml -f docker-compose-import.yml up
```
3. To be able to use this environment, you need to add this line to your local HOSTS file:
@@ -62,43 +62,31 @@ Another cool feature of custom extension is its capability to discover the OpenF
| Store API | http://store-api:9091 | | Custom image |
-## Post configuration steps
-### OpenFGA
-1. Import the [OpenFGA authorization schema for Keycloak](openfga/keycloak-authorization-model.json):
- ```bash
- cd openfga
- ./import.sh
- ```
-2. As the result you will see the following OpenFGA Authorization Model in the [OpenFGA Playground Console](http://localhost:8080/playground) :
+## Review configuration (optional)
- ![openfga-keycloak-authorization-model](doc/images/openfga-authz-model.png)
+>
+> In this new version of the workshop, we automatically import all the required configurations into the Keycloak and OpenFGA platforms 😄 🪄
+>
+### Keycloak Platform
+- You will find that the OpenFGA Event Listener 'openfga-events-publisher' extension in Keycloak is enabled.
-### Keycloak
-1. Enable the Keycloak OpenFGA Event Listener extension in Keycloak:
-
- * Open [administration console](http://keycloak:8081)
- * Choose realm
- * Realm settings
- * Select `Events` tab and add `openfga-events-publisher` to Event Listeners.
+ * [Administration console](http://keycloak:8081) > Realm settings > `openfga-events-publisher`
-2. Proceed to initialize the PoC:
-
- Execute the following [script](keycloak/initialize-poc.sh) to initialize the PoC:
-
- ```bash
- docker exec keycloak /bin/bash /opt/keycloak/initialize-poc.sh
- ```
-
- This script will create the OAuth Clients and the following Users and Role Model:
+- The following roles and demo users have already been created in Keycloak.
![users](doc/images/users.png)
The password for all the users is `demo1234!`
- Once these steps are finished, the Keycloak OpenFGA Event Publisher extension has proceed to send these events over HTTP to the OpenFGA solution. Here, are all tuples stored.
+### OpenFGA Platform
+- You will see the following OpenFGA Authorization Model in the [OpenFGA Playground Console](http://localhost:3000/playground) and the Tuples tab:
+
+
+
+- Once the workshop is deployed, the Keycloak OpenFGA Event Publisher extension proceeds to send these events over HTTP to the OpenFGA solution. Here, all tuples are stored.
| User | Relation | Object |
| ------------------------- |:-----------------------------:|:---------------------:|
@@ -109,16 +97,11 @@ Another cool feature of custom extension is its capability to discover the OpenF
| user:richard | assignee | role:admin-catalog |
- The users are identified by the value of the claim sub in the [OpenFGA Playground](http://localhost:3000/playground), see the Tuples tab:
-
-
-
-
-3. Restart the apps (containers: `store` and `store-api`)
+ The users are identified by the value of the claim sub.
## Test cases
As an example, we will implement an Product Catalog web application that has the following requirements:
-* Only authenticated user with MFA can access to the application
+* Only authenticated user can access to the application
* Product can be viewed by their Analyst
* Product can be edited by their Admin
* Global Admin users can view or edit any Product
diff --git a/docker-compose-import.yml b/docker-compose-import.yml
new file mode 100644
index 0000000..8c94fd0
--- /dev/null
+++ b/docker-compose-import.yml
@@ -0,0 +1,38 @@
+version: '3.8'
+
+services:
+ openfga-import:
+ depends_on:
+ openfga:
+ condition: service_healthy
+ image: openfga/cli:v0.2.0
+ container_name: openfga-import
+ restart: "no"
+ command: "store create --name keycloak --api-url http://openfga:8080 --model /tmp/model.dsl"
+ networks:
+ - default
+ volumes:
+ - $PWD/openfga:/tmp
+ keycloak-import:
+ depends_on:
+ openfga:
+ condition: service_healthy
+ keycloak:
+ condition: service_healthy
+ openfga-import:
+ condition: service_completed_successfully
+ image: quay.io/keycloak/keycloak:21.1
+ container_name: keycloak-import
+ restart: "no"
+ entrypoint: [
+ "sh",
+ "-c",
+ "echo 'Waiting 10 secs for importing Keycloak configuration...';sleep 10;/opt/keycloak/import.sh"
+ ]
+ environment:
+ KEYCLOAK_URL: http://keycloak:8081
+ KEYCLOAK_USER: admin
+ KEYCLOAK_PASSWORD: password
+ volumes:
+ - $PWD/keycloak/initialize-poc.sh:/opt/keycloak/import.sh
+
\ No newline at end of file
diff --git a/docker-compose-openfga.yml b/docker-compose-openfga.yml
index d945f07..8e638fe 100644
--- a/docker-compose-openfga.yml
+++ b/docker-compose-openfga.yml
@@ -46,4 +46,9 @@ services:
- default
ports:
- "8080:8080" #http
- - "3000:3000" #playground
\ No newline at end of file
+ - "3000:3000" #playground
+ healthcheck:
+ test: ["CMD", "/usr/local/bin/grpc_health_probe", "-addr=openfga:8081"]
+ interval: 3s
+ timeout: 30s
+ retries: 3
\ No newline at end of file
diff --git a/keycloak/initialize-poc.sh b/keycloak/initialize-poc.sh
old mode 100644
new mode 100755
index 94ea84a..15085a0
--- a/keycloak/initialize-poc.sh
+++ b/keycloak/initialize-poc.sh
@@ -2,7 +2,13 @@
echo "Creating PoC Users, Role Model, User Role Assigments and Clients"
-/opt/keycloak/bin/kcadm.sh config credentials --server http://localhost:8081 --realm master --user $KEYCLOAK_USER --password $KEYCLOAK_PASSWORD
+/opt/keycloak/bin/kcadm.sh config credentials --server $KEYCLOAK_URL --realm master --user $KEYCLOAK_USER --password $KEYCLOAK_PASSWORD
+
+# Enable openfga-events
+/opt/keycloak/bin/kcadm.sh update events/config -s 'eventsListeners=["openfga-events-publisher","jboss-logging"]'
+
+# Clients
+/opt/keycloak/bin/kcadm.sh create clients -r master -s clientId=portal -s publicClient=true -s 'redirectUris=["http://store:9090/callback"]' -s 'webOrigins=["http://store:9090"]' -s 'attributes={ "post.logout.redirect.uris": "http://store:9090/home?action=logout", "access.token.lifespan": 3600}' -o
# Users
/opt/keycloak/bin/kcadm.sh create users -r master -s username=paula -s firstName=Paula -s lastName=Von -s enabled=true -s email=paula@demo.com
@@ -25,8 +31,3 @@ echo "Creating PoC Users, Role Model, User Role Assigments and Clients"
/opt/keycloak/bin/kcadm.sh add-roles -r master --uusername paula --rolename analyst-catalog
/opt/keycloak/bin/kcadm.sh add-roles -r master --uusername richard --rolename admin-catalog
-
-# Clients
-/opt/keycloak/bin/kcadm.sh create clients -r master -s clientId=portal -s publicClient=true -s 'redirectUris=["http://store:9090/callback"]' -s 'webOrigins=["http://store:9090"]' -s 'attributes={ "post.logout.redirect.uris": "http://store:9090/home?action=logout", "access.token.lifespan": 3600}' -o
-
-
diff --git a/openfga/import.sh b/openfga/import.sh
deleted file mode 100755
index b5d79cf..0000000
--- a/openfga/import.sh
+++ /dev/null
@@ -1,23 +0,0 @@
-#!/bin/bash
-#
-# Create store and authorization model in OpenFGA
-# Version: 1.0.0
-
-OPENFGA_API_URI=${OPENFGA_API_URI:-http://localhost:8080}
-OPENFGA_STORE_ID=""
-OPENFGA_AUTHORIZATION_MODEL_ID=""
-
-create_store() {
- OPENFGA_STORE_ID=$(curl -X POST $OPENFGA_API_URI/stores -d @store.json | jq -r '.id')
-}
-
-create_authorization_model() {
- OPENFGA_AUTHORIZATION_MODEL_ID=$(curl -X POST $OPENFGA_API_URI/stores/$OPENFGA_STORE_ID/authorization-models -d @keycloak-authorization-model.json | jq -r '.authorization_model_id')
-}
-
-
-create_store
-echo "OpenFGA store id: " + $OPENFGA_STORE_ID
-
-create_authorization_model
-echo "OpenFGA authorization model id: " + $OPENFGA_AUTHORIZATION_MODEL_ID
\ No newline at end of file
diff --git a/openfga/keycloak-authorization-model.json b/openfga/keycloak-authorization-model.json
deleted file mode 100644
index 7548ef0..0000000
--- a/openfga/keycloak-authorization-model.json
+++ /dev/null
@@ -1,98 +0,0 @@
-{
- "type_definitions": [
- {
- "type": "group",
- "relations": {
- "assignee": {
- "this": {}
- }
- },
- "metadata": {
- "relations": {
- "assignee": {
- "directly_related_user_types": [
- {
- "type": "user"
- }
- ]
- }
- }
- }
- },
- {
- "type": "role",
- "relations": {
- "assignee": {
- "union": {
- "child": [
- {
- "this": {}
- },
- {
- "tupleToUserset": {
- "tupleset": {
- "object": "",
- "relation": "parent"
- },
- "computedUserset": {
- "object": "",
- "relation": "assignee"
- }
- }
- },
- {
- "tupleToUserset": {
- "tupleset": {
- "object": "",
- "relation": "parent_group"
- },
- "computedUserset": {
- "object": "",
- "relation": "assignee"
- }
- }
- }
- ]
- }
- },
- "parent": {
- "this": {}
- },
- "parent_group": {
- "this": {}
- }
- },
- "metadata": {
- "relations": {
- "assignee": {
- "directly_related_user_types": [
- {
- "type": "user"
- }
- ]
- },
- "parent": {
- "directly_related_user_types": [
- {
- "type": "role"
- }
- ]
- },
- "parent_group": {
- "directly_related_user_types": [
- {
- "type": "group"
- }
- ]
- }
- }
- }
- },
- {
- "type": "user",
- "relations": {},
- "metadata": null
- }
- ],
- "schema_version": "1.1"
-}
\ No newline at end of file
diff --git a/openfga/model.dsl b/openfga/model.dsl
new file mode 100644
index 0000000..a8f2a92
--- /dev/null
+++ b/openfga/model.dsl
@@ -0,0 +1,11 @@
+model
+ schema 1.1
+type group
+ relations
+ define assignee: [user]
+type role
+ relations
+ define assignee: [user] or assignee from parent or assignee from parent_group
+ define parent: [role]
+ define parent_group: [group]
+type user
\ No newline at end of file
diff --git a/store-oidc-app/vue.config.js b/store-oidc-app/vue.config.js
index c1850f5..79fa048 100644
--- a/store-oidc-app/vue.config.js
+++ b/store-oidc-app/vue.config.js
@@ -1,5 +1,6 @@
module.exports = {
devServer: {
- disableHostCheck: true
+ disableHostCheck: true,
+ progress: false
}
}
\ No newline at end of file