Skip to main content
Version: v0.9.x

API Management

This guide is for platform engineers who need to configure and manage API Management capabilities in OpenChoreo. Learn how to enable the default WSO2 API Platform and integrate external API management vendors.

Overview​

OpenChoreo provides a flexible, trait-based API Management architecture that supports:

  • Default Integration: WSO2 API Platform for out-of-the-box API management
  • Vendor Flexibility: Integrate any API management solution through OpenChoreo custom traits
  • Declarative Configuration: Manage API configuration as Kubernetes resources
  • Multi-Tenancy: Isolated API management per environment or organization

Architecture​

OpenChoreo's API Management is built on three key components:

  1. API Gateway: Default WSO2 API Platform gateway, can integrate external vendors
  2. API Configuration Trait: Declarative trait that components use to enable API management (default api-configuration trait for WSO2 API Platform or any platform engineer defined traits)
  3. Identity Provider Integration: OAuth2/JWT token validation (Thunder IDP or any external IDP)

How It Works​

Component + API Trait
↓
ReleaseBinding (applies trait)
↓
Release (renders API config)
↓
Data Plane (enforces policies via gateway)

When a component includes an API management trait, OpenChoreo:

  • Generates API gateway configuration resources based on the trait template
  • Configures gateway policies like authentication and rate limiting
  • Routes traffic through the configured API gateway layer

Prerequisites​

  • OpenChoreo control plane and data plane installed
  • Cluster admin access for CRD installation
  • Helm 3.12+ for chart installation
  • Understanding of OpenChoreo traits and component model

WSO2 API Platform (Default)​

OpenChoreo includes native integration with WSO2 API Platform, providing enterprise-grade API management out of the box.

Installation​

The API Platform module is disabled by default and must be explicitly enabled during data plane installation.

During Initial Data Plane Installation​

Enable the API Platform module using Helm values:

helm upgrade --install openchoreo-data-plane oci://ghcr.io/openchoreo/helm-charts/openchoreo-data-plane \
--version 0.0.0-latest-dev \
--namespace openchoreo-data-plane \
--create-namespace \
--set gateway.httpPort=19080 \
--set gateway.httpsPort=19443 \
--set external-secrets.enabled=true \
--set gateway.envoy.mountTmpVolume=true \
--set api-platform.enabled=true

Adding to Existing Data Plane​

If OpenChoreo is already installed:

Step 1: Install API Platform CRDs

kubectl apply --server-side \
-f https://raw.githubusercontent.com/wso2/api-platform/gateway-operator-v0.1.0/kubernetes/helm/operator-helm-chart/crds/api.api-platform.wso2.com_apiconfigurations.yaml \
-f https://raw.githubusercontent.com/wso2/api-platform/gateway-operator-v0.1.0/kubernetes/helm/operator-helm-chart/crds/api.api-platform.wso2.com_gatewayconfigurations.yaml

Step 2: Upgrade data plane with API Platform enabled

helm upgrade --install openchoreo-data-plane oci://ghcr.io/openchoreo/helm-charts/openchoreo-data-plane \
--version 0.0.0-latest-dev \
--namespace openchoreo-data-plane \
--reuse-values \
--set api-platform.enabled=true

Verify Installation​

Confirm all API Platform components are running:

kubectl get pods -n openchoreo-data-plane --selector="app.kubernetes.io/instance=api-platform-default-gateway"

Expected output:

NAME                                                          READY   STATUS    RESTARTS   AGE
api-platform-default-gateway-controller-6d574f8478-skd8n 1/1 Running 0 2m
api-platform-default-gateway-policy-engine-6ccc5f76b4-m87f7 1/1 Running 0 2m
api-platform-default-gateway-router-55cd96cfc9-njf56 1/1 Running 0 2m

Configuration Options​

The WSO2 API Platform module supports extensive configuration via Helm values:

