Merge branch 'backstage:master' into fcorti-roadmap-001

This commit is contained in:
Francesco Corti
2022-01-14 12:12:02 +01:00
committed by GitHub
416 changed files with 7831 additions and 3057 deletions
+125
View File
@@ -0,0 +1,125 @@
---
id: provider
title: Google Identity-Aware Proxy Provider
sidebar_label: Google IAP
# prettier-ignore
description: Adding Google Identity-Aware Proxy as an authentication provider in Backstage
---
Backstage allows offloading the responsibility of authenticating users to the
Google HTTPS Load Balancer & [IAP](https://cloud.google.com/iap), leveraging the
authentication support on the latter.
This tutorial shows how to use authentication on an IAP sitting in front of
Backstage.
It is assumed an IAP is already serving traffic in front of a Backstage instance
configured to serve the frontend app from the backend.
## Configuration
Let's start by adding the following `auth` configuration in your
`app-config.yaml` or `app-config.production.yaml` or similar:
```yaml
auth:
providers:
gcp-iap:
audience:
'/projects/<project number>/global/backendServices/<backend service id>'
```
You can find the project number and service ID in the Google Cloud Console.
This config section must be in place for the provider to load at all. Now let's
add the provider itself.
## Backend Changes
This provider is not enabled by default in the auth backend code, because
besides the config section above, it also needs to be given one or more
callbacks in actual code as well as described below.
Add a `providerFactories` entry to the router in
`packages/backend/plugin/auth.ts`.
```ts
import { createGcpIapProvider } from '@backstage/plugin-auth-backend';
export default async function createPlugin({
logger,
database,
config,
discovery,
}: PluginEnvironment): Promise<Router> {
return await createRouter({
logger,
config,
database,
discovery,
providerFactories: {
'gcp-iap': createGcpIapProvider({
// Replace the auth handler if you want to customize the returned user
// profile info (can be left out; the default implementation is shown
// below which only returns the email). You may want to amend this code
// with something that loads additional user profile data out of e.g.
// GSuite or LDAP or similar.
async authHandler({ iapToken }) {
return { profile: { email: iapToken.email } };
},
signIn: {
// You need to supply an identity resolver, that takes the profile
// and the IAP token and produces the Backstage token with the
// relevant user info.
async resolver({ profile, result: { iapToken } }, ctx) {
// Somehow compute the Backstage token claims. Just some dummy code
// shown here, but you may want to query your LDAP server, or
// GSuite or similar, based on the IAP token sub/email claims
const id = `user:default/${iapToken.email.split('@')[0]}`;
const fullEnt = ['group:default/team-name'];
const token = await ctx.tokenIssuer.issueToken({
claims: { sub: id, ent: fullEnt },
});
return { id, token };
},
},
}),
},
});
}
```
Now the backend is ready to serve auth requests on the
`/api/auth/gcp-iap/refresh` endpoint. All that's left is to update the frontend
sign-in mechanism to poll that endpoint through the IAP, on the user's behalf.
## Frontend Changes
All Backstage apps need a `SignInPage` to be configured. Its purpose is to
establish who the user is and what their identifying credentials are, blocking
rendering the rest of the UI until that's complete, and then keeping those
credentials fresh.
When using IAP Proxy authentication, the Backstage UI will only be loaded once
the user has already successfully completely authenticated themselves with the
IAP and has an active session, so we don't want to make the user have to go
through a _second_ layer of authentication flows after that.
As such, we want to not display a sign-in page visually at all. Instead, we will
pick a `SignInPage` implementation component which knows how to silently make
requests to the backend provider we configured above, and just trusting its
output to properly represent the current user. Luckily, Backstage comes with a
component for this purpose out of the box.
Update your `createApp` call in `packages/app/src/App.tsx`, as follows.
```diff
+import { ProxiedSignInPage } from '@backstage/core-components';
const app = createApp({
components: {
+ SignInPage: props => <ProxiedSignInPage {...props} provider="gcp-iap" />,
```
After this, your app should be ready to leverage the Identity-Aware Proxy for
authentication!
+1 -1
View File
@@ -96,7 +96,7 @@ It can be enabled like this
```tsx
// File: packages/backend/src/plugins/auth.ts
import { googleEmailSignInResolver } from '@backstage/plugin-auth-backend';
import { googleEmailSignInResolver, createGoogleProvider } from '@backstage/plugin-auth-backend';
export default async function createPlugin({
...
@@ -1266,6 +1266,10 @@ shape, this kind has the following structure.
Exactly equal to `backstage.io/v1alpha1` and `Location`, respectively.
### `spec` [required]
The `spec` field is required. The minimal spec should be an empty object.
### `spec.type` [optional]
The single location type, that's common to the targets specified in the spec. If
@@ -204,6 +204,24 @@ browser when viewing that user.
This annotation can be used on a [User entity](descriptor-format.md#kind-user)
to note that it originated from that user on GitHub.
### gocd.org/pipelines
```yaml
# Example:
metadata:
annotations:
gocd.org/pipelines: backstage,backstage-pr,backstage-builder
```
The value of this annotation is a comma-separated list of the GoCD pipeline
names to fetch CI/CD information for.
The pipeline name is usually defined in the `gocd.yml` file for the pipeline
definition.
Specifying this annotation will enable GoCD related features in Backstage for
that entity.
### sentry.io/project-slug
```yaml
+5 -6
View File
@@ -301,12 +301,11 @@ in storybook. If you don't find a component that suits your needs but want to
contribute, check the
[Contributing documentation](https://github.com/backstage/backstage/blob/master/plugins/home/README.md#contributing).
!!! tip If you want to use one of the available homepage templates you can find
the
[templates](https://backstage.io/storybook/?path=/story/plugins-home-templates)
in the storybook under the "Home" plugin. And if you would like to contribute a
template, please see the
[Contributing documentation](https://github.com/backstage/backstage/blob/master/plugins/home/README.md#contributing)
> If you want to use one of the available homepage templates you can find the
> [templates](https://backstage.io/storybook/?path=/story/plugins-home-templates)
> in the storybook under the "Home" plugin. And if you would like to contribute
> a template, please see the
> [Contributing documentation](https://github.com/backstage/backstage/blob/master/plugins/home/README.md#contributing)
```tsx
import React from 'react';
+13
View File
@@ -26,3 +26,16 @@ catalog:
```
Note the `s3-discovery` type, as this is not a regular `url` processor.
As this processor is not one of the default providers, you will also need to add
the below to `packages/backend/src/plugins/catalog.ts`:
```ts
/* packages/backend/src/plugins/catalog.ts */
import { AwsS3DiscoveryProcessor } from '@backstage/plugin-catalog-backend';
const builder = await CatalogBuilder.create(env);
/** ... other processors ... */
builder.addProcessor(new AwsS3DiscoveryProcessor(env.reader));
```
+2 -2
View File
@@ -30,8 +30,8 @@ yarn add @backstage/plugin-catalog-backend-module-ldap
```typescript
// packages/backend/src/plugins/catalog.ts
builder.addProcessor(
LdapOrgReaderProcessor.fromConfig(config, {
logger,
LdapOrgReaderProcessor.fromConfig(env.config, {
logger: env.logger,
}),
);
```
+1
View File
@@ -556,6 +556,7 @@ Options:
--package &lt;name&gt; Only load config schema that applies to the given package
--lax Do not require environment variables to be set
--frontend Only validate the frontend configuration
--deprecated List all deprecated configuration settings
--config &lt;path&gt; Config files to load instead of app-config.yaml (default: [])
-h, --help display help for command
```
-58
View File
@@ -1,58 +0,0 @@
---
id: publishing
title: Publishing
description: Documentation on Publishing npm packages
---
## npm
npm packages are published through CI/CD in the
[`.github/workflows/master.yml`](https://github.com/backstage/backstage/blob/master/.github/workflows/master.yml)
workflow. Every commit that is merged to master will be checked for new versions
of all public packages, and any new versions will automatically be published to
npm.
### Creating a new release
Version bumps are made through release PRs. To create a new release, checkout
out a new branch that you will use for the release, e.g.
```sh
$ git checkout -b new-release
```
First bump the `CHANGELOG.md` in the root of the repo and commit. You bump it by
adding a header for the new version just below the `## Next Release` one.
Then, from the root of the repo, run
```sh
$ yarn release
```
This will bring up the lerna release CLI where you choose what type of version
bump you want to make, (major/minor/patch/prerelease). The CLI will take you
through choosing a version, previewing all changes, and then approving the
release. Once the release is approved, a new commit is created that you can
submit as a PR. Push the branch to GitHub:
```sh
$ git push origin -u new-release
```
And then create a PR. Once the PR is approved and merged into master, the master
build will publish new versions of all bumped packages.
### Include new changes in existing release PR
If you want to include some last minute changes to an existing release PR,
follow these instructions:
```sh
$ git checkout master
$ git pull
$ git checkout new-release
$ git reset --hard master
$ yarn release
$ git push --force
```
+72
View File
@@ -0,0 +1,72 @@
<!-- This is intentionally left out of the microsite, since it only applies to the main repo -->
## npm
npm packages are published through CI/CD in the
[`.github/workflows/master.yml`](https://github.com/backstage/backstage/blob/master/.github/workflows/master.yml)
workflow. Every commit that is merged to master will be checked for new versions
of all public packages, and any new versions will automatically be published to
npm.
### Creating a new release
Releases are handled by changesets and trigger whenever the "Version Packages"
PR is merged. This is typically done every Thursday around noon CET.
## Emergency Release Process
**This emergency release process is intended only for the Backstage
maintainers.**
For this example we will be using the `@backstage/plugin-foo` package as an
example and assume that it is currently version `1.5.0` in the master branch.
In the event of a severe bug being introduced in version `1.5.0` of the
`@backstage/plugin-foo` released in the `2048-01-01` release, the following
process is used to release an emergency fix as `1.5.1`:
- [ ] Identify the release that needs to be patched, in this case we're fixing a
broken release, so it would be the most recent one, `2048-01-01`. In the
event of a backported security fix, the release that has the last
published version of each major version of the package should be the one
patched.
- [ ] Make sure a patch branch exists for the release that is being patched. If
a patch already exists, reuse the existing branch. The branch **must
always** be named exactly `release-<release>-patch`.
```bash
git checkout release-2048-01-01
git checkout -b release-2048-01-01-patch
git push --set-upstream origin release-2048-01-01-patch
```
- [ ] With the `release-2048-01-01-patch` branch as a base, create a new branch
for your fix. This branch can be named anything, but the following naming
pattern may be suitable:
```bash
git checkout -b ${USER}/release-2048-01-01-emergency-fix
```
- [ ] Apply fixes and create a new patch changeset for the affected package,
then commit these changes.
- [ ] Run `yarn release` in the root of the repo in order to convert your
changeset into package version bumps and changelog entries. Commit these
changes as a second `"Generated release"` commit.
- [ ] Create PR towards the base branch (`release-2048-01-01-patch`) containing
the two commits.
- [ ] Review/Merge the PR into `release-2048-01-01-patch`. This will
automatically trigger a release.
- [ ] Make sure the same fix is applied in master before the next release, and
create an appropriate changeset for that as well. In the changeset towards
master you should refer back to all patch releases that also received the
same fix. Also be sure to update `.changeset/patched.json` in the same PR
to make sure that future releases of the packages are bumped accordingly:
```json
{
"currentReleaseVersion": {
"@backstage/plugin-foo": "1.5.1"
}
}
```