The following tutorial steps through provisioning and configuration for API management using 3scale in the context of services deployed to a Service Mesh.
The following assumptions are made about the target environment:
- OpenShift version 4.8+
- At least 3 worker nodes
- Appropriate Red Hat software subscriptions
Install the OpenShift Container Storage Operator into the recommended namespace openshift-storage
.
Label nodes where OpenShift Container Storage should be hosted. If all worker nodes should be used, the following command can be used to label them.
for node in $(oc get node -l node-role.kubernetes.io/worker -o name); do oc label ${node} cluster.ocs.openshift.io/openshift-storage=""; done
Apply the StorageCluster:
oc apply -f openshift-storage/StorageCluster_ocs-storagecluster.yaml -n openshift-storage
3scale requires a RWX storage class. The storage class used by the 3scale control plane will be ocs-storagecluster-cephfs
. Ensure that the storage class is available with the following command.
oc get storageclasses
Install 3scale operator into 3scale
namespace. (Create new namespace)
Set the cluster wildcard domain in 3scale/APIManager_3scale.yaml
Example wildcard domain: apps.cluster-8glcz.8glcz.sandbox730.opentlc.com
oc apply -f 3scale/APIManager_3scale.yaml -n 3scale
- Install Elasticsearch operator all namespaces
- Install Jaeger operator all namespaces
- Install Kiali operator all namespaces
- Install OpenShift Service Mesh operator all namespaces
- Create a namespace for the service mesh control plane
- Provision a control plane (see below)
oc new-project istio-system
oc apply -f istio-system/ServiceMeshControlPlane_basic.yaml -n istio-system
Create a new project and include bookinfo
in the service mesh.
oc new-project bookinfo
oc apply -f istio-system/ServiceMeshMemberRoll_default.yaml -n istio-system
Provision the bookinfo application.
oc apply -f https://raw.githubusercontent.com/maistra/istio/maistra-2.1/samples/bookinfo/platform/kube/bookinfo.yaml -n bookinfo
oc apply -f https://raw.githubusercontent.com/maistra/istio/maistra-2.1/samples/bookinfo/networking/bookinfo-gateway.yaml -n bookinfo
You can now verify that the bookinfo service is responding:
curl -v http://istio-ingressgateway-istio-system.{cluster wildcard url}/productpage
Log into 3scale using the route whose hostname begins with 3scale-admin
in the 3scale
namespace.
NOTE: You will find the admin username and password in a secret called system-seed
in the 3scale
namespace.
- Create a new Product and give it any name
- Go to Integration->Settings and choose
Istio
as the deployment - Go to Integration->Configuration and Promote the config
- Go to Overview and create an application plan
- Go to Applications->Application Plans and publish the application plan
- Go to the Product Overview and take note of the ID given to the API (This will be used in later steps)
Find the URLs for the 3scale-admin and backend-3scale routes in the 3scale
namespace. Substitute those URLs into the ServiceEntry resources.
oc apply -f bookinfo/ServiceEntry_system-entry.yaml -f bookinfo/ServiceEntry_backend-entry.yaml -n bookinfo
Copy the ADMIN_ACCESS_TOKEN
key of the system-seed
secret in the 3scale
namespace and replace the value of spec.config.system.token
in bookinfo/ServiceMeshExtension_bookinfo.yaml
Use 3scale admin access token along with the 3scale product ID from the 3scale product configuration and run the following command with values replaced:
curl https://3scale-admin.{cluster wildcard url}/admin/api/services/{product id}/proxy/configs/production/latest.json?access_token={access token} | jq '.proxy_config.content.backend_authentication_value'
The output will be the service token. Modify the id
and token
of the spec.config.services
entry in bookinfo/ServiceMeshExtension_bookinfo.yaml
. The id
value should be the product ID.
oc apply -f bookinfo/ServiceMeshExtension_bookinfo.yaml -n bookinfo
- In 3scale, go to Audience
- Choose an account to authorize (you can use the default Developer account)
- Follow the Link at the top of the page that says
N Applications
(N being the number of applications the account has) - Click Create Application
- Select the target application plan and provide a name, then create
You should now have an API key that you can copy and use for authorization
Access without credentials:
curl -v http://istio-ingressgateway-istio-system.{cluster wildcard url}/productpage`
You should see an HTTP 401 response.
Access with credentials (from the previous step):
curl -v http://istio-ingressgateway-istio-system.{cluster wildcard url}/productpage?user_key={user key}
You should see an HTTP 200 response.
Install the Red Hat SSO operator into the keycloak
namespace.
Provision an instance of Keycloak.
oc apply -f keycloak/Keycloak_keycloak.yaml -n keycloak
Wait for all pods to be in a running state.
NOTE: The URL to the Keycloak admin console can be found by listing the routes in the keycloak
namespace, and the administrator credentials can be found in the secret called credential-keycloak
Apply the custom resources provided in this repository in order to leverage the Keycloak operator to create the realm, client, and user.
oc apply -f keycloak/ -n keycloak
More info on the Keycloak operator
At this time it is not possible to configure the necessary service account permissions with custom resources.
To add the permissions in the Red Hat SSO UI:
- Log into RH SSO and select the
Threescale
realm. - Browse to
Clients
and select the3scale-zync
client - Select the
Service Account Roles
tab - Select
realm-management
from theClient Roles
dropdown - Select
manage-clients
from theAvailable Roles
and add it toAssigned Roles
Log into 3scale using the route whose hostname begins with 3scale-admin
in the 3scale
namespace.
NOTE: You will find the admin username and password in a secret called system-seed
in the 3scale
namespace.
- Create a new Product and give it any name
- Go to Integration->Settings and choose
Istio
as the deployment - Go to Integration->Authentication and choose
OpenID Connect Use OpenID Connect for any OAuth 2.0 flow.
as the authentication - Go to Integration->'OpendID Connect (OIDC) Basics' and enter
https://3scale-zync:zync-secret@{keycloak url}/auth/realms/threescale
. Keycloak URL can be obtained using
oc get route keycloak -o jsonpath="{.spec.host}{.spec.path}" -n keycloak
- Go to Integration->'OIDC Authorization Flow' and Select
Authorization Code Flow
andService Accounts Flow
. ClickUpdate Product
at the bottom of the screen - Go to Integration->Configuration and Promote the config
- Go to Overview and create an application plan
- Go to Applications->Application Plans and publish the application plan
- Go to the Product Overview and take note of the ID given to the API by searching for text
ID for API calls is
(This will be used in later steps)
If the Service Entry
for 3scale system-provider and backend are not created earlier then please perform the below step
OSSM ServiceEntries for 3scale-admin and 3scale-backend uses OpenShift service URLs in the 3scale
namespace. So, please go ahead and apply them.
oc apply -f bookinfo/ServiceEntry_system-entry.yaml -f bookinfo/ServiceEntry_backend-entry.yaml -n bookinfo
Request authentication when applied to OSSM will validate the JWT
token and store the contents in an internal metadata object which will be used by the 3scale WASM module to validate against 3scale.
oc get route keycloak -o jsonpath="{.spec.host}{.spec.path}" -n keycloak
Get the Keycloak URL as shown above, modify RequestAuthentication_bookinfo-oidc.yaml
and apply
oc apply -f bookinfo/RequestAuthentication_bookinfo-oidc.yaml -n bookinfo
Copy the ADMIN_ACCESS_TOKEN
key of the system-seed
secret in the 3scale
namespace and replace the value of spec.config.system.token
in bookinfo/ServiceMeshExtension_bookinfo-oidc.yaml
Use 3scale admin access token along with the 3scale product ID from the 3scale product configuration and run the following command with values replaced:
curl https://3scale-admin.{cluster wildcard url}/admin/api/services/{product id}/proxy/configs/production/latest.json?access_token={access token} | jq '.proxy_config.content.backend_authentication_value'
The output will be the service token. Modify the id
and token
of the spec.config.services
entry in bookinfo/ServiceMeshExtension_bookinfo-oidc.yaml
. The id
value should be the product ID.
3scale app_id
for OIDC matches the OAuth's client_id
typically found in the azp
field of the JWT
token. Here is how you can access azp
credentials:
app_id:
- filter:
path:
- envoy.filters.http.jwt_authn
- "0"
keys:
- azp
ops:
- take:
head: 1
Please delete the ServiceMeshExtension
if created before else ignore the step
oc delete sme bookinfo -n bookinfo
Apply the ServiceMesh Extension
oc apply -f bookinfo/ServiceMeshExtension_bookinfo-oidc.yaml -n bookinfo
- In 3scale, go to Audience
- Choose an account to authorize (you can use the default Developer account)
- Follow the Link at the top of the page that says
N Applications
(N being the number of applications the account has) - Click Create Application
- Select the target application plan and provide a name, then create
- This is required to test
Authorization Code flow
. In the current page where application details are shown, underAPI Credentials
section clickEdit
and apply(based on the version of the postman) eitherhttps://oauth.pstmn.io/v1/callback
ORhttps://www.getpostman.com/oauth2/callback
to theRedirect URL
You should now have the Client ID
and Client Secret
. This is needed to test Client Credentials
and Authorization Code
flows.
Access without credentials:
curl -v http://istio-ingressgateway-istio-system.{cluster wildcard url}/api/v1/products
You should see an HTTP 403 response.
Access with JWT
token using Client Credential flow
using the Client ID
and Client Secret
obtained in the previous step:
export SSO_CLIENT_ID=<Client ID>
export SSO_CLIENT_SECRET=<Client Secret>
export SSO_URL=<Keycloak URL>
export TKN=$(curl -k -X POST \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials&client_id=$SSO_CLIENT_ID&client_secret=$SSO_CLIENT_SECRET" \
https://$SSO_URL/auth/realms/threescale/protocol/openid-connect/token \
| sed 's/.*access_token":"//g' | sed 's/".*//g')
curl -v -H "Accept: application/json" -H "Authorization: Bearer $TKN" http://istio-ingressgateway-istio-system.{cluster wildcard url}/api/v1/products
You should see an HTTP 200 response.
Postman will be used to test this flow as it has to open the browser to capture the user credentials. So, please install postman if you do not have it and import the collection from support/postman_collection.json
.
Upon importing change the keycloak_url
, istio-url
, client_id
, client_secret
collection variables as below
- keycloak-url: RH-SSO/Keycloak URL
- istio-url: istio-ingressgateway-istio-system.{cluster wildcard url}
- client_id : Client Id of the 3scale application
- client_secret: Client Secret of the 3scale application
Open OIDC-Bookinfo-OSSM-Auth Flow
request in postman, click Authorization
tab, scroll down and click Get New Access Token
. This will open the browser and asks for user credentials. Please enter user1
and openshift
as username and password. This will generate the JWT token.
Click Use this token
and Click Send
for the request to be successful.