api-platform:
enabled: false
gateway:
helm:
chartName: "oci://ghcr.io/wso2/api-platform/helm-charts/gateway"
values:
gateway:
config:
policy_configurations:
JWTAuth_v010:
KeyManagers:
- name: ThunderKeyManager
issuer: thunder
jwks:
remote:
uri: http://thunder-service.openchoreo-control-plane:8090/oauth2/jwks
skipTlsVerify: true
JwksCacheTtl: "5m"
JwksFetchTimeout: "5s"
JwksFetchRetryCount: 3
JwksFetchRetryInterval: "2s"
AllowedAlgorithms:
- RS256
- ES256
Leeway: "30s"
AuthHeaderScheme: Bearer
HeaderName: Authorization
OnFailureStatusCode: 401
ErrorMessageFormat: json
ErrorMessage: "Authentication failed."
ValidateIssuer: true

API Configuration Trait Reference​

The api-configuration trait is the primary way components enable API management with WSO2 API Platform.

Trait Schema​

apiVersion: openchoreo.dev/v1alpha1
kind: Component
metadata:
name: my-service
spec:
traits:
- name: api-configuration
instanceName: my-api # Unique name for this API instance
parameters:
# Required parameters
apiName: string # API identifier
apiVersion: string # API version (e.g., v1.0, v2.0)
context: string # API context path (e.g., /my-api/v1.0)
upstreamPort: integer # Target service port (typically 80)

# Optional parameters
policies: # Authentication and security policies
- name: string # Policy name (e.g., JwtAuthentication)
version: string # Policy version (e.g., v0.1.0)
parameters: object # Policy-specific configuration
operations: # By default operations are /* for GET, POST, PATCH, PUT, DELETE, OPTIONS
- method: string # HTTP method (GET, POST, PUT, DELETE, PATCH, OPTIONS)
path: string # API path pattern (e.g., /books, /*)

External API Management Vendors​

OpenChoreo's trait-based architecture allows integration with any API management solution. You can create custom traits that integrate with vendors like Kong, Apigee, AWS API Gateway, or Azure API Management.

Integration Architecture​

External API management integration works through OpenChoreo traits:

Component + Custom API Trait
↓
Trait Template (your implementation)
↓
Vendor-Specific Resources (ConfigMaps, Secrets, CRDs)
↓
External API Gateway

Creating a Custom API Management Trait​

Custom traits allow you to define how OpenChoreo components integrate with your API management solution. The trait structure follows the same pattern as the default api-configuration trait.

Example: Kong Gateway Integration​

apiVersion: openchoreo.dev/v1alpha1
kind: Trait
metadata:
name: kong-api-management
namespace: default
spec:
schema:
types:
Plugin:
name: "string"
config: "map<string>"

parameters:
# Developer-facing parameters
apiName: "string | required"
apiVersion: "string | default=v1.0"
context: "string | required" # API context path
upstreamPort: "integer | default=80"
plugins:
"array<Plugin> | default=[]"
# Example:
# - name: jwt
# config:
# claims_to_verify: ["exp"]
# - name: rate-limiting
# config:
# minute: 100

envOverrides:
# Platform engineers can override per environment
kongGateway:
"string | default=kong-gateway"
# Kong gateway service name

creates:
# Create KongPlugin resources for each plugin
- forEach: ${parameters.plugins}
var: plugin
template:
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
name: ${metadata.name}-${plugin.name}
namespace: ${metadata.namespace}
plugin: ${plugin.name}
config: ${plugin.config}

# Create KongIngress resource
- template:
apiVersion: configuration.konghq.com/v1
kind: KongIngress
metadata:
name: ${metadata.name}-ingress
namespace: ${metadata.namespace}
route:
paths:
- ${parameters.context}
upstream:
targets:
- target: ${metadata.componentName}.${metadata.namespace}:${parameters.upstreamPort}

patches:
# Patch Ingress to use Kong plugins
- target:
group: networking.k8s.io
version: v1
kind: Ingress
operations:
- op: add
path: /metadata/annotations/konghq.com~1plugins
value: ${join(map(parameters.plugins, "plugin", "${metadata.name}-${plugin.name}"), ",")}

Components can use this trait:

