Skip to main content
Redhat Developers  Logo
  • Products

    Featured

    • Red Hat Enterprise Linux
      Red Hat Enterprise Linux Icon
    • Red Hat OpenShift AI
      Red Hat OpenShift AI
    • Red Hat Enterprise Linux AI
      Linux icon inside of a brain
    • Image mode for Red Hat Enterprise Linux
      RHEL image mode
    • Red Hat OpenShift
      Openshift icon
    • Red Hat Ansible Automation Platform
      Ansible icon
    • Red Hat Developer Hub
      Developer Hub
    • View All Red Hat Products
    • Linux

      • Red Hat Enterprise Linux
      • Image mode for Red Hat Enterprise Linux
      • Red Hat Universal Base Images (UBI)
    • Java runtimes & frameworks

      • JBoss Enterprise Application Platform
      • Red Hat build of OpenJDK
    • Kubernetes

      • Red Hat OpenShift
      • Microsoft Azure Red Hat OpenShift
      • Red Hat OpenShift Virtualization
      • Red Hat OpenShift Lightspeed
    • Integration & App Connectivity

      • Red Hat Build of Apache Camel
      • Red Hat Service Interconnect
      • Red Hat Connectivity Link
    • AI/ML

      • Red Hat OpenShift AI
      • Red Hat Enterprise Linux AI
    • Automation

      • Red Hat Ansible Automation Platform
      • Red Hat Ansible Lightspeed
    • Developer tools

      • Red Hat Trusted Software Supply Chain
      • Podman Desktop
      • Red Hat OpenShift Dev Spaces
    • Developer Sandbox

      Developer Sandbox
      Try Red Hat products and technologies without setup or configuration fees for 30 days with this shared Openshift and Kubernetes cluster.
    • Try at no cost
  • Technologies

    Featured

    • AI/ML
      AI/ML Icon
    • Linux
      Linux Icon
    • Kubernetes
      Cloud icon
    • Automation
      Automation Icon showing arrows moving in a circle around a gear
    • View All Technologies
    • Programming Languages & Frameworks

      • Java
      • Python
      • JavaScript
    • System Design & Architecture

      • Red Hat architecture and design patterns
      • Microservices
      • Event-Driven Architecture
      • Databases
    • Developer Productivity

      • Developer productivity
      • Developer Tools
      • GitOps
    • Secure Development & Architectures

      • Security
      • Secure coding
    • Platform Engineering

      • DevOps
      • DevSecOps
      • Ansible automation for applications and services
    • Automated Data Processing

      • AI/ML
      • Data Science
      • Apache Kafka on Kubernetes
      • View All Technologies
    • Start exploring in the Developer Sandbox for free

      sandbox graphic
      Try Red Hat's products and technologies without setup or configuration.
    • Try at no cost
  • Learn

    Featured

    • Kubernetes & Cloud Native
      Openshift icon
    • Linux
      Rhel icon
    • Automation
      Ansible cloud icon
    • Java
      Java icon
    • AI/ML
      AI/ML Icon
    • View All Learning Resources

    E-Books

    • GitOps Cookbook
    • Podman in Action
    • Kubernetes Operators
    • The Path to GitOps
    • View All E-books

    Cheat Sheets

    • Linux Commands
    • Bash Commands
    • Git
    • systemd Commands
    • View All Cheat Sheets

    Documentation

    • API Catalog
    • Product Documentation
    • Legacy Documentation
    • Red Hat Learning

      Learning image
      Boost your technical skills to expert-level with the help of interactive lessons offered by various Red Hat Learning programs.
    • Explore Red Hat Learning
  • Developer Sandbox

    Developer Sandbox

    • Access Red Hat’s products and technologies without setup or configuration, and start developing quicker than ever before with our new, no-cost sandbox environments.
    • Explore Developer Sandbox

    Featured Developer Sandbox activities

    • Get started with your Developer Sandbox
    • OpenShift virtualization and application modernization using the Developer Sandbox
    • Explore all Developer Sandbox activities

    Ready to start developing apps?

    • Try at no cost
  • Blog
  • Events
  • Videos

How to secure microservices with Red Hat Single Sign-On, Fuse, and 3scale

October 30, 2019
raphael abreu
Related topics:
Developer ToolsMicroservicesSecurity
Related products:
Developer ToolsRed Hat 3scale API ManagementRed Hat OpenShift Container Platform

