APC 技術ブログ

株式会社エーピーコミュニケーションズの技術ブログです。

株式会社 エーピーコミュニケーションズの技術ブログです。

Backstage 新Backend Systemの動作をカスタマイズする

Backstageとは

なにかと話題にしていますBackstageですが、ご存知無い方のためにあらためて。
BackstageはCNCFのプロジェクトの1つで、拡張性の高い開発者ポータルのOSSです。機能拡張などはPluginを追加導入することで実現します。

techblog.ap-com.co.jp

BackstageのNew Backend System

数多くのPluginを導入することで機能を追加できるBackstageですが、すでに用意されているPluginを導入する際にも手間がかかるのが課題でした。そうした点を改善しようとするのがNew Backend Systemです。

techblog.ap-com.co.jp

New Backend Systemは導入が簡単・便利になるのですが、それと既存機能の拡張方法も変わりました。今回はその機能拡張方法の1つをご紹介したいと思います。

認証機能の拡張方法

BackstageのAPIはデフォルトでは認証確認がなく、誰でもアクセスできるようになっています。こうした点を改善し、原則すべてのAPIアクセスで認証確認を行うようにするPluginを以前ご紹介しました。

techblog.ap-com.co.jp

今回はこの機能をNew Backend System対応にしていきます。

旧Backend Systemでの対応方法

旧Backend Systemでは、backend packageのmainでルーティング情報を登録していました。ここでExpressJSのMiddlewareとして登録すればOKでした。

// packages/backend/src/index.ts from a create-app deployment

import { createAuthMiddleware, setCookieService } from '@platt/plugin-http-router-backend-module-authorization';
import cookieParser from 'cookie-parser';

// ...

async function main() {
  // ...

  const authMiddleware = await createAuthMiddleware(config, appEnv);

  const apiRouter = Router();
  apiRouter.use(cookieParser());
  // The auth route must be publicly available as it is used during login
  apiRouter.use('/auth', await auth(authEnv));
  // Add a simple endpoint to be used when setting a token cookie
  apiRouter.use('/cookie', authMiddleware, setCookieService);
  // Only authenticated requests are allowed to the routes below
  apiRouter.use('/catalog', authMiddleware, await catalog(catalogEnv));
  apiRouter.use('/techdocs', authMiddleware, await techdocs(techdocsEnv));
  apiRouter.use('/proxy', authMiddleware, await proxy(proxyEnv));
  apiRouter.use(authMiddleware, notFoundHandler());

  // ...
}

新Backend Systemでの対応

新Backend Systemではルーティング情報なども隠蔽されており、利用者は意識する必要はなくなりました。 このため、認証などの機能を付加するためには旧Backend Systemとは異なる方法で行う必要があります。

新Backend Systemでは、各種のサービスをServiceFactoryとして用意し、その中で指定するようになります。デフォルトのServiceFactoryは @backstage/backend-defaults パッケージの中で指定されています

export const defaultServiceFactories = [
  cacheServiceFactory(),
  rootConfigServiceFactory(),
  databaseServiceFactory(),
  discoveryServiceFactory(),
  httpRouterServiceFactory(),
  identityServiceFactory(),
  lifecycleServiceFactory(),
  loggerServiceFactory(),
  permissionsServiceFactory(),
  rootHttpRouterServiceFactory(),
  rootLifecycleServiceFactory(),
  rootLoggerServiceFactory(),
  schedulerServiceFactory(),
  tokenManagerServiceFactory(),
  urlReaderServiceFactory(),
];

ルーティング情報は rootHttpRouterServiceFactoryで指定されており、ここを上書きすることで認証機能を組み込みます。

イメージとしては以下のようになります(参考コード)。

import { rootHttpRouterServiceFactory } from '@backstage/backend-app-api';
import cookieParser from 'cookie-parser';
import { authMiddlewareFactory } from './middlewares';

export default rootHttpRouterServiceFactory ({
  configure: ({ app, config, logger, middleware, routes }) => {
    app.use(middleware.helmet());
    app.use(middleware.cors());
    app.use(middleware.compression());
    app.use(cookieParser());
    app.use(middleware.logging());

    app.use(authMiddlewareFactory({ config, logger }));

    // Simple handler to set auth cookie for user
    app.use('/api/cookie', (_, res) => {
      res.status(200).send();
    });

    app.use(routes);

    app.use(middleware.notFound());
    app.use(middleware.error());
  },
});

これを以下のように組み込めばOKです。

const backend = createBackend();

backend.add(import('./上記モジュール'));

Pluginを利用する側は簡単になったのですが、それを拡張するためにはBackstageの中を理解していかないといけない、そんな仕組みになってきています。

便利な認証Plugin

今回ご紹介した認証機能はPluginとして簡単にご利用いただけるようになっています。 以前は認証確認Pluginは旧Backend Systemだけの対応でしたが、このたび新Backend Systemにも対応いたしました。 こちらを利用することで、面倒なコーディングを追加することなくAPIに認証確認機能を付加いただけるようになっています。

www.npmjs.com

ぜひご活用ください。