-
Notifications
You must be signed in to change notification settings - Fork 60
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
authN-authZ: change folder and split support
* change the folder to a upper level directory * split the support for helm chart and gmc-based deployment Signed-off-by: Ruoyu Ying <[email protected]>
- Loading branch information
Showing
31 changed files
with
195 additions
and
33 deletions.
There are no files selected for viewing
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 |
---|---|---|
@@ -1,22 +1,32 @@ | ||
# Use GMC and Istio to compose an OPEA Pipeline with authentication and authorization enabled | ||
# Leveraging Istio to compose an OPEA Pipeline with authentication and authorization enabled | ||
|
||
In enterprise settings not only do we want to identify who is using a service but also what they are entitled to use. This is where authentication and authorization comes in. In contrast, API tokens provide full access by virtue of possession as long as they are valid/not expired. With that aside, we first provide the solution on AuthN and AuthZ in OPEA using Istio and JWT tokens. Another option is to leverage the oauth2-proxy with various OIDC providers for authentication and authorization. Using oauth2-proxy with Istio ensures secure, scalable access control, centralizes user management, and provides seamless single sign-on capabilities, improving overall security and user experience in complex microservices environments. | ||
|
||
Currently we provide three kinds of setups for authentication and authorization: via fake JWT token, via JWT token generated by OIDC providers and via oauth2-proxy and OIDC providers. And here we use the chatQnA pipeline as an example. | ||
|
||
## Prerequisite | ||
|
||
Before composing an OPEA pipeline with authN & authZ using GMC, user need to install Istio to support this feature. Please follow the steps [here](https://istio.io/latest/docs/setup/install/istioctl/) for installation. | ||
Before composing an OPEA pipeline with authN & authZ, user need to install Istio to support this feature. Please follow the steps [here](https://istio.io/latest/docs/setup/install/istioctl/) for Istio installation. | ||
|
||
**Deploy chatQnA GMC custom resource and enable Istio sidecar injection** | ||
**Deploy chatQnA pipeline and enable Istio sidecar injection** | ||
|
||
```sh | ||
# make sure you are executing under the microservices-connector folder | ||
kubectl create ns chatqa | ||
kubectl apply -f $(pwd)/config/samples/chatQnA_xeon.yaml | ||
|
||
# patch the router deployment to enable istio sidecar injection | ||
kubectl patch deployment -n chatqa router-server --patch '{ | ||
# deploy ChatQnA pipeline. You can either leverage GMC or the ChatQnA helm chart. | ||
kubectl create ns chatqa | ||
# here's the command to leverage GMC custom resource for ChatQnA deployment. | ||
kubectl apply -f $(pwd)/../microservices-connector/config/samples/chatQnA_xeon.yaml | ||
# please refer the doc https://github.com/opea-project/GenAIInfra/tree/main/helm-charts/chatqna for deployment with helm chart. | ||
# and install under `chatqa` namespace | ||
|
||
# expose an environment variable to set the deployment method | ||
# which will affect the configuration we use for authentication and authorization | ||
export DEPLOY_METHOD=<your deploy method, valid values: "gmc-based" and "helm-chart-based"> | ||
|
||
# patch the deployment to enable istio sidecar injection | ||
# for GMC based deployment, set the `deployment-name` to `router-service-deployment` | ||
# for helm chart based deployment, set the `deployment-name` to `chatqna` | ||
kubectl patch deployment -n chatqa <deployment-name> --patch '{ | ||
"spec": { | ||
"template": { | ||
"metadata": { | ||
|
@@ -29,9 +39,9 @@ kubectl patch deployment -n chatqa router-server --patch '{ | |
}' | ||
``` | ||
|
||
The istio ingress gateway will be used to access the chatQnA service in different setups. Follow the istio guide [here](https://istio.io/latest/docs/tasks/traffic-management/ingress/ingress-control/#determining-the-ingress-ip-and-ports) to determine the ingress IP and ports. | ||
The istio ingress gateway will be used to access the chatQnA service in different setups. Follow the istio guide [here](https://istio.io/latest/docs/tasks/traffic-management/ingress/ingress-control/#determining-the-ingress-ip-and-ports) to determine the ingress IP and ports and expose them as environment variables. | ||
|
||
## Perform authentication and authorization via Bearer JWT tokens | ||
## Perform authentication and authorization via Bearer JWT tokens and curl | ||
|
||
Authentication and authorization are essential for securing microservices architectures. Using Bearer JWT tokens for these processes ensures that only authenticated users with valid tokens can access specific services, protecting sensitive data. Authentication verifies user identity, while authorization controls their permissions. This layered approach not only prevents unauthorized access but also provides detailed control over service interactions, maintaining system security and compliance. Here we leverage Istio mechanisms together with Bearer JWT tokens to fulfill that. | ||
|
||
|
@@ -46,13 +56,14 @@ In this example, we setup rules that only users with JWT token issued by "testin | |
**Apply authentication and authorization policies to the pipeline endpoint based on raw JWT tokens** | ||
|
||
```sh | ||
# make sure running under authN-authZ folder | ||
# apply the yaml to request authentication using JWT token | ||
kubectl apply -f $(pwd)/config/authN-authZ/chatQnA_authZ_fakejwt.yaml -n chatqa | ||
kubectl apply -f $(pwd)/$(DEPLOY_METHOD)/chatQnA_authZ_fakejwt.yaml -n chatqa | ||
|
||
# apply the yaml file to request that only JWT token with | ||
# issuer & sub == "[email protected]" and groups belongs to group1 | ||
# can access the endpoint of chatQnA service | ||
kubectl apply -f $(pwd)/config/authN-authZ/chatQnA_authN_fakejwt.yaml -n chatqa | ||
kubectl apply -f $(pwd)/$(DEPLOY_METHOD)/chatQnA_authN_fakejwt.yaml -n chatqa | ||
``` | ||
|
||
After applying these two yaml files, we have setup the policy that only user with a valid JWT token (with valid issuer and claims) could access the pipeline endpoint. | ||
|
@@ -83,7 +94,12 @@ Deploy one client pod and test the chatQnA application with different tokens | |
kubectl create deployment client-test -n chatqa --image=python:3.8.13 -- sleep infinity | ||
|
||
export CLIENT_POD=$(kubectl get pod -n chatqa -l app=client-test -o jsonpath={.items..metadata.name}) | ||
export accessUrl=$(kubectl get gmc -n chatqa -o jsonpath="{.items[?(@.metadata.name=='chatqa')].status.accessUrl}") | ||
|
||
# export an accessUrl based on either GMC or helm chart based ChatQnA | ||
if [ "${DEPLOY_METHOD}" = "gmc-based" ]; then | ||
export accessUrl=$(kubectl get gmc -n chatqa -o jsonpath="{.items[?(@.metadata.name=='chatqa')].status.accessUrl}") | ||
else | ||
export accessUrl="http://chatqna.chatqa.svc.cluster.local:8888" | ||
|
||
# try without token. Shall get response: "RBAC: access denied 403" | ||
kubectl exec -it -n chatqa $CLIENT_POD -- curl -X POST $accessUrl -d '{"text":"What is the revenue of Nike in 2023?","parameters":{"max_new_tokens":17, "do_sample": true}}' -sS -H 'Content-Type: application/json' -w " %{http_code}\n" | ||
|
@@ -106,8 +122,9 @@ In this sample, we are going to test with the scenario that only privileged user | |
Install Keycloak in the kubernetes cluster for user management. **Note:** Replace the admin password as your own in the keycloak_install.yaml file. | ||
```bash | ||
# make sure running under authN-authZ folder | ||
cd $(pwd) | ||
kubectl apply -f $(pwd)/config/authN-authZ/keycloak_install.yaml | ||
kubectl apply -f $(pwd)/keycloak_install.yaml | ||
# get the ip and port to access keycloak. | ||
export HOST_IP=$(kubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}' | cut -d '/' -f3 | cut -d ':' -f1) | ||
|
@@ -135,14 +152,14 @@ Use the commands to apply the authentication and authorization rules. | |
```bash | ||
# export the router service through istio ingress gateway | ||
kubectl apply -f $(pwd)/config/authN-authZ/chatQnA_router_gateway.yaml | ||
kubectl apply -f $(pwd)/$(DEPLOY_METHOD)/chatQnA_router_gateway.yaml | ||
# 'envsubst' is used to substitute envs in yaml. | ||
# use 'sudo apt-get install gettext-base' to install envsubst if it does not exist on your machine | ||
# apply the authentication and authorization rule | ||
# these files will restrict user access with valid token (with valid issuer, username and realm role) | ||
envsubst < $(pwd)/config/authN-authZ/chatQnA_authN_keycloak.yaml | kubectl -n chatqa apply -f - | ||
envsubst < $(pwd)/config/authN-authZ/chatQnA_authZ_keycloak.yaml | kubectl -n chatqa apply -f - | ||
envsubst < $(pwd)/$(DEPLOY_METHOD)/chatQnA_authN_keycloak.yaml | kubectl -n chatqa apply -f - | ||
envsubst < $(pwd)/$(DEPLOY_METHOD)/chatQnA_authZ_keycloak.yaml | kubectl -n chatqa apply -f - | ||
``` | ||
User could customize the chatQnA_authZ_keycloak.yaml to reflect roles, groups or any other claims they defined in the OIDC provider for the user. | ||
|
@@ -175,9 +192,9 @@ curl -X POST $accessUrl -d '{"text":"What is the revenue of Nike in 2023?","para | |
curl -X POST $accessUrl -d '{"text":"What is the revenue of Nike in 2023?","parameters":{"max_new_tokens":17, "do_sample": true}}' -sS -H "Authorization: Bearer $TOKENA" -H 'Content-Type: application/json' -w " %{http_code}\n" | ||
``` | ||
## Perform authentication and authorization via oauth2-proxy and OIDC provider | ||
## Perform authentication and authorization via oauth2-proxy and OIDC provider and UI | ||
Another choice we have is using oauth2-proxy and OIDC providers. These two streamline authentication and authorization by handling user identity and access management. oauth2-Proxy acts as a gateway, integrating with OIDC providers to authenticate users and issue tokens. This setup ensures secure access to applications by validating user credentials and managing permissions, simplifying the implementation of robust security protocols across services. | ||
Another choice we have is using oauth2-proxy and OIDC providers. These two streamline authentication and authorization by handling user identity and access management. oauth2-proxy acts as a gateway, integrating with OIDC providers to authenticate users and issue tokens. This setup ensures secure access to applications by validating user credentials and managing permissions, simplifying the implementation of robust security protocols across services. | ||
<img src="./docs/OPEA auth flow with oauth2-proxy.png" width="700" height="400"> | ||
|
@@ -188,8 +205,9 @@ We are using a similar scenario here that only privileged users can access our c | |
Here we take Keycloak as the sample OIDC Provider to use in the example. Follow the steps to install and configure Keycloak. | ||
```bash | ||
# make sure running under authN-authZ folder | ||
cd $(pwd) | ||
kubectl apply -f $(pwd)/config/authN-authZ/keycloak_install.yaml | ||
kubectl apply -f $(pwd)/keycloak_install.yaml | ||
# get the ip and port to access keycloak. | ||
export HOST_IP=$(kubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}' | cut -d '/' -f3 | cut -d ':' -f1) | ||
|
@@ -245,7 +263,7 @@ export CLIENT_SECRET=<YOUR_CLIENT_SECRET> | |
# Using bash here. More methods found here: | ||
# https://oauth2-proxy.github.io/oauth2-proxy/configuration/overview#generating-a-cookie-secret | ||
export COOKIE_SECRET=$(dd if=/dev/urandom bs=32 count=1 2>/dev/null | base64 | tr -d -- '\n' | tr -- '+/' '-_' ; echo) | ||
envsubst < $(pwd)/config/authN-authZ/oauth2_install.yaml | kubectl apply -f - | ||
envsubst < $(pwd)/oauth2_install.yaml | kubectl apply -f - | ||
``` | ||
**Expose the pipeline endpoint through Istio Ingressgateway and install chatQnA UI** | ||
|
@@ -254,21 +272,19 @@ Here we expose the chatQnA endpoint through the ingress gateway and then install | |
```bash | ||
# expose chatqna endpoint | ||
kubectl apply -f $(pwd)/config/authN-authZ/chatQnA_router_gateway_oauth.yaml | ||
# build chatqna UI image | ||
kubectl apply -f $(pwd)/$(DEPLOY_METHOD)/chatQnA_router_gateway_oauth.yaml | ||
# build chatqna UI image if not exist on your machine | ||
git clone https://github.com/opea-project/GenAIExamples.git | ||
cd GenAIExamples/ChatQnA/docker/ui/ | ||
export BACKEND_SERVICE_ENDPOINT="http://chatqna-service.com:${INGRESS_PORT}/" | ||
export DATAPREP_SERVICE_ENDPOINT="http://chatqna-service.com:${INGRESS_PORT}/dataprep" | ||
docker build --no-cache -t opea/chatqna-conversation-ui:latest --build-arg https_proxy=$https_proxy --build-arg http_proxy=$http_proxy --build-arg BACKEND_SERVICE_ENDPOINT=$BACKEND_SERVICE_ENDPOINT --build-arg DATAPREP_SERVICE_ENDPOINT=$DATAPREP_SERVICE_ENDPOINT -f ./docker/Dockerfile.react . | ||
docker build --no-cache -t opea/chatqna-conversation-ui:latest --build-arg https_proxy=$https_proxy --build-arg http_proxy=$http_proxy -f ./docker/Dockerfile.react . | ||
# inject image to containerd repo | ||
docker save -o ui.tar opea/chatqna-conversation-ui:latest | ||
sudo ctr -n k8s.io image import ui.tar | ||
# install chatqna conversation UI | ||
cd && cd GenAIInfra/microservices-connector | ||
helm install chatqna-ui ../helm-charts/common/chatqna-ui | ||
cd && cd GenAIInfra | ||
helm install chatqna-ui $(pwd)/helm-charts/common/chatqna-ui | ||
# expose ui service outside | ||
kubectl apply -f $(pwd)/config/authN-authZ/chatQnA_ui_gateway.yaml | ||
kubectl apply -f $(pwd)/chatQnA_ui_gateway.yaml | ||
``` | ||
**Add authentication and authorization rules to the pipeline through Istio Ingress Gateway** | ||
|
@@ -277,13 +293,13 @@ Here we apply the authentication and authorization rules. | |
```bash | ||
# Before applying the authorization rule, need to add the oauth2-proxy as the external authorization provider | ||
kubectl apply -f $(pwd)/config/authN-authZ/chatQnA_istio_external_auth.yaml | ||
kubectl apply -f $(pwd)/chatQnA_istio_external_auth.yaml | ||
# 'envsubst' is used to substitute envs in yaml. | ||
# use 'sudo apt-get install gettext-base' to install envsubst if it does not exist on your machine | ||
# apply the authentication and authorization rule | ||
# these files will restrict user access with valid token (with valid group and role) | ||
envsubst < $(pwd)/config/authN-authZ/chatQnA_authN_oauth.yaml | kubectl apply -f - | ||
envsubst < $(pwd)/config/authN-authZ/chatQnA_authZ_oauth.yaml | kubectl apply -f - | ||
envsubst < $(pwd)/chatQnA_authN_oauth.yaml | kubectl apply -f - | ||
envsubst < $(pwd)/chatQnA_authZ_oauth.yaml | kubectl apply -f - | ||
``` | ||
**Validate authentication and authorization with UI service** | ||
|
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
# Copyright (C) 2024 Intel Corporation | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
apiVersion: security.istio.io/v1 | ||
kind: RequestAuthentication | ||
metadata: | ||
name: fake-jwt-example | ||
spec: | ||
jwtRules: | ||
- issuer: [email protected] | ||
jwksUri: https://raw.githubusercontent.com/istio/istio/release-1.22/security/tools/jwt/samples/jwks.json | ||
selector: | ||
matchLabels: | ||
app: chatqna |
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 |
---|---|---|
@@ -0,0 +1,15 @@ | ||
# Copyright (C) 2024 Intel Corporation | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
apiVersion: security.istio.io/v1 | ||
kind: RequestAuthentication | ||
metadata: | ||
name: jwt-keycloak | ||
spec: | ||
jwtRules: | ||
- issuer: http://${KEYCLOAK_ADDR}/realms/${REALM} | ||
jwksUri: http://${KEYCLOAK_ADDR}/realms/${REALM}/protocol/openid-connect/certs | ||
outputPayloadToHeader: jwt-parsed | ||
selector: | ||
matchLabels: | ||
app: chatqna |
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 |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# Copyright (C) 2024 Intel Corporation | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
apiVersion: security.istio.io/v1 | ||
kind: AuthorizationPolicy | ||
metadata: | ||
name: fake-jwt-example | ||
spec: | ||
action: ALLOW | ||
rules: | ||
- from: | ||
- source: | ||
requestPrincipals: | ||
- [email protected]/[email protected] | ||
when: | ||
- key: request.auth.claims[groups] | ||
values: | ||
- group1 | ||
selector: | ||
matchLabels: | ||
app: chatqna |
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 |
---|---|---|
@@ -0,0 +1,23 @@ | ||
# Copyright (C) 2024 Intel Corporation | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
apiVersion: security.istio.io/v1 | ||
kind: AuthorizationPolicy | ||
metadata: | ||
name: router | ||
spec: | ||
action: ALLOW | ||
rules: | ||
- when: | ||
- key: request.auth.claims[iss] | ||
values: | ||
- 'http://${KEYCLOAK_ADDR}/realms/istio' | ||
- key: request.auth.claims[preferred_username] | ||
values: | ||
- 'mary' | ||
- key: request.auth.claims[realm_access][roles] | ||
values: | ||
- 'user' | ||
selector: | ||
matchLabels: | ||
app: chatqna |
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 |
---|---|---|
@@ -0,0 +1,34 @@ | ||
# Copyright (C) 2024 Intel Corporation | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
apiVersion: networking.istio.io/v1 | ||
kind: Gateway | ||
metadata: | ||
name: router-gateway | ||
spec: | ||
selector: | ||
istio: ingressgateway | ||
servers: | ||
- hosts: | ||
- '*' | ||
port: | ||
name: http | ||
number: 80 | ||
protocol: HTTP | ||
--- | ||
apiVersion: networking.istio.io/v1 | ||
kind: VirtualService | ||
metadata: | ||
name: chatqna-router | ||
namespace: chatqa | ||
spec: | ||
gateways: | ||
- default/router-gateway | ||
hosts: | ||
- '*' | ||
http: | ||
- route: | ||
- destination: | ||
host: chatqna | ||
port: | ||
number: 8888 |
39 changes: 39 additions & 0 deletions
39
authN-authZ/helm-chart-based/chatQnA_router_gateway_oauth.yaml
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 |
---|---|---|
@@ -0,0 +1,39 @@ | ||
# Copyright (C) 2024 Intel Corporation | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
--- | ||
apiVersion: networking.istio.io/v1 | ||
kind: Gateway | ||
metadata: | ||
name: chatqna-gateway | ||
namespace: istio-system | ||
spec: | ||
selector: | ||
istio: ingressgateway | ||
servers: | ||
- hosts: | ||
- chatqna-service.com | ||
port: | ||
name: http | ||
number: 80 | ||
protocol: HTTP | ||
--- | ||
apiVersion: networking.istio.io/v1 | ||
kind: VirtualService | ||
metadata: | ||
name: chatqna-virtual-service | ||
namespace: istio-system | ||
spec: | ||
gateways: | ||
- istio-system/chatqna-gateway | ||
hosts: | ||
- chatqna-service.com | ||
http: | ||
- match: | ||
- uri: | ||
prefix: / | ||
route: | ||
- destination: | ||
host: chatqna.chatqa.svc.cluster.local | ||
port: | ||
number: 8888 |
File renamed without changes.
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