VeeCode Kong Service Manager logo

Backstage VeeCode Kong Service Manager Plugin

Created by VeeCode Platform

VeeCode Kong Service Manager is a Backstage plugin that connects your catalog to Kong Gateway. It lets you view a service, see its routes, and manage plugins from one place. You can point it at more than one Kong instance and switch between them inside Backstage.

Inside an entity page you can inspect the service that the component references. You can list every route tied to it. You can create, edit, or delete routes when you need to change traffic. You can install, update, or disable plugins on the service or on a single route. The plugin keeps the work in Backstage so you do not jump between tools.

It can also surface an OpenAPI spec linked to the component. You see which plugins are associated with that service. You can enable or remove them from the spec with a pull request to your repo. This helps you review changes before they land in Kong.

Common use cases include rolling out auth across services, setting rate limits during a launch, tuning logging or analytics, and auditing what is installed today. Teams use the permissions in the plugin to control who can read, change, or delete routes and plugins. If you already run Kong and Backstage, this gives you a simple control plane inside your portal.

Installation Instructions

These instructions apply to self-hosted Backstage only.

Install the frontend package

If you use Yarn 3

Copy
yarn workspace app add @veecode-platform/plugin-kong-service-manager

If you use another Yarn version

Copy
yarn add --cwd packages/app @veecode-platform/plugin-kong-service-manager

Wire the frontend into your Backstage app

Edit packages app src components catalog EntityPage.tsx

Copy
import React from 'react';
import { EntityLayout } from '@backstage/plugin-catalog';
import { EntitySwitch, isKind } from '@backstage/plugin-catalog';
import { EntityAboutCard } from '@backstage/plugin-catalog';
import { Content } from '@backstage/core-components';

// Import the Kong Service Manager components
import {
  KongServiceManagerContent,
  isKongServiceManagerAvailable,
} from '@veecode-platform/plugin-kong-service-manager';

const overviewContent = (
  <Content>
    <EntityAboutCard variant="gridItem" />
  </Content>
);

const serviceEntityPage = (
  <EntityLayout>
    <EntityLayout.Route path="/" title="Overview">
      {overviewContent}
    </EntityLayout.Route>

    <EntityLayout.Route path="/ci-cd" title="CI/CD">
      {/* your CI CD content here */}
    </EntityLayout.Route>

    {/* Add the Kong route */}
    <EntityLayout.Route
      if={isKongServiceManagerAvailable}
      path="/kong-service-manager"
      title="Kong"
    >
      <KongServiceManagerContent />
    </EntityLayout.Route>
  </EntityLayout>
);

export const EntityPage = () => (
  <EntitySwitch>
    <EntitySwitch.Case if={isKind('component')} children={serviceEntityPage} />
    {/* other cases */}
  </EntitySwitch>
);

You can add the route to any entity page that makes sense for your portal. The example above adds it to the Service entity page

Configure Kong instances in app config

Add your Kong instances to app-config.yaml

Example for Kong Enterprise with admin token

Copy
kong:
  instances:
    - id: kong-instance01
      apiBaseUrl: ${KONG_HOST}
      workspace: ${KONG_WORKSPACE}
      auth:
        kongAdmin: ${KONG_ADMIN_TOKEN}

Example for Kong Community with a custom header

Copy
kong:
  instances:
    - id: kong-instance01
      apiBaseUrl: ${KONG_HOST}
      auth:
        custom:
          header: ${KONG_HEADER}
          value: ${KONG_AUTH}

You can set these variables in your environment or in app-config.local.yaml as needed

Add catalog annotations to your component

Add the annotations to the entity that represents the service you want to manage. Only one service per entity

Copy
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
  name: component-a
  description: Example service
  annotations:
    kong-manager/service-name: nameservice_test_A01
    kong-manager/instance: kongInstance1,kongInstance2
    kong-manager/spec: openapi-swagger.yaml
spec:
  type: service
  owner: team-a
  lifecycle: production

kong manager instance accepts a comma separated list without spaces. Every instance listed here must exist in app config

