Enabling generative AI through the model gateway

The model gateway provides a unified platform infrastructure that enables access to multiple large language model (LLM) providers. This vendor-agnostic approach gives you the flexibility to choose the optimal AI model for each workflow task, while maintaining centralized governance, security, and cost optimization.

The model gateway supports connections to multiple LLM providers, including IBM watsonx.ai, OpenAI, Google Gemini, and AWS Bedrock. The list of available models is dynamically generated based on what is configured in the model gateway.

Deploying the model gateway

A script automates the deployment of the model gateway operator in your environment, and handles the complete deployment lifecycle, including prerequisites verification, operator installation, and instance configuration. Configuration of the AI provider is done post deployment.

For more information, see Installing IBM Model Gateway.

Remember: The model gateway used in this deployment is provisioned and configured through an automated process. As a result, some configuration and setup procedures described in the general model gateway documentation might not apply.

Prerequisites

  • The model gateway is deployed in your Cloud Pak for Business Automation environment.
  • Access to one or more LLM provider accounts.
  • Appropriate credentials and API keys for your chosen LLM providers configured in the model gateway.

Configuring the model gateway connection in Cloud Pak for Business Automation

When the model gateway is deployed in your environment, the installation process creates a service ID, which Cloud Pak for Business Automation uses to authenticate and connect to the model gateway.

A reference to this service ID is configured in the gateway API, enabling access to the large language models (LLMs) that are registered with the gateway. Access to specific models is controlled through gateway access policies, which define the permissions granted to each service ID or user.

The credentials that are associated with the service ID are managed within your environment and are used by Cloud Pak for Business Automation to establish secure communication with the model gateway. Depending on your security requirements, you might need to update these credentials, for example, if an API key is rotated, revoked, or replaced.

If required, you can update the API key that is associated with the service ID. For more information, see Managing the model gateway API key.

For generative AI usage information, see Adding a generative AI task to a service flow.

Managing the model gateway API key

The operator automatically creates and manages authentication credentials for connecting to the model gateway. Use the following information to understand how to locate, view, rotate, and troubleshoot the API key that is used for model gateway authentication.

When the operator detects a model gateway service in the namespace, it automatically:
  1. Creates a service ID in IAM/Zen for model gateway authentication.
  2. Generates an API key for the service ID.
  3. Stores credentials in Kubernetes secrets.
  4. Configures authentication in the authoring and runtime environments.
Creating Kubernetes secrets
The operator creates two secrets in your namespace:
Table 1. Kubernetes secrets
Secret name Purpose Contents
ai-gateway-credentials Stores the service ID. serviceId: The IAM Service ID username
ai-gateway-api-key Stores the API key. apiKey: The authentication password or token
Retrieving the service ID
To retrieve the service ID stored in the ai-gateway-credentials Kubernetes secret in the specified namespace, use the following command.

# Set your namespace
export NAMESPACE=<your-cp4ba-namespace>

# Get the Service ID
kubectl get secret ai-gateway-credentials -n $NAMESPACE -o jsonpath='{.data.serviceId}' | base64 -d
echo
Example output: ServiceId-a1b2c3d4-e5f6-7890-abcd-ef1234567890
Retrieving the API key
To retrieve the API key stored in the ai-gateway-api-key Kubernetes secret in the namespace, use the following command:

# Set your namespace
export NAMESPACE=<your-cp4ba-namespace>

# Get the API Key
kubectl get secret ai-gateway-api-key -n $NAMESPACE -o jsonpath='{.data.apiKey}' | base64 -d
echo
Example output: abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOP
Rotating the API key automatically (recommended method)
You can rotate (regenerate) the API key and service credentials that are used by the model gateway by deleting the existing Kubernetes secrets and allowing the operator to automatically recreate them.
  • Delete the secrets and let the operator recreate them:
    # Set your namespace
    export NAMESPACE=<your-cp4ba-namespace>
    
    # Delete both secrets
    kubectl delete secret ai-gateway-credentials -n $NAMESPACE
    kubectl delete secret ai-gateway-api-key -n $NAMESPACE
    
  • The operator automatically:
    • Detects the missing secrets
    • Creates a new service ID in IAM/Zen.
    • Generates a new API key.
    • Recreates the secrets.
    • Updates all CP4BA components.
  • Wait for reconciliation to complete (typically 1-5 minutes).
  • Verify that the new secrets are created:
    kubectl get secrets -n $NAMESPACE | grep ai-gateway
