Merge branch 'master' into firehydrant-plugin

This commit is contained in:
Christine Yi
2021-08-09 12:04:10 -04:00
5 changed files with 51 additions and 5 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/integration': patch
---
Adds an allow list of GitHub installations
+20
View File
@@ -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`);
}
+11
View File
@@ -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', () => {