This is an automated email from the ASF dual-hosted git repository.

ricardozanini pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-kie-kogito-docs.git


The following commit(s) were added to refs/heads/main by this push:
     new 9a25a3f2f KIE-ISSUES 1056 - Introduce AuthZ Guide for SonataFlow 
Deployments (#614)
9a25a3f2f is described below

commit 9a25a3f2f99aee33e1efa1eaa9bf5e43df1cbadb
Author: Ricardo Zanini <[email protected]>
AuthorDate: Thu Apr 18 10:33:48 2024 -0300

    KIE-ISSUES 1056 - Introduce AuthZ Guide for SonataFlow Deployments (#614)
---
 .../cloud/apisix-keycloak/01-create-realm.png      | Bin 0 -> 49363 bytes
 .../cloud/apisix-keycloak/02-create-client.png     | Bin 0 -> 48371 bytes
 .../cloud/apisix-keycloak/03-create-client.png     | Bin 0 -> 60630 bytes
 .../apisix-keycloak/04-client-credentials.png      | Bin 0 -> 62142 bytes
 .../cloud/apisix-keycloak/05-create-user.png       | Bin 0 -> 51906 bytes
 .../cloud/apisix-keycloak/06-user-set-password.png | Bin 0 -> 49251 bytes
 .../SonataFlow-Apisix-Keycloak.drawio              |  52 ++++
 .../apisix-keycloak/ingress-apisix-keycloak.png    | Bin 0 -> 25544 bytes
 serverlessworkflow/modules/ROOT/nav.adoc           |   1 +
 .../ROOT/pages/cloud/custom-ingress-authz.adoc     | 340 +++++++++++++++++++++
 .../modules/ROOT/pages/cloud/index.adoc            |  10 +
 11 files changed, 403 insertions(+)

diff --git 
a/serverlessworkflow/modules/ROOT/assets/images/cloud/apisix-keycloak/01-create-realm.png
 
b/serverlessworkflow/modules/ROOT/assets/images/cloud/apisix-keycloak/01-create-realm.png
new file mode 100644
index 000000000..86fd0051e
Binary files /dev/null and 
b/serverlessworkflow/modules/ROOT/assets/images/cloud/apisix-keycloak/01-create-realm.png
 differ
diff --git 
a/serverlessworkflow/modules/ROOT/assets/images/cloud/apisix-keycloak/02-create-client.png
 
b/serverlessworkflow/modules/ROOT/assets/images/cloud/apisix-keycloak/02-create-client.png
new file mode 100644
index 000000000..26879f4fc
Binary files /dev/null and 
b/serverlessworkflow/modules/ROOT/assets/images/cloud/apisix-keycloak/02-create-client.png
 differ
diff --git 
a/serverlessworkflow/modules/ROOT/assets/images/cloud/apisix-keycloak/03-create-client.png
 
b/serverlessworkflow/modules/ROOT/assets/images/cloud/apisix-keycloak/03-create-client.png
new file mode 100644
index 000000000..4b67a12b5
Binary files /dev/null and 
b/serverlessworkflow/modules/ROOT/assets/images/cloud/apisix-keycloak/03-create-client.png
 differ
diff --git 
a/serverlessworkflow/modules/ROOT/assets/images/cloud/apisix-keycloak/04-client-credentials.png
 
b/serverlessworkflow/modules/ROOT/assets/images/cloud/apisix-keycloak/04-client-credentials.png
new file mode 100644
index 000000000..a962604d1
Binary files /dev/null and 
b/serverlessworkflow/modules/ROOT/assets/images/cloud/apisix-keycloak/04-client-credentials.png
 differ
diff --git 
a/serverlessworkflow/modules/ROOT/assets/images/cloud/apisix-keycloak/05-create-user.png
 
b/serverlessworkflow/modules/ROOT/assets/images/cloud/apisix-keycloak/05-create-user.png
new file mode 100644
index 000000000..0ee5cccff
Binary files /dev/null and 
b/serverlessworkflow/modules/ROOT/assets/images/cloud/apisix-keycloak/05-create-user.png
 differ
diff --git 
a/serverlessworkflow/modules/ROOT/assets/images/cloud/apisix-keycloak/06-user-set-password.png
 
b/serverlessworkflow/modules/ROOT/assets/images/cloud/apisix-keycloak/06-user-set-password.png
new file mode 100644
index 000000000..7ff329cb3
Binary files /dev/null and 
b/serverlessworkflow/modules/ROOT/assets/images/cloud/apisix-keycloak/06-user-set-password.png
 differ
diff --git 
a/serverlessworkflow/modules/ROOT/assets/images/cloud/apisix-keycloak/SonataFlow-Apisix-Keycloak.drawio
 
b/serverlessworkflow/modules/ROOT/assets/images/cloud/apisix-keycloak/SonataFlow-Apisix-Keycloak.drawio
new file mode 100644
index 000000000..1d178d428
--- /dev/null
+++ 
b/serverlessworkflow/modules/ROOT/assets/images/cloud/apisix-keycloak/SonataFlow-Apisix-Keycloak.drawio
@@ -0,0 +1,52 @@
+<mxfile host="app.diagrams.net" modified="2024-04-05T20:27:34.957Z" 
agent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 
(KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36" etag="3HWgvx48M6thK74tnyBa" 
version="24.2.2" type="google">
+  <diagram name="Página-1" id="CqzFufLg_pr2HWkyKqtd">
+    <mxGraphModel grid="1" page="1" gridSize="10" guides="1" tooltips="1" 
connect="1" arrows="1" fold="1" pageScale="1" pageWidth="1169" pageHeight="827" 
math="0" shadow="0">
+      <root>
+        <mxCell id="0" />
+        <mxCell id="1" parent="0" />
+        <mxCell id="vT6yfp5O44col5OBctIR-5" 
style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;"
 edge="1" parent="1" source="vT6yfp5O44col5OBctIR-1" 
target="vT6yfp5O44col5OBctIR-4">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="vT6yfp5O44col5OBctIR-1" value="User" 
style="shape=umlActor;verticalLabelPosition=bottom;verticalAlign=top;html=1;outlineConnect=0;"
 vertex="1" parent="1">
+          <mxGeometry x="70" y="180" width="30" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="vT6yfp5O44col5OBctIR-10" 
style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.25;exitDx=0;exitDy=0;entryX=0;entryY=0.25;entryDx=0;entryDy=0;"
 edge="1" parent="1" source="vT6yfp5O44col5OBctIR-4" 
target="vT6yfp5O44col5OBctIR-6">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="vT6yfp5O44col5OBctIR-14" 
style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;"
 edge="1" parent="1" source="vT6yfp5O44col5OBctIR-4" 
target="vT6yfp5O44col5OBctIR-13">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="vT6yfp5O44col5OBctIR-4" value="APISIX Ingress" 
style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="190" y="180" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="vT6yfp5O44col5OBctIR-8" 
style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;entryPerimeter=0;"
 edge="1" parent="1" source="vT6yfp5O44col5OBctIR-6" 
target="vT6yfp5O44col5OBctIR-7">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="vT6yfp5O44col5OBctIR-12" 
style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.75;exitDx=0;exitDy=0;entryX=1;entryY=0.75;entryDx=0;entryDy=0;"
 edge="1" parent="1" source="vT6yfp5O44col5OBctIR-6" 
target="vT6yfp5O44col5OBctIR-4">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="vT6yfp5O44col5OBctIR-6" value="Keycloak" 
style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="420" y="180" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="vT6yfp5O44col5OBctIR-7" value="PostgreSQL" 
style="shape=cylinder3;whiteSpace=wrap;html=1;boundedLbl=1;backgroundOutline=1;size=15;"
 vertex="1" parent="1">
+          <mxGeometry x="590" y="170" width="80" height="80" as="geometry" />
+        </mxCell>
+        <mxCell id="vT6yfp5O44col5OBctIR-13" value="Workflow Application" 
style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="190" y="300" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="vT6yfp5O44col5OBctIR-15" value="1" 
style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;fillColor=#D4E1F5;" 
vertex="1" parent="1">
+          <mxGeometry x="140" y="180" width="20" height="20" as="geometry" />
+        </mxCell>
+        <mxCell id="vT6yfp5O44col5OBctIR-16" value="2" 
style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;fillColor=#D4E1F5;" 
vertex="1" parent="1">
+          <mxGeometry x="350" y="170" width="20" height="20" as="geometry" />
+        </mxCell>
+        <mxCell id="vT6yfp5O44col5OBctIR-17" value="3" 
style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;fillColor=#D4E1F5;" 
vertex="1" parent="1">
+          <mxGeometry x="350" y="230" width="20" height="20" as="geometry" />
+        </mxCell>
+        <mxCell id="vT6yfp5O44col5OBctIR-18" value="4" 
style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;fillColor=#D4E1F5;" 
vertex="1" parent="1">
+          <mxGeometry x="220" y="260" width="20" height="20" as="geometry" />
+        </mxCell>
+      </root>
+    </mxGraphModel>
+  </diagram>
+</mxfile>
diff --git 
a/serverlessworkflow/modules/ROOT/assets/images/cloud/apisix-keycloak/ingress-apisix-keycloak.png
 
b/serverlessworkflow/modules/ROOT/assets/images/cloud/apisix-keycloak/ingress-apisix-keycloak.png
new file mode 100644
index 000000000..667c439b8
Binary files /dev/null and 
b/serverlessworkflow/modules/ROOT/assets/images/cloud/apisix-keycloak/ingress-apisix-keycloak.png
 differ
diff --git a/serverlessworkflow/modules/ROOT/nav.adoc 
b/serverlessworkflow/modules/ROOT/nav.adoc
index adf95c527..36403b49b 100644
--- a/serverlessworkflow/modules/ROOT/nav.adoc
+++ b/serverlessworkflow/modules/ROOT/nav.adoc
@@ -68,6 +68,7 @@
 ** xref:persistence/core-concepts.adoc[Core concepts]
 // * Java Workflow Library TODO: https://issues.redhat.com/browse/KOGITO-9454
 * xref:cloud/index.adoc[Cloud]
+** xref:cloud/custom-ingress-authz.adoc[Securing Workflows]
 ** Operator
 *** xref:cloud/operator/install-serverless-operator.adoc[Installation]
 *** xref:cloud/operator/global-configuration.adoc[Admin Configuration]
diff --git 
a/serverlessworkflow/modules/ROOT/pages/cloud/custom-ingress-authz.adoc 
b/serverlessworkflow/modules/ROOT/pages/cloud/custom-ingress-authz.adoc
new file mode 100644
index 000000000..cefb17752
--- /dev/null
+++ b/serverlessworkflow/modules/ROOT/pages/cloud/custom-ingress-authz.adoc
@@ -0,0 +1,340 @@
+= Using an Ingress to add authentication and authorization to Workflow 
applications
+:compat-mode!:
+// Metadata:
+:description: Securing workflow applications via a 
+:keywords: cloud, kubernetes, docker, image, podman, openshift, oidc, 
keycloak, apisix
+// links
+:oidc_spec_url: https://openid.net/specs/openid-connect-core-1_0.html
+:kubernetes_svc_url: 
https://kubernetes.io/docs/concepts/services-networking/service/
+:kubernetes_networkpolicy_url: 
https://kubernetes.io/docs/concepts/services-networking/network-policies/
+:sonataflow_apisix_example_url: 
https://github.com/apache/incubator-kie-kogito-examples/tree/stable/serverless-operator-examples/sonataflow-apisix-oidc
+:keycloak_resource_owner_granttype_url: 
https://www.keycloak.org/docs/23.0.7/securing_apps/#_resource_owner_password_credentials_flow
+:apisix_install_url: 
https://apisix.apache.org/docs/ingress-controller/deployments/minikube/
+
+This document describes how you add an Ingress to a {product_name} workflow to 
handle authentication and authorization use cases.
+
+In the approach outlined in this guide, protect your workflows from anonymous 
access outside the cluster with the link:{oidc_spec_url}[OpenID Connect] 
specification. 
+
+Although the example demonstrated in this document is not meant to be used in 
production, you can use it as a reference to create your own architecture.
+
+== Architecture
+
+The following image illustrates a simplified architecture view of the 
recommended approach for protecting {product_name} workflow endpoints.
+
+image::cloud/apisix-keycloak/ingress-apisix-keycloak.png[]
+
+1. User makes a request with their credentials
+2. APISIX do the JWT token introspection in the OIDC Server (Keycloak)
+3. Keycloak validates the token
+4. APISIX forwards the request to the workflow application
+
+This is a simplified approach for OIDC (OpenID Connect protocol) use cases. In 
production environments, you can tailor your gateway and OIDC server to meet 
your requirements and scope.
+
+[IMPORTANT]
+====
+This approach only protects the communication via Ingress. Direct calls to the 
workflow application link:{kubernetes_svc_url}[internal service] would be 
anonymous.
+For example, another microservice in the cluster making requests to the 
workflow internal service.
+Set link:{kubernetes_networkpolicy_url}[Kuberbetes NetworkPolicies] to your 
workflow applications if this is not the desired behavior.
+====
+
+== How to deploy the example architecture
+
+The following sections describe how to deploy the example architecture using 
APISIX and Keycloak to protect your {product_name} workflows.
+
+.Prerequisites
+
+* Minikube is installed. You can use Kind or any other cluster if you have 
admin access. Just ensure to adapt the steps below to your environment.
+* link:{sonataflow_apisix_example_url}[Clone the example SonataFlow APISIX 
with Keycloak in a local directory].
+* (Optional) 
xref:cloud/operator/install-serverless-operator.adoc[{operator_name} is 
installed] if you are going to deploy via the operator.
+* (Optional) 
xref:use-cases/advanced-developer-use-cases/deployments/deploying-on-minikube.adoc[Quarkus
 {product_name} workflow is deployed] if you are not using the operator.
+
+=== Installing Keycloak
+
+From the example's cloned directory 'sonataflow-apisix-oidc', run the 
following command:
+
+.Running kustomize to install Keycloak
+[source,shell,subs="attributes+"]
+----
+kubectl create ns keycloak
+kubectl kustomize manifests/bases | kubectl apply -f - -n keycloak
+----
+
+This command creates a namespace called `keycloak` and a Keycloak server 
deployment connected to a PostgreSQL database to persist your data across 
cluster restarts.
+
+==== Exposing Keycloak locally
+
+[TIP]
+====
+You can skip this section if you are running on OpenShift or any cluster that 
you can expose Keycloak via an Ingress DNS or Route.
+====
+
+Since Keycloak is running on Minikube, expose the service port to your local 
network by running the following command:
+
+.Exposing Keycloak to the local network
+[source,shell,subs="attributes+"]
+----
+kubectl port-forward $(kubectl get pods -l app=keycloak 
--output=jsonpath='{.items[*].metadata.name}' -n keycloak) 8080:8080 -n keycloak
+----
+
+From now on, every connection to the `8080` port is forwarded to the Keycloak 
service endpoint.
+
+The next step is to configure your local `/etc/hosts`. This step is needed 
because the token you are going to generate must come from the same URL that 
the APISIX server introspects once you access the workflow.
+
+Edit your local `/etc/hosts` file and add the following line:
+
+.Hosts file with the Keycloak address entry
+[source,txt,subs="attributes+"]
+----
+127.0.0.1 keycloak.keycloak.svc.cluster.local
+----
+
+You can try accessing your Keycloak admin console in the address 
link:http://keycloak.keycloak.svc.cluster.local:8080[]. The default user and 
password are `admin`.
+
+[IMPORTANT]
+====
+In real-life environments, this step is not needed since Keycloak or any OIDC 
server is served by a load balancer with the correct address configured.
+====
+
+==== Configuring the Keycloak OIDC Server
+
+In the next step, log in to the Keycloak admin console in the address 
link:http://keycloak.keycloak.svc.cluster.local:8080[] using the default 
credentials.
+
+Once you are logged into the console, click *Create realm* in the top left 
menu. In this screen, create a new realm named `sonataflow`. See the image 
below for more details:
+
+.Creation of the new sonataflow realm
+image::cloud/apisix-keycloak/01-create-realm.png[]
+
+Next, create a client for the APISIX Ingress to introspect the JWT tokens.
+
+In the left menu, make sure that you are in the `sonataflow` realm and click 
on *Clients*, then *Create client*. Give the name `apisix-ingress` and then 
click on *Next*.
+
+.Creation of the APISIX Ingress client
+image::cloud/apisix-keycloak/02-create-client.png[]
+
+Next, add the details about this client:
+
+1. Turn the *Client authentication* option on.
+2. Leave *Authorization* off.
+3. Mark the options *Standard flow* and *Direct access grants* and leave the 
rest blank.
+
+.APISIX Ingress client details
+image::cloud/apisix-keycloak/03-create-client.png[]
+
+Click on *Next*, leave everything blank in the next screen and click on *Save*.
+
+==== Creating a user
+
+In this example, create a user registered in the Keycloak server to access the 
workflow application.
+
+[IMPORTANT]
+====
+For simplicity, use the link:{keycloak_resource_owner_granttype_url}[Grant 
Type Resource Owner Password]. This flow is not recommended for production 
architectures. Consider using other mechanisms such as Authorization Code or 
Client Credentials.
+====
+
+In the left menu, make sure that you are in the `sonataflow` realm and click 
on *Users* and then click *Create new user*.
+
+In this screen, fill in the details according to the figure below:
+
+1. Switch *Email verified* option on.
+2. Set *Username* to `luke`.
+3. Set *Email* to `[email protected]`
+4. Set *First name* to `Luke` and *Last name* to `Skywalker`
+
+.Creating a workflow user
+image::cloud/apisix-keycloak/05-create-user.png[]
+
+Click on *Create*.
+
+Next, set the credentials for this newly created user. Click on *Users* in the 
left menu and then in the name `luke`. 
+
+In this screen, click on the tab *Credentials*, and then on *Set password*.
+
+.Setting user's password
+image::cloud/apisix-keycloak/06-user-set-password.png[]
+
+Set the password as `luke` (same as the username), leave the *Temporary* 
option off and click on *Save*.
+
+Use the credentials `luke`/`luke` later in this guide to acquire a JWT token 
to make requests to the workflow application.
+
+=== Installing the APISIX Ingress
+
+Follow the documentation on link:{apisix_install_url}[APISIX Documentation 
website] and install the APISIX Ingress in your cluster (install the HELM 
client first).
+
+If you are running on Minikube, expose the APISIX Ingress server:
+
+.Exposing apisix-ingress service to the local network
+[source,shell,subs="attributes+"]
+----
+minikube service apisix-gateway --url -n ingress-apisix
+----
+
+The command outcome is the local URL which you can access the Ingress you 
create later in this guide. Leave the terminal open.
+
+[TIP]
+====
+If you are not running on Minikube, see the APISIX Ingress documentation for 
more information on how to expose the Ingress already in your cluster. 
+====
+
+After this step, Keycloak OIDC Server and APISIX Ingress Controller on your 
cluster are able to protect your {product_name} workflow applications from 
external requests.
+
+== Deploying the {product_name} sample workflow
+
+In this section, learn how to deploy the Greeting workflow example and a 
custom APIXSIX Ingress to protect external requests to the application's 
endpoints.
+
+.Prerequisites
+
+* You installed, configured, and exposed the Keycloak server
+* You installed and exposed the APISIX Ingress server
+* You installed the {operator_name} 
+* You link:{sonataflow_apisix_example_url}[cloned the example application 
locally]
+
+The first step is to deploy the {product_name} workflow. 
+
+Enter the example project directory that you cloned locally and run the 
command below:
+
+.Deploying the Greeting workflow
+[source,shell,subs="attributes+"]
+----
+kubectl create ns sonataflow
+kubectl apply -f workflow-app/01-sonataflow-greeting.yaml -n sonataflow
+----
+
+You can follow the workflow deployment by running
+
+.Follow the workflow deployment process
+[source,shell,subs="attributes+"]
+----
+kubectl -n sonataflow get workflow/greeting -w
+
+NAME       PROFILE   VERSION   URL   READY   REASON
+greeting             0.0.1           False   WaitingForBuild
+----
+
+=== Configuring the Ingress Route
+
+Once you deploy the {product_name} workflow you can configure and deploy the 
APISIX Route.
+
+Open the file `workflow-app/02-sonataflow-route.yaml` in the example 
application you cloned earlier and change the credentials for the 
`apisix-ingress` client that you created in the Keycloak server:
+
+.Greeting workflow APISIX Route
+[source,yaml,subs="attributes+"]
+----
+apiVersion: apisix.apache.org/v2
+kind: ApisixRoute
+metadata:
+  name: sonataflow
+spec:
+  http:
+    - name: greeting
+      match:
+        hosts:
+          - local.greeting.sonataflow.org
+        paths:
+          - "/*"
+      backends:
+        - serviceName: greeting
+          servicePort: 80
+      plugins:
+        - name: openid-connect <1>
+          enable: true
+          config:
+            client_id: apisix-ingress
+            client_secret: <2>
+            discovery: 
http://keycloak.keycloak.svc.cluster.local:8080/realms/sonataflow/.well-known/openid-configuration
+            scope: profile email
+            bearer_only: true
+            realm: sonataflow
+            introspection_endpoint_auth_method: client_secret_post
+----
+
+<1> The link:{}[OpenID Connect plugin] to make the Ingress connect to Keycloak
+<2> The `apisix-ingress` client credential to be changed
+
+Open the Keycloak server 
(link:http://keycloak.keycloak.svc.cluster.local:8080[]) and in the realm 
`sonataflow` click on *Clients*, and then on `apisix-ingress`.
+
+Click on the tab *Credentials* and copy the *Client Secret*:
+
+.Creating the workflow user
+image::cloud/apisix-keycloak/04-client-credentials.png[]
+
+Paste the *Client Secret* into the `ApisixRoute` file 
`workflow-app/02-sonataflow-route.yaml` in the example application and run:
+
+.Deploy the `ApisixRoute`
+[source,shell,subs="attributes+"]
+----
+kubectl apply -f workflow-app/02-sonataflow-route.yaml -n sonataflow
+----
+
+To this point, you have installed in your cluster the Keycloak and APISIX 
Ingress server, and deployed the example Greeting workflow application.
+
+=== Accessing the Workflow
+
+Access the workflow without a token to see a rejection:
+
+.Directly accessing the workflow without a token
+[source,shell,subs="attributes+"]
+----
+INGRESS_URL= <1>
+
+curl -v POST $\{INGRESS_URL\}/greeting -H "Content-type: application/json" -H 
"Host: local.greeting.sonataflow.org" --data '{ "name": "Luke" }' 
+----
+
+<1> The ingress url is accessible via the Minikube service command. If you 
have not done it already, run `minikube service apisix-gateway --url -n 
ingress-apisix`.
+
+See a 401 HTTP Status message denying your access to the workflow.
+
+Next, access the application using an access token. First, you need to get the 
access token from the Keycloak server:
+
+.Requesting an access token to Keycloak server
+[source,shell,subs="attributes+"]
+----
+CLIENT_SECRET="secret from apisix-ingress client" <1>
+
+ACCESS_TOKEN=$(curl \
+  -d "client_id=apisix-ingress" \
+  -d "client_secret=$\{CLIENT_SECRET\}" \
+  -d "username=luke" \
+  -d "password=luke" \
+  -d "grant_type=password" \
+  
"http://keycloak.keycloak.svc.cluster.local:8080/realms/sonataflow/protocol/openid-connect/token";
 | jq -r .access_token) <2>
+----
+
+<1> Copy the secret from the `apisix-ingress` client
+<2> Request an access token from the Keycloak server using the user `luke` 
credentials
+
+[NOTE]
+====
+The token returned with the command above has a default timeout of 5 minutes, 
which means that if you take too long to use it, or want to execute several 
requests, you might need to execute the command again and get a new token.
+====
+Having the access token set in an environment variable, access the application 
again:
+
+[source,shell,subs="attributes+"]
+----
+INGRESS_URL= <1>
+
+curl -v POST $\{INGRESS_URL\}/greeting -H "Content-type: application/json" -H 
"Host: local.greeting.sonataflow.org" -H "Authorization: Bearer 
$\{ACCESS_TOKEN\}" --data '{ "name": "Luke" }' 
+----
+
+<1> The ingress url is accessible via the Minikube service command. If you 
have not done it already, run `minikube service apisix-gateway --url -n 
ingress-apisix`.
+
+This request is passing through the APISIX Gateway, which is validating the 
token via the `Authorization: Bearer` header. Then the request is passed 
internally to the workflow application which process and return to the original 
client.
+
+Finally, this time, in the last part of the command output, you should see a 
JSON document similar to the excerpt below, which indicates that the workflow 
instance was created successfully.
+
+[source,json]
+----
+{"id":"a9fc1a97-e274-4e40-80e5-4ff5ba203231","workflowdata":{"message":"Hello 
from YAML Workflow, anonymous"}}
+----
+
+== Conclusion
+
+In this guide you were able to deploy an architecture of services capable of 
authenticating a valid user using OIDC mechanisms. Now, everytime that someone 
needs access to the deployed workflow, it must first get a valid JWT token in 
the Keycloak OIDC Server.
+
+Next steps now, would be to tailor this architecture for your needs such as a 
cluster of Keycloak servers behind a TLS and valid domain. Also, APISIX Ingress 
offers many other capabilities and configurations that can be tuned to favor 
your use cases.
+
+== Additional resources
+
+* xref:cloud/operator/install-serverless-operator.adoc[]
+* xref:cloud/operator/configuring-workflows.adoc[]
+
+include::../../pages/_common-content/report-issue.adoc[]
diff --git a/serverlessworkflow/modules/ROOT/pages/cloud/index.adoc 
b/serverlessworkflow/modules/ROOT/pages/cloud/index.adoc
index d1cf5c142..ab459adea 100644
--- a/serverlessworkflow/modules/ROOT/pages/cloud/index.adoc
+++ b/serverlessworkflow/modules/ROOT/pages/cloud/index.adoc
@@ -17,6 +17,16 @@ Eventually, these two options will converge, and the 
{operator_name} will also b
 ====
 
 [.card-section]
+== Common Kubernetes Guides
+
+[.card]
+--
+[.card-title]
+xref:cloud/custom-ingress-authz.adoc[]
+[.card-description]
+Learn how to secure a {product_name} workflow with OIDC
+--
+
 == Kubernetes with the Operator
 
 For developers that are looking for a native Kubernetes approach where you can 
model workflows using YAML definitions and directly deploy them, you can use 
the {operator_name}. The operator registers a new Kubernetes resource in the 
cluster to manage your workflow development iteration cycle and composition of 
services and events. The application is managed by the operator.


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to