Rotating the API key manually (through Zen API)
Alternatively, for more control over the rotation process, you can generate a new API key using the Zen API:
  1. Retrieve the required information:
    export NAMESPACE=<your-cp4ba-namespace>
    
    # Get the Service ID
    SERVICE_ID=$(kubectl get secret ai-gateway-credentials -n $NAMESPACE -o jsonpath='{.data.serviceId}' | base64 -d)
    echo "Service ID: $SERVICE_ID"
    
    # Get the Service ID secret (client secret)
    SERVICE_SECRET=$(kubectl get secret ai-gateway-credentials -n $NAMESPACE -o jsonpath='{.data.serviceSecret}' | base64 -d)
    
    # Get the common services namespace (where IAM is running)
    COMMON_SERVICES_NS=$(kubectl get pods --all-namespaces | grep platform-identity-provider | awk '{print $1}' | head -1)
    echo "Common Services Namespace: $COMMON_SERVICES_NS"
    
  2. Get the IAM access token:
    # Get IAM token for the Service ID
    IAM_TOKEN_RESPONSE=$(curl -k -X POST \
      "https://platform-identity-provider.${COMMON_SERVICES_NS}.svc:4300/v1/auth/token" \
      -H "Content-Type: application/x-www-form-urlencoded" \
      -d "grant_type=client_credentials&scope=openid&client_id=${SERVICE_ID}&client_secret=${SERVICE_SECRET}")
    
    # Extract access token
    IAM_ACCESS_TOKEN=$(echo $IAM_TOKEN_RESPONSE | jq -r '.access_token')
    
    if [ "$IAM_ACCESS_TOKEN" == "null" ] || [ -z "$IAM_ACCESS_TOKEN" ]; then
      echo "ERROR: Failed to get IAM access token"
      echo "Response: $IAM_TOKEN_RESPONSE"
      exit 1
    fi
    
    echo "IAM Access Token obtained successfully"
    
  3. Exchange the IAM token for a Zen token:
    # Exchange IAM token with Zen token
    ZEN_TOKEN_RESPONSE=$(curl -k -X GET \
      "https://ibm-nginx-svc.${NAMESPACE}.svc/v1/preauth/validateAuth" \
      -H "username: ${SERVICE_ID}" \
      -H "iam-token: ${IAM_ACCESS_TOKEN}")
    
    # Extract Zen token
    ZEN_TOKEN=$(echo $ZEN_TOKEN_RESPONSE | jq -r '.accessToken')
    
    if [ "$ZEN_TOKEN" == "null" ] || [ -z "$ZEN_TOKEN" ]; then
      echo "ERROR: Failed to get Zen token"
      echo "Response: $ZEN_TOKEN_RESPONSE"
      exit 1
    fi
    
    echo "Zen Token obtained successfully"
    
  4. Generate the new API key:
    # Generate new API key
    API_KEY_RESPONSE=$(curl -k -X POST \
      "https://usermgmt-svc.${NAMESPACE}.svc:3443/v1/user/apiKey" \
      -H "Authorization: Bearer ${ZEN_TOKEN}" \
      -H "username: ${SERVICE_ID}")
    
    # Extract the new API key
    NEW_API_KEY=$(echo $API_KEY_RESPONSE | jq -r '.apiKey')
    
    if [ "$NEW_API_KEY" == "null" ] || [ -z "$NEW_API_KEY" ]; then
      echo "ERROR: Failed to generate API key"
      echo "Response: $API_KEY_RESPONSE"
      exit 1
    fi
    
    echo "New API Key generated successfully"
    echo "API Key: $NEW_API_KEY"
    
  5. Update the Kubernetes secret:
    # Update the secret with the new API key
    kubectl create secret generic ai-gateway-api-key \
      --from-literal=apiKey=$NEW_API_KEY \
      --dry-run=client -o yaml | kubectl apply -n $NAMESPACE -f -
    
    # Verify the secret was updated
    echo "Verifying secret update..."
    STORED_KEY=$(kubectl get secret ai-gateway-api-key -n $NAMESPACE -o jsonpath='{.data.apiKey}' | base64 -d)
    
    if [ "$STORED_KEY" == "$NEW_API_KEY" ]; then
      echo "✓ Secret updated successfully"
    else
      echo "✗ ERROR: Secret update failed"
      exit 1
    fi
    
  6. Restart the operator:
    # Restart the CP4BA operator to trigger reconciliation
    kubectl delete pod -n $NAMESPACE -l name=ibm-cp4a-operator
    
    # Wait for operator to be ready
    kubectl wait --for=condition=ready pod -n $NAMESPACE -l name=ibm-cp4a-operator --timeout=120s
    
    echo "✓ Operator restarted successfully"
    
    # The operator will automatically update all component configurations
    
