From 68af4d556b6643593b02e0df6b876f826bc4224f Mon Sep 17 00:00:00 2001 From: Brian Fletcher Date: Mon, 14 Jun 2021 13:50:36 +0100 Subject: [PATCH 1/5] Add allowedInstallationIds list to each github app This allows a single instance of backstage to optionally limit the set of github app installations that may be used by backstage. Previously, if you had github app installations for tenant1 and tenant2 there was nothing stopping the first from accessing resources of the second. The default behaviour of the GithubCredentialsProvider remains the same. Signed-off-by: Brian Fletcher --- .changeset/ninety-worms-kick.md | 5 +++++ docs/plugins/github-apps.md | 20 +++++++++++++++++++ .../src/github/GithubCredentialsProvider.ts | 13 ++++++++++++ packages/integration/src/github/config.ts | 7 +++++++ 4 files changed, 45 insertions(+) create mode 100644 .changeset/ninety-worms-kick.md diff --git a/.changeset/ninety-worms-kick.md b/.changeset/ninety-worms-kick.md new file mode 100644 index 0000000000..5170dbbdce --- /dev/null +++ b/.changeset/ninety-worms-kick.md @@ -0,0 +1,5 @@ +--- +'@backstage/integration': patch +--- + +adds an allow list of github installations diff --git a/docs/plugins/github-apps.md b/docs/plugins/github-apps.md index 87d23b45d5..5e69ae8294 100644 --- a/docs/plugins/github-apps.md +++ b/docs/plugins/github-apps.md @@ -84,3 +84,23 @@ integrations: apps: - $include: example-backstage-app-credentials.yaml ``` + +### Limiting the Github App installations + +If you want to limit the Github app installations visible to backstage you +may optionally include the `allowedInstallationIds` option. + +```yaml +appId: 1 +allowedInstallationIds: [1234] +clientId: client id +clientSecret: client secret +webhookSecret: webhook secret +privateKey: | + -----BEGIN RSA PRIVATE KEY----- + ...Key content... + -----END RSA PRIVATE KEY----- +``` + +This will result in backstage preventing the use of any installation that is not within the +allow list. diff --git a/packages/integration/src/github/GithubCredentialsProvider.ts b/packages/integration/src/github/GithubCredentialsProvider.ts index 9bc09deab3..8dbc3e7a69 100644 --- a/packages/integration/src/github/GithubCredentialsProvider.ts +++ b/packages/integration/src/github/GithubCredentialsProvider.ts @@ -68,8 +68,10 @@ class GithubAppManager { private readonly baseAuthConfig: { appId: number; privateKey: string }; private installations?: RestEndpointMethodTypes['apps']['listInstallations']['response']; private readonly cache = new Cache(); + private readonly allowedInstallations: number[] | undefined; // undefined allows all installations constructor(config: GithubAppConfig, baseUrl?: string) { + this.allowedInstallations = config.allowedInstallations; this.baseAuthConfig = { appId: config.appId, privateKey: config.privateKey, @@ -91,6 +93,17 @@ class GithubAppManager { suspended, repositorySelection, } = await this.getInstallationData(owner); + if (this.allowedInstallations) { + if (!this.allowedInstallations?.includes(installationId)) { + throw new Error( + `The GitHub application for ${[owner, repo] + .filter(Boolean) + .join( + '/', + )} is not included in the allowed installation list (${installationId}).`, + ); + } + } if (suspended) { throw new Error( `The GitHub application for ${[owner, repo] diff --git a/packages/integration/src/github/config.ts b/packages/integration/src/github/config.ts index 94ed00731e..370aed9c8b 100644 --- a/packages/integration/src/github/config.ts +++ b/packages/integration/src/github/config.ts @@ -93,6 +93,10 @@ export type GithubAppConfig = { * Client secrets can be generated at https://github.com/organizations/$org/settings/apps/$AppName */ clientSecret: string; + /** + * List of installations allowed to be used by this backstage https://github.com/app/installations/$InstallationId + */ + allowedInstallations?: number[]; }; /** @@ -113,6 +117,9 @@ export function readGitHubIntegrationConfig( clientSecret: c.getString('clientSecret'), webhookSecret: c.getString('webhookSecret'), privateKey: c.getString('privateKey'), + allowedInstallations: c + .getOptionalStringArray('allowedInstallations') + ?.map(allowedInstallation => Number(allowedInstallation)), })); if (!isValidHost(host)) { From 5fa0c32bffaeb8cdfa98f3691fbf5f92582d68d6 Mon Sep 17 00:00:00 2001 From: Brian Fletcher Date: Mon, 14 Jun 2021 14:15:02 +0100 Subject: [PATCH 2/5] Fixes some typos in changeset and docs Signed-off-by: Brian Fletcher --- .changeset/ninety-worms-kick.md | 2 +- docs/plugins/github-apps.md | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.changeset/ninety-worms-kick.md b/.changeset/ninety-worms-kick.md index 5170dbbdce..f350c6eb31 100644 --- a/.changeset/ninety-worms-kick.md +++ b/.changeset/ninety-worms-kick.md @@ -2,4 +2,4 @@ '@backstage/integration': patch --- -adds an allow list of github installations +Adds an allow list of GitHub installations diff --git a/docs/plugins/github-apps.md b/docs/plugins/github-apps.md index 5e69ae8294..386320cbb3 100644 --- a/docs/plugins/github-apps.md +++ b/docs/plugins/github-apps.md @@ -85,10 +85,10 @@ integrations: - $include: example-backstage-app-credentials.yaml ``` -### Limiting the Github App installations +### Limiting the GitHub App installations -If you want to limit the Github app installations visible to backstage you -may optionally include the `allowedInstallationIds` option. +If you want to limit the GitHub app installations visible to backstage you may +optionally include the `allowedInstallationIds` option. ```yaml appId: 1 @@ -102,5 +102,5 @@ privateKey: | -----END RSA PRIVATE KEY----- ``` -This will result in backstage preventing the use of any installation that is not within the -allow list. +This will result in backstage preventing the use of any installation that is not +within the allow list. From beb1d7812c2509e9171f3079a79aaedfd1b8b2da Mon Sep 17 00:00:00 2001 From: Brian Fletcher Date: Wed, 14 Jul 2021 08:52:03 +0100 Subject: [PATCH 3/5] changing to using the installation owner over id Signed-off-by: Brian Fletcher --- .../src/github/GithubCredentialsProvider.ts | 8 ++++---- packages/integration/src/github/config.ts | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/integration/src/github/GithubCredentialsProvider.ts b/packages/integration/src/github/GithubCredentialsProvider.ts index 8dbc3e7a69..9988d669f3 100644 --- a/packages/integration/src/github/GithubCredentialsProvider.ts +++ b/packages/integration/src/github/GithubCredentialsProvider.ts @@ -68,10 +68,10 @@ class GithubAppManager { private readonly baseAuthConfig: { appId: number; privateKey: string }; private installations?: RestEndpointMethodTypes['apps']['listInstallations']['response']; private readonly cache = new Cache(); - private readonly allowedInstallations: number[] | undefined; // undefined allows all installations + private readonly allowedInstallationOwners: string[] | undefined; // undefined allows all installations constructor(config: GithubAppConfig, baseUrl?: string) { - this.allowedInstallations = config.allowedInstallations; + this.allowedInstallationOwners = config.allowedInstallationOwners; this.baseAuthConfig = { appId: config.appId, privateKey: config.privateKey, @@ -93,8 +93,8 @@ class GithubAppManager { suspended, repositorySelection, } = await this.getInstallationData(owner); - if (this.allowedInstallations) { - if (!this.allowedInstallations?.includes(installationId)) { + if (this.allowedInstallationOwners) { + if (!this.allowedInstallationOwners?.includes(owner)) { throw new Error( `The GitHub application for ${[owner, repo] .filter(Boolean) diff --git a/packages/integration/src/github/config.ts b/packages/integration/src/github/config.ts index 370aed9c8b..f530879959 100644 --- a/packages/integration/src/github/config.ts +++ b/packages/integration/src/github/config.ts @@ -94,9 +94,9 @@ export type GithubAppConfig = { */ clientSecret: string; /** - * List of installations allowed to be used by this backstage https://github.com/app/installations/$InstallationId + * List of installation owners allowed to be used by this backstage https://github.com/app/installations/$InstallationId */ - allowedInstallations?: number[]; + allowedInstallationOwners?: string[]; }; /** @@ -117,9 +117,9 @@ export function readGitHubIntegrationConfig( clientSecret: c.getString('clientSecret'), webhookSecret: c.getString('webhookSecret'), privateKey: c.getString('privateKey'), - allowedInstallations: c - .getOptionalStringArray('allowedInstallations') - ?.map(allowedInstallation => Number(allowedInstallation)), + allowedInstallationOwners: c.getOptionalStringArray( + 'allowedInstallationOwners', + ), })); if (!isValidHost(host)) { From e1178b43613ff4c15a9479a0996bfe4cfb6f36b7 Mon Sep 17 00:00:00 2001 From: Brian Fletcher Date: Wed, 14 Jul 2021 08:57:51 +0100 Subject: [PATCH 4/5] update github readme to include owners filter Signed-off-by: Brian Fletcher --- docs/plugins/github-apps.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/plugins/github-apps.md b/docs/plugins/github-apps.md index 81fc870593..8d86c03220 100644 --- a/docs/plugins/github-apps.md +++ b/docs/plugins/github-apps.md @@ -92,11 +92,11 @@ integrations: ### Limiting the GitHub App installations If you want to limit the GitHub app installations visible to backstage you may -optionally include the `allowedInstallationIds` option. +optionally include the `allowedInstallationOwners` option. ```yaml appId: 1 -allowedInstallationIds: [1234] +allowedInstallationOwners: [1234] clientId: client id clientSecret: client secret webhookSecret: webhook secret From 5927bf864fda2b66563418b313b66612c3baa8c5 Mon Sep 17 00:00:00 2001 From: Brian Fletcher Date: Fri, 6 Aug 2021 10:22:33 +0100 Subject: [PATCH 5/5] Makes some suggested documentation improvements Signed-off-by: Brian Fletcher --- docs/plugins/github-apps.md | 2 +- packages/integration/src/github/config.ts | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/plugins/github-apps.md b/docs/plugins/github-apps.md index 8d86c03220..f9f7590e09 100644 --- a/docs/plugins/github-apps.md +++ b/docs/plugins/github-apps.md @@ -96,7 +96,7 @@ optionally include the `allowedInstallationOwners` option. ```yaml appId: 1 -allowedInstallationOwners: [1234] +allowedInstallationOwners: ['GlobexCorp'] clientId: client id clientSecret: client secret webhookSecret: webhook secret diff --git a/packages/integration/src/github/config.ts b/packages/integration/src/github/config.ts index d16e8897a7..4ecac99295 100644 --- a/packages/integration/src/github/config.ts +++ b/packages/integration/src/github/config.ts @@ -94,7 +94,11 @@ export type GithubAppConfig = { */ clientSecret: string; /** - * List of installation owners allowed to be used by this backstage https://github.com/app/installations/$InstallationId + * List of installation owners allowed to be used by this GitHub app. The GitHub UI does not provide a way to list the installations. + * However you can list the installations with the GitHub API. You can find the list of installations here: + * https://api.github.com/app/installations + * The relevant documentation for this is here. + * https://docs.github.com/en/rest/reference/apps#list-installations-for-the-authenticated-app--code-samples */ allowedInstallationOwners?: string[]; };