apiVersion: openchoreo.dev/v1alpha1
kind: Component
metadata:
name: my-service
spec:
traits:
- name: kong-api-management
parameters:
apiName: my-api
apiVersion: v2.0
context: /my-api/v2.0
plugins:
- name: jwt
config:
claims_to_verify:
- exp
- name: rate-limiting
config:
minute: 100

Example: Apigee Integration​

For Apigee integration, create a trait that generates Apigee proxy configurations:

apiVersion: openchoreo.dev/v1alpha1
kind: Trait
metadata:
name: apigee-api-management
namespace: default
spec:
schema:
types:
Policy:
name: "string"
config: "map<string>"

parameters:
# Developer-facing parameters
apiName: "string | required"
apiVersion: "string | default=v1.0"
context: "string | required" # API base path
upstreamPort: "integer | default=80"
policies:
"array<Policy> | default=[]"
# Example:
# - name: VerifyAPIKey
# - name: SpikeArrest
# config:
# rate: 100pm

envOverrides:
# Platform engineers can override per environment
apigeeOrg: "string | required"
apigeeEnv: "string | required"
# Apigee organization and environment

creates:
# Create ConfigMap with Apigee proxy configuration
- template:
apiVersion: v1
kind: ConfigMap
metadata:
name: ${metadata.name}-apigee-config
namespace: ${metadata.namespace}
data:
proxy.xml: |
<APIProxy name="${parameters.apiName}">
<BasePath>/${parameters.context}</BasePath>
<TargetEndpoint>
<HTTPTargetConnection>
<URL>http://${metadata.componentName}.${metadata.namespace}:${parameters.upstreamPort}</URL>
</HTTPTargetConnection>
</TargetEndpoint>
<Policies>
${join(map(parameters.policies, "policy", "<Policy name=\"${policy.name}\" ${policy.config ? "rate=\"${policy.config.rate}\"" : ""}/>"), "\n")}
</Policies>
</APIProxy>

# Create ApigeeDeployment resource (using Apigee CRD)
- template:
apiVersion: apigee.cloud.google.com/v1alpha1
kind: ApigeeDeployment
metadata:
name: ${metadata.name}-deployment
namespace: ${metadata.namespace}
spec:
organization: ${envOverrides.apigeeOrg}
environment: ${envOverrides.apigeeEnv}
apiProxyConfigMap: ${metadata.name}-apigee-config

Components select the appropriate trait based on deployment target.

Troubleshooting​

API Platform Pods Not Running​

Check pod status and logs:

kubectl get pods -n openchoreo-data-plane -l app.kubernetes.io/instance=api-platform-default-gateway
kubectl logs -n openchoreo-data-plane -l app.kubernetes.io/instance=api-platform-default-gateway

Production Considerations​

External Identity Provider​

For production environments, configure an external OAuth2 provider like Okta:

api-platform:
enabled: true
gateway:
values:
gateway:
config:
policy_configurations:
JWTAuth_v010:
KeyManagers:
- name: OktaKeyManager
issuer: https://your-domain.okta.com/oauth2/default
jwks:
remote:
uri: https://your-domain.okta.com/oauth2/default/v1/keys
skipTlsVerify: false
JwksCacheTtl: "5m"
JwksFetchTimeout: "5s"
ValidateIssuer: true
AllowedAlgorithms:
- RS256
HeaderName: Authorization
AuthHeaderScheme: Bearer

Summary​

You've successfully:

  • Enabled the API Platform module in OpenChoreo
  • Explored OpenChoreo Traits for advanced API management use cases
  • Explored IDP Configuration for production use cases

Your APIs are now protected with enterprise-grade security and access controlβ€”all managed declaratively through OpenChoreo!

Next Steps​

Clean Up​

To disable API Management for a component, remove the trait:

kubectl patch component greeter-service --type=json \
-p='[{"op": "remove", "path": "/spec/traits"}]'

To uninstall the API Platform module:

helm upgrade openchoreo-data-plane oci://ghcr.io/openchoreo/helm-charts/openchoreo-data-plane \
--version 0.0.0-latest-dev \
--namespace openchoreo-data-plane \
--reuse-values \
--set api-platform.enabled=false