-
Notifications
You must be signed in to change notification settings - Fork 59
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Wraping up first iteration of the guide
Signed-off-by: Ricardo Zanini <[email protected]>
- Loading branch information
1 parent
737fe78
commit e4b808d
Showing
10 changed files
with
261 additions
and
10 deletions.
There are no files selected for viewing
Binary file added
BIN
+48.2 KB
...ssworkflow/modules/ROOT/assets/images/cloud/apisix-keycloak/01-create-realm.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+47.2 KB
...sworkflow/modules/ROOT/assets/images/cloud/apisix-keycloak/02-create-client.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+59.2 KB
...sworkflow/modules/ROOT/assets/images/cloud/apisix-keycloak/03-create-client.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+60.7 KB
...flow/modules/ROOT/assets/images/cloud/apisix-keycloak/04-client-credentials.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+50.7 KB
...essworkflow/modules/ROOT/assets/images/cloud/apisix-keycloak/05-create-user.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+48.1 KB
...kflow/modules/ROOT/assets/images/cloud/apisix-keycloak/06-user-set-password.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
File renamed without changes
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,17 +7,21 @@ | |
: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: | ||
: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, you will be able to protect your workflows from anonymous access outside the cluster with link:{oidc_spec_url}[OpenID Connect]. | ||
In the approach outlined in this guide, you will be able to 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 use 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/ingress-apisix-keycloak.png[] | ||
image::cloud/apisix-keycloak/ingress-apisix-keycloak.png[] | ||
|
||
1. User makes a request with their credentials | ||
2. APISIX do the JWT token instrospection in the OIDC Server (Keycloak) | ||
|
@@ -28,7 +32,7 @@ This is a simplified approach for OIDC use cases. In production environments, yo | |
|
||
[IMPORTANT] | ||
==== | ||
This approach only protects the communication made via Ingress. Direct calls to the workflow application link:{kubernetes_svc_url}[internal service] would be anonymous. | ||
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. | ||
Make sure to set link:{kubernetes_networkpolicy_url}[Kuberbetes NetworkPolicies] to your workflow applications if this is not the desired behavior. | ||
==== | ||
|
@@ -41,12 +45,12 @@ In the following sections you will be able to understand and deploy the example | |
|
||
* Minikube installed. You can try using KIND or any other cluster if you have admin access. Just ensure to adapt the steps bellow 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[{product_name} operator installed] if you're going to deploy via the operator. | ||
* (Optional) xref:cloud/operator/install-serverless-operator.adoc[{operator_name installed] if you're going to deploy via the operator. | ||
* (Optional) xref:use-cases/advanced-developer-use-cases/deployments/deploying-on-minikube.adoc[Quarkus {product_name} workflow deployed] if you're not using the operator. | ||
|
||
=== Installing Keycloak | ||
|
||
From the example's directory, run the following command: | ||
From the example's cloned directory, run the following command: | ||
|
||
.Running kustomize to install Keycloak | ||
[source,shell,subs="attributes+"] | ||
|
@@ -69,18 +73,254 @@ Since Keycloak is running on Minikube, you must expose the service port to your | |
.Exposing Keycloak to the local network | ||
[source,shell,subs="attributes+"] | ||
---- | ||
# Let's use kubectl port-forward to equalize the Keycloak endpoint URI so APISIX and your local env access Keycloak using the same URL | ||
# This method works even in Windows/Darwin where Podman/Docker won't give access to the internal network | ||
# Hence, we must rely on tunnel/port-forward | ||
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 will be forwarded to the Keycloak service endpoint. | ||
|
||
The next step is to configure your local `/etc/hosts`. This step is needed because the token you're going to generate must come from the same URL that APISIX server will introspect once you try to 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] | ||
==== | ||
Of course in real-life environments this step is not needed since Keycloak or any OIDC server will be served by a load balancer with the correct DNS configured. | ||
In real-life environments this step is not needed since Keycloak or any OIDC server will be served by a load balancer with the correct address configured. | ||
==== | ||
|
||
==== Configuring the Keycloak OIDC Server | ||
|
||
In this next step, you should be able to login to the Keycloak admin console in the address link:http://keycloak.keycloak.svc.cluster.local:8080[] using the default credentials. | ||
|
||
Once in the console, click on "Create realm" in the top left menu. In this screen you will be able to create a new realm named "sonataflow". See the image bellow for more details: | ||
|
||
.Creation of the new realm "sonataflow" | ||
image::cloud/apisix-keycloak/01-create-realm.png[] | ||
|
||
Next, you must create a client for the APISIX Ingress to introspect the JWT tokens. | ||
|
||
In the left menu, make sure that you're 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, you should be able to 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 in blank in the next screen and click on "Save". | ||
|
||
==== Creating the user | ||
|
||
You will access the workflow application in this example with a user registered in the Keycloak server. | ||
|
||
[IMPORTANT] | ||
==== | ||
For simplicity, we will 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're in the "sonataflow" realm and click on "Users" and then "Create new user". | ||
|
||
In this screen, fill in the details according to the figure below: | ||
|
||
1. Turn "Email verified" option on. | ||
2. Username set to `luke`. | ||
3. Email to `[email protected]` | ||
4. First name `Luke` and last name `Skywalker` | ||
|
||
.Creating the 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". | ||
|
||
You will 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. You should have to install HELM client first. | ||
|
||
If you're running on minikube, you must expose the APISIX Ingress server: | ||
|
||
.Exposing Keycloak 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 will create later in this guide. Leave the terminal opened. | ||
|
||
[TIP] | ||
==== | ||
If you're not running on Minikube, you must have a way to expose the Ingress already in your cluster. Consult the APISIX Ingress documentation for more information on how to proceed. | ||
==== | ||
|
||
After this step you will have a Keycloak OIDC Server and a APISIX Ingress Controller on your cluster able to protect your {product_name} workflow applications from external requests. | ||
|
||
== Deploying the {product_name} sample workflow | ||
|
||
In this section, you will learn how to deploy the example "Greeting" workflow 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 in 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 deployed 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: | ||
|
||
."Greetings" workflow APISIX Route | ||
[source,yaml,subs="attributes+"] | ||
---- | ||
apiVersion: apisix.apache.org/v2 | ||
kind: ApisixRoute | ||
metadata: | ||
name: sonataflow | ||
namespace: 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 that you will change | ||
|
||
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 should have installed in your cluster the Keycloak and APISIX Ingress server, and deployed the example "Greetings" workflow application. | ||
|
||
=== Accessing the Workflow | ||
|
||
You should not be able to access the workflow without a token, so to test it you can run: | ||
|
||
.Directly accessing the workflow without a token | ||
[source,shell,subs="attributes+"] | ||
---- | ||
curl -v POST http://127.0.0.1:$\{INGRESS_PORT\}/greeting -H "Content-type: application/json" -H "Host: local.greeting.sonataflow.org" --data '{ "name": "Luke" }' | ||
---- | ||
|
||
You should receive a 401 HTTP Status message dening your access to the workflow. | ||
|
||
Next, try to 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 | ||
|
||
Having the access token set in an environment variable, access the application again: | ||
|
||
[source,shell,subs="attributes+"] | ||
---- | ||
INGRESS_PORT= <1> | ||
curl -v POST http://127.0.0.1:$\{INGRESS_PORT\}/greeting -H "Content-type: application/json" -H "Host: local.greeting.sonataflow.org" -H "Authorization: Bearer $\{ACCESS_TOKEN\}" --data '{ "name": "Luke" }' | ||
---- | ||
|
||
<1> The ingress port should be acessible via the Minikube service command. You haven't done it already, you can run it with `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 will process and return to the original client. | ||
|
||
== 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[] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters