Merge pull request #6034 from RoadieHQ/github-installations-limit
Add allowedInstallationIds list to each github app
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/integration': patch
|
||||
---
|
||||
|
||||
Adds an allow list of GitHub installations
|
||||
@@ -89,6 +89,26 @@ integrations:
|
||||
- $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 `allowedInstallationOwners` option.
|
||||
|
||||
```yaml
|
||||
appId: 1
|
||||
allowedInstallationOwners: ['GlobexCorp']
|
||||
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.
|
||||
|
||||
### Permissions for pull requests
|
||||
|
||||
These are the minimum permissions required for creating a pull request with
|
||||
|
||||
@@ -66,8 +66,10 @@ class GithubAppManager {
|
||||
private readonly appClient: Octokit;
|
||||
private readonly baseAuthConfig: { appId: number; privateKey: string };
|
||||
private readonly cache = new Cache();
|
||||
private readonly allowedInstallationOwners: string[] | undefined; // undefined allows all installations
|
||||
|
||||
constructor(config: GithubAppConfig, baseUrl?: string) {
|
||||
this.allowedInstallationOwners = config.allowedInstallationOwners;
|
||||
this.baseAuthConfig = {
|
||||
appId: config.appId,
|
||||
privateKey: config.privateKey,
|
||||
@@ -85,6 +87,13 @@ class GithubAppManager {
|
||||
repo?: string,
|
||||
): Promise<{ accessToken: string }> {
|
||||
const { installationId, suspended } = await this.getInstallationData(owner);
|
||||
if (this.allowedInstallationOwners) {
|
||||
if (!this.allowedInstallationOwners?.includes(owner)) {
|
||||
throw new Error(
|
||||
`The GitHub application for ${owner} is not included in the allowed installation list (${installationId}).`,
|
||||
);
|
||||
}
|
||||
}
|
||||
if (suspended) {
|
||||
throw new Error(`The GitHub application for ${owner} is suspended`);
|
||||
}
|
||||
|
||||
@@ -93,6 +93,14 @@ export type GithubAppConfig = {
|
||||
* Client secrets can be generated at https://github.com/organizations/$org/settings/apps/$AppName
|
||||
*/
|
||||
clientSecret: string;
|
||||
/**
|
||||
* 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[];
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -113,6 +121,9 @@ export function readGitHubIntegrationConfig(
|
||||
clientSecret: c.getString('clientSecret'),
|
||||
webhookSecret: c.getString('webhookSecret'),
|
||||
privateKey: c.getString('privateKey'),
|
||||
allowedInstallationOwners: c.getOptionalStringArray(
|
||||
'allowedInstallationOwners',
|
||||
),
|
||||
}));
|
||||
|
||||
if (!isValidHost(host)) {
|
||||
|
||||
@@ -24,17 +24,18 @@ jest.mock('@backstage/catalog-model', () => ({
|
||||
},
|
||||
}));
|
||||
|
||||
const mockIsValidObjectName = KubernetesValidatorFunctions.isValidObjectName as jest.MockedFunction<
|
||||
typeof KubernetesValidatorFunctions.isValidObjectName
|
||||
>;
|
||||
const mockIsValidObjectName =
|
||||
KubernetesValidatorFunctions.isValidObjectName as jest.MockedFunction<
|
||||
typeof KubernetesValidatorFunctions.isValidObjectName
|
||||
>;
|
||||
|
||||
describe('EntityNamePicker Validation', () => {
|
||||
let mockFieldValidation: FieldValidation;
|
||||
|
||||
beforeEach(() => {
|
||||
mockFieldValidation = ({
|
||||
mockFieldValidation = {
|
||||
addError: jest.fn(),
|
||||
} as unknown) as FieldValidation;
|
||||
} as unknown as FieldValidation;
|
||||
});
|
||||
|
||||
it('calls isValidObjectName to validate value', () => {
|
||||
|
||||
Reference in New Issue
Block a user