概要
ではGitHubのIDを持っていればログインできる認証機能を追加しました。
今回は「そのGitHubアカウントが特定のGitHub Organizationに所属しているかどうか」を使ってページを閲覧できるかどうか認可する仕組みを導入します。
認証と認可の違い
認証と認可の違いは以下です。
用語 | 定義 | 例 |
---|---|---|
認証 | 誰であるかを確認すること | パスワード、指紋、etc... |
認可 | 権限を与えること | 切符を購入した人には電車に乗る権限を与える ※誰かを特定する必要はない |
ただ多くのケースでは認証と認可はセットになっていることが多いです。
環境
- backstage v1.21.1
導入方法
GitHub Appの変更
Organizationの情報を利用するので、GitHub Integrationの機能(GitHub APIを使ってBackstageがアクセスできる情報を増やす)を使います。
Permission
GitHub Apps | Backstage Software Catalog and Developer Platform
で説明されている通りに設定してください。
カテゴリ | 対象リソース | どんな操作を許可するか | 備考 |
---|---|---|---|
Repository | Contents | Read & write | Software Catalog用。Templateでも使うならWrite権限も |
Repository | Administration | Read & write | Templateでリポジトリ作成のため |
Repository | Metadata | Read-only | - |
Repository | Pull requests | Read & write | - |
Repository | Issues | Read & write | - |
Repository | Workflows | Read & write | TemplateがGitHub workflowsを使うなら必要 |
Repository | Commit statuses | Read-only | - |
Repository | Variables | Read & write | TemplateがGitHub ActionのVariablesを使うなら必要 |
Repository | Secrets | Read & write | TemplateがGitHub ActionのSecretsを使うなら必要 |
Repository | Environments | Read & write | TemplateがGitHub Environmentsを使うなら必要 |
Organization | Members | Read-only | 認証やSoftware CatalogのOrg情報読み込み用 |
Private Keysの生成
https://github.com/organizations/<Org名>/settings/apps/<GitHub App名>
にてPrivate Keyを生成します。このKeyを使ってGitHubのOrg情報やOrg内のリポジトリにアクセスします。
生成すると自動的に.pem
ファイルをダウンロードします。
Backstageにcredentialの登録
github-app-credentials.yaml
のようなファイルを作ります。
appId: <app id> # GitHub AppのID clientId: <client id> # GitHub AppのClientID clientSecret: <client secret> # GitHub AppのClientSecret webhookSecret: <webhook secret> # 任意 privateKey: | -----BEGIN RSA PRIVATE KEY----- ...Key content... -----END RSA PRIVATE KEY-----
RSA PRIVATE
の部分に先程の.pem
の中身を書きます。インデントに気をつけてください。
そしてapp-config.yaml
に次の様に登録します。
integrations: github: - host: github.com apps: - $include: github-app-credentials.yaml
インストール
特定のOrganizationにアクセスしているかどうかを取得するために、そのOrganizationに作成したGitHub Appをインストールします。
https://github.com/organizations/<Org名>/settings/apps/<GitHub App名>/installations
にアクセスし、installボタンを押します。
Organizationやリポジトリへの認可処理が挟まります。Backstageを新規リポジトリ作成時にも使う場合はAll repositories
を選択してください。
実装
GitHub Orgのimport
GitHub Organizational Data | Backstage Software Catalog and Developer Platform
に則って実装します。
まずプラグインのインストール。
$ yarn add --cwd packages/backend @backstage/plugin-catalog-backend-module-github
packages/backend/src/plugins/catalog.ts
を次のように実装します。orgUrl
は自分の組織のOrg名にしてください。
import { GithubOrgEntityProvider } from '@backstage/plugin-catalog-backend-module-github'; export default async function createPlugin( env: PluginEnvironment, ): Promise<Router> { const builder = await CatalogBuilder.create(env); // The org URL below needs to match a configured integrations.github entry // specified in your app-config. builder.addEntityProvider( GithubOrgEntityProvider.fromConfig(env.config, { id: 'production', orgUrl: 'https://github.com/jun06t-org', logger: env.logger, schedule: env.scheduler.createScheduledTaskRunner({ frequency: { minutes: 60 }, timeout: { minutes: 15 }, }), }), ); ...
またapp-config.yaml
のcatalog部分にproviders
を追加します。
catalog: providers: githubOrg: id: 'production' orgs: - jun06t-org
すると起動時に次のようにOrg情報を読み込むようになります。
[1] 2024-01-01T00:12:43.170Z catalog info Read 1 GitHub users and 3 GitHub teams in 1.3 seconds. Committing... type=plugin target=https://github.com/jun06t-org class=GithubOrgEntityProvider taskId=GithubOrgEntityProvider:development:refresh taskInstanceId=31fa7cab-2fa9-4077-92b5-3face253ecaa [1] 2024-01-01T00:12:43.175Z catalog info Committed 1 GitHub users and 3 GitHub teams in 0.0 seconds. type=plugin target=https://github.com/jun06t-org class=GithubOrgEntityProvider taskId=GithubOrgEntityProvider:development:refresh taskInstanceId=31fa7cab-2fa9-4077-92b5-3face253ecaa
読み込みが完了すると
- OrgのMembers情報がBackstageのUser
- OrgのTeam情報がBackstageのGroup
として登録されます。
認証部分の変更
次は認証部分に認可処理を追加します。
packages/backend/src/plugins/auth.ts
を次のように変更します。デフォルトのresolverを削除して、コメントアウトされていた部分をアンコメントするだけで済みます。
export default async function createPlugin( env: PluginEnvironment, ): Promise<Router> { return await createRouter({ logger: env.logger, config: env.config, database: env.database, discovery: env.discovery, tokenManager: env.tokenManager, providerFactories: { ...defaultAuthProviderFactories, github: providers.github.create({ signIn: { resolver: providers.github.resolvers.usernameMatchingUserEntityName(), }, }), }, }); }
動作確認
ユーザがOrgにいない(=Entityに存在しない)場合、以下のようにエラーになります。
ユーザがOrgにいる場合(=Entityに存在する)場合、問題なくログインできます。
その他
サンプルコード
今回の変更点はこちらで確認できます。
GitHub Appインストール時のコールバックでエラーが出る
"error":{"name":"InputError","message":"Must specify 'env' query to select environment","stack":"InputError: Must specify 'env' query to select environment
というエラーが出るケースです。
を読むとコールバックURLにenv
パラメータがないとそうなるようですが、手動でいじらない限り付かなそうでした。
インストール自体は問題ないのでそのまま閉じるでも問題ないです。
Kubernetesでの機密情報の管理
github-app-credentials.yaml
をバージョン管理するのは良くないので、これ自体をSecretで管理してマウントし、
integrations: github: - host: github.com apps: - $include: ${GITHUB_CREDENTIALS_PATH}
として$includeすると良いでしょう。
また本番用ビルドを作る際はapp-config.yaml
に↑の設定がある一方で、ローカルにgithub-app-credentials.yaml
を用意していない(Secretに登録後削除した)と次のエラーが発生します。
$ yarn build:backend --config ../../app-config.yaml yarn run v1.22.19 $ yarn workspace backend build --config ../../app-config.yaml $ backstage-cli package build --config ../../app-config.yaml Building app separately because it is a bundled package $ backstage-cli package build --config github.com/jun06t/backstage-sample/app/app-config.yaml app: app: app: Error: Failed to read config file at "github.com/jun06t/backstage-sample/app/app-config.yaml", error at .integrations.github[0].apps[0], failed to include "github.com/jun06t/backstage-sample/app/github-app-credentials.yaml", file does not exist
なのでapp-config.yaml
でなくapp-config.production.yaml
にintegrationsの設定を書くと良いです。
まとめ
GitHubのOrg情報を使った認可機能を実装しました。