For convenience, here is the end-to-end script:
#!/bin/bash
# rotate-ai-gateway-api-key.sh
# Usage: ./rotate-ai-gateway-api-key.sh <namespace>

set -e

NAMESPACE=${1:-cp4ba}

echo "=== AI Model Gateway API Key Rotation ==="
echo "Namespace: $NAMESPACE"
echo ""

# Step 1: Get Service ID and credentials
echo "Step 1: Retrieving Service ID..."
SERVICE_ID=$(kubectl get secret ai-gateway-credentials -n $NAMESPACE -o jsonpath='{.data.serviceId}' | base64 -d)
SERVICE_SECRET=$(kubectl get secret ai-gateway-credentials -n $NAMESPACE -o jsonpath='{.data.serviceSecret}' | base64 -d)
COMMON_SERVICES_NS=$(kubectl get pods --all-namespaces | grep platform-identity-provider | awk '{print $1}' | head -1)
echo "✓ Service ID: $SERVICE_ID"
echo "✓ Common Services NS: $COMMON_SERVICES_NS"

# Step 2: Get IAM token
echo ""
echo "Step 2: Getting IAM access token..."
IAM_TOKEN_RESPONSE=$(curl -k -s -X POST \
  "https://platform-identity-provider.${COMMON_SERVICES_NS}.svc:4300/v1/auth/token" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials&scope=openid&client_id=${SERVICE_ID}&client_secret=${SERVICE_SECRET}")

IAM_ACCESS_TOKEN=$(echo $IAM_TOKEN_RESPONSE | jq -r '.access_token')
if [ "$IAM_ACCESS_TOKEN" == "null" ] || [ -z "$IAM_ACCESS_TOKEN" ]; then
  echo "✗ ERROR: Failed to get IAM access token"
  exit 1
fi
echo "✓ IAM token obtained"

# Step 3: Exchange for Zen token
echo ""
echo "Step 3: Exchanging IAM token for Zen token..."
ZEN_TOKEN_RESPONSE=$(curl -k -s -X GET \
  "https://ibm-nginx-svc.${NAMESPACE}.svc/v1/preauth/validateAuth" \
  -H "username: ${SERVICE_ID}" \
  -H "iam-token: ${IAM_ACCESS_TOKEN}")

ZEN_TOKEN=$(echo $ZEN_TOKEN_RESPONSE | jq -r '.accessToken')
if [ "$ZEN_TOKEN" == "null" ] || [ -z "$ZEN_TOKEN" ]; then
  echo "✗ ERROR: Failed to get Zen token"
  exit 1
fi
echo "✓ Zen token obtained"

# Step 4: Generate new API key
echo ""
echo "Step 4: Generating new API key..."
API_KEY_RESPONSE=$(curl -k -s -X POST \
  "https://usermgmt-svc.${NAMESPACE}.svc:3443/v1/user/apiKey" \
  -H "Authorization: Bearer ${ZEN_TOKEN}" \
  -H "username: ${SERVICE_ID}")

NEW_API_KEY=$(echo $API_KEY_RESPONSE | jq -r '.apiKey')
if [ "$NEW_API_KEY" == "null" ] || [ -z "$NEW_API_KEY" ]; then
  echo "✗ ERROR: Failed to generate API key"
  exit 1
fi
echo "✓ New API key generated"

# Step 5: Update secret
echo ""
echo "Step 5: Updating Kubernetes secret..."
kubectl create secret generic ai-gateway-api-key \
  --from-literal=apiKey=$NEW_API_KEY \
  --dry-run=client -o yaml | kubectl apply -n $NAMESPACE -f -
echo "✓ Secret updated"

# Step 6: Restart operator
echo ""
echo "Step 6: Restarting CP4BA operator..."
kubectl delete pod -n $NAMESPACE -l name=ibm-cp4a-operator
kubectl wait --for=condition=ready pod -n $NAMESPACE -l name=ibm-cp4a-operator --timeout=120s
echo "✓ Operator restarted"

echo ""
echo "=== API Key Rotation Complete ==="
echo ""
echo "The operator will automatically update all component configurations."
echo "Monitor operator logs: kubectl logs -n $NAMESPACE -l name=ibm-cp4a-operator -f"
Save this script and make it executable:
chmod +x rotate-ai-gateway-api-key.sh
./rotate-ai-gateway-api-key.sh $NAMESPACE
Troubleshoot
If you encounter issues that are not covered in these instructions:
  1. Check the operator logs: kubectl logs -n $NAMESPACE -l name=ibm-cp4a-operator
  2. Review the CP4BA pod logs for authentication errors.