Harness Infrastructure as Code Management helps teams manage cloud resources through code at scale. It adds structure around your IaC work. You get workspaces that track resources, runs, and state. You get a clear place to review changes and standardize how they flow from pull request to provision.
This Backstage plugin brings that view into your service catalog. You map a Backstage service to a Harness workspace. The plugin shows workspace resources in context so you can see what your service owns. When you need to dig deeper, you can jump straight to the right pipeline run in Harness. The goal is simple. Keep infra details close to the code and the team that owns it.
Common use cases include giving developers a quick snapshot of current resources for a service. Helping platform teams spot drift or out of date assets faster. Reducing context switching when someone needs to check a workspace or trigger a pipeline. Making infra reviews part of the same place people look for builds, docs, and ownership.
If you already use Backstage and Harness, this plugin ties the two together in a natural way. It adds visibility without new habits or extra tools. It meets engineers where they work today.
Installation Instructions
These instructions apply to self-hosted Backstage only.
Install the plugin frontend package
- Add the plugin to your Backstage app package
yarn add --cwd packages/app @harnessio/backstage-plugin-iacm
yarn install
Configure the proxy in app config
- Add a proxy entry to your app config
# app-config.yaml
proxy:
'/harness/prod':
target: 'https://app.harness.io/'
headers:
'x-api-key': '<YOUR PAT OR SAT>'
Use a Harness Personal Access Token or Service Account Token in the x-api-key header
Set target to your on prem URL if you use the Harness on prem offering
The token needs project view permission
It also needs pipeline view permission
It also needs execute permission
For service accounts assign a role that grants these permissions
Enable the proxy backend in the legacy backend
- If your app uses the legacy backend setup add the proxy backend plugin
Install the backend package if it is missing
yarn add --cwd packages/backend @backstage/plugin-proxy-backend
Create the proxy plugin module
// packages/backend/src/plugins/proxy.ts
import express from 'express';
import { createRouter } from '@backstage/plugin-proxy-backend';
import { PluginEnvironment } from '../types';
export default async function createPlugin(
env: PluginEnvironment,
): Promise<express.Router> {
return await createRouter({
logger: env.logger,
config: env.config,
discovery: env.discovery,
tokenManager: env.tokenManager,
});
}
Mount it in the backend
// packages/backend/src/index.ts
import proxy from './plugins/proxy';
// inside main bootstrap
const proxyEnv = useHotMemoize(module, () => createEnv('proxy'));
apiRouter.use('/proxy', await proxy(proxyEnv));
Enable the proxy backend in the new backend system
- If your app uses the new backend system add the proxy backend module
Install the backend package if it is missing
yarn add --cwd packages/backend @backstage/plugin-proxy-backend @backstage/backend-defaults
Register the module
// packages/backend/src/index.ts
import { createBackend } from '@backstage/backend-defaults';
import { proxyPlugin } from '@backstage/plugin-proxy-backend';
const backend = createBackend();
backend.add(proxyPlugin());
await backend.start();
Add the plugin to the entity page
- Import the plugin components in your app
// packages/app/src/components/catalog/EntityPage.tsx
import React from 'react';
import { EntityLayout, EntitySwitch } from '@backstage/plugin-catalog';
import {
isHarnessIacmAvailable,
EntityIacmContent,
} from '@harnessio/backstage-plugin-iacm';
Option A add a tab route inside the service entity page
// packages/app/src/components/catalog/EntityPage.tsx
const serviceEntityPage = (
<EntityLayout>
{/* existing routes */}
<EntityLayout.Route
path="/harness-iacm"
title="Harness IACM"
if={isHarnessIacmAvailable}
>
<EntityIacmContent />
</EntityLayout.Route>
</EntityLayout>
);
Option B render with an entity switch
// packages/app/src/components/catalog/EntityPage.tsx
const serviceEntityPage = (
<EntityLayout>
<EntitySwitch>
<EntitySwitch.Case if={isHarnessIacmAvailable}>
<EntityIacmContent />
</EntitySwitch.Case>
{/* other cases */}
</EntitySwitch>
</EntityLayout>
);
Place this in the same file where you define your service entity page so the tab shows for matching entities
Add catalog annotations to your component
- Add the required annotation to each entity that should show Harness IACM
# catalog-info.yaml for a service
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: my-service
annotations:
harness.io/workspace-url: |
labelA: <harness_iacm_workspace_url>
labelB: <harness_iacm_workspace_url>
spec:
type: service
owner: team-a
lifecycle: production
The keys like labelA become the labels in the workspace dropdown
Each value is the Harness IACM workspace URL for that label
Notes
Use the proxy path you added when the plugin calls Harness
The plugin reads the token from the proxy config
Keep the token scoped with the permissions listed above
Changelog
This changelog is produced from commits made to the Harness IaaC 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.
Features
- Show workspace outputs in the Resources tab #155 merged 8 months ago
Set up Backstage in minutes with Roadie
Focus on using Backstage, rather than building and maintaining it.