Share:

    In this article, we'll cover microservice security concepts by using protocols such as OpenID Connect with the support of Red Hat Single Sign-On and 3scale. Working with a microservice-based architecture, user identity, and access control in a distributed, in-depth form must be carefully designed. Here, the integration of these tools will be detailed, step-by-step, in a realistic view.

    This article exemplifies the use of tools that can securely run your businesses, avoiding using homemade solutions, and protecting your services by using an API gateway, preventing your applications from being exposed to the public network. The use of an API gateway also provides additional access control, monetization, and analytics.

    security

    Technology Version
    Spring Boot 2.1.8.RELEASE
    Apache Camel 7.4.0.fuse-740036-redhat-00002
    (w/ spring boot 1.5.22.RELEASE)
    3scale 2.6
    Red Hat Single Sign-On (RHSSO) 7.3.3
    (based on keycloak 4.8)

    TL;DR: This is a demonstration of how to protect APIs with Red Hat Single Sign-On (Keycloak) and 3scale.

    How to protect APIs with Red Hat Single Sign-On (Keycloak) and 3scale graphics

    This is a lengthy article with step-by-step instructions, screenshots of products, and architecture concepts. All source code is hosted on GitHub.

    Note: This is a proof of concept. In production environments, additional configurations will be needed regarding scalability, security (refinement) and using a proper CA-trusted certificate.

    The use case scenario

    The main purpose of this tutorial is to achieve concepts regarding the security of microservices using a whole use case scenario. A web app is offered to promote a more natural understanding of all API calls and authorizations used.

    The All APIs catalog is exposed below.

    auth-integration-api endpoints

    :8081

    Method URI Description
    GET /health API actuator embedded health.
    GET /metrics API actuator embedded metrics.

     

     

     

    :8080

    Method URI Description Secured?
    POST /api/v1/product Create a new product. true
    DELETE /api/v1/product/* Delete product by ID. true
    PUT /api/v1/product/* Update product by ID. true
    GET /api/v1/product$ Retrieve all products true
    GET /api/v1/product/* Same as above. true
    GET /api/v1/status Check Integration API health. true
    GET /api/v1/product/status Check Product API health. true
    GET /api/v1/supplier/status Check Supplier API health. true
    GET /api/v1/stock/status Check Stock API health. true
    GET /api/v1/stock/maintenance Call Stock API maintenance. true
    GET /api/v1/supplier/maintenance Call Supplier API maintenance. true

    stock-api endpoints

    Method URI Description
    GET /api/v1/sync Stock Maintenance
    GET /actuator/health Supplier Maintenance

    supplier-api endpoints

    Method URI Description Secured?
    GET /api/v1/sync Supplier Maintenance true
    GET /actuator/health Supplier Maintenance true

    product-api endpoints

    Method URI Description Secured?
    GET /api/v1/product Retrieve all products. true
    GET /api/v1/product/{id} Retrieve product by ID. true
    POST /api/v1/product Create a new product. true
    PUT /api/v1/product/{id} Update product by ID. true
    DELETE /api/v1/product/{id} Delete product by ID. true

    Security lab

    Each endpoint has its own specificity, so to drive our test scenarios, I've ended up with three simple questions:

    • Will this API be protected by an Integration Layer (FUSE)?
    • Will this API be exposed as a unique service on 3scale AMP? (This factor enables API self-service subscriptions for external clients.)
    • Will this API be managed by RHSSO (Keycloak) and have its client-id, groups, and roles?

    So, I came up with the following requirements matrix:

    requirements matrix

    As we can see, each API has differences, and we will strive to demonstrate each one in this microservices security lab.

    Step 1: Project creation

    Create this project as follows:

    export PROJECT_NAMESPACE=microservices
    # login into openshift platform
    oc login https://master.<>.com:443 --token=<>
    # create a new project
    oc new-project microservices-security --description="microservices security" --display-name="microservices-security"

    Step 2: Nexus prototype deploy

    Provide a Sonatype Nexus instance in the microservices namespace. Detailed instructions can be found in this readme.

    Step 3: 3scale AMP deploy

    You must also provision a 3scale AMP into your Red Hat Openshift Container Platform. Refer to the documentation on how to install the 3scale application.

    Step 4: Red Hat Single Sign-On deploy

    Additionally, install Red Hat Single Sign-On for this example. Refer to the documentation on how to install the RHSSO application.

    Step 5: Nexus environment setup

    Set up your Nexus environment as follows:

    export PROJECT_NAMESPACE=microservices-security
    git clone https://github.com/aelkz/microservices-security.git

    cd microservices-security/
    # download maven settings.xml file
    curl -o maven-settings-template.xml -s https://raw.githubusercontent.com/aelkz/microservices-security/master/_configuration/nexus/maven-settings-template.xml
    # change mirror url using your nexus openshift route
    export NEXUS_NAMESPACE=cicd-devtools
    export MAVEN_URL=http://$(oc get route nexus3 -n ${NEXUS_NAMESPACE} --template='{{ .spec.host }}')/repository/maven-group/
    export MAVEN_URL_RELEASES=http://$(oc get route nexus3 -n ${NEXUS_NAMESPACE} --template='{{ .spec.host }}')/repository/maven-releases/
    export MAVEN_URL_SNAPSHOTS=http://$(oc get route nexus3 -n ${NEXUS_NAMESPACE} --template='{{ .spec.host }}')/repository/maven-snapshots/
    awk -v path="$MAVEN_URL" '/<url>/{sub(/>.*</,">"path"<")}1' maven-settings-template.xml > maven-settings.xml
    rm -fr maven-settings-template.xml

    Step 6: Create Red Hat Container Catalog secret

    In order to import Red Hat container images, you must create a secret and set up your credentials on OpenShift:

    NOTE. In order to import Red Hat container images, you must setup your credentials on openshift. See: https://access.redhat.com/articles/3399531
    # The config.json can be found at: /var/lib/origin/.docker/ on openshift master node.
    # create a secret with your container credentials

    export $PROJECT_NAMESPACE=microservices-security

    oc delete secret redhat.io -n $PROJECT_NAMESPACE
    oc create secret generic "redhat.io" --from-file=.dockerconfigjson=config.json --type=kubernetes.io/dockerconfigjson -n $PROJECT_NAMESPACE
    oc create secret generic redhat.io --from-file=.dockerconfigjson=config.json --type=kubernetes.io/dockerconfigjson -n $PROJECT_NAMESPACE
    oc secrets link default redhat.io --for=pull -n $PROJECT_NAMESPACE
    oc secrets link builder redhat.io -n $PROJECT_NAMESPACE

    Step 7: RHSSO realms configuration

    In this step, we will configure realms on RHSSO to register all five applications.

    1. Logging into RHSSO.
    2. Create three realms with default settings:
      • 3scale-api
      • 3scale-admin
      • 3scale-devportal

    After creating the realms, you'll have something like this:

    RHSSO realms configuration

    1. On the 3scale-api realm, create a client 3scale with the following definition:

    create a client 3scale figure

    Leave these fields blank:

      • root URL
      • base URL
      • admin URL
    1. On the Service Account Roles tab, assign the role manage-clients from realm-management.
    2. Copy and save the client-secret that was generated for this client. This secret will be used later to configure OAuth service authentication on 3scale, and will look something like this: 823b6ek5-1936-42e6-1135-d48rt3a1f632.
    3. Under the realm 3scale-api, create a new user with the following definition:

    create a new user image

    1. Set a new password for this user on the Credentials tab with temporary=false.
    2. Set the Email Verified attribute totrue on the Details tab.

    Step 8: 3scale microservices configuration

    In this step, we register the APIs and configure them to enable 3scale automatic synchronization with RHSSO. Let's set up the auth-integration-api and the supplier-api:

    1. Create a new API on the 3scale admin portal. You can hit the NEW API button on the main dashboard:

    Create a new API on the 3scale admin portal image

    This new API will represent the auth-integration-api, which we previously deployed:

    new API screen

    1. Navigate through the Configuration menu under Integration to set up the API mappings and security:

    Set up the API mappings and security screen

    1. Choose APIcast for the gateway:

    Choose APIcast for the gateway

    1. Choose OpenID Connect in Integration settings:

    Choose OpenID Connect in Integration settings

    Note: OpenID Connect is chosen because we will to protect our APIs with the OAuth2 capabilities provided by RHSSO.

    1. Click:

    Add base url of API and Save configuration

    1. Define the Private Base URL (your auth-integration-api URL), the Staging Public Base URL, and the Production Public Base URL:

    Enter Correct domain under each URL

    Note: Set the correct domain under each URL, which will become your API route on OpenShift.

    1. Define all of the mapping rules for this API, according to the following table:
    Verb Pattern + Metric or Method
    POST /api/v1/product 1 hits
    DELETE /api/v1/product/* 1 hits
    PUT /api/v1/product/* 1 hits
    GET /api/v1/product$ 1 hits
    GET /api/v1/product/* 1 hits
    GET /api/v1/status 1 hits
    GET /api/v1/product/status 1 hits
    GET /api/v1/supplier/status 1 hits
    GET /api/v1/stock/status 1 hits
    GET /api/v1/stock/maintenance 1 hits
    GET /api/v1/supplier/maintenance 1 hits
    1. Define the authentication mechanism for this API:

    Define the authentication mechanism for this API

    1. Configure the API policies required to enable proper communication between resources inside the OpenShift Container Platform:
    Configure the API policies
    Please follow the next steps carefully:
    1. Select Authorization Code Flow, Service Accounts Flow, and Direct Access Grant Flow under the OIDC AUTHORIZATION FLOW section.
    2. In Credentials location set As HTTP Headers.
    3. In the Policies section, add (in this order) CORS and 3scale APIcast.
    4. Expand CORS configuration, and set the following:
      • ALLOW_HEADERS adds a 1x1 per input array:
    Enabled=checked
    ALLOW_HEADERS
    3scale CORS Policy: HEADERS
    Content-Type
    Authorization
    Content-Length
    X-Requested-With
    Origin
    Accept
    X-Requested-With
    Content-Type
    Access-Control-Request-Method
    Access-Control-Request-Headers
    Accept-Encoding
    Accept-Language
    Connection
    Host
    Referer
    User-Agent
    Access-Control-Allow-Origin
    X-Business-FooBar

    Note: The last header is used only for testing purposes.

      • ALLOW_METHODS adds a 1x1 per input array:
    allow_credentials=checked
    ALLOW_METHODS
    
    3scale CORS Policy: HTTP Methods
    GET
    HEAD
    POST
    PUT
    DELETE
    OPTIONS
    1. Leave allow_origin empty, and the rest as default.
    2. Save the CORS configuration.

    Note: After every change, remember to promote the staging configuration to production, by clicking:
    Promote the staging configuration to production

    Your auth-integration-api is ready to be used.

    Repeat the same sequence of steps in this section for the Supplier API. This API has only two mapping rules:

    Verb Pattern + Metric or Method
    POST /api/v1/sync 1 hits
    GET /actuator/health 1 hits

    Step 9: 3scale microservices application plans

    Let's define the API's application plans. These plans will be used upon client registration for creating a new application:

    3scale microservices application plans

    Click Click on Create Application Plan under the Applications/Application Plans menu, then set the following configuration:

    Create Application Plan

    After doing this, click the Publish link to publish the application plan.

    Follow the same steps for the Supplier API. Remember to publish this application plan as well.

    After you have done all of the previous steps, you'll get something like this:

    Publish the Application plan

    Step 10: 3scale microservices application

    Navigate through the Audience menu and under Accounts/Listing, click Create a new account to create a new account. Then, create a new account with your credentials for this demo:

    Create New Account screen

    This action creates a new 3scale application. If the application couldn't be created, just hit the Create Application Link link.

    This new application is created for use with the auth-integration-api. A client-id and a Client-Secret will be generated automatically and pushed into RHSSO in the 3Scale-api realm by the zynnc-que 3scale application:

    A client-id screen

    After creating the API definition on 3scale, check if the generated client was pushed into the 3scale-api realm on RHSSO. If you're using a self-signed certificate, you'll need to make additional configurations in order to enable zynnc-que 3scale application synchronization. Please refer to the Documentation: Troubleshooting SSL issues and Configure Zync to use custom CA certificates.

    To fix this problem, proceed with the self-signed certificate installation:

    export THREESCALE_NAMESPACE=3scale26
    export THREESCALE_ZYNC_QUE_POD=$(oc get pods --selector deploymentconfig=zync-que -n 3scale26 | { read line1 ; read line2 ; echo "$line2" ; } | awk '{print $1;}')
    export RHSSO_URI=sso73.apps.<YOUR-DOMAIN>.com
    echo | openssl s_client -showcerts -servername ${RHSSO_URI} -connect ${RHSSO_URI}:443 2>/dev/null | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > self-signed-cert.pem

    # Validate the connection first! must return HTTP/1.1 200 OK
    curl -v https://${RHSSO_URI}/auth/realms/master --cacert self-signed-cert.pem
    oc exec ${THREESCALE_ZYNC_QUE_POD} cat /etc/pki/tls/cert.pem > zync-que.pem -n ${THREESCALE_NAMESPACE}
    cp zync-que.pem zync-que-original.pem
    echo '\n# Red Hat Single Sign-On CA '${RHSSO_URI} >> zync-que.pem
    cat self-signed-cert.pem >> zync-que.pem

    # oc delete configmap zync-que-ca-bundle
    oc create configmap zync-que-ca-bundle --from-file=./zync-que.pem -n ${THREESCALE_NAMESPACE}
    oc label configmap zync-que-ca-bundle app=3scale-api-management -n ${THREESCALE_NAMESPACE}
    oc set volume dc/zync-que --overwrite --add --name=zync-que-ca-bundle --mount-path /etc/pki/tls/zync-que/zync-que.pem --sub-path zync-que.pem --source='{"configMap":{"name":"zync-que-ca-bundle","items":[{"key":"zync-que.pem","path":"zync-que.pem"}]}}' -n ${THREESCALE_NAMESPACE}

    oc patch dc/zync-que --type=json -p '[{"op": "add", "path": "/spec/template/spec/containers/0/volumeMounts/0/subPath", "value":"zync-que.pem"}]' -n ${THREESCALE_NAMESPACE}
    oc exec ${THREESCALE_ZYNC_QUE_POD} cat /etc/pki/tls/zync-que/zync-que.pem -n ${THREESCALE_NAMESPACE}
    oc set env dc/zync-que SSL_CERT_FILE=/etc/pki/tls/zync-que/zync-que.pem -n ${THREESCALE_NAMESPACE}

    # wait for the container restart and check the logs for any issue.
    oc logs -f po/${THREESCALE_ZYNC_QUE_POD}

    # Voila! You have the 3Scale in sync with RHSSO using a self-signed certificate.

    Step 11: Node.js web application deployment

    In this step, we will test all scenarios with a suited NodeJS webapp based on Angular and Bootstrap. This application was designed to ease the understanding process and can be used to give clarification regarding the authorization behavior using our Jon Doe user account:

    # Deploy nodejs-web application
    # https://access.redhat.com/containers/?tab=images#/registry.access.redhat.com/rhscl/nodejs-10-rhel7

    oc import-image rhscl/nodejs-10-rhel7 --from=registry.redhat.io/rhscl/nodejs-10-rhel7 -n openshift --confirm

    export APIS_NAMESPACE=microservices-security
    export THREESCALE_NAMESPACE=3scale26
    export RHSSO_NAMESPACE=sso73
    export RHSSO_URL=https://$(oc get route -n ${RHSSO_NAMESPACE} | grep secured | awk '{print $2;}')/auth
    export THREESCALE_APP_DOMAIN=<YOUR-DOMAIN>.com
    export THREESCALE_API_URL=https://$(oc get routes -n ${THREESCALE_NAMESPACE} | grep auth-integration | grep production | awk '{print $2;}')
    export INTEGRATION_HEALTH_URL=http://$(oc get routes -n ${APIS_NAMESPACE} | grep auth-integration | grep metrics | awk '{print $2;}')

    echo -e \
    " AUTH_CLIENT_ID=<AUTH_INTEGRATION_CLIENT_ID>\n" \
    "AUTH_URL=${RHSSO_URL}\n" \
    "AUTH_REALM=3scale-api\n" \
    "KEYCLOAK=true\n" \
    "INTEGRATION_URI=${THREESCALE_API_URL}\n" \
    "PRODUCT_PATH=/product\n" \
    "STOCK_PATH=/stock\n" \
    "SUPPLIER_PATH=/supplier\n" \
    "AUTH_CLIENT_SECRET=1d1beebcF1cJd002d51be7a346ab987p\n" \
    "NODE_TLS_REJECT_UNAUTHORIZED=0\n" \
    > temp

    sed "s/^.//g" temp >> nodejs-config.properties

    rm -fr temp

    # oc delete configmap nodejs-web-config
    oc create configmap nodejs-web-config \
    --from-literal=AUTH_CLIENT_ID= \
    --from-literal=AUTH_URL= \
    --from-literal=AUTH_REALM= \
    --from-literal=KEYCLOAK= \
    --from-literal=INTEGRATION_URI= \
    --from-literal=PRODUCT_PATH= \
    --from-literal=SUPPLIER_PATH= \
    --from-literal=STOCK_PATH= \
    --from-literal=AUTH_CLIENT_SECRET= \
    --from-literal=NODE_TLS_REJECT_UNAUTHORIZED=

    # oc delete all -lapp=nodejs-web
    oc new-app nodejs-10-rhel7:latest~https://github.com/aelkz/microservices-security.git --name=nodejs-web --context-dir=/webapp -n ${APIS_NAMESPACE}

    # with the properties defined, set the environment variable on nodejs-web container.
    oc set env --from=configmap/nodejs-web-config dc/nodejs-web -n ${APIS_NAMESPACE}

    Note: Set all environment variables on the nodejs-web container in order to enable API calls properly.

    Expose the web app route:

    oc create route edge --service=nodejs-web --cert=webapp/server.cert --key=webapp/server.key -n ${APIS_NAMESPACE}

    Step 12: Application settings and roles

    Now we create our application roles. These roles are assigned to the application users that will be used to log into our web app.

    Access the client-id that represents the auth-integration client registered previously by the 3scale application process, then go to the client's Settings tab and apply additional configurations. Valid redirect URIs include:

    http://*
    https://*

    and valid web origins are simply:

    *

    Go to the Roles tab on the Clients menu on RHSSO (Keycloak) and create the following roles:

    Create Roles into Roles tab

    Repeat the same steps for the Supplier API client. This client will have only one role defined:

    Supplier API Client screen

    Note: This client was also generated through 3scale. (You must create two applications: one for auth-integration-api and another for supplier-api.

    Step 13: User roles

    In this step, we assign all client roles to the john doe user and the service-account user will handle the supplier-service calls inside the auth-integration-api.

    Go to the Role Mappings tab on the John Doe user details page in the Users menu. Assign all roles to the user, following the image below:

    Go to the Role Mappings tab and Assign all roles to the user

    In Step 7 we created the John Doe user. We need to create another user that will be used as a service-account to call the Supplier API inside the auth-integration-api (see line 123 of application.yaml). This user will also have a password, so reset its credentials with 12345. The name of this user can be the id of the Supplier API client-id generated by 3scale appended with the _svcacc suffix (see line 131 of application.yaml).

    We also need to assign the SUPPLIER_MAINTAINER role to this user.

    NOTE: This procedure is used as an alternative to the token-exchange mechanism, but we could do a more detailed study of other possibilities of consuming third-party APIs by using the token-exchange feature.

    At last, create a realm-admin user. This user will serve to consume the RHSSO REST API. Assign the credentials 12345 and all realm-management roles:

    Realm admin, role mapping

    In the end, we will have three users in the 3scale-api realm:

    Three users in the 3scale-api realm screen

    Step 14: Archive the SSO-common library jar on Nexus

    To make sure the auth-integration-api (Fuse) works correctly, we need to archive a library, and then use that library to enable authentication and authorizations on top of Red Hat Single Sign-On:

    # NOTE: To make sure the auth-integration-api (Fuse) works correctly, we need to archive a library that will be used to provide authentication and authorizations capabilities on top of Red Hat Single Sign-On (Keycloak).Then, this library will be used on auth-integration-api to enable such capabilities.

    # Deploy auth-sso-common library on nexus
    export NEXUS_NAMESPACE=cicd-devtools
    export MAVEN_URL=http://$(oc get route nexus3 -n ${NEXUS_NAMESPACE} --template='{{ .spec.host }}')/repository/maven-group/
    export MAVEN_URL_RELEASES=http://$(oc get route nexus3 -n ${NEXUS_NAMESPACE} --template='{{ .spec.host }}')/repository/maven-releases/
    export MAVEN_URL_SNAPSHOTS=http://$(oc get route nexus3 -n ${NEXUS_NAMESPACE} --template='{{ .spec.host }}')/repository/maven-snapshots/

    mvn clean package deploy -DnexusReleaseRepoUrl=$MAVEN_URL_RELEASES -DnexusSnapshotRepoUrl=$MAVEN_URL_SNAPSHOTS -s ./maven-settings.xml -e -X -pl auth-sso-common 

    This action creates the following artifact on Nexus:
    Archive the SSO-common library jar on Nexus

    Step 15: Microservices deployment

    Retrieve RHSSO realm public key:

    export RHSSO_REALM=3scale-api
    export RHSSO_URI=sso73.apps.<YOUR-DOMAIN>.com
    export TOKEN_URL=https://${RHSSO_URI}/auth/realms/${RHSSO_REALM}/protocol/openid-connect/token
    export THREESCALE_REALM_USERNAME=admin
    export THREESCALE_REALM_PASSWORD=12345

    TKN=$(curl -k -X POST "$TOKEN_URL" \
    -H "Content-Type: application/x-www-form-urlencoded" \
    -d "username=$THREESCALE_REALM_USERNAME" \
    -d "password=$THREESCALE_REALM_PASSWORD" \
    -d "grant_type=password" \
    -d "client_id=admin-cli" \
    | sed 's/.*access_token":"//g' | sed 's/".*//g')

    export REALM_KEYS_URL=https://${RHSSO_URI}/auth/admin/realms/${RHSSO_REALM}/keys

    RSA_PUB_KEY=$(curl -k -X GET "$REALM_KEYS_URL" \
    -H "Authorization: Bearer $TKN" \
    | jq -r '.keys[] | select(.type=="RSA") | .publicKey' )

    # Create a valid .pem certificate
    REALM_CERT=$RHSSO_REALM.pem
    echo "-----BEGIN CERTIFICATE-----" > $REALM_CERT; echo $RSA_PUB_KEY >> $REALM_CERT; echo "-----END CERTIFICATE-----" >> $REALM_CERT

    # Check the generated .pem certificate
    # fold -s -w 64 $REALM_CERT > $RHSSO_REALM.fixed.pem
    # openssl x509 -in $RHSSO_REALM.fixed.pem -text -noout
    # openssl x509 -in $RHSSO_REALM.fixed.pem -noout -issuer -fingerprint

    Then, deploy the parent project:

    # Deploy parent project on nexus
    mvn clean package deploy -DnexusReleaseRepoUrl=$MAVEN_URL_RELEASES -DnexusSnapshotRepoUrl=$MAVEN_URL_SNAPSHOTS -s ./maven-settings.xml -e -X -N

    Now, deploy the stock-api:

    # oc delete all -lapp=stock-api
    oc new-app openjdk-8-rhel8:latest~https://github.com/aelkz/microservices-security.git --name=stock-api --context-dir=/stock --build-env='MAVEN_MIRROR_URL='${MAVEN_URL} -e MAVEN_MIRROR_URL=${MAVEN_URL}

    oc patch svc stock-api -p '{"spec":{"ports":[{"name":"http","port":8080,"protocol":"TCP","targetPort":8080}]}}'

    oc label svc stock-api monitor=springboot2-api

    Use the provided configmap and secret to set the required variables:

    oc create -f configuration/configmap/stock-api-env.yml -n ${PROJECT_NAMESPACE}
    oc create -f configuration/secret/stock-api.yml -n ${PROJECT_NAMESPACE}

    export APP=stock-api
    oc set env dc/${APP} --from=secret/stock-api-secret
    oc set env dc/${APP} --from=configmap/stock-api-config

    Deploy the supplier-api, but first check all settings in the application.yaml file before continuing. The attributes here must be updated to reflect your actual environment:

    • rest.security.issuer-uri on Line 61.
    • security.oauth2.resource.id on Line 71.
    • security.oauth2.resource.jwt.key-value on Line 75.

    # oc delete all -lapp=supplier-api
    oc new-app openjdk-8-rhel8:latest~https://github.com/aelkz/microservices-security.git --name=supplier-api --context-dir=/supplier --build-env='MAVEN_MIRROR_URL='${MAVEN_URL} -e MAVEN_MIRROR_URL=${MAVEN_URL}

    oc patch svc supplier-api -p '{"spec":{"ports":[{"name":"http","port":8080,"protocol":"TCP","targetPort":8080}]}}'

    oc label svc supplier-api monitor=springboot2-api

    Use the provided configmap and secret to set the required variables:

    oc create -f configuration/configmap/supplier-api-env.yml -n ${PROJECT_NAMESPACE}
    oc create -f configuration/secret/supplier-api.yml -n ${PROJECT_NAMESPACE}

    export APP=supplier-api

    oc set env dc/${APP} --from=secret/supplier-api-secret
    oc set env dc/${APP} --from=configmap/supplier-api-config

    Deploy the product-api, but again, check all settings in the application.yaml file before continuing. The following attributes must be updated to reflect your actual environment: rest.security.issuer-uri on Line 61, and thesecurity.oauth2.resource.jwt.key-value on Line 75:

    # oc delete all -lapp=product-api
    oc new-app openjdk-8-rhel8:latest~https://github.com/aelkz/microservices-security.git --name=product-api --context-dir=/product --build-env='MAVEN_MIRROR_URL='${MAVEN_URL} -e MAVEN_MIRROR_URL=${MAVEN_URL}

    oc patch svc product-api -p '{"spec":{"ports":[{"name":"http","port":8080,"protocol":"TCP","targetPort":8080}]}}'

    oc label svc product-api monitor=springboot2-api

    Use the provided configmap and secret to set the required variables:

    oc create -f configuration/configmap/product-api-env.yml -n ${PROJECT_NAMESPACE}
    oc create -f configuration/secret/product-api.yml -n ${PROJECT_NAMESPACE}

    export APP=supplier-api

    oc set env dc/${APP} --from=secret/product-api-secret
    oc set env dc/${APP} --from=configmap/product-api-config

    Step 16: Integration deployment (FUSE)

    Now that the microservices APIs are deployed, let’s deploy the integration layer:

    # import a new spring-boot camel template
    curl -o s2i-microservices-fuse74-spring-boot-camel.yaml -s https://raw.githubusercontent.com/aelkz/microservices-security/master/_configuration/openshift/s2i-microservices-fuse74-spring-boot-camel.yaml

    oc delete template s2i-microservices-fuse74-spring-boot-camel -n ${PROJECT_NAMESPACE}
    oc create -n ${PROJECT_NAMESPACE} -f s2i-microservices-fuse74-spring-boot-camel.yaml

    # NOTE. You may want to check the ..self-signed.yaml template as it uses a customized imagestream for use with self-signed certificates. (see the APPENDIX-README.md for for info)
    export NEXUS_NAMESPACE=cicd-devtools
    export PROJECT_NAMESPACE=microservices-security
    export APP=auth-integration-api
    export APP_NAME=auth-integration
    export APP_GROUP=com.redhat.microservices
    export APP_GIT=https://github.com/aelkz/microservices-security.git
    export APP_GIT_BRANCH=master
    export MAVEN_URL=http://$(oc get route nexus3 -n ${NEXUS_NAMESPACE} --template='{{ .spec.host }}')/repository/maven-group/
    export CUSTOM_TEMPLATE=s2i-microservices-fuse74-spring-boot-camel-selfsigned

    # the previous template have some modifications regarding services,route and group definitions.
    # oc delete all -lapp=${APP}
    oc new-app --template=${CUSTOM_TEMPLATE} --name=${APP} --build-env='MAVEN_MIRROR_URL='${MAVEN_URL} -e MAVEN_MIRROR_URL=${MAVEN_URL} --param GIT_REPO=${APP_GIT} --param APP_NAME=${APP} --param ARTIFACT_DIR=${APP_NAME}/target --param GIT_REF=${APP_GIT_BRANCH} --param MAVEN_ARGS_APPEND='-pl '${APP_NAME}' --also-make'

    # Use this param if using a different TAG (example)
    # --param BUILDER_VERSION=2.0

    # check the created services:
    # 1 for default app-context and 1 for /metrics endpoint.
    oc get svc -n ${PROJECT_NAMESPACE} | grep ${APP_NAME}

    # in order to auth-integration-api call the others APIs, we need to change it's configuration:
    curl -o application.yaml -s https://raw.githubusercontent.com/aelkz/microservices-security/master/_configuration/openshift/auth-integration/application.yaml

    # NOTE. If you have changed the service or application's name, you need to edit and change the downloaded application.yaml file with your definitions.

    # create a configmap and mount a volume for auth-integration-api
    oc delete configmap ${APP} -n ${PROJECT_NAMESPACE}

    oc create -f configuration/configmap/auth-integration-api-env.yml -n ${PROJECT_NAMESPACE}
    oc create -f configuration/secret/auth-integration-api.yml -n ${PROJECT_NAMESPACE}

    oc set env dc/${APP} --from=secret/auth-integration-api-secret
    oc set env dc/${APP} --from=configmap/auth-integration-api-config

    Note: All application roles are prefixed with ROLE_ on source-code. This prefix can be changed if you want on line 80 in the ../configuration/security/JwtAccessTokenCustomizer.java class. On RHSSO, these roles are registered without this prefix. See this stack overflow reference.

    Step 17: Testing the NodeJS application with Red Hat Single Sign-On

    Open the NodeJS web app in your browser:

    export MICROSERVICES_NAMESPACE=microservices-security
    echo http://$(oc get route nodejs-web -n ${MICROSERVICES_NAMESPACE} --template='{{ .spec.host }}')

    If you're using a self-signed certificate, the browser will request authorization to open an insecure URL. Navigate through the menus and test all actions by clicking on every button to see the final result. If an action returns 401 or 403, there is probably pending configuration on 3scale, or missing or invalid credentials on some application. If you get HTTP error 500, maybe the application is unavailable. Try changing Jon Doe roles and check every situation after refreshing the access token:

    Testing the NodeJS application with Red Hat Single Sign-On

    (Click on the image to see it larger.)

    Testing the NodeJS application with Red Hat Single Sign-On

    I hope you enjoyed this tutorial. The troubleshooting was somewhat difficult because of all the OAuth2 adapters and security mechanisms involved. Please let me know if you want to improve something, or add more context to this PoC. Thank you.

    References

    • API Key Generator
    • JWT Key Generator
    • OpenID Connect Debugger
    • Generate Plain Old Java Objects from JSON or JSON-Schema
    • Securing REST API using Keycloak and Spring Oauth2 (@bcarun)
    • Keycloak: A real Scenario from Development to Production
    • HOW-TO setup 3scale OpenID Connect (OIDC) Integration with RH SSO
    • Red Hat Openshift Single Sign-On Secured N-tier application (@mechevarria)
    Last updated: October 31, 2023

    Recent Posts

    • Storage considerations for OpenShift Virtualization

    • Upgrade from OpenShift Service Mesh 2.6 to 3.0 with Kiali

    • EE Builder with Ansible Automation Platform on OpenShift

    • How to debug confidential containers securely

    • Announcing self-service access to Red Hat Enterprise Linux for Business Developers

    Red Hat Developers logo LinkedIn YouTube Twitter Facebook

    Products

    • Red Hat Enterprise Linux
    • Red Hat OpenShift
    • Red Hat Ansible Automation Platform

    Build

    • Developer Sandbox
    • Developer Tools
    • Interactive Tutorials
    • API Catalog

    Quicklinks

    • Learning Resources
    • E-books
    • Cheat Sheets
    • Blog
    • Events
    • Newsletter

    Communicate

    • About us
    • Contact sales
    • Find a partner
    • Report a website issue
    • Site Status Dashboard
    • Report a security problem

    RED HAT DEVELOPER

    Build here. Go anywhere.

    We serve the builders. The problem solvers who create careers with code.

    Join us if you’re a developer, software engineer, web designer, front-end designer, UX designer, computer scientist, architect, tester, product manager, project manager or team lead.

    Sign me up

    Red Hat legal and privacy links

    • About Red Hat
    • Jobs
    • Events
    • Locations
    • Contact Red Hat
    • Red Hat Blog
    • Inclusion at Red Hat
    • Cool Stuff Store
    • Red Hat Summit
    © 2025 Red Hat

    Red Hat legal and privacy links

    • Privacy statement
    • Terms of use
    • All policies and guidelines
    • Digital accessibility

    Report a website issue