Harness IaaC Management logo

Backstage Harness Infrastructure as Code Management Plugin

Created by harness.io

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

  1. Add the plugin to your Backstage app package
Copy
yarn add --cwd packages/app @harnessio/backstage-plugin-iacm
yarn install

Configure the proxy in app config

  1. Add a proxy entry to your app config
Copy
# 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

  1. If your app uses the legacy backend setup add the proxy backend plugin

Install the backend package if it is missing

Copy
yarn add --cwd packages/backend @backstage/plugin-proxy-backend

Create the proxy plugin module

Copy
// 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

Copy
// 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

  1. If your app uses the new backend system add the proxy backend module

Install the backend package if it is missing

Copy
yarn add --cwd packages/backend @backstage/plugin-proxy-backend @backstage/backend-defaults

Register the module

Copy
// 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

  1. Import the plugin components in your app
Copy
// 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

Copy
// 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

Copy
// 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

  1. Add the required annotation to each entity that should show Harness IACM
Copy
# 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