Install the backend plugin old backend system

Add the backend package

Copy
yarn add --cwd packages/backend @veecode-platform/plugin-kong-service-manager-backend

Create a router module at packages backend src plugins kongServiceManager.ts

Copy
import { Router } from 'express';
import { PluginEnvironment } from '../types';
import { createRouter } from '@veecode-platform/plugin-kong-service-manager-backend';

export default async function createPlugin(
  env: PluginEnvironment,
): Promise<Router> {
  // Many plugins accept more options. Start minimal and pass what you have
  const router = await createRouter({
    logger: env.logger,
    config: env.config,
    discovery: env.discovery,
    permissions: env.permissions,
    httpAuth: env.httpAuth,
  });
  return router;
}

Wire the router in packages backend src index.ts

Copy
import { createEnv } from './createEnv';
import kongServiceManager from './plugins/kongServiceManager';

async function main() {
  const env = await createEnv('backend');
  const apiRouter = Router();

  // other plugin routers

  apiRouter.use(
    '/kong-service-manager',
    await kongServiceManager(env),
  );

  env.serve(apiRouter);
}

main().catch(err => {
  console.error(err);
  process.exit(1);
});

If your backend uses a different env helper pattern adapt the import of env fields logger config discovery permissions httpAuth to your setup

Install the backend plugin new backend system

Add the backend package

Copy
yarn add --cwd packages/backend @veecode-platform/plugin-kong-service-manager-backend

Register the backend module in packages backend src index.ts

Copy
import { createBackend } from '@backstage/backend-defaults';

const backend = createBackend();

// Register other modules
backend.add(import('@backstage/plugin-app-backend'));
backend.add(import('@backstage/plugin-catalog-backend'));

// Register Kong Service Manager backend module
backend.add(import('@veecode-platform/plugin-kong-service-manager-backend'));

backend.start();

This uses the new backend module registration style. The module mounts its routes under the default path it provides

Set up permissions

Grant the plugin permissions in your backend. Start permissive then tighten later

Install the common package to access the permission constants if needed

Copy
yarn add --cwd packages/backend @veecode-platform/plugin-kong-service-manager-common

Old backend system example using a static policy

packages backend src plugins permission.ts

Copy
import { AuthorizeResult } from '@backstage/plugin-permission-common';
import { createStaticPermissionPolicy } from '@backstage/plugin-permission-node';
import {
  kongServiceReadPermission,
  kongReadAvailablePluginsPermission,
  kongRoutesReadPermission,
  kongApplyPluginToServicePermission,
  kongUpdateServicePluginPermission,
  kongDisableServicePluginPermission,
  kongRouteCreatePermission,
  kongUpdateRoutePermission,
  kongRouteDeletePermission,
  kongApplyPluginToRoutePermission,
  kongUpdateRoutePluginPermission,
  kongDisableRoutePluginPermission,
  kongReadSpecsPermission,
  kongUpdateSpecPermission,
  kongAIPluginsPermission,
  kongAuthPluginsPermission,
  kongSecurityPluginsPermission,
  kongTrafficPluginsPermission,
  kongServerlessPluginsPermission,
  kongTransformPluginsPermission,
  kongLoggingPluginsPermission,
  kongAnalyticsPluginsPermission,
} from '@veecode-platform/plugin-kong-service-manager-common';

