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 <brian@roadie.io>
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/integration': patch
|
||||
---
|
||||
|
||||
adds an allow list of github installations
|
||||
@@ -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.
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
Reference in New Issue
Block a user