Kuadrant Plugin Installation Guide¶
This guide covers installing the Kuadrant plugins into an existing Red Hat Developer Hub (RHDH) or Backstage instance.
For plugin development, see the main README.
Packages¶
| Plugin | Package | Type |
|---|---|---|
| Frontend | @kuadrant/kuadrant-backstage-plugin-frontend | Frontend |
| Backend | @kuadrant/kuadrant-backstage-plugin-backend-dynamic | Backend |
Why Two Packages?¶
We publish only two packages that work for both dynamic (RHDH) and static (Backstage) deployments:
-
Frontend plugin: Published directly from
plugins/kuadrant. Frontend plugins are bundled by the app's webpack at build time, so the dynamic plugin system simply needs the source to be available. Thedist-scalprum/assets for dynamic loading are included alongside the standard build output in the same package. -
Backend plugin: Published from
plugins/kuadrant-backend/dist-dynamic(not the root). Backend plugins run in Node.js and are loaded at runtime, not bundled by webpack. For dynamic loading to work, the backend code must be pre-bundled as a self-contained module with all dependencies embedded. The@janus-idp/cli export-dynamiccommand generates this indist-dynamic/with its ownpackage.json. This is a separate package because the dependency structure differs from the source plugin.
In short: frontend plugins are bundled by the consuming app (so source is fine), while backend plugins must be pre-bundled for runtime loading (so we publish the generated dist-dynamic output).
Prerequisites¶
Kubernetes Cluster with Kuadrant¶
The plugins require a Kubernetes cluster with Kuadrant installed. You can either:
- Use an existing cluster with:
-
Kuadrant operator 1.4+ installed
-
Use the development setup (recommended for testing):
This creates a kind cluster with: - Kuadrant operator
- Gateway API CRDs v1.2.0
- Istio service mesh
- APIProduct and APIKey CRDs
- Demo resources (toystore)
- RHDH service account with proper RBAC
Installation on Red Hat Developer Hub (RHDH)¶
This section covers installing the Kuadrant plugins on a Red Hat Developer Hub deployment in a Kubernetes/OpenShift cluster.
Prerequisites¶
- Red Hat Developer Hub
The Kuadrant v0.1.0 plugins are tested and supported on Red Hat Developer Hub 1.6 (based on Backstage 1.45.3).
Installation guide:
Choose your preferred deployment method:
- Operator-based deployment (recommended for production)
- Helm-based deployment
Configure Red Hat Developer Hub¶
Set the following environment variables used for convenience in this tutorial:
# Your backstage instance namespace. Choose your own.
export RHDH_NS=rhdh
export KUADRANT_BACKSTAGE_PLUGIN_BACKEND_DYNAMIC_SHA256=$(npm view @kuadrant/kuadrant-backstage-plugin-backend-dynamic@v0.1.0 dist.integrity)
export KUADRANT_BACKSTAGE_PLUGIN_FRONTEND_SHA256=$(npm view @kuadrant/kuadrant-backstage-plugin-frontend@v0.1.0 dist.integrity)
# base hostname of the cluster.
# In openshift, this can be easily read with the following command
# oc get ingress.config.openshift.io cluster -o jsonpath='{.spec.domain}'
export CLUSTER_HOSTNAME=apps.example.com
Backstage Namespace¶
Create namespace for the backstage instance
Dynamic Plugin ConfigMap¶
Create a config map with the dynamic plugin configuration required to load kuadrant backstage plugins as dynamic plugins.
Copy Kuadrant backstage dynamic plugins metadata into a file named, for example, dynamic-plugins-rhdh.yaml. Replace the environment variables with their actual values. Then, create dynamic-plugins-rhdh configmap from that file.
kubectl create configmap dynamic-plugins-rhdh --from-file=dynamic-plugins-rhdh.yaml --namespace=$RHDH_NS
Backstage app-config.yaml¶
This is the main backstage application level configuration.
1. Enable authentication and the permission framework
The Kuadrant backstage plugin requires that the permissions framework is set up and configured properly.
Set permissions.enabled to true in app-config.yaml:
Additionally, set up some authentication in backstage.
2. Set up RBAC for the kuadrant plugin functionality
This configuration will define kuadrant plugin user roles and permissions on those roles. Basically, who can do what within the plugin. The kuadrant backstage plugin permission model is detailed in RBAC and Permissions doc.
Create rbac-policy.csv file with the kuadrant plugin's permission definition.
You can start with this RBAC policy content sample that includes three roles [api-consumer, api-owner, api-admin]. Then, create rbac-policies configmap from that file.
Add reference to rbac-policy.csv file in the permissions.rbac.policies-csv-file section of the app-config.yaml:
Note: The mounting path
/opt/app-root/etcis configured later in the Backstage CR. Ensure they match.
3. Configure Kubernetes access
Kubernetes access is configured in app-config.yaml.
The recommended approach is so-called in-cluster mode. In this mode, the backstage application running inside a Kubernetes pod authenticates to the Kubernetes API server using the service account automatically provided by Kubernetes.
The in-cluster mode can be configured by either:
-
Omitting the
kubernetessection entirely (setting it to null): -
Omitting the
serviceAccountTokenwhen configuring clusters:
Alternatively, the kuadrant backstage plugin also supports the cluster locator method config. With this method, the kuadrant plugin will read cluster information, typically cluster URL and cluster access token (which usually expires), from the app-config.yaml file.
kubernetes:
serviceLocatorMethod:
type: multiTenant
clusterLocatorMethods:
- type: config
clusters:
- name: remote-cluster
url: https://example.com
authProvider: serviceAccount
serviceAccountToken: ${K8S_ACCESS_TOKEN}
4. Configure Catalog Rules
Add APIProduct to catalog.rules in app-config.yaml:
Follow the steps in Provisioning your custom Red Hat Developer Hub configuration for the full procedure.
A full example for "app-config.yaml"
app:
title: Red Hat Developer Hub
baseUrl: https://frontend.$CLUSTER_HOSTNAME
# Testing only: enables guest access for rhdh-local.
# In production, configure your own identity provider and map roles/permissions to your users or groups.
auth:
environment: development
providers:
guest:
dangerouslyAllowOutsideDevelopment: true
userEntityRef: user:default/guest
kubernetes: null
catalog:
rules:
- allow: [Component, API, APIProduct, Location, Template, Domain, User, Group, System, Resource, Plugin, Package]
permission:
enabled: true
rbac:
policies-csv-file: /opt/app-root/etc/rbac-policy.csv
policyFileReload: true
Finally, create a config map from the app-config.yaml file.
RBAC for Kuadrant CRDs¶
This step grants permissions to the backstage application to manage kuadrant CRD's existing in the cluster. It consist on two steps: creating the clusterRole and then the ClusterRoleBinding.
First, create the ClusterRole which defines permissions on the kuadrant CRD's.
By default, backstage application will run with the default service account of the namespace.
Thus, secondly, we need to bind that cluster role to this service account with cluster wide scope. Therefore, create CluterRoleBinding as follows:
kubectl apply -f - <<EOF
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: rhdh-kuadrant
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: rhdh-kuadrant
subjects:
- kind: ServiceAccount
name: default
namespace: $RHDH_NS
EOF
You can verify permissions with the following command:
Backstage instance¶
The Backstage CR represents one backstage instance. It is where all preparation comes into one place and takes effect.
- Link the dynamic plugin configmap
- Link the main
rhdh-app-configconfigmap
- Link the RBAC policies from the
rbac-policiesconfigmap
The mounting path is referenced from
app-config.yaml, RBAC for the kuadrant functionality section. Ensure they match.
- [Optional] Enable serviceaccount token automount
Only required for kubernetes access in-cluster mode.
A full example for "rhdh" Backstage instance
# https://github.com/redhat-developer/rhdh-operator/blob/main/api/v1alpha3/backstage_types.go
apiVersion: rhdh.redhat.com/v1alpha3
kind: Backstage
metadata:
name: rhdh
namespace: $RHDH_NS
spec:
application:
appConfig:
mountPath: /opt/app-root/src
configMaps:
- name: rhdh-app-config
extraFiles:
mountPath: /opt/app-root/etc
configMaps:
- name: rbac-policies
route:
enabled: true
subdomain: frontend
dynamicPluginsConfigMapName: dynamic-plugins-rhdh
database:
enableLocalDb: true
deployment:
patch:
spec:
template:
spec:
automountServiceAccountToken: true
Go to backstage_types.go for v1alpha3 for full reference on the Backstage CRD.
Installation on Red Hat Developer Hub (RHDH) Local¶
This section covers installing the plugins using rhdh-local for local development with Docker Compose.
1. Configure Dynamic Plugins¶
Copy Kuadrant backstage dynamic plugins metadata into a file named configs/dynamic-plugins/dynamic-plugins.override.yaml:
To get the integrity hash:
npm view @kuadrant/kuadrant-backstage-plugin-frontend dist.integrity
npm view @kuadrant/kuadrant-backstage-plugin-backend-dynamic dist.integrity
2. Configure Kubernetes Access¶
Add to configs/app-config/app-config.yaml:
kubernetes:
serviceLocatorMethod:
type: multiTenant
clusterLocatorMethods:
- type: config
clusters:
- name: production
url: https://host.docker.internal:<port>
authProvider: serviceAccount
serviceAccountToken: <your-token>
skipTLSVerify: true
Note: Use
host.docker.internalto access the host machine's kind cluster from Docker. Get the port withkubectl cluster-info.
3. Configure RBAC¶
Add to configs/app-config/app-config.yaml:
permission:
enabled: true
rbac:
policies-csv-file: /opt/app-root/src/configs/rbac-policy.csv
policyFileReload: true
Create configs/rbac-policy.csv with the RBAC policy content.
4. Service Account Setup¶
Create a service account with permissions to manage Kuadrant resources
ClusterRole¶
Create the ClusterRole which defines permissions on the kuadrant CRD's.
Namespace¶
ServiceAccount¶
kubectl apply -f - <<EOF
apiVersion: v1
kind: ServiceAccount
metadata:
name: rhdh-kuadrant
namespace: rhdh
EOF
ClusterRoleBinding¶
kubectl apply -f - <<EOF
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: rhdh-kuadrant
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: rhdh-kuadrant
subjects:
- kind: ServiceAccount
name: rhdh-kuadrant
namespace: rhdh
EOF
5. Start RHDH¶
Visit http://localhost:7007/kuadrant
Installation on Backstage¶
This section covers installing the plugins on a standard Backstage instance.
Important: RBAC Plugin Requirement¶
The Kuadrant backend plugin includes an RBAC module that integrates with the Backstage permission framework. Standard Backstage does not include the RBAC plugin that RHDH provides.
To use the RBAC module on Backstage, you need to install the community RBAC plugin:
yarn --cwd packages/backend add @backstage-community/plugin-rbac-backend @backstage-community/plugin-rbac-node
If you don't need RBAC, you can skip the RBAC module - the core plugin functionality works without it.
1. Install Dependencies¶
Frontend (packages/app):
Backend (packages/backend):
2. Register Backend Plugin¶
Edit packages/backend/src/index.ts:
import { createBackend } from '@backstage/backend-defaults';
import {
kuadrantPlugin,
catalogModuleApiProductEntityProvider,
} from '@kuadrant/kuadrant-backstage-plugin-backend-dynamic';
const backend = createBackend();
// ... other plugins ...
// Kuadrant plugin
backend.add(kuadrantPlugin);
backend.add(catalogModuleApiProductEntityProvider);
backend.start();
3. Register Frontend Routes¶
Edit packages/app/src/App.tsx:
import {
KuadrantPage,
ApiProductsPage,
ApiProductDetailPage,
ApiKeysPage,
ApiKeyDetailPage,
} from '@kuadrant/kuadrant-backstage-plugin-frontend';
// In your routes:
const routes = (
<FlatRoutes>
{/* ... other routes ... */}
<Route path="/kuadrant" element={<KuadrantPage />} />
<Route path="/kuadrant/api-products" element={<ApiProductsPage />} />
<Route path="/kuadrant/api-products/:namespace/:name" element={<ApiProductDetailPage />} />
<Route path="/kuadrant/api-keys" element={<ApiKeysPage />} />
<Route path="/kuadrant/api-keys/:namespace/:name" element={<ApiKeyDetailPage />} />
</FlatRoutes>
);
4. Add Sidebar Navigation (Optional)¶
Edit packages/app/src/components/Root/Root.tsx:
import ExtensionIcon from '@material-ui/icons/Extension';
// In your sidebar:
<SidebarItem icon={ExtensionIcon} to="kuadrant" text="Kuadrant" />
5. Configure Auth¶
Add to app-config.yaml. The userEntityRef ensures the guest user identity matches the RBAC policy:
# Testing only: enables guest access for local development.
# In production, configure your own identity provider and map roles/permissions to your users or groups.
auth:
environment: development
providers:
guest:
dangerouslyAllowOutsideDevelopment: true
userEntityRef: user:default/guest
6. Configure Kubernetes Access¶
Add to app-config.yaml:
kubernetes:
serviceLocatorMethod:
type: multiTenant
clusterLocatorMethods:
- type: config
clusters:
- name: production
url: https://127.0.0.1:<port>
authProvider: serviceAccount
serviceAccountToken: <your-token>
skipTLSVerify: true
7. Configure Catalog Rules¶
Add to app-config.yaml:
8. Configure Permissions and RBAC¶
Add to app-config.yaml:
Then create the RBAC policy file at configs/rbac-policy.csv in your project root. See the RBAC Policy section for the full file contents.
For example, to grant the guest user admin access:
Create configs/rbac-policy.csv with the policies from the RBAC Policy section.
9. Register RBAC Backend Plugin¶
The default Backstage permission backend uses an allow-all policy. To use the RBAC CSV policies, replace it with the community RBAC plugin.
In packages/backend/src/index.ts, replace:
with:
10. Service Account Setup¶
Create a service account with permissions to manage Kuadrant resources
ClusterRole¶
Create the ClusterRole which defines permissions on the kuadrant CRD's.
Namespace¶
ServiceAccount¶
kubectl apply -f - <<EOF
apiVersion: v1
kind: ServiceAccount
metadata:
name: rhdh-kuadrant
namespace: rhdh
EOF
ClusterRoleBinding¶
kubectl apply -f - <<EOF
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: rhdh-kuadrant
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: rhdh-kuadrant
subjects:
- kind: ServiceAccount
name: rhdh-kuadrant
namespace: rhdh
EOF
11. Start Backstage¶
Visit http://localhost:3000/kuadrant
Assets¶
Dynamic Plugins¶
includes:
- dynamic-plugins.default.yaml
plugins:
# Kuadrant Backend
- package: "@kuadrant/kuadrant-backstage-plugin-backend-dynamic@v0.1.0"
disabled: false
integrity: $KUADRANT_BACKSTAGE_PLUGIN_BACKEND_DYNAMIC_SHA256
# Kuadrant Frontend
- package: "@kuadrant/kuadrant-backstage-plugin-frontend@v0.1.0"
integrity: $KUADRANT_BACKSTAGE_PLUGIN_FRONTEND_SHA256
disabled: false
pluginConfig:
dynamicPlugins:
frontend:
internal.plugin-kuadrant:
appIcons:
- name: kuadrantIcon
importName: KuadrantIcon
dynamicRoutes:
- path: /kuadrant
importName: KuadrantPage
menuItem:
icon: kuadrantIcon
text: Kuadrant
- path: /kuadrant/api-products/:namespace/:name
importName: ApiProductDetailPage
- path: /kuadrant/api-keys/:namespace/:name
importName: ApiKeyDetailPage
mountPoints:
- mountPoint: entity.page.api/cards
importName: EntityKuadrantApiKeyManagementTab
config:
layout:
gridColumn: "1 / -1"
if:
allOf:
- isKind: api
- mountPoint: entity.page.api/cards
importName: EntityKuadrantApiProductInfoContent
config:
layout:
gridColumn: "1 / -1"
if:
allOf:
- isKind: api
RBAC Policy¶
Example rbac-policy.csv for Kuadrant permissions:
# api consumer: browses apis, requests access
p, role:default/api-consumer, kuadrant.apiproduct.read.all, read, allow
p, role:default/api-consumer, kuadrant.apiproduct.list, read, allow
p, role:default/api-consumer, kuadrant.apikey.create, create, allow, apiproduct:*/*
p, role:default/api-consumer, kuadrant.apikey.read.own, read, allow
p, role:default/api-consumer, kuadrant.apikey.update.own, update, allow
p, role:default/api-consumer, kuadrant.apikey.delete.own, delete, allow
p, role:default/api-consumer, catalog.entity.read, read, allow
# api owner: publishes apis they own, approves requests for their apis
p, role:default/api-owner, kuadrant.planpolicy.read, read, allow
p, role:default/api-owner, kuadrant.planpolicy.list, read, allow
p, role:default/api-owner, kuadrant.apiproduct.create, create, allow
p, role:default/api-owner, kuadrant.apiproduct.read.all, read, allow
p, role:default/api-owner, kuadrant.apiproduct.update.own, update, allow
p, role:default/api-owner, kuadrant.apiproduct.delete.own, delete, allow
p, role:default/api-owner, kuadrant.apiproduct.list, read, allow
p, role:default/api-owner, kuadrant.apikey.create, create, allow, apiproduct:*/*
p, role:default/api-owner, kuadrant.apikey.read.own, read, allow
p, role:default/api-owner, kuadrant.apikey.update.own, update, allow
p, role:default/api-owner, kuadrant.apikey.delete.own, delete, allow
p, role:default/api-owner, kuadrant.apikey.approve, update, allow
p, role:default/api-owner, catalog.entity.read, read, allow
# api admin: platform engineers who manage all api products
p, role:default/api-admin, kuadrant.planpolicy.read, read, allow
p, role:default/api-admin, kuadrant.planpolicy.list, read, allow
p, role:default/api-admin, kuadrant.apiproduct.create, create, allow
p, role:default/api-admin, kuadrant.apiproduct.read.all, read, allow
p, role:default/api-admin, kuadrant.apiproduct.update.all, update, allow
p, role:default/api-admin, kuadrant.apiproduct.delete.all, delete, allow
p, role:default/api-admin, kuadrant.apiproduct.list, read, allow
p, role:default/api-admin, kuadrant.apikey.create, create, allow, apiproduct:*/*
p, role:default/api-admin, kuadrant.apikey.read.all, read, allow
p, role:default/api-admin, kuadrant.apikey.update.all, update, allow
p, role:default/api-admin, kuadrant.apikey.delete.all, delete, allow
p, role:default/api-admin, kuadrant.apikey.approve, update, allow
p, role:default/api-admin, catalog.entity.read, read, allow
# assign groups to roles
g, group:default/api-consumers, role:default/api-consumer
g, group:default/api-owners, role:default/api-owner
g, group:default/api-admins, role:default/api-admin
# Development/testing only: assign guest user to admin role.
# For production, remove this line and assign roles to your actual users or groups.
g, user:default/guest, role:default/api-admin
ClusterRole¶
Permissions to manage resources from kuadrant CRDs.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: rhdh-kuadrant
rules:
- apiGroups: ["kuadrant.io"]
resources:
- authpolicies
- ratelimitpolicies
- dnspolicies
- tlspolicies
verbs: ["get", "list", "watch"]
- apiGroups: ["extensions.kuadrant.io"]
resources:
- planpolicies
verbs: ["get", "list", "watch"]
- apiGroups: ["devportal.kuadrant.io"]
resources:
- apiproducts
- apikeys
verbs: ["get", "list", "watch", "create", "delete", "patch", "update"]
- apiGroups: ["devportal.kuadrant.io"]
resources:
- apikeys/status
verbs: ["get", "patch", "update"]
- apiGroups: ["gateway.networking.k8s.io"]
resources:
- gateways
- httproutes
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources:
- namespaces
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources:
- secrets
verbs: ["get", "list", "watch", "create", "delete"]
Exposed Modules¶
Frontend¶
| Import Name | Description |
|---|---|
KuadrantPage |
Main page with API products and approval queue |
ApiProductsPage |
API products list page |
ApiProductDetailPage |
Single API product detail page |
ApiKeysPage |
API keys list page |
ApiKeyDetailPage |
Single API key detail page |
EntityKuadrantApiAccessCard |
API key request card for entity overview |
EntityKuadrantApiKeyManagementTab |
Full API keys management tab |
EntityKuadrantApiKeysContent |
API keys content component |
EntityKuadrantApiProductInfoContent |
APIProduct details tab |
KuadrantIcon |
Kuadrant logo icon for navigation |
Backend¶
| Export | Description |
|---|---|
kuadrantPlugin |
Main backend plugin with HTTP router |
catalogModuleApiProductEntityProvider |
Catalog entity provider for APIProduct sync |
rbacModule |
RBAC module for permission integration (requires RBAC plugin) |
Verification¶
After installation:
- Navigate to
/kuadrant- you should see the main Kuadrant page - Check the catalog for APIProduct entities synced from Kubernetes
- Navigate to an API entity and verify Kuadrant components appear
Troubleshooting¶
APIProduct entities not appearing¶
- Check backend logs for entity provider sync messages
- Verify Kubernetes connectivity
- Ensure APIProduct CRDs exist in your cluster
- Check catalog rules allow APIProduct kind
API key requests failing¶
- Verify Kubernetes write permissions for the service account
- Check backend logs for detailed error messages
- Ensure the target namespace exists and is accessible
Related Documentation¶
- RBAC Permissions - Detailed permissions guide
- Kuadrant Docs - Kuadrant documentation
- RHDH Local - RHDH local development