export const permissionPolicy = createStaticPermissionPolicy({
  decisions: [
    { permission: kongServiceReadPermission, result: AuthorizeResult.ALLOW },
    { permission: kongReadAvailablePluginsPermission, result: AuthorizeResult.ALLOW },
    { permission: kongRoutesReadPermission, result: AuthorizeResult.ALLOW },
    { permission: kongApplyPluginToServicePermission, result: AuthorizeResult.ALLOW },
    { permission: kongUpdateServicePluginPermission, result: AuthorizeResult.ALLOW },
    { permission: kongDisableServicePluginPermission, result: AuthorizeResult.ALLOW },
    { permission: kongRouteCreatePermission, result: AuthorizeResult.ALLOW },
    { permission: kongUpdateRoutePermission, result: AuthorizeResult.ALLOW },
    { permission: kongRouteDeletePermission, result: AuthorizeResult.ALLOW },
    { permission: kongApplyPluginToRoutePermission, result: AuthorizeResult.ALLOW },
    { permission: kongUpdateRoutePluginPermission, result: AuthorizeResult.ALLOW },
    { permission: kongDisableRoutePluginPermission, result: AuthorizeResult.ALLOW },
    { permission: kongReadSpecsPermission, result: AuthorizeResult.ALLOW },
    { permission: kongUpdateSpecPermission, result: AuthorizeResult.ALLOW },
    { permission: kongAIPluginsPermission, result: AuthorizeResult.ALLOW },
    { permission: kongAuthPluginsPermission, result: AuthorizeResult.ALLOW },
    { permission: kongSecurityPluginsPermission, result: AuthorizeResult.ALLOW },
    { permission: kongTrafficPluginsPermission, result: AuthorizeResult.ALLOW },
    { permission: kongServerlessPluginsPermission, result: AuthorizeResult.ALLOW },
    { permission: kongTransformPluginsPermission, result: AuthorizeResult.ALLOW },
    { permission: kongLoggingPluginsPermission, result: AuthorizeResult.ALLOW },
    { permission: kongAnalyticsPluginsPermission, result: AuthorizeResult.ALLOW },
  ],
});

Wire the policy into your permission backend as you usually do

New backend system example

Create a module file packages backend src modules permissionPolicy.ts

Copy
import { coreServices, createBackendModule } from '@backstage/backend-plugin-api';
import { AuthorizeResult } from '@backstage/plugin-permission-common';
import { createStaticPermissionPolicy } from '@backstage/plugin-permission-node';
import {
  kongServiceReadPermission,
  kongReadAvailablePluginsPermission,
  kongRoutesReadPermission,
  kongApplyPluginToServicePermission,
  kongUpdateServicePluginPermission,
  kongDisableServicePluginPermission,
  kongRouteCreatePermission,
  kongUpdateRoutePermission,
  kongRouteDeletePermission,
  kongApplyPluginToRoutePermission,
  kongUpdateRoutePluginPermission,
  kongDisableRoutePluginPermission,
  kongReadSpecsPermission,
  kongUpdateSpecPermission,
  kongAIPluginsPermission,
  kongAuthPluginsPermission,
  kongSecurityPluginsPermission,
  kongTrafficPluginsPermission,
  kongServerlessPluginsPermission,
  kongTransformPluginsPermission,
  kongLoggingPluginsPermission,
  kongAnalyticsPluginsPermission,
} from '@veecode-platform/plugin-kong-service-manager-common';

export default createBackendModule({
  pluginId: 'permission',
  moduleId: 'kong-service-manager-policy',
  register(env) {
    env.registerInit({
      deps: { permissions: coreServices.permissions },
      async init({ permissions }) {
        const policy = createStaticPermissionPolicy({
          decisions: [
            { permission: kongServiceReadPermission, result: AuthorizeResult.ALLOW },
            { permission: kongReadAvailablePluginsPermission, result: AuthorizeResult.ALLOW },
            { permission: kongRoutesReadPermission, result: AuthorizeResult.ALLOW },
            { permission: kongApplyPluginToServicePermission, result: AuthorizeResult.ALLOW },
            { permission: kongUpdateServicePluginPermission, result: AuthorizeResult.ALLOW },
            { permission: kongDisableServicePluginPermission, result: AuthorizeResult.ALLOW },
            { permission: kongRouteCreatePermission, result: AuthorizeResult.ALLOW },
            { permission: kongUpdateRoutePermission, result: AuthorizeResult.ALLOW },
            { permission: kongRouteDeletePermission, result: AuthorizeResult.ALLOW },
            { permission: kongApplyPluginToRoutePermission, result: AuthorizeResult.ALLOW },
            { permission: kongUpdateRoutePluginPermission, result: AuthorizeResult.ALLOW },
            { permission: kongDisableRoutePluginPermission, result: AuthorizeResult.ALLOW },
            { permission: kongReadSpecsPermission, result: AuthorizeResult.ALLOW },
            { permission: kongUpdateSpecPermission, result: AuthorizeResult.ALLOW },
            { permission: kongAIPluginsPermission, result: AuthorizeResult.ALLOW },
            { permission: kongAuthPluginsPermission, result: AuthorizeResult.ALLOW },
            { permission: kongSecurityPluginsPermission, result: AuthorizeResult.ALLOW },
            { permission: kongTrafficPluginsPermission, result: AuthorizeResult.ALLOW },
            { permission: kongServerlessPluginsPermission, result: AuthorizeResult.ALLOW },
            { permission: kongTransformPluginsPermission, result: AuthorizeResult.ALLOW },
            { permission: kongLoggingPluginsPermission, result: AuthorizeResult.ALLOW },
            { permission: kongAnalyticsPluginsPermission, result: AuthorizeResult.ALLOW },
          ],
        });

        await permissions.setPolicy(policy);
      },
    });
  },
});

