Merge branch 'backstage:master' into fcorti-roadmap-001
This commit is contained in:
@@ -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!
|
||||
@@ -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
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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));
|
||||
```
|
||||
|
||||
@@ -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,
|
||||
}),
|
||||
);
|
||||
```
|
||||
|
||||
@@ -556,6 +556,7 @@ Options:
|
||||
--package <name> 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 <path> Config files to load instead of app-config.yaml (default: [])
|
||||
-h, --help display help for command
|
||||
```
|
||||
|
||||
@@ -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
|
||||
```
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
```
|
||||
Reference in New Issue
Block a user