Kyverno Policy Reports capture the results of policy checks inside your Kubernetes clusters. They record which resources passed or failed specific rules. They update as your cluster changes. For engineers, this gives a clear way to see the current compliance state without scraping logs or switching tools.
The Kyverno Policy Reports Backstage plugin brings those reports into the software catalog view you already use. On a service page you can see summary counts for pass fail warn skip and error. You can drill into a resource to understand what triggered a result. You can open the policy YAML in a viewer. You can copy it or download it for a quick review. This helps platform and security teams spot patterns across clusters. It helps service owners fix issues near the code and ownership context. Common uses include checking release readiness, tracking recurring violations, and giving developers fast feedback during migrations or policy rollouts.
Companies are adopting similar Backstage views for Kyverno results. VELUX published an open approach that integrates Kyverno policy reports into Backstage. In their words, “The Backstage policy reporter plugin integrates Policy Reporter with Backstage to provide a clear and detailed view of Kyverno Policies applied to your workloads.” See their repo at.
Installation Instructions
These instructions apply to self-hosted Backstage only.
Install the frontend package
yarn add --cwd packages/app @terasky/backstage-plugin-kyverno-policy-reports
Add the Kyverno tab to the entity page
Edit packages/app/src/components/catalog/EntityPage.tsx
Import the plugin exports
// packages/app/src/components/catalog/EntityPage.tsx
import React from 'react';
import { EntityLayout } from '@backstage/plugin-catalog';
import {
EntityKyvernoPolicyReportsContent,
isKyvernoPolicyReportsAvailable,
} from '@terasky/backstage-plugin-kyverno-policy-reports';
import { EntitySwitch, EntitySwitchCase } from '@backstage/plugin-catalog';
Add a Kyverno route to the entity layout
// Inside your <EntityLayout>
<EntityLayout.Route path="/kyverno" title="Kyverno">
<EntitySwitch>
<EntitySwitchCase if={isKyvernoPolicyReportsAvailable}>
<EntityKyvernoPolicyReportsContent />
</EntitySwitchCase>
</EntitySwitch>
</EntityLayout.Route>
If your app does not use EntitySwitch yet, you can render the content directly
<EntityLayout.Route path="/kyverno" title="Kyverno">
<EntityKyvernoPolicyReportsContent />
</EntityLayout.Route>
Optional show a card on the overview tab
Place the card inside the overview grid
// packages/app/src/components/catalog/EntityPage.tsx
import React from 'react';
import Grid from '@material-ui/core/Grid';
import {
KyvernoPolicyReportsCard,
isKyvernoPolicyReportsAvailable,
} from '@terasky/backstage-plugin-kyverno-policy-reports';
import { EntitySwitch, EntitySwitchCase } from '@backstage/plugin-catalog';
// Inside your Overview content
<Grid container spacing={3}>
<EntitySwitch>
<EntitySwitchCase if={isKyvernoPolicyReportsAvailable}>
<Grid item xs={12}>
<KyvernoPolicyReportsCard />
</Grid>
</EntitySwitchCase>
</EntitySwitch>
</Grid>
Add Kubernetes annotations to your entities
The plugin resolves reports for a component through Kubernetes annotations. Add at least the Kubernetes id. Add namespace if you need it
# catalog-info.yaml
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: my-service
annotations:
backstage.io/kubernetes-id: my-service
backstage.io/kubernetes-namespace: my-namespace
spec:
type: service
owner: team-a
lifecycle: production
Configure the Kubernetes plugin to read PolicyReport resources
Add the PolicyReport custom resources to your Kubernetes config. Use the version that matches your cluster. v1beta1 is common today
# app-config.yaml
kubernetes:
# your cluster definitions go here
# ...
customResources:
- group: wgpolicyk8s.io
apiVersion: v1beta1
plural: policyreports
objectType: PolicyReport
namespaced: true
- group: wgpolicyk8s.io
apiVersion: v1beta1
plural: clusterpolicyreports
objectType: ClusterPolicyReport
namespaced: false
If your cluster still uses v1alpha2 switch apiVersion to v1alpha2
kubernetes:
customResources:
- group: wgpolicyk8s.io
apiVersion: v1alpha2
plural: policyreports
objectType: PolicyReport
namespaced: true
- group: wgpolicyk8s.io
apiVersion: v1alpha2
plural: clusterpolicyreports
objectType: ClusterPolicyReport
namespaced: false
Make sure the Kubernetes backend is installed
If your app already uses the Kubernetes plugin you can skip this step
Install the backend package
yarn add --cwd packages/backend @backstage/plugin-kubernetes-backend
New backend system
Register the Kubernetes backend plugin
// packages/backend/src/index.ts
import { createBackend } from '@backstage/backend-defaults';
import { kubernetesPlugin } from '@backstage/plugin-kubernetes-backend';
const backend = createBackend();
backend.add(kubernetesPlugin());
export default backend;
Old backend system
Create the plugin wireup
// packages/backend/src/plugins/kubernetes.ts
import { Router } from 'express';
import { PluginEnvironment } from '../types';
import { createRouter } from '@backstage/plugin-kubernetes-backend';
export default async function createPlugin(env: PluginEnvironment): Promise<Router> {
return await createRouter({
logger: env.logger,
config: env.config,
discovery: env.discovery,
tokenManager: env.tokenManager,
httpAuth: env.httpAuth,
permissions: env.permissions,
});
}
Register the router
// packages/backend/src/index.ts
import kubernetes from './plugins/kubernetes';
// inside main bootstrap where apiRouter is created
apiRouter.use('/kubernetes', await kubernetes(env));
Grant the backend access to your cluster
The Kubernetes plugin needs credentials that can read PolicyReport and ClusterPolicyReport. Grant get list watch on those resources. Use your normal cluster onboarding for the Backstage service account
Example cluster role
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: backstage-kubernetes-read
rules:
- apiGroups:
- ''
resources:
- pods
- services
- deployments
- replicasets
verbs:
- get
- list
- watch
- apiGroups:
- wgpolicyk8s.io
resources:
- policyreports
- clusterpolicyreports
verbs:
- get
- list
- watch
Bind this role to the service account used by your Backstage backend
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: backstage-kubernetes-read-binding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: backstage-kubernetes-read
subjects:
- kind: ServiceAccount
name: backstage
namespace: backstage
Notes
This plugin is frontend only. There is no separate plugin backend to install. It reads data through the Kubernetes backend you already run in Backstage
Export names can change between versions. If the imports shown do not exist in your version check the package exports. Common exports include a content component for the entity page and a small card for the overview tab
Changelog
This changelog is produced from commits made to the Kyverno Policy Reports plugin since 8 months ago, and based on the code located here. It may not contain information about all commits. Releases and version bumps are intentionally omitted. This changelog is generated by AI.
Breaking changes
- Kyverno Policy Reports plugin now uses a backend plugin instead of calling the Kubernetes plugin from the frontend. You must install and configure the Kyverno backend plugin. Review permissions in your backend app. #89 merged 10 days ago
Features
- Add MCP Action support in the Kyverno Policy Reports plugin. #89 merged 10 days ago
- Add support for the new Frontend System in Backstage for the Kyverno plugin. #83 merged 26 days ago
Maintenance
Set up Backstage in minutes with Roadie
Focus on using Backstage, rather than building and maintaining it.