Harness Cloud Cost Management logo

Backstage Harness Cloud Cost Management Plugin

Created by Harness

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

  1. From the root of your Backstage app run
Copy
yarn add --cwd packages/app @harnessio/backstage-plugin-harness-ccm
yarn install

Configure the proxy in app config

  1. Open app-config.yaml
  2. Add a proxy entry for Harness. Put your Harness personal access token or service account token in the x-api-key header
Copy
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

  1. Add the proxy backend dependency if it is missing
Copy
yarn add --cwd packages/backend @backstage/plugin-proxy-backend
  1. Create packages/backend/src/plugins/proxy.ts if it does not exist
Copy
// 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,
  });
}
  1. Wire the proxy plugin in packages/backend/src/index.ts
Copy
// 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

  1. Add the proxy backend dependency if it is missing
Copy
yarn add --cwd packages/backend @backstage/plugin-proxy-backend
  1. Register the proxy backend in packages/backend/src/index.ts
Copy
// 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

  1. Open packages/app/src/components/catalog/EntityPage.tsx
  2. Import the CCM components
Copy
// packages/app/src/components/catalog/EntityPage.tsx
import {
  isHarnessCcmAvailable,
  EntityCcmContent,
  EntityCcmOverviewCard,
} from '@harnessio/backstage-plugin-harness-ccm';
  1. Add a CCM tab to the service Entity page
Copy
// 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>
);
  1. Add the CCM overview card to the Overview tab
Copy
// 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

  1. Open the catalog info file for each service you want to link
  2. Add the Harness perspective URL annotation
Copy
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

Copy
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