Register the module in packages backend src index.ts

Copy
import { createBackend } from '@backstage/backend-defaults';

const backend = createBackend();

// other modules
backend.add(import('@backstage/plugin-permission-backend'));

// register the policy module
backend.add(import('./modules/permissionPolicy'));

backend.start();

Adjust the policy later to match your access model

Configure git provider for Specs feature

Add an integration for your git provider. Below are minimal examples

GitHub example

Copy
integrations:
  github:
    - host: github.com
      token: ${GITHUB_TOKEN}

auth:
  environment: development
  providers:
    github:
      development:
        clientId: ${GITHUB_CLIENT_ID}
        clientSecret: ${GITHUB_CLIENT_SECRET}

GitLab example

Copy
integrations:
  gitlab:
    - host: gitlab.com
      token: ${GITLAB_TOKEN}

auth:
  environment: development
  providers:
    gitlab:
      development:
        clientId: ${GITLAB_CLIENT_ID}
        clientSecret: ${GITLAB_CLIENT_SECRET}

Environment variables reference

Set these to match your Kong setup

Copy
export KONG_HOST="https://kong.example.com"
export KONG_WORKSPACE="default"
export KONG_ADMIN_TOKEN="your_admin_token"

# For community with custom header
export KONG_HEADER="Authorization"
export KONG_AUTH="Basic your_token_or_key"

Quick recap

  • Install the frontend package
  • Add the route and content to EntityPage
  • Add kong instances in app config
  • Add the catalog annotations on the service entity
  • Install and wire the backend plugin for your backend style
  • Add a permission policy that allows the plugin actions
  • Add git provider integration if you want to use the Specs features

Changelog

This changelog is produced from commits made to the VeeCode Kong Service Manager 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

None

Features

  • Add Tenant Explorer plugin with overview and table components merged 3 months ago
  • Add alpha exports to Kong Service Manager merged 3 months ago

Improvements

  • Refactor and enhance plugin management components merged 3 months ago
  • Improve re render behavior in a component merged 8 months ago

Bug fixes

  • Fix validate issue merged 8 months ago
  • Fix bug merged 8 months ago

Documentation

  • Update README merged 8 months ago

Maintenance

  • Reorder dependencies in package.json files and update yarn.lock merged 3 months ago
  • Refactor code structure for readability and maintainability merged 3 months ago
  • Refactor components for readability and maintainability merged 3 months ago
  • Style updates merged 8 months ago
  • Style updates merged 8 months ago
  • Release chores merged 3 months ago
  • Release chores merged 3 months ago
  • Release chores merged 8 months ago
  • Release chores merged 8 months ago
  • Release chores merged 8 months ago
  • Release chores merged 8 months ago
  • Release chores merged 8 months ago
  • Release chores merged 8 months ago

Set up Backstage in minutes with Roadie