Harness Cloud Cost Management helps engineering and FinOps teams see where cloud money goes. It brings cost visibility across AWS, Azure, GCP, and Kubernetes. It supports rich allocation so you can view spend by service, team, or app. It also offers optimization features like recommendations, AutoStopping of idle resources, budgets, and anomaly detection. The goal is simple. Make cloud costs measurable, predictable, and actionable.
The Backstage plugin brings these insights into your developer portal. You can link a Backstage service to a Harness Perspective so cost views match how your org groups resources. Once connected, developers get an overview card on the service page plus a full tab for deeper cost detail. That keeps cost context next to docs, builds, and runbooks. No extra tabs. No context switches.
Typical use cases include giving each service owner a live view of spend by environment and component. Teams can track trends during feature work, compare expected versus actual costs, and notice spikes soon after a change. Finance partners can align chargeback or showback with the same Perspective used by the team. The result is faster feedback on the cost impact of everyday engineering decisions, inside a tool engineers already use.
Installation Instructions
These instructions apply to self-hosted Backstage only.
Install the frontend package
- From the root of your Backstage app run
yarn add --cwd packages/app @harnessio/backstage-plugin-harness-ccm
yarn install
Configure the proxy in app config
- Open app-config.yaml
- Add a proxy entry for Harness. Put your Harness personal access token or service account token in the x-api-key header
proxy:
'/harness/prod':
target: 'https://app.harness.io/'
headers:
'x-api-key': '<YOUR_PAT_OR_SAT>'
Use your on prem Harness base URL for the target value if you run Harness on prem.
The plugin uses this token for Harness API calls. The token must have perspective view permission. Service accounts need a role with the same permission.
Enable the proxy on the old backend system
- Add the proxy backend dependency if it is missing
yarn add --cwd packages/backend @backstage/plugin-proxy-backend
- Create packages/backend/src/plugins/proxy.ts if it does not exist
// packages/backend/src/plugins/proxy.ts
import { createRouter } from '@backstage/plugin-proxy-backend';
import { PluginEnvironment } from '../types';
export default async function createPlugin(env: PluginEnvironment) {
return await createRouter({
logger: env.logger,
config: env.config,
discovery: env.discovery,
tokenManager: env.tokenManager,
});
}
- Wire the proxy plugin in packages/backend/src/index.ts
// packages/backend/src/index.ts
import proxy from './plugins/proxy';
// inside the main bootstrap where apiRouter is created
apiRouter.use('/proxy', await proxy(env));
The config you added under proxy in app-config.yaml will now be served by the backend at the proxy path.
Enable the proxy on the new backend system
- Add the proxy backend dependency if it is missing
yarn add --cwd packages/backend @backstage/plugin-proxy-backend
- Register the proxy backend in packages/backend/src/index.ts
// packages/backend/src/index.ts
import { createBackend } from '@backstage/backend-defaults';
const backend = createBackend();
// register the proxy backend
backend.add(import('@backstage/plugin-proxy-backend'));
backend.start();
The config you added under proxy in app-config.yaml will now be served by the backend.
Add the plugin to the Entity page
- Open packages/app/src/components/catalog/EntityPage.tsx
- Import the CCM components
// packages/app/src/components/catalog/EntityPage.tsx
import {
isHarnessCcmAvailable,
EntityCcmContent,
EntityCcmOverviewCard,
} from '@harnessio/backstage-plugin-harness-ccm';
- Add a CCM tab to the service Entity page
// example structure using EntityLayout
import { EntityLayout, EntitySwitch } from '@backstage/plugin-catalog';
export const serviceEntityPage = (
<EntityLayout>
{/* existing routes */}
<EntityLayout.Route path="/ccm" title="Costs">
<EntitySwitch>
<EntitySwitch.Case if={isHarnessCcmAvailable}>
<EntityCcmContent />
</EntitySwitch.Case>
</EntitySwitch>
</EntityLayout.Route>
</EntityLayout>
);
- Add the CCM overview card to the Overview tab
// inside your existing overview content
import Grid from '@material-ui/core/Grid';
const overviewContent = (
<Grid container spacing={3}>
{/* existing cards */}
<Grid item md={6} xs={12}>
<EntityCcmOverviewCard variant="gridItem" />
</Grid>
</Grid>
);
Add the entity annotation
- Open the catalog info file for each service you want to link
- Add the Harness perspective URL annotation
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: my-service
annotations:
harness.io/perspective-url: https://app.harness.io/ng/#/account/<acct>/perspective/<id>
spec:
type: service
owner: team
lifecycle: production
Notes on on prem Harness
If you run Harness on prem use your on prem base URL in app-config.yaml for the proxy target. Keep the same proxy path key
proxy:
'/harness/prod':
target: 'https://<your_on_prem_harness_host>/'
headers:
'x-api-key': '<YOUR_PAT_OR_SAT>'
Changelog
This changelog is produced from commits made to the Harness Cloud Cost Management plugin since a year 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.
Documentation
- Add EntityCcmOverviewCard to CCM Backstage plugin README #153 merged 11 months ago
Set up Backstage in minutes with Roadie
Focus on using Backstage, rather than